tarantool 0.4.3.8 → 0.4.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: