*/
std::string rb_autogen_comment();
- std::string rb_imports();
std::string render_includes();
std::string declare_field(t_field* tfield);
std::string type_name(t_type* ttype);
// Print header
f_types_ <<
rb_autogen_comment() << endl <<
- rb_imports() << endl <<
render_includes() << endl;
begin_namespace(f_types_, ruby_modules(program_));
f_consts_ <<
rb_autogen_comment() << endl <<
- rb_imports() << endl <<
"require File.dirname(__FILE__) + '/" << program_name_ << "_types'" << endl <<
endl;
begin_namespace(f_consts_, ruby_modules(program_));
"#\n";
}
-/**
- * Prints standard thrift imports
- */
-string t_rb_generator::rb_imports() {
- return
- string("require 'thrift/protocol'");
-}
-
/**
* Closes the type files
*/
f_service_ <<
rb_autogen_comment() << endl <<
- "require 'thrift'" << endl <<
- rb_imports() << endl;
+ "require 'thrift'" << endl;
if (tservice->get_extends() != NULL) {
f_service_ <<
benchmark/benchmark.rb
benchmark/Benchmark.thrift
benchmark/client.rb
-benchmark/gen-rb/Benchmark_constants.rb
-benchmark/gen-rb/Benchmark_types.rb
-benchmark/gen-rb/BenchmarkService.rb
benchmark/server.rb
benchmark/thin_server.rb
CHANGELOG
lib/thrift/core_ext.rb
lib/thrift/exceptions.rb
lib/thrift/processor.rb
-lib/thrift/protocol/binaryprotocol.rb
-lib/thrift/protocol/binaryprotocolaccelerated.rb
+lib/thrift/protocol/binary_protocol_accelerated.rb
+lib/thrift/protocol/binary_protocol.rb
lib/thrift/protocol/compact_protocol.rb
lib/thrift/protocol.rb
-lib/thrift/serializer.rb
-lib/thrift/server/httpserver.rb
-lib/thrift/server/nonblockingserver.rb
+lib/thrift/serializer/serializer.rb
+lib/thrift/serializer/deserializer.rb
+lib/thrift/server/mongrel_http_server.rb
+lib/thrift/server/nonblocking_server.rb
lib/thrift/server.rb
lib/thrift/struct.rb
lib/thrift/thrift_native.rb
-lib/thrift/transport/httpclient.rb
-lib/thrift/transport/socket.rb
-lib/thrift/transport/unixsocket.rb
+lib/thrift/transport/buffered_transport.rb
+lib/thrift/transport/framed_transport.rb
+lib/thrift/transport/http_client_transport.rb
+lib/thrift/transport/io_stream_transport.rb
+lib/thrift/transport/memory_buffer_transport.rb
lib/thrift/transport.rb
lib/thrift/types.rb
lib/thrift.rb
Manifest
+Rakefile
README
-spec/binaryprotocol_spec.rb
-spec/binaryprotocol_spec_shared.rb
-spec/binaryprotocolaccelerated_spec.rb
+script/proto_benchmark.rb
+script/read_struct.rb
+script/write_struct.rb
+setup.rb
+spec/binary_protocol_accelerated_spec.rb
+spec/binary_protocol_spec.rb
+spec/binary_protocol_spec_shared.rb
spec/client_spec.rb
spec/compact_protocol_spec.rb
spec/exception_spec.rb
-spec/httpclient_spec.rb
-spec/httpserver_spec.rb
-spec/nonblockingserver_spec.rb
+spec/http_client_spec.rb
+spec/mongrel_http_server_spec.rb
+spec/nonblocking_server_spec.rb
spec/processor_spec.rb
spec/protocol_spec.rb
spec/serializer_spec.rb
+spec/server_socket_spec.rb
spec/server_spec.rb
spec/socket_spec.rb
spec/socket_spec_shared.rb
spec/ThriftSpec.thrift
spec/transport_spec.rb
spec/types_spec.rb
-spec/unixsocket_spec.rb
+spec/unix_socket_spec.rb
require 'rubygems'
$:.unshift File.dirname(__FILE__) + '/../lib'
require 'thrift'
-require 'thrift/server/nonblockingserver'
-require 'thrift/transport/unixsocket'
require 'stringio'
HOST = '127.0.0.1'
$:.unshift File.dirname(__FILE__) + '/../lib'
require 'thrift'
-require 'thrift/server/nonblockingserver'
$:.unshift File.dirname(__FILE__) + "/gen-rb"
require 'BenchmarkService'
$:.unshift File.dirname(__FILE__) + '/../lib'
require 'thrift'
-require 'thrift/server/nonblockingserver'
$:.unshift File.dirname(__FILE__) + "/gen-rb"
require 'BenchmarkService'
handler = BenchmarkHandler.new
processor = ThriftBenchmark::BenchmarkService::Processor.new(handler)
transport = ServerSocket.new(host, port)
- transportFactory = FramedTransportFactory.new
- args = [processor, transport, transportFactory, nil, 20]
+ transport_factory = FramedTransportFactory.new
+ args = [processor, transport, transport_factory, nil, 20]
if serverClass == NonblockingServer
logger = Logger.new(STDERR)
logger.level = Logger::WARN
$:.unshift File.dirname(__FILE__) + '/../lib'
require 'thrift'
-require 'thrift/server/nonblockingserver'
$:.unshift File.dirname(__FILE__) + "/gen-rb"
require 'BenchmarkService'
HOST = 'localhost'
handler = BenchmarkHandler.new
processor = ThriftBenchmark::BenchmarkService::Processor.new(handler)
transport = Thrift::ServerSocket.new(HOST, PORT)
-transportFactory = Thrift::FramedTransportFactory.new
+transport_factory = Thrift::FramedTransportFactory.new
logger = Logger.new(STDERR)
logger.level = Logger::WARN
-Thrift::NonblockingServer.new(processor, transport, transportFactory, nil, 20, logger).serve
+Thrift::NonblockingServer.new(processor, transport, transport_factory, nil, 20, logger).serve
}
void Init_memory_buffer() {
- VALUE thrift_memory_buffer_class = rb_const_get(thrift_module, rb_intern("MemoryBuffer"));
+ VALUE thrift_memory_buffer_class = rb_const_get(thrift_module, rb_intern("MemoryBufferTransport"));
rb_define_method(thrift_memory_buffer_class, "write", rb_thrift_memory_buffer_write, 1);
rb_define_method(thrift_memory_buffer_class, "read", rb_thrift_memory_buffer_read, 1);
}
void Init_protocol() {
- VALUE c_protocol = rb_const_get(thrift_module, rb_intern("Protocol"));
+ VALUE c_protocol = rb_const_get(thrift_module, rb_intern("BaseProtocol"));
rb_define_method(c_protocol, "skip", rb_thrift_protocol_skip, 1);
rb_define_method(c_protocol, "write_message_end", rb_thrift_write_message_end, 0);
require 'thrift/processor'
require 'thrift/client'
require 'thrift/struct'
-require 'thrift/protocol'
-require 'thrift/protocol/binaryprotocol'
+
+# serializer
+require 'thrift/serializer/serializer'
+require 'thrift/serializer/deserializer'
+
+# protocol
+require 'thrift/protocol/base_protocol'
+require 'thrift/protocol/binary_protocol'
+require 'thrift/protocol/binary_protocol_accelerated'
require 'thrift/protocol/compact_protocol'
-require 'thrift/transport'
+
+# transport
+require 'thrift/transport/base_transport'
+require 'thrift/transport/base_server_transport'
require 'thrift/transport/socket'
-require 'thrift/server'
-require "thrift/thrift_native"
\ No newline at end of file
+require 'thrift/transport/server_socket'
+require 'thrift/transport/unix_socket'
+require 'thrift/transport/unix_server_socket'
+require 'thrift/transport/buffered_transport'
+require 'thrift/transport/framed_transport'
+require 'thrift/transport/http_client_transport'
+require 'thrift/transport/io_stream_transport'
+require 'thrift/transport/memory_buffer_transport'
+
+# server
+require 'thrift/server/base_server'
+require 'thrift/server/nonblocking_server'
+require 'thrift/server/simple_server'
+require 'thrift/server/threaded_server'
+require 'thrift/server/thread_pool_server'
+
+require 'thrift/thrift_native'
\ No newline at end of file
super(message)
@type = type
end
-
end
- class Protocol
+ class BaseProtocol
attr_reader :trans
read_list_end
end
end
-
end
- class ProtocolFactory
+ class BaseProtocolFactory
def get_protocol(trans)
raise NotImplementedError
end
end
-end
+end
\ No newline at end of file
# under the License.
#
-require 'thrift/protocol'
-
module Thrift
- class BinaryProtocol < Protocol
+ class BinaryProtocol < BaseProtocol
VERSION_MASK = 0xffff0000
VERSION_1 = 0x80010000
TYPE_MASK = 0x000000ff
end
- class BinaryProtocolFactory < ProtocolFactory
+ class BinaryProtocolFactory < BaseProtocolFactory
def get_protocol(trans)
return Thrift::BinaryProtocol.new(trans)
end
# under the License.
#
-require 'thrift/protocol/binaryprotocol'
-require 'thrift_native'
-
=begin
-The only change required for a transport to support TBinaryProtocolAccelerated is to implement 2 methods:
+The only change required for a transport to support BinaryProtocolAccelerated is to implement 2 methods:
* borrow(size), which takes an optional argument and returns atleast _size_ bytes from the transport,
or the default buffer size if no argument is given
* consume!(size), which removes size bytes from the front of the buffer
-See TMemoryBuffer and TBufferedTransport for examples.
+See MemoryBuffer and BufferedTransport for examples.
=end
module Thrift
- class BinaryProtocolAcceleratedFactory < ProtocolFactory
+ class BinaryProtocolAcceleratedFactory < BaseProtocolFactory
def get_protocol(trans)
BinaryProtocolAccelerated.new(trans)
end
# under the License.
#
-require 'thrift/protocol'
-
module Thrift
- class CompactProtocol < Protocol
+ class CompactProtocol < BaseProtocol
PROTOCOL_ID = [0x82].pack('c').unpack('c').first
VERSION = 1
end
end
- class CompactProtocolFactory < ProtocolFactory
+ class CompactProtocolFactory < BaseProtocolFactory
def get_protocol(trans)
CompactProtocol.new(trans)
end
--- /dev/null
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Thrift
+ class Deserializer
+ def initialize(protocol_factory = BinaryProtocolFactory.new)
+ @transport = MemoryBufferTransport.new
+ @protocol = protocol_factory.get_protocol(@transport)
+ end
+
+ def deserialize(base, buffer)
+ @transport.reset_buffer(buffer)
+ base.read(@protocol)
+ base
+ end
+ end
+end
\ No newline at end of file
module Thrift
class Serializer
- def initialize(protocolFactory = BinaryProtocolFactory.new)
- @transport = MemoryBuffer.new
- @protocol = protocolFactory.get_protocol(@transport)
+ def initialize(protocol_factory = BinaryProtocolFactory.new)
+ @transport = MemoryBufferTransport.new
+ @protocol = protocol_factory.get_protocol(@transport)
end
def serialize(base)
@transport.read(@transport.available)
end
end
-
- class Deserializer
- def initialize(protocolFactory = BinaryProtocolFactory.new)
- @transport = MemoryBuffer.new
- @protocol = protocolFactory.get_protocol(@transport)
- end
-
- def deserialize(base, buffer)
- @transport.reset_buffer(buffer)
- base.read(@protocol)
- base
- end
- end
end
+
+++ /dev/null
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-require 'thrift/protocol'
-require 'thrift/protocol/binaryprotocol'
-require 'thrift/transport'
-
-module Thrift
- class Server
- def initialize(processor, serverTransport, transportFactory=nil, protocolFactory=nil)
- @processor = processor
- @serverTransport = serverTransport
- @transportFactory = transportFactory ? transportFactory : Thrift::TransportFactory.new
- @protocolFactory = protocolFactory ? protocolFactory : Thrift::BinaryProtocolFactory.new
- end
-
- def serve; nil; end
- end
-
- class SimpleServer < Server
- def serve
- begin
- @serverTransport.listen
- loop do
- client = @serverTransport.accept
- trans = @transportFactory.get_transport(client)
- prot = @protocolFactory.get_protocol(trans)
- begin
- loop do
- @processor.process(prot, prot)
- end
- rescue Thrift::TransportException, Thrift::ProtocolException
- ensure
- trans.close
- end
- end
- ensure
- @serverTransport.close
- end
- end
- end
-end
-
-# do *not* use fastthread
-# it has a bug that triggers on NonblockingServer
-require 'thread'
-
-module Thrift
- class ThreadedServer < Server
- def serve
- begin
- @serverTransport.listen
- loop do
- client = @serverTransport.accept
- trans = @transportFactory.get_transport(client)
- prot = @protocolFactory.get_protocol(trans)
- Thread.new(prot, trans) do |p, t|
- begin
- loop do
- @processor.process(p, p)
- end
- rescue Thrift::TransportException, Thrift::ProtocolException
- ensure
- t.close
- end
- end
- end
- ensure
- @serverTransport.close
- end
- end
- end
-
- class ThreadPoolServer < Server
- def initialize(processor, serverTransport, transportFactory=nil, protocolFactory=nil, num=20)
- super(processor, serverTransport, transportFactory, protocolFactory)
- @thread_q = SizedQueue.new(num)
- @exception_q = Queue.new
- @running = false
- end
-
- ## exceptions that happen in worker threads will be relayed here and
- ## must be caught. 'retry' can be used to continue. (threads will
- ## continue to run while the exception is being handled.)
- def rescuable_serve
- Thread.new { serve } unless @running
- @running = true
- raise @exception_q.pop
- end
-
- ## exceptions that happen in worker threads simply cause that thread
- ## to die and another to be spawned in its place.
- def serve
- @serverTransport.listen
-
- begin
- loop do
- @thread_q.push(:token)
- Thread.new do
- begin
- loop do
- client = @serverTransport.accept
- trans = @transportFactory.get_transport(client)
- prot = @protocolFactory.get_protocol(trans)
- begin
- loop do
- @processor.process(prot, prot)
- end
- rescue Thrift::TransportException, Thrift::ProtocolException => e
- ensure
- trans.close
- end
- end
- rescue => e
- @exception_q.push(e)
- ensure
- @thread_q.pop # thread died!
- end
- end
- end
- ensure
- @serverTransport.close
- end
- end
- end
-end
--- /dev/null
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Thrift
+ class BaseServer
+ def initialize(processor, server_transport, transport_factory=nil, protocol_factory=nil)
+ @processor = processor
+ @server_transport = server_transport
+ @transport_factory = transport_factory ? transport_factory : Thrift::BaseTransportFactory.new
+ @protocol_factory = protocol_factory ? protocol_factory : Thrift::BinaryProtocolFactory.new
+ end
+
+ def serve; nil; end
+ end
+end
\ No newline at end of file
# under the License.
#
-require 'thrift/protocol'
-require 'thrift/protocol/binaryprotocol'
-require 'thrift/transport'
-
require 'mongrel'
## Sticks a service on a URL, using mongrel to do the HTTP work
module Thrift
- class SimpleMongrelHTTPServer
+ class MongrelHTTPServer < BaseServer
class Handler < Mongrel::HttpHandler
def initialize(processor, protocol_factory)
@processor = processor
# under the License.
#
-require 'thrift/server'
require 'logger'
require 'thread'
module Thrift
# this class expects to always use a FramedTransport for reading messages
- class NonblockingServer < Server
- def initialize(processor, serverTransport, transportFactory=nil, protocolFactory=nil, num=20, logger = nil)
- super(processor, serverTransport, transportFactory, protocolFactory)
+ class NonblockingServer < BaseServer
+ def initialize(processor, server_transport, transport_factory=nil, protocol_factory=nil, num=20, logger=nil)
+ super(processor, server_transport, transport_factory, protocol_factory)
@num_threads = num
if logger.nil?
@logger = Logger.new(STDERR)
def serve
@logger.info "Starting #{self}"
- @serverTransport.listen
+ @server_transport.listen
@io_manager = start_io_manager
begin
loop do
- break if @serverTransport.closed?
- rd, = select([@serverTransport], nil, nil, 0.1)
+ break if @server_transport.closed?
+ rd, = select([@server_transport], nil, nil, 0.1)
next if rd.nil?
- socket = @serverTransport.accept
+ socket = @server_transport.accept
@logger.debug "Accepted socket: #{socket.inspect}"
@io_manager.add_connection socket
end
@logger.info "#{self} is shutting down, goodbye"
ensure
@transport_semaphore.synchronize do
- @serverTransport.close
+ @server_transport.close
end
@io_manager.ensure_closed unless @io_manager.nil?
end
shutdown_proc = lambda do
@io_manager.shutdown(timeout)
@transport_semaphore.synchronize do
- @serverTransport.close # this will break the accept loop
+ @server_transport.close # this will break the accept loop
end
end
if block
private
def start_io_manager
- iom = IOManager.new(@processor, @serverTransport, @transportFactory, @protocolFactory, @num_threads, @logger)
+ iom = IOManager.new(@processor, @server_transport, @transport_factory, @protocol_factory, @num_threads, @logger)
iom.spawn
iom
end
class IOManager # :nodoc:
DEFAULT_BUFFER = 2**20
- def initialize(processor, serverTransport, transportFactory, protocolFactory, num, logger)
+ def initialize(processor, server_transport, transport_factory, protocol_factory, num, logger)
@processor = processor
- @serverTransport = serverTransport
- @transportFactory = transportFactory
- @protocolFactory = protocolFactory
+ @server_transport = server_transport
+ @transport_factory = transport_factory
+ @protocol_factory = protocol_factory
@num_threads = num
@logger = logger
@connections = []
end
def spin_thread
- Worker.new(@processor, @transportFactory, @protocolFactory, @logger, @worker_queue).spawn
+ Worker.new(@processor, @transport_factory, @protocol_factory, @logger, @worker_queue).spawn
end
def signal(msg)
end
class Worker # :nodoc:
- def initialize(processor, transportFactory, protocolFactory, logger, queue)
+ def initialize(processor, transport_factory, protocol_factory, logger, queue)
@processor = processor
- @transportFactory = transportFactory
- @protocolFactory = protocolFactory
+ @transport_factory = transport_factory
+ @protocol_factory = protocol_factory
@logger = logger
@queue = queue
end
when :frame
fd, frame = args
begin
- otrans = @transportFactory.get_transport(fd)
- oprot = @protocolFactory.get_protocol(otrans)
- membuf = MemoryBuffer.new(frame)
- itrans = @transportFactory.get_transport(membuf)
- iprot = @protocolFactory.get_protocol(itrans)
+ otrans = @transport_factory.get_transport(fd)
+ oprot = @protocol_factory.get_protocol(otrans)
+ membuf = MemoryBufferTransport.new(frame)
+ itrans = @transport_factory.get_transport(membuf)
+ iprot = @protocol_factory.get_protocol(itrans)
@processor.process(iprot, oprot)
rescue => e
@logger.error "#{Thread.current.inspect} raised error: #{e.inspect}\n#{e.backtrace.join("\n")}"
--- /dev/null
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Thrift
+ class SimpleServer < BaseServer
+ def serve
+ begin
+ @server_transport.listen
+ loop do
+ client = @server_transport.accept
+ trans = @transport_factory.get_transport(client)
+ prot = @protocol_factory.get_protocol(trans)
+ begin
+ loop do
+ @processor.process(prot, prot)
+ end
+ rescue Thrift::TransportException, Thrift::ProtocolException
+ ensure
+ trans.close
+ end
+ end
+ ensure
+ @server_transport.close
+ end
+ end
+ end
+end
\ No newline at end of file
--- /dev/null
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require 'thread'
+
+module Thrift
+ class ThreadPoolServer < BaseServer
+ def initialize(processor, server_transport, transport_factory=nil, protocol_factory=nil, num=20)
+ super(processor, server_transport, transport_factory, protocol_factory)
+ @thread_q = SizedQueue.new(num)
+ @exception_q = Queue.new
+ @running = false
+ end
+
+ ## exceptions that happen in worker threads will be relayed here and
+ ## must be caught. 'retry' can be used to continue. (threads will
+ ## continue to run while the exception is being handled.)
+ def rescuable_serve
+ Thread.new { serve } unless @running
+ @running = true
+ raise @exception_q.pop
+ end
+
+ ## exceptions that happen in worker threads simply cause that thread
+ ## to die and another to be spawned in its place.
+ def serve
+ @server_transport.listen
+
+ begin
+ loop do
+ @thread_q.push(:token)
+ Thread.new do
+ begin
+ loop do
+ client = @server_transport.accept
+ trans = @transport_factory.get_transport(client)
+ prot = @protocol_factory.get_protocol(trans)
+ begin
+ loop do
+ @processor.process(prot, prot)
+ end
+ rescue Thrift::TransportException, Thrift::ProtocolException => e
+ ensure
+ trans.close
+ end
+ end
+ rescue => e
+ @exception_q.push(e)
+ ensure
+ @thread_q.pop # thread died!
+ end
+ end
+ end
+ ensure
+ @server_transport.close
+ end
+ end
+ end
+end
\ No newline at end of file
--- /dev/null
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require 'thread'
+
+module Thrift
+ class ThreadedServer < BaseServer
+ def serve
+ begin
+ @server_transport.listen
+ loop do
+ client = @server_transport.accept
+ trans = @transport_factory.get_transport(client)
+ prot = @protocol_factory.get_protocol(trans)
+ Thread.new(prot, trans) do |p, t|
+ begin
+ loop do
+ @processor.process(p, p)
+ end
+ rescue Thrift::TransportException, Thrift::ProtocolException
+ ensure
+ t.close
+ end
+ end
+ end
+ ensure
+ @server_transport.close
+ end
+ end
+ end
+end
\ No newline at end of file
# under the License.
#
-require 'thrift/types'
require 'set'
module Thrift
+++ /dev/null
-# encoding: ascii-8bit
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-module Thrift
- class TransportException < Exception
- UNKNOWN = 0
- NOT_OPEN = 1
- ALREADY_OPEN = 2
- TIMED_OUT = 3
- END_OF_FILE = 4
-
- attr_reader :type
-
- def initialize(type=UNKNOWN, message=nil)
- super(message)
- @type = type
- end
- end
-
- class Transport
- def open?; end
-
- def open; end
-
- def close; end
-
- def read(sz)
- raise NotImplementedError
- end
-
- def read_all(size)
- buf = ''
-
- while (buf.length < size)
- chunk = read(size - buf.length)
- buf << chunk
- end
-
- buf
- end
-
- def write(buf); end
- alias_method :<<, :write
-
- def flush; end
- end
-
- class ServerTransport
- def listen
- raise NotImplementedError
- end
-
- def accept
- raise NotImplementedError
- end
-
- def close; nil; end
-
- def closed?
- raise NotImplementedError
- end
- end
-
- class TransportFactory
- def get_transport(trans)
- return trans
- end
- end
-
- class BufferedTransport < Transport
- DEFAULT_BUFFER = 4096
-
- def initialize(transport)
- @transport = transport
- @wbuf = ''
- @rbuf = ''
- @index = 0
- end
-
- def open?
- return @transport.open?
- end
-
- def open
- @transport.open
- end
-
- def close
- flush
- @transport.close
- end
-
- def read(sz)
- @index += sz
- ret = @rbuf.slice(@index - sz, sz) || ''
-
- if ret.length == 0
- @rbuf = @transport.read([sz, DEFAULT_BUFFER].max)
- @index = sz
- ret = @rbuf.slice(0, sz) || ''
- end
-
- ret
- end
-
- def write(buf)
- @wbuf << buf
- end
-
- def flush
- if @wbuf != ''
- @transport.write(@wbuf)
- @wbuf = ''
- end
-
- @transport.flush
- end
- end
-
- class BufferedTransportFactory < TransportFactory
- def get_transport(transport)
- return BufferedTransport.new(transport)
- end
- end
-
- class FramedTransport < Transport
- def initialize(transport, read=true, write=true)
- @transport = transport
- @rbuf = ''
- @wbuf = ''
- @read = read
- @write = write
- @index = 0
- end
-
- def open?
- @transport.open?
- end
-
- def open
- @transport.open
- end
-
- def close
- @transport.close
- end
-
- def read(sz)
- return @transport.read(sz) unless @read
-
- return '' if sz <= 0
-
- read_frame if @index >= @rbuf.length
-
- @index += sz
- @rbuf.slice(@index - sz, sz) || ''
- end
-
- def write(buf,sz=nil)
- return @transport.write(buf) unless @write
-
- @wbuf << (sz ? buf[0...sz] : buf)
- end
-
- #
- # Writes the output buffer to the stream in the format of a 4-byte length
- # followed by the actual data.
- #
- def flush
- return @transport.flush unless @write
-
- out = [@wbuf.length].pack('N')
- out << @wbuf
- @transport.write(out)
- @transport.flush
- @wbuf = ''
- end
-
- private
-
- def read_frame
- sz = @transport.read_all(4).unpack('N').first
-
- @index = 0
- @rbuf = @transport.read_all(sz)
- end
- end
-
- class FramedTransportFactory < TransportFactory
- def get_transport(transport)
- return FramedTransport.new(transport)
- end
- end
-
- class MemoryBuffer < Transport
- GARBAGE_BUFFER_SIZE = 4*(2**10) # 4kB
-
- # If you pass a string to this, you should #dup that string
- # unless you want it to be modified by #read and #write
- #--
- # this behavior is no longer required. If you wish to change it
- # go ahead, just make sure the specs pass
- def initialize(buffer = nil)
- @buf = buffer || ''
- @index = 0
- end
-
- def open?
- return true
- end
-
- def open
- end
-
- def close
- end
-
- def peek
- @index < @buf.size
- end
-
- # this method does not use the passed object directly but copies it
- def reset_buffer(new_buf = '')
- @buf.replace new_buf
- @index = 0
- end
-
- def available
- @buf.length - @index
- end
-
- def read(len)
- data = @buf.slice(@index, len)
- @index += len
- @index = @buf.size if @index > @buf.size
- if @index >= GARBAGE_BUFFER_SIZE
- @buf = @buf.slice(@index..-1)
- @index = 0
- end
- data
- end
-
- def write(wbuf)
- @buf << wbuf
- end
-
- def flush
- end
-
- def inspect_buffer
- out = []
- for idx in 0...(@buf.size)
- # if idx != 0
- # out << " "
- # end
-
- if idx == @index
- out << ">"
- end
-
- out << @buf[idx].to_s(16)
- end
- out.join(" ")
- end
- end
-
- ## Very very simple implementation of wrapping two objects, one with a #read
- ## method and one with a #write method, into a transport for thrift.
- ##
- ## Assumes both objects are open, remain open, don't require flushing, etc.
- class IOStreamTransport < Transport
- def initialize(input, output)
- @input = input
- @output = output
- end
-
- def open?; not @input.closed? or not @output.closed? end
- def read(sz); @input.read(sz) end
- def write(buf); @output.write(buf) end
- def close; @input.close; @output.close end
- def to_io; @input end # we're assuming this is used in a IO.select for reading
- end
-end
--- /dev/null
+# encoding: ascii-8bit
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Thrift
+ class BaseServerTransport
+ def listen
+ raise NotImplementedError
+ end
+
+ def accept
+ raise NotImplementedError
+ end
+
+ def close; nil; end
+
+ def closed?
+ raise NotImplementedError
+ end
+ end
+end
\ No newline at end of file
--- /dev/null
+# encoding: ascii-8bit
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Thrift
+ class TransportException < Exception
+ UNKNOWN = 0
+ NOT_OPEN = 1
+ ALREADY_OPEN = 2
+ TIMED_OUT = 3
+ END_OF_FILE = 4
+
+ attr_reader :type
+
+ def initialize(type=UNKNOWN, message=nil)
+ super(message)
+ @type = type
+ end
+ end
+
+ class BaseTransport
+ def open?; end
+
+ def open; end
+
+ def close; end
+
+ def read(sz)
+ raise NotImplementedError
+ end
+
+ def read_all(size)
+ buf = ''
+
+ while (buf.length < size)
+ chunk = read(size - buf.length)
+ buf << chunk
+ end
+
+ buf
+ end
+
+ def write(buf); end
+ alias_method :<<, :write
+
+ def flush; end
+ end
+
+ class BaseTransportFactory
+ def get_transport(trans)
+ return trans
+ end
+ end
+end
\ No newline at end of file
--- /dev/null
+# encoding: ascii-8bit
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Thrift
+ class BufferedTransport < BaseTransport
+ DEFAULT_BUFFER = 4096
+
+ def initialize(transport)
+ @transport = transport
+ @wbuf = ''
+ @rbuf = ''
+ @index = 0
+ end
+
+ def open?
+ return @transport.open?
+ end
+
+ def open
+ @transport.open
+ end
+
+ def close
+ flush
+ @transport.close
+ end
+
+ def read(sz)
+ @index += sz
+ ret = @rbuf.slice(@index - sz, sz) || ''
+
+ if ret.length == 0
+ @rbuf = @transport.read([sz, DEFAULT_BUFFER].max)
+ @index = sz
+ ret = @rbuf.slice(0, sz) || ''
+ end
+
+ ret
+ end
+
+ def write(buf)
+ @wbuf << buf
+ end
+
+ def flush
+ if @wbuf != ''
+ @transport.write(@wbuf)
+ @wbuf = ''
+ end
+
+ @transport.flush
+ end
+ end
+
+ class BufferedTransportFactory < BaseTransportFactory
+ def get_transport(transport)
+ return BufferedTransport.new(transport)
+ end
+ end
+end
\ No newline at end of file
--- /dev/null
+# encoding: ascii-8bit
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Thrift
+ class FramedTransport < BaseTransport
+ def initialize(transport, read=true, write=true)
+ @transport = transport
+ @rbuf = ''
+ @wbuf = ''
+ @read = read
+ @write = write
+ @index = 0
+ end
+
+ def open?
+ @transport.open?
+ end
+
+ def open
+ @transport.open
+ end
+
+ def close
+ @transport.close
+ end
+
+ def read(sz)
+ return @transport.read(sz) unless @read
+
+ return '' if sz <= 0
+
+ read_frame if @index >= @rbuf.length
+
+ @index += sz
+ @rbuf.slice(@index - sz, sz) || ''
+ end
+
+ def write(buf,sz=nil)
+ return @transport.write(buf) unless @write
+
+ @wbuf << (sz ? buf[0...sz] : buf)
+ end
+
+ #
+ # Writes the output buffer to the stream in the format of a 4-byte length
+ # followed by the actual data.
+ #
+ def flush
+ return @transport.flush unless @write
+
+ out = [@wbuf.length].pack('N')
+ out << @wbuf
+ @transport.write(out)
+ @transport.flush
+ @wbuf = ''
+ end
+
+ private
+
+ def read_frame
+ sz = @transport.read_all(4).unpack('N').first
+
+ @index = 0
+ @rbuf = @transport.read_all(sz)
+ end
+ end
+
+ class FramedTransportFactory < BaseTransportFactory
+ def get_transport(transport)
+ return FramedTransport.new(transport)
+ end
+ end
+end
\ No newline at end of file
+# encoding: ascii-8bit
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# under the License.
#
-require 'thrift/transport'
-
require 'net/http'
require 'net/https'
require 'uri'
require 'stringio'
-## Very simple HTTP client
module Thrift
- class HTTPClient < Transport
+ class HTTPClientTransport < BaseTransport
def initialize(url)
@url = URI url
@outbuf = ""
--- /dev/null
+# encoding: ascii-8bit
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Very very simple implementation of wrapping two objects, one with a #read
+# method and one with a #write method, into a transport for thrift.
+#
+# Assumes both objects are open, remain open, don't require flushing, etc.
+#
+module Thrift
+ class IOStreamTransport < BaseTransport
+ def initialize(input, output)
+ @input = input
+ @output = output
+ end
+
+ def open?; not @input.closed? or not @output.closed? end
+ def read(sz); @input.read(sz) end
+ def write(buf); @output.write(buf) end
+ def close; @input.close; @output.close end
+ def to_io; @input end # we're assuming this is used in a IO.select for reading
+ end
+end
\ No newline at end of file
--- /dev/null
+# encoding: ascii-8bit
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Thrift
+ class MemoryBufferTransport < BaseTransport
+ GARBAGE_BUFFER_SIZE = 4*(2**10) # 4kB
+
+ # If you pass a string to this, you should #dup that string
+ # unless you want it to be modified by #read and #write
+ #--
+ # this behavior is no longer required. If you wish to change it
+ # go ahead, just make sure the specs pass
+ def initialize(buffer = nil)
+ @buf = buffer || ''
+ @index = 0
+ end
+
+ def open?
+ return true
+ end
+
+ def open
+ end
+
+ def close
+ end
+
+ def peek
+ @index < @buf.size
+ end
+
+ # this method does not use the passed object directly but copies it
+ def reset_buffer(new_buf = '')
+ @buf.replace new_buf
+ @index = 0
+ end
+
+ def available
+ @buf.length - @index
+ end
+
+ def read(len)
+ data = @buf.slice(@index, len)
+ @index += len
+ @index = @buf.size if @index > @buf.size
+ if @index >= GARBAGE_BUFFER_SIZE
+ @buf = @buf.slice(@index..-1)
+ @index = 0
+ end
+ data
+ end
+
+ def write(wbuf)
+ @buf << wbuf
+ end
+
+ def flush
+ end
+
+ def inspect_buffer
+ out = []
+ for idx in 0...(@buf.size)
+ # if idx != 0
+ # out << " "
+ # end
+
+ if idx == @index
+ out << ">"
+ end
+
+ out << @buf[idx].to_s(16)
+ end
+ out.join(" ")
+ end
+ end
+end
\ No newline at end of file
--- /dev/null
+# encoding: ascii-8bit
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require 'socket'
+
+module Thrift
+ class ServerSocket < BaseServerTransport
+ # call-seq: initialize(host = nil, port)
+ def initialize(host_or_port, port = nil)
+ if port
+ @host = host_or_port
+ @port = port
+ else
+ @host = nil
+ @port = host_or_port
+ end
+ @handle = nil
+ end
+
+ attr_reader :handle
+
+ def listen
+ @handle = TCPServer.new(@host, @port)
+ end
+
+ def accept
+ unless @handle.nil?
+ sock = @handle.accept
+ trans = Socket.new
+ trans.handle = sock
+ trans
+ end
+ end
+
+ def close
+ @handle.close unless @handle.nil? or @handle.closed?
+ @handle = nil
+ end
+
+ def closed?
+ @handle.nil? or @handle.closed?
+ end
+
+ alias to_io handle
+ end
+end
\ No newline at end of file
+# encoding: ascii-8bit
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# specific language governing permissions and limitations
# under the License.
#
-require 'thrift/transport'
+
require 'socket'
module Thrift
- class Socket < Transport
+ class Socket < BaseTransport
def initialize(host='localhost', port=9090, timeout=nil)
@host = host
@port = port
@handle
end
end
-
- class ServerSocket < ServerTransport
- # call-seq: initialize(host = nil, port)
- def initialize(host_or_port, port = nil)
- if port
- @host = host_or_port
- @port = port
- else
- @host = nil
- @port = host_or_port
- end
- @handle = nil
- end
-
- attr_reader :handle
-
- def listen
- @handle = TCPServer.new(@host, @port)
- end
-
- def accept
- unless @handle.nil?
- sock = @handle.accept
- trans = Socket.new
- trans.handle = sock
- trans
- end
- end
-
- def close
- @handle.close unless @handle.nil? or @handle.closed?
- @handle = nil
- end
-
- def closed?
- @handle.nil? or @handle.closed?
- end
-
- alias to_io handle
- end
-end
+end
\ No newline at end of file
+# encoding: ascii-8bit
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# under the License.
#
-require 'thrift/transport'
require 'socket'
module Thrift
- class UNIXSocket < Socket
- def initialize(path, timeout=nil)
- @path = path
- @timeout = timeout
- @desc = @path # for read()'s error
- @handle = nil
- end
-
- def open
- begin
- @handle = ::UNIXSocket.new(@path)
- rescue StandardError
- raise TransportException.new(TransportException::NOT_OPEN, "Could not open UNIX socket at #{@path}")
- end
- end
- end
-
- class UNIXServerSocket < ServerTransport
+ class UNIXServerSocket < BaseServerTransport
def initialize(path)
@path = path
@handle = nil
alias to_io handle
end
-end
+end
\ No newline at end of file
--- /dev/null
+# encoding: ascii-8bit
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require 'socket'
+
+module Thrift
+ class UNIXSocket < Socket
+ def initialize(path, timeout=nil)
+ @path = path
+ @timeout = timeout
+ @desc = @path # for read()'s error
+ @handle = nil
+ end
+
+ def open
+ begin
+ @handle = ::UNIXSocket.new(@path)
+ rescue StandardError
+ raise TransportException.new(TransportException::NOT_OPEN, "Could not open UNIX socket at #{@path}")
+ end
+ end
+ end
+end
\ No newline at end of file
require File.dirname(__FILE__) + "/../spec/spec_helper.rb"
require "lib/thrift/serializer"
-require "lib/thrift/protocol/binaryprotocolaccelerated"
+require "lib/thrift/protocol/binary_protocol_accelerated"
require "benchmark"
# require "ruby-prof"
# f = File.new("/tmp/testfile", "w")
- # proto = Thrift::BinaryProtocolAccelerated.new(Thrift::IOStreamTransport.new(Thrift::MemoryBuffer.new, f))
+ # proto = Thrift::BinaryProtocolAccelerated.new(Thrift::IOStreamTransport.new(Thrift::MemoryBufferTransport.new, f))
# reporter.report("accelerated binary protocol, write (to disk)") do
# HOW_MANY.times do
# obj.write(proto)
# f.close
#
# f = File.new("/tmp/testfile", "r")
- # proto = Thrift::BinaryProtocolAccelerated.new(Thrift::IOStreamTransport.new(f, Thrift::MemoryBuffer.new))
+ # proto = Thrift::BinaryProtocolAccelerated.new(Thrift::IOStreamTransport.new(f, Thrift::MemoryBufferTransport.new))
# reporter.report("accelerated binary protocol, read (from disk)") do
# HOW_MANY.times do
# obj.read(proto)
#
# f = File.new("/tmp/testfile", "w")
# reporter.report("compact protocol, write (to disk)") do
- # proto = Thrift::CompactProtocol.new(Thrift::IOStreamTransport.new(Thrift::MemoryBuffer.new, f))
+ # proto = Thrift::CompactProtocol.new(Thrift::IOStreamTransport.new(Thrift::MemoryBufferTransport.new, f))
# HOW_MANY.times do
# obj.write(proto)
# end
#
# f = File.new("/tmp/testfile", "r")
# reporter.report("compact protocol, read (from disk)") do
- # proto = Thrift::CompactProtocol.new(Thrift::IOStreamTransport.new(f, Thrift::MemoryBuffer.new))
+ # proto = Thrift::CompactProtocol.new(Thrift::IOStreamTransport.new(f, Thrift::MemoryBufferTransport.new))
# HOW_MANY.times do
# obj.read(proto)
# end
#
require "spec/spec_helper"
-require "lib/thrift/serializer"
path, factory_class = ARGV
#
require "spec/spec_helper"
-require "lib/thrift/serializer"
path, factory_class = ARGV
require File.dirname(__FILE__) + '/spec_helper'
-class ThriftProtocolSpec < Spec::ExampleGroup
+class ThriftBaseProtocolSpec < Spec::ExampleGroup
include Thrift
before(:each) do
@trans = mock("MockTransport")
- @prot = Protocol.new(@trans)
+ @prot = BaseProtocol.new(@trans)
end
- describe Protocol do
+ describe BaseProtocol do
# most of the methods are stubs, so we can ignore them
it "should make trans accessible" do
end
end
- describe ProtocolFactory do
+ describe BaseProtocolFactory do
it "should raise NotImplementedError" do
# returning nil since Protocol is just an abstract class
- lambda {ProtocolFactory.new.get_protocol(mock("MockTransport"))}.should raise_error(NotImplementedError)
+ lambda {BaseProtocolFactory.new.get_protocol(mock("MockTransport"))}.should raise_error(NotImplementedError)
end
end
end
require File.dirname(__FILE__) + '/spec_helper'
-class ThriftTransportSpec < Spec::ExampleGroup
+class ThriftBaseTransportSpec < Spec::ExampleGroup
include Thrift
describe TransportException do
end
end
- describe Transport do
+ describe BaseTransport do
it "should read the specified size" do
- transport = Transport.new
+ transport = BaseTransport.new
transport.should_receive(:read).with(40).ordered.and_return("10 letters")
transport.should_receive(:read).with(30).ordered.and_return("fifteen letters")
transport.should_receive(:read).with(15).ordered.and_return("more characters")
it "should stub out the rest of the methods" do
# can't test for stubbiness, so just make sure they're defined
[:open?, :open, :close, :read, :write, :flush].each do |sym|
- Transport.method_defined?(sym).should be_true
+ BaseTransport.method_defined?(sym).should be_true
end
end
it "should alias << to write" do
- Transport.instance_method(:<<).should == Transport.instance_method(:write)
+ BaseTransport.instance_method(:<<).should == BaseTransport.instance_method(:write)
end
end
- describe ServerTransport do
+ describe BaseServerTransport do
it "should stub out its methods" do
[:listen, :accept, :close].each do |sym|
- ServerTransport.method_defined?(sym).should be_true
+ BaseServerTransport.method_defined?(sym).should be_true
end
end
end
- describe TransportFactory do
+ describe BaseTransportFactory do
it "should return the transport it's given" do
transport = mock("Transport")
- TransportFactory.new.get_transport(transport).should eql(transport)
+ BaseTransportFactory.new.get_transport(transport).should eql(transport)
end
end
end
end
- describe MemoryBuffer do
+ describe MemoryBufferTransport do
before(:each) do
- @buffer = MemoryBuffer.new
+ @buffer = MemoryBufferTransport.new
end
it "should accept a buffer on input and use it directly" do
s = "this is a test"
- @buffer = MemoryBuffer.new(s)
+ @buffer = MemoryBufferTransport.new(s)
@buffer.read(4).should == "this"
s.slice!(-4..-1)
@buffer.read(@buffer.available).should == " is a "
#
require File.dirname(__FILE__) + '/spec_helper'
-require 'thrift/protocol/binaryprotocolaccelerated'
-require File.dirname(__FILE__) + '/binaryprotocol_spec_shared'
+require File.dirname(__FILE__) + '/binary_protocol_spec_shared'
require File.dirname(__FILE__) + '/gen-rb/ThriftSpec_types'
class ThriftBinaryProtocolAcceleratedSpec < Spec::ExampleGroup
#
require File.dirname(__FILE__) + '/spec_helper'
-require 'thrift/protocol/binaryprotocol'
-require File.dirname(__FILE__) + '/binaryprotocol_spec_shared'
+require File.dirname(__FILE__) + '/binary_protocol_spec_shared'
class ThriftBinaryProtocolSpec < Spec::ExampleGroup
include Thrift
shared_examples_for 'a binary protocol' do
before(:each) do
- @trans = Thrift::MemoryBuffer.new
+ @trans = Thrift::MemoryBufferTransport.new
@prot = protocol_class.new(@trans)
end
lambda { @prot.write_string(nil) }.should raise_error
end
- it "should read message header correctly" do
- @trans.write([protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::CALL, "testMessage".size, "testMessage", 17].pack("NNa11N"))
- @prot.read_message_begin().should == ['testMessage', Thrift::MessageTypes::CALL, 17]
+ it "should write the message header without version when writes are not strict" do
+ @prot = protocol_class.new(@trans, true, false) # no strict write
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
+ @trans.read(1000).should == "\000\000\000\vtestMessage\001\000\000\000\021"
end
-
- it "should read the message header without version when writes are not strict" do
- @prot = protocol_class.new(@trans, false, true) # no strict write
- @trans.write("\000\000\000\vtestMessage\001\000\000\000\021")
- @prot.read_message_begin().should == ['testMessage', Thrift::MessageTypes::CALL, 17]
+
+ it "should write the message header with a version when writes are strict" do
+ @prot = protocol_class.new(@trans) # strict write
+ @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17)
+ @trans.read(1000).should == "\200\001\000\001\000\000\000\vtestMessage\000\000\000\021"
end
-
+
# message footer is a noop
it "should read a field header" do
processor = Srv::Processor.new(SrvHandler.new)
client = Srv::Client.new(clientproto, clientproto)
-
+
# first block
firstblock.call(client)
Fixtures::COMPACT_PROTOCOL_TEST_STRUCT
end
end
-
end
#
require File.dirname(__FILE__) + '/spec_helper'
-require "thrift/protocol/compact_protocol"
describe Thrift::CompactProtocol do
TESTS = {
TESTS.each_pair do |primitive_type, test_values|
test_values.each do |value|
# puts "testing #{value}" if primitive_type == :i64
- trans = Thrift::MemoryBuffer.new
+ trans = Thrift::MemoryBufferTransport.new
proto = Thrift::CompactProtocol.new(trans)
proto.send(writer(primitive_type), value)
thrift_type = Thrift::Types.const_get(final_primitive_type.to_s.upcase)
# puts primitive_type
test_values.each do |value|
- trans = Thrift::MemoryBuffer.new
+ trans = Thrift::MemoryBufferTransport.new
proto = Thrift::CompactProtocol.new(trans)
proto.write_field_begin(nil, thrift_type, 15)
end
it "should encode and decode a monster struct correctly" do
- trans = Thrift::MemoryBuffer.new
+ trans = Thrift::MemoryBufferTransport.new
proto = Thrift::CompactProtocol.new(trans)
struct = CompactProtoTestStruct.new
end
it "should make method calls correctly" do
- client_out_trans = Thrift::MemoryBuffer.new
+ client_out_trans = Thrift::MemoryBufferTransport.new
client_out_proto = Thrift::CompactProtocol.new(client_out_trans)
- client_in_trans = Thrift::MemoryBuffer.new
+ client_in_trans = Thrift::MemoryBufferTransport.new
client_in_proto = Thrift::CompactProtocol.new(client_in_trans)
processor = Srv::Processor.new(JankyHandler.new)
#
require File.dirname(__FILE__) + '/spec_helper'
-require 'thrift/transport/httpclient'
-class ThriftHTTPClientSpec < Spec::ExampleGroup
+class ThriftHTTPClientTransportSpec < Spec::ExampleGroup
include Thrift
- describe HTTPClient do
+ describe HTTPClientTransport do
before(:each) do
- @client = HTTPClient.new("http://my.domain.com/path/to/service")
+ @client = HTTPClientTransport.new("http://my.domain.com/path/to/service")
end
it "should always be open" do
#
require File.dirname(__FILE__) + '/spec_helper'
-require 'thrift/server/httpserver'
+require 'thrift/server/mongrel_http_server'
class ThriftHTTPServerSpec < Spec::ExampleGroup
include Thrift
- Handler = SimpleMongrelHTTPServer::Handler
+ Handler = MongrelHTTPServer::Handler
- describe SimpleMongrelHTTPServer do
+ describe MongrelHTTPServer do
it "should have appropriate defaults" do
mock_factory = mock("BinaryProtocolFactory")
mock_proc = mock("Processor")
mock.should_receive(:register).with("/", handler)
end
end
- SimpleMongrelHTTPServer.new(mock_proc)
+ MongrelHTTPServer.new(mock_proc)
end
it "should understand :ip, :port, :path, and :protocol_factory" do
mock.should_receive(:register).with("/foo", handler)
end
end
- SimpleMongrelHTTPServer.new(mock_proc, :ip => "1.2.3.4", :port => 1234, :path => "foo",
+ MongrelHTTPServer.new(mock_proc, :ip => "1.2.3.4", :port => 1234, :path => "foo",
:protocol_factory => mock_factory)
end
end
end
end
- SimpleMongrelHTTPServer.new(nil).serve
+ MongrelHTTPServer.new(nil).serve
end
end
- describe SimpleMongrelHTTPServer::Handler do
+ describe MongrelHTTPServer::Handler do
before(:each) do
@processor = mock("Processor")
@factory = mock("ProtocolFactory")
#
require File.dirname(__FILE__) + '/spec_helper'
-require 'thrift/server/nonblockingserver'
require File.dirname(__FILE__) + '/gen-rb/NonblockingService'
class ThriftNonblockingServerSpec < Spec::ExampleGroup
end
end
- class SpecTransport < Transport
+ class SpecTransport < BaseTransport
def initialize(transport, queue)
@transport = transport
@queue = queue
processor = NonblockingService::Processor.new(handler)
queue = Queue.new
@transport = SpecServerSocket.new('localhost', @port, queue)
- transportFactory = FramedTransportFactory.new
+ transport_factory = FramedTransportFactory.new
logger = Logger.new(STDERR)
logger.level = Logger::WARN
- @server = NonblockingServer.new(processor, @transport, transportFactory, nil, 5, logger)
+ @server = NonblockingServer.new(processor, @transport, transport_factory, nil, 5, logger)
handler.server = @server
@server_thread = Thread.new(Thread.current) do |master_thread|
begin
#
require File.dirname(__FILE__) + '/spec_helper'
-require 'thrift/serializer'
require File.dirname(__FILE__) + '/gen-rb/ThriftSpec_types'
class ThriftSerializerSpec < Spec::ExampleGroup
end
it "should serialize structs to the given protocol" do
- protocol = Protocol.new(mock("transport"))
+ protocol = BaseProtocol.new(mock("transport"))
protocol.should_receive(:write_struct_begin).with("SpecNamespace::Hello")
protocol.should_receive(:write_field_begin).with("greeting", Types::STRING, 1)
protocol.should_receive(:write_string).with("Good day")
protocol.should_receive(:write_field_end)
protocol.should_receive(:write_field_stop)
protocol.should_receive(:write_struct_end)
- protocolFactory = mock("ProtocolFactory")
- protocolFactory.stub!(:get_protocol).and_return(protocol)
- serializer = Serializer.new(protocolFactory)
+ protocol_factory = mock("ProtocolFactory")
+ protocol_factory.stub!(:get_protocol).and_return(protocol)
+ serializer = Serializer.new(protocol_factory)
serializer.serialize(Hello.new(:greeting => "Good day"))
end
end
end
it "should deserialize structs from the given protocol" do
- protocol = Protocol.new(mock("transport"))
+ protocol = BaseProtocol.new(mock("transport"))
protocol.should_receive(:read_struct_begin).and_return("SpecNamespace::Hello")
protocol.should_receive(:read_field_begin).and_return(["greeting", Types::STRING, 1],
[nil, Types::STOP, 0])
protocol.should_receive(:read_string).and_return("Good day")
protocol.should_receive(:read_field_end)
protocol.should_receive(:read_struct_end)
- protocolFactory = mock("ProtocolFactory")
- protocolFactory.stub!(:get_protocol).and_return(protocol)
- deserializer = Deserializer.new(protocolFactory)
+ protocol_factory = mock("ProtocolFactory")
+ protocol_factory.stub!(:get_protocol).and_return(protocol)
+ deserializer = Deserializer.new(protocol_factory)
deserializer.deserialize(Hello.new, "").should == Hello.new(:greeting => "Good day")
end
end
--- /dev/null
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require File.dirname(__FILE__) + '/spec_helper'
+require File.dirname(__FILE__) + "/socket_spec_shared"
+
+class ThriftServerSocketSpec < Spec::ExampleGroup
+ include Thrift
+
+ describe ServerSocket do
+ before(:each) do
+ @socket = ServerSocket.new(1234)
+ end
+
+ it "should create a handle when calling listen" do
+ TCPServer.should_receive(:new).with(nil, 1234)
+ @socket.listen
+ end
+
+ it "should accept an optional host argument" do
+ @socket = ServerSocket.new('localhost', 1234)
+ TCPServer.should_receive(:new).with('localhost', 1234)
+ @socket.listen
+ end
+
+ it "should create a Thrift::Socket to wrap accepted sockets" do
+ handle = mock("TCPServer")
+ TCPServer.should_receive(:new).with(nil, 1234).and_return(handle)
+ @socket.listen
+ sock = mock("sock")
+ handle.should_receive(:accept).and_return(sock)
+ trans = mock("Socket")
+ Socket.should_receive(:new).and_return(trans)
+ trans.should_receive(:handle=).with(sock)
+ @socket.accept.should == trans
+ end
+
+ it "should close the handle when closed" do
+ handle = mock("TCPServer", :closed? => false)
+ TCPServer.should_receive(:new).with(nil, 1234).and_return(handle)
+ @socket.listen
+ handle.should_receive(:close)
+ @socket.close
+ end
+
+ it "should return nil when accepting if there is no handle" do
+ @socket.accept.should be_nil
+ end
+
+ it "should return true for closed? when appropriate" do
+ handle = mock("TCPServer", :closed? => false)
+ TCPServer.stub!(:new).and_return(handle)
+ @socket.listen
+ @socket.should_not be_closed
+ handle.stub!(:close)
+ @socket.close
+ @socket.should be_closed
+ @socket.listen
+ @socket.should_not be_closed
+ handle.stub!(:closed?).and_return(true)
+ @socket.should be_closed
+ end
+ end
+end
class ThriftServerSpec < Spec::ExampleGroup
include Thrift
- describe Server do
- it "should default to TransportFactory and BinaryProtocolFactory when not specified" do
- server = Server.new(mock("Processor"), mock("ServerTransport"))
- server.instance_variable_get(:'@transportFactory').should be_an_instance_of(TransportFactory)
- server.instance_variable_get(:'@protocolFactory').should be_an_instance_of(BinaryProtocolFactory)
+ describe BaseServer do
+ it "should default to BaseTransportFactory and BinaryProtocolFactory when not specified" do
+ server = BaseServer.new(mock("Processor"), mock("BaseServerTransport"))
+ server.instance_variable_get(:'@transport_factory').should be_an_instance_of(BaseTransportFactory)
+ server.instance_variable_get(:'@protocol_factory').should be_an_instance_of(BinaryProtocolFactory)
end
# serve is a noop, so can't test that
before(:each) do
@processor = mock("Processor")
@serverTrans = mock("ServerTransport")
- @trans = mock("Transport")
- @prot = mock("Protocol")
+ @trans = mock("BaseTransport")
+ @prot = mock("BaseProtocol")
@client = mock("Client")
@server = server_type.new(@processor, @serverTrans, @trans, @prot)
end
Socket.new('localhost', 8080, 5).timeout.should == 5
end
end
-
- describe ServerSocket do
- before(:each) do
- @socket = ServerSocket.new(1234)
- end
-
- it "should create a handle when calling listen" do
- TCPServer.should_receive(:new).with(nil, 1234)
- @socket.listen
- end
-
- it "should accept an optional host argument" do
- @socket = ServerSocket.new('localhost', 1234)
- TCPServer.should_receive(:new).with('localhost', 1234)
- @socket.listen
- end
-
- it "should create a Thrift::Socket to wrap accepted sockets" do
- handle = mock("TCPServer")
- TCPServer.should_receive(:new).with(nil, 1234).and_return(handle)
- @socket.listen
- sock = mock("sock")
- handle.should_receive(:accept).and_return(sock)
- trans = mock("Socket")
- Socket.should_receive(:new).and_return(trans)
- trans.should_receive(:handle=).with(sock)
- @socket.accept.should == trans
- end
-
- it "should close the handle when closed" do
- handle = mock("TCPServer", :closed? => false)
- TCPServer.should_receive(:new).with(nil, 1234).and_return(handle)
- @socket.listen
- handle.should_receive(:close)
- @socket.close
- end
-
- it "should return nil when accepting if there is no handle" do
- @socket.accept.should be_nil
- end
-
- it "should return true for closed? when appropriate" do
- handle = mock("TCPServer", :closed? => false)
- TCPServer.stub!(:new).and_return(handle)
- @socket.listen
- @socket.should_not be_closed
- handle.stub!(:close)
- @socket.close
- @socket.should be_closed
- @socket.listen
- @socket.should_not be_closed
- handle.stub!(:closed?).and_return(true)
- @socket.should be_closed
- end
- end
end
$:.unshift File.join(File.dirname(__FILE__), *%w[.. ext])
-# pretend we already loaded fastthread, otherwise the nonblockingserver_spec
+# pretend we already loaded fastthread, otherwise the nonblocking_server_spec
# will get screwed up
# $" << 'fastthread.bundle'
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + '/gen-rb/ThriftSpec_types'
-# require "binaryprotocolaccelerated"
-
class ThriftStructSpec < Spec::ExampleGroup
include Thrift
include SpecNamespace
it "should read itself off the wire" do
struct = Foo.new
- prot = Protocol.new(mock("transport"))
+ prot = BaseProtocol.new(mock("transport"))
prot.should_receive(:read_struct_begin).twice
prot.should_receive(:read_struct_end).twice
prot.should_receive(:read_field_begin).and_return(
it "should skip unexpected fields in structs and use default values" do
struct = Foo.new
- prot = Protocol.new(mock("transport"))
+ prot = BaseProtocol.new(mock("transport"))
prot.should_receive(:read_struct_begin)
prot.should_receive(:read_struct_end)
prot.should_receive(:read_field_begin).and_return(
end
it "should write itself to the wire" do
- prot = Protocol.new(mock("transport")) #mock("Protocol")
+ prot = BaseProtocol.new(mock("transport")) #mock("Protocol")
prot.should_receive(:write_struct_begin).with("SpecNamespace::Foo")
prot.should_receive(:write_struct_begin).with("SpecNamespace::Hello")
prot.should_receive(:write_struct_end).twice
e.message.should == "something happened"
e.code.should == 1
# ensure it gets serialized properly, this is the really important part
- prot = Protocol.new(mock("trans"))
+ prot = BaseProtocol.new(mock("trans"))
prot.should_receive(:write_struct_begin).with("SpecNamespace::Xception")
prot.should_receive(:write_struct_end)
prot.should_receive(:write_field_begin).with('message', Types::STRING, 1)#, "something happened")
rescue Thrift::Exception => e
e.message.should == "something happened"
e.code.should == 5
- prot = Protocol.new(mock("trans"))
+ prot = BaseProtocol.new(mock("trans"))
prot.should_receive(:write_struct_begin).with("SpecNamespace::Xception")
prot.should_receive(:write_struct_end)
prot.should_receive(:write_field_begin).with('message', Types::STRING, 1)
#
require File.dirname(__FILE__) + '/spec_helper'
-require 'thrift/transport/unixsocket'
require File.dirname(__FILE__) + "/socket_spec_shared"
class ThriftUNIXSocketSpec < Spec::ExampleGroup