Commit b1b8a97d authored by Daniel DeLeo's avatar Daniel DeLeo
Browse files

[CHEF-1154] auto-clean the checksum dir when a Marshal error occurs

* Workaround marshal errors w/ moneta by deleting 0byte files in the
  checksum cache dir
* Assumes you're using the BasicFile backend to moneta.
* even though every file is checked, total time should be negligable,
  and this approach avoids depending too much on moneta's implementation
parent 043e4660
......@@ -8,9 +8,9 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
......@@ -27,28 +27,28 @@ require 'chef/mixin/convert_to_class_name'
require 'singleton'
require 'moneta'
class Chef
class Chef
class ChecksumCache
include Chef::Mixin::ConvertToClassName
include ::Singleton
attr_reader :moneta
def initialize(*args)
self.reset!(*args)
end
def reset!(backend=nil, options=nil)
backend ||= Chef::Config[:cache_type]
options ||= Chef::Config[:cache_options]
begin
require "moneta/#{convert_to_snake_case(backend, 'Moneta')}"
rescue LoadError => e
Chef::Log.fatal("Could not load Moneta back end #{backend.inspect}")
raise e
end
@moneta = Moneta.const_get(backend).new(options)
end
......@@ -112,7 +112,7 @@ class Chef
end
def lookup_checksum(key, fstat)
cached = @moneta.fetch(key)
cached = fetch(key)
if cached && file_unchanged?(cached, fstat)
validate_checksum(key)
cached["checksum"]
......@@ -146,6 +146,22 @@ class Chef
private
def fetch(key)
@moneta.fetch(key)
rescue ArgumentError => e
Log.warn "Error loading cached checksum for key #{key.inspect}"
Log.warn(e)
repair_checksum_cache
nil
end
def repair_checksum_cache
Chef::Log.info("Removing invalid checksum cache files")
Dir["#{Chef::Config[:cache_options][:path]}/*"].each do |file_path|
File.unlink(file_path) unless File.size?(file_path)
end
end
def file_unchanged?(cached, fstat)
cached["mtime"].to_f == fstat.mtime.to_f
end
......
......@@ -193,6 +193,14 @@ describe Chef::ChecksumCache do
Chef::ChecksumCache.cleanup_checksum_cache
end
it "cleans all 0byte checksum files when it encounters a Marshal error" do
@cache.moneta.stub!(:fetch).and_raise(ArgumentError)
# This cache file is 0 bytes, raises an argument error when
# attempting to Marshal.load
File.should_receive(:unlink).with(File.join(CHEF_SPEC_DATA, "checksum_cache", "chef-file--tmp-chef-rendered-template20100929-10863-6m8zdk-0"))
@cache.lookup_checksum("chef-file--tmp-chef-rendered-template20100929-10863-6m8zdk-0", "foo")
end
end
end
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment