garru-ruby_scribe_client 0.0.2

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 (40) hide show
  1. data/CHANGELOG +3 -0
  2. data/LICENSE +0 -0
  3. data/Manifest +39 -0
  4. data/README +0 -0
  5. data/Rakefile +8 -0
  6. data/etc/scribe_cat.rb +23 -0
  7. data/lib/ruby_scribe_client/FacebookService.rb +685 -0
  8. data/lib/ruby_scribe_client/fb303_types.rb +16 -0
  9. data/lib/ruby_scribe_client/reflection_limited_types.rb +148 -0
  10. data/lib/ruby_scribe_client/scribe.rb +82 -0
  11. data/lib/ruby_scribe_client/scribe_types.rb +32 -0
  12. data/lib/ruby_scribe_client.rb +33 -0
  13. data/ruby_scribe_client.gemspec +31 -0
  14. data/vendor/thrift/client.rb +44 -0
  15. data/vendor/thrift/deprecation.rb +155 -0
  16. data/vendor/thrift/exceptions.rb +65 -0
  17. data/vendor/thrift/processor.rb +39 -0
  18. data/vendor/thrift/protocol/binaryprotocol.rb +213 -0
  19. data/vendor/thrift/protocol/binaryprotocolaccelerated.rb +19 -0
  20. data/vendor/thrift/protocol/tbinaryprotocol.rb +2 -0
  21. data/vendor/thrift/protocol/tprotocol.rb +2 -0
  22. data/vendor/thrift/protocol.rb +270 -0
  23. data/vendor/thrift/serializer.rb +27 -0
  24. data/vendor/thrift/server/httpserver.rb +44 -0
  25. data/vendor/thrift/server/nonblockingserver.rb +278 -0
  26. data/vendor/thrift/server/thttpserver.rb +2 -0
  27. data/vendor/thrift/server/tserver.rb +2 -0
  28. data/vendor/thrift/server.rb +135 -0
  29. data/vendor/thrift/struct.rb +272 -0
  30. data/vendor/thrift/thrift.rb +14 -0
  31. data/vendor/thrift/transport/httpclient.rb +29 -0
  32. data/vendor/thrift/transport/socket.rb +153 -0
  33. data/vendor/thrift/transport/thttpclient.rb +2 -0
  34. data/vendor/thrift/transport/tsocket.rb +2 -0
  35. data/vendor/thrift/transport/ttransport.rb +2 -0
  36. data/vendor/thrift/transport/unixsocket.rb +58 -0
  37. data/vendor/thrift/transport.rb +319 -0
  38. data/vendor/thrift/types.rb +83 -0
  39. data/vendor/thrift.rb +28 -0
  40. metadata +104 -0
