riak-client 2.4.0 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,5 @@
1
1
  module Riak
2
2
  module Crdt
3
-
4
3
  # A distributed map of multiple fields, such as counters, flags, registers,
5
4
  # sets, and, recursively, other maps, using the Riak 2 Data Types feature.
6
5
  #
@@ -1,3 +1,5 @@
1
+ require 'riak/util/string'
2
+
1
3
  module Riak
2
4
  module Crdt
3
5
 
@@ -6,6 +8,7 @@ module Riak
6
8
  # Uses the Ruby standard library `::Set` frequently, so the full class names will
7
9
  # be used frequently.
8
10
  class Set < Base
11
+ include Util::String
9
12
 
10
13
  # Create a set instance. The bucket type is determined by the first of
11
14
  # these sources:
@@ -73,7 +76,7 @@ module Riak
73
76
  # @param [String] candidate string to check for inclusion in this structure
74
77
  # @return [Boolean] if the structure includes
75
78
  def include?(candidate)
76
- members.include?(candidate)
79
+ members.any? { |m| equal_bytes?(m, candidate) }
77
80
  end
78
81
 
79
82
  # Add a {String} to the {Riak::Crdt::Set}
@@ -74,7 +74,7 @@ module Riak
74
74
  # @param [String] key the key to get the value for
75
75
  # @return the value for the given key
76
76
  def [](key)
77
- key = normalize_key key
77
+ key = normalize_key(key)
78
78
  if include? key
79
79
  candidate = @contents[key]
80
80
  return candidate unless candidate.respond_to? :parent
@@ -97,7 +97,7 @@ module Riak
97
97
  # @param [Boolean, String, Integer] value the value to set at the key,
98
98
  # or in the case of counters, the amount to increment
99
99
  def []=(key, value)
100
- key = normalize_key key
100
+ key = normalize_key(key)
101
101
 
102
102
  operation = @type.update value
103
103
  operation.name = key
@@ -112,11 +112,15 @@ module Riak
112
112
 
113
113
  alias_method :increment, :[]=
114
114
 
115
+ def length
116
+ @contents.length
117
+ end
118
+
115
119
  # Remove the entry from the map.
116
120
  #
117
121
  # @param [String] key the key to remove from the map
118
122
  def delete(key)
119
- key = normalize_key key
123
+ key = normalize_key(key)
120
124
  operation = @type.delete
121
125
  operation.name = key
122
126
 
@@ -127,7 +131,7 @@ module Riak
127
131
 
128
132
  # @api private
129
133
  def operate(key, inner_operation)
130
- key = normalize_key key
134
+ key = normalize_key(key)
131
135
 
132
136
  inner_operation.name = key
133
137
 
@@ -152,7 +156,7 @@ module Riak
152
156
  private
153
157
 
154
158
  def normalize_key(unnormalized_key)
155
- unnormalized_key.to_s
159
+ unnormalized_key.to_s.dup.force_encoding('binary')
156
160
  end
157
161
 
158
162
  def initialize_nil?
@@ -0,0 +1,31 @@
1
+ module Riak
2
+ module Util
3
+ # Methods comparing strings
4
+ module String
5
+ def equal_bytes?(a, b)
6
+ return true if a.nil? && b.nil?
7
+
8
+ return false unless a.respond_to?(:bytesize)
9
+ return false unless b.respond_to?(:bytesize)
10
+ return false unless a.bytesize == b.bytesize
11
+
12
+ return false unless a.respond_to?(:bytes)
13
+ return false unless b.respond_to?(:bytes)
14
+
15
+ b1 = a.bytes.to_a
16
+ b2 = b.bytes.to_a
17
+ i = 0
18
+ loop do
19
+ c1 = b1[i]
20
+ c2 = b2[i]
21
+ return false unless c1 == c2
22
+ i += 1
23
+ break if i > b1.length
24
+ end
25
+ true
26
+ end
27
+
28
+ module_function :equal_bytes?
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  module Riak
2
- VERSION = "2.4.0"
2
+ VERSION = "2.4.1"
3
3
  end
