aerospike 2.6.0 → 2.7.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +3 -1
  4. data/lib/aerospike.rb +9 -5
  5. data/lib/aerospike/client.rb +101 -83
  6. data/lib/aerospike/cluster.rb +11 -50
  7. data/lib/aerospike/cluster/create_connection.rb +1 -1
  8. data/lib/aerospike/cluster/find_nodes_to_remove.rb +66 -0
  9. data/lib/aerospike/cluster/partition.rb +5 -2
  10. data/lib/aerospike/command/batch_direct_command.rb +104 -0
  11. data/lib/aerospike/command/batch_direct_exists_command.rb +51 -0
  12. data/lib/aerospike/command/batch_direct_node.rb +40 -0
  13. data/lib/aerospike/command/batch_index_command.rb +119 -0
  14. data/lib/aerospike/command/batch_index_exists_command.rb +45 -0
  15. data/lib/aerospike/command/batch_index_node.rb +52 -0
  16. data/lib/aerospike/command/batch_item.rb +18 -47
  17. data/lib/aerospike/command/command.rb +6 -65
  18. data/lib/aerospike/command/field_type.rb +13 -10
  19. data/lib/aerospike/command/{batch_command.rb → multi_command.rb} +29 -9
  20. data/lib/aerospike/command/read_command.rb +4 -2
  21. data/lib/aerospike/command/single_command.rb +6 -9
  22. data/lib/aerospike/connection/create.rb +3 -3
  23. data/lib/aerospike/host/parse.rb +28 -2
  24. data/lib/aerospike/node.rb +6 -2
  25. data/lib/aerospike/node/refresh/friends.rb +1 -1
  26. data/lib/aerospike/node/refresh/peers.rb +1 -1
  27. data/lib/aerospike/node_validator.rb +3 -3
  28. data/lib/aerospike/peers.rb +4 -0
  29. data/lib/aerospike/peers/parse.rb +26 -6
  30. data/lib/aerospike/policy/batch_policy.rb +25 -15
  31. data/lib/aerospike/policy/client_policy.rb +2 -2
  32. data/lib/aerospike/policy/query_policy.rb +25 -12
  33. data/lib/aerospike/policy/scan_policy.rb +39 -16
  34. data/lib/aerospike/query/stream_command.rb +6 -5
  35. data/lib/aerospike/record.rb +4 -3
  36. data/lib/aerospike/socket/ssl.rb +13 -13
  37. data/lib/aerospike/socket/tcp.rb +8 -1
  38. data/lib/aerospike/utils/string_parser.rb +7 -3
  39. data/lib/aerospike/version.rb +1 -1
  40. metadata +11 -7
  41. data/lib/aerospike/command/batch_command_exists.rb +0 -93
  42. data/lib/aerospike/command/batch_command_get.rb +0 -84
  43. data/lib/aerospike/command/batch_node.rb +0 -82
@@ -0,0 +1,45 @@
1
+ # Copyright 2018 Aerospike, Inc.
2
+ #
3
+ # Portions may be licensed to Aerospike, Inc. under one or more contributor
4
+ # license agreements.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # 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, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+
18
+ require 'aerospike/command/batch_index_command'
19
+
20
+ module Aerospike
21
+
22
+ class BatchIndexExistsCommand < BatchIndexCommand #:nodoc:
23
+
24
+ def initialize(node, batch, policy, results)
25
+ super(node, batch, policy, nil, results, INFO1_READ | INFO1_NOBINDATA)
26
+ end
27
+
28
+ # Parse all results in the batch. Add records to shared list.
29
+ # If the record was not found, the bins will be nil.
30
+ def parse_row(result_code)
31
+ batch_index = @data_buffer.read_int32(14)
32
+ field_count = @data_buffer.read_int16(18)
33
+ op_count = @data_buffer.read_int16(20)
34
+
35
+ if op_count > 0
36
+ raise Aerospike::Exceptions::Parse.new('Received bins that were not requested!')
37
+ end
38
+
39
+ parse_key(field_count)
40
+ results[batch_index] = (result_code == 0)
41
+ end
42
+
43
+ end # class
44
+
45
+ end # module
@@ -0,0 +1,52 @@
1
+ # Copyright 2018 Aerospike, Inc.
2
+ #
3
+ # Portions may be licensed to Aerospike, Inc. under one or more contributor
4
+ # license agreements.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # 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, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+
18
+ module Aerospike
19
+
20
+ class BatchIndexNode #:nodoc:
21
+
22
+ attr_accessor :node
23
+ attr_accessor :keys_by_idx
24
+
25
+ def self.generate_list(cluster, keys)
26
+ keys.each_with_index
27
+ .group_by { |key, _| cluster.get_node_for_key(key) }
28
+ .map { |node, keys_with_idx| BatchIndexNode.new(node, keys_with_idx) }
29
+ end
30
+
31
+ def initialize(node, keys_with_idx)
32
+ @node = node
33
+ @keys_by_idx = Hash[keys_with_idx.map(&:reverse)]
34
+ end
35
+
36
+ def keys
37
+ keys_by_idx.values
38
+ end
39
+
40
+ def each_key_with_index
41
+ keys_by_idx.each do |idx, key|
42
+ yield key, idx
43
+ end
44
+ end
45
+
46
+ def key_for_index(idx)
47
+ keys_by_idx[idx]
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -1,12 +1,13 @@
1
- # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
1
+ # Copyright 2014-2018 Aerospike, Inc.
3
2
  #
