aerospike 0.1.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/lib/aerospike.rb +5 -0
  4. data/lib/aerospike/atomic/atomic.rb +3 -1
  5. data/lib/aerospike/client.rb +98 -32
  6. data/lib/aerospike/cluster/cluster.rb +25 -8
  7. data/lib/aerospike/cluster/connection.rb +1 -1
  8. data/lib/aerospike/cluster/node.rb +16 -3
  9. data/lib/aerospike/cluster/node_validator.rb +16 -4
  10. data/lib/aerospike/cluster/partition.rb +1 -1
  11. data/lib/aerospike/cluster/partition_tokenizer_new.rb +4 -2
  12. data/lib/aerospike/cluster/partition_tokenizer_old.rb +1 -1
  13. data/lib/aerospike/command/admin_command.rb +353 -0
  14. data/lib/aerospike/command/batch_command.rb +12 -42
  15. data/lib/aerospike/command/batch_command_exists.rb +1 -1
  16. data/lib/aerospike/command/batch_command_get.rb +1 -1
  17. data/lib/aerospike/command/batch_item.rb +1 -1
  18. data/lib/aerospike/command/batch_node.rb +1 -1
  19. data/lib/aerospike/command/command.rb +9 -14
  20. data/lib/aerospike/command/delete_command.rb +1 -1
  21. data/lib/aerospike/command/execute_command.rb +1 -1
  22. data/lib/aerospike/command/exists_command.rb +1 -1
  23. data/lib/aerospike/command/operate_command.rb +1 -1
  24. data/lib/aerospike/command/read_command.rb +12 -38
  25. data/lib/aerospike/command/read_header_command.rb +2 -2
  26. data/lib/aerospike/command/roles.rb +36 -0
  27. data/lib/aerospike/command/single_command.rb +1 -1
  28. data/lib/aerospike/command/touch_command.rb +1 -1
  29. data/lib/aerospike/command/write_command.rb +1 -1
  30. data/lib/aerospike/info.rb +1 -1
  31. data/lib/aerospike/loggable.rb +1 -1
  32. data/lib/aerospike/policy/admin_policy.rb +33 -0
  33. data/lib/aerospike/policy/batch_policy.rb +5 -5
  34. data/lib/aerospike/policy/client_policy.rb +15 -4
  35. data/lib/aerospike/policy/generation_policy.rb +0 -5
  36. data/lib/aerospike/policy/policy.rb +6 -6
  37. data/lib/aerospike/policy/query_policy.rb +2 -2
  38. data/lib/aerospike/policy/scan_policy.rb +6 -6
  39. data/lib/aerospike/policy/write_policy.rb +8 -8
  40. data/lib/aerospike/query/query_command.rb +1 -1
  41. data/lib/aerospike/query/scan_command.rb +1 -1
  42. data/lib/aerospike/query/stream_command.rb +1 -1
  43. data/lib/aerospike/record.rb +2 -3
  44. data/lib/aerospike/result_code.rb +11 -1
  45. data/lib/aerospike/user_role.rb +30 -0
  46. data/lib/aerospike/utils/buffer.rb +22 -2
  47. data/lib/aerospike/utils/epoc.rb +3 -1
  48. data/lib/aerospike/utils/pool.rb +1 -1
  49. data/lib/aerospike/value/value.rb +12 -13
  50. data/lib/aerospike/version.rb +1 -1
  51. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c3befa3762779a41284c82d7d1c91071b2d808ba
4
- data.tar.gz: e68d7474c1cc4f87b2b4e1ae2dc1f9cf6ce5363b
3
+ metadata.gz: 60bb290526217118edd3256087baf8f3b1979229
4
+ data.tar.gz: 3298f8ddaa97c6d93294f8dfa1610f2b0770b7da
5
5
  SHA512:
6
- metadata.gz: 0670ec0132babe9a91821511c0303c866dd058d35c9e7e6dada688c20ce3d85ae44af4d29734200f8879d95530d94e8d2feff203ddce8f45f034ece463457d0f
7
- data.tar.gz: 6a7ec991acdee8ae19227a33ec72f73bf11a845533032e9555cd3538c362f2398c4e09c2ff0ad5fe55cb60bfcdcbc33a3ace4ab72c93e7c43464f42174772d48
6
+ metadata.gz: 8f0cbc5177d8c217583531fc0408ba07f99d379a66f21e8f723326b06d99aa48d2ab315a636f7fa1ec3497fd52b8aec677b43a195420b289fd091815e80f8a50
7
+ data.tar.gz: 2900d08848a56766a865080a07ad09df17f23f14374eea6a92f873baddb1ee9d172b737f87934f75cfde425822a9f1d0923abc5bb7252d0252df613563a57c36
data/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## Jan 26 2014 (1.0.0)
2
+
3
+ Major release. With this release, Ruby client graduates to version 1.
4
+
5
+ * **Breaking Changes**:
6
+
7
+ * All `policy` initialize signatures have changed. Using policies was not documented, so it shouldn't affect most code. It will however, break any code initializing policies.
8
+ * Removed `Record.dups` and `GenerationPolicy::DUPLICATE`
9
+
10
+ * **New Features**:
11
+
12
+ * Added Security Features: Please consult [Security Docs](https://www.aerospike.com/docs/guide/security.html) on Aerospike website.
13
+
14
+ * `ClientPolicy.User`, `ClientPolicy.Password`
15
+ * `Client.CreateUser()`, `Client.DropUser()`, `Client.ChangePassword()`
16
+ * `Client.GrantRoles()`, `Client.RevokeRoles()`, `Client.ReplaceRoles()`
17
+ * `Client.QueryUser()`, `Client.QueryUsers`
18
+
19
+ * **Fixes**:
20
+
21
+ * fixed size returned from `BytesValue.write`
22
+
1
23
  ## Dec 28 2014 (0.1.6)
2
24
 
3
25
  Minor features added, minor fixes and improvements.
data/lib/aerospike.rb CHANGED
@@ -5,6 +5,7 @@ require "monitor"
5
5
  require "timeout"
6
6
  require 'resolv'
7
7
  require 'msgpack'
8
+ require 'bcrypt'
8
9
 
9
10
  require 'aerospike/atomic/atomic'
10
11
 
@@ -35,6 +36,7 @@ require 'aerospike/command/touch_command'
35
36
  require 'aerospike/command/batch_command_exists'
36
37
  require 'aerospike/command/read_command'
37
38
  require 'aerospike/command/delete_command'
39
+ require 'aerospike/command/admin_command'
38
40
  require 'aerospike/key'
39
41
  require 'aerospike/operation'
40
42
 
@@ -48,6 +50,7 @@ require 'aerospike/policy/scan_policy'
48
50
  require 'aerospike/policy/query_policy'
49
51
  require 'aerospike/policy/consistency_level'
50
52
  require 'aerospike/policy/commit_level'
53
+ require 'aerospike/policy/admin_policy'
51
54
 
52
55
  require 'aerospike/cluster/connection'
53
56
  require 'aerospike/cluster/cluster'
@@ -65,6 +68,8 @@ require 'aerospike/info'
65
68
  require 'aerospike/udf'
66
69
  require 'aerospike/bin'
67
70
  require 'aerospike/aerospike_exception'
71
+ require 'aerospike/user_role'
72
+
68
73
  require 'aerospike/task/index_task'
69
74
  require 'aerospike/task/udf_remove_task'
70
75
  require 'aerospike/task/udf_register_task'
@@ -15,8 +15,10 @@
15
15
 
16
16
  module Aerospike
17
17
 
18
+ private
19
+
18
20
  # Container object for client policy command.
19
- class Atomic
21
+ class Atomic # :nodoc:
20
22
 
21
23
  def initialize(value)
22
24
  @value = value
@@ -36,13 +36,15 @@ module Aerospike
36
36
 
37
37
  class Client
38
38
 
39
- attr_accessor :default_policy, :default_write_policy
39
+ attr_accessor :default_policy, :default_write_policy,
40
+ :default_scan_policy, :default_query_policy, :default_admin_policy
40
41
 
41
42
  def initialize(host, port, options={})
42
43
  @default_policy = Policy.new
43
44
  @default_write_policy = WritePolicy.new
44
45
  @default_scan_policy = ScanPolicy.new
45
46
  @default_query_policy = QueryPolicy.new
47
+ @default_admin_policy = QueryPolicy.new
46
48
 
47
49
  policy = opt_to_client_policy(options)
48
50
 
@@ -594,7 +596,7 @@ module Aerospike
594
596
  begin
595
597
  command.execute
596
598
  rescue => e
597
- Aerospike.logger.error(e) unless e == Rescordset::SCAN_TERMINATED_EXCEPTION
599
+ Aerospike.logger.error(e.backtrace.join("\n")) unless e == SCAN_TERMINATED_EXCEPTION
598
600
  recordset.cancel(e)
599
601
  ensure
600
602
  recordset.thread_finished
@@ -609,7 +611,7 @@ module Aerospike
609
611
  begin
610
612
  command.execute
611
613
  rescue => e
612
- Aerospike.logger.error(e) unless e == Rescordset::SCAN_TERMINATED_EXCEPTION
614
+ Aerospike.logger.error(e.backtrace.join("\n")) unless e == SCAN_TERMINATED_EXCEPTION
613
615
  recordset.cancel(e)
614
616
  ensure
615
617
  recordset.thread_finished
@@ -644,7 +646,7 @@ module Aerospike
644
646
  begin
645
647
  command.execute
646
648
  rescue => e
647
- Aerospike.logger.error(e) unless e == Rescordset::SCAN_TERMINATED_EXCEPTION
649
+ Aerospike.logger.error(e.backtrace.join("\n")) unless e == SCAN_TERMINATED_EXCEPTION
648
650
  recordset.cancel(e)
649
651
  ensure
650
652
  recordset.thread_finished
@@ -684,7 +686,7 @@ module Aerospike
684
686
  begin
685
687
  command.execute
686
688
  rescue => e
687
- Aerospike.logger.error(e) unless e == Rescordset::QUERY_TERMINATED_EXCEPTION
689
+ Aerospike.logger.error(e.backtrace.join("\n")) unless e == QUERY_TERMINATED_EXCEPTION
688
690
  recordset.cancel(e)
689
691
  ensure
690
692
  recordset.thread_finished
@@ -695,6 +697,82 @@ module Aerospike
695
697
  recordset
696
698
  end
697
699
 
700
+ #-------------------------------------------------------
701
+ # User administration
702
+ #-------------------------------------------------------
703
+
704
+ # Create user with password and roles. Clear-text password will be hashed using bcrypt
705
+ # before sending to server.
706
+ def create_user(user, password, roles, options={})
707
+ policy = opt_to_admin_policy(options)
708
+ hash = AdminCommand.hash_password(password)
709
+ command = AdminCommand.new
710
+ command.create_user(@cluster, policy, user, hash, roles)
711
+ end
712
+
713
+ # Remove user from cluster.
714
+ def drop_user(user, options={})
715
+ policy = opt_to_admin_policy(options)
716
+ command = AdminCommand.new
717
+ command.drop_user(@cluster, policy, user)
718
+ end
719
+
720
+ # Change user's password. Clear-text password will be hashed using bcrypt before sending to server.
721
+ def change_password(user, password, options={})
722
+ policy = opt_to_admin_policy(options)
723
+ if @cluster.user == ''
724
+ return NewAerospikeError(INVALID_USER)
725
+ end
726
+
727
+ hash = AdminCommand.hash_password(password)
728
+ command = AdminCommand.new
729
+
730
+ if user == @cluster.user
731
+ # Change own password.
732
+ command.change_password(@cluster, policy, user, hash)
733
+ else
734
+ # Change other user's password by user admin.
735
+ command.set_password(@cluster, policy, user, hash)
736
+ end
737
+
738
+ @cluster.change_password(user, hash)
739
+ end
740
+
741
+ # Add roles to user's list of roles.
742
+ def grant_roles(user, roles, options={})
743
+ policy = opt_to_admin_policy(options)
744
+ command = AdminCommand.new
745
+ command.grant_roles(@cluster, policy, user, roles)
746
+ end
747
+
748
+ # Remove roles from user's list of roles.
749
+ def revoke_roles(user, roles, options={})
750
+ policy = opt_to_admin_policy(options)
751
+ command = AdminCommand.new
752
+ command.revoke_roles(@cluster, policy, user, roles)
753
+ end
754
+
755
+ # Replace user's list of roles.
756
+ def replace_roles(user, roles, options={})
757
+ policy = opt_to_admin_policy(options)
758
+ command = AdminCommand.new
759
+ command.replace_roles(@cluster, policy, user, roles)
760
+ end
761
+
762
+ # Retrieve roles for a given user.
763
+ def query_user(user, options={})
764
+ policy = opt_to_admin_policy(options)
765
+ command = AdminCommand.new
766
+ command.query_user(@cluster, policy, user)
767
+ end
768
+
769
+ # Retrieve all users and their roles.
770
+ def query_users(options={})
771
+ policy = opt_to_admin_policy(options)
772
+ command = AdminCommand.new
773
+ command.query_users(@cluster, policy)
774
+ end
775
+
698
776
  private
699
777
 
700
778
  def send_info_command(policy, command)
@@ -720,11 +798,7 @@ module Aerospike
720
798
  elsif options.is_a?(ClientPolicy)
721
799
  options
722
800
  elsif options.is_a?(Hash)
723
- ClientPolicy.new(
724
- options[:timeout],
725
- options[:connection_queue_size],
726
- options[:fail_if_not_connected]
727
- )
801
+ ClientPolicy.new(options)
728
802
  end
729
803
  end
730
804
 
@@ -734,13 +808,7 @@ module Aerospike
734
808
  elsif options.is_a?(Policy)
735
809
  options
736
810
  elsif options.is_a?(Hash)
737
- Policy.new(
738
- options[:priority],
739
- options[:timeout],
740
- options[:max_retiries],
741
- options[:sleep_between_retries],
742
- options[:consistency_level]
743
- )
811
+ Policy.new(options)
744
812
  end
745
813
  end
746
814
 
@@ -750,14 +818,7 @@ module Aerospike
750
818
  elsif options.is_a?(WritePolicy)
751
819
  options
752
820
  elsif options.is_a?(Hash)
753
- WritePolicy.new(
754
- options[:record_exists_action],
755
- options[:gen_policy],
756
- options[:generation],
757
- options[:expiration],
758
- options[:send_key],
759
- options[:commit_level]
760
- )
821
+ WritePolicy.new(options)
761
822
  end
762
823
  end
763
824
 
@@ -767,12 +828,7 @@ module Aerospike
767
828
  elsif options.is_a?(ScanPolicy)
768
829
  options
769
830
  elsif options.is_a?(Hash)
770
- ScanPolicy.new(
771
- options[:scan_percent],
772
- options[:concurrent_nodes],
773
- options[:include_bin_data],
774
- options[:fail_on_cluster_change]
775
- )
831
+ ScanPolicy.new(options)
776
832
  end
777
833
  end
778
834
 
@@ -782,7 +838,17 @@ module Aerospike
782
838
  elsif options.is_a?(QueryPolicy)
783
839
  options
784
840
  elsif options.is_a?(Hash)
785
- QueryPolicy.new()
841
+ QueryPolicy.new(options)
842
+ end
843
+ end
844
+
845
+ def opt_to_admin_policy(options)
846
+ if options.nil? || options == {}
847
+ @default_admin_policy
848
+ elsif options.is_a?(AdminPolicy)
849
+ options
850
+ elsif options.is_a?(Hash)
851
+ AdminPolicy.new(options)
786
852
  end
787
853
  end
788
854
 
@@ -25,7 +25,7 @@ module Aerospike
25
25
 
26
26
  class Cluster
27
27
 
28
- attr_reader :connection_timeout, :connection_queue_size
28
+ attr_reader :connection_timeout, :connection_queue_size, :user, :password
29
29
 
30
30
  def initialize(policy, *hosts)
31
31
  @cluster_seeds = hosts
@@ -38,6 +38,12 @@ module Aerospike
38
38
  @closed = Atomic.new(false)
39
39
  @mutex = Mutex.new
40
40
 
41
+ # setup auth info for cluster
42
+ if policy.requires_authentication
43
+ @user = policy.user
44
+ @password = AdminCommand.hash_password(policy.password)
45
+ end
46
+
41
47
  wait_till_stablized
42
48
 
43
49
  if policy.fail_if_not_connected && !connected?
@@ -88,7 +94,8 @@ module Aerospike
88
94
  # Must copy array reference for copy on write semantics to work.
89
95
  node_array = nodes
90
96
  length = node_array.length
91
- for i in 0..length
97
+ i = 0
98
+ while i < length
92
99
  # Must handle concurrency with other non-tending threads, so node_index is consistent.
93
100
  index = (@node_index.update{|v| v+1} % node_array.length).abs
94
101
  node = node_array[index]
@@ -96,6 +103,8 @@ module Aerospike
96
103
  if node.active?
97
104
  return node
98
105
  end
106
+
107
+ i = i.succ
99
108
  end
100
109
  raise Aerospike::Exceptions::InvalidNode.new
101
110
  end
@@ -166,6 +175,11 @@ module Aerospike
166
175
  end
167
176
  end
168
177
 
178
+ def change_password(user, password)
179
+ # change password ONLY if the user is the same
180
+ @password = password if @user == user
181
+ end
182
+
169
183
  private
170
184
 
171
185
  def launch_tend_thread
@@ -210,7 +224,7 @@ module Aerospike
210
224
  refresh_count += 1
211
225
  friend_list.concat(friends) if friends
212
226
  rescue => e
213
- Aerospike.logger.error("Node `#{node}` refresh failed: #{e.to_s}")
227
+ Aerospike.logger.error("Node `#{node}` refresh failed: #{e.backtrace.join("\n")}")
214
228
  end
215
229
  end
216
230
  end
@@ -283,9 +297,9 @@ module Aerospike
283
297
 
284
298
  seed_array.each do |seed|
285
299
  begin
286
- seed_node_validator = NodeValidator.new(seed, @connection_timeout)
300
+ seed_node_validator = NodeValidator.new(self, seed, @connection_timeout)
287
301
  rescue => e
288
- Aerospike.logger.error("Seed #{seed.to_s} failed: #{e}")
302
+ Aerospike.logger.error("Seed #{seed.to_s} failed: #{e.backtrace.join("\n")}")
289
303
  next
290
304
  end
291
305
 
@@ -297,7 +311,7 @@ module Aerospike
297
311
  nv = seed_node_validator
298
312
  else
299
313
  begin
300
- nv = NodeValidator.new(aliass, @connection_timeout)
314
+ nv = NodeValidator.new(self, aliass, @connection_timeout)
301
315
  rescue Exection => e
302
316
  Aerospike.logger.error("Seed #{seed.to_s} failed: #{e}")
303
317
  next
@@ -345,7 +359,7 @@ module Aerospike
345
359
 
346
360
  hosts.each do |host|
347
361
  begin
348
- nv = NodeValidator.new(host, @connection_timeout)
362
+ nv = NodeValidator.new(self, host, @connection_timeout)
349
363
 
350
364
  # if node is already in cluster's node list,
351
365
  # or already included in the list to be added, we should skip it
@@ -432,12 +446,15 @@ module Aerospike
432
446
  partitions_list.each do |node_array|
433
447
  max = node_array.length
434
448
 
435
- for i in 0...max
449
+ i = 0
450
+ while i < max
436
451
  node = node_array[i]
437
452
  # Use reference equality for performance.
438
453
  if node == filter
439
454
  return true
440
455
  end
456
+
457
+ i = i.succ
441
458
  end
442
459
  end
443
460
  false
@@ -20,7 +20,7 @@ module Aerospike
20
20
 
21
21
  private
22
22
 
23
- class Connection
23
+ class Connection # :nodoc:
24
24
 
25
25
  def initialize(host, port, timeout = 30)
26
26
 
@@ -47,12 +47,25 @@ module Aerospike
47
47
  @connections = Pool.new(@cluster.connection_queue_size)
48
48
  @connections.create_block = Proc.new do
49
49
  while conn = Connection.new(@host.name, @host.port, @cluster.connection_timeout)
50
+
51
+ # need to authenticate
52
+ if @cluster.user && @cluster.user != ''
53
+ begin
54
+ command = AdminCommand.new
55
+ command.authenticate(conn, @cluster.user, @cluster.password)
56
+ rescue => e
57
+ # Socket not authenticated. Do not put back into pool.
58
+ conn.close if conn
59
+ raise e
60
+ end
61
+ end
62
+
50
63
  break if conn.connected?
51
64
  end
52
65
  conn
53
66
  end
54
67
 
55
- @connections.cleanup_block = Proc.new { |conn| conn.close }
68
+ @connections.cleanup_block = Proc.new { |conn| conn.close if conn }
56
69
  end
57
70
 
58
71
  # Request current status from server node, and update node with the result
@@ -65,7 +78,7 @@ module Aerospike
65
78
  rescue => e
66
79
  Aerospike.logger.error(e)
67
80
 
68
- conn.close
81
+ conn.close if conn
69
82
  decrease_health
70
83
 
71
84
  raise e
@@ -179,7 +192,7 @@ module Aerospike
179
192
  # drain connections and close all of them
180
193
  # non-blocking, does not call create_block when passed false
181
194
  while conn = @connections.poll(false)
182
- conn.close
195
+ conn.close if conn
183
196
  end
184
197
  end
185
198