@@ -15,19 +15,20 @@ Gem::Specification.new do |gem|
15
15
  gem.required_ruby_version = '>= 1.9.3'
16
16
 
17
17
  # Deps
18
- gem.add_development_dependency 'rspec', '~> 3.0'
19
- gem.add_development_dependency 'rake', '~> 10.1'
20
- gem.add_development_dependency 'yard', '~> 0.8'
18
+ gem.add_development_dependency 'activesupport', '~> 4.2'
19
+ gem.add_development_dependency 'instrumentable', '~> 1.1'
21
20
  gem.add_development_dependency 'kramdown', '~> 1.4'
21
+ gem.add_development_dependency 'rake', '~> 10.1'
22
+ gem.add_development_dependency 'rspec', '~> 3.0'
23
+ gem.add_development_dependency 'rubocop', '~> 0.40.0'
22
24
  gem.add_development_dependency 'simplecov', '~> 0.10'
23
- gem.add_development_dependency 'instrumentable', '~> 1.1'
24
- gem.add_development_dependency 'rubocop', '~> 0.40'
25
+ gem.add_development_dependency 'yard', '~> 0.8'
25
26
 
26
- gem.add_runtime_dependency 'i18n', '~> 0.6'
27
27
  gem.add_runtime_dependency 'beefcake', '~> 1.1'
28
- gem.add_runtime_dependency 'multi_json', '~> 1.0'
29
- gem.add_runtime_dependency 'innertube', '~> 1.0'
30
28
  gem.add_runtime_dependency 'cert_validator', '~> 0.0.1'
29
+ gem.add_runtime_dependency 'i18n', '~> 0.6'
30
+ gem.add_runtime_dependency 'innertube', '~> 1.0'
31
+ gem.add_runtime_dependency 'multi_json', '~> 1.0'
31
32
 
32
33
  # Files
33
34
 
@@ -1,6 +1,7 @@
1
1
  # coding: utf-8
2
2
  require 'spec_helper'
3
3
  require 'riak'
4
+ require 'riak/util/string'
4
5
 
5
6
  describe 'Encoding and CRDTs', integration: true, search_config: true do
6
7
  shared_examples 'CRDTs with weird names' do
@@ -16,6 +17,7 @@ describe 'Encoding and CRDTs', integration: true, search_config: true do
16
17
 
17
18
  it 'creates counters' do
18
19
  counter = nil
20
+
19
21
  expect{ counter = Riak::Crdt::Counter.new counter_bucket, random_string }.
20
22
  to_not raise_error
21
23
 
@@ -24,44 +26,61 @@ describe 'Encoding and CRDTs', integration: true, search_config: true do
24
26
  expect(value = counter.value).to be_a Numeric
25
27
 
26
28
  expect{ counter.increment }.to_not raise_error
29
+
27
30
  expect(counter.value).to eq value + 1
28
31
  end
29
32
 
30
33
  it 'updates registers in maps' do
31
34
  map = nil
35
+
36
+ expect(random_string.encoding.name).to eq expected_encoding
37
+
32
38
  expect{ map = Riak::Crdt::Map.new map_bucket, random_string }.
33
39
  to_not raise_error
34
40
 
35
41
  expect(map).to be_a Riak::Crdt::Map
36
42
 
37
43
  expect(map.registers[random_string]).to be_nil
44
+
38
45
  expect{ map.registers[random_string] = random_string }.
39
46
  to_not raise_error
40
47
 
41
- expect(map.registers[random_string]).to eq random_string
48
+ expect(map.registers.length).to eq 1
49
+
50
+ expect(map.registers[random_string]).to_not be_nil
51
+
52
+ expect(Riak::Util::String.equal_bytes?(map.registers[random_string], random_string)).to be
53
+
54
+ expect(random_string.encoding.name).to eq expected_encoding
42
55
  end
