summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/puppet/storage.rb45
-rw-r--r--lib/puppet/util.rb10
-rwxr-xr-xtest/other/storage.rb21
3 files changed, 56 insertions, 20 deletions
diff --git a/lib/puppet/storage.rb b/lib/puppet/storage.rb
index 8f2d12de6..da6061738 100644
--- a/lib/puppet/storage.rb
+++ b/lib/puppet/storage.rb
@@ -33,22 +33,25 @@ module Puppet
end
begin
#Puppet.debug "Loading statefile %s" % Puppet[:checksumfile]
- File.open(Puppet[:checksumfile]) { |file|
- file.each { |line|
- myclass, key, value = line.split(@@splitchar)
+ Puppet::Util.lock(Puppet[:checksumfile]) {
+ File.open(Puppet[:checksumfile]) { |file|
+ file.each { |line|
+ myclass, key, value = line.split(@@splitchar)
- begin
- @@state[eval(myclass)][key] = Marshal::load(value)
- rescue => detail
- raise Puppet::Error,
- "Failed to load value for %s::%s => %s" % [
- myclass,key,detail
- ], caller
- end
- }
- }
+ begin
+ @@state[eval(myclass)][key] = Marshal::load(value)
+ rescue => detail
+ raise Puppet::Error,
+ "Failed to load value for %s::%s => %s" % [
+ myclass,key,detail
+ ], caller
+ end
+ }
+ }
+ }
rescue => detail
Puppet.err "Could not read %s" % Puppet[:checksumfile]
+ raise
end
#Puppet.debug "Loaded state is %s" % @@state.inspect
@@ -78,14 +81,16 @@ module Puppet
Puppet.info "Creating state file %s" % Puppet[:checksumfile]
end
- File.open(Puppet[:checksumfile], File::CREAT|File::WRONLY, 0600) { |file|
- @@state.each { |klass, thash|
- thash.each { |key,value|
- mvalue = Marshal::dump(value)
- file.puts([klass,key,mvalue].join(@@splitchar))
+ Puppet::Util.lock(Puppet[:checksumfile]) {
+ File.open(Puppet[:checksumfile], File::CREAT|File::WRONLY, 0600) { |file|
+ @@state.each { |klass, thash|
+ thash.each { |key,value|
+ mvalue = Marshal::dump(value)
+ file.puts([klass,key,mvalue].join(@@splitchar))
+ }
}
- }
- }
+ }
+ }
#Puppet.debug "Stored state is %s" % @@state.inspect
end
diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb
index e5179a587..ec9b6e1fe 100644
--- a/lib/puppet/util.rb
+++ b/lib/puppet/util.rb
@@ -85,6 +85,16 @@ module Util
return retval
end
+ # Create a lock file while something is happening
+ def self.lock(file)
+ lock = file + ".lock"
+ while File.exists?(lock)
+ Puppet.debug "%s is locked" % file
+ sleep 0.1
+ end
+ yield
+ end
+
# Create instance methods for each of the log levels. This allows
# the messages to be a little richer. Most classes will be calling this
# method.
diff --git a/test/other/storage.rb b/test/other/storage.rb
index aa010b7f3..787fe9cdd 100755
--- a/test/other/storage.rb
+++ b/test/other/storage.rb
@@ -34,6 +34,27 @@ class TestParsedFile < Test::Unit::TestCase
assert_equal(state["name"], hash)
end
+
+ # we're getting corrupt files, probably because multiple processes
+ # are reading or writing the file at once
+ # so we need to test that
+ def test_multiwrite
+ value = {:a => :b, :c => :d}
+ threads = []
+ 9.times { |a|
+ threads << Thread.new {
+ 9.times { |b|
+ assert_nothing_raised {
+ Puppet::Storage.load
+ state = Puppet::Storage.state(value)
+ state[:e] = rand(100)
+ Puppet::Storage.store
+ }
+ }
+ }
+ }
+ threads.each { |th| th.join }
+ end
end
# $Id$