4
3
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
4
  # license agreements.
6
5
  #
7
6
  # Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
7
  # use this file except in compliance with the License. You may obtain a copy of
9
- # the License at http:#www.apache.org/licenses/LICENSE-2.0
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
10
11
  #
11
12
  # Unless required by applicable law or agreed to in writing, software
12
13
  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
@@ -14,61 +15,31 @@
14
15
  # License for the specific language governing permissions and limitations under
15
16
  # the License.
16
17
 
17
- require 'thread'
18
-
19
- require 'aerospike/record'
20
-
21
- require 'aerospike/command/command'
22
-
23
18
  module Aerospike
24
19
 
25
- private
26
-
27
20
  class BatchItem #:nodoc:
28
21
 
29
- def self.generate_map(keys)
30
- key_map = {}
31
- keys.each_with_index do |key, i|
32
- item = key_map[key.digest]
33
- unless item
34
- item = BatchItem.new(key, i)
35
- key_map[key.digest] = item
36
- else
37
- item.add_duplicate(i)
38
- end
39
- end
22
+ attr_accessor :key
23
+ attr_accessor :indexes
40
24
 
41
- key_map
25
+ def self.generate_map(keys)
26
+ map = keys.each_with_index
27
+ .group_by { |key, _| key }
28
+ .map { |key, keys_with_idx|
29
+ [key.digest, BatchItem.new(key, keys_with_idx.map(&:last))]
30
+ }
31
+ Hash[map]
42
32
  end
43
33
 
44
-
45
- def initialize(key, index)
34
+ def initialize(key, indexes)
46
35
  @key = key
47
- @index = index
48
- end
49
-
50
- def add_duplicate(idx)
51
- unless @duplicates
52
- @duplicates = []
53
- @duplicates << @index
54
- @index = 0
55
- end
56
-
57
- @duplicates << idx
36
+ @indexes = indexes
58
37
  end
59
38
 
60
39
  def index
61
- return @index unless @duplicates
62
-
63
- r = @duplicates[@index]
64
- @index+=1
65
- return r
66
- end
67
-
68
- def key
69
- @key
40
+ indexes.shift
70
41
  end
71
42
 
72
- end # class
43
+ end
73
44
 
74
- end # module
45
+ end
@@ -1,12 +1,13 @@
1
- # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
1
+ # Copyright 2014-2018 Aerospike, Inc.
3
2
  #
4
3
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
4
  # license agreements.
6
5
  #
7
6
  # Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
7
  # use this file except in compliance with the License. You may obtain a copy of
9
- # the License at http:#www.apache.org/licenses/LICENSE-2.0
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
10
11
  #
11
12
  # Unless required by applicable law or agreed to in writing, software
12
13
  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
@@ -16,7 +17,6 @@
16
17
 
17
18
  require 'time'
18
19
 
19
-
20
20
  require 'msgpack'
21
21
  require 'aerospike/result_code'
22
22
  require 'aerospike/command/field_type'
@@ -34,6 +34,8 @@ module Aerospike
34
34
  # Get all bins.