43
56
 
44
57
  it 'updates sets' do
45
58
  set = nil
59
+
60
+ expect(random_string.encoding.name).to eq expected_encoding
61
+
46
62
  expect{ set = Riak::Crdt::Set.new set_bucket, random_string }.
47
63
  to_not raise_error
48
64
 
49
65
  expect(set).to be_a Riak::Crdt::Set
50
66
 
51
- expect(set.members).to_not include random_string
67
+ expect(set.include?(random_string)).to_not be
52
68
 
53
69
  set.add random_string
54
70
 
55
- expect(set.members).to include random_string
71
+ expect(set.include?(random_string)).to be
56
72
 
57
73
  set.remove random_string
58
74
 
59
- expect(set.members).to_not include random_string
75
+ expect(set.include?(random_string)).to_not be
76
+
77
+ expect(random_string.encoding.name).to eq expected_encoding
60
78
  end
61
79
  end
62
80
 
63
81
  describe 'with utf-8 strings' do
64
82
  let(:string){ "\xF0\x9F\x9A\xB4こんにちはสวัสดี" }
83
+ let(:expected_encoding){ 'UTF-8' }
65
84
  let(:random_string){ string + random_key }
66
85
 
67
86
  include_examples 'CRDTs with weird names'
@@ -69,6 +88,7 @@ describe 'Encoding and CRDTs', integration: true, search_config: true do
69
88
 
70
89
  describe 'with binary strings' do
71
90
  let(:string){ "\xff\xff".force_encoding('binary') }
91
+ let(:expected_encoding){ 'ASCII-8BIT' }
72
92
  let(:random_string){ string + random_key }
73
93
 
74
94
  include_examples 'CRDTs with weird names'
@@ -5,170 +5,174 @@ require 'riak/client/beefcake/messages'
5
5
  require 'riak/client/beefcake/protocol'
6
6
 
7
7
  describe 'Protocol Buffers', test_client: true, integration: true do
8
- describe 'timeouts' do
9
- it 'raises error on connect timeout' do
10
- # unroutable TEST-NET (https://tools.ietf.org/html/rfc5737)
11
- config = {}
12
- config[:host] = '192.0.2.0'
13
- config[:pb_port] = 65535
14
-
15
- config[:connect_timeout] = 0.0001
16
- client = Riak::Client.new(config)
17
-
18
- expect do
19
- client.ping
20
- end.to raise_error RuntimeError, /timed out/
21
- end
22
-
23
- it 'raises error on read timeout' do
24
- ok_to_continue = false
25
- quitting = false
26
- port = 0
8
+ if RUBY_VERSION >= '2.0.0'
9
+ describe 'timeouts' do
10
+ it 'raises error on connect timeout' do
11
+ # unroutable TEST-NET (https://tools.ietf.org/html/rfc5737)
12
+ config = {}
13
+ config[:host] = '192.0.2.0'
14
+ config[:pb_port] = 65535
15
+
16
+ config[:connect_timeout] = 0.0001
17
+ client = Riak::Client.new(config)
18
+
19
+ expect do
20
+ client.ping
21
+ end.to raise_error RuntimeError, /timed out/
22
+ end
27
23
 
