aerospike 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +0 -0
  3. data/LICENSE +203 -0
  4. data/README.md +123 -0
  5. data/lib/aerospike.rb +69 -0
  6. data/lib/aerospike/aerospike_exception.rb +111 -0
  7. data/lib/aerospike/bin.rb +46 -0
  8. data/lib/aerospike/client.rb +649 -0
  9. data/lib/aerospike/cluster/cluster.rb +537 -0
  10. data/lib/aerospike/cluster/connection.rb +113 -0
  11. data/lib/aerospike/cluster/node.rb +248 -0
  12. data/lib/aerospike/cluster/node_validator.rb +85 -0
  13. data/lib/aerospike/cluster/partition.rb +54 -0
  14. data/lib/aerospike/cluster/partition_tokenizer_new.rb +128 -0
  15. data/lib/aerospike/cluster/partition_tokenizer_old.rb +135 -0
  16. data/lib/aerospike/command/batch_command.rb +120 -0
  17. data/lib/aerospike/command/batch_command_exists.rb +93 -0
  18. data/lib/aerospike/command/batch_command_get.rb +150 -0
  19. data/lib/aerospike/command/batch_item.rb +69 -0
  20. data/lib/aerospike/command/batch_node.rb +82 -0
  21. data/lib/aerospike/command/command.rb +680 -0
  22. data/lib/aerospike/command/delete_command.rb +57 -0
  23. data/lib/aerospike/command/execute_command.rb +42 -0
  24. data/lib/aerospike/command/exists_command.rb +57 -0
  25. data/lib/aerospike/command/field_type.rb +44 -0
  26. data/lib/aerospike/command/operate_command.rb +37 -0
  27. data/lib/aerospike/command/read_command.rb +174 -0
  28. data/lib/aerospike/command/read_header_command.rb +63 -0
  29. data/lib/aerospike/command/single_command.rb +60 -0
  30. data/lib/aerospike/command/touch_command.rb +50 -0
  31. data/lib/aerospike/command/write_command.rb +60 -0
  32. data/lib/aerospike/host.rb +43 -0
  33. data/lib/aerospike/info.rb +96 -0
  34. data/lib/aerospike/key.rb +99 -0
  35. data/lib/aerospike/language.rb +25 -0
  36. data/lib/aerospike/ldt/large.rb +69 -0
  37. data/lib/aerospike/ldt/large_list.rb +100 -0
  38. data/lib/aerospike/ldt/large_map.rb +82 -0
  39. data/lib/aerospike/ldt/large_set.rb +78 -0
  40. data/lib/aerospike/ldt/large_stack.rb +72 -0
  41. data/lib/aerospike/loggable.rb +55 -0
  42. data/lib/aerospike/operation.rb +70 -0
  43. data/lib/aerospike/policy/client_policy.rb +37 -0
  44. data/lib/aerospike/policy/generation_policy.rb +37 -0
  45. data/lib/aerospike/policy/policy.rb +54 -0
  46. data/lib/aerospike/policy/priority.rb +34 -0
  47. data/lib/aerospike/policy/record_exists_action.rb +45 -0
  48. data/lib/aerospike/policy/write_policy.rb +61 -0
  49. data/lib/aerospike/record.rb +42 -0
  50. data/lib/aerospike/result_code.rb +353 -0
  51. data/lib/aerospike/task/index_task.rb +59 -0
  52. data/lib/aerospike/task/task.rb +71 -0
  53. data/lib/aerospike/task/udf_register_task.rb +55 -0
  54. data/lib/aerospike/task/udf_remove_task.rb +55 -0
  55. data/lib/aerospike/udf.rb +24 -0
  56. data/lib/aerospike/utils/buffer.rb +139 -0
  57. data/lib/aerospike/utils/epoc.rb +28 -0
  58. data/lib/aerospike/utils/pool.rb +65 -0
  59. data/lib/aerospike/value/particle_type.rb +45 -0
  60. data/lib/aerospike/value/value.rb +380 -0
  61. data/lib/aerospike/version.rb +4 -0
  62. metadata +132 -0
