thrift 0.8.0 → 0.13.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.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/{README → README.md} +0 -0
  3. data/ext/binary_protocol_accelerated.c +33 -14
  4. data/ext/bytes.c +36 -0
  5. data/ext/bytes.h +31 -0
  6. data/ext/compact_protocol.c +27 -8
  7. data/ext/constants.h +8 -5
  8. data/ext/extconf.rb +5 -1
  9. data/ext/memory_buffer.c +12 -9
  10. data/ext/protocol.c +0 -185
  11. data/ext/protocol.h +0 -20
  12. data/ext/strlcpy.h +7 -3
  13. data/ext/struct.c +27 -7
  14. data/ext/thrift_native.c +16 -11
  15. data/lib/thrift.rb +10 -4
  16. data/lib/thrift/bytes.rb +131 -0
  17. data/lib/thrift/client.rb +13 -4
  18. data/lib/thrift/exceptions.rb +3 -0
  19. data/lib/thrift/multiplexed_processor.rb +76 -0
  20. data/lib/thrift/processor.rb +24 -6
  21. data/lib/thrift/protocol/base_protocol.rb +109 -12
  22. data/lib/thrift/protocol/binary_protocol.rb +22 -7
  23. data/lib/thrift/protocol/binary_protocol_accelerated.rb +8 -0
  24. data/lib/thrift/protocol/compact_protocol.rb +23 -6
  25. data/lib/thrift/protocol/json_protocol.rb +786 -0
  26. data/lib/thrift/protocol/multiplexed_protocol.rb +44 -0
  27. data/lib/thrift/protocol/protocol_decorator.rb +194 -0
  28. data/lib/thrift/server/base_server.rb +8 -2
  29. data/lib/thrift/server/mongrel_http_server.rb +2 -0
  30. data/lib/thrift/server/simple_server.rb +5 -1
  31. data/lib/thrift/server/thin_http_server.rb +91 -0
  32. data/lib/thrift/server/thread_pool_server.rb +5 -1
  33. data/lib/thrift/server/threaded_server.rb +5 -1
  34. data/lib/thrift/struct.rb +1 -1
  35. data/lib/thrift/struct_union.rb +2 -2
  36. data/lib/thrift/transport/base_server_transport.rb +1 -1
  37. data/lib/thrift/transport/base_transport.rb +30 -20
  38. data/lib/thrift/transport/buffered_transport.rb +25 -11
  39. data/lib/thrift/transport/framed_transport.rb +20 -11
  40. data/lib/thrift/transport/http_client_transport.rb +16 -6
  41. data/lib/thrift/transport/io_stream_transport.rb +5 -2
  42. data/lib/thrift/transport/memory_buffer_transport.rb +10 -6
  43. data/lib/thrift/transport/server_socket.rb +6 -1
  44. data/lib/thrift/transport/socket.rb +23 -17
  45. data/lib/thrift/transport/ssl_server_socket.rb +41 -0
  46. data/lib/thrift/transport/ssl_socket.rb +51 -0
  47. data/lib/thrift/transport/unix_server_socket.rb +5 -1
  48. data/lib/thrift/transport/unix_socket.rb +5 -1
  49. data/lib/thrift/union.rb +3 -6
  50. data/spec/BaseService.thrift +27 -0
  51. data/spec/ExtendedService.thrift +25 -0
  52. data/spec/Referenced.thrift +44 -0
  53. data/spec/ThriftNamespacedSpec.thrift +53 -0
  54. data/spec/ThriftSpec.thrift +52 -1
  55. data/spec/base_protocol_spec.rb +158 -93
  56. data/spec/base_transport_spec.rb +194 -157
  57. data/spec/binary_protocol_accelerated_spec.rb +14 -14
  58. data/spec/binary_protocol_spec.rb +29 -16
  59. data/spec/binary_protocol_spec_shared.rb +148 -65
  60. data/spec/bytes_spec.rb +160 -0
  61. data/spec/client_spec.rb +45 -47
  62. data/spec/compact_protocol_spec.rb +36 -22
  63. data/spec/exception_spec.rb +79 -80
  64. data/spec/flat_spec.rb +62 -0
  65. data/spec/http_client_spec.rb +91 -16
  66. data/spec/json_protocol_spec.rb +552 -0
  67. data/spec/namespaced_spec.rb +67 -0
  68. data/spec/nonblocking_server_spec.rb +26 -28
  69. data/spec/processor_spec.rb +29 -32
  70. data/spec/serializer_spec.rb +31 -33
  71. data/spec/server_socket_spec.rb +32 -28
  72. data/spec/server_spec.rb +112 -84
  73. data/spec/socket_spec.rb +27 -20
  74. data/spec/socket_spec_shared.rb +32 -32
  75. data/spec/spec_helper.rb +17 -11
  76. data/spec/ssl_server_socket_spec.rb +34 -0
  77. data/spec/ssl_socket_spec.rb +78 -0
  78. data/spec/struct_nested_containers_spec.rb +191 -0
  79. data/spec/struct_spec.rb +159 -161
  80. data/spec/thin_http_server_spec.rb +141 -0
  81. data/spec/types_spec.rb +71 -69
  82. data/spec/union_spec.rb +97 -76
  83. data/spec/unix_socket_spec.rb +49 -41
  84. metadata +268 -188
  85. data/CHANGELOG +0 -1
  86. data/benchmark/gen-rb/benchmark_constants.rb +0 -10
  87. data/benchmark/gen-rb/benchmark_service.rb +0 -80
  88. data/benchmark/gen-rb/benchmark_types.rb +0 -9
  89. data/spec/gen-rb/nonblocking_service.rb +0 -272
  90. data/spec/gen-rb/thrift_spec_constants.rb +0 -10
  91. data/spec/gen-rb/thrift_spec_types.rb +0 -345
  92. data/spec/mongrel_http_server_spec.rb +0 -117
  93. data/test/debug_proto/gen-rb/debug_proto_test_constants.rb +0 -273
  94. data/test/debug_proto/gen-rb/debug_proto_test_types.rb +0 -760
  95. data/test/debug_proto/gen-rb/empty_service.rb +0 -24
  96. data/test/debug_proto/gen-rb/inherited.rb +0 -79
  97. data/test/debug_proto/gen-rb/reverse_order_service.rb +0 -82
  98. data/test/debug_proto/gen-rb/service_for_exception_with_a_map.rb +0 -81
  99. data/test/debug_proto/gen-rb/srv.rb +0 -330
