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.
@@ -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
@@ -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)
@@ -1,4 +1,4 @@
1
1
  module Tarantool
2
- VERSION = "0.4.3.8"
2
+ VERSION = "0.4.4.0"
3
3
  RECORD_VERSION = "0.4.2.1"
4
4
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: tarantool
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.4.3.8
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-01-17 00:00:00.000000000 Z
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: