aerospike 2.1.1 → 2.2.0

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