zk 0.9.1 → 1.0.0.rc.1

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.
Files changed (63) hide show
  1. data/.gitignore +2 -2
  2. data/Gemfile +3 -4
  3. data/README.markdown +14 -5
  4. data/RELEASES.markdown +69 -1
  5. data/Rakefile +50 -18
  6. data/docs/examples/block_until_node_deleted_ex.rb +63 -0
  7. data/docs/examples/events_01.rb +36 -0
  8. data/docs/examples/events_02.rb +41 -0
  9. data/lib/{z_k → zk}/client/base.rb +87 -30
  10. data/lib/{z_k → zk}/client/conveniences.rb +0 -1
  11. data/lib/{z_k → zk}/client/state_mixin.rb +0 -0
  12. data/lib/zk/client/threaded.rb +196 -0
  13. data/lib/{z_k → zk}/client/unixisms.rb +0 -0
  14. data/lib/zk/client.rb +59 -0
  15. data/lib/zk/core_ext.rb +75 -0
  16. data/lib/{z_k → zk}/election.rb +0 -0
  17. data/lib/zk/event.rb +168 -0
  18. data/lib/{z_k → zk}/event_handler.rb +53 -28
  19. data/lib/zk/event_handler_subscription.rb +68 -0
  20. data/lib/{z_k → zk}/exceptions.rb +38 -23
  21. data/lib/zk/extensions.rb +79 -0
  22. data/lib/{z_k → zk}/find.rb +0 -0
  23. data/lib/{z_k → zk}/locker.rb +0 -0
  24. data/lib/{z_k → zk}/logging.rb +0 -0
  25. data/lib/{z_k → zk}/message_queue.rb +8 -4
  26. data/lib/{z_k → zk}/mongoid.rb +0 -0
  27. data/lib/{z_k → zk}/pool.rb +0 -0
  28. data/lib/zk/stat.rb +115 -0
  29. data/lib/{z_k → zk}/threadpool.rb +52 -4
  30. data/lib/zk/version.rb +3 -0
  31. data/lib/zk.rb +238 -1
  32. data/spec/message_queue_spec.rb +2 -2
  33. data/spec/shared/client_contexts.rb +8 -20
  34. data/spec/shared/client_examples.rb +136 -2
  35. data/spec/spec_helper.rb +4 -2
  36. data/spec/support/event_catcher.rb +11 -0
  37. data/spec/support/exist_matcher.rb +6 -0
  38. data/spec/support/logging.rb +2 -1
  39. data/spec/watch_spec.rb +194 -10
  40. data/spec/{z_k → zk}/client/locking_and_session_death_spec.rb +0 -32
  41. data/spec/zk/client_spec.rb +23 -0
  42. data/spec/{z_k → zk}/election_spec.rb +0 -0
  43. data/spec/{z_k → zk}/extensions_spec.rb +0 -0
  44. data/spec/{z_k → zk}/locker_spec.rb +0 -40
  45. data/spec/zk/module_spec.rb +185 -0
  46. data/spec/{z_k → zk}/mongoid_spec.rb +0 -2
  47. data/spec/{z_k → zk}/pool_spec.rb +0 -2
  48. data/spec/{z_k → zk}/threadpool_spec.rb +32 -4
  49. data/spec/zookeeper_spec.rb +1 -6
  50. data/zk.gemspec +2 -2
  51. metadata +64 -56
  52. data/lib/z_k/client/continuation_proxy.rb +0 -109
  53. data/lib/z_k/client/drop_box.rb +0 -98
  54. data/lib/z_k/client/multiplexed.rb +0 -28
  55. data/lib/z_k/client/threaded.rb +0 -76
  56. data/lib/z_k/client.rb +0 -35
  57. data/lib/z_k/event_handler_subscription.rb +0 -36
  58. data/lib/z_k/extensions.rb +0 -155
  59. data/lib/z_k/version.rb +0 -3
  60. data/lib/z_k.rb +0 -97
  61. data/spec/z_k/client/drop_box_spec.rb +0 -90
  62. data/spec/z_k/client/multiplexed_spec.rb +0 -20
  63. data/spec/z_k/client_spec.rb +0 -7
