aerospike 1.0.12 → 2.0.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.
@@ -56,7 +56,7 @@ module Aerospike
56
56
  # This is the last of a multi-part message.
57
57
  INFO3_LAST = Integer(1 << 0)
58
58
  # Commit to master only before declaring success.
59
- INFO3_COMMIT_MASTER = Integer(1 << 1)
59
+ INFO3_COMMIT_MASTER = Integer(1 << 1)
60
60
  # Update only. Merge bins.
61
61
  INFO3_UPDATE_ONLY = Integer(1 << 3)
62
62
 
@@ -460,7 +460,7 @@ module Aerospike
460
460
  else
461
461
  Aerospike.logger.error(e)
462
462
  end
463
-
463
+
464
464
  # close the connection
465
465
  # cancelling/closing the batch/multi commands will return an error, which will
466
466
  # close the connection to throw away its data and signal the server about the
@@ -16,24 +16,24 @@
16
16
 
17
17
  module Aerospike
18
18
 
19
- # Pre-defined user roles.
20
- module Role
19
+ # Pre-defined user roles.
20
+ module Role
21
21
 
22
- # Manage users and their roles.
23
- USER_ADMIN = 'user-admin'
22
+ # Manage users and their roles.
23
+ USER_ADMIN = 'user-admin'
24
24
 
25
- # Manage indicies, user-defined functions and server configuration.
26
- SYS_ADMIN = 'sys-admin'
25
+ # Manage indicies, user-defined functions and server configuration.
26
+ SYS_ADMIN = 'sys-admin'
27
27
 
28
- # Allow read, write and UDF transactions with the database.
29
- READ_WRITE_UDF = "read-write-udf"
28
+ # Allow read, write and UDF transactions with the database.
29
+ READ_WRITE_UDF = "read-write-udf"
30
30
 
31
- # Allow read and write transactions with the database.
32
- READ_WRITE = 'read-write'
31
+ # Allow read and write transactions with the database.
32
+ READ_WRITE = 'read-write'
33
33
 
34
- # Allow read transactions with the database.
35
- READ = 'read'
34
+ # Allow read transactions with the database.
35
+ READ = 'read'
36
36
 
37
- end # module
37
+ end # module
38
38
 
39
39
  end # module
@@ -17,6 +17,7 @@
17
17
  require 'digest'
18
18
 
19
19
  require 'aerospike/value/value'
20
+ require 'aerospike/utils/pool'
20
21
 
21
22
  module Aerospike
22
23
 
@@ -24,20 +25,31 @@ module Aerospike
24
25
 
25
26
  @@digest_pool = Pool.new
26
27
  @@digest_pool.create_block = Proc.new do
27
- unless RUBY_PLATFORM == 'java'
28
- Digest::RMD160.new
28
+ if RUBY_PLATFORM == 'java'
29
+ OpenSSL::Digest::RIPEMD160.new
29
30
  else
30
- h = OpenSSL::Digest::RIPEMD160.new
31
+ Digest::RMD160.new
31
32
  end
32
33
  end
33
34
 
35
+ # enable backwards compatibility with v1 client for integer keys
36
+ # ref. https://github.com/aerospike/aerospike-client-ruby/pull/34
37
+ def self.enable_v1_compatibility!(comp = true)
38
+ @v1_compatibility = !!comp
39
+ end
40
+ def self.v1_compatible?
41
+ @v1_compatibility
42
+ end
34
43
 
35
44
  attr_reader :namespace, :set_name, :digest
45
+ attr_reader :v1_compatible
46
+ alias_method :v1_compatible?, :v1_compatible
36
47
 
37
- def initialize(ns, set, val, digest=nil)
48
+ def initialize(ns, set, val, digest=nil, v1_compatible: self.class.v1_compatible?)
38
49
  @namespace = ns
39
50
  @set_name = set
40
51
  @user_key = Value.of(val)
52
+ @v1_compatible = v1_compatible
41
53
 
42
54
  unless digest
43
55
  compute_digest
@@ -48,6 +60,7 @@ module Aerospike
48
60
  self
