zookeeper 0.9.4 → 1.0.0.beta.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 (44) hide show
  1. data/.dotfiles/rvmrc +1 -0
  2. data/.gitignore +3 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +22 -0
  5. data/CHANGELOG +38 -5
  6. data/Gemfile +18 -1
  7. data/README.markdown +2 -0
  8. data/Rakefile +47 -109
  9. data/ext/c_zookeeper.rb +10 -6
  10. data/ext/zookeeper_base.rb +23 -11
  11. data/ext/zookeeper_c.c +14 -10
  12. data/java/{zookeeper_base.rb → java_base.rb} +13 -12
  13. data/lib/zookeeper.rb +32 -244
  14. data/lib/zookeeper/acls.rb +17 -13
  15. data/lib/zookeeper/callbacks.rb +28 -11
  16. data/lib/zookeeper/client.rb +30 -0
  17. data/lib/zookeeper/client_methods.rb +241 -0
  18. data/lib/zookeeper/common.rb +13 -12
  19. data/lib/zookeeper/common/queue_with_pipe.rb +3 -7
  20. data/lib/zookeeper/compatibility.rb +135 -0
  21. data/lib/zookeeper/constants.rb +35 -1
  22. data/lib/zookeeper/em_client.rb +1 -1
  23. data/lib/zookeeper/exceptions.rb +117 -93
  24. data/lib/zookeeper/rake_tasks.rb +165 -0
  25. data/lib/zookeeper/stat.rb +16 -16
  26. data/lib/zookeeper/version.rb +2 -4
  27. data/scripts/upgrade-1.0-sed-alike.rb +46 -0
  28. data/spec/c_zookeeper_spec.rb +10 -9
  29. data/spec/chrooted_connection_spec.rb +2 -2
  30. data/spec/default_watcher_spec.rb +4 -4
  31. data/spec/em_spec.rb +1 -1
  32. data/spec/shared/connection_examples.rb +52 -37
  33. data/spec/spec_helper.rb +22 -84
  34. data/spec/support/00_spawn_zookeeper.rb +20 -0
  35. data/spec/support/zookeeper_spec_helpers.rb +84 -0
  36. data/spec/zookeeper_spec.rb +1 -1
  37. metadata +47 -34
  38. data/examples/cloud_config.rb +0 -125
  39. data/test/test_basic.rb +0 -37
  40. data/test/test_callback1.rb +0 -36
  41. data/test/test_close.rb +0 -16
  42. data/test/test_esoteric.rb +0 -7
  43. data/test/test_watcher1.rb +0 -56
  44. data/test/test_watcher2.rb +0 -52
@@ -4,9 +4,13 @@ $LOAD_PATH.uniq!
4
4
 
5
5
  require 'rubygems'
6
6
 
7
- gem 'flexmock', '~> 0.8.11'
7
+ release_ops_path = File.expand_path('../../releaseops/lib', __FILE__)
8
+
9
+ if File.exists?(release_ops_path)
10
+ require File.join(release_ops_path, 'releaseops')
11
+ ReleaseOps::SimpleCov.maybe_start
12
+ end
8
13
 
9
- require 'flexmock'
10
14
  require 'zookeeper'
11
15
 
12
16
  Dir[File.expand_path('../support/**/*.rb', __FILE__)].sort.each { |f| require(f) }
@@ -26,94 +30,28 @@ if ENV['ZKRB_NOLOG']
26
30
  end
27
31
 
28
32
 
29
- module ZookeeperSpecHeleprs
30
- class TimeoutError < StandardError; end
31
-
32
- def logger
33
- Zookeeper.logger
34
- end
35
-
36
- def ensure_node(zk, path, data)
37
- return if zk.closed?
38
- if zk.stat(:path => path)[:stat].exists?
39
- zk.set(:path => path, :data => data)
40
- else
41
- zk.create(:path => path, :data => data)
42
- end
43
- end
44
-
45
- def with_open_zk(host='localhost:2181')
46
- z = Zookeeper.new(host)
47
- yield z
48
- ensure
49
- if z
50
- unless z.closed?
51
- z.close
33
+ RSpec.configure do |config|
34
+ config.mock_with :rspec
35
+ config.include ZookeeperSpecHeleprs
36
+ config.extend ZookeeperSpecHeleprs
52
37
 
