thrift 0.0.751142

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/CHANGELOG +2 -0
  2. data/COPYING +14 -0
  3. data/LICENSE +14 -0
  4. data/Makefile.am +15 -0
  5. data/Manifest +78 -0
  6. data/README +30 -0
  7. data/Rakefile +102 -0
  8. data/benchmark/Benchmark.thrift +5 -0
  9. data/benchmark/benchmark.rb +254 -0
  10. data/benchmark/client.rb +56 -0
  11. data/benchmark/gen-rb/BenchmarkService.rb +81 -0
  12. data/benchmark/gen-rb/Benchmark_constants.rb +11 -0
  13. data/benchmark/gen-rb/Benchmark_types.rb +10 -0
  14. data/benchmark/server.rb +64 -0
  15. data/benchmark/thin_server.rb +26 -0
  16. data/ext/binary_protocol_accelerated.c +463 -0
  17. data/ext/binary_protocol_accelerated.h +1 -0
  18. data/ext/constants.h +77 -0
  19. data/ext/extconf.rb +7 -0
  20. data/ext/memory_buffer.c +52 -0
  21. data/ext/memory_buffer.h +1 -0
  22. data/ext/protocol.c +166 -0
  23. data/ext/protocol.h +1 -0
  24. data/ext/struct.c +574 -0
  25. data/ext/struct.h +48 -0
  26. data/ext/thrift_native.c +173 -0
  27. data/lib/thrift/client.rb +44 -0
  28. data/lib/thrift/deprecation.rb +155 -0
  29. data/lib/thrift/exceptions.rb +65 -0
  30. data/lib/thrift/processor.rb +39 -0
  31. data/lib/thrift/protocol/binaryprotocol.rb +213 -0
  32. data/lib/thrift/protocol/binaryprotocolaccelerated.rb +19 -0
  33. data/lib/thrift/protocol/tbinaryprotocol.rb +2 -0
  34. data/lib/thrift/protocol/tprotocol.rb +2 -0
  35. data/lib/thrift/protocol.rb +270 -0
  36. data/lib/thrift/serializer.rb +27 -0
  37. data/lib/thrift/server/httpserver.rb +44 -0
  38. data/lib/thrift/server/nonblockingserver.rb +278 -0
  39. data/lib/thrift/server/thttpserver.rb +2 -0
  40. data/lib/thrift/server/tserver.rb +2 -0
  41. data/lib/thrift/server.rb +135 -0
  42. data/lib/thrift/struct.rb +272 -0
  43. data/lib/thrift/thrift.rb +14 -0
  44. data/lib/thrift/transport/httpclient.rb +29 -0
  45. data/lib/thrift/transport/socket.rb +167 -0
  46. data/lib/thrift/transport/thttpclient.rb +2 -0
  47. data/lib/thrift/transport/tsocket.rb +2 -0
  48. data/lib/thrift/transport/ttransport.rb +2 -0
  49. data/lib/thrift/transport/unixsocket.rb +58 -0
  50. data/lib/thrift/transport.rb +319 -0
  51. data/lib/thrift/types.rb +83 -0
  52. data/lib/thrift.rb +28 -0
  53. data/setup.rb +1585 -0
  54. data/spec/ThriftSpec.thrift +46 -0
  55. data/spec/backwards_compatibility_spec.rb +136 -0
  56. data/spec/binaryprotocol_spec.rb +45 -0
  57. data/spec/binaryprotocol_spec_shared.rb +274 -0
  58. data/spec/binaryprotocolaccelerated_spec.rb +101 -0
  59. data/spec/client_spec.rb +81 -0
  60. data/spec/deprecation_spec.rb +443 -0
  61. data/spec/exception_spec.rb +123 -0
  62. data/spec/gen-rb/NonblockingService.rb +268 -0
  63. data/spec/gen-rb/ThriftSpec_constants.rb +11 -0
  64. data/spec/gen-rb/ThriftSpec_types.rb +134 -0
  65. data/spec/httpclient_spec.rb +31 -0
  66. data/spec/httpserver_spec.rb +98 -0
  67. data/spec/nonblockingserver_spec.rb +245 -0
  68. data/spec/processor_spec.rb +64 -0
  69. data/spec/protocol_spec.rb +142 -0
  70. data/spec/serializer_spec.rb +52 -0
  71. data/spec/server_spec.rb +141 -0
  72. data/spec/socket_spec.rb +97 -0
  73. data/spec/socket_spec_shared.rb +85 -0
  74. data/spec/spec_helper.rb +35 -0
  75. data/spec/struct_spec.rb +244 -0
  76. data/spec/transport_spec.rb +359 -0
  77. data/spec/types_spec.rb +98 -0
  78. data/spec/unixsocket_spec.rb +90 -0
  79. data/thrift.gemspec +33 -0
  80. data.tar.gz.sig +0 -0
  81. metadata +200 -0
  82. metadata.gz.sig +0 -0