49
61
  end
50
62
 
63
+
51
64
  def to_s
52
65
  "#{@namespace}:#{@set_name}:#{@user_key}:#{@digest.nil? ? '' : @digest.bytes}"
53
66
  end
@@ -75,11 +88,17 @@ module Aerospike
75
88
 
76
89
  def compute_digest
77
90
  key_type = @user_key.type
91
+ key_bytes = @user_key.to_bytes
78
92
 
79
93
  if key_type == Aerospike::ParticleType::NULL
80
94
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::PARAMETER_ERROR, "Invalid key: nil")
81
95
  end
82
96
 
97
+ # v1.0.12 and prior computed integer key digest using little endian byte order
98
+ if key_type == Aerospike::ParticleType::INTEGER && v1_compatible?
99
+ key_bytes.reverse!
100
+ end
101
+
83
102
  # get a hash from pool and make it ready for work
84
103
  h = @@digest_pool.poll
85
104
  h.reset
@@ -87,7 +106,7 @@ module Aerospike
87
106
  # Compute a complete digest
88
107
  h.update(@set_name)
89
108
  h.update(key_type.chr)
90
- h.update(@user_key.to_bytes)
109
+ h.update(key_bytes)
91
110
  @digest = h.digest
92
111
 
93
112
  # put the hash object back to the pool
@@ -25,6 +25,8 @@ module Aerospike
25
25
  READ = 1
26
26
  READ_HEADER = 1
27
27
  WRITE = 2
28
+ CDT_READ = 3
29
+ CDT_MODIFY = 4
28
30
  ADD = 5
29
31
  APPEND = 9
30
32
  PREPEND = 10
@@ -16,18 +16,18 @@
16
16
 
17
17
  module Aerospike
18
18
 
19
- # Policy attributes used for user administration commands.
20
- class AdminPolicy
19
+ # Policy attributes used for user administration commands.
20
+ class AdminPolicy
21
21
 
22
- # User administration command socket timeout in milliseconds.
23
- # Default is one second timeout.
24
- attr_accessor :timeout
22
+ # User administration command socket timeout in milliseconds.
23
+ # Default is one second timeout.
24
+ attr_accessor :timeout
25
25
 
26
- # NewAdminPolicy generates a new AdminPolicy with default values.
27
- def initialize(opt={})
28
- @timeout = opt[:timeout] || 1
29
- end
26
+ # NewAdminPolicy generates a new AdminPolicy with default values.
27
+ def initialize(opt={})
28
+ @timeout = opt[:timeout] || 1
29
+ end
30
30
 
31
- end # class
31
+ end # class
32
32
 
33
33
  end # module
@@ -17,11 +17,11 @@ module Aerospike
17
17
 
18
18
  module ConsistencyLevel
19
19
 
20
- # Involve a single replica in the operation.
21
- CONSISTENCY_ONE = 0
20
+ # Involve a single replica in the operation.
21
+ CONSISTENCY_ONE = 0
22
22
 
23
- # Involve all replicas in the operation.
24
- CONSISTENCY_ALL = 1
23
+ # Involve all replicas in the operation.
24
+ CONSISTENCY_ALL = 1
25
25
 
26
26
  end # module
27
27
 
@@ -40,7 +40,7 @@ module Aerospike
40
40
  # return successfully
41
41
  if (@recordset == nil) && (result_code == Aerospike::ResultCode::KEY_NOT_FOUND_ERROR)
42
42
  # consume the rest of the input buffer from the socket
43
- read_bytes(receive_size - data_offset) if @data_offset < receive_size
43
+ read_bytes(receive_size - @data_offset) if @data_offset < receive_size
44
44
 
45
45
  return nil
46
46
  end
@@ -365,7 +365,7 @@ module Aerospike
365
365
  "Index not readable"
366
366
 
367
367
  when INDEX_GENERIC
368
- "Index error"
368
+ "Index error - check server logs"
369
369
 
370
370
  when INDEX_NAME_MAXLEN
371
371
  "Index name max length exceeded"
@@ -14,72 +14,72 @@
14
14
 
