thrift 0.2.0.4 → 0.4.0

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 (45) hide show
  1. data/CHANGELOG +1 -13
  2. data/Manifest +11 -23
  3. data/Rakefile +8 -6
  4. data/ext/binary_protocol_accelerated.c +4 -53
  5. data/ext/compact_protocol.c +3 -53
  6. data/ext/extconf.rb +4 -18
  7. data/ext/struct.c +181 -130
  8. data/ext/struct.h +2 -44
  9. data/ext/thrift_native.c +3 -3
  10. data/lib/thrift.rb +6 -1
  11. data/lib/thrift/protocol/binary_protocol_accelerated.rb +5 -1
  12. data/lib/thrift/protocol/compact_protocol.rb +1 -0
  13. data/lib/thrift/server/nonblocking_server.rb +1 -2
  14. data/lib/thrift/struct.rb +46 -112
  15. data/lib/thrift/struct_union.rb +159 -0
  16. data/lib/thrift/transport/http_client_transport.rb +12 -6
  17. data/lib/thrift/transport/memory_buffer_transport.rb +2 -2
  18. data/lib/thrift/types.rb +1 -1
  19. data/lib/thrift/union.rb +179 -0
  20. data/spec/ThriftSpec.thrift +48 -0
  21. data/spec/binary_protocol_accelerated_spec.rb +18 -13
  22. data/spec/binary_protocol_spec_shared.rb +2 -2
  23. data/spec/compact_protocol_spec.rb +19 -3
  24. data/spec/http_client_spec.rb +17 -2
  25. data/spec/struct_spec.rb +34 -0
  26. data/spec/union_spec.rb +193 -0
  27. data/thrift.gemspec +11 -13
  28. metadata +36 -67
  29. data.tar.gz.sig +0 -2
  30. data/Makefile.am +0 -47
  31. data/benchmark/gen-rb/BenchmarkService.rb +0 -81
  32. data/benchmark/gen-rb/Benchmark_constants.rb +0 -11
  33. data/benchmark/gen-rb/Benchmark_types.rb +0 -10
  34. data/lib/thrift/protocol/binaryprotocol.rb +0 -213
  35. data/lib/thrift/protocol/binaryprotocolaccelerated.rb +0 -19
  36. data/lib/thrift/protocol/tbinaryprotocol.rb +0 -2
  37. data/lib/thrift/protocol/tprotocol.rb +0 -2
  38. data/lib/thrift/server/httpserver.rb +0 -44
  39. data/lib/thrift/server/nonblockingserver.rb +0 -278
  40. data/lib/thrift/server/thttpserver.rb +0 -2
  41. data/lib/thrift/server/tserver.rb +0 -2
  42. data/spec/gen-rb/NonblockingService.rb +0 -268
  43. data/spec/gen-rb/ThriftSpec_constants.rb +0 -11
  44. data/spec/gen-rb/ThriftSpec_types.rb +0 -134
  45. metadata.gz.sig +0 -0
@@ -1,5 +1,5 @@
1
1
  # encoding: ascii-8bit
2
- #
2
+ #
3
3
  # Licensed to the Apache Software Foundation (ASF) under one
4
4
  # or more contributor license agreements. See the NOTICE file
5
5
  # distributed with this work for additional information
@@ -7,16 +7,16 @@
7
7
  # to you under the Apache License, Version 2.0 (the
8
8
  # "License"); you may not use this file except in compliance
9
9
  # with the License. You may obtain a copy of the License at
10
- #
10
+ #
11
11
  # http://www.apache.org/licenses/LICENSE-2.0
12
- #
12
+ #
13
13
  # Unless required by applicable law or agreed to in writing,
14
14
  # software distributed under the License is distributed on an
15
15
  # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
16
  # KIND, either express or implied. See the License for the
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
- #
19
+ #
20
20
 
21
21
  require 'net/http'
22
22
  require 'net/https'
@@ -25,19 +25,25 @@ require 'stringio'
25
25
 
26
26
  module Thrift
27
27
  class HTTPClientTransport < BaseTransport
28
+
28
29
  def initialize(url)
29
30
  @url = URI url
31
+ @headers = {'Content-Type' => 'application/x-thrift'}
30
32
  @outbuf = ""
31
33
  end
32
34
 
33
35
  def open?; true end
34
36
  def read(sz); @inbuf.read sz end
35
37
  def write(buf); @outbuf << buf end
38
+
39
+ def add_headers(headers)
40
+ @headers = @headers.merge(headers)
41
+ end
42
+
36
43
  def flush
37
44
  http = Net::HTTP.new @url.host, @url.port
38
45
  http.use_ssl = @url.scheme == "https"
