Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # alternacache.rb
- # =Notes:
- # It is also possible to make the ChecksumCache class a singleton, as there's
- # little reason to have more than one of these per-process and this might
- # have important benefits if the backend store is a network daemon somewhere.
- #
- # Ruby's built-in singleton module also takes care of thread safety issues for
- # you, whereas this example uses @cache_obj ||= ChecksumCache.new which is
- # thread-UNsafe.
- class Chef
- # if you want to cache other things in the future, extract superclass,
- # name it Cache and you're done. bam.
- class Cache
- include Singleton
- include Chef::Mixin::ConvertToClassName
- def initialize
- reset!
- end
- def reset!(backend=nil, backend_opts=nil)
- backend ||= Chef::Config[:cache_type]
- backend_opts ||= Chef::Config[:cache_options]
- # 08methodnotmissing can convert CamelCase to snake_case
- begin
- require "moneta/#{convert_to_snake_case(backend, Moneta)}"
- rescue LoadError => e
- Chef::Log.fatal "could not find moneta backend #{backend}"
- raise e
- end
- backend_class = Moneta.const_get(backend)
- @moneta = backend_class.new(backend_opts)
- end
- end
- class ChecksumCache < Cache
- def self.checksum_for_file(*args)
- instance.checksum_for_file(*args)
- end
- def checksum_for_file(file)
- fstat = File.stat(file)
- key = filename_to_keyname(file)
- find_checksum(key, fstat) || generate_checksum(key, fstat)
- end
- private
- def find_checksum(key, fstat)
- cached_value = @moneta.fetch(key)
- if cached_value && file_unchanged?(cached_value, fstat)
- cached_value["checksum"]
- else
- false
- end
- end
- def generate_checksum(file, key, fstat)
- digest = Digest::SHA256.new
- IO.foreach(file) {|line| digest.update(line) }
- checksum = digest.hexdigest
- @moneta.store(key, { "mtime" => fstat.mtime.to_f, "checksum" => checksum }
- checksum
- end
- def file_unchanged?(cached_value, stat)
- cached_value["mtime"] == stat.mtime.to_f
- end
- def filename_to_keyname(filename)
- "chef-file#{filename.gsub(/(#{File::SEPARATOR}|\.)/, '-')}"
- end
- end
- end
- class Chef
- module Mixin
- module Checksum
- def checksum(file)
- ChecksumCache.checksum_for_file(file)
- end
- end
- end
- end
Add Comment
Please, Sign In to add comment