tarantool 0.4.3.8 → 0.4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/tarantool/extconf.rb +9 -0
- data/ext/tarantool/response_c.c +287 -0
- data/lib/tarantool.rb +2 -2
- data/lib/tarantool/response.rb +13 -2
- data/lib/tarantool/version.rb +1 -1
- metadata +7 -3
@@ -0,0 +1,9 @@
|
|
1
|
+
if RUBY_ENGINE == 'ruby' and "\x01\x02\x03\x04".unpack('L') == [0x04030201]
|
2
|
+
require 'mkmf'
|
3
|
+
have_func('rb_str_drop_bytes')
|
4
|
+
create_makefile("response_c")
|
5
|
+
else
|
6
|
+
File.open(File.dirname(__FILE__) + "/Makefile", 'w') do |f|
|
7
|
+
f.write("install:\n\t#nothing to build")
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,287 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <ruby/encoding.h>
|
3
|
+
|
4
|
+
#if HAVE_STDINT_H
|
5
|
+
#include "stdint.h"
|
6
|
+
#elif defined(_MSC_VER)
|
7
|
+
typedef __int8 int8_t;
|
8
|
+
typedef unsigned __int8 uint8_t;
|
9
|
+
typedef __int16 int16_t;
|
10
|
+
typedef unsigned __int16 uint16_t;
|
11
|
+
typedef __int32 int32_t;
|
12
|
+
typedef unsigned __int32 uint32_t;
|
13
|
+
typedef __int64 int64_t;
|
14
|
+
typedef unsigned __int64 uint64_t;
|
15
|
+
#else
|
16
|
+
#ifndef __int8_t_defined
|
17
|
+
typedef char int8_t;
|
18
|
+
typedef short int16_t;
|
19
|
+
typedef int int32_t;
|
20
|
+
#endif
|
21
|
+
typedef unsigned char uint8_t;
|
22
|
+
typedef unsigned short uint16_t;
|
23
|
+
typedef unsigned int uint32_t;
|
24
|
+
#if SIZEOF_LONG==8
|
25
|
+
typedef long int64_t;
|
26
|
+
typedef unsigned long uint64_t;
|
27
|
+
#else
|
28
|
+
typedef long long int64_t;
|
29
|
+
typedef unsigned long long uint64_t;
|
30
|
+
#endif
|
31
|
+
#endif
|
32
|
+
|
33
|
+
#ifdef __GNUC__
|
34
|
+
#define FORCE_INLINE __attribute__((always_inline))
|
35
|
+
#elif defined(_MSC_VER)
|
36
|
+
#define FORCE_INLINE __forceinline
|
37
|
+
#else
|
38
|
+
#define FORCE_INLINE
|
39
|
+
#endif
|
40
|
+
|
41
|
+
#if defined(_MSC_VER)
|
42
|
+
#define LL(x) (x)
|
43
|
+
#define LLU(x) (x)
|
44
|
+
#else
|
45
|
+
#define LL(x) (x##LL)
|
46
|
+
#define LLU(x) (x##LLU)
|
47
|
+
#endif
|
48
|
+
|
49
|
+
#if SIZEOF_LONG == 8
|
50
|
+
#define I642NUM(v) LONG2NUM(v)
|
51
|
+
#define U642NUM(v) ULONG2NUM(v)
|
52
|
+
#define NUM2I64(v) NUM2LONG(v)
|
53
|
+
#define NUM2U64(v) NUM2ULONG(v)
|
54
|
+
#else
|
55
|
+
#define I642NUM(v) LL2NUM(v)
|
56
|
+
#define U642NUM(v) ULL2NUM(v)
|
57
|
+
#define NUM2I64(v) NUM2LL(v)
|
58
|
+
#define NUM2U64(v) NUM2ULL(v)
|
59
|
+
#endif
|
60
|
+
|
61
|
+
#ifndef HAVE_RB_STR_DROP_BYTES
|
62
|
+
/* rubinius has no rb_str_drop_bytes */
|
63
|
+
ID aslice;
|
64
|
+
static VALUE
|
65
|
+
rb_str_drop_bytes(VALUE str, long bytes)
|
66
|
+
{
|
67
|
+
VALUE args[2] = {0, INT2FIX(bytes)};
|
68
|
+
rb_funcall2(str, aslice, 2, args);
|
69
|
+
return str;
|
70
|
+
}
|
71
|
+
#endif
|
72
|
+
|
73
|
+
ID id_rshft, id_band, id_get_serializer, id_decode;
|
74
|
+
VALUE sym_int, sym_integer, sym_string, sym_str, sym_int64, sym_bytes, sym_int16;
|
75
|
+
VALUE sym_int8, sym_sint, sym_sint64, sym_sint16, sym_sint8, sym_varint, sym_auto;
|
76
|
+
VALUE rb_eValueError, rb_cAutoType;
|
77
|
+
|
78
|
+
#ifndef RARRAY_CONST_PTR
|
79
|
+
#define RARRAY_CONST_PTR(v) RARRAY_PTR(v)
|
80
|
+
#endif
|
81
|
+
|
82
|
+
static inline size_t
|
83
|
+
slice_ber(const uint8_t **str, size_t *len)
|
84
|
+
{
|
85
|
+
size_t res = 0;
|
86
|
+
while (*len > 0) {
|
87
|
+
uint8_t digit = **str;
|
88
|
+
res = (res << 7) | (digit & 127);
|
89
|
+
(*str)++; (*len)--;
|
90
|
+
if (digit < 128) return res;
|
91
|
+
}
|
92
|
+
rb_raise(rb_eValueError, "Response too short");
|
93
|
+
return 0;
|
94
|
+
}
|
95
|
+
|
96
|
+
static inline uint16_t
|
97
|
+
get_uint16(const char *str)
|
98
|
+
{
|
99
|
+
uint8_t *u = (uint8_t*)str;
|
100
|
+
return *u | (*(u+1) << 8);
|
101
|
+
}
|
102
|
+
static inline uint32_t
|
103
|
+
get_uint32(const char *str)
|
104
|
+
{
|
105
|
+
uint8_t *u = (uint8_t*)str;
|
106
|
+
return *u | (*(u+1) << 8) | (*(u+2) << 16) | (*(u+3) << 24);
|
107
|
+
}
|
108
|
+
static inline uint64_t
|
109
|
+
get_uint64(const char *str)
|
110
|
+
{
|
111
|
+
return (uint64_t)get_uint32(str) | ((uint64_t)get_uint32(str+4) << 32);
|
112
|
+
}
|
113
|
+
|
114
|
+
static VALUE
|
115
|
+
unpack_tuples(VALUE self, VALUE data, VALUE fields, VALUE _tail, VALUE tuples_affected)
|
116
|
+
{
|
117
|
+
uint32_t fieldsn = RARRAY_LEN(fields);
|
118
|
+
uint32_t tuplesn = NUM2UINT(tuples_affected);
|
119
|
+
uint32_t tail = NUM2UINT(_tail);
|
120
|
+
const char *str = StringValuePtr(data);
|
121
|
+
size_t len = RSTRING_LEN(data);
|
122
|
+
rb_encoding *utf8 = rb_utf8_encoding(), *binary = rb_ascii8bit_encoding();
|
123
|
+
|
124
|
+
VALUE tuples = rb_ary_new2(tuplesn);
|
125
|
+
VALUE serializers = rb_ary_new2(fieldsn);
|
126
|
+
|
127
|
+
for (;tuplesn > 0; tuplesn--) {
|
128
|
+
uint32_t tuplen, i, realfield;
|
129
|
+
const char *end;
|
130
|
+
VALUE tuple;
|
131
|
+
if (len < 8) {
|
132
|
+
rb_raise(rb_eValueError, "Response too short");
|
133
|
+
}
|
134
|
+
end = str + 8 + *(uint32_t*)str;
|
135
|
+
tuplen = *(uint32_t*)(str+4);
|
136
|
+
tuple = rb_ary_new2(fieldsn);
|
137
|
+
str += 8;
|
138
|
+
len -= 8;
|
139
|
+
for(i = 0; i < tuplen; i++) {
|
140
|
+
size_t fieldsize = slice_ber((const uint8_t**)&str, &len);
|
141
|
+
VALUE field, value;
|
142
|
+
if (fieldsize == 0) {
|
143
|
+
rb_ary_push(tuple, Qnil);
|
144
|
+
continue;
|
145
|
+
}
|
146
|
+
if (fieldsize > len) {
|
147
|
+
rb_raise(rb_eValueError, "Response mailformed at field #%u fieldsize: %zu tail len: %zu", i, fieldsize, len);
|
148
|
+
}
|
149
|
+
realfield = i;
|
150
|
+
if (i >= fieldsn) {
|
151
|
+
if (tail == 1) {
|
152
|
+
realfield = fieldsn - 1;
|
153
|
+
} else {
|
154
|
+
realfield = fieldsn + (i - fieldsn) % tail - tail;
|
155
|
+
}
|
156
|
+
}
|
157
|
+
field = RARRAY_CONST_PTR(fields)[realfield];
|
158
|
+
|
159
|
+
if (field == sym_int || field == sym_integer) {
|
160
|
+
if (fieldsize != 4) {
|
161
|
+
rb_raise(rb_eValueError, "Bad field size %zd for integer field #%u", fieldsize, i);
|
162
|
+
}
|
163
|
+
value = UINT2NUM(get_uint32(str));
|
164
|
+
} else if (field == sym_str || field == sym_string) {
|
165
|
+
if (*str == 0 && fieldsize > 0) {
|
166
|
+
str++; len--; fieldsize--;
|
167
|
+
}
|
168
|
+
value = rb_enc_str_new(str, fieldsize, utf8);
|
169
|
+
} else if (field == sym_int64) {
|
170
|
+
if (fieldsize != 8) {
|
171
|
+
rb_raise(rb_eValueError, "Bad field size %zd for 64bit integer field #%u", fieldsize, i);
|
172
|
+
}
|
173
|
+
#if SIZEOF_LONG == 8
|
174
|
+
value = ULONG2NUM(get_uint64(str));
|
175
|
+
#elif HAVE_LONG_LONG
|
176
|
+
value = ULL2NUM(get_uint64(str));
|
177
|
+
#else
|
178
|
+
#error "Should have long long or sizeof(long) == 8"
|
179
|
+
#endif
|
180
|
+
} else if (field == sym_bytes) {
|
181
|
+
if (*str == 0 && fieldsize > 0) {
|
182
|
+
str++; len--; fieldsize--;
|
183
|
+
}
|
184
|
+
value = rb_enc_str_new(str, fieldsize, binary);
|
185
|
+
} else if (field == sym_int16) {
|
186
|
+
if (fieldsize != 2) {
|
187
|
+
rb_raise(rb_eValueError, "Bad field size %zd for 16bit integer field #%u", fieldsize, i);
|
188
|
+
}
|
189
|
+
value = UINT2NUM(get_uint16(str));
|
190
|
+
} else if (field == sym_int8) {
|
191
|
+
if (fieldsize != 1) {
|
192
|
+
rb_raise(rb_eValueError, "Bad field size %zd for 8bit integer field #%u", fieldsize, i);
|
193
|
+
}
|
194
|
+
value = UINT2NUM(*(uint8_t*)str);
|
195
|
+
} else if (field == sym_sint) {
|
196
|
+
if (fieldsize != 4) {
|
197
|
+
rb_raise(rb_eValueError, "Bad field size %zd for integer field #%u", fieldsize, i);
|
198
|
+
}
|
199
|
+
value = INT2NUM((int32_t)get_uint32(str));
|
200
|
+
} else if (field == sym_sint64) {
|
201
|
+
if (fieldsize != 8) {
|
202
|
+
rb_raise(rb_eValueError, "Bad field size %zd for 64bit integer field #%u", fieldsize, i);
|
203
|
+
}
|
204
|
+
#if SIZEOF_LONG == 8
|
205
|
+
value = LONG2NUM((int64_t)get_uint64(str));
|
206
|
+
#elif HAVE_LONG_LONG
|
207
|
+
value = LL2NUM((int64_t)get_uint64(str));
|
208
|
+
#endif
|
209
|
+
} else if (field == sym_sint16) {
|
210
|
+
if (fieldsize != 2) {
|
211
|
+
rb_raise(rb_eValueError, "Bad field size %zd for 16bit integer field #%u", fieldsize, i);
|
212
|
+
}
|
213
|
+
value = INT2NUM((int16_t)get_uint16(str));
|
214
|
+
} else if (field == sym_sint8) {
|
215
|
+
if (fieldsize != 1) {
|
216
|
+
rb_raise(rb_eValueError, "Bad field size %zd for 8bit integer field #%u", fieldsize, i);
|
217
|
+
}
|
218
|
+
value = INT2NUM(*(int8_t*)str);
|
219
|
+
} else if (field == sym_varint) {
|
220
|
+
if (fieldsize == 4) {
|
221
|
+
value = UINT2NUM(get_uint32(str));
|
222
|
+
} else if (fieldsize == 8) {
|
223
|
+
#if SIZEOF_LONG == 8
|
224
|
+
value = ULONG2NUM(get_uint64(str));
|
225
|
+
#elif HAVE_LONG_LONG
|
226
|
+
value = ULL2NUM(get_uint64(str));
|
227
|
+
#endif
|
228
|
+
} else if (fieldsize == 2) {
|
229
|
+
value = UINT2NUM(get_uint16(str));
|
230
|
+
} else {
|
231
|
+
rb_raise(rb_eValueError, "Bad field size %zd for integer field %d", fieldsize, i);
|
232
|
+
}
|
233
|
+
} else if (field == sym_auto) {
|
234
|
+
value = rb_enc_str_new(str, fieldsize, utf8);
|
235
|
+
if (fieldsize == 2 || fieldsize == 4 || fieldsize == 8) {
|
236
|
+
value = rb_class_new_instance(1, &value, rb_cAutoType);
|
237
|
+
}
|
238
|
+
} else {
|
239
|
+
VALUE serializer = rb_ary_entry(serializers, realfield);
|
240
|
+
VALUE substr = rb_enc_str_new(str, fieldsize, binary);
|
241
|
+
if (!RTEST(serializer)) {
|
242
|
+
serializer = rb_funcall2(self, id_get_serializer, 1, &field);
|
243
|
+
rb_ary_store(serializers, realfield, serializer);
|
244
|
+
}
|
245
|
+
value = rb_funcall2(serializer, id_decode, 1, &substr);
|
246
|
+
}
|
247
|
+
str += fieldsize;
|
248
|
+
len -= fieldsize;
|
249
|
+
rb_ary_push(tuple, value);
|
250
|
+
}
|
251
|
+
if (end != str) {
|
252
|
+
rb_raise(rb_eValueError, "Response mailformed");
|
253
|
+
}
|
254
|
+
rb_ary_push(tuples, tuple);
|
255
|
+
}
|
256
|
+
|
257
|
+
RB_GC_GUARD(data);
|
258
|
+
return tuples;
|
259
|
+
}
|
260
|
+
|
261
|
+
void
|
262
|
+
Init_response_c()
|
263
|
+
{
|
264
|
+
VALUE rb_mTarantool = rb_define_module("Tarantool");
|
265
|
+
VALUE rb_mUnpackTuples = rb_define_module_under(rb_mTarantool, "UnpackTuples");
|
266
|
+
VALUE rb_mUtil = rb_const_get(rb_mTarantool, rb_intern("Util"));
|
267
|
+
rb_define_method(rb_mUnpackTuples, "_unpack_tuples", unpack_tuples, 4);
|
268
|
+
rb_eValueError = rb_const_get(rb_mTarantool, rb_intern("ValueError"));
|
269
|
+
rb_cAutoType = rb_const_get(rb_mUtil, rb_intern("AutoType"));
|
270
|
+
|
271
|
+
sym_int = ID2SYM(rb_intern("int"));
|
272
|
+
sym_integer = ID2SYM(rb_intern("integer"));
|
273
|
+
sym_str = ID2SYM(rb_intern("str"));
|
274
|
+
sym_string = ID2SYM(rb_intern("string"));
|
275
|
+
sym_int16 = ID2SYM(rb_intern("int16"));
|
276
|
+
sym_int64 = ID2SYM(rb_intern("int64"));
|
277
|
+
sym_bytes = ID2SYM(rb_intern("bytes"));
|
278
|
+
sym_int8 = ID2SYM(rb_intern("int8"));
|
279
|
+
sym_sint = ID2SYM(rb_intern("sint"));
|
280
|
+
sym_sint8 = ID2SYM(rb_intern("sint8"));
|
281
|
+
sym_sint16 = ID2SYM(rb_intern("sint16"));
|
282
|
+
sym_sint64 = ID2SYM(rb_intern("sint64"));
|
283
|
+
sym_varint = ID2SYM(rb_intern("varint"));
|
284
|
+
sym_auto = ID2SYM(rb_intern("auto"));
|
285
|
+
id_get_serializer = rb_intern("get_serializer");
|
286
|
+
id_decode = rb_intern("decode");
|
287
|
+
}
|
data/lib/tarantool.rb
CHANGED
@@ -115,9 +115,9 @@ module Tarantool
|
|
115
115
|
@query ||= self.class::Query.new(self)
|
116
116
|
end
|
117
117
|
|
118
|
-
def method_missing(name, *args)
|
118
|
+
def method_missing(name, *args, &block)
|
119
119
|
if query.respond_to?(name)
|
120
|
-
query.send(name, *args)
|
120
|
+
query.send(name, *args, &block)
|
121
121
|
else
|
122
122
|
super
|
123
123
|
end
|
data/lib/tarantool/response.rb
CHANGED
@@ -3,6 +3,13 @@ require 'tarantool/exceptions'
|
|
3
3
|
require 'tarantool/serializers'
|
4
4
|
|
5
5
|
module Tarantool
|
6
|
+
module UnpackTuples
|
7
|
+
end
|
8
|
+
begin
|
9
|
+
require 'tarantool/response_c'
|
10
|
+
rescue LoadError
|
11
|
+
end
|
12
|
+
|
6
13
|
module ParseIProto
|
7
14
|
include Util::Packer
|
8
15
|
def _parse_iproto(data)
|
@@ -21,6 +28,7 @@ module Tarantool
|
|
21
28
|
include Util::Packer
|
22
29
|
include Util::TailGetter
|
23
30
|
include Serializers
|
31
|
+
include UnpackTuples
|
24
32
|
UTF8 = 'utf-8'.freeze
|
25
33
|
|
26
34
|
def call(data)
|
@@ -67,14 +75,17 @@ module Tarantool
|
|
67
75
|
|
68
76
|
def unpack_tuples(data)
|
69
77
|
tuples_affected = ::BinUtils.slice_int32_le!(data)
|
70
|
-
tuples = []
|
71
78
|
fields = fields()
|
72
79
|
if Integer === fields.last
|
73
80
|
*fields, tail = fields
|
74
81
|
else
|
75
82
|
tail = 1
|
76
83
|
end
|
84
|
+
_unpack_tuples(data, fields, tail, tuples_affected)
|
85
|
+
end
|
77
86
|
|
87
|
+
def _unpack_tuples(data, fields, tail, tuples_affected)
|
88
|
+
tuples = []
|
78
89
|
while tuples_affected > 0
|
79
90
|
byte_size = ::BinUtils.slice_int32_le!(data)
|
80
91
|
fields_num = ::BinUtils.slice_int32_le!(data)
|
@@ -162,7 +173,7 @@ module Tarantool
|
|
162
173
|
tuples_affected -= 1
|
163
174
|
end
|
164
175
|
tuples
|
165
|
-
end
|
176
|
+
end unless method_defined?(:_unpack_tuples)
|
166
177
|
|
167
178
|
def return_code(data)
|
168
179
|
::BinUtils.slice_int32_le!(data)
|
data/lib/tarantool/version.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: tarantool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.4.
|
5
|
+
version: 0.4.4.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Andrew Rudenko
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-
|
13
|
+
date: 2014-03-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
type: :runtime
|
@@ -81,7 +81,8 @@ email:
|
|
81
81
|
- ceo@prepor.ru
|
82
82
|
- funny.falcon@gmail.com
|
83
83
|
executables: []
|
84
|
-
extensions:
|
84
|
+
extensions:
|
85
|
+
- ext/tarantool/extconf.rb
|
85
86
|
extra_rdoc_files:
|
86
87
|
- README.md
|
87
88
|
- LICENSE
|
@@ -107,6 +108,8 @@ files:
|
|
107
108
|
- lib/tarantool/base_record.rb
|
108
109
|
- lib/tarantool/response.rb
|
109
110
|
- lib/tarantool.rb
|
111
|
+
- ext/tarantool/extconf.rb
|
112
|
+
- ext/tarantool/response_c.c
|
110
113
|
- test/shared_query.rb
|
111
114
|
- test/test_reshard_block.rb
|
112
115
|
- test/test_space_array_callback.rb
|
@@ -145,6 +148,7 @@ rdoc_options:
|
|
145
148
|
- --charset=UTF-8
|
146
149
|
require_paths:
|
147
150
|
- lib
|
151
|
+
- ext
|
148
152
|
required_ruby_version: !ruby/object:Gem::Requirement
|
149
153
|
none: false
|
150
154
|
requirements:
|