39
- headers = { 'Content-Type' => 'application/x-thrift' }
40
- resp, data = http.post(@url.path, @outbuf, headers)
46
+ resp, data = http.post(@url.request_uri, @outbuf, @headers)
41
47
  @inbuf = StringIO.new data
42
48
  @outbuf = ""
43
49
  end
@@ -88,9 +88,9 @@ module Thrift
88
88
  out << ">"
89
89
  end
90
90
 
91
- out << @buf[idx].to_s(16)
91
+ out << @buf[idx].ord.to_s(16)
92
92
  end
93
93
  out.join(" ")
94
94
  end
95
95
  end
96
- end
96
+ end
@@ -57,7 +57,7 @@ module Thrift
57
57
  when Types::STRING
58
58
  String
59
59
  when Types::STRUCT
60
- Struct
60
+ [Struct, Union]
61
61
  when Types::MAP
62
62
  Hash
63
63
  when Types::SET
@@ -0,0 +1,179 @@
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
+ module Thrift
21
+ class Union
22
+ def initialize(name=nil, value=nil)
23
+ if name
24
+ if name.is_a? Hash
25
+ if name.size > 1
26
+ raise "#{self.class} cannot be instantiated with more than one field!"
27
+ end
28
+
29
+ name, value = name.keys.first, name.values.first
30
+ end
31
+
32
+ if Thrift.type_checking
33
+ raise Exception, "#{self.class} does not contain a field named #{name}!" unless name_to_id(name.to_s)
34
+ end
35
+
36
+ if value.nil?
37
+ raise Exception, "Union #{self.class} cannot be instantiated with setfield and nil value!"
38
+ end
39
+
40
+ Thrift.check_type(value, struct_fields[name_to_id(name.to_s)], name) if Thrift.type_checking
41
+ elsif !value.nil?
42
+ raise Exception, "Value provided, but no name!"
43
+ end
44
+ @setfield = name
45
+ @value = value
46
+ end
47
+
48
+ def inspect
49
+ if get_set_field
50
+ "<#{self.class} #{@setfield}: #{inspect_field(@value, struct_fields[name_to_id(@setfield.to_s)])}>"
51
+ else
52
+ "<#{self.class} >"
53
+ end
54
+ end
55
+
56
+ def read(iprot)
57
+ iprot.read_struct_begin
58
+ fname, ftype, fid = iprot.read_field_begin
59
+ handle_message(iprot, fid, ftype)
60
+ iprot.read_field_end
61
+
62
+ fname, ftype, fid = iprot.read_field_begin
63
+ raise "Too many fields for union" unless (ftype == Types::STOP)
64
+
65
+ iprot.read_struct_end
66
+ validate
67
+ end
68
+
69
+ def write(oprot)
70
+ validate
71
+ oprot.write_struct_begin(self.class.name)
72
+
73
+ fid = self.name_to_id(@setfield.to_s)
74
+
75
+ field_info = struct_fields[fid]
76
+ type = field_info[:type]
77
+ if is_container? type
78
+ oprot.write_field_begin(@setfield, type, fid)
79
+ write_container(oprot, @value, field_info)
80
+ oprot.write_field_end
81
+ else
82
+ oprot.write_field(@setfield, type, fid, @value)
83
+ end
84
+
85
+ oprot.write_field_stop
86
+ oprot.write_struct_end
87
+ end
88
+
89
+ def ==(other)
90
+ other != nil && @setfield == other.get_set_field && @value == other.get_value
91
+ end
92
+
93
+ def eql?(other)
94
+ self.class == other.class && self == other
95
+ end
96
+
97
+ def hash
98
+ [self.class.name, @setfield, @value].hash
99
+ end
100
+
101
+ def self.field_accessor(klass, field_info)
102
+ klass.send :define_method, field_info[:name] do
103
+ if field_info[:name].to_sym == @setfield
104
+ @value
105
+ else
106
+ raise RuntimeError, "#{field_info[:name]} is not union's set field."
107
+ end
108
+ end
109
+
110
+ klass.send :define_method, "#{field_info[:name]}=" do |value|
111
+ Thrift.check_type(value, field_info, field_info[:name]) if Thrift.type_checking
112
+ @setfield = field_info[:name].to_sym
113
+ @value = value
114
+ end
115
+ end
116
+
117
+ def self.qmark_isset_method(klass, field_info)
118
+ klass.send :define_method, "#{field_info[:name]}?" do
119
+ get_set_field == field_info[:name].to_sym && !get_value.nil?
120
+ end
121
+ end
122
+
123
+ def self.generate_accessors(klass)
124
+ klass::FIELDS.values.each do |field_info|
125
+ field_accessor(klass, field_info)
126
+ qmark_isset_method(klass, field_info)
127
+ end
128
+ end
129
+
130
+ # get the symbol that indicates what the currently set field type is.
131
+ def get_set_field
132
+ @setfield
133
+ end
134
+
135
+ # get the current value of this union, regardless of what the set field is.
136
+ # generally, you should only use this method when you don't know in advance
137
+ # what field to expect.
138
+ def get_value
139
+ @value
140
+ end
141
+
142
+ def <=>(other)
143
+ if self.class == other.class
144
+ if get_set_field == other.get_set_field
145
+ if get_set_field.nil?
146
+ 0
147
+ else
148
+ get_value <=> other.get_value
149
+ end
150
+ else
151
+ if get_set_field && other.get_set_field.nil?
152
+ -1
153
+ elsif get_set_field.nil? && other.get_set_field
154
+ 1
155
+ elsif get_set_field.nil? && other.get_set_field.nil?
156
+ 0
157
+ else
158
+ name_to_id(get_set_field.to_s) <=> name_to_id(other.get_set_field.to_s)
159
+ end
160
+ end
161
+ else
162
+ self.class <=> other.class
163
+ end
164
+ end
165
+
166
+ protected
167
+
168
+ def handle_message(iprot, fid, ftype)
169
+ field = struct_fields[fid]
170
+ if field and field[:type] == ftype
171
+ @value = read_field(iprot, field)
172
+ name = field[:name].to_sym
173
+ @setfield = name
174
+ else
175
+ iprot.skip(ftype)
176
+ end
177
+ end
178
+ end
179
+ end
@@ -42,6 +42,26 @@ struct Hello {
42
42
  1: string greeting = "hello world"
43
43
  }
