aerospike 1.0.12 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +54 -18
- data/README.md +7 -2
- data/lib/aerospike.rb +8 -0
- data/lib/aerospike/cdt/list_operation.rb +199 -0
- data/lib/aerospike/cdt/map_operation.rb +352 -0
- data/lib/aerospike/cdt/map_order.rb +38 -0
- data/lib/aerospike/cdt/map_policy.rb +37 -0
- data/lib/aerospike/cdt/map_return_type.rb +74 -0
- data/lib/aerospike/cdt/map_write_mode.rb +41 -0
- data/lib/aerospike/client.rb +84 -119
- data/lib/aerospike/cluster/cluster.rb +4 -4
- data/lib/aerospike/command/admin_command.rb +325 -325
- data/lib/aerospike/command/command.rb +2 -2
- data/lib/aerospike/command/roles.rb +13 -13
- data/lib/aerospike/key.rb +24 -5
- data/lib/aerospike/operation.rb +2 -0
- data/lib/aerospike/policy/admin_policy.rb +10 -10
- data/lib/aerospike/policy/consistency_level.rb +4 -4
- data/lib/aerospike/query/stream_command.rb +1 -1
- data/lib/aerospike/result_code.rb +1 -1
- data/lib/aerospike/task/execute_task.rb +68 -68
- data/lib/aerospike/task/task.rb +2 -6
- data/lib/aerospike/utils/packer.rb +47 -0
- data/lib/aerospike/utils/unpacker.rb +106 -0
- data/lib/aerospike/value/value.rb +19 -51
- data/lib/aerospike/version.rb +1 -1
- metadata +17 -7
@@ -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
|
-
|
20
|
-
|
19
|
+
# Pre-defined user roles.
|
20
|
+
module Role
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
# Manage users and their roles.
|
23
|
+
USER_ADMIN = 'user-admin'
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
# Manage indicies, user-defined functions and server configuration.
|
26
|
+
SYS_ADMIN = 'sys-admin'
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
# Allow read, write and UDF transactions with the database.
|
29
|
+
READ_WRITE_UDF = "read-write-udf"
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
# Allow read and write transactions with the database.
|
32
|
+
READ_WRITE = 'read-write'
|
33
33
|
|
34
|
-
|
35
|
-
|
34
|
+
# Allow read transactions with the database.
|
35
|
+
READ = 'read'
|
36
36
|
|
37
|
-
|
37
|
+
end # module
|
38
38
|
|
39
39
|
end # module
|
data/lib/aerospike/key.rb
CHANGED
@@ -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
|
-
|
28
|
-
Digest::
|
28
|
+
if RUBY_PLATFORM == 'java'
|
29
|
+
OpenSSL::Digest::RIPEMD160.new
|
29
30
|
else
|
30
|
-
|
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(
|
109
|
+
h.update(key_bytes)
|
91
110
|
@digest = h.digest
|
92
111
|
|
93
112
|
# put the hash object back to the pool
|
data/lib/aerospike/operation.rb
CHANGED
@@ -16,18 +16,18 @@
|
|
16
16
|
|
17
17
|
module Aerospike
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
# Policy attributes used for user administration commands.
|
20
|
+
class AdminPolicy
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
# User administration command socket timeout in milliseconds.
|
23
|
+
# Default is one second timeout.
|
24
|
+
attr_accessor :timeout
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
# NewAdminPolicy generates a new AdminPolicy with default values.
|
27
|
+
def initialize(opt={})
|
28
|
+
@timeout = opt[:timeout] || 1
|
29
|
+
end
|
30
30
|
|
31
|
-
|
31
|
+
end # class
|
32
32
|
|
33
33
|
end # module
|
@@ -17,11 +17,11 @@ module Aerospike
|
|
17
17
|
|
18
18
|
module ConsistencyLevel
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
# Involve a single replica in the operation.
|
21
|
+
CONSISTENCY_ONE = 0
|
22
22
|
|
23
|
-
|
24
|
-
|
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
|
@@ -14,72 +14,72 @@
|
|
14
14
|
|
15
15
|
module Aerospike
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
data/lib/aerospike/task/task.rb
CHANGED
@@ -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
|
-
|
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
|