thrift 0.8.0 → 0.13.0

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