35
35
  INFO1_GET_ALL = Integer(1 << 1)
36
36
 
37
+
38
+ INFO1_BATCH = Integer(1 << 3)
37
39
  # Do not read the bins
38
40
  INFO1_NOBINDATA = Integer(1 << 5)
39
41
 
@@ -257,67 +259,6 @@ module Aerospike
257
259
  end_cmd
258
260
  end
259
261
 
260
- def set_batch_exists(policy, batch_namespace)
261
- # Estimate buffer size
262
- begin_cmd
263
- keys = batch_namespace.keys
264
- byte_size = keys.length * DIGEST_SIZE
265
-
266
- @data_offset += (batch_namespace ? batch_namespace.namespace.bytesize : 0) +
267
- FIELD_HEADER_SIZE + byte_size + FIELD_HEADER_SIZE
268
-
269
- size_buffer
270
-
271
- write_header(policy, INFO1_READ|INFO1_NOBINDATA, 0, 2, 0)
272
- write_field_string(batch_namespace.namespace, Aerospike::FieldType::NAMESPACE)
273
- write_field_header(byte_size, Aerospike::FieldType::DIGEST_RIPE_ARRAY)
274
-
275
- keys.each do |key|
276
- @data_buffer.write_binary(key.digest, @data_offset)
277
- @data_offset += key.digest.bytesize
278
- end
279
- end_cmd
280
- end
281
-
282
- def set_batch_get(policy, batch_namespace, bin_names, read_attr)
283
- # Estimate buffer size
284
- begin_cmd
285
- byte_size = batch_namespace.keys.length * DIGEST_SIZE
286
-
287
- @data_offset += batch_namespace.namespace.bytesize +
288
- FIELD_HEADER_SIZE + byte_size + FIELD_HEADER_SIZE
289
-
290
- if bin_names
291
- bin_names.each do |bin_name|
292
- estimate_operation_size_for_bin_name(bin_name)
293
- end
294
- end
295
-
296
- size_buffer
297
-
298
- operation_count = 0
299
- if bin_names
300
- operation_count = bin_names.length
301
- end
302
-
303
- write_header(policy, read_attr, 0, 2, operation_count)
304
- write_field_string(batch_namespace.namespace, Aerospike::FieldType::NAMESPACE)
305
- write_field_header(byte_size, Aerospike::FieldType::DIGEST_RIPE_ARRAY)
306
-
307
- batch_namespace.keys.each do |key|
308
- @data_buffer.write_binary(key.digest, @data_offset)
309
- @data_offset += key.digest.bytesize
310
- end
311
-
312
- if bin_names
313
- bin_names.each do |bin_name|
314
- write_operation_for_bin_name(bin_name, Aerospike::Operation::READ)
315
- end
316
- end
317
-
318
- end_cmd
319
- end
320
-
321
262
  def set_scan(policy, namespace, set_name, bin_names)
322
263
  # Estimate buffer size
323
264
  begin_cmd
@@ -1,17 +1,19 @@
1
- # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
1
+ # Copyright 2014-2018 Aerospike, Inc.
3
2
  #
4
- # Licensed under the Apache License, Version 2.0 (the "License")
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
3
+ # Portions may be licensed to Aerospike, Inc. under one or more contributor
4
+ # license agreements.
7
5
  #
8
- # http:#www.apache.org/licenses/LICENSE-2.0
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
9
11
  #
10
12
  # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
15
17
 
16
18
  module Aerospike
17
19
 
@@ -40,6 +42,7 @@ module Aerospike
40
42
  UDF_ARGLIST = 32
41
43
  UDF_OP = 33
42
44
  QUERY_BINLIST = 40
45
+ BATCH_INDEX = 41
43
46
 
44
47
  end # module
45
48
 
@@ -1,12 +1,13 @@
1
- # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
1
+ # Copyright 2014-2018 Aerospike, Inc.
3
2
  #
4
3
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
4
  # license agreements.
6
5
  #
7
6
  # Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
7
  # use this file except in compliance with the License. You may obtain a copy of
9
- # the License at http:#www.apache.org/licenses/LICENSE-2.0
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
10
11
  #
11
12
  # Unless required by applicable law or agreed to in writing, software
12
13
  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
