aerospike 1.0.12 → 2.0.0

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