@@ -37,6 +37,9 @@ module Thrift
37
37
  MISSING_RESULT = 5
38
38
  INTERNAL_ERROR = 6
39
39
  PROTOCOL_ERROR = 7
40
+ INVALID_TRANSFORM = 8
41
+ INVALID_PROTOCOL = 9
42
+ UNSUPPORTED_CLIENT_TYPE = 10
40
43
 
41
44
  attr_reader :type
42
45
 
@@ -0,0 +1,76 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+
19
+ require 'thrift/protocol/protocol_decorator'
20
+ require 'thrift/protocol/base_protocol'
21
+
22
+ module Thrift
23
+ class MultiplexedProcessor
24
+ def initialize
25
+ @actual_processors = {}
26
+ end
27
+
28
+ def register_processor(service_name, processor)
29
+ @actual_processors[service_name] = processor
30
+ end
31
+
32
+ def process(iprot, oprot)
33
+ name, type, seqid = iprot.read_message_begin
34
+ check_type(type)
35
+ check_separator(name)
36
+ service_name, method = name.split(':')
37
+ processor(service_name).process(StoredMessageProtocol.new(iprot, [method, type, seqid]), oprot)
38
+ end
39
+
40
+ protected
41
+
42
+ def processor(service_name)
43
+ if @actual_processors.has_key?(service_name)
44
+ @actual_processors[service_name]
45
+ else
46
+ raise Thrift::Exception.new("Service name not found: #{service_name}. Did you forget to call #{self.class.name}#register_processor?")
47
+ end
48
+ end
49
+
50
+ def check_type(type)
51
+ unless [MessageTypes::CALL, MessageTypes::ONEWAY].include?(type)
52
+ raise Thrift::Exception.new('This should not have happened!?')
53
+ end
54
+ end
55
+
56
+ def check_separator(name)
57
+ if name.count(':') < 1
58
+ raise Thrift::Exception.new("Service name not found in message name: #{name}. Did you forget to use a Thrift::Protocol::MultiplexedProtocol in your client?")
59
+ end
60
+ end
61
+ end
62
+
63
+ class StoredMessageProtocol < BaseProtocol
64
+
65
+ include ProtocolDecorator
66
+
67
+ def initialize(protocol, message_begin)
68
+ super(protocol)
69
+ @message_begin = message_begin
70
+ end
71
+
72
+ def read_message_begin
73
+ @message_begin
74
+ end
75
+ end
76
+ end
@@ -17,25 +17,36 @@
17
17
  # under the License.