53
- wait_until do
54
- begin
55
- !z.connected?
56
- rescue RuntimeError
57
- true
58
- end
59
- end
60
- end
61
- end
62
- end
38
+ if Zookeeper.spawn_zookeeper?
39
+ require 'zk-server'
63
40
 
64
- # this is not as safe as the one in ZK, just to be used to clean up
65
- # when we're the only one adjusting a particular path
66
- def rm_rf(z, path)
67
- z.get_children(:path => path).tap do |h|
68
- if h[:rc].zero?
69
- h[:children].each do |child|
70
- rm_rf(z, File.join(path, child))
71
- end
72
- elsif h[:rc] == ZookeeperExceptions::ZNONODE
73
- # no-op
74
- else
75
- raise "Oh noes! unexpected return value! #{h.inspect}"
41
+ config.before(:suite) do
42
+ Zookeeper.logger.debug { "Starting zookeeper service" }
43
+ ZK::Server.run do |c|
44
+ c.base_dir = File.expand_path('../../.zkserver', __FILE__)
45
+ c.client_port = Zookeeper.test_port
46
+ c.force_sync = false
47
+ c.snap_count = 1_000_000
76
48
  end
77
49
  end
78
50
 
79
- rv = z.delete(:path => path)
80
-
81
- unless (rv[:rc].zero? or rv[:rc] == ZookeeperExceptions::ZNONODE)
82
- raise "oh noes! failed to delete #{path}"
83
- end
84
-
85
- path
86
- end
87
-
88
-
89
- # method to wait until block passed returns true or timeout (default is 10 seconds) is reached
90
- # raises TiemoutError on timeout
91
- def wait_until(timeout=10)
92
- time_to_stop = Time.now + timeout
93
- while true
94
- rval = yield
95
- return rval if rval
96
- raise TimeoutError, "timeout of #{timeout}s exceeded" if Time.now > time_to_stop
97
- Thread.pass
98
- end
99
- end
100
-
101
- # inverse of wait_until
102
- def wait_while(timeout=10)
103
- time_to_stop = Time.now + timeout
104
- while true
105
- rval = yield
106
- return rval unless rval
107
- raise TimeoutError, "timeout of #{timeout}s exceeded" if Time.now > time_to_stop
108
- Thread.pass
51
+ config.after(:suite) do
52
+ Zookeeper.logger.debug { "stopping zookeeper service" }
53
+ ZK::Server.shutdown
109
54
  end
110
55
  end
111
56
  end
112
57
 
113
- RSpec.configure do |config|
114
- config.mock_with :flexmock
115
- config.include ZookeeperSpecHeleprs
116
- config.extend ZookeeperSpecHeleprs
117
- end
118
-
119
-
@@ -0,0 +1,20 @@
1
+ module Zookeeper
2
+ def self.spawn_zookeeper?
3
+ !!ENV['SPAWN_ZOOKEEPER']
4
+ end
5
+
6
+ def self.travis?
7
+ !!ENV['TRAVIS']
8
+ end
9
+
10
+ @test_port ||= spawn_zookeeper? ? 21811 : 2181
11
+
12
+ class << self
13
+ attr_accessor :test_port
14
+ end
15
+
16
+ def self.default_cnx_str
17
+ "localhost:#{test_port}"
18
+ end
19
+ end
20
+
@@ -0,0 +1,84 @@
1
+ module ZookeeperSpecHeleprs
2
+ class TimeoutError < StandardError; end
3
+
4
+ def logger
5
+ Zookeeper.logger
6
+ end
7
+
8
+ def ensure_node(zk, path, data)
9
+ return if zk.closed?
10
+ if zk.stat(:path => path)[:stat].exists?
11
+ zk.set(:path => path, :data => data)
12
+ else
13
+ zk.create(:path => path, :data => data)
14
+ end
15
+ end
16
+
17
+ def with_open_zk(host=nil)
18
+ z = Zookeeper.new(Zookeeper.default_cnx_str)
19
+ yield z
20
+ ensure
21
+ if z
22
+ unless z.closed?
23
+ z.close
24
+
25
+ wait_until do
26
+ begin
27
+ !z.connected?
28
+ rescue RuntimeError
29
+ true
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ # this is not as safe as the one in ZK, just to be used to clean up
37
+ # when we're the only one adjusting a particular path
38
+ def rm_rf(z, path)
39
+ z.get_children(:path => path).tap do |h|
40
+ if h[:rc].zero?
41
+ h[:children].each do |child|
42
+ rm_rf(z, File.join(path, child))
43
+ end
44
+ elsif h[:rc] == Zookeeper::Exceptions::ZNONODE
45
+ # no-op
46
+ else
47
+ raise "Oh noes! unexpected return value! #{h.inspect}"
48
+ end
49
+ end
50
+
51
+ rv = z.delete(:path => path)
52
+
53
+ unless (rv[:rc].zero? or rv[:rc] == Zookeeper::Exceptions::ZNONODE)
54
+ raise "oh noes! failed to delete #{path}"
55
+ end
56
+
57
+ path
58
+ end
59
+
60
+
61
+ # method to wait until block passed returns true or timeout (default is 10 seconds) is reached
62
+ # raises TiemoutError on timeout
63
+ def wait_until(timeout=10)
64
+ time_to_stop = Time.now + timeout
65
+ while true
66
+ rval = yield
67
+ return rval if rval
68
+ raise TimeoutError, "timeout of #{timeout}s exceeded" if Time.now > time_to_stop
69
+ Thread.pass
70
+ end
71
+ end
72
+
73
+ # inverse of wait_until
74
+ def wait_while(timeout=10)
75
+ time_to_stop = Time.now + timeout
76
+ while true
77
+ rval = yield
78
+ return rval unless rval
79
+ raise TimeoutError, "timeout of #{timeout}s exceeded" if Time.now > time_to_stop
80
+ Thread.pass
81
+ end
82
+ end
83
+ end
84
+
@@ -5,7 +5,7 @@ require 'shared/connection_examples'
5
5
  describe 'Zookeeper' do