44
44
 
45
+ enum SomeEnum {
46
+ ONE
47
+ TWO
48
+ }
49
+
50
+ struct StructWithSomeEnum {
51
+ 1: SomeEnum some_enum;
52
+ }
53
+
54
+ union TestUnion {
55
+ /**
56
+ * A doc string
57
+ */
58
+ 1: string string_field;
59
+ 2: i32 i32_field;
60
+ 3: i32 other_i32_field;
61
+ 4: SomeEnum enum_field;
62
+ 5: binary binary_field;
63
+ }
64
+
45
65
  struct Foo {
46
66
  1: i32 simple = 53,
47
67
  2: string words = "words",
@@ -50,6 +70,11 @@ struct Foo {
50
70
  5: map<i32, map<string, double>> complex,
51
71
  6: set<i16> shorts = [5, 17, 239],
52
72
  7: optional string opt_string
73
+ 8: bool my_bool
74
+ }
75
+
76
+ struct Foo2 {
77
+ 1: binary my_binary
53
78
  }
54
79
 
55
80
  struct BoolStruct {
@@ -82,3 +107,26 @@ service NonblockingService {
82
107
  oneway void shutdown()
83
108
  void sleep(1:double seconds)
84
109
  }
110
+
111
+ union My_union {
112
+ 1: bool im_true,
113
+ 2: byte a_bite,
114
+ 3: i16 integer16,
115
+ 4: i32 integer32,
116
+ 5: i64 integer64,
117
+ 6: double double_precision,
118
+ 7: string some_characters,
119
+ 8: i32 other_i32
120
+ 9: SomeEnum some_enum;
121
+ 10: map<SomeEnum, list<SomeEnum>> my_map;
122
+ }
123
+
124
+ struct Struct_with_union {
125
+ 1: My_union fun_union
126
+ 2: i32 integer32
127
+ 3: string some_characters
128
+ }
129
+
130
+ struct StructWithEnumMap {
131
+ 1: map<SomeEnum, list<SomeEnum>> my_map;
132
+ }
@@ -20,22 +20,27 @@
20
20
  require File.dirname(__FILE__) + '/spec_helper'
21
21
  require File.dirname(__FILE__) + '/binary_protocol_spec_shared'
22
22
 
23
- class ThriftBinaryProtocolAcceleratedSpec < Spec::ExampleGroup
24
- include Thrift
23
+ if defined? Thrift::BinaryProtocolAccelerated
25
24
 
26
- describe Thrift::BinaryProtocolAccelerated do
27
- # since BinaryProtocolAccelerated should be directly equivalent to
28
- # BinaryProtocol, we don't need any custom specs!
29
- it_should_behave_like 'a binary protocol'
25
+ class ThriftBinaryProtocolAcceleratedSpec < Spec::ExampleGroup
26
+ include Thrift
30
27
 
31
- def protocol_class
32
- BinaryProtocolAccelerated
28
+ describe Thrift::BinaryProtocolAccelerated do
29
+ # since BinaryProtocolAccelerated should be directly equivalent to
30
+ # BinaryProtocol, we don't need any custom specs!
31
+ it_should_behave_like 'a binary protocol'
32
+
33
+ def protocol_class
34
+ BinaryProtocolAccelerated
35
+ end
33
36
  end
34
- end
35
37
 
36
- describe BinaryProtocolAcceleratedFactory do
37
- it "should create a BinaryProtocolAccelerated" do
38
- BinaryProtocolAcceleratedFactory.new.get_protocol(mock("MockTransport")).should be_instance_of(BinaryProtocolAccelerated)
38
+ describe BinaryProtocolAcceleratedFactory do
39
+ it "should create a BinaryProtocolAccelerated" do
40
+ BinaryProtocolAcceleratedFactory.new.get_protocol(mock("MockTransport")).should be_instance_of(BinaryProtocolAccelerated)
41
+ end
39
42
  end
40
43
  end
41
- end
44
+ else
45
+ puts "skipping BinaryProtocolAccelerated spec because it is not defined."
46
+ end
@@ -349,9 +349,9 @@ shared_examples_for 'a binary protocol' do
349
349
 
350
350
  # first block
351
351
  firstblock.call(client)
352
-
352
+
353
353
  processor.process(serverproto, serverproto)
354
-
354
+
355
355
  # second block
356
356
  secondblock.call(client)
357
357
  ensure
@@ -86,12 +86,12 @@ describe Thrift::CompactProtocol do
86
86
  it "should make method calls correctly" do
87
87
  client_out_trans = Thrift::MemoryBufferTransport.new
88
88
  client_out_proto = Thrift::CompactProtocol.new(client_out_trans)
89
-
89
+
90
90
  client_in_trans = Thrift::MemoryBufferTransport.new
91
91
  client_in_proto = Thrift::CompactProtocol.new(client_in_trans)
92
-
92
+
93
93
  processor = Srv::Processor.new(JankyHandler.new)
94
-
94
+
95
95
  client = Srv::Client.new(client_in_proto, client_out_proto)
96
96
  client.send_Janky(1)
97
97
  # puts client_out_trans.inspect_buffer
@@ -99,6 +99,22 @@ describe Thrift::CompactProtocol do
99
99
  client.recv_Janky.should == 2
100
100
  end
101
101
 
102
+ it "should deal with fields following fields that have non-delta ids" do
103
+ brcp = BreaksRubyCompactProtocol.new(
104
+ :field1 => "blah",
105
+ :field2 => BigFieldIdStruct.new(
106
+ :field1 => "string1",
107
+ :field2 => "string2"),
108
+ :field3 => 3)
109
+ ser = Thrift::Serializer.new(Thrift::CompactProtocolFactory.new)
110
+ bytes = ser.serialize(brcp)
111
+
112
+ deser = Thrift::Deserializer.new(Thrift::CompactProtocolFactory.new)
113
+ brcp2 = BreaksRubyCompactProtocol.new
114
+ deser.deserialize(brcp2, bytes)
115
+ brcp2.should == brcp
116
+ end
117
+
102
118
  class JankyHandler
103
119
  def Janky(i32arg)
104
120
  i32arg * 2
@@ -24,7 +24,7 @@ class ThriftHTTPClientTransportSpec < Spec::ExampleGroup
24
24
 
25
25
  describe HTTPClientTransport do
26
26
  before(:each) do
27
- @client = HTTPClientTransport.new("http://my.domain.com/path/to/service")
27
+ @client = HTTPClientTransport.new("http://my.domain.com/path/to/service?param=value")
28
28
  end
29
29
 
30
30
  it "should always be open" do
@@ -39,11 +39,26 @@ class ThriftHTTPClientTransportSpec < Spec::ExampleGroup
39
39
  Net::HTTP.should_receive(:new).with("my.domain.com", 80).and_return do
40
40
  mock("Net::HTTP").tee do |http|
41
41
  http.should_receive(:use_ssl=).with(false)
42
- http.should_receive(:post).with("/path/to/service", "a test frame", {"Content-Type"=>"application/x-thrift"}).and_return([nil, "data"])
42
+ http.should_receive(:post).with("/path/to/service?param=value", "a test frame", {"Content-Type"=>"application/x-thrift"}).and_return([nil, "data"])
43
43
  end
44
44
  end
45
45
  @client.flush
46
46
  @client.read(10).should == "data"
47
47
  end
48
+
49
+ it "should send custom headers if defined" do
50
+ @client.write "test"
51
+ custom_headers = {"Cookie" => "Foo"}
52
+ headers = {"Content-Type"=>"application/x-thrift"}.merge(custom_headers)
53
+
54
+ @client.add_headers(custom_headers)
55
+ Net::HTTP.should_receive(:new).with("my.domain.com", 80).and_return do
56
+ mock("Net::HTTP").tee do |http|
57
+ http.should_receive(:use_ssl=).with(false)
58
+ http.should_receive(:post).with("/path/to/service?param=value", "test", headers).and_return([nil, "data"])
59
+ end
60
+ end
61
+ @client.flush
62
+ end
48
63
  end
49
64
  end