officer 0.2.2 → 0.3.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.
- data/README.markdown +2 -3
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/bin/officer +11 -3
- data/lib/officer/client.rb +6 -3
- data/lib/officer/commands.rb +0 -3
- data/lib/officer/connection.rb +4 -18
- data/lib/officer/lock_store.rb +23 -16
- data/lib/officer/log.rb +16 -2
- data/lib/officer/server.rb +1 -1
- data/lib/officer.rb +1 -0
- data/officer.gemspec +8 -5
- metadata +13 -3
data/README.markdown
CHANGED
@@ -5,8 +5,8 @@ It is implemented using Ruby and Eventmachine. Inspiration comes from [elock](ht
|
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
gem install gemcutter
|
9
|
+
gem install officer
|
10
10
|
|
11
11
|
## Usage
|
12
12
|
|
@@ -47,7 +47,6 @@ All debugging output goes to stdout for now.
|
|
47
47
|
|
48
48
|
## Planned Features
|
49
49
|
|
50
|
-
- Properly handle nested with_lock() blocks.
|
51
50
|
- Option to abort a lock request if there is already a certain number of clients waiting for the lock.
|
52
51
|
- Lock statistics.
|
53
52
|
- Retrieve the complete list of locks.
|
data/Rakefile
CHANGED
@@ -12,7 +12,8 @@ begin
|
|
12
12
|
gem.authors = ["Chad Remesch"]
|
13
13
|
gem.add_development_dependency "eventmachine", ">= 0"
|
14
14
|
gem.add_development_dependency "json", ">= 0"
|
15
|
-
gem.add_development_dependency "
|
15
|
+
gem.add_development_dependency "activesupport", ">= 0"
|
16
|
+
gem.add_development_dependency "daemons", ">= 0"
|
16
17
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
18
|
end
|
18
19
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/bin/officer
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require 'rubygems'
|
5
4
|
require 'officer'
|
6
5
|
|
7
|
-
|
6
|
+
options = {
|
7
|
+
:dir_mode => :system,
|
8
|
+
:multiple => false,
|
9
|
+
:monitor => true
|
10
|
+
}
|
11
|
+
|
12
|
+
|
13
|
+
Daemons.run_proc('officer', options) do
|
14
|
+
Officer::Server.new.run
|
15
|
+
end
|
data/lib/officer/client.rb
CHANGED
@@ -42,13 +42,16 @@ module Officer
|
|
42
42
|
result = response['result']
|
43
43
|
|
44
44
|
raise LockTimeoutError if result == 'timed_out'
|
45
|
-
raise LockError
|
45
|
+
raise LockError unless %w(acquired already_acquired).include?(result)
|
46
46
|
|
47
47
|
begin
|
48
48
|
yield
|
49
49
|
ensure
|
50
|
-
|
51
|
-
|
50
|
+
# Deal with nested with_lock calls. Only the outer most call should tell the server to unlock.
|
51
|
+
if result == 'acquired'
|
52
|
+
response = unlock name
|
53
|
+
raise UnlockError unless response['result'] == 'released'
|
54
|
+
end
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
data/lib/officer/commands.rb
CHANGED
@@ -57,7 +57,6 @@ module Officer
|
|
57
57
|
register
|
58
58
|
|
59
59
|
def execute
|
60
|
-
L.debug 'executing lock command.'
|
61
60
|
Officer::LockStore.instance.acquire @name, @connection, :timeout => @timeout
|
62
61
|
end
|
63
62
|
|
@@ -77,7 +76,6 @@ module Officer
|
|
77
76
|
register
|
78
77
|
|
79
78
|
def execute
|
80
|
-
L.debug 'executing unlock command.'
|
81
79
|
Officer::LockStore.instance.release @name, @connection
|
82
80
|
end
|
83
81
|
|
@@ -95,7 +93,6 @@ module Officer
|
|
95
93
|
register
|
96
94
|
|
97
95
|
def execute
|
98
|
-
L.debug 'executing reset command.'
|
99
96
|
Officer::LockStore.instance.reset @connection
|
100
97
|
end
|
101
98
|
end
|
data/lib/officer/connection.rb
CHANGED
@@ -3,8 +3,6 @@ module Officer
|
|
3
3
|
|
4
4
|
module EmCallbacks
|
5
5
|
def post_init
|
6
|
-
L.debug "Client connected."
|
7
|
-
|
8
6
|
@connected = true
|
9
7
|
@timers = {} # name => Timer
|
10
8
|
end
|
@@ -12,8 +10,6 @@ module Officer
|
|
12
10
|
def receive_line line
|
13
11
|
line.chomp!
|
14
12
|
|
15
|
-
L.debug "Received line: #{line}"
|
16
|
-
|
17
13
|
command = Officer::Command::Factory.create line, self
|
18
14
|
command.execute
|
19
15
|
|
@@ -25,43 +21,35 @@ module Officer
|
|
25
21
|
def unbind
|
26
22
|
@connected = false
|
27
23
|
|
28
|
-
L.debug "client disconnected."
|
29
|
-
|
30
24
|
Officer::LockStore.instance.reset self
|
31
25
|
end
|
32
26
|
end
|
33
27
|
|
34
28
|
module LockCallbacks
|
35
29
|
def acquired name
|
36
|
-
L.debug "acquired lock: #{name}"
|
37
|
-
|
38
30
|
@timers.delete(name).cancel if @timers[name]
|
39
31
|
|
40
32
|
send_line({:result => 'acquired', :name => name}.to_json)
|
41
33
|
end
|
42
34
|
|
43
|
-
def
|
44
|
-
|
35
|
+
def already_acquired name
|
36
|
+
send_line({:result => 'already_acquired', :name => name}.to_json)
|
37
|
+
end
|
45
38
|
|
39
|
+
def released name
|
46
40
|
send_line({:result => 'released', :name => name}.to_json)
|
47
41
|
end
|
48
42
|
|
49
43
|
def release_failed name
|
50
|
-
L.debug "release lock failed: #{name}"
|
51
|
-
|
52
44
|
send_line({:result => 'release_failed', :name => name}.to_json)
|
53
45
|
end
|
54
46
|
|
55
47
|
def reset_succeeded
|
56
|
-
L.debug "reset"
|
57
|
-
|
58
48
|
@timers.values.each {|timer| timer.cancel}
|
59
49
|
send_line({:result => 'reset_succeeded'}.to_json)
|
60
50
|
end
|
61
51
|
|
62
52
|
def queued name, options={}
|
63
|
-
L.debug "queued. options=#{options.inspect}"
|
64
|
-
|
65
53
|
timeout = options[:timeout]
|
66
54
|
|
67
55
|
return if timeout.nil? || @timers[name]
|
@@ -72,8 +60,6 @@ module Officer
|
|
72
60
|
end
|
73
61
|
|
74
62
|
def timed_out name
|
75
|
-
L.debug "Timed out connection=#{object_id}, name=#{name}"
|
76
|
-
|
77
63
|
@timers.delete name
|
78
64
|
send_line({:result => 'timed_out', :name => name}.to_json)
|
79
65
|
end
|
data/lib/officer/lock_store.rb
CHANGED
@@ -16,40 +16,47 @@ module Officer
|
|
16
16
|
def initialize
|
17
17
|
@locks = {} # name => Lock
|
18
18
|
@connections = {} # Connection => Set(name, ...)
|
19
|
+
@acquire_counter = 0
|
19
20
|
end
|
20
21
|
|
21
22
|
def log_state
|
22
|
-
L.
|
23
|
+
L.info '-----'
|
23
24
|
|
24
|
-
L.
|
25
|
-
|
25
|
+
L.info 'LOCK STORE:'
|
26
|
+
L.info ''
|
26
27
|
|
27
|
-
|
28
|
+
L.info "locks:"
|
28
29
|
@locks.each do |name, lock|
|
29
|
-
|
30
|
+
L.info "#{name}: connections=[#{lock.queue.map{|c| c.object_id}.join(', ')}]"
|
30
31
|
end
|
31
|
-
|
32
|
+
L.info ''
|
32
33
|
|
33
|
-
|
34
|
+
L.info "Connections:"
|
34
35
|
@connections.each do |connection, names|
|
35
|
-
|
36
|
+
L.info "#{connection.object_id}: names=[#{names.to_a.join(', ')}]"
|
36
37
|
end
|
37
|
-
|
38
|
+
L.info ''
|
38
39
|
|
39
|
-
L.
|
40
|
+
L.info "Acquire Rate: #{@acquire_counter.to_f / 5}/s"
|
41
|
+
@acquire_counter = 0
|
42
|
+
L.info ''
|
43
|
+
|
44
|
+
L.info '-----'
|
40
45
|
end
|
41
46
|
|
42
47
|
def acquire name, connection, options={}
|
48
|
+
@acquire_counter += 1
|
49
|
+
|
43
50
|
lock = @locks[name] ||= Lock.new(name)
|
44
51
|
|
45
|
-
|
52
|
+
if lock.queue.include? connection
|
53
|
+
lock.queue.first == connection ? connection.already_acquired(name) : connection.queued(name, options)
|
46
54
|
|
47
|
-
(@connections[connection] ||= Set.new) << name
|
48
|
-
|
49
|
-
if lock.queue.first == connection
|
50
|
-
connection.acquired name
|
51
55
|
else
|
52
|
-
|
56
|
+
lock.queue << connection
|
57
|
+
(@connections[connection] ||= Set.new) << name
|
58
|
+
|
59
|
+
lock.queue.count == 1 ? connection.acquired(name) : connection.queued(name, options)
|
53
60
|
end
|
54
61
|
end
|
55
62
|
|
data/lib/officer/log.rb
CHANGED
@@ -4,7 +4,15 @@ module Officer
|
|
4
4
|
include Singleton
|
5
5
|
|
6
6
|
def debug message
|
7
|
-
|
7
|
+
return unless [:debug].include?(LOG_LEVEL)
|
8
|
+
|
9
|
+
write message
|
10
|
+
end
|
11
|
+
|
12
|
+
def info message
|
13
|
+
return unless [:debug, :info].include?(LOG_LEVEL)
|
14
|
+
|
15
|
+
write message
|
8
16
|
end
|
9
17
|
|
10
18
|
def debug_exception e
|
@@ -14,8 +22,14 @@ module Officer
|
|
14
22
|
debug e.backtrace.join "\n "
|
15
23
|
debug '-----'
|
16
24
|
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def write message
|
28
|
+
puts message
|
29
|
+
end
|
17
30
|
end
|
18
31
|
|
19
32
|
end
|
20
33
|
|
21
|
-
L = Officer::Log.instance
|
34
|
+
L = Officer::Log.instance
|
35
|
+
LOG_LEVEL = :info
|
data/lib/officer/server.rb
CHANGED
data/lib/officer.rb
CHANGED
data/officer.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{officer}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Chad Remesch"]
|
12
|
-
s.date = %q{2010-02-
|
12
|
+
s.date = %q{2010-02-07}
|
13
13
|
s.default_executable = %q{officer}
|
14
14
|
s.description = %q{Distributed lock server and client written in Ruby and EventMachine}
|
15
15
|
s.email = %q{chad@remesch.com}
|
@@ -54,16 +54,19 @@ Gem::Specification.new do |s|
|
|
54
54
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
55
55
|
s.add_development_dependency(%q<eventmachine>, [">= 0"])
|
56
56
|
s.add_development_dependency(%q<json>, [">= 0"])
|
57
|
-
s.add_development_dependency(%q<
|
57
|
+
s.add_development_dependency(%q<activesupport>, [">= 0"])
|
58
|
+
s.add_development_dependency(%q<daemons>, [">= 0"])
|
58
59
|
else
|
59
60
|
s.add_dependency(%q<eventmachine>, [">= 0"])
|
60
61
|
s.add_dependency(%q<json>, [">= 0"])
|
61
|
-
s.add_dependency(%q<
|
62
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
63
|
+
s.add_dependency(%q<daemons>, [">= 0"])
|
62
64
|
end
|
63
65
|
else
|
64
66
|
s.add_dependency(%q<eventmachine>, [">= 0"])
|
65
67
|
s.add_dependency(%q<json>, [">= 0"])
|
66
|
-
s.add_dependency(%q<
|
68
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
69
|
+
s.add_dependency(%q<daemons>, [">= 0"])
|
67
70
|
end
|
68
71
|
end
|
69
72
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: officer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chad Remesch
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-02-
|
12
|
+
date: 2010-02-07 00:00:00 -05:00
|
13
13
|
default_executable: officer
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -33,7 +33,17 @@ dependencies:
|
|
33
33
|
version: "0"
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
36
|
+
name: activesupport
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: daemons
|
37
47
|
type: :development
|
38
48
|
version_requirement:
|
39
49
|
version_requirements: !ruby/object:Gem::Requirement
|