28
- server = nil
29
- thr = Thread.new do
30
- server = TCPServer.new port
31
- port = server.addr[1]
32
- ok_to_continue = true
33
- loop do
34
- begin
35
- Thread.start(server.accept) do |s|
36
- loop do
37
- p = Riak::Client::BeefcakeProtobuffsBackend::Protocol.new s
38
- begin
39
- msgname, _body = p.receive
40
- rescue IOError
41
- break if quitting
42
- raise
43
- end
44
- case msgname
45
- when :PingReq
46
- sleep 0.5
47
- p.write :PingResp
48
- else
49
- $stderr.puts("unknown msgname: #{msgname}")
24
+ it 'raises error on read timeout' do
25
+ ok_to_continue = false
26
+ quitting = false
27
+ port = 0
28
+
29
+ server = nil
30
+ thr = Thread.new do
31
+ server = TCPServer.new port
32
+ port = server.addr[1]
33
+ ok_to_continue = true
34
+ loop do
35
+ begin
36
+ Thread.start(server.accept) do |s|
37
+ loop do
38
+ p = Riak::Client::BeefcakeProtobuffsBackend::Protocol.new s
39
+ begin
40
+ msgname, _body = p.receive
41
+ rescue IOError
42
+ break if quitting
43
+ raise
44
+ end
45
+ case msgname
46
+ when :PingReq
47
+ sleep 0.5
48
+ p.write :PingResp
49
+ else
50
+ $stderr.puts("unknown msgname: #{msgname}")
51
+ end
50
52
  end
51
53
  end
54
+ rescue IOError
55
+ break if quitting
56
+ raise
52
57
  end
53
- rescue IOError
54
- break if quitting
55
- raise
56
58
  end
57
59
  end
58
- end
59
60
 
60
- loop do
61
- break if ok_to_continue
62
- sleep 0.1
63
- end
64
- ok_to_continue = false
65
-
66
- config = {}
67
- config[:pb_port] = port
68
- config[:client_id] = port
69
- config[:read_timeout] = 0.0001
70
- client = Riak::Client.new(config)
71
-
72
- max_ping_attempts = 16
73
- ping_count = 0
74
- loop do
75
- begin
76
- client.ping
77
- ping_count += 1
78
- break if ping_count > max_ping_attempts
79
- rescue RuntimeError => e
80
- break if e.message =~ /timed out/
61
+ loop do
62
+ break if ok_to_continue
63
+ sleep 0.1
81
64
  end
82
- sleep 0.5
83
- end
84
-
85
- quitting = true
86
- server.close
87
- thr.join
65
+ ok_to_continue = false
88
66
 
89
- expect(ping_count).to be < max_ping_attempts
90
- end
91
-
92
- it 'raises error on write timeout' do
93
- ok_to_continue = false
94
- quitting = false
95
- port = 0
67
+ config = {}
68
+ config[:pb_port] = port
69
+ config[:client_id] = port
70
+ config[:read_timeout] = 0.0001
71
+ client = Riak::Client.new(config)
96
72
 
97
- server = nil
98
- thr = Thread.new do
99
- server = TCPServer.new port
100
- port = server.addr[1]
101
- ok_to_continue = true
73
+ max_ping_attempts = 16
74
+ ping_count = 0
102
75
  loop do
103
76
  begin
104
- Thread.start(server.accept) do |s|
105
- loop do
106
- p = Riak::Client::BeefcakeProtobuffsBackend::Protocol.new s
107
- begin
108
- msgname, _body = p.receive
109
- rescue IOError
110
- break if quitting
111
- raise
112
- end
113
- case msgname
114
- when :PingReq
115
- p.write :PingResp
116
- when :GetServerInfoReq
117
- r = Riak::Client::BeefcakeProtobuffsBackend::RpbGetServerInfoResp.new
118
- r.node = 'dev1@127.0.0.1'.force_encoding('BINARY')
119
- r.server_version = '2.1.4'.force_encoding('BINARY')
120
- p.write :GetServerInfoResp, r
121
- when :PutReq
122
- r = Riak::Client::BeefcakeProtobuffsBackend::RpbPutResp.new
123
- p.write :PutResp, r
124
- else
125
- $stderr.puts("unknown msgname: #{msgname}")
77
+ client.ping
78
+ ping_count += 1
79
+ break if ping_count > max_ping_attempts
80
+ rescue RuntimeError => e
81
+ break if e.message =~ /timed out/
82
+ end
83
+ sleep 0.5
84
+ end
85
+
86
+ quitting = true
87
+ server.close
88
+ thr.join
89
+
90
+ expect(ping_count).to be < max_ping_attempts
91
+ end
92
+
93
+ it 'raises error on write timeout' do
94
+ ok_to_continue = false
95
+ quitting = false
96
+ port = 0
97
+
98
+ server = nil
99
+ thr = Thread.new do
100
+ server = TCPServer.new port
101
+ port = server.addr[1]
102
+ ok_to_continue = true
103
+ loop do
104
+ begin
105
+ Thread.start(server.accept) do |s|
106
+ loop do
107
+ p = Riak::Client::BeefcakeProtobuffsBackend::Protocol.new s
108
+ begin
109
+ msgname, _body = p.receive
110
+ rescue IOError
111
+ break if quitting
112
+ raise
113
+ end
114
+ case msgname
115
+ when :PingReq
116
+ p.write :PingResp
117
+ when :GetServerInfoReq
118
+ r = Riak::Client::BeefcakeProtobuffsBackend::RpbGetServerInfoResp.new
119
+ r.node = 'dev1@127.0.0.1'.force_encoding('BINARY')
120
+ r.server_version = '2.1.4'.force_encoding('BINARY')
121
+ p.write :GetServerInfoResp, r
122
+ when :PutReq
123
+ r = Riak::Client::BeefcakeProtobuffsBackend::RpbPutResp.new
124
+ p.write :PutResp, r
125
+ else
126
+ $stderr.puts("unknown msgname: #{msgname}")
127
+ end
126
128
  end