18
18
  #
19
19
 
20
+ require 'logger'
21
+
20
22
  module Thrift
21
23
  module Processor
22
- def initialize(handler)
24
+ def initialize(handler, logger=nil)
23
25
  @handler = handler
26
+ if logger.nil?
27
+ @logger = Logger.new(STDERR)
28
+ @logger.level = Logger::WARN
29
+ else
30
+ @logger = logger
31
+ end
24
32
  end
25
33
 
26
34
  def process(iprot, oprot)
27
35
  name, type, seqid = iprot.read_message_begin
28
36
  if respond_to?("process_#{name}")
29
- send("process_#{name}", seqid, iprot, oprot)
37
+ begin
38
+ send("process_#{name}", seqid, iprot, oprot)
39
+ rescue => e
40
+ x = ApplicationException.new(ApplicationException::INTERNAL_ERROR, 'Internal error')
41
+ @logger.debug "Internal error : #{e.message}\n#{e.backtrace.join("\n")}"
42
+ write_error(x, oprot, name, seqid)
43
+ end
30
44
  true
31
45
  else
32
46
  iprot.skip(Types::STRUCT)
33
47
  iprot.read_message_end
34
48
  x = ApplicationException.new(ApplicationException::UNKNOWN_METHOD, 'Unknown function '+name)
35
- oprot.write_message_begin(name, MessageTypes::EXCEPTION, seqid)
36
- x.write(oprot)
37
- oprot.write_message_end
38
- oprot.trans.flush
49
+ write_error(x, oprot, name, seqid)
39
50
  false
40
51
  end
41
52
  end
@@ -53,5 +64,12 @@ module Thrift
53
64
  oprot.write_message_end
54
65
  oprot.trans.flush
55
66
  end
67
+
68
+ def write_error(err, oprot, name, seqid)
69
+ oprot.write_message_begin(name, MessageTypes::EXCEPTION, seqid)
70
+ err.write(oprot)
71
+ oprot.write_message_end
72
+ oprot.trans.flush
73
+ end
56
74
  end
57
75
  end
@@ -28,6 +28,8 @@ module Thrift
28
28
  NEGATIVE_SIZE = 2
29
29
  SIZE_LIMIT = 3
30
30
  BAD_VERSION = 4
31
+ NOT_IMPLEMENTED = 5
32
+ DEPTH_LIMIT = 6
31
33
 
32
34
  attr_reader :type
33
35
 
@@ -114,10 +116,27 @@ module Thrift
114
116
  raise NotImplementedError
115
117
  end
116
118
 
119
+ # Writes a Thrift String. In Ruby 1.9+, the String passed will be transcoded to UTF-8.
120
+ #
121
+ # str - The String to write.
122
+ #
123
+ # Raises EncodingError if the transcoding to UTF-8 fails.
124
+ #
125
+ # Returns nothing.
117
126
  def write_string(str)
118
127
  raise NotImplementedError
119
128
  end
120
129
 
130
+ # Writes a Thrift Binary (Thrift String with no encoding). In Ruby 1.9+, the String passed
131
+ # will forced into BINARY encoding.
132
+ #
133
+ # buf - The String to write.
134
+ #
135
+ # Returns nothing.
136
+ def write_binary(buf)
137
+ raise NotImplementedError
138
+ end
139
+
121
140
  def read_message_begin
122
141
  raise NotImplementedError
123
142
  end
@@ -178,18 +197,67 @@ module Thrift
178
197
  raise NotImplementedError
179
198
  end
180
199
 
200
+ # Reads a Thrift String. In Ruby 1.9+, all Strings will be returned with an Encoding of UTF-8.
201
+ #
202
+ # Returns a String.
181
203
  def read_string
182
204
  raise NotImplementedError
183
205
  end
184
206
 
