tiny_thrift 1.0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/README +43 -0
  3. data/benchmark/Benchmark.thrift +24 -0
  4. data/benchmark/benchmark.rb +271 -0
  5. data/benchmark/client.rb +74 -0
  6. data/benchmark/server.rb +82 -0
  7. data/benchmark/thin_server.rb +44 -0
  8. data/ext/binary_protocol_accelerated.c +460 -0
  9. data/ext/binary_protocol_accelerated.h +20 -0
  10. data/ext/bytes.c +36 -0
  11. data/ext/bytes.h +31 -0
  12. data/ext/compact_protocol.c +635 -0
  13. data/ext/compact_protocol.h +20 -0
  14. data/ext/constants.h +96 -0
  15. data/ext/extconf.rb +32 -0
  16. data/ext/macros.h +41 -0
  17. data/ext/memory_buffer.c +134 -0
  18. data/ext/memory_buffer.h +20 -0
  19. data/ext/protocol.c +0 -0
  20. data/ext/protocol.h +0 -0
  21. data/ext/strlcpy.c +41 -0
  22. data/ext/strlcpy.h +34 -0
  23. data/ext/struct.c +688 -0
  24. data/ext/struct.h +25 -0
  25. data/ext/thrift_native.c +195 -0
  26. data/lib/thrift.rb +66 -0
  27. data/lib/thrift/bytes.rb +131 -0
  28. data/lib/thrift/client.rb +62 -0
  29. data/lib/thrift/core_ext.rb +23 -0
  30. data/lib/thrift/core_ext/fixnum.rb +29 -0
  31. data/lib/thrift/exceptions.rb +87 -0
  32. data/lib/thrift/processor.rb +57 -0
  33. data/lib/thrift/protocol/base_protocol.rb +377 -0
  34. data/lib/thrift/protocol/binary_protocol.rb +237 -0
  35. data/lib/thrift/protocol/binary_protocol_accelerated.rb +39 -0
  36. data/lib/thrift/protocol/compact_protocol.rb +434 -0
  37. data/lib/thrift/protocol/json_protocol.rb +769 -0
  38. data/lib/thrift/serializer/deserializer.rb +33 -0
  39. data/lib/thrift/serializer/serializer.rb +34 -0
  40. data/lib/thrift/server/base_server.rb +31 -0
  41. data/lib/thrift/server/mongrel_http_server.rb +60 -0
  42. data/lib/thrift/server/nonblocking_server.rb +305 -0
  43. data/lib/thrift/server/simple_server.rb +43 -0
  44. data/lib/thrift/server/thin_http_server.rb +91 -0
  45. data/lib/thrift/server/thread_pool_server.rb +75 -0
  46. data/lib/thrift/server/threaded_server.rb +47 -0
  47. data/lib/thrift/struct.rb +237 -0
  48. data/lib/thrift/struct_union.rb +192 -0
  49. data/lib/thrift/thrift_native.rb +24 -0
  50. data/lib/thrift/transport/base_server_transport.rb +37 -0
  51. data/lib/thrift/transport/base_transport.rb +109 -0
  52. data/lib/thrift/transport/buffered_transport.rb +114 -0
  53. data/lib/thrift/transport/framed_transport.rb +117 -0
  54. data/lib/thrift/transport/http_client_transport.rb +56 -0
  55. data/lib/thrift/transport/io_stream_transport.rb +39 -0
  56. data/lib/thrift/transport/memory_buffer_transport.rb +125 -0
  57. data/lib/thrift/transport/server_socket.rb +63 -0
  58. data/lib/thrift/transport/socket.rb +139 -0
  59. data/lib/thrift/transport/unix_server_socket.rb +60 -0
  60. data/lib/thrift/transport/unix_socket.rb +40 -0
  61. data/lib/thrift/types.rb +101 -0
  62. data/lib/thrift/union.rb +179 -0
  63. data/lib/tiny_thrift.rb +1 -0
  64. data/spec/ThriftSpec.thrift +183 -0
  65. data/spec/base_protocol_spec.rb +217 -0
  66. data/spec/base_transport_spec.rb +350 -0
  67. data/spec/binary_protocol_accelerated_spec.rb +42 -0
  68. data/spec/binary_protocol_spec.rb +66 -0
  69. data/spec/binary_protocol_spec_shared.rb +455 -0
  70. data/spec/bytes_spec.rb +160 -0
  71. data/spec/client_spec.rb +99 -0
  72. data/spec/compact_protocol_spec.rb +143 -0
  73. data/spec/exception_spec.rb +141 -0
  74. data/spec/http_client_spec.rb +120 -0
  75. data/spec/json_protocol_spec.rb +513 -0
  76. data/spec/nonblocking_server_spec.rb +263 -0
  77. data/spec/processor_spec.rb +80 -0
  78. data/spec/serializer_spec.rb +67 -0
  79. data/spec/server_socket_spec.rb +79 -0
  80. data/spec/server_spec.rb +147 -0
  81. data/spec/socket_spec.rb +61 -0
  82. data/spec/socket_spec_shared.rb +104 -0
  83. data/spec/spec_helper.rb +61 -0
  84. data/spec/struct_nested_containers_spec.rb +191 -0
  85. data/spec/struct_spec.rb +293 -0
  86. data/spec/thin_http_server_spec.rb +141 -0
  87. data/spec/types_spec.rb +115 -0
  88. data/spec/union_spec.rb +203 -0
  89. data/spec/unix_socket_spec.rb +107 -0
  90. metadata +313 -0