@@ -0,0 +1,128 @@
1
+ # encoding: utf-8
2
+ # Copyright 2014 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 'base64'
18
+
19
+ module Aerospike
20
+
21
+ private
22
+
23
+ REPLICAS_NAME = 'replicas-master'
24
+
25
+ class PartitionTokenizerNew
26
+
27
+ def initialize(conn)
28
+ # Use low-level info methods and parse byte array directly for maximum performance.
29
+ # Send format: replicas-master\n
30
+ # Receive format: replicas-master\t<ns1>:<base 64 encoded bitmap>;<ns2>:<base 64 encoded bitmap>... \n
31
+ info_map = Info.request(conn, REPLICAS_NAME)
32
+
33
+ info = info_map[REPLICAS_NAME]
34
+
35
+ @length = info ? info.length : 0
36
+
37
+ if !info || @length == 0
38
+ raise Aerospike::Exceptions::Connection.new("#{replicas_name} is empty")
39
+ end
40
+
41
+ @buffer = info
42
+ @offset = 0
43
+
44
+ self
45
+ end
46
+
47
+ def update_partition(nmap, node)
48
+ amap = nil
49
+
50
+ beginning = @offset
51
+ copied = false
52
+
53
+ while @offset < @length
54
+ if @buffer[@offset] == ':'
55
+ # Parse namespace.
56
+ namespace = @buffer[beginning...@offset].strip
57
+
58
+ if namespace.length <= 0 || namespace.length >= 32
59
+ response = get_truncated_response
60
+ raise Aerospike::Exceptions::Parse.new(
61
+ "Invalid partition namespace #{namespace}. Response=#{response}"
62
+ )
63
+ end
64
+
65
+ @offset+=1
66
+ beginning = @offset
67
+
68
+ # Parse partition id.
69
+ while @offset < @length
70
+ b = @buffer[@offset]
71
+
72
+ break if b == ';' || b == "\n"
73
+ @offset+=1
74
+ end
75
+
76
+ if @offset == beginning
77
+ response = get_truncated_response
78
+
79
+ raise Aerospike::Exceptions::Parse.new(
80
+ "Empty partition id for namespace #{namespace}. Response=#{response}"
81
+ )
82
+ end
83
+
84
+ node_array = nmap[namespace]
85
+
86
+ if !node_array
87
+ if !copied
88
+ # Make shallow copy of map.
89
+ amap = {}
90
+ nmap.each {|k, v| amap[k] = Atomic.new(v)}
91
+ copied = true
92
+ end
93
+
94
+ node_array = Atomic.new(Array.new(Aerospike::Node::PARTITIONS))
95
+ amap[namespace] = node_array
96
+ end
97
+
98
+ bit_map_length = @offset - beginning
99
+ restore_buffer = Base64.strict_decode64(@buffer[beginning, bit_map_length])
100
+ for i in 0...Aerospike::Node::PARTITIONS
101
+ if (restore_buffer[i>>3].ord & (0x80 >> (i & 7))) != 0
102
+ # Logger.Info("Map: `" + namespace + "`," + strconv.Itoa(i) + "," + node.String)
103
+ node_array.update{|v| v[i] = node; v}
104
+ end
105
+ end
106
+
107
+ @offset+=1
108
+ beginning = @offset
109
+ else
110
+ @offset+=1
111
+ end
112
+ end
113
+
114
+ copied ? amap : nil
115
+ end
116
+
117
+ private
118
+
119
+ def get_truncated_response
120
+ max = @length
121
+ @length = max if @length > 200
122
+ @buffer[0...max]
123
+ end
124
+
125
+
126
+ end # class
127
+
128
+ end # module
@@ -0,0 +1,135 @@
1
+ # encoding: utf-8
2
+ # Copyright 2014 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 'base64'
18
+
19
+ module Aerospike
20
+
21
+ private
22
+
23
+ class PartitionTokenizerOld
24
+
25
+ def initialize(conn)
26
+ # Use low-level info methods and parse byte array directly for maximum performance.
27
+ # Send format: replicas-master\n
28
+ # Receive format: replicas-master\t<ns1>:<base 64 encoded bitmap>;<ns2>:<base 64 encoded bitmap>... \n
29
+ info_map = Info.request(conn, REPLICAS_NAME)
30
+
31
+ info = info_map[REPLICAS_NAME]
32
+
33
+ @length = info ? info.length : 0
34
+
35
+ if !info || @length == 0
36
+ raise Aerospike::Exceptions::Connection.new("#{replicas_name} is empty")
37
+ end
38
+
39
+ @buffer = info
40
+ @offset = 0
41
+
42
+ self
43
+ end
44
+
45
+ def update_partition(nmap, node)
46
+ amap = nil
47
+ copied = false
48
+
49
+ while partition = get_next
50
+ node_array = nmap[partition.namespace]
51
+
52
+ if !node_array
53
+ if !copied
54
+ # Make shallow copy of map.
55
+ amap = {}
56
+ nmap.each {|k, v| amap[k] = v}
57
+ copied = true
58
+ end
59
+
60
+ node_array = Atomic.new(Array.new(Aerospike::Node::PARTITIONS))
61
+ amap[partition.namespace] = node_array
62
+ end
63
+
64
+ Aerospike.logger.debug("#{partition.to_s}, #{node.name}")
65
+ node_array.update{|v| v[partition.partition_id] = node; v }
66
+ end
67
+
68
+ copied ? amap : nil
69
+ end
70
+
71
+ private
72
+
73
+ def get_next
74
+ beginning = @offset
75
+
76
+ while @offset < @length
77
+ if @buffer[@offset] == ':'
78
+ # Parse namespace.
79
+ namespace = @buffer[beginning...@offset].strip
80
+
81
+ if namespace.length <= 0 || namespace.length >= 32
82
+ response = get_truncated_response
83
+ raise Aerospike::Exceptions::Parse.new(
84
+ "Invalid partition namespace #{namespace}. Response=#{response}"
85
+ )
86
+ end
87
+
88
+ @offset+=1
89
+ beginning = @offset
90
+
91
+ # Parse partition id.
92
+ while @offset < @length
93
+ b = @buffer[@offset]
94
+
95
+ break if b == ';' || b == "\n"
96
+ @offset+=1
97
+ end
98
+
99
+ if @offset == beginning
100
+ response = get_truncated_response
101
+ raise Aerospike::Exceptions::Parse.new(
102
+ "Empty partition id for namespace #{namespace}. Response=#{response}"
103
+ )
104
+ end
105
+
106
+ partition_id = @buffer[beginning...@offset].to_i
107
+ if partition_id < 0 || partition_id >= Aerospike::Node::PARTITIONS
108
+ response = get_truncated_response
109
+ partition_string = @buffer[beginning...@offset]
110
+ raise Aerospike::Exceptions::Parse.new(
111
+ "Invalid partition id #{partition_string} for namespace #{namespace}. Response=#{response}"
112
+ )
113
+ end
114
+
115
+ @offset+=1
116
+ beginning = @offset
117
+
118
+ return Partition.new(namespace, partition_id)
119
+ end
120
+ @offset+=1
121
+ end
122
+ return nil
123
+ end
124
+
125
+
126
+ def get_truncated_response
127
+ max = @length
128
+ @length = max if @length > 200
129
+ @buffer[0...max]
130
+ end
131
+
132
+
133
+ end # class
134
+
135
+ end # module
@@ -0,0 +1,120 @@
1
+ # encoding: utf-8
2
+ # Copyright 2014 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 'thread'
18
+
19
+ require 'aerospike/record'
20
+
21
+ require 'aerospike/command/command'
22
+
23
+ module Aerospike
24
+
25
+ private
26
+
27
+ class BatchCommand < Command
28
+
29
+ def initialize(node)
30
+ super(node)
31
+
32
+ @valid = true
33
+ @mutex = Mutex.new
34
+ @records = Queue.new
35
+
36
+ self
37
+ end
38
+
39
+ def parse_result
40
+ # Read socket into receive buffer one record at a time. Do not read entire receive size
41
+ # because the receive buffer would be too big.
42
+ status = true
43
+
44
+ while status
45
+ # Read header.
46
+ read_bytes(8)
47
+
48
+ size = @data_buffer.read_int64(0)
49
+ receive_size = size & 0xFFFFFFFFFFFF
50
+
51
+ if receive_size > 0
52
+ status = parse_record_results(receive_size)
53
+ else
54
+ status = false
55
+ end
56
+ end
57
+ end
58
+
59
+ def parse_key(field_count)
60
+ digest = nil
61
+ namespace = nil
62
+ set_name = nil
63
+ user_key = nil
64
+
65
+ for i in 0...field_count
66
+ read_bytes(4)
67
+
68
+ fieldlen = @data_buffer.read_int32(0)
69
+ read_bytes(fieldlen)
70
+
71
+ fieldtype = @data_buffer.read(0).ord
72
+ size = fieldlen - 1
73
+
74
+ case fieldtype
75
+ when Aerospike::FieldType::DIGEST_RIPE
76
+ digest = @data_buffer.read(1, size)
77
+ when Aerospike::FieldType::NAMESPACE
78
+ namespace = @data_buffer.read(1, size).force_encoding('utf-8')
79
+ when Aerospike::FieldType::TABLE
80
+ set_name = @data_buffer.read(1, size).force_encoding('utf-8')
81
+ when Aerospike::FieldType::KEY
82
+ user_key = Value.bytes_to_key_value(@data_buffer.read(1).ord, @data_buffer, 2, size-1)
83
+ end
84
+ end
85
+
86
+ Aerospike::Key.new(namespace, set_name, user_key, digest)
87
+ end
88
+
89
+ def read_bytes(length)
90
+ if length > @data_buffer.length
91
+ # Corrupted data streams can result in a huge length.
92
+ # Do a sanity check here.
93
+ if length > Aerospike::Buffer::MAX_BUFFER_SIZE
94
+ raise Aerospike::Exceptions::Parse.new("Invalid read_bytes length: #{length}")
95
+ end
96
+ @data_buffer = Buffer.new(length)
97
+ end
98
+
99
+ @conn.read(@data_buffer, length)
100
+ @data_offset += length
101
+ end
102
+
103
+ def stop
104
+ @mutex.synchronize do
105
+ @valid = false
106
+ end
107
+ end
108
+
109
+ def valid?
110
+ res = nil
111
+ @mutex.synchronize do
112
+ res = @valid
113
+ end
114
+
115
+ res
116
+ end
117
+
118
+ end # class
119
+
120
+ end # module
@@ -0,0 +1,93 @@
1
+ # encoding: utf-8
2
+ # Copyright 2014 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 'aerospike/command/batch_command'
18
+
19
+ module Aerospike
20
+
21
+ private
22
+
23
+ class BatchCommandExists < BatchCommand
24
+
25
+ def initialize(node, batch_namespace, policy, key_map, exists_array)
26
+ super(node)
27
+
28
+ @batch_namespace = batch_namespace
29
+ @policy = policy
30
+ @key_map = key_map
31
+ @exists_array = exists_array
32
+
33
+ self
34
+ end
35
+
36
+ def write_buffer
37
+ set_batch_exists(@batch_namespace)
38
+ end
39
+
40
+ # Parse all results in the batch. Add records to shared list.
41
+ # If the record was not found, the bins will be nil.
42
+ def parse_record_results(receive_size)
43
+ #Parse each message response and add it to the result array
44
+ @data_offset = 0
45
+
46
+ while @data_offset < receive_size
47
+ if !valid?
48
+ raise Aerospike::Exceptions::QueryTerminated.new
49
+ end
50
+
51
+ read_bytes(MSG_REMAINING_HEADER_SIZE)
52
+
53
+ result_code = @data_buffer.read(5).ord & 0xFF
54
+
55
+ # The only valid server return codes are "ok" and "not found".
56
+ # If other return codes are received, then abort the batch.
57
+ if result_code != 0 && result_code != Aerospike::ResultCode::KEY_NOT_FOUND_ERROR
58
+ raise Aerospike::Exceptions::Aerospike.new(result_code)
59
+ end
60
+
61
+ info3 = @data_buffer.read(3).ord
62
+
63
+ # If cmd is the end marker of the response, do not proceed further
64
+ return false if info3 & INFO3_LAST == INFO3_LAST
65
+
66
+ field_count = @data_buffer.read_int16(18)
67
+ op_count = @data_buffer.read_int16(20)
68
+
69
+ if op_count > 0
70
+ raise Aerospike::Exceptions::Parse('Received bins that were not requested!')
71
+ end
72
+
73
+ key = parse_key(field_count)
74
+ item = @key_map[key.digest]
75
+
76
+ if item
77
+ index = item.index
78
+
79
+ # only set the results to true; as a result, no synchronization is needed
80
+ @exists_array[index] = (result_code == 0)
81
+ else
82
+ Aerospike::logger.debug("Unexpected batch key returned: #{key.namespace}, #{key.digest}")
83
+ end
84
+
85
+ end # while
86
+
87
+ return true
88
+ end
89
+
90
+
91
+ end # class
92
+
93
+ end # module