admit_one 0.1.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2011 Jonathan S. Garvin (http://www.5valleys.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  AdmitOne
2
2
  ========
3
3
 
4
- A Ruby lock file manager that is immune to race conditions.
4
+ A Ruby lock file manager that is highly resistant, if not outright immune, to race conditions.
5
5
 
6
6
  Usage
7
7
  -----
@@ -11,7 +11,7 @@ Usage
11
11
  # code that needs to run with confidence
12
12
  # that the same code isn't also running
13
13
  # at the same time in another process
14
- rescue AdmitOne::LockFileAlreadyExists
14
+ rescue AdmitOne::LockFailure
15
15
  # gracefully recover if the lock could not
16
16
  # be established
17
17
  end
@@ -55,19 +55,18 @@ append mode. If the file doesn't already exist, it creates it and then opens
55
55
  it. Otherwise it just opens it. Then, any writes to the file are appended
56
56
  to the end. Two processes can open and write to the file at the same time.
57
57
 
58
- AdmitOne writes the process id to the file, closes the file and then reopens
59
- it, this time in read mode, to compare it's process id with the one on the
60
- first line in the file. In the event of a race condition, two process ids
61
- will be written to the file (remember, append mode), but *only one* can
62
- possibly be on the first line.
63
-
64
- The first process will reopen the lock file in read mode, compare it's process
65
- id with the one on the first line, see that they match, and only then
66
- execute your block of code that needed a lock. The second process also opens
67
- the file, but it will see that the process id on the first line does *not*
68
- match it's own, and instead of executing the code block, will raise an
69
- exception for your application to catch and handle gracefully according to
70
- your preferences (such as trying again later, or triggering a missile launch).
58
+ AdmitOne appends the process id to the end of file, then reads the first
59
+ line in file to compare it's process id with the one on the first line.
60
+ In the event of a race condition, two process ids will be written to the
61
+ file (remember, append mode), but *only one* can possibly be on the first
62
+ line.
63
+
64
+ The first process will confirm that it's process id is on the first line,
65
+ and only then execute your block of code that needed a lock. The second
66
+ process will see that the process id on the first line does *not* match
67
+ it's own, and instead of executing the code block, will raise an exception
68
+ for your application to catch and handle gracefully according to your
69
+ preferences (such as trying again later, or triggering a missile launch).
71
70
 
72
71
  Contributions
73
72
  -------------
@@ -7,8 +7,8 @@ Gem::Specification.new do |s|
7
7
  s.authors = ["Jonathan S. Garvin"]
8
8
  s.email = ["jon@5valleys.com"]
9
9
  s.homepage = "https://github.com/jsgarvin/admit_one"
10
- s.summary = %q{Lock file manager.}
11
- s.description = %q{Lock file manager that is immune to race conditions.}
10
+ s.summary = %q{Race resistant lock file manager.}
11
+ s.description = %q{Ruby lock file manager that is highly resistant, if not outright immune, to race conditions.}
12
12
 
13
13
  s.rubyforge_project = "admit_one"
14
14
 
@@ -1,42 +1,52 @@
1
1
  module AdmitOne
2
-
2
+
3
3
  class LockFile
4
4
  require 'tempfile'
5
5
 
6
- attr_accessor :filename
6
+ attr_accessor :name, :lock_file
7
7
 
8
8
  def initialize(name,&block)
9
- @filename = "#{name}.lock"
10
- begin
11
- lock!
12
- yield
13
- ensure
14
- unlock!
9
+ @name = name
10
+ if lock! then
11
+ begin
12
+ yield
13
+ ensure
14
+ unlock!
15
+ end
15
16
  end
16
17
  end
17
18
 
19
+ #######
20
+ private
21
+ #######
22
+
18
23
  def full_path
19
- "#{Dir.tmpdir}/#{filename}"
24
+ "#{Dir.tmpdir}/#{name}.lock"
20
25
  end
21
26
 
22
27
  def lock!
23
- File.open(full_path, "a") { |file| file.write("#{Process.pid}\n") }
24
- raise LockFileAlreadyExists unless lock_file_acquired?
28
+ @lock_file = File.open(full_path, "a+")
29
+ lock_file.write("#{Process.pid}\n")
30
+ lock_file.flush
31
+ lock_file.rewind
32
+ raise(LockFailure,'already locked by other process') unless lock_file.gets.to_i == Process.pid
33
+ return true
25
34
  end
26
35
 
27
36
  def unlock!
37
+ lock_file.close
28
38
  begin
29
- File.delete(full_path) if lock_file_acquired?
39
+ File.delete(full_path)
30
40
  rescue
31
- raise LockFileMissing
41
+ # This should never happen. It would indicate that another process deleted
42
+ # a lock file that it didn't rightfully own, or that a user deleted it manually
43
+ # before this process completed.
44
+ raise LockFileMissing, 'Lockfile unexpectedly vanished! This should probably be investigated!'
32
45
  end
33
46
  end
34
47
 
35
- def lock_file_acquired?
36
- File.open(full_path, "r") { |file| file.gets.to_i == Process.pid }
37
- end
38
48
  end
39
49
 
40
- class LockFileAlreadyExists < StandardError; end
50
+ class LockFailure < StandardError; end
41
51
  class LockFileMissing < StandardError; end
42
52
  end
@@ -1,3 +1,3 @@
1
1
  module AdmitOne
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.2'
3
3
  end
@@ -8,15 +8,18 @@ class LockFileTest < Test::Unit::TestCase
8
8
  end
9
9
 
10
10
  def test_should_create_and_remove_lockfile
11
+ block_executed = false
11
12
  AdmitOne::LockFile.new(:admit_one_lock_file_unit_test) do
13
+ block_executed = true
12
14
  assert(File.exist?(lock_file_path))
13
15
  end
16
+ assert(block_executed)
14
17
  assert(!File.exist?(lock_file_path))
15
18
  end
16
19
 
17
20
  def test_should_not_clobber_another_lock_file
18
21
  File.open(lock_file_path, "a") { |file| file.write("1\n") }
19
- assert_raise(AdmitOne::LockFileAlreadyExists) do
22
+ assert_raise(AdmitOne::LockFailure) do
20
23
  AdmitOne::LockFile.new(:admit_one_lock_file_unit_test) do
21
24
  assert false #should never run
22
25
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 0
9
- version: 0.1.0
7
+ - 2
8
+ - 2
9
+ version: 0.2.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jonathan S. Garvin
@@ -14,11 +14,11 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-05-19 00:00:00 -06:00
17
+ date: 2011-05-21 00:00:00 -06:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
21
- description: Lock file manager that is immune to race conditions.
21
+ description: Ruby lock file manager that is highly resistant, if not outright immune, to race conditions.
22
22
  email:
23
23
  - jon@5valleys.com
24
24
  executables: []
@@ -29,6 +29,7 @@ extra_rdoc_files: []
29
29
 
30
30
  files:
31
31
  - .gitignore
32
+ - LICENSE
32
33
  - README.md
33
34
  - Rakefile
34
35
  - admit_one.gemspec
@@ -46,7 +47,6 @@ rdoc_options: []
46
47
  require_paths:
47
48
  - lib
48
49
  required_ruby_version: !ruby/object:Gem::Requirement
49
- none: false
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
@@ -54,7 +54,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
54
54
  - 0
55
55
  version: "0"
56
56
  required_rubygems_version: !ruby/object:Gem::Requirement
57
- none: false
58
57
  requirements:
59
58
  - - ">="
60
59
  - !ruby/object:Gem::Version
@@ -64,9 +63,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
63
  requirements: []
65
64
 
66
65
  rubyforge_project: admit_one
67
- rubygems_version: 1.3.7
66
+ rubygems_version: 1.3.6
68
67
  signing_key:
69
68
  specification_version: 3
70
- summary: Lock file manager.
69
+ summary: Race resistant lock file manager.
71
70
  test_files:
72
71
  - test/unit/lock_file_test.rb