diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-02 22:04:31 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-01-02 22:04:31 +0000 |
commit | 3c14db187d68bcfebbd5cd017f1b38326645b07d (patch) | |
tree | 7389271aa90a853faae9aadc0ca7d5fda7bfc1bb | |
parent | 5ce5b95af489685f64dbaa6189f7569e976e9dc5 (diff) | |
download | puppet-3c14db187d68bcfebbd5cd017f1b38326645b07d.tar.gz puppet-3c14db187d68bcfebbd5cd017f1b38326645b07d.tar.xz puppet-3c14db187d68bcfebbd5cd017f1b38326645b07d.zip |
adding Util.lock, and switching storage to using it
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@758 980ebf18-57e1-0310-9a29-db15c13687c0
-rw-r--r-- | lib/puppet/storage.rb | 45 | ||||
-rw-r--r-- | lib/puppet/util.rb | 10 | ||||
-rwxr-xr-x | test/other/storage.rb | 21 |
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$ |