thrift 0.2.0.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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