@@ -14,17 +15,13 @@
14
15
  # License for the specific language governing permissions and limitations under
15
16
  # the License.
16
17
 
17
- require 'thread'
18
-
19
18
  require 'aerospike/record'
20
19
 
21
20
  require 'aerospike/command/command'
22
21
 
23
22
  module Aerospike
24
23
 
25
- private
26
-
27
- class BatchCommand < Command #:nodoc:
24
+ class MultiCommand < Command #:nodoc:
28
25
 
29
26
  def initialize(node)
30
27
  super(node)
@@ -48,13 +45,36 @@ module Aerospike
48
45
  receive_size = size & 0xFFFFFFFFFFFF
49
46
 
50
47
  if receive_size > 0
51
- status = parse_record_results(receive_size)
48
+ status = parse_group(receive_size)
52
49
  else
53
50
  status = false
54
51
  end
55
52
  end
56
53
  end
57
54
 
55
+ def parse_group(receive_size)
56
+ @data_offset = 0
57
+
58
+ while @data_offset < receive_size
59
+ read_bytes(MSG_REMAINING_HEADER_SIZE)
60
+ result_code = @data_buffer.read(5).ord & 0xFF
61
+
62
+ # The only valid server return codes are "ok" and "not found".
63
+ # If other return codes are received, then abort the batch.
64
+ if result_code != 0 && result_code != Aerospike::ResultCode::KEY_NOT_FOUND_ERROR
65
+ raise Aerospike::Exceptions::Aerospike.new(result_code)
66
+ end
67
+
68
+ # If cmd is the end marker of the response, do not proceed further
69
+ info3 = @data_buffer.read(3).ord
70
+ return false if (info3 & INFO3_LAST) == INFO3_LAST
71
+
72
+ parse_row(result_code)
73
+ end
74
+
75
+ true
76
+ end
77
+
58
78
  def parse_key(field_count)
59
79
  # in Stream queries, there are no keys
60
80
  return unless field_count > 0
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  # Copyright 2014-2017 Aerospike, Inc.
3
4
  #
4
5
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
@@ -25,6 +26,7 @@ module Aerospike
25
26
  private
26
27
 
27
28
  class ReadCommand < SingleCommand #:nodoc:
29
+ BIN_NAME_ENCODING = 'utf-8'
28
30
 
29
31
  attr_reader :record, :policy
30
32
 
@@ -127,7 +129,7 @@ module Aerospike
127
129
  op_size = @data_buffer.read_int32(receive_offset)
128
130
  particle_type = @data_buffer.read(receive_offset+5).ord
129
131
  name_size = @data_buffer.read(receive_offset+7).ord
130
- name = @data_buffer.read(receive_offset+8, name_size).force_encoding('utf-8')
132
+ name = @data_buffer.read(receive_offset+8, name_size).force_encoding(BIN_NAME_ENCODING)
131
133
  receive_offset += 4 + 4 + name_size
132
134
 
133
135
  particle_bytes_size = op_size - (4 + name_size)
@@ -1,12 +1,13 @@
1
- # encoding: utf-8
2
- # Copyright 2014-2017 Aerospike, Inc.
1
+ # Copyright 2014-2018 Aerospike, Inc.
3
2
  #
4
3
  # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
4
  # license agreements.
6
5
  #
7
6
  # Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
7
  # use this file except in compliance with the License. You may obtain a copy of
9
- # the License at http:#www.apache.org/licenses/LICENSE-2.0
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
10
11
  #
11
12
  # Unless required by applicable law or agreed to in writing, software
12
13
  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
@@ -14,7 +15,6 @@
14
15
  # License for the specific language governing permissions and limitations under
15
16
  # the License.
16
17
 
17
- require 'aerospike/cluster/partition'
18
18
  require 'aerospike/command/command'
19
19
 
20
20
  module Aerospike
@@ -26,14 +26,11 @@ module Aerospike
26
26
  def initialize(cluster, key)
27
27
  @cluster = cluster
28
28
  @key = key
29
- @partition = Partition.new_by_key(key)
30
-
31
- super(@cluster.get_node(@partition))
32
29
 
33
- self
30
+ node = cluster.get_node_for_key(key)
31
+ super(node)
34
32
  end
35
33
 
36
-
37
34
  protected
38
35
 
39
36
  def empty_socket