thrift 0.0.751142

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 (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