185
- def write_field(name, type, fid, value)
186
- write_field_begin(name, type, fid)
187
- write_type(type, value)
207
+ # Reads a Thrift Binary (Thrift String without encoding). In Ruby 1.9+, all Strings will be returned
208
+ # with an Encoding of BINARY.
209
+ #
210
+ # Returns a String.
211
+ def read_binary
212
+ raise NotImplementedError
213
+ end
214
+
215
+ # Writes a field based on the field information, field ID and value.
216
+ #
217
+ # field_info - A Hash containing the definition of the field:
218
+ # :name - The name of the field.
219
+ # :type - The type of the field, which must be a Thrift::Types constant.
220
+ # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
221
+ # fid - The ID of the field.
222
+ # value - The field's value to write; object type varies based on :type.
223
+ #
224
+ # Returns nothing.
225
+ def write_field(*args)
226
+ if args.size == 3
227
+ # handles the documented method signature - write_field(field_info, fid, value)
228
+ field_info = args[0]
229
+ fid = args[1]
230
+ value = args[2]
231
+ elsif args.size == 4
232
+ # handles the deprecated method signature - write_field(name, type, fid, value)
233
+ field_info = {:name => args[0], :type => args[1]}
234
+ fid = args[2]
235
+ value = args[3]
236
+ else
237
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 3)"
238
+ end
239
+
240
+ write_field_begin(field_info[:name], field_info[:type], fid)
241
+ write_type(field_info, value)
188
242
  write_field_end
189
243
  end
190
244
 
191
- def write_type(type, value)
192
- case type
245
+ # Writes a field value based on the field information.
246
+ #
247
+ # field_info - A Hash containing the definition of the field:
248
+ # :type - The Thrift::Types constant that determines how the value is written.
249
+ # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
250
+ # value - The field's value to write; object type varies based on field_info[:type].
251
+ #
252
+ # Returns nothing.
253
+ def write_type(field_info, value)
254
+ # if field_info is a Fixnum, assume it is a Thrift::Types constant
255
+ # convert it into a field_info Hash for backwards compatibility
256
+ if field_info.is_a? Fixnum
257
+ field_info = {:type => field_info}
258
+ end
259
+
260
+ case field_info[:type]
193
261
  when Types::BOOL
194
262
  write_bool(value)
195
263
  when Types::BYTE
@@ -203,7 +271,11 @@ module Thrift
203
271
  when Types::I64
204
272
  write_i64(value)
205
273
  when Types::STRING
206
- write_string(value)
274
+ if field_info[:binary]
275
+ write_binary(value)
276
+ else
277
+ write_string(value)
278
+ end
207
279
  when Types::STRUCT
208
280
  value.write(self)
209
281
  else
@@ -211,8 +283,21 @@ module Thrift
211
283
  end
212
284
  end
213
285
 
214
- def read_type(type)
215
- case type
286
+ # Reads a field value based on the field information.
287
+ #
288
+ # field_info - A Hash containing the pertinent data to write:
289
+ # :type - The Thrift::Types constant that determines how the value is written.
290
+ # :binary - A flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
291
+ #
292
+ # Returns the value read; object type varies based on field_info[:type].
293
+ def read_type(field_info)
294
+ # if field_info is a Fixnum, assume it is a Thrift::Types constant
295
+ # convert it into a field_info Hash for backwards compatibility
296
+ if field_info.is_a? Fixnum
297
+ field_info = {:type => field_info}
298
+ end
299
+
300
+ case field_info[:type]
216
301
  when Types::BOOL
217
302
  read_bool
218
303
  when Types::BYTE
@@ -226,7 +311,11 @@ module Thrift
226
311
  when Types::I64
227
312
  read_i64
228
313
  when Types::STRING
229
- read_string
314
+ if field_info[:binary]
315
+ read_binary
316
+ else
317
+ read_string
318
+ end
230
319
  else
231
320
  raise NotImplementedError
232
321
  end
@@ -234,8 +323,6 @@ module Thrift
234
323
 
235
324
  def skip(type)
236
325
  case type
237
- when Types::STOP
238
- nil
239
326
  when Types::BOOL
240
327
  read_bool
241
328
  when Types::BYTE
@@ -278,13 +365,23 @@ module Thrift
278
365
  skip(etype)
279
366
  end
280
367
  read_list_end
368
+ else
369
+ raise ProtocolException.new(ProtocolException::INVALID_DATA, 'Invalid data')
281
370
  end
282
371
  end
372
+
373
+ def to_s
374
+ "#{trans.to_s}"
375
+ end
283
376
  end
284
377
 
285
378
  class BaseProtocolFactory
286
379
  def get_protocol(trans)
287
380
  raise NotImplementedError
288
381
  end
382
+
383
+ def to_s
384
+ "base"
385
+ end
289
386
  end
290
- end
387
+ end
@@ -32,8 +32,7 @@ module Thrift
32
32
 
33
33
  # Pre-allocated read buffer for fixed-size read methods. Needs to be at least 8 bytes long for
34
34
  # read_i64() and read_double().
