thrift 0.24.0 → 0.25.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.
- checksums.yaml +4 -4
- data/README.md +107 -4
- data/ext/binary_protocol_accelerated.c +52 -17
- data/ext/compact_protocol.c +135 -70
- data/ext/constants.h +3 -0
- data/ext/extconf.rb +4 -4
- data/ext/macros.h +11 -0
- data/ext/memory_buffer.c +35 -17
- data/ext/struct.c +185 -64
- data/ext/thrift_native.c +6 -0
- data/lib/thrift/bytes.rb +2 -2
- data/lib/thrift/client.rb +31 -22
- data/lib/thrift/exceptions.rb +10 -8
- data/lib/thrift/multiplexed_processor.rb +5 -6
- data/lib/thrift/processor.rb +24 -3
- data/lib/thrift/protocol/base_protocol.rb +53 -27
- data/lib/thrift/protocol/binary_protocol.rb +54 -40
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +6 -2
- data/lib/thrift/protocol/compact_protocol.rb +193 -88
- data/lib/thrift/protocol/header_protocol.rb +14 -3
- data/lib/thrift/protocol/json_protocol.rb +146 -104
- data/lib/thrift/protocol/multiplexed_protocol.rb +2 -3
- data/lib/thrift/protocol/protocol_decorator.rb +5 -2
- data/lib/thrift/serializer/serializer.rb +6 -0
- data/lib/thrift/server/base_server.rb +10 -2
- data/lib/thrift/server/nonblocking_server.rb +49 -26
- data/lib/thrift/server/rack_application.rb +69 -0
- data/lib/thrift/server/simple_server.rb +27 -23
- data/lib/thrift/server/thin_http_server.rb +20 -44
- data/lib/thrift/server/thread_pool_server.rb +20 -17
- data/lib/thrift/server/threaded_server.rb +22 -26
- data/lib/thrift/struct.rb +33 -18
- data/lib/thrift/struct_union.rb +36 -30
- data/lib/thrift/transport/base_transport.rb +23 -5
- data/lib/thrift/transport/buffered_transport.rb +4 -4
- data/lib/thrift/transport/framed_transport.rb +32 -7
- data/lib/thrift/transport/header_transport.rb +130 -50
- data/lib/thrift/transport/http_client_transport.rb +27 -14
- data/lib/thrift/transport/io_stream_transport.rb +2 -1
- data/lib/thrift/transport/memory_buffer_transport.rb +8 -10
- data/lib/thrift/transport/server_socket.rb +4 -5
- data/lib/thrift/transport/socket.rb +20 -22
- data/lib/thrift/transport/ssl_server_socket.rb +64 -4
- data/lib/thrift/transport/ssl_socket.rb +32 -5
- data/lib/thrift/transport/unix_server_socket.rb +1 -1
- data/lib/thrift/transport/unix_socket.rb +4 -6
- data/lib/thrift/types.rb +22 -22
- data/lib/thrift/union.rb +20 -11
- data/lib/thrift/uuid.rb +8 -8
- data/lib/thrift.rb +39 -39
- metadata +5 -230
- data/benchmark/Benchmark.thrift +0 -24
- data/benchmark/benchmark.rb +0 -286
- data/benchmark/client.rb +0 -118
- data/benchmark/server.rb +0 -121
- data/benchmark/thin_server.rb +0 -46
- data/lib/thrift/server/mongrel_http_server.rb +0 -61
- data/spec/BaseService.thrift +0 -27
- data/spec/ExtendedService.thrift +0 -25
- data/spec/Referenced.thrift +0 -44
- data/spec/ThriftNamespacedSpec.thrift +0 -53
- data/spec/ThriftSpec.thrift +0 -203
- data/spec/base_protocol_spec.rb +0 -244
- data/spec/base_transport_spec.rb +0 -428
- data/spec/binary_protocol_accelerated_spec.rb +0 -47
- data/spec/binary_protocol_spec.rb +0 -73
- data/spec/binary_protocol_spec_shared.rb +0 -509
- data/spec/bytes_spec.rb +0 -117
- data/spec/client_spec.rb +0 -167
- data/spec/compact_protocol_spec.rb +0 -295
- data/spec/constants_demo_spec.rb +0 -102
- data/spec/exception_spec.rb +0 -141
- data/spec/flat_spec.rb +0 -63
- data/spec/header_protocol_spec.rb +0 -476
- data/spec/header_transport_spec.rb +0 -431
- data/spec/http_client_spec.rb +0 -160
- data/spec/json_protocol_spec.rb +0 -574
- data/spec/multiplexed_processor_spec.rb +0 -75
- data/spec/namespaced_spec.rb +0 -67
- data/spec/nonblocking_server_spec.rb +0 -429
- data/spec/processor_spec.rb +0 -80
- data/spec/recursion_depth_spec.rb +0 -223
- data/spec/serializer_spec.rb +0 -67
- data/spec/server_socket_spec.rb +0 -121
- data/spec/server_spec.rb +0 -238
- data/spec/socket_spec.rb +0 -174
- data/spec/socket_spec_shared.rb +0 -168
- data/spec/spec_helper.rb +0 -70
- data/spec/ssl_server_socket_spec.rb +0 -85
- data/spec/ssl_socket_spec.rb +0 -248
- data/spec/struct_nested_containers_spec.rb +0 -191
- data/spec/struct_spec.rb +0 -398
- data/spec/support/header_protocol_helper.rb +0 -55
- data/spec/thin_http_server_spec.rb +0 -127
- data/spec/types_spec.rb +0 -118
- data/spec/union_spec.rb +0 -273
- data/spec/unix_socket_spec.rb +0 -131
- data/spec/uuid_validation_spec.rb +0 -239
- data/test/fuzz/Makefile +0 -779
- data/test/fuzz/Makefile.am +0 -173
- data/test/fuzz/Makefile.in +0 -775
- data/test/fuzz/README.md +0 -149
- data/test/fuzz/fuzz_common.rb +0 -96
- data/test/fuzz/fuzz_parse_binary_protocol.rb +0 -23
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +0 -23
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +0 -23
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_parse_compact_protocol.rb +0 -23
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_parse_json_protocol.rb +0 -23
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +0 -23
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +0 -23
- data/test/fuzz/fuzz_tracer.rb +0 -29
|
@@ -18,15 +18,20 @@
|
|
|
18
18
|
# under the License.
|
|
19
19
|
#
|
|
20
20
|
|
|
21
|
-
require
|
|
22
|
-
require
|
|
21
|
+
require "logger"
|
|
22
|
+
require "thread"
|
|
23
23
|
|
|
24
24
|
module Thrift
|
|
25
25
|
# this class expects to always use a FramedTransport for reading messages
|
|
26
26
|
class NonblockingServer < BaseServer
|
|
27
|
-
def initialize(processor, server_transport, transport_factory = nil, protocol_factory = nil, num = 20, logger = nil
|
|
27
|
+
def initialize(processor, server_transport, transport_factory = nil, protocol_factory = nil, num = 20, logger = nil,
|
|
28
|
+
max_frame_size: FramedTransport::DEFAULT_MAX_FRAME_SIZE)
|
|
28
29
|
super(processor, server_transport, transport_factory, protocol_factory)
|
|
30
|
+
unless max_frame_size > 0 && max_frame_size <= FramedTransport::HARD_MAX_FRAME_SIZE
|
|
31
|
+
raise ArgumentError, "max_frame_size must be > 0 and <= #{FramedTransport::HARD_MAX_FRAME_SIZE}"
|
|
32
|
+
end
|
|
29
33
|
@num_threads = num
|
|
34
|
+
@max_frame_size = max_frame_size
|
|
30
35
|
if logger.nil?
|
|
31
36
|
@logger = Logger.new(STDERR)
|
|
32
37
|
@logger.level = Logger::WARN
|
|
@@ -53,11 +58,16 @@ module Thrift
|
|
|
53
58
|
break
|
|
54
59
|
end
|
|
55
60
|
next if rd.nil?
|
|
56
|
-
|
|
61
|
+
begin
|
|
62
|
+
socket = @server_transport.accept
|
|
63
|
+
rescue => e
|
|
64
|
+
next if defined?(OpenSSL::SSL::SSLError) && e.is_a?(OpenSSL::SSL::SSLError)
|
|
65
|
+
raise
|
|
66
|
+
end
|
|
57
67
|
@logger.debug "Accepted socket: #{socket.inspect}"
|
|
58
68
|
@io_manager.add_connection socket
|
|
59
69
|
end
|
|
60
|
-
rescue IOError
|
|
70
|
+
rescue IOError
|
|
61
71
|
end
|
|
62
72
|
# we must be shutting down
|
|
63
73
|
@logger.info "#{self} is shutting down, goodbye"
|
|
@@ -84,14 +94,17 @@ module Thrift
|
|
|
84
94
|
if block
|
|
85
95
|
shutdown_proc.call
|
|
86
96
|
else
|
|
87
|
-
Thread.new
|
|
97
|
+
Thread.new(&shutdown_proc)
|
|
88
98
|
end
|
|
89
99
|
end
|
|
90
100
|
|
|
91
101
|
private
|
|
92
102
|
|
|
93
103
|
def start_io_manager
|
|
94
|
-
iom = IOManager.new(
|
|
104
|
+
iom = IOManager.new(
|
|
105
|
+
@processor, @server_transport, @transport_factory, @protocol_factory, @num_threads, @logger,
|
|
106
|
+
max_frame_size: @max_frame_size,
|
|
107
|
+
)
|
|
95
108
|
iom.spawn
|
|
96
109
|
iom
|
|
97
110
|
end
|
|
@@ -99,13 +112,15 @@ module Thrift
|
|
|
99
112
|
class IOManager # :nodoc:
|
|
100
113
|
DEFAULT_BUFFER = 2**20
|
|
101
114
|
|
|
102
|
-
def initialize(processor, server_transport, transport_factory, protocol_factory, num, logger
|
|
115
|
+
def initialize(processor, server_transport, transport_factory, protocol_factory, num, logger,
|
|
116
|
+
max_frame_size: FramedTransport::DEFAULT_MAX_FRAME_SIZE)
|
|
103
117
|
@processor = processor
|
|
104
118
|
@server_transport = server_transport
|
|
105
119
|
@transport_factory = transport_factory
|
|
106
120
|
@protocol_factory = protocol_factory
|
|
107
121
|
@num_threads = num
|
|
108
122
|
@logger = logger
|
|
123
|
+
@max_frame_size = max_frame_size
|
|
109
124
|
@connections = []
|
|
110
125
|
@buffers = Hash.new { |h, k| h[k] = Bytes.empty_byte_buffer }
|
|
111
126
|
@signal_queue = Queue.new
|
|
@@ -158,15 +173,13 @@ module Thrift
|
|
|
158
173
|
break if read_signals == :shutdown
|
|
159
174
|
end
|
|
160
175
|
rd.each do |fd|
|
|
161
|
-
|
|
162
|
-
if fd.handle.eof?
|
|
163
|
-
remove_connection fd
|
|
164
|
-
else
|
|
165
|
-
read_connection fd
|
|
166
|
-
end
|
|
167
|
-
rescue Errno::ECONNRESET
|
|
176
|
+
if fd.handle.eof?
|
|
168
177
|
remove_connection fd
|
|
178
|
+
else
|
|
179
|
+
read_connection fd
|
|
169
180
|
end
|
|
181
|
+
rescue Errno::ECONNRESET
|
|
182
|
+
remove_connection fd
|
|
170
183
|
end
|
|
171
184
|
end
|
|
172
185
|
join_worker_threads(@shutdown_timeout)
|
|
@@ -175,8 +188,22 @@ module Thrift
|
|
|
175
188
|
end
|
|
176
189
|
|
|
177
190
|
def read_connection(fd)
|
|
178
|
-
@buffers[fd]
|
|
179
|
-
|
|
191
|
+
buf = @buffers[fd]
|
|
192
|
+
buf << fd.read(DEFAULT_BUFFER)
|
|
193
|
+
while buf.length >= 4
|
|
194
|
+
# Refuse the size before collecting the frame: the four-byte length
|
|
195
|
+
# is read here and the bytes are then buffered as they arrive, for as
|
|
196
|
+
# long as the declared length allows. FramedTransport applies the
|
|
197
|
+
# same maximum to the frame the worker later reads back.
|
|
198
|
+
size = buf.unpack1("N")
|
|
199
|
+
if size > @max_frame_size
|
|
200
|
+
@logger.error "Frame size #{size} exceeds maximum #{@max_frame_size}, closing connection"
|
|
201
|
+
fd.close
|
|
202
|
+
remove_connection fd
|
|
203
|
+
break
|
|
204
|
+
end
|
|
205
|
+
frame = slice_frame!(buf)
|
|
206
|
+
break if frame.nil?
|
|
180
207
|
@logger.debug "#{self} is processing a frame"
|
|
181
208
|
@worker_queue.push [:frame, fd, frame]
|
|
182
209
|
end
|
|
@@ -254,10 +281,8 @@ module Thrift
|
|
|
254
281
|
|
|
255
282
|
def close_connections
|
|
256
283
|
@connections.each do |fd|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
rescue IOError, SystemCallError, TransportException
|
|
260
|
-
end
|
|
284
|
+
fd.close
|
|
285
|
+
rescue IOError, SystemCallError, TransportException
|
|
261
286
|
end
|
|
262
287
|
@connections.clear
|
|
263
288
|
@buffers.clear
|
|
@@ -265,16 +290,14 @@ module Thrift
|
|
|
265
290
|
|
|
266
291
|
def close_signal_pipes
|
|
267
292
|
@signal_pipes.each do |pipe|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
rescue IOError
|
|
271
|
-
end
|
|
293
|
+
pipe.close unless pipe.closed?
|
|
294
|
+
rescue IOError
|
|
272
295
|
end
|
|
273
296
|
end
|
|
274
297
|
|
|
275
298
|
def slice_frame!(buf)
|
|
276
299
|
if buf.length >= 4
|
|
277
|
-
size = buf.
|
|
300
|
+
size = buf.unpack1("N")
|
|
278
301
|
if buf.length >= size + 4
|
|
279
302
|
buf.slice!(0, size + 4)
|
|
280
303
|
else
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
|
+
# or more contributor license agreements. See the NOTICE file
|
|
5
|
+
# distributed with this work for additional information
|
|
6
|
+
# regarding copyright ownership. The ASF licenses this file
|
|
7
|
+
# to you under the Apache License, Version 2.0 (the
|
|
8
|
+
# "License"); you may not use this file except in compliance
|
|
9
|
+
# with the License. You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing,
|
|
14
|
+
# software distributed under the License is distributed on an
|
|
15
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
16
|
+
# KIND, either express or implied. See the License for the
|
|
17
|
+
# specific language governing permissions and limitations
|
|
18
|
+
# under the License.
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
require "rack"
|
|
22
|
+
require "thrift/transport/io_stream_transport"
|
|
23
|
+
|
|
24
|
+
module Thrift
|
|
25
|
+
class RackApplication
|
|
26
|
+
THRIFT_HEADER = "application/x-thrift"
|
|
27
|
+
|
|
28
|
+
def initialize(processor, protocol_factory = BinaryProtocolFactory.new)
|
|
29
|
+
@processor = processor
|
|
30
|
+
@protocol_factory = protocol_factory
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def call(env)
|
|
34
|
+
request = Rack::Request.new(env)
|
|
35
|
+
|
|
36
|
+
if self.class.valid_thrift_request?(request)
|
|
37
|
+
self.class.successful_request(request, @processor, @protocol_factory).finish
|
|
38
|
+
else
|
|
39
|
+
self.class.failed_request.finish
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.mapped(path, processor, protocol_factory = BinaryProtocolFactory.new)
|
|
44
|
+
Rack::Builder.new do
|
|
45
|
+
use Rack::ContentLength
|
|
46
|
+
map path do
|
|
47
|
+
run RackApplication.new(processor, protocol_factory)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.successful_request(rack_request, processor, protocol_factory)
|
|
53
|
+
response = Rack::Response.new([], 200, {Rack::CONTENT_TYPE => THRIFT_HEADER})
|
|
54
|
+
transport = IOStreamTransport.new(rack_request.body, response)
|
|
55
|
+
protocol = protocol_factory.get_protocol(transport)
|
|
56
|
+
processor.process protocol, protocol
|
|
57
|
+
|
|
58
|
+
response
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.failed_request
|
|
62
|
+
Rack::Response.new(["Not Found"], 404, {Rack::CONTENT_TYPE => THRIFT_HEADER})
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.valid_thrift_request?(rack_request)
|
|
66
|
+
rack_request.post? && rack_request.media_type == THRIFT_HEADER
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -21,35 +21,39 @@
|
|
|
21
21
|
module Thrift
|
|
22
22
|
class SimpleServer < BaseServer
|
|
23
23
|
def serve
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
@processor.process(prot, prot)
|
|
40
|
-
end
|
|
41
|
-
rescue Thrift::TransportException, Thrift::ProtocolException
|
|
42
|
-
ensure
|
|
43
|
-
trans.close
|
|
24
|
+
@server_transport.listen
|
|
25
|
+
loop do
|
|
26
|
+
begin
|
|
27
|
+
client = @server_transport.accept
|
|
28
|
+
rescue Errno::ECONNRESET, Errno::EPIPE
|
|
29
|
+
next
|
|
30
|
+
rescue => e
|
|
31
|
+
next if defined?(OpenSSL::SSL::SSLError) && e.is_a?(OpenSSL::SSL::SSLError)
|
|
32
|
+
raise
|
|
33
|
+
end
|
|
34
|
+
trans = @transport_factory.get_transport(client)
|
|
35
|
+
prot = @protocol_factory.get_protocol(trans)
|
|
36
|
+
begin
|
|
37
|
+
loop do
|
|
38
|
+
@processor.process(prot, prot)
|
|
44
39
|
end
|
|
40
|
+
rescue Thrift::TransportException, Thrift::ProtocolException
|
|
41
|
+
# The client hung up or sent a message this connection could not
|
|
42
|
+
# read. Close it below and keep accepting other clients.
|
|
43
|
+
rescue => e
|
|
44
|
+
# Any other error raised while serving this one client must not end
|
|
45
|
+
# the accept loop. Log it, close the connection, and keep serving.
|
|
46
|
+
@logger.error("Error while serving a client connection: #{e.inspect}")
|
|
47
|
+
ensure
|
|
48
|
+
trans.close
|
|
45
49
|
end
|
|
46
|
-
ensure
|
|
47
|
-
@server_transport.close
|
|
48
50
|
end
|
|
51
|
+
ensure
|
|
52
|
+
@server_transport.close
|
|
49
53
|
end
|
|
50
54
|
|
|
51
55
|
def to_s
|
|
52
|
-
"simple(#{super
|
|
56
|
+
"simple(#{super})"
|
|
53
57
|
end
|
|
54
58
|
end
|
|
55
59
|
end
|
|
@@ -18,14 +18,16 @@
|
|
|
18
18
|
# under the License.
|
|
19
19
|
#
|
|
20
20
|
|
|
21
|
-
require
|
|
22
|
-
require
|
|
21
|
+
require "rack"
|
|
22
|
+
require "thin"
|
|
23
|
+
require "thrift/server/rack_application"
|
|
23
24
|
|
|
24
25
|
##
|
|
25
26
|
# Wraps the Thin web server to provide a Thrift server over HTTP.
|
|
27
|
+
# <b>DEPRECATED:</b> Use <tt>Thrift::RackApplication</tt> with a maintained Rack
|
|
28
|
+
# server instead.
|
|
26
29
|
module Thrift
|
|
27
30
|
class ThinHTTPServer < BaseServer
|
|
28
|
-
|
|
29
31
|
##
|
|
30
32
|
# Accepts a Thrift::Processor
|
|
31
33
|
# Options include:
|
|
@@ -33,13 +35,26 @@ module Thrift
|
|
|
33
35
|
# * :ip
|
|
34
36
|
# * :path
|
|
35
37
|
# * :protocol_factory
|
|
38
|
+
# * :ssl
|
|
39
|
+
# * :ssl_options
|
|
36
40
|
def initialize(processor, options = {})
|
|
41
|
+
Kernel.warn "[DEPRECATION WARNING] `Thrift::ThinHTTPServer` is deprecated because Thin is no longer maintained. Please use `Thrift::RackApplication` with a maintained Rack server instead."
|
|
37
42
|
port = options[:port] || 80
|
|
38
43
|
ip = options[:ip] || "0.0.0.0"
|
|
39
44
|
path = options[:path] || "/"
|
|
40
45
|
protocol_factory = options[:protocol_factory] || BinaryProtocolFactory.new
|
|
41
|
-
|
|
46
|
+
endpoint = RackApplication.mapped(path, processor, protocol_factory)
|
|
47
|
+
app = Rack::Builder.new do
|
|
48
|
+
use Rack::CommonLogger
|
|
49
|
+
use Rack::ShowExceptions
|
|
50
|
+
use Rack::Lint
|
|
51
|
+
run endpoint
|
|
52
|
+
end
|
|
42
53
|
@server = Thin::Server.new(ip, port, app)
|
|
54
|
+
if options[:ssl]
|
|
55
|
+
@server.ssl = true
|
|
56
|
+
@server.ssl_options = options[:ssl_options] || {}
|
|
57
|
+
end
|
|
43
58
|
end
|
|
44
59
|
|
|
45
60
|
##
|
|
@@ -48,45 +63,6 @@ module Thrift
|
|
|
48
63
|
@server.start
|
|
49
64
|
end
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
THRIFT_HEADER = "application/x-thrift"
|
|
54
|
-
|
|
55
|
-
def self.for(path, processor, protocol_factory)
|
|
56
|
-
Rack::Builder.new do
|
|
57
|
-
use Rack::CommonLogger
|
|
58
|
-
use Rack::ShowExceptions
|
|
59
|
-
use Rack::Lint
|
|
60
|
-
map path do
|
|
61
|
-
run lambda { |env|
|
|
62
|
-
request = Rack::Request.new(env)
|
|
63
|
-
if RackApplication.valid_thrift_request?(request)
|
|
64
|
-
RackApplication.successful_request(request, processor, protocol_factory).finish
|
|
65
|
-
else
|
|
66
|
-
RackApplication.failed_request.finish
|
|
67
|
-
end
|
|
68
|
-
}
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def self.successful_request(rack_request, processor, protocol_factory)
|
|
74
|
-
response = Rack::Response.new([], 200, {'Content-Type' => THRIFT_HEADER})
|
|
75
|
-
transport = IOStreamTransport.new rack_request.body, response
|
|
76
|
-
protocol = protocol_factory.get_protocol transport
|
|
77
|
-
processor.process protocol, protocol
|
|
78
|
-
response
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def self.failed_request
|
|
82
|
-
Rack::Response.new(['Not Found'], 404, {'Content-Type' => THRIFT_HEADER})
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def self.valid_thrift_request?(rack_request)
|
|
86
|
-
rack_request.post? && rack_request.env["CONTENT_TYPE"] == THRIFT_HEADER
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
end
|
|
90
|
-
|
|
66
|
+
RackApplication = Thrift::RackApplication
|
|
91
67
|
end
|
|
92
68
|
end
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
# under the License.
|
|
19
19
|
#
|
|
20
20
|
|
|
21
|
-
require
|
|
21
|
+
require "thread"
|
|
22
22
|
|
|
23
23
|
module Thrift
|
|
24
24
|
class ThreadPoolServer < BaseServer
|
|
@@ -47,25 +47,28 @@ module Thrift
|
|
|
47
47
|
loop do
|
|
48
48
|
@thread_q.push(:token)
|
|
49
49
|
Thread.new do
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
loop do
|
|
51
|
+
begin
|
|
52
52
|
client = @server_transport.accept
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
53
|
+
rescue => e
|
|
54
|
+
next if defined?(OpenSSL::SSL::SSLError) && e.is_a?(OpenSSL::SSL::SSLError)
|
|
55
|
+
raise
|
|
56
|
+
end
|
|
57
|
+
trans = @transport_factory.get_transport(client)
|
|
58
|
+
prot = @protocol_factory.get_protocol(trans)
|
|
59
|
+
begin
|
|
60
|
+
loop do
|
|
61
|
+
@processor.process(prot, prot)
|
|
62
62
|
end
|
|
63
|
+
rescue Thrift::TransportException, Thrift::ProtocolException
|
|
64
|
+
ensure
|
|
65
|
+
trans.close
|
|
63
66
|
end
|
|
64
|
-
rescue => e
|
|
65
|
-
@exception_q.push(e)
|
|
66
|
-
ensure
|
|
67
|
-
@thread_q.pop # thread died!
|
|
68
67
|
end
|
|
68
|
+
rescue => e
|
|
69
|
+
@exception_q.push(e)
|
|
70
|
+
ensure
|
|
71
|
+
@thread_q.pop # thread died!
|
|
69
72
|
end
|
|
70
73
|
end
|
|
71
74
|
ensure
|
|
@@ -74,7 +77,7 @@ module Thrift
|
|
|
74
77
|
end
|
|
75
78
|
|
|
76
79
|
def to_s
|
|
77
|
-
"threadpool(#{super
|
|
80
|
+
"threadpool(#{super})"
|
|
78
81
|
end
|
|
79
82
|
end
|
|
80
83
|
end
|
|
@@ -18,42 +18,38 @@
|
|
|
18
18
|
# under the License.
|
|
19
19
|
#
|
|
20
20
|
|
|
21
|
-
require
|
|
21
|
+
require "thread"
|
|
22
22
|
|
|
23
23
|
module Thrift
|
|
24
24
|
class ThreadedServer < BaseServer
|
|
25
25
|
def serve
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
loop do
|
|
42
|
-
@processor.process(p, p)
|
|
43
|
-
end
|
|
44
|
-
rescue Thrift::TransportException, Thrift::ProtocolException
|
|
45
|
-
ensure
|
|
46
|
-
t.close
|
|
47
|
-
end
|
|
26
|
+
@server_transport.listen
|
|
27
|
+
loop do
|
|
28
|
+
begin
|
|
29
|
+
client = @server_transport.accept
|
|
30
|
+
rescue Errno::ECONNRESET, Errno::EPIPE
|
|
31
|
+
next
|
|
32
|
+
rescue => e
|
|
33
|
+
next if defined?(OpenSSL::SSL::SSLError) && e.is_a?(OpenSSL::SSL::SSLError)
|
|
34
|
+
raise
|
|
35
|
+
end
|
|
36
|
+
trans = @transport_factory.get_transport(client)
|
|
37
|
+
prot = @protocol_factory.get_protocol(trans)
|
|
38
|
+
Thread.new(prot, trans) do |p, t|
|
|
39
|
+
loop do
|
|
40
|
+
@processor.process(p, p)
|
|
48
41
|
end
|
|
42
|
+
rescue Thrift::TransportException, Thrift::ProtocolException
|
|
43
|
+
ensure
|
|
44
|
+
t.close
|
|
49
45
|
end
|
|
50
|
-
ensure
|
|
51
|
-
@server_transport.close
|
|
52
46
|
end
|
|
47
|
+
ensure
|
|
48
|
+
@server_transport.close
|
|
53
49
|
end
|
|
54
50
|
|
|
55
51
|
def to_s
|
|
56
|
-
"threaded(#{super
|
|
52
|
+
"threaded(#{super})"
|
|
57
53
|
end
|
|
58
54
|
end
|
|
59
55
|
end
|
data/lib/thrift/struct.rb
CHANGED
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
# under the License.
|
|
19
19
|
#
|
|
20
20
|
|
|
21
|
-
require
|
|
21
|
+
require "set"
|
|
22
|
+
require "thrift/struct_union"
|
|
22
23
|
|
|
23
24
|
module Thrift
|
|
24
25
|
module Struct
|
|
@@ -52,7 +53,7 @@ module Thrift
|
|
|
52
53
|
end
|
|
53
54
|
end
|
|
54
55
|
|
|
55
|
-
yield self if
|
|
56
|
+
yield self if block
|
|
56
57
|
end
|
|
57
58
|
|
|
58
59
|
def fields_with_default_values
|
|
@@ -81,19 +82,31 @@ module Thrift
|
|
|
81
82
|
"<#{self.class} #{fields.join(", ")}>"
|
|
82
83
|
end
|
|
83
84
|
|
|
84
|
-
def read(iprot)
|
|
85
|
+
def read(iprot, remaining_depth = DEFAULT_RECURSION_DEPTH)
|
|
86
|
+
raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum recursion depth exceeded") if remaining_depth <= 0
|
|
87
|
+
unless instance_variables.empty?
|
|
88
|
+
defaults = fields_with_default_values
|
|
89
|
+
struct_fields.each_value do |field_info|
|
|
90
|
+
instance_variable_set("@#{field_info[:name]}", nil)
|
|
91
|
+
end
|
|
92
|
+
defaults.each do |name, default_value|
|
|
93
|
+
instance_variable_set("@#{name}", (default_value.dup rescue default_value))
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
85
97
|
iprot.read_struct_begin
|
|
86
98
|
loop do
|
|
87
|
-
|
|
99
|
+
_, ftype, fid = iprot.read_field_begin
|
|
88
100
|
break if (ftype == Types::STOP)
|
|
89
|
-
handle_message(iprot, fid, ftype)
|
|
101
|
+
handle_message(iprot, fid, ftype, remaining_depth)
|
|
90
102
|
iprot.read_field_end
|
|
91
103
|
end
|
|
92
104
|
iprot.read_struct_end
|
|
93
105
|
validate
|
|
94
106
|
end
|
|
95
107
|
|
|
96
|
-
def write(oprot)
|
|
108
|
+
def write(oprot, remaining_depth = DEFAULT_RECURSION_DEPTH)
|
|
109
|
+
raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum recursion depth exceeded") if remaining_depth <= 0
|
|
97
110
|
validate
|
|
98
111
|
oprot.write_struct_begin(self.class.name)
|
|
99
112
|
each_field do |fid, field_info|
|
|
@@ -103,8 +116,10 @@ module Thrift
|
|
|
103
116
|
unless value.nil?
|
|
104
117
|
if is_container? type
|
|
105
118
|
oprot.write_field_begin(name, type, fid)
|
|
106
|
-
write_container(oprot, value, field_info)
|
|
119
|
+
write_container(oprot, value, field_info, remaining_depth)
|
|
107
120
|
oprot.write_field_end
|
|
121
|
+
elsif type == Types::STRUCT
|
|
122
|
+
oprot.write_field(field_info, fid, value, remaining_depth)
|
|
108
123
|
else
|
|
109
124
|
oprot.write_field(field_info, fid, value)
|
|
110
125
|
end
|
|
@@ -115,10 +130,10 @@ module Thrift
|
|
|
115
130
|
end
|
|
116
131
|
|
|
117
132
|
def ==(other)
|
|
118
|
-
return false
|
|
133
|
+
return false unless other.instance_of?(self.class)
|
|
119
134
|
each_field do |fid, field_info|
|
|
120
135
|
name = field_info[:name]
|
|
121
|
-
return false unless other.respond_to?(name) &&
|
|
136
|
+
return false unless other.respond_to?(name) && send(name) == other.send(name)
|
|
122
137
|
end
|
|
123
138
|
true
|
|
124
139
|
end
|
|
@@ -132,8 +147,8 @@ module Thrift
|
|
|
132
147
|
total = 17
|
|
133
148
|
each_field do |fid, field_info|
|
|
134
149
|
name = field_info[:name]
|
|
135
|
-
value =
|
|
136
|
-
total = (total * 37 + value.hash) & 0xffffffff
|
|
150
|
+
value = send(name)
|
|
151
|
+
total = ((total * 37) + value.hash) & 0xffffffff
|
|
137
152
|
end
|
|
138
153
|
total
|
|
139
154
|
end
|
|
@@ -145,7 +160,7 @@ module Thrift
|
|
|
145
160
|
else
|
|
146
161
|
each_field do |fid, field_info|
|
|
147
162
|
name = field_info[:name]
|
|
148
|
-
diffs << "#{name} differs!" unless
|
|
163
|
+
diffs << "#{name} differs!" unless instance_variable_get("@#{name}") == other.instance_variable_get("@#{name}")
|
|
149
164
|
end
|
|
150
165
|
end
|
|
151
166
|
diffs
|
|
@@ -169,14 +184,14 @@ module Thrift
|
|
|
169
184
|
|
|
170
185
|
def self.qmark_isset_method(klass, field_info)
|
|
171
186
|
klass.send :define_method, "#{field_info[:name]}?" do
|
|
172
|
-
!
|
|
187
|
+
!send(field_info[:name].to_sym).nil?
|
|
173
188
|
end
|
|
174
189
|
end
|
|
175
190
|
|
|
176
191
|
def <=>(other)
|
|
177
192
|
if self.class == other.class
|
|
178
193
|
each_field do |fid, field_info|
|
|
179
|
-
v1 =
|
|
194
|
+
v1 = send(field_info[:name])
|
|
180
195
|
v1_set = !v1.nil?
|
|
181
196
|
v2 = other.send(field_info[:name])
|
|
182
197
|
v2_set = !v2.nil?
|
|
@@ -218,17 +233,17 @@ module Thrift
|
|
|
218
233
|
else
|
|
219
234
|
# call the Struct initializer first with no args
|
|
220
235
|
# this will set our field default values
|
|
221
|
-
method(:struct_initialize).call
|
|
236
|
+
method(:struct_initialize).call
|
|
222
237
|
# now give it to the exception
|
|
223
|
-
self.class.send(:class_variable_get, :'@@__thrift_struct_real_initialize').
|
|
238
|
+
self.class.send(:class_variable_get, :'@@__thrift_struct_real_initialize').bind_call(self, *args, &block) if args.size > 0
|
|
224
239
|
# self.class.instance_method(:initialize).bind(self).call(*args, &block)
|
|
225
240
|
end
|
|
226
241
|
end
|
|
227
242
|
|
|
228
|
-
def handle_message(iprot, fid, ftype)
|
|
243
|
+
def handle_message(iprot, fid, ftype, remaining_depth)
|
|
229
244
|
field = struct_fields[fid]
|
|
230
245
|
if field and field[:type] == ftype
|
|
231
|
-
value = read_field(iprot, field)
|
|
246
|
+
value = read_field(iprot, field, remaining_depth)
|
|
232
247
|
instance_variable_set("@#{field[:name]}", value)
|
|
233
248
|
else
|
|
234
249
|
iprot.skip(ftype)
|