@@ -0,0 +1,192 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+ require 'set'
20
+
21
+ module Thrift
22
+ module Struct_Union
23
+ def name_to_id(name)
24
+ names_to_ids = self.class.instance_variable_get(:@names_to_ids)
25
+ unless names_to_ids
26
+ names_to_ids = {}
27
+ struct_fields.each do |fid, field_def|
28
+ names_to_ids[field_def[:name]] = fid
29
+ end
30
+ self.class.instance_variable_set(:@names_to_ids, names_to_ids)
31
+ end
32
+ names_to_ids[name]
33
+ end
34
+
35
+ def sorted_field_ids
36
+ sorted_field_ids = self.class.instance_variable_get(:@sorted_field_ids)
37
+ unless sorted_field_ids
38
+ sorted_field_ids = struct_fields.keys.sort
39
+ self.class.instance_variable_set(:@sorted_field_ids, sorted_field_ids)
40
+ end
41
+ sorted_field_ids
42
+ end
43
+
44
+ def each_field
45
+ sorted_field_ids.each do |fid|
46
+ data = struct_fields[fid]
47
+ yield fid, data
48
+ end
49
+ end
50
+
51
+ def read_field(iprot, field = {})
52
+ case field[:type]
53
+ when Types::STRUCT
54
+ value = field[:class].new
55
+ value.read(iprot)
56
+ when Types::MAP
57
+ key_type, val_type, size = iprot.read_map_begin
58
+ # Skip the map contents if the declared key or value types don't match the expected ones.
59
+ if (size != 0 && (key_type != field[:key][:type] || val_type != field[:value][:type]))
60
+ size.times do
61
+ iprot.skip(key_type)
62
+ iprot.skip(val_type)
63
+ end
64
+ value = nil
65
+ else
66
+ value = {}
67
+ size.times do
68
+ k = read_field(iprot, field_info(field[:key]))
69
+ v = read_field(iprot, field_info(field[:value]))
70
+ value[k] = v
71
+ end
72
+ end
73
+ iprot.read_map_end
74
+ when Types::LIST
75
+ e_type, size = iprot.read_list_begin
76
+ # Skip the list contents if the declared element type doesn't match the expected one.
77
+ if (e_type != field[:element][:type])
78
+ size.times do
79
+ iprot.skip(e_type)
80
+ end
81
+ value = nil
82
+ else
83
+ value = Array.new(size) do |n|
84
+ read_field(iprot, field_info(field[:element]))
85
+ end
86
+ end
87
+ iprot.read_list_end
88
+ when Types::SET
89
+ e_type, size = iprot.read_set_begin
90
+ # Skip the set contents if the declared element type doesn't match the expected one.
91
+ if (e_type != field[:element][:type])
92
+ size.times do
93
+ iprot.skip(e_type)
94
+ end
95
+ else
96
+ value = Set.new
97
+ size.times do
98
+ element = read_field(iprot, field_info(field[:element]))
99
+ value << element
100
+ end
101
+ end
102
+ iprot.read_set_end
103
+ else
104
+ value = iprot.read_type(field)
105
+ end
106
+ value
107
+ end
108
+
109
+ def write_data(oprot, value, field)
110
+ if is_container? field[:type]
111
+ write_container(oprot, value, field)
112
+ else
113
+ oprot.write_type(field, value)
114
+ end
115
+ end
116
+
117
+ def write_container(oprot, value, field = {})
118
+ case field[:type]
119
+ when Types::MAP
120
+ oprot.write_map_begin(field[:key][:type], field[:value][:type], value.size)
121
+ value.each do |k, v|
122
+ write_data(oprot, k, field[:key])
123
+ write_data(oprot, v, field[:value])
124
+ end
125
+ oprot.write_map_end
126
+ when Types::LIST
127
+ oprot.write_list_begin(field[:element][:type], value.size)
128
+ value.each do |elem|
129
+ write_data(oprot, elem, field[:element])
130
+ end
131
+ oprot.write_list_end
132
+ when Types::SET
133
+ oprot.write_set_begin(field[:element][:type], value.size)
134
+ value.each do |v,| # the , is to preserve compatibility with the old Hash-style sets
135
+ write_data(oprot, v, field[:element])
136
+ end
137
+ oprot.write_set_end
138
+ else
139
+ raise "Not a container type: #{field[:type]}"
140
+ end
141
+ end
142
+
143
+ CONTAINER_TYPES = []
144
+ CONTAINER_TYPES[Types::LIST] = true
145
+ CONTAINER_TYPES[Types::MAP] = true
146
+ CONTAINER_TYPES[Types::SET] = true
147
+ def is_container?(type)
148
+ CONTAINER_TYPES[type]
149
+ end
150
+
151
+ def field_info(field)
152
+ { :type => field[:type],
153
+ :class => field[:class],
154
+ :key => field[:key],
155
+ :value => field[:value],
156
+ :element => field[:element] }
157
+ end
158
+
159
+ def inspect_field(value, field_info)
160
+ if enum_class = field_info[:enum_class]
161
+ "#{enum_class.const_get(:VALUE_MAP)[value]} (#{value})"
162
+ elsif value.is_a? Hash
163
+ if field_info[:type] == Types::MAP
164
+ map_buf = []
165
+ value.each do |k, v|
166
+ map_buf << inspect_field(k, field_info[:key]) + ": " + inspect_field(v, field_info[:value])
167
+ end
168
+ "{" + map_buf.join(", ") + "}"
169
+ else
170
+ # old-style set
171
+ inspect_collection(value.keys, field_info)
172
+ end
173
+ elsif value.is_a? Array
174
+ inspect_collection(value, field_info)
175
+ elsif value.is_a? Set
176
+ inspect_collection(value, field_info)
177
+ elsif value.is_a?(String) && field_info[:binary]
178
+ value.unpack("H*").first
179
+ else
180
+ value.inspect
181
+ end
182
+ end
183
+
184
+ def inspect_collection(collection, field_info)
185
+ buf = []
186
+ collection.each do |k|
187
+ buf << inspect_field(k, field_info[:element])
188
+ end
189
+ "[" + buf.join(", ") + "]"
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,24 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ begin
21
+ require "thrift_native"
22
+ rescue LoadError
23
+ puts "Unable to load thrift_native extension. Defaulting to pure Ruby libraries."
24
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: ascii-8bit
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ #
20
+
21
+ module Thrift
22
+ class BaseServerTransport
23
+ def listen
24
+ raise NotImplementedError
25
+ end
26
+
27
+ def accept
28
+ raise NotImplementedError
29
+ end
30
+
31
+ def close; nil; end
32
+
33
+ def closed?
34
+ raise NotImplementedError
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,109 @@
1
+ # encoding: ascii-8bit
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ #
20
+
21
+ module Thrift
22
+ class TransportException < Exception
23
+ UNKNOWN = 0
24
+ NOT_OPEN = 1
25
+ ALREADY_OPEN = 2
26
+ TIMED_OUT = 3
27
+ END_OF_FILE = 4
28
+
29
+ attr_reader :type
30
+
31
+ def initialize(type=UNKNOWN, message=nil)
32
+ super(message)
33
+ @type = type
34
+ end
35
+ end
36
+
37
+ module TransportUtils
38
+ # Deprecated: Use Thrift::Bytes instead
39
+ def self.get_string_byte(string, index)
40
+ Bytes.get_string_byte(string, index)
41
+ end
42
+
43
+ # Deprecated: Use Thrift::Bytes instead
44
+ def self.set_string_byte(string, index, byte)
45
+ Bytes.set_string_byte(string, index, byte)
46
+ end
47
+ end
48
+
49
+ class BaseTransport
50
+ def open?; end
51
+
52
+ def open; end
53
+
54
+ def close; end
55
+
56
+ # Reads a number of bytes from the transports. In Ruby 1.9+, the String returned will have a BINARY (aka ASCII8BIT) encoding.
57
+ #
58
+ # sz - The number of bytes to read from the transport.
59
+ #
60
+ # Returns a String acting as a byte buffer.
61
+ def read(sz)
62
+ raise NotImplementedError
63
+ end
64
+
65
+ # Returns an unsigned byte as a Fixnum in the range (0..255).
66
+ def read_byte
67
+ buf = read_all(1)
68
+ return Bytes.get_string_byte(buf, 0)
69
+ end
70
+
71
+ # Reads size bytes and copies them into buffer[0..size].
72
+ def read_into_buffer(buffer, size)
73
+ tmp = read_all(size)
74
+ i = 0
75
+ tmp.each_byte do |byte|
76
+ Bytes.set_string_byte(buffer, i, byte)
77
+ i += 1
78
+ end
79
+ i
80
+ end
81
+
82
+ def read_all(size)
83
+ return Bytes.empty_byte_buffer if size <= 0
84
+ buf = read(size)
85
+ while (buf.length < size)
86
+ chunk = read(size - buf.length)
87
+ buf << chunk
88
+ end
89
+
90
+ buf
91
+ end
92
+
93
+ # Writes the byte buffer to the transport. In Ruby 1.9+, the buffer will be forced into BINARY encoding.
94
+ #
95
+ # buf - A String acting as a byte buffer.
96
+ #
97
+ # Returns nothing.
98
+ def write(buf); end
99
+ alias_method :<<, :write
100
+
101
+ def flush; end
102
+ end
103
+
104
+ class BaseTransportFactory
105
+ def get_transport(trans)
106
+ return trans
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: ascii-8bit
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The ASF licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+ #
20
+
21
+ module Thrift
22
+ class BufferedTransport < BaseTransport
23
+ DEFAULT_BUFFER = 4096
24
+
25
+ def initialize(transport)
26
+ @transport = transport
27
+ @wbuf = Bytes.empty_byte_buffer
28
+ @rbuf = Bytes.empty_byte_buffer
29
+ @index = 0
30
+ end
31
+
32
+ def open?
33
+ return @transport.open?
34
+ end
35
+
36
+ def open
37
+ @transport.open
38
+ end
39
+
40
+ def close
41
+ flush
42
+ @transport.close
43
+ end
44
+
45
+ def read(sz)
46
+ @index += sz
47
+ ret = @rbuf.slice(@index - sz, sz) || Bytes.empty_byte_buffer
48
+
49
+ if ret.length == 0
50
+ @rbuf = @transport.read([sz, DEFAULT_BUFFER].max)
51
+ @index = sz
52
+ ret = @rbuf.slice(0, sz) || Bytes.empty_byte_buffer
53
+ end
54
+
55
+ ret
56
+ end
57
+
58
+ def read_byte
59
+ # If the read buffer is exhausted, try to read up to DEFAULT_BUFFER more bytes into it.
60
+ if @index >= @rbuf.size
61
+ @rbuf = @transport.read(DEFAULT_BUFFER)
62
+ @index = 0
63
+ end
64
+
65
+ # The read buffer has some data now, read a single byte. Using get_string_byte() avoids
66
+ # allocating a temp string of size 1 unnecessarily.
67
+ @index += 1
68
+ return Bytes.get_string_byte(@rbuf, @index - 1)
69
+ end
70
+
71
+ # Reads a number of bytes from the transport into the buffer passed.
72
+ #
73
+ # buffer - The String (byte buffer) to write data to; this is assumed to have a BINARY encoding.
74
+ # size - The number of bytes to read from the transport and write to the buffer.
75
+ #
76
+ # Returns the number of bytes read.
77
+ def read_into_buffer(buffer, size)
78
+ i = 0
79
+ while i < size
80
+ # If the read buffer is exhausted, try to read up to DEFAULT_BUFFER more bytes into it.
81
+ if @index >= @rbuf.size
82
+ @rbuf = @transport.read(DEFAULT_BUFFER)
83
+ @index = 0
84
+ end
85
+
86
+ # The read buffer has some data now, so copy bytes over to the output buffer.
87
+ byte = Bytes.get_string_byte(@rbuf, @index)
88
+ Bytes.set_string_byte(buffer, i, byte)
89
+ @index += 1
90
+ i += 1
91
+ end
92
+ i
93
+ end
94
+
95
+ def write(buf)
96
+ @wbuf << Bytes.force_binary_encoding(buf)
97
+ end
98
+
99
+ def flush
100
+ unless @wbuf.empty?
101
+ @transport.write(@wbuf)
102
+ @wbuf = Bytes.empty_byte_buffer
103
+ end
104
+
105
+ @transport.flush
106
+ end
107
+ end
108
+
109
+ class BufferedTransportFactory < BaseTransportFactory
110
+ def get_transport(transport)
111
+ return BufferedTransport.new(transport)
112
+ end
113
+ end
114
+ end