6
6
  let(:path) { "/_zktest_" }
7
7
  let(:data) { "underpants" }
8
- let(:connection_string) { 'localhost:2181' }
8
+ let(:connection_string) { Zookeeper.default_cnx_str }
9
9
 
10
10
  before do
11
11
  @zk = Zookeeper.new(connection_string)
metadata CHANGED
@@ -1,13 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zookeeper
3
3
  version: !ruby/object:Gem::Version
4
- hash: 51
5
- prerelease:
4
+ hash: 3809227699
5
+ prerelease: 6
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 9
9
- - 4
10
- version: 0.9.4
9
+ - 0
10
+ - beta
11
+ - 1
12
+ version: 1.0.0.beta.1
11
13
  platform: ruby
12
14
  authors:
13
15
  - Phillip Pearson
@@ -21,17 +23,27 @@ bindir: bin
21
23
  cert_chain: []
22
24
 
23
25
  date: 2012-05-07 00:00:00 Z
24
- dependencies: []
25
-
26
+ dependencies:
27
+ - !ruby/object:Gem::Dependency
28
+ name: backports
29
+ prerelease: false
30
+ requirement: &id001 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ hash: 25
36
+ segments:
37
+ - 2
38
+ - 5
39
+ - 1
40
+ version: 2.5.1
41
+ type: :runtime
42
+ version_requirements: *id001
26
43
  description: |+
27
- A low-level multi-Ruby wrapper around the ZooKeeper API bindings.
28
- For a friendlier interface, see http://github.com/slyphon/zk
29
-
30
- Currently supported:
31
-
32
- MRI: 1.8.7, 1.9.2, 1.9.3
33
- JRuby: ~> 1.6.7
34
- Rubinius: 2.0.testing
44
+ A low-level multi-Ruby wrapper around the ZooKeeper API bindings. For a
45
+ friendlier interface, see http://github.com/slyphon/zk. Currently supported:
46
+ MRI: {1.8.7, 1.9.2, 1.9.3}, JRuby: ~> 1.6.7, Rubinius: 2.0.testing, REE 1.8.7.
35
47
 
36
48
  This library uses version 3.3.5 of zookeeper bindings.
37
49
 
@@ -44,14 +56,16 @@ extensions:
44
56
  extra_rdoc_files: []
45
57
 
46
58
  files:
59
+ - .dotfiles/rvmrc
47
60
  - .gitignore
61
+ - .gitmodules
62
+ - .travis.yml
48
63
  - CHANGELOG
49
64
  - Gemfile
50
65
  - LICENSE