35
- @rbuf = "\0" * 8
36
- @rbuf.force_encoding("BINARY") if @rbuf.respond_to?(:force_encoding)
35
+ @rbuf = Bytes.empty_byte_buffer(8)
37
36
  end
38
37
 
39
38
  def write_message_begin(name, type, seqid)
@@ -108,8 +107,13 @@ module Thrift
108
107
  end
109
108
 
110
109
  def write_string(str)
111
- write_i32(str.length)
112
- trans.write(str)
110
+ buf = Bytes.convert_to_utf8_byte_buffer(str)
111
+ write_binary(buf)
112
+ end
113
+
114
+ def write_binary(buf)
115
+ write_i32(buf.bytesize)
116
+ trans.write(buf)
113
117
  end
114
118
 
115
119
  def read_message_begin
@@ -214,16 +218,27 @@ module Thrift
214
218
  end
215
219
 
216
220
  def read_string
217
- sz = read_i32
218
- dat = trans.read_all(sz)
219
- dat
221
+ buffer = read_binary
222
+ Bytes.convert_to_string(buffer)
220
223
  end
221
224
 
225
+ def read_binary
226
+ size = read_i32
227
+ trans.read_all(size)
228
+ end
229
+
230
+ def to_s
231
+ "binary(#{super.to_s})"
232
+ end
222
233
  end
223
234
 
224
235
  class BinaryProtocolFactory < BaseProtocolFactory
225
236
  def get_protocol(trans)
226
237
  return Thrift::BinaryProtocol.new(trans)
227
238
  end
239
+
240
+ def to_s
241
+ "binary"
242
+ end
228
243
  end
229
244
  end
@@ -35,5 +35,13 @@ module Thrift
35
35
  BinaryProtocol.new(trans)
36
36
  end
37
37
  end
38
+
39
+ def to_s
40
+ if (defined? BinaryProtocolAccelerated)
41
+ "binary-accel"
42
+ else
43
+ "binary"
44
+ end
45
+ end
38
46
  end
39
47
  end
@@ -24,6 +24,7 @@ module Thrift
24
24
  VERSION = 1
25
25
  VERSION_MASK = 0x1f
26
26
  TYPE_MASK = 0xE0
27
+ TYPE_BITS = 0x07
27
28
  TYPE_SHIFT_AMOUNT = 5
28
29
 
29
30
  TSTOP = ["", Types::STOP, 0]
@@ -100,8 +101,7 @@ module Thrift
100
101
  @boolean_value = nil
101
102
 
102
103
  # Pre-allocated read buffer for read_double().
103
- @rbuf = "\0" * 8
104
- @rbuf.force_encoding("BINARY") if @rbuf.respond_to?(:force_encoding)
104
+ @rbuf = Bytes.empty_byte_buffer(8)
105
105
  end
106
106
 
107
107
  def write_message_begin(name, type, seqid)
@@ -211,8 +211,13 @@ module Thrift
211
211
  end
212
212
 
213
213
  def write_string(str)
214
- write_varint32(str.length)
215
- @trans.write(str)
214
+ buf = Bytes.convert_to_utf8_byte_buffer(str)
215
+ write_binary(buf)
216
+ end
217
+
218
+ def write_binary(buf)
219
+ write_varint32(buf.bytesize)
220
+ @trans.write(buf)
216
221
  end
217
222
 
218
223
  def read_message_begin
@@ -227,7 +232,7 @@ module Thrift
227
232
  raise ProtocolException.new("Expected version #{VERSION} but got #{version}");
228
233
  end
229
234
 
230
- type = (version_and_type >> TYPE_SHIFT_AMOUNT) & 0x03
235
+ type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS
231
236
  seqid = read_varint32()
232
237
  messageName = read_string()
233
238
  [messageName, type, seqid]
@@ -332,11 +337,19 @@ module Thrift
332
337
  end
333
338
 
334
339
  def read_string
340
+ buffer = read_binary
341
+ Bytes.convert_to_string(buffer)
342
+ end
343
+
344
+ def read_binary
335
345
  size = read_varint32()
336
346
  trans.read_all(size)
337
347
  end
338
348
 
339
-
349
+ def to_s
350
+ "compact(#{super.to_s})"
351
+ end
352
+
340
353
  private
341
354
 
342
355
  #
@@ -422,5 +435,9 @@ module Thrift
422
435
  def get_protocol(trans)
423
436
  CompactProtocol.new(trans)
424
437
  end
438
+
439
+ def to_s
440
+ "compact"
441
+ end
425
442
  end
426
443
  end