aerospike 2.1.1 → 2.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 291a0bd794307c4287931048cacb5588fa0cf963
4
- data.tar.gz: d91a674c710b1cc49dde762261d65de3aa58e675
3
+ metadata.gz: 903b61fdf1d17d80049e051d70b90ce8159d0403
4
+ data.tar.gz: d87f7a61c12f457c94ebe2319adf06f3ce0fa8db
5
5
  SHA512:
6
- metadata.gz: 825242c46dc27ee6fe674387c639e9968978d4509c2a27f82f8d3a49102674525a9ca293c488621f2df3bff8ec2cd2fea1074582761acb48b05c90f82c254d8c
7
- data.tar.gz: 05636b87e30ed3087f2efd5f5af92399b8ee9bdba7b9360b03599e3d4b275283319642d5e9bea410fce7b9e77550c2b2659f452c8991d0ea24b4896f1e9a4420
6
+ metadata.gz: feaa5085e9fb331fc43f5b8c45b4f765f75c0b5ed02e056623ceacf57b7a9c4d39ea817e5c18b7b059c2564273ba106793adb632923719c2ffcb0f5825e36115
7
+ data.tar.gz: 72985529453d486919b11827d74ad4d6884a038e4390d740c90ef48246341727435bcb47e6d2563a3aa5ca4a11904c02c42a2fa1b6b068d2a309c10a1ae47193
@@ -1,3 +1,23 @@
1
+ v2.2.0 / 2016-09-20
2
+ ===================
3
+
4
+ * **New Features**
5
+ * Support for durable delete write policy [CLIENT-768]; requires Aerospike
6
+ Server Enterprise Edition v3.10 or later.
7
+ * Support Cluster Name verification [CLIENT-776]; requires Aerospike Server v3.10 or later.
8
+
9
+ * **Bug Fixes**
10
+ * Fix error handling in node refresh during cluster tend.
11
+
12
+ * **Improvements**
13
+ * Optionally return multiple results from read operations on same record bin.
14
+ [#39](https://github.com/aerospike/aerospike-client-ruby/issues/39) Thanks
15
+ to [@zingoba](https://github.com/zingoba).
16
+
17
+ * **Documentation**
18
+ * Added note about potential issues with usage in Ruby on Rails with Phusion Passenger.
19
+ * Amend/clean up documentation of client policies.
20
+
1
21
  v2.1.1 / 2016-08-16
2
22
  ===================
3
23
 
data/README.md CHANGED
@@ -13,7 +13,6 @@ This library is compatible with Ruby 2.0+ and supports Linux, Mac OS X and vario
13
13
  - [Usage](#Usage)
14
14
  - [Prerequisites](#Prerequisites)
15
15
  - [Installation](#Installation)
16
- - [Tweaking Performance](#Performance)
17
16
  - [Benchmarks](#Benchmarks)
18
17
  - [API Documentaion](#API-Documentation)
19
18
  - [Tests](#Tests)
@@ -75,11 +74,13 @@ Supported operating systems:
75
74
  - other BSDs (untested)
76
75
 
77
76
  <a name="Installation"></a>
78
- ## Installation from Ruby gems:
77
+ ## Installation
78
+
79
+ ### Installation from Ruby gems
79
80
 
80
81
  1. gem install aerospike
81
82
 
82
- ## Installation from source:
83
+ ### Installation from source
83
84
 
84
85
  1. Install Ruby 2.0+
85
86
  2. Install RubyGems
@@ -88,13 +89,6 @@ Supported operating systems:
88
89
  5. Build and Install the gem locally: ```rake build && rake install```
89
90
  6. Run the benchmark: ```./tools/benchmark/benchmark.rb -u```
90
91
 
91
- <a name="Performance"></a>
92
- ## Performance Tweaking
93
-
94
- We are bending all efforts to improve the client's performance. In out reference benchmarks, Go client performs almost as good as the C client.
95
-
96
- To read about performance variables, please refer to [`docs/performance.md`](docs/performance.md)
97
-
98
92
  <a name="Tests"></a>
99
93
  ## Tests
100
94
 
@@ -104,7 +98,6 @@ To run all the test cases:
104
98
 
105
99
  $ bundle exec rspec
106
100
 
107
-
108
101
  <a name="Examples"></a>
109
102
  ## Examples
110
103
 
@@ -40,6 +40,8 @@ module Aerospike
40
40
  ret
41
41
  end
42
42
  alias_method :value, :get
43
+ alias_method :to_s, :value
44
+ alias_method :inspect, :to_s
43
45
 
44
46
  def set(value)
45
47
  @mutex.synchronize do
@@ -88,9 +88,7 @@ module Aerospike
88
88
  # Returns list of active server node names in the cluster.
89
89
 
90
90
  def node_names
91
- @cluster.nodes.map do |node|
92
- node.get_name
93
- end
91
+ @cluster.nodes.map(&:get_name)
94
92
  end
95
93
 
96
94
  def supports_feature?(feature)
@@ -252,11 +250,9 @@ module Aerospike
252
250
 
253
251
  key_map = BatchItem.generate_map(keys)
254
252
 
255
- cmd_gen = Proc.new do |node, bns|
253
+ batch_execute(keys) do |node, bns|
256
254
  BatchCommandExists.new(node, bns, policy, key_map, exists_array)
257
255
  end
258
-
259
- batch_execute(keys, &cmd_gen)
260
256
  exists_array
261
257
  end
262
258
 
@@ -304,11 +300,9 @@ module Aerospike
304
300
 
305
301
  key_map = BatchItem.generate_map(keys)
306
302
 
307
- cmd_gen = Proc.new do |node, bns|
303
+ batch_execute(keys) do |node, bns|
308
304
  BatchCommandGet.new(node, bns, policy, key_map, bin_names.uniq, records, INFO1_READ)
309
305
  end
310
-
311
- batch_execute(keys, &cmd_gen)
312
306
  records
313
307
  end
314
308
 
@@ -329,11 +323,10 @@ module Aerospike
329
323
 
330
324
  key_map = BatchItem.generate_map(keys)
331
325
 
332
- cmd_gen = Proc.new do |node, bns|
326
+ batch_execute(keys) do |node, bns|
333
327
  BatchCommandGet.new(node, bns, policy, key_map, nil, records, INFO1_READ | INFO1_NOBINDATA)
334
328
  end
335
329
 
336
- batch_execute(keys, &cmd_gen)
337
330
  records
338
331
  end
339
332
 
@@ -343,10 +336,8 @@ module Aerospike
343
336
 
344
337
  # Perform multiple read/write operations on a single key in one batch call.
345
338
  # An example would be to add an integer value to an existing record and then
346
- # read the result, all in one database call.
347
- #
348
- # Write operations are always performed first, regardless of operation order
349
- # relative to read operations.
339
+ # read the result, all in one database call. Operations are executed in
340
+ # the order they are specified.
350
341
  def operate(key, operations, options={})
351
342
  policy = create_policy(options, WritePolicy)
352
343
 
@@ -410,7 +401,7 @@ module Aerospike
410
401
  # This method is only supported by Aerospike 3 servers.
411
402
  def register_udf_from_file(client_path, server_path, language, options={})
412
403
  udf_body = File.read(client_path)
413
- register_udf(udf_body, server_path, language, options={})
404
+ register_udf(udf_body, server_path, language, options)
414
405
  end
415
406
 
416
407
  # Register package containing user defined functions with server.
@@ -510,22 +501,17 @@ module Aerospike
510
501
 
511
502
  record = command.record
512
503
 
513
- return nil if !record || record.bins.length == 0
504
+ return nil if !record || record.bins.empty?
514
505
 
515
506
  result_map = record.bins
516
507
 
517
508
  # User defined functions don't have to return a value.
518
- key, obj = result_map.detect{|k, v| k.include?('SUCCESS')}
519
- if key
520
- return obj
521
- end
522
-
523
- key, obj = result_map.detect{|k, v| k.include?('FAILURE')}
524
- if key
525
- raise Aerospike::Exceptions::Aerospike.new(UDF_BAD_RESPONSE, "#{obj}")
526
- end
509
+ key, obj = result_map.detect{ |k, _| k.include?('SUCCESS') }
510
+ return obj if key
527
511
 
528
- raise Aerospike::Exceptions::Aerospike.new(UDF_BAD_RESPONSE, "Invalid UDF return value")
512
+ key, obj = result_map.detect{ |k, _| k.include?('FAILURE') }
513
+ message = key ? obj.to_s : "Invalid UDF return value"
514
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::UDF_BAD_RESPONSE, message)
529
515
  end
530
516
 
531
517
  # execute_udf_on_query applies user defined function on records that match the statement filter.
@@ -540,7 +526,7 @@ module Aerospike
540
526
  policy = create_policy(options, QueryPolicy)
541
527
 
542
528
  nodes = @cluster.nodes
543
- if nodes.length == 0
529
+ if nodes.empty?
544
530
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Executing UDF failed because cluster is empty.")
545
531
  end
546
532
 
@@ -644,7 +630,7 @@ module Aerospike
644
630
  new_policy = policy.clone
645
631
 
646
632
  nodes = @cluster.nodes
647
- if nodes.length == 0
633
+ if nodes.empty?
648
634
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Scan failed because cluster is empty.")
649
635
  end
650
636
 
@@ -699,7 +685,7 @@ module Aerospike
699
685
  new_policy = policy.clone
700
686
  new_policy.max_retries = 0
701
687
 
702
- node = @cluster.get_node_by_name(node) if !node.is_a?(Aerospike::Node)
688
+ node = @cluster.get_node_by_name(node) unless node.is_a?(Aerospike::Node)
703
689
 
704
690
  recordset = Recordset.new(policy.record_queue_size, 1, :scan)
705
691
 
@@ -735,7 +721,7 @@ module Aerospike
735
721
  new_policy = policy.clone
736
722
 
737
723
  nodes = @cluster.nodes
738
- if nodes.length == 0
724
+ if nodes.empty?
739
725
  raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::SERVER_NOT_AVAILABLE, "Scan failed because cluster is empty.")
740
726
  end
741
727
 
@@ -782,10 +768,8 @@ module Aerospike
782
768
 
783
769
  # Change user's password. Clear-text password will be hashed using bcrypt before sending to server.
784
770
  def change_password(user, password, options={})
771
+ raise Aerospike::Exceptions::Aerospike.new(INVALID_USER) unless @cluster.user && @cluster.user != ""
785
772
  policy = create_policy(options, AdminPolicy)
786
- if @cluster.user == ''
787
- return NewAerospikeError(INVALID_USER)
788
- end
789
773
 
790
774
  hash = AdminCommand.hash_password(password)
791
775
  command = AdminCommand.new
@@ -832,7 +816,8 @@ module Aerospike
832
816
  private
833
817
 
834
818
  def send_info_command(policy, command)
835
- @cluster.request_info(@default_policy, command)
819
+ policy ||= default_policy
820
+ @cluster.request_info(policy, command)
836
821
  end
837
822
 
838
823
  def hash_to_bins(hash)
@@ -912,7 +897,7 @@ module Aerospike
912
897
  command.execute
913
898
  end
914
899
 
915
- def batch_execute(keys, &cmd_gen)
900
+ def batch_execute(keys)
916
901
  batch_nodes = BatchNode.generate_list(@cluster, keys)
917
902
  threads = []
918
903
 
@@ -923,15 +908,15 @@ module Aerospike
923
908
  bn.batch_namespaces.each do |bns|
924
909
  threads << Thread.new do
925
910
  Thread.current.abort_on_exception = true
926
- command = cmd_gen.call(bn.node, bns)
911
+ command = yield bn.node, bns
927
912
  execute_command(command)
928
913
  end
929
914
  end
930
915
  end
931
916
 
932
- threads.each { |thr| thr.join }
917
+ threads.each(&:join)
933
918
  end
934
919
 
935
920
  end # class
936
921
 
937
- end #module
922
+ end # module
@@ -35,6 +35,7 @@ module Aerospike
35
35
  @connection_queue_size = policy.connection_queue_size
36
36
  @connection_timeout = policy.timeout
37
37
  @tend_interval = policy.tend_interval
38
+ @cluster_name = policy.cluster_name
38
39
  @aliases = {}
39
40
  @cluster_nodes = []
40
41
  @partition_write_map = {}
@@ -44,7 +45,7 @@ module Aerospike
44
45
  @mutex = Mutex.new
45
46
  @cluster_config_change_listeners = Atomic.new([])
46
47
 
47
- @old_node_cound = 0
48
+ @old_node_count = 0
48
49
 
49
50
  # setup auth info for cluster
50
51
  if policy.requires_authentication
@@ -208,6 +209,10 @@ module Aerospike
208
209
  end
209
210
  end
210
211
 
212
+ def inspect
213
+ "#<Aerospike::Cluster @cluster_nodes=#{@cluster_nodes}>"
214
+ end
215
+
211
216
  private
212
217
 
213
218
  def launch_tend_thread
@@ -254,7 +259,8 @@ module Aerospike
254
259
  refresh_count += 1
255
260
  friend_list.concat(friends) if friends
256
261
  rescue => e
257
- Aerospike.logger.error("Node `#{node}` refresh failed: #{e.backtrace.join("\n")}")
262
+ Aerospike.logger.error("Node `#{node}` refresh failed: #{e}")
263
+ Aerospike.logger.error(e.backtrace.join("\n"))
258
264
  end
259
265
  end
260
266
  end
@@ -279,12 +285,10 @@ module Aerospike
279
285
 
280
286
  # only log the tend finish IF the number of nodes has been changed.
281
287
  # This prevents spamming the log on every tend interval
282
- if @old_node_cound > nodes.length
283
- Aerospike.logger.info("Tend finished. #{@old_node_cound - nodes.length} nodes have left the cluster. Old node count: #{@old_node_cound}, New node count #{nodes.length} #{nodes}")
284
- else
285
- Aerospike.logger.info("Tend finished. #{nodes.length - @old_node_cound} nodes have joined the cluster. Old node count: #{@old_node_cound}, New node count #{nodes.length} #{nodes}")
286
- end
287
- @old_node_cound = nodes.length
288
+ diff = nodes.length - @old_node_count
289
+ action = "#{diff.abs} #{diff.abs == 1 ? "node has" : "nodes have"} #{diff > 0 ? "joined" : "left"} the cluster."
290
+ Aerospike.logger.info("Tend finished. #{action} Old node count: #{@old_node_count}, New node count: #{nodes.length}")
291
+ @old_node_count = nodes.length
288
292
 
289
293
  notify_cluster_config_changed
290
294
  end
@@ -362,7 +366,7 @@ module Aerospike
362
366
 
363
367
  seed_array.each do |seed|
364
368
  begin
365
- seed_node_validator = NodeValidator.new(self, seed, @connection_timeout)
369
+ seed_node_validator = NodeValidator.new(self, seed, @connection_timeout, @cluster_name)
366
370
  rescue => e
367
371
  Aerospike.logger.error("Seed #{seed.to_s} failed: #{e.backtrace.join("\n")}")
368
372
  next
@@ -376,7 +380,7 @@ module Aerospike
376
380
  nv = seed_node_validator
377
381
  else
378
382
  begin
379
- nv = NodeValidator.new(self, aliass, @connection_timeout)
383
+ nv = NodeValidator.new(self, aliass, @connection_timeout, @cluster_name)
380
384
  rescue Exection => e
381
385
  Aerospike.logger.error("Seed #{seed.to_s} failed: #{e}")
382
386
  next
@@ -22,7 +22,7 @@ module Aerospike
22
22
 
23
23
  class Node
24
24
 
25
- attr_reader :reference_count, :responded, :name, :features
25
+ attr_reader :reference_count, :responded, :name, :features, :cluster_name
26
26
 
27
27
  PARTITIONS = 4096
28
28
  FULL_HEALTH = 100
@@ -35,17 +35,18 @@ module Aerospike
35
35
  @host = nv.host
36
36
  @use_new_info = Atomic.new(nv.use_new_info)
37
37
  @features = nv.features
38
+ @cluster_name = nv.cluster_name
38
39
 
39
40
  # Assign host to first IP alias because the server identifies nodes
40
41
  # by IP address (not hostname).
41
- @host = nv.aliases[0]
42
- @health = Atomic.new(FULL_HEALTH)
42
+ @host = nv.aliases[0]
43
+ @health = Atomic.new(FULL_HEALTH)
43
44
  @partition_generation = Atomic.new(-1)
44
- @reference_count = Atomic.new(0)
45
- @responded = Atomic.new(false)
46
- @active = Atomic.new(true)
45
+ @reference_count = Atomic.new(0)
46
+ @responded = Atomic.new(false)
47
+ @active = Atomic.new(true)
47
48
 
48
- @connections = Pool.new(@cluster.connection_queue_size)
49
+ @connections = Pool.new(@cluster.connection_queue_size)
49
50
  @connections.create_block = Proc.new do
50
51
  while conn = Connection.new(@host.name, @host.port, @cluster.connection_timeout)
51
52
 
@@ -75,9 +76,10 @@ module Aerospike
75
76
 
76
77
  begin
77
78
  conn = get_connection(1)
78
- info_map = Info.request(conn, "node", "partition-generation", "services")
79
+ info_map = Info.request(conn, "node", "partition-generation", "services", "cluster-name")
79
80
  rescue => e
80
81
  Aerospike.logger.error("Error during refresh for node #{self}: #{e}")
82
+ Aerospike.logger.error(e.backtrace.join("\n"))
81
83
 
82
84
  conn.close if conn
83
85
  decrease_health
@@ -85,7 +87,7 @@ module Aerospike
85
87
  return friends
86
88
  end
87
89
 
88
- verify_node_name(info_map)
90
+ verify_node_name_and_cluster_name(info_map)
89
91
  restore_health
90
92
 
91
93
  @responded.update{|v| true}
@@ -173,10 +175,6 @@ module Aerospike
173
175
  @features.include?(feature.to_s)
174
176
  end
175
177
 
176
- def to_s
177
- "#{@name}:#{@host}"
178
- end
179
-
180
178
  def ==(other)
181
179
  other && other.is_a?(Node) && (@name == other.name)
182
180
  end
@@ -190,6 +188,10 @@ module Aerospike
190
188
  @name.hash
191
189
  end
192
190
 
191
+ def inspect
192
+ "#<Aerospike::Node: @name=#{@name}, @host=#{@host}>"
193
+ end
194
+
193
195
  private
194
196
 
195
197
  def close_connections
@@ -206,18 +208,23 @@ module Aerospike
206
208
  @aliases.value = aliases
207
209
  end
208
210
 
209
- def verify_node_name(info_map)
211
+ def verify_node_name_and_cluster_name(info_map)
210
212
  info_name = info_map['node']
211
213
 
212
214
  if !info_name
213
215
  decrease_health
214
- raise Aerospike::Exceptions.Aerospike.new("Node name is empty")
216
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, "Node name is empty")
215
217
  end
216
218
 
217
219
  if !(@name == info_name)
218
220
  # Set node to inactive immediately.
219
221
  @active.update{|v| false}
220
- raise Aerospike::Exceptions.Aerospike.new("Node name has changed. Old=#{@name} New= #{info_name}")
222
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, "Node name has changed. Old=#{@name} New= #{info_name}")
223
+ end
224
+
225
+ if cluster_name && cluster_name != info_map['cluster-name']
226
+ @active.update{|v| false}
227
+ raise Aerospike::Exceptions::Aerospike.new(Aerospike::ResultCode::INVALID_NODE_ERROR, "Cluster name does not match. expected: #{cluster_name}, got: #{info_map['cluster-name']}")
221
228
  end
222
229
  end
223
230
 
@@ -239,7 +246,7 @@ module Aerospike
239
246
  if node
240
247
  node.reference_count.update{|v| v + 1}
241
248
  else
242
- unless friends.any? {|host| host == aliass}
249
+ unless friends.any? {|h| h == aliass}
243
250
  friends << aliass
244
251
  end
245
252
  end
@@ -20,13 +20,14 @@ module Aerospike
20
20
 
21
21
  class NodeValidator # :nodoc:
22
22
 
23
- attr_reader :host, :aliases, :name, :use_new_info, :features
23
+ attr_reader :host, :aliases, :name, :use_new_info, :features, :cluster_name
24
24
 
25
- def initialize(cluster, host, timeout)
25
+ def initialize(cluster, host, timeout, cluster_name)
26
26
  @cluster = cluster
27
27
  @use_new_info = true
28
28
  @features = Set.new
29
29
  @host = host
30
+ @cluster_name = cluster_name
30
31
 
31
32
  set_aliases(host)
32
33
  set_address(timeout)
@@ -48,8 +48,8 @@ module Aerospike
48
48
  INFO2_GENERATION = Integer(1 << 2)
49
49
  # Update if new generation >= old, good for restore.
50
50
  INFO2_GENERATION_GT = Integer(1 << 3)
51
- # Create a duplicate on a generation collision.
52
- INFO2_GENERATION_DUP = Integer(1 << 4)
51
+ # Transaction resulting in record deletion leaves tombstone (Enterprise only).
52
+ INFO2_DURABLE_DELETE = Integer(1 << 4)
53
53
  # Create only. Fail if record already exists.
54
54
  INFO2_CREATE_ONLY = Integer(1 << 5)
55
55
 
@@ -600,6 +600,7 @@ module Aerospike
600
600
 
601
601
  info_attr |= INFO3_COMMIT_MASTER if policy.commit_level == Aerospike::CommitLevel::COMMIT_MASTER
602
602
  read_attr |= INFO1_CONSISTENCY_ALL if policy.consistency_level == Aerospike::ConsistencyLevel::CONSISTENCY_ALL
603
+ write_attr |= INFO2_DURABLE_DELETE if policy.durable_delete
603
604
 
604
605
  # Write all header data except total size which must be written last.
605
606
  @data_buffer.write_byte(MSG_REMAINING_HEADER_SIZE, 8) # Message heade.length.
@@ -17,6 +17,7 @@
17
17
  require 'aerospike/record'
18
18
 
19
19
  require 'aerospike/command/single_command'
20
+ require 'aerospike/policy/operate_policy'
20
21
  require 'aerospike/utils/epoc'
21
22
  require 'aerospike/value/value'
22
23
 
@@ -26,7 +27,7 @@ module Aerospike
26
27
 
27
28
  class ReadCommand < SingleCommand #:nodoc:
28
29
 
29
- attr_reader :record
30
+ attr_reader :record, :policy
30
31
 
31
32
  def initialize(cluster, policy, key, bin_names)
32
33
  super(cluster, key)
@@ -108,6 +109,7 @@ module Aerospike
108
109
  def parse_record(op_count, field_count, generation, expiration)
109
110
  bins = op_count > 0 ? {} : nil
110
111
  receive_offset = 0
112
+ single_bin_value = (!(OperatePolicy === policy) || policy.record_bin_multiplicity == RecordBinMultiplicity::SINGLE)
111
113
 
112
114
  # There can be fields in the response (setname etc).
113
115
  # But for now, ignore them. Expose them to the API if needed in the future.
@@ -129,12 +131,17 @@ module Aerospike
129
131
  name = @data_buffer.read(receive_offset+8, name_size).force_encoding('utf-8')
130
132
  receive_offset += 4 + 4 + name_size
131
133
 
132
-
133
134
  particle_bytes_size = op_size - (4 + name_size)
134
135
  value = Aerospike.bytes_to_particle(particle_type, @data_buffer, receive_offset, particle_bytes_size)
135
136
  receive_offset += particle_bytes_size
136
137
 
137
- bins[name] = value
138
+ if single_bin_value || !bins.has_key?(name)
139
+ bins[name] = value
140
+ elsif (prev = bins[name]).kind_of?(OpResults)
141
+ prev << value
142
+ else
143
+ bins[name] = OpResults.new << prev << value
144
+ end
138
145
 
139
146
  i = i.succ
140
147
  end
@@ -144,4 +151,6 @@ module Aerospike
144
151
 
145
152
  end # class
146
153
 
154
+ class OpResults < Array; end
155
+
147
156
  end # module
@@ -26,8 +26,9 @@ module Aerospike
26
26
  end
27
27
 
28
28
  def to_s
29
- "#{@name}:#{@port.to_s}"
29
+ "#{@name}:#{@port}"
30
30
  end
31
+ alias_method :inspect, :to_s
31
32
 
32
33
  def ==(other)
33
34
  other && other.is_a?(Host) && other.name == @name && other.port == @port
@@ -20,6 +20,7 @@ module Aerospike
20
20
 
21
21
  attr_accessor :user, :password
22
22
  attr_accessor :timeout, :connection_queue_size, :fail_if_not_connected, :tend_interval
23
+ attr_accessor :cluster_name
23
24
 
24
25
  def initialize(opt={})
25
26
  # Initial host connection timeout in seconds. The timeout when opening a connection
@@ -41,6 +42,9 @@ module Aerospike
41
42
 
42
43
  # password
43
44
  @password = opt[:password]
45
+
46
+ # Cluster Name
47
+ @cluster_name = opt[:cluster_name]
44
48
  end
45
49
 
46
50
  def requires_authentication
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+ # Copyright 2016 Aerospike, Inc.
3
+ #
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
7
+ #
8
+ # http:#www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # 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.
15
+
16
+ require 'aerospike/policy/write_policy'
17
+ require 'aerospike/policy/record_bin_multiplicity'
18
+
19
+ module Aerospike
20
+
21
+ class OperatePolicy < WritePolicy
22
+
23
+ attr_accessor :record_bin_multiplicity
24
+
25
+ def initialize(opt = {})
26
+ super(opt)
27
+
28
+ # Specifies how to merge results from multiple operations returning
29
+ # results for the same record bin.
30
+ @record_bin_multiplicity = opt[:record_bin_multiplicity] || RecordBinMultiplicity::SINGLE
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ # Copyright 2016 Aerospike, Inc.
3
+ #
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
7
+ #
8
+ # http:#www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # 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.
15
+
16
+ module Aerospike
17
+
18
+ module RecordBinMultiplicity
19
+
20
+ # Returns only the result of the last operation on a given record bin.
21
+ SINGLE = 0
22
+
23
+ # Returns the results of all operations on a given record bin as a list.
24
+ ARRAY = 1
25
+
26
+ end
27
+
28
+ end
@@ -24,7 +24,8 @@ module Aerospike
24
24
  class WritePolicy < Policy
25
25
 
26
26
  attr_accessor :record_exists_action, :generation_policy,
27
- :generation, :expiration, :send_key, :commit_level
27
+ :generation, :expiration, :send_key, :commit_level,
28
+ :durable_delete
28
29
 
29
30
  def initialize(opt={})
30
31
  super(opt)
@@ -59,6 +60,12 @@ module Aerospike
59
60
  # The default is to send the user defined key.
60
61
  @send_key = opt[:send_key].nil? ? true : opt[:send_key]
61
62
 
63
+ # If the transaction results in a record deletion, leave a tombstone for
64
+ # the record. This prevents deleted records from reappearing after node
65
+ # failures.
66
+ # Valid for Aerospike Server Enterprise Edition 3.10+ only.
67
+ @durable_delete = opt.fetch(:durable_delete, false)
68
+
62
69
  self
63
70
  end
64
71
 
@@ -120,6 +120,9 @@ module Aerospike
120
120
  # Returned by Map put and put_items operations when policy is CREATE_ONLY but key already exists
121
121
  ELEMENT_EXISTS = 24
122
122
 
123
+ # Enterprise-only feature not supported by the community edition
124
+ ENTERPRISE_ONLY = 25
125
+
123
126
  # There are no more records left for query.
124
127
  QUERY_END = 50
125
128
 
@@ -302,6 +305,9 @@ module Aerospike
302
305
  when ELEMENT_EXISTS
303
306
  "Element already exists"
304
307
 
308
+ when ENTERPRISE_ONLY
309
+ "Enterprise-only feature not supported by community edition"
310
+
305
311
  when QUERY_END
306
312
  "Query end"
307
313
 
@@ -14,9 +14,6 @@
14
14
  # License for the specific language governing permissions and limitations under
15
15
  # the License.
16
16
 
17
- require 'thread'
18
- require 'timeout'
19
-
20
17
  module Aerospike
21
18
 
22
19
  private
@@ -43,13 +40,10 @@ module Aerospike
43
40
  alias_method :<<, :offer
44
41
 
45
42
  def poll(create_new=true)
46
- res = nil
47
- begin
48
- res = @pool.pop(true) # non_blocking
49
- return res
50
- rescue
51
- return @create_block.call if @create_block && create_new
52
- end
43
+ non_block = true
44
+ @pool.pop(non_block)
45
+ rescue
46
+ @create_block.call() if @create_block && create_new
53
47
  end
54
48
 
55
49
  def empty?
@@ -59,6 +53,11 @@ module Aerospike
59
53
  def length
60
54
  @pool.length
61
55
  end
56
+ alias_method :size, :length
57
+
58
+ def inspect
59
+ "#<Aerospike::Pool: size=#{size}>"
60
+ end
62
61
 
63
62
  end
64
63
 
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Aerospike
3
- VERSION = "2.1.1"
3
+ VERSION = "2.2.0"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aerospike
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Khosrow Afroozeh
@@ -9,14 +9,9 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-08-16 00:00:00.000000000 Z
12
+ date: 2016-09-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- version_requirements: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.0'
20
15
  name: msgpack
21
16
  requirement: !ruby/object:Gem::Requirement
22
17
  requirements:
@@ -25,12 +20,12 @@ dependencies:
25
20
  version: '1.0'
26
21
  type: :runtime
27
22
  prerelease: false
28
- - !ruby/object:Gem::Dependency
29
23
  version_requirements: !ruby/object:Gem::Requirement
30
24
  requirements:
31
25
  - - "~>"
32
26
  - !ruby/object:Gem::Version
33
- version: '3.1'
27
+ version: '1.0'
28
+ - !ruby/object:Gem::Dependency
34
29
  name: bcrypt
35
30
  requirement: !ruby/object:Gem::Requirement
36
31
  requirements:
@@ -39,6 +34,11 @@ dependencies:
39
34
  version: '3.1'
40
35
  type: :runtime
41
36
  prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '3.1'
42
42
  description: Official Aerospike Client for ruby. Access your Aerospike cluster with
43
43
  ease of Ruby.
44
44
  email:
@@ -106,9 +106,11 @@ files:
106
106
  - lib/aerospike/policy/commit_level.rb
107
107
  - lib/aerospike/policy/consistency_level.rb
108
108
  - lib/aerospike/policy/generation_policy.rb
109
+ - lib/aerospike/policy/operate_policy.rb
109
110
  - lib/aerospike/policy/policy.rb
110
111
  - lib/aerospike/policy/priority.rb
111
112
  - lib/aerospike/policy/query_policy.rb
113
+ - lib/aerospike/policy/record_bin_multiplicity.rb
112
114
  - lib/aerospike/policy/record_exists_action.rb
113
115
  - lib/aerospike/policy/scan_policy.rb
114
116
  - lib/aerospike/policy/write_policy.rb
@@ -157,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
159
  version: '0'
158
160
  requirements: []
159
161
  rubyforge_project:
160
- rubygems_version: 2.6.2
162
+ rubygems_version: 2.5.1
161
163
  signing_key:
162
164
  specification_version: 4
163
165
  summary: An Aerospike driver for Ruby.