51
66
  - Manifest
52
67
  - README.markdown
53
68
  - Rakefile
54
- - examples/cloud_config.rb
55
69
  - ext/.gitignore
56
70
  - ext/Rakefile
57
71
  - ext/c_zookeeper.rb
@@ -68,18 +82,23 @@ files:
68
82
  - ext/zookeeper_c.c
69
83
  - ext/zookeeper_lib.c
70
84
  - ext/zookeeper_lib.h
71
- - java/zookeeper_base.rb
85
+ - java/java_base.rb
72
86
  - lib/zookeeper.rb
73
87
  - lib/zookeeper/acls.rb
74
88
  - lib/zookeeper/callbacks.rb
89
+ - lib/zookeeper/client.rb
90
+ - lib/zookeeper/client_methods.rb
75
91
  - lib/zookeeper/common.rb
76
92
  - lib/zookeeper/common/queue_with_pipe.rb
93
+ - lib/zookeeper/compatibility.rb
77
94
  - lib/zookeeper/constants.rb
78
95
  - lib/zookeeper/em_client.rb
79
96
  - lib/zookeeper/exceptions.rb
97
+ - lib/zookeeper/rake_tasks.rb
80
98
  - lib/zookeeper/stat.rb
81
99
  - lib/zookeeper/version.rb
82
100
  - notes.txt
101
+ - scripts/upgrade-1.0-sed-alike.rb
83
102
  - spec/c_zookeeper_spec.rb
84
103
  - spec/chrooted_connection_spec.rb
85
104
  - spec/default_watcher_spec.rb
@@ -88,14 +107,10 @@ files:
88
107
  - spec/shared/all_success_return_values.rb
89
108
  - spec/shared/connection_examples.rb
90
109
  - spec/spec_helper.rb
110
+ - spec/support/00_spawn_zookeeper.rb
91
111
  - spec/support/progress_formatter.rb
112
+ - spec/support/zookeeper_spec_helpers.rb
92
113
  - spec/zookeeper_spec.rb
93
- - test/test_basic.rb
94
- - test/test_callback1.rb
95
- - test/test_close.rb
96
- - test/test_esoteric.rb
97
- - test/test_watcher1.rb
98
- - test/test_watcher2.rb
99
114
  - zookeeper.gemspec
100
115
  homepage: https://github.com/slyphon/zookeeper
101
116
  licenses: []
@@ -118,19 +133,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
118
133
  required_rubygems_version: !ruby/object:Gem::Requirement
119
134
  none: false
120
135
  requirements:
121
- - - ">="
136
+ - - ">"
122
137
  - !ruby/object:Gem::Version
123
- hash: 3
138
+ hash: 25
124
139
  segments:
125
- - 0
126
- version: "0"
140
+ - 1
141
+ - 3
142
+ - 1
143
+ version: 1.3.1
127
144
  requirements: []
128
145
 
129
146
  rubyforge_project:
130
147
  rubygems_version: 1.8.15
131
148
  signing_key:
132
149
  specification_version: 3
133
- summary: Low level zookeeper client
150
+ summary: Apache ZooKeeper driver for Rubies
134
151
  test_files:
135
152
  - spec/c_zookeeper_spec.rb
136
153
  - spec/chrooted_connection_spec.rb
@@ -140,11 +157,7 @@ test_files:
140
157
  - spec/shared/all_success_return_values.rb
141
158
  - spec/shared/connection_examples.rb
142
159
  - spec/spec_helper.rb
160
+ - spec/support/00_spawn_zookeeper.rb
143
161
  - spec/support/progress_formatter.rb
162
+ - spec/support/zookeeper_spec_helpers.rb
144
163
  - spec/zookeeper_spec.rb