@@ -0,0 +1,135 @@
1
+ # Copyright (c) 2006- Facebook
2
+ # Distributed under the Apache Software License
3
+ #
4
+ # See accompanying file LICENSE or visit the Thrift site at:
5
+ # http://developers.facebook.com/thrift/
6
+ #
7
+ # Author: Mark Slee <mcslee@facebook.com>
8
+ #
9
+ require 'thrift/protocol'
10
+ require 'thrift/protocol/binaryprotocol'
11
+ require 'thrift/transport'
12
+
13
+ module Thrift
14
+ class Server
15
+ def initialize(processor, serverTransport, transportFactory=nil, protocolFactory=nil)
16
+ @processor = processor
17
+ @serverTransport = serverTransport
18
+ @transportFactory = transportFactory ? transportFactory : Thrift::TransportFactory.new
19
+ @protocolFactory = protocolFactory ? protocolFactory : Thrift::BinaryProtocolFactory.new
20
+ end
21
+
22
+ def serve; nil; end
23
+ end
24
+ deprecate_class! :TServer => Server
25
+
26
+ class SimpleServer < Server
27
+ def serve
28
+ begin
29
+ @serverTransport.listen
30
+ loop do
31
+ client = @serverTransport.accept
32
+ trans = @transportFactory.get_transport(client)
33
+ prot = @protocolFactory.get_protocol(trans)
34
+ begin
35
+ loop do
36
+ @processor.process(prot, prot)
37
+ end
38
+ rescue Thrift::TransportException, Thrift::ProtocolException
39
+ ensure
40
+ trans.close
41
+ end
42
+ end
43
+ ensure
44
+ @serverTransport.close
45
+ end
46
+ end
47
+ end
48
+ deprecate_class! :TSimpleServer => SimpleServer
49
+ end
50
+
51
+ # do *not* use fastthread
52
+ # it has a bug that triggers on NonblockingServer
53
+ require 'thread'
54
+
55
+ module Thrift
56
+ class ThreadedServer < Server
57
+ def serve
58
+ begin
59
+ @serverTransport.listen
60
+ loop do
61
+ client = @serverTransport.accept
62
+ trans = @transportFactory.get_transport(client)
63
+ prot = @protocolFactory.get_protocol(trans)
64
+ Thread.new(prot, trans) do |p, t|
65
+ begin
66
+ loop do
67
+ @processor.process(p, p)
68
+ end
69
+ rescue Thrift::TransportException, Thrift::ProtocolException
70
+ ensure
71
+ t.close
72
+ end
73
+ end
74
+ end
75
+ ensure
76
+ @serverTransport.close
77
+ end
78
+ end
79
+ end
80
+ deprecate_class! :TThreadedServer => ThreadedServer
81
+
82
+ class ThreadPoolServer < Server
83
+ def initialize(processor, serverTransport, transportFactory=nil, protocolFactory=nil, num=20)
84
+ super(processor, serverTransport, transportFactory, protocolFactory)
85
+ @thread_q = SizedQueue.new(num)
86
+ @exception_q = Queue.new
87
+ @running = false
88
+ end
89
+
90
+ ## exceptions that happen in worker threads will be relayed here and
91
+ ## must be caught. 'retry' can be used to continue. (threads will
92
+ ## continue to run while the exception is being handled.)
93
+ def rescuable_serve
94
+ Thread.new { serve } unless @running
95
+ @running = true
96
+ raise @exception_q.pop
97
+ end
98
+
99
+ ## exceptions that happen in worker threads simply cause that thread
100
+ ## to die and another to be spawned in its place.
101
+ def serve
102
+ @serverTransport.listen
103
+
104
+ begin
105
+ loop do
106
+ @thread_q.push(:token)
107
+ Thread.new do
108
+ begin
109
+ loop do
110
+ client = @serverTransport.accept
111
+ trans = @transportFactory.get_transport(client)
112
+ prot = @protocolFactory.get_protocol(trans)
113
+ begin
114
+ loop do
115
+ @processor.process(prot, prot)
116
+ end
117
+ rescue Thrift::TransportException, Thrift::ProtocolException => e
118
+ ensure
119
+ trans.close
120
+ end
121
+ end
122
+ rescue => e
123
+ @exception_q.push(e)
124
+ ensure
125
+ @thread_q.pop # thread died!
126
+ end
127
+ end
128
+ end
129
+ ensure
130
+ @serverTransport.close
131
+ end
132
+ end
133
+ end
134
+ deprecate_class! :TThreadPoolServer => ThreadPoolServer
135
+ end
@@ -0,0 +1,272 @@
1
+ require 'thrift/types'
2
+ require 'set'
3
+
4
+ module Thrift
5
+ module Struct
6
+ def initialize(d={})
7
+ # get a copy of the default values to work on, removing defaults in favor of arguments
8
+ fields_with_defaults = fields_with_default_values.dup
9
+
10
+ # check if the defaults is empty, or if there are no parameters for this
11
+ # instantiation, and if so, don't bother overriding defaults.
12
+ unless fields_with_defaults.empty? || d.empty?
13
+ d.each_key do |name|
14
+ fields_with_defaults.delete(name.to_s)
15
+ end
16
+ end
17
+
18
+ # assign all the user-specified arguments
19
+ unless d.empty?
20
+ d.each do |name, value|
21
+ unless name_to_id(name.to_s)
22
+ raise Exception, "Unknown key given to #{self.class}.new: #{name}"
23
+ end
24
+ Thrift.check_type(value, struct_fields[name_to_id(name.to_s)], name) if Thrift.type_checking
25
+ instance_variable_set("@#{name}", value)
26
+ end
27
+ end
28
+
29
+ # assign all the default values
30
+ unless fields_with_defaults.empty?
31
+ fields_with_defaults.each do |name, default_value|
32
+ instance_variable_set("@#{name}", (default_value.dup rescue default_value))
33
+ end
34
+ end
35
+ end
36
+
37
+ def fields_with_default_values
38
+ fields_with_default_values = self.class.instance_variable_get("@fields_with_default_values")
39
+ unless fields_with_default_values
40
+ fields_with_default_values = {}
41
+ struct_fields.each do |fid, field_def|
42
+ if field_def[:default]
43
+ fields_with_default_values[field_def[:name]] = field_def[:default]
44
+ end
45
+ end
46
+ self.class.instance_variable_set("@fields_with_default_values", fields_with_default_values)
47
+ end
48
+ fields_with_default_values
49
+ end
50
+
51
+ def name_to_id(name)
52
+ names_to_ids = self.class.instance_variable_get("@names_to_ids")
53
+ unless names_to_ids
54
+ names_to_ids = {}
55
+ struct_fields.each do |fid, field_def|
56
+ names_to_ids[field_def[:name]] = fid
57
+ end
58
+ self.class.instance_variable_set("@names_to_ids", names_to_ids)
59
+ end
60
+ names_to_ids[name]
61
+ end
62
+
63
+ # Obsoleted by THRIFT-246, which generates this method inline
64
+ # TODO: Should be removed at some point. -- Kevin Clark
65
+ def struct_fields
66
+ self.class.const_get(:FIELDS)
67
+ end
68
+
69
+ def each_field
70
+ struct_fields.each do |fid, data|
71
+ yield fid, data[:type], data[:name], data[:default], data[:optional]
72
+ end
73
+ end
74
+
75
+ def inspect(skip_optional_nulls = true)
76
+ fields = []
77
+ each_field do |fid, type, name, default, optional|
78
+ value = instance_variable_get("@#{name}")
79
+ unless skip_optional_nulls && optional && value.nil?
80
+ fields << "#{name}:#{value.inspect}"
81
+ end
82
+ end
83
+ "<#{self.class} #{fields.join(", ")}>"
84
+ end
85
+
86
+ def read(iprot)
87
+ # TODO(kevinclark): Make sure transport is C readable
88
+ if iprot.respond_to?(:decode_binary)
89
+ iprot.decode_binary(self, iprot.trans)
90
+ else
91
+ iprot.read_struct_begin
92
+ loop do
93
+ fname, ftype, fid = iprot.read_field_begin
94
+ break if (ftype == Types::STOP)
95
+ handle_message(iprot, fid, ftype)
96
+ iprot.read_field_end
97
+ end
98
+ iprot.read_struct_end
99
+ end
100
+ validate
101
+ end
102
+
103
+ def write(oprot)
104
+ validate
105
+ # if oprot.respond_to?(:encode_binary)
106
+ # # TODO(kevinclark): Clean this so I don't have to access the transport.
107
+ # oprot.trans.write oprot.encode_binary(self)
108
+ # else
109
+ oprot.write_struct_begin(self.class.name)
110
+ each_field do |fid, type, name|
111
+ unless (value = instance_variable_get("@#{name}")).nil?
112
+ if is_container? type
113
+ oprot.write_field_begin(name, type, fid)
114
+ write_container(oprot, value, struct_fields[fid])
115
+ oprot.write_field_end
116
+ else
117
+ oprot.write_field(name, type, fid, value)
118
+ end
119
+ end
120
+ end
121
+ oprot.write_field_stop
122
+ oprot.write_struct_end
123
+ # end
124
+ end
125
+
126
+ def ==(other)
127
+ return false unless other.is_a?(self.class)
128
+ each_field do |fid, type, name, default|
129
+ return false unless self.instance_variable_get("@#{name}") == other.instance_variable_get("@#{name}")
130
+ end
131
+ true
132
+ end
133
+
134
+ def eql?(other)
135
+ self.class == other.class && self == other
136
+ end
137
+
138
+ # for the time being, we're ok with a naive hash. this could definitely be improved upon.
139
+ def hash
140
+ 0
141
+ end
142
+
143
+ def self.field_accessor(klass, *fields)
144
+ fields.each do |field|
145
+ klass.send :attr_reader, field
146
+ klass.send :define_method, "#{field}=" do |value|
147
+ Thrift.check_type(value, klass::FIELDS.values.find { |f| f[:name].to_s == field.to_s }, field) if Thrift.type_checking
148
+ instance_variable_set("@#{field}", value)
149
+ end
150
+ end
151
+ end
152
+
153
+ protected
154
+
155
+ def self.append_features(mod)
156
+ if mod.ancestors.include? ::Exception
157
+ mod.send :class_variable_set, :'@@__thrift_struct_real_initialize', mod.instance_method(:initialize)
158
+ super
159
+ # set up our custom initializer so `raise Xception, 'message'` works
160
+ mod.send :define_method, :struct_initialize, mod.instance_method(:initialize)
161
+ mod.send :define_method, :initialize, mod.instance_method(:exception_initialize)
162
+ else
163
+ super
164
+ end
165
+ end
166
+
167
+ def exception_initialize(*args, &block)
168
+ if args.size == 1 and args.first.is_a? Hash
169
+ # looks like it's a regular Struct initialize
170
+ method(:struct_initialize).call(args.first)
171
+ else
172
+ # call the Struct initializer first with no args
173
+ # this will set our field default values
174
+ method(:struct_initialize).call()
175
+ # now give it to the exception
176
+ self.class.send(:class_variable_get, :'@@__thrift_struct_real_initialize').bind(self).call(*args, &block) if args.size > 0
177
+ # self.class.instance_method(:initialize).bind(self).call(*args, &block)
178
+ end
179
+ end
180
+
181
+ def handle_message(iprot, fid, ftype)
182
+ field = struct_fields[fid]
183
+ if field and field[:type] == ftype
184
+ value = read_field(iprot, field)
185
+ instance_variable_set("@#{field[:name]}", value)
186
+ else
187
+ iprot.skip(ftype)
188
+ end
189
+ end
190
+
191
+ def read_field(iprot, field = {})
192
+ case field[:type]
193
+ when Types::STRUCT
194
+ value = field[:class].new
195
+ value.read(iprot)
196
+ when Types::MAP
197
+ key_type, val_type, size = iprot.read_map_begin
198
+ value = {}
199
+ size.times do
200
+ k = read_field(iprot, field_info(field[:key]))
201
+ v = read_field(iprot, field_info(field[:value]))
202
+ value[k] = v
203
+ end
204
+ iprot.read_map_end
205
+ when Types::LIST
206
+ e_type, size = iprot.read_list_begin
207
+ value = Array.new(size) do |n|
208
+ read_field(iprot, field_info(field[:element]))
209
+ end
210
+ iprot.read_list_end
211
+ when Types::SET
212
+ e_type, size = iprot.read_set_begin
213
+ value = Set.new
214
+ size.times do
215
+ element = read_field(iprot, field_info(field[:element]))
216
+ value << element
217
+ end
218
+ iprot.read_set_end
219
+ else
220
+ value = iprot.read_type(field[:type])
221
+ end
222
+ value
223
+ end
224
+
225
+ def write_data(oprot, value, field)
226
+ if is_container? field[:type]
227
+ write_container(oprot, value, field)
228
+ else
229
+ oprot.write_type(field[:type], value)
230
+ end
231
+ end
232
+
233
+ def write_container(oprot, value, field = {})
234
+ case field[:type]
235
+ when Types::MAP
236
+ oprot.write_map_begin(field[:key][:type], field[:value][:type], value.size)
237
+ value.each do |k, v|
238
+ write_data(oprot, k, field[:key])
239
+ write_data(oprot, v, field[:value])
240
+ end
241
+ oprot.write_map_end
242
+ when Types::LIST
243
+ oprot.write_list_begin(field[:element][:type], value.size)
244
+ value.each do |elem|
245
+ write_data(oprot, elem, field[:element])
246
+ end
247
+ oprot.write_list_end
248
+ when Types::SET
249
+ oprot.write_set_begin(field[:element][:type], value.size)
250
+ value.each do |v,| # the , is to preserve compatibility with the old Hash-style sets
251
+ write_data(oprot, v, field[:element])
252
+ end
253
+ oprot.write_set_end
254
+ else
255
+ raise "Not a container type: #{field[:type]}"
256
+ end
257
+ end
258
+
259
+ def is_container?(type)
260
+ [Types::LIST, Types::MAP, Types::SET].include? type
261
+ end
262
+
263
+ def field_info(field)
264
+ { :type => field[:type],
265
+ :class => field[:class],
266
+ :key => field[:key],
267
+ :value => field[:value],
268
+ :element => field[:element] }
269
+ end
270
+ end
271
+ deprecate_module! :ThriftStruct => Struct
272
+ end
@@ -0,0 +1,14 @@
1
+ # This file kept for backwards compatability
2
+ # require File.join(File.dirname(__FILE__), '../thrift')
3
+ $:.unshift File.dirname(File.dirname(__FILE__))
4
+ require 'thrift/deprecation'
5
+ require 'thrift/types'
6
+ require 'thrift/processor'
7
+ require 'thrift/exceptions'
8
+ require 'thrift/client'
9
+ require 'thrift/struct'
10
+ begin
11
+ require "thrift_native"
12
+ rescue
13
+ puts "Could not load thrift_native libraries. Using pure ruby version."
14
+ end
@@ -0,0 +1,29 @@
1
+ require 'thrift/transport'
2
+
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'uri'
6
+ require 'stringio'
7
+
8
+ ## Very simple HTTP client
9
+ module Thrift
10
+ class HTTPClient < Transport
11
+ def initialize(url)
12
+ @url = URI url
13
+ @outbuf = ""
14
+ end
15
+
16
+ def open?; true end
17
+ def read(sz); @inbuf.read sz end
18
+ def write(buf); @outbuf << buf end
19
+ def flush
20
+ http = Net::HTTP.new @url.host, @url.port
21
+ http.use_ssl = @url.scheme == "https"
22
+ headers = { 'Content-Type' => 'application/x-thrift' }
23
+ resp, data = http.post(@url.path, @outbuf, headers)
24
+ @inbuf = StringIO.new data
25
+ @outbuf = ""
26
+ end
27
+ end
28
+ deprecate_class! :THttpClient => HTTPClient
29
+ end
@@ -0,0 +1,167 @@
1
+ # Copyright (c) 2006- Facebook
2
+ # Distributed under the Apache Software License
3
+ #
4
+ # See accompanying file LICENSE or visit the Thrift site at:
5
+ # http://developers.facebook.com/thrift/
6
+ #
7
+ # Author: Mark Slee <mcslee@facebook.com>
8
+ #
9
+ require 'thrift/transport'
10
+ require 'socket'
11
+
12
+ module Thrift
13
+ class Socket < Transport
14
+ def initialize(host='localhost', port=9090, timeout=nil)
15
+ @host = host
16
+ @port = port
17
+ @timeout = timeout
18
+ @desc = "#{host}:#{port}"
19
+ @handle = nil
20
+ end
21
+
22
+ attr_accessor :handle, :timeout
23
+
24
+ def open
25
+ begin
26
+ addrinfo = ::Socket::getaddrinfo(@host, @port).first
27
+ @handle = ::Socket.new(addrinfo[4], ::Socket::SOCK_STREAM, 0)
28
+ sockaddr = ::Socket.sockaddr_in(addrinfo[1], addrinfo[3])
29
+ begin
30
+ @handle.connect_nonblock(sockaddr)
31
+ rescue Errno::EINPROGRESS
32
+ unless IO.select(nil, [ @handle ], nil, @timeout)
33
+ raise TransportException.new(TransportException::NOT_OPEN, "Connection timeout to #{@desc}")
34
+ end
35
+ begin
36
+ @handle.connect_nonblock(sockaddr)
37
+ rescue Errno::EISCONN
38
+ end
39
+ end
40
+ @handle
41
+ rescue StandardError => e
42
+ raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}: #{e}")
43
+ end
44
+ end
45
+
46
+ def open?
47
+ !@handle.nil? and !@handle.closed?
48
+ end
49
+
50
+ def write(str)
51
+ raise IOError, "closed stream" unless open?
52
+ begin
53
+ if @timeout.nil? or @timeout == 0
54
+ @handle.write(str)
55
+ else
56
+ len = 0
57
+ start = Time.now
58
+ while Time.now - start < @timeout
59
+ rd, wr, = IO.select(nil, [@handle], nil, @timeout)
60
+ if wr and not wr.empty?
61
+ len += @handle.write_nonblock(str[len..-1])
62
+ break if len >= str.length
63
+ end
64
+ end
65
+ if len < str.length
66
+ raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out writing #{str.length} bytes to #{@desc}")
67
+ else
68
+ len
69
+ end
70
+ end
71
+ rescue TransportException => e
72
+ # pass this on
73
+ raise e
74
+ rescue StandardError => e
75
+ @handle.close
76
+ @handle = nil
77
+ raise TransportException.new(TransportException::NOT_OPEN, e.message)
78
+ end
79
+ end
80
+
81
+ def read(sz)
82
+ raise IOError, "closed stream" unless open?
83
+
84
+ begin
85
+ if @timeout.nil? or @timeout == 0
86
+ data = @handle.readpartial(sz)
87
+ else
88
+ # it's possible to interrupt select for something other than the timeout
89
+ # so we need to ensure we've waited long enough
90
+ start = Time.now
91
+ rd = nil # scoping
92
+ loop do
93
+ rd, = IO.select([@handle], nil, nil, @timeout)
94
+ break if (rd and not rd.empty?) or Time.now - start >= @timeout
95
+ end
96
+ if rd.nil? or rd.empty?
97
+ raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out reading #{sz} bytes from #{@desc}")
98
+ else
99
+ data = @handle.readpartial(sz)
100
+ end
101
+ end
102
+ rescue TransportException => e
103
+ # don't let this get caught by the StandardError handler
104
+ raise e
105
+ rescue StandardError => e
106
+ @handle.close unless @handle.closed?
107
+ @handle = nil
108
+ raise TransportException.new(TransportException::NOT_OPEN, e.message)
109
+ end
110
+ if (data.nil? or data.length == 0)
111
+ raise TransportException.new(TransportException::UNKNOWN, "Socket: Could not read #{sz} bytes from #{@desc}")
112
+ end
113
+ data
114
+ end
115
+
116
+ def close
117
+ @handle.close unless @handle.nil? or @handle.closed?
118
+ @handle = nil
119
+ end
120
+
121
+ def to_io
122
+ @handle
123
+ end
124
+ end
125
+ deprecate_class! :TSocket => Socket
126
+
127
+ class ServerSocket < ServerTransport
128
+ # call-seq: initialize(host = nil, port)
129
+ def initialize(host_or_port, port = nil)
130
+ if port
131
+ @host = host_or_port
132
+ @port = port
133
+ else
134
+ @host = nil
135
+ @port = host_or_port
136
+ end
137
+ @handle = nil
138
+ end
139
+
140
+ attr_reader :handle
141
+
142
+ def listen
143
+ @handle = TCPServer.new(@host, @port)
144
+ end
145
+
146
+ def accept
147
+ unless @handle.nil?
148
+ sock = @handle.accept
149
+ trans = Socket.new
150
+ trans.handle = sock
151
+ trans
152
+ end
153
+ end
154
+
155
+ def close
156
+ @handle.close unless @handle.nil? or @handle.closed?
157
+ @handle = nil
158
+ end
159
+
160
+ def closed?
161
+ @handle.nil? or @handle.closed?
162
+ end
163
+
164
+ alias to_io handle
165
+ end
166
+ deprecate_class! :TServerSocket => ServerSocket
167
+ end
@@ -0,0 +1,2 @@
1
+ require 'thrift/deprecation'
2
+ require 'thrift/transport/httpclient'
@@ -0,0 +1,2 @@
1
+ require 'thrift/deprecation'
2
+ require 'thrift/transport/socket'
@@ -0,0 +1,2 @@
1
+ require 'thrift/deprecation'
2
+ require 'thrift/transport'
@@ -0,0 +1,58 @@
1
+ require 'thrift/transport'
2
+ require 'socket'
3
+
4
+ module Thrift
5
+ class UNIXSocket < Socket
6
+ def initialize(path, timeout=nil)
7
+ @path = path
8
+ @timeout = timeout
9
+ @desc = @path # for read()'s error
10
+ @handle = nil
11
+ end
12
+
13
+ def open
14
+ begin
15
+ @handle = ::UNIXSocket.new(@path)
16
+ rescue StandardError
17
+ raise TransportException.new(TransportException::NOT_OPEN, "Could not open UNIX socket at #{@path}")
18
+ end
19
+ end
20
+ end
21
+
22
+ class UNIXServerSocket < ServerTransport
23
+ def initialize(path)
24
+ @path = path
25
+ @handle = nil
26
+ end
27
+
28
+ attr_accessor :handle
29
+
30
+ def listen
31
+ @handle = ::UNIXServer.new(@path)
32
+ end
33
+
34
+ def accept
35
+ unless @handle.nil?
36
+ sock = @handle.accept
37
+ trans = UNIXSocket.new(nil)
38
+ trans.handle = sock
39
+ trans
40
+ end
41
+ end
42
+
43
+ def close
44
+ if @handle
45
+ @handle.close unless @handle.closed?
46
+ @handle = nil
47
+ # UNIXServer doesn't delete the socket file, so we have to do it ourselves
48
+ File.delete(@path)
49
+ end
50
+ end
51
+
52
+ def closed?
53
+ @handle.nil? or @handle.closed?
54
+ end
55
+
56
+ alias to_io handle
57
+ end
58
+ end