@@ -1,155 +0,0 @@
1
- module ZK
2
- module Extensions
3
- # some extensions to the ZookeeperCallbacks classes, mainly convenience
4
- # interrogators
5
- module Callbacks
6
- module Callback
7
- # allow access to the connection that fired this callback
8
- attr_accessor :zk
9
-
10
- def self.included(mod)
11
- mod.extend(ZK::Extensions::Callbacks::Callback::ClassMethods)
12
- end
13
-
14
- module ClassMethods
15
- # allows for easier construction of a user callback block that will be
16
- # called with the callback object itself as an argument.
17
- #
18
- # *args, if given, will be passed on *after* the callback
19
- #
20
- # @example
21
- #
22
- # WatcherCallback.create do |cb|
23
- # puts "watcher callback called with argument: #{cb.inspect}"
24
- # end
25
- #
26
- # "watcher callback called with argument: #<ZookeeperCallbacks::WatcherCallback:0x1018a3958 @state=3, @type=1, ...>"
27
- #
28
- #
29
- def create(*args, &block)
30
- # honestly, i have no idea how this could *possibly* work, but it does...
31
- cb_inst = new { block.call(cb_inst) }
32
- end
33
- end
34
- end
35
-
36
- module WatcherCallbackExt
37
- include ZookeeperConstants
38
-
39
- EVENT_NAME_MAP = {
40
- 1 => 'created',
41
- 2 => 'deleted',
42
- 3 => 'changed',
43
- 4 => 'child',
44
- -1 => 'session',
45
- -2 => 'notwatching',
46
- }.freeze
47
-
48
- STATES = %w[connecting associating connected auth_failed expired_session].freeze unless defined?(STATES)
49
-
50
- EVENT_TYPES = %w[created deleted changed child session notwatching].freeze unless defined?(EVENT_TYPES)
51
-
52
- STATES.each do |state|
53
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
54
- def state_#{state}?
55
- @state == ZOO_#{state.upcase}_STATE
56
- end
57
- RUBY
58
- end
59
-
60
- EVENT_TYPES.each do |ev|
61
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
62
- def node_#{ev}?
63
- @type == ZOO_#{ev.upcase}_EVENT
64
- end
65
- RUBY
66
- end
67
-
68
- alias :node_not_watching? :node_notwatching?
69
-
70
- # has this watcher been called because of a change in connection state?
71
- def state_event?
72
- path.nil? or path.empty?
73
- end
74
- alias session_event? state_event?
75
-
76
- # has this watcher been called because of a change to a zookeeper node?
77
- def node_event?
78
- path and not path.empty?
79
- end
80
-
81
- # cause this watch to be re-registered
82
- # def renew_watch!
83
- # zk.stat(path, :watch => true)
84
- # nil
85
- # end
86
- end
87
- end # Callbacks
88
-
89
- # aliases for long-names of properties from mb-zookeeper version
90
- module Stat
91
- [ %w[created_zxid czxid],
92
- %w[last_modified_zxid mzxid],
93
- %w[created_time ctime],
94
- %w[last_modified_time mtime],
95
- %w[child_list_version cversion],
96
- %w[acl_list_version aversion] ].each do |long, short|
97
-
98
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
99
- def #{long}
100
- #{short}
101
- end
102
- RUBY
103
- end
104
-
105
- MEMBERS = [:version, :exists, :czxid, :mzxid, :ctime, :mtime, :cversion, :aversion, :ephemeralOwner, :dataLength, :numChildren, :pzxid]
106
-
107
- def self.included(mod)
108
- mod.class_eval do
109
- unless method_defined?(:exists?)
110
- alias :exists? :exists
111
- end
112
- end
113
- end
114
-
115
- def ==(other)
116
- MEMBERS.all? { |m| self.__send__(m) == other.__send__(m) }
117
- end
118
- end
119
- end # Extensions
120
- end # ZK
121
-
122
- # ZookeeperCallbacks::Callback.extend(ZK::Extensions::Callbacks::Callback)
123
- ZookeeperCallbacks::Callback.send(:include, ZK::Extensions::Callbacks::Callback)
124
- ZookeeperCallbacks::WatcherCallback.send(:include, ZK::Extensions::Callbacks::WatcherCallbackExt)
125
- ZookeeperStat::Stat.send(:include, ZK::Extensions::Stat)
126
-
127
- # Include the InterruptedSession module in key ZookeeperExceptions to allow
128
- # clients to catch a single error type when waiting on a node (for example)
129
-
130
- [:ConnectionClosed, :NotConnected, :SessionExpired, :SessionMoved, :ConnectionLoss].each do |class_name|
131
- ZookeeperExceptions::ZookeeperException.const_get(class_name).tap do |klass|
132
- klass.__send__(:include, ZK::Exceptions::InterruptedSession)
133
- end
134
- end
135
-
136
- class ::Exception
137
- unless method_defined?(:to_std_format)
138
- def to_std_format
139
- ary = ["#{self.class}: #{message}"]
140
- ary.concat(backtrace || [])
141
- ary.join("\n\t")
142
- end
143
- end
144
- end
145
-
146
- class ::Thread
147
- def zk_mongoid_lock_registry
148
- self[:_zk_mongoid_lock_registry]
149
- end
150
-
151
- def zk_mongoid_lock_registry=(obj)
152
- self[:_zk_mongoid_lock_registry] = obj
153
- end
154
- end
155
-
data/lib/z_k/version.rb DELETED
@@ -1,3 +0,0 @@
1
- module ZK
2
- VERSION = "0.9.1"
3
- end
data/lib/z_k.rb DELETED
@@ -1,97 +0,0 @@
1
- require 'rubygems'
2
-
3
- require 'logger'
4
- require 'zookeeper'
5
- require 'forwardable'
6
- require 'thread'
7
- require 'monitor'
8
- require 'set'
9
-
10
- require 'z_k/logging'
11
- require 'z_k/exceptions'
12
- require 'z_k/threadpool'
13
- require 'z_k/event_handler_subscription'
14
- require 'z_k/event_handler'
15
- require 'z_k/message_queue'
16
- # require 'z_k/locker_base'
17
- require 'z_k/locker'
18
- require 'z_k/extensions'
19
- require 'z_k/election'
20
- require 'z_k/mongoid'
21
- require 'z_k/client'
22
- require 'z_k/pool'
23
- require 'z_k/find'
24
-
25
- module ZK
26
- ZK_ROOT = File.expand_path('../..', __FILE__)
27
-
28
- KILL_TOKEN = Object.new unless defined?(KILL_TOKEN)
29
-
30
- unless @logger
31
- @logger = Logger.new($stderr).tap { |n| n.level = Logger::ERROR }
32
- end
33
-
34
- # The logger used by the ZK library. uses a Logger stderr with Logger::ERROR
35
- # level. The only thing that should ever be logged are exceptions that are
36
- # swallowed by background threads.
37
- #
38
- # You can change this logger by setting ZK#logger= to an object that
39
- # implements the stdllb Logger API.
40
- #
41
- def self.logger
42
- @logger
43
- end
44
-
45
- # Assign the Logger instance to be used by ZK
46
- def self.logger=(logger)
47
- @logger = logger
48
- end
49
-
50
- # Create a new ZK::Client instance. If no arguments are given, the default
51
- # config of 'localhost:2181' will be used. Otherwise all args will be passed
52
- # to ZK::Client#new
53
- #
54
- # if a block is given, it will be yielded the client *before* the connection
55
- # is established, this is useful for registering connected-state handlers.
56
- #
57
- def self.new(*args, &block)
58
- # XXX: might need to do some param parsing here
59
-
60
- opts = args.pop if args.last.kind_of?(Hash)
61
- args = %w[localhost:2181] if args.empty?
62
-
63
- # ignore opts for now
64
- Client.new(*args, &block)
65
- end
66
-
67
- # Like new, yields a connection to the given block and closes it when the
68
- # block returns
69
- def self.open(*args)
70
- cnx = new(*args)
71
- yield cnx
72
- ensure
73
- cnx.close! if cnx
74
- end
75
-
76
- # creates a new ZK::Pool::Bounded with the default options.
77
- def self.new_pool(host, opts={})
78
- ZK::Pool::Bounded.new(host, opts)
79
- end
80
-
81
- # Eventually this will implement proper File.join-like behavior, but only
82
- # using the '/' char for a separator. for right now, this simply delegates to
83
- # File.join
84
- #--
85
- # like File.join but ignores $INPUT_RECORD_SEPARATOR (i.e. $/, which is
86
- # platform dependent) and only uses the '/' character
87
- def self.join(*paths)
88
- File.join(*paths)
89
- end
90
-
91
- protected
92
- def self.chomp_sep(str)
93
- p = (p[0] == ?/ ) ? p[1..-1] : p
94
- p = (p[-1] == ?/) ? p[0..-2] : p
95
- end
96
- end
97
-
@@ -1,90 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module ZK
4
- module Client
5
- describe 'ZK::Client::DropBox' do
6
- let(:drop_box) { DropBox.new }
7
-
8
- after do
9
- DropBox.remove_current
10
- end
11
-
12
- it %[should start out with an undefined value] do
13
- drop_box.value.should == DropBox::UNDEFINED
14
- end
15
-
16
- it %[should block the caller waiting for a response] do
17
- @rv = nil
18
-
19
- th1 = Thread.new do
20
- Thread.current.abort_on_exception = true
21
- @rv = drop_box.pop
22
- end
23
-
24
- wait_until(2) { th1.status == 'sleep' }
25
-
26
- th1.status.should == 'sleep'
27
-
28
- th2 = Thread.new do
29
- drop_box.push :result
30
- end
31
-
32
- th2.join(2).should == th2
33
- th1.join(2).should == th1
34
-
35
- @rv.should == :result
36
- end
37
-
38
- describe :oh_noes! do
39
- let(:error_class) { SpecialHappyFuntimeError }
40
- let(:error_msg) { 'this is a unique message' }
41
-
42
- it %[should wake the caller by raising the exception class and message given] do
43
- drop_box.should_not be_done # sanity check
44
-
45
- th1 = Thread.new do
46
- drop_box.pop
47
- end
48
-
49
- wait_until(2) { th1.status == 'sleep' }
50
-
51
- th1.status.should == 'sleep'
52
-
53
- drop_box.oh_noes!(error_class, error_msg).should_not be_nil
54
-
55
- lambda { th1.join(2) }.should raise_error(error_class, error_msg)
56
-
57
- drop_box.should be_done
58
- end
59
- end
60
-
61
- describe :done? do
62
- it %[should be done if the value is defined] do
63
- drop_box.should_not be_done
64
- drop_box.push :defined
65
- drop_box.should be_done
66
- end
67
-
68
- it %[should not be done once cleared] do
69
- drop_box.push :defined
70
- drop_box.should be_done
71
- drop_box.clear
72
- drop_box.should_not be_done
73
- end
74
- end
75
-
76
- describe :with_current do
77
- it %[should clear the current thread's drop_box once the block exits] do
78
- DropBox.with_current do |c|
79
- c.should_not be_done
80
- c.push 'yo_mama'
81
- c.should be_done
82
- end
83
-
84
- DropBox.current.should_not be_done
85
- end
86
- end
87
- end
88
- end
89
- end
90
-
@@ -1,20 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'ZK::Client::Multiplexed', :client => :multiplexed do
4
- before do
5
- @zk = ZK::Client::Multiplexed.new("localhost:#{ZK_TEST_PORT}").tap do |zk|
6
- wait_until { zk.connected? }
7
- end
8
-
9
- @zk.rm_rf('/test')
10
- end
11
-
12
- after do
13
- @zk.rm_rf('/test')
14
- @zk.close!
15
-
16
- wait_until(2) { @zk.closed? }
17
- end
18
-
19
- it_should_behave_like 'client'
20
- end
@@ -1,7 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ZK::Client::Threaded do
4
- include_context 'threaded client connection'
5
- it_should_behave_like 'client'
6
- end
7
-