127
129
  end
130
+ rescue IOError
131
+ break if quitting
132
+ raise
128
133
  end
129
- rescue IOError
130
- break if quitting
131
- raise
132
134
  end
133
135
  end
134
- end
135
136
 
136
- loop do
137
- break if ok_to_continue
138
- sleep 0.1
139
- end
140
- ok_to_continue = false
141
-
142
- config = {}
143
- config[:pb_port] = port
144
- config[:client_id] = port
145
- config[:write_timeout] = 0.0001
146
- client = Riak::Client.new(config)
147
-
148
- bucket = client.bucket('timeouts')
149
-
150
- max_store_attempts = 16
151
- store_count = 0
152
- loop do
153
- begin
154
- obj = bucket.new "obj-#{store_count}"
155
- # write enough data to grow beyond socket buffer capacity
156
- obj.data = SecureRandom.urlsafe_base64(10_000_000)
157
- obj.content_type = 'text/plain'
158
- obj.store
159
- store_count += 1
160
- break if store_count > max_store_attempts
161
- rescue RuntimeError => e
162
- break if e.message =~ /timed out/
137
+ loop do
138
+ break if ok_to_continue
139
+ sleep 0.1
163
140
  end
164
- sleep 0.5
165
- end
141
+ ok_to_continue = false
166
142
 
167
- quitting = true
168
- server.close
169
- thr.join
143
+ config = {}
144
+ config[:pb_port] = port
145
+ config[:client_id] = port
146
+ config[:write_timeout] = 0.0001
147
+ client = Riak::Client.new(config)
170
148
 
171
- expect(store_count).to be < max_store_attempts
149
+ bucket = client.bucket('timeouts')
150
+
151
+ max_store_attempts = 16
152
+ store_count = 0
153
+ loop do
154
+ begin
155
+ obj = bucket.new "obj-#{store_count}"
156
+ # write enough data to grow beyond socket buffer capacity
157
+ obj.data = SecureRandom.urlsafe_base64(10_000_000)
158
+ obj.content_type = 'text/plain'
159
+ obj.store
160
+ store_count += 1
161
+ break if store_count > max_store_attempts
162
+ rescue RuntimeError => e
163
+ break if e.message =~ /timed out/
164
+ end
165
+ sleep 0.5
166
+ end
167
+
168
+ quitting = true
169
+ server.close
170
+ thr.join
171
+
172
+ expect(store_count).to be < max_store_attempts
173
+ end
172
174
  end
175
+ else
176
+ skip 'not supported in this version of Ruby'
173
177
  end
174
178
  end