15
15
  module Aerospike
16
16
 
17
- private
18
-
19
- # ExecuteTask is used to poll for long running server execute job completion.
20
- class ExecuteTask < Task
21
-
22
- # NewExecuteTask initializes task with fields needed to query server nodes.
23
- def initialize(cluster, statement)
24
- super(cluster, false)
25
-
26
- @task_id = statement.task_id
27
- @scan = statement.is_scan?
28
-
29
- self
30
- end
31
-
32
- # IsDone queries all nodes for task completion status.
33
- def all_nodes_done?
34
-
35
- if @scan
36
- command = 'scan-list'
37
- else
38
- command = 'query-list'
39
- end
40
-
41
- nodes = @cluster.nodes
42
- done = false
43
-
44
- nodes.each do |node|
45
- conn = node.get_connection(0)
46
- responseMap, err = Info.request(conn, command)
47
- node.put_connection(conn)
48
-
49
- response = responseMap[command]
50
- find = "job_id=#{@task_id}:"
51
- index = response.index(find)
52
-
53
- unless index
54
- # don't return on first check
55
- done = true
56
- next
57
- end
58
-
59
- b = index + find.length
60
- response = response[b, response.length]
61
- find = 'job_status='
62
- index = response.index(find)
63
-
64
- next unless index
65
-
66
- b = index + find.length
67
- response = response[b, response.length]
68
- e = response.index(':')
69
- status = response[0, e]
70
-
71
- case status
72
- when 'ABORTED'
73
- raise raise Aerospike::Exceptions::QueryTerminated
74
- when 'IN PROGRESS'
75
- return false
76
- when 'DONE'
77
- done = true
78
- end
79
- end
80
-
81
- done
82
- end
83
-
84
- end
17
+ private
18
+
19
+ # ExecuteTask is used to poll for long running server execute job completion.
20
+ class ExecuteTask < Task
21
+
22
+ # NewExecuteTask initializes task with fields needed to query server nodes.
23
+ def initialize(cluster, statement)
24
+ super(cluster, false)
25
+
26
+ @task_id = statement.task_id
27
+ @scan = statement.is_scan?
28
+
29
+ self
30
+ end
31
+
32
+ # IsDone queries all nodes for task completion status.
33
+ def all_nodes_done?
34
+
35
+ if @scan
36
+ command = 'scan-list'
37
+ else
38
+ command = 'query-list'
39
+ end
40
+
41
+ nodes = @cluster.nodes
42
+ done = false
43
+
44
+ nodes.each do |node|
45
+ conn = node.get_connection(0)
46
+ responseMap, _ = Info.request(conn, command)
47
+ node.put_connection(conn)
48
+
49
+ response = responseMap[command]
50
+ find = "job_id=#{@task_id}:"
51
+ index = response.index(find)
52
+
53
+ unless index
54
+ # don't return on first check
55
+ done = true
56
+ next
57
+ end
58
+
59
+ b = index + find.length
60
+ response = response[b, response.length]
61
+ find = 'job_status='
62
+ index = response.index(find)
63
+
64
+ next unless index
65
+
66
+ b = index + find.length
67
+ response = response[b, response.length]
68
+ e = response.index(':')
69
+ status = response[0, e]
70
+
71
+ case status
72
+ when 'ABORTED'
73
+ raise raise Aerospike::Exceptions::QueryTerminated
74
+ when 'IN PROGRESS'
75
+ return false
76
+ when 'DONE'
77
+ done = true
78
+ end
79
+ end
80
+
81
+ done
82
+ end
83
+
84
+ end
85
85
  end
@@ -38,7 +38,7 @@ module Aerospike
38
38
  # make sure there will be only ONE thread polling for completetion status
39
39
  @done_thread.update do |dt|
40
40
  dt ? dt : Thread.new do
41
- abort_on_exception=true
41
+ Thread.current.abort_on_exception = true
42
42
  failures = 0
43
43
  while true
44
44
  begin
@@ -60,11 +60,7 @@ module Aerospike
60
60
  end
61
61
 
62
62
  def completed?