145
- - test/test_basic.rb
146
- - test/test_callback1.rb
147
- - test/test_close.rb
148
- - test/test_esoteric.rb
149
- - test/test_watcher1.rb
150
- - test/test_watcher2.rb
@@ -1,125 +0,0 @@
1
- require "rubygems"
2
- require "zookeeper"
3
-
4
- # A basic cloud-based YAML config library. Ruby Zookeeper client example.
5
- #
6
- # If you pass in a file as 'zk:/foo.yml/blah' it will go out to zookeeper.
7
- # Otherwise the file is assumed to be local. The yml file will get parsed
8
- # and cached locally, and keys after the .yml get interpreted as keys into
9
- # the YAML.
10
- #
11
- # e.g. get(zk:/config/service.yml/key1/key2/key3..) =>
12
- # zk.get(:path => /config/service.yml)
13
- # yaml <= YAML.parse(data)
14
- # yaml[key1][key2][key3]...
15
- #
16
- # If keys are unspecified, it returns the parsed YAML as one big object
17
- #
18
- # TODO if staleness is set to 0, read in YAML immediately before next
19
- # get(...)
20
-
21
- class CloudConfig
22
- class NodeNotFound < StandardError; end
23
- class BadPathError < StandardError; end
24
-
25
- DEFAULT_SERVERS = "localhost:2181"
26
-
27
- def initialize(zkservers = DEFAULT_SERVERS, staleness = 15) # maximum allowed staleness in seconds
28
- @staleness = staleness
29
- @lock = Mutex.new
30
- @zkservers = DEFAULT_SERVERS
31
-
32
- # cache
33
- @data = {}
34
- @zkcb = Zookeeper::WatcherCallback.new { dirty_callback(@zkcb.context) }
35
- @zk = nil
36
- end
37
-
38
- def get(node)
39
- filename, keys = extract_filename(node)
40
-
41
- # read(filename) is potentially a zk call, so do not hold the lock during the read
42
- if @lock.synchronize { !@data.has_key?(filename) }
43
- d = YAML.load(read(filename))
44
- @lock.synchronize { @data[filename] = d }
45
- end
46
-
47
- # synchronized b/c we potentially have a background thread updating data nodes from zk
48
- # if keys is empty, return the whole file, otherwise roll up the keys
49
- @lock.synchronize {
50
- keys.empty? ? @data[filename] : keys.inject(@data[filename]) { |hash, key| hash[key] }
51
- }
52
- end
53
-
54
- # todo:
55
- # factor get-and-watch into a different subsystem (so you can have
56
- # polling stat() ops on local filesystem.)
57
- def read(yaml)
58
- # read yaml file and register watcher. if watcher fires, set up
59
- # background thread to do read and update data.
60
- if yaml.match(/^zk:/)
61
- @zk ||= init_zk
62
- yaml = yaml['zk:'.length..-1] # strip off zk: from zk:/config/path.yml
63
- resp = get_and_register(yaml)
64
-
65
- if resp[:rc] != Zookeeper::ZOK
66
- @zk.unregister_watcher(resp[:req_id])
67
- raise NodeNotFound
68
- end
69
-
70
- resp[:data]
71
- else
72
- raise NodeNotFound unless File.exists?(yaml)
73
- File.read(yaml)
74
- end
75
- end
76
-
77
- def extract_filename(node)
78
- path_elements = node.split("/")
79
-
80
- yamlindex = path_elements.map{ |x| x.match("\.yml$") != nil }.index(true)
81
- raise BadPathError unless yamlindex
82
-
83
- yamlname = path_elements[0..yamlindex].join '/'
84
- yamlkeys = path_elements[(yamlindex+1)..-1]
85
-
86
- return yamlname, yamlkeys
87
- end
88
-
89
- private
90
- def init_zk
91
- Zookeeper.new(@zkservers)
92
- end
93
-
94
- def get_and_register(znode)
95
- @zk.get(:path => znode, :watcher => @zkcb,
96
- :watcher_context => { :path => znode,
97
- :wait => rand(@staleness) })
98
- end
99
-
100
- def dirty_callback(context)
101
- path = context[:path]
102
- wait = context[:wait]
103
-
104
- # Fire off a background update that waits a randomized period of time up
105
- # to @staleness seconds.
106
- Thread.new do
107
- sleep wait
108
- background_update(path)
109
- end
110
- end
111
-
112
- def background_update(zkpath)
113
- # do a synchronous get/register a new watcher
114
- resp = get_and_register(zkpath)
115
- if resp[:rc] != Zookeeper::ZOK
116
- # puts "Unable to read #{zkpath} from Zookeeper!" @logger.error
117
- zk.unregister_watcher(resp[:req_id])
118
- else
119
- # puts "Updating data."
120
- d = YAML.load(resp[:data])
121
- @lock.synchronize { @data["zk:#{zkpath}"] = d }
122
- end
123
- end
124
- end
125
-