@@ -0,0 +1,278 @@
1
+ require 'thrift/server'
2
+ require 'logger'
3
+ require 'thread'
4
+
5
+ module Thrift
6
+ # this class expects to always use a FramedTransport for reading messages
7
+ class NonblockingServer < Server
8
+ def initialize(processor, serverTransport, transportFactory=nil, protocolFactory=nil, num=20, logger = nil)
9
+ super(processor, serverTransport, transportFactory, protocolFactory)
10
+ @num_threads = num
11
+ if logger.nil?
12
+ @logger = Logger.new(STDERR)
13
+ @logger.level = Logger::WARN
14
+ else
15
+ @logger = logger
16
+ end
17
+ @shutdown_semaphore = Mutex.new
18
+ @transport_semaphore = Mutex.new
19
+ end
20
+
21
+ def serve
22
+ @logger.info "Starting #{self}"
23
+ @serverTransport.listen
24
+ @io_manager = start_io_manager
25
+
26
+ begin
27
+ loop do
28
+ break if @serverTransport.closed?
29
+ rd, = select([@serverTransport], nil, nil, 0.1)
30
+ next if rd.nil?
31
+ socket = @serverTransport.accept
32
+ @logger.debug "Accepted socket: #{socket.inspect}"
33
+ @io_manager.add_connection socket
34
+ end
35
+ rescue IOError => e
36
+ end
37
+ # we must be shutting down
38
+ @logger.info "#{self} is shutting down, goodbye"
39
+ ensure
40
+ @transport_semaphore.synchronize do
41
+ @serverTransport.close
42
+ end
43
+ @io_manager.ensure_closed unless @io_manager.nil?
44
+ end
45
+
46
+ def shutdown(timeout = 0, block = true)
47
+ @shutdown_semaphore.synchronize do
48
+ return if @is_shutdown
49
+ @is_shutdown = true
50
+ end
51
+ # nonblocking is intended for calling from within a Handler
52
+ # but we can't change the order of operations here, so lets thread
53
+ shutdown_proc = lambda do
54
+ @io_manager.shutdown(timeout)
55
+ @transport_semaphore.synchronize do
56
+ @serverTransport.close # this will break the accept loop
57
+ end
58
+ end
59
+ if block
60
+ shutdown_proc.call
61
+ else
62
+ Thread.new &shutdown_proc
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def start_io_manager
69
+ iom = IOManager.new(@processor, @serverTransport, @transportFactory, @protocolFactory, @num_threads, @logger)
70
+ iom.spawn
71
+ iom
72
+ end
73
+
74
+ class IOManager # :nodoc:
75
+ DEFAULT_BUFFER = 2**20
76
+
77
+ def initialize(processor, serverTransport, transportFactory, protocolFactory, num, logger)
78
+ @processor = processor
79
+ @serverTransport = serverTransport
80
+ @transportFactory = transportFactory
81
+ @protocolFactory = protocolFactory
82
+ @num_threads = num
83
+ @logger = logger
84
+ @connections = []
85
+ @buffers = Hash.new { |h,k| h[k] = '' }
86
+ @signal_queue = Queue.new
87
+ @signal_pipes = IO.pipe
88
+ @signal_pipes[1].sync = true
89
+ @worker_queue = Queue.new
90
+ @shutdown_queue = Queue.new
91
+ end
92
+
93
+ def add_connection(socket)
94
+ signal [:connection, socket]
95
+ end
96
+
97
+ def spawn
98
+ @iom_thread = Thread.new do
99
+ @logger.debug "Starting #{self}"
100
+ run
101
+ end
102
+ end
103
+
104
+ def shutdown(timeout = 0)
105
+ @logger.debug "#{self} is shutting down workers"
106
+ @worker_queue.clear
107
+ @num_threads.times { @worker_queue.push [:shutdown] }
108
+ signal [:shutdown, timeout]
109
+ @shutdown_queue.pop
110
+ @signal_pipes[0].close
111
+ @signal_pipes[1].close
112
+ @logger.debug "#{self} is shutting down, goodbye"
113
+ end
114
+
115
+ def ensure_closed
116
+ kill_worker_threads if @worker_threads
117
+ @iom_thread.kill
118
+ end
119
+
120
+ private
121
+
122
+ def run
123
+ spin_worker_threads
124
+
125
+ loop do
126
+ rd, = select([@signal_pipes[0], *@connections])
127
+ if rd.delete @signal_pipes[0]
128
+ break if read_signals == :shutdown
129
+ end
130
+ rd.each do |fd|
131
+ if fd.handle.eof?
132
+ remove_connection fd
133
+ else
134
+ read_connection fd
135
+ end
136
+ end
137
+ end
138
+ join_worker_threads(@shutdown_timeout)
139
+ ensure
140
+ @shutdown_queue.push :shutdown
141
+ end
142
+
143
+ def read_connection(fd)
144
+ @buffers[fd] << fd.read(DEFAULT_BUFFER)
145
+ frame = slice_frame!(@buffers[fd])
146
+ if frame
147
+ @logger.debug "#{self} is processing a frame"
148
+ @worker_queue.push [:frame, fd, frame]
149
+ end
150
+ end
151
+
152
+ def spin_worker_threads
153
+ @logger.debug "#{self} is spinning up worker threads"
154
+ @worker_threads = []
155
+ @num_threads.times do
156
+ @worker_threads << spin_thread
157
+ end
158
+ end
159
+
160
+ def spin_thread
161
+ Worker.new(@processor, @transportFactory, @protocolFactory, @logger, @worker_queue).spawn
162
+ end
163
+
164
+ def signal(msg)
165
+ @signal_queue << msg
166
+ @signal_pipes[1].write " "
167
+ end
168
+
169
+ def read_signals
170
+ # clear the signal pipe
171
+ # note that since read_nonblock is broken in jruby,
172
+ # we can only read up to a set number of signals at once
173
+ sigstr = @signal_pipes[0].readpartial(1024)
174
+ # now read the signals
175
+ begin
176
+ sigstr.length.times do
177
+ signal, obj = @signal_queue.pop(true)
178
+ case signal
179
+ when :connection
180
+ @connections << obj
181
+ when :shutdown
182
+ @shutdown_timeout = obj
183
+ return :shutdown
184
+ end
185
+ end
186
+ rescue ThreadError
187
+ # out of signals
188
+ # note that in a perfect world this would never happen, since we're
189
+ # only reading the number of signals pushed on the pipe, but given the lack
190
+ # of locks, in theory we could clear the pipe/queue while a new signal is being
191
+ # placed on the pipe, at which point our next read_signals would hit this error
192
+ end
193
+ end
194
+
195
+ def remove_connection(fd)
196
+ # don't explicitly close it, a thread may still be writing to it
197
+ @connections.delete fd
198
+ @buffers.delete fd
199
+ end
200
+
201
+ def join_worker_threads(shutdown_timeout)
202
+ start = Time.now
203
+ @worker_threads.each do |t|
204
+ if shutdown_timeout > 0
205
+ timeout = (start + shutdown_timeout) - Time.now
206
+ break if timeout <= 0
207
+ t.join(timeout)
208
+ else
209
+ t.join
210
+ end
211
+ end
212
+ kill_worker_threads
213
+ end
214
+
215
+ def kill_worker_threads
216
+ @worker_threads.each do |t|
217
+ t.kill if t.status
218
+ end
219
+ @worker_threads.clear
220
+ end
221
+
222
+ def slice_frame!(buf)
223
+ if buf.length >= 4
224
+ size = buf.unpack('N').first
225
+ if buf.length >= size + 4
226
+ buf.slice!(0, size + 4)
227
+ else
228
+ nil
229
+ end
230
+ else
231
+ nil
232
+ end
233
+ end
234
+
235
+ class Worker # :nodoc:
236
+ def initialize(processor, transportFactory, protocolFactory, logger, queue)
237
+ @processor = processor
238
+ @transportFactory = transportFactory
239
+ @protocolFactory = protocolFactory
240
+ @logger = logger
241
+ @queue = queue
242
+ end
243
+
244
+ def spawn
245
+ Thread.new do
246
+ @logger.debug "#{self} is spawning"
247
+ run
248
+ end
249
+ end
250
+
251
+ private
252
+
253
+ def run
254
+ loop do
255
+ cmd, *args = @queue.pop
256
+ case cmd
257
+ when :shutdown
258
+ @logger.debug "#{self} is shutting down, goodbye"
259
+ break
260
+ when :frame
261
+ fd, frame = args
262
+ begin
263
+ otrans = @transportFactory.get_transport(fd)
264
+ oprot = @protocolFactory.get_protocol(otrans)
265
+ membuf = MemoryBuffer.new(frame)
266
+ itrans = @transportFactory.get_transport(membuf)
267
+ iprot = @protocolFactory.get_protocol(itrans)
268
+ @processor.process(iprot, oprot)
269
+ rescue => e
270
+ @logger.error "#{Thread.current.inspect} raised error: #{e.inspect}\n#{e.backtrace.join("\n")}"
271
+ end
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
277
+ end
278
+ end
@@ -0,0 +1,2 @@
1
+ require 'thrift/deprecation'
2
+ require 'thrift/server/httpserver'
@@ -0,0 +1,2 @@
1
+ require 'thrift/deprecation'
2
+ require 'thrift/server'
@@ -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