63
- if @done.value == true
64
- true
65
- else
66
- @done.value = all_nodes_done?
67
- end
63
+ @done.value ||= all_nodes_done?
68
64
  end
69
65
 
70
66
  end # class
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+ # Copyright 2016 Aerospike, Inc.
3
+ #
4
+ # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
+ # license agreements.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
+ # 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
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+
17
+ require 'msgpack'
18
+ require 'aerospike/utils/pool'
19
+
20
+ module Aerospike
21
+
22
+ private
23
+
24
+ class Packer < MessagePack::Packer #:nodoc:
25
+
26
+ @@pool = Pool.new
27
+ @@pool.create_block = Proc.new { Packer.new }
28
+
29
+ def self.use
30
+ packer = @@pool.poll
31
+ packer.clear
32
+ yield packer
33
+ ensure
34
+ @@pool.offer(packer)
35
+ end
36
+
37
+ # WARNING: This method is not compatible with message pack standard.
38
+ def write_raw_short(val)
39
+ buffer << [val].pack("S>")
40
+ end
41
+
42
+ def bytes
43
+ self.to_s.force_encoding('binary')
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,106 @@
1
+ # encoding: utf-8
2
+ # Copyright 2016 Aerospike, Inc.
3
+ #
4
+ # Portions may be licensed to Aerospike, Inc. under one or more contributor
5
+ # license agreements.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
+ # 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
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ # License for the specific language governing permissions and limitations under
15
+ # the License.
16
+
17
+ require 'msgpack'
18
+ require 'aerospike/utils/pool'
19
+
20
+ module Aerospike
21
+
22
+ private
23
+
24
+ class Unpacker
25
+
26
+ @@pool = Pool.new
27
+ @@pool.create_block = Proc.new { Unpacker.new }
28
+
29
+ def self.use
30
+ unpacker = @@pool.poll
31
+ unpacker.reset
32
+ yield unpacker
33
+ ensure
34
+ @@pool.offer(unpacker)
35
+ end
36
+
37
+ MsgPackExt = Struct.new(:type, :data)
38
+ MsgPackExt::TYPES = [
39
+ # Map Create Flags:
40
+ 0x00, # UNORDERED
41
+ 0x01, # K_ORDERED
42
+ 0x03, # KV_ORDERED
43
+ 0x08, # PRESERVE_ORDER
44
+ ]
45
+
46
+ def initialize
47
+ @unpacker = MessagePack::Unpacker.new
48
+ MsgPackExt::TYPES.each do |type|
49
+ @unpacker.register_type(type) { |data| MsgPackExt.new(type, data) }
50
+ end
51
+ end
52
+
53
+ def unpack(bytes)
54
+ obj = @unpacker.feed(bytes).read
55
+ case obj
56
+ when Array then unpack_list(obj)
57
+ when Hash then unpack_map(obj)
58
+ else obj
59
+ end
60
+ end
61
+
62
+ def reset
63
+ @unpacker.reset
64
+ end
65
+
66
+ private
67
+
68
+ def unpack_list(array)
69
+ normalize_strings_in_array(array)
70
+ end
71
+
72
+ def unpack_map(hash)
73
+ hash = normalize_strings_in_map(hash)
74
+ if hash.any?
75
+ (key, _) = hash.first
76
+ hash.shift if MsgPackExt === key
77
+ end
78
+ hash
79
+ end
80
+
81
+ def normalize_elem(elem)
82
+ case elem
83
+ when String
84
+ elem[1..-1].encode(Aerospike.encoding)
85
+ when Array
86
+ normalize_strings_in_array(elem)
87
+ when Hash
88
+ normalize_strings_in_map(elem)
89
+ else
90
+ elem
91
+ end
92
+ end
93
+
94
+ def normalize_strings_in_array(arr)
95
+ arr.map! { |elem| normalize_elem(elem) }
96
+ end
97
+
98
+ def normalize_strings_in_map(hash)
99
+ hash.inject({}) do |h, (k,v)|
100
+ h.update({ normalize_elem(k) => normalize_elem(v) })
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ end