Cache: change to a Singleton object so it is only loaded from disk once

This commit is contained in:
Josh Holtrop 2014-04-15 14:02:26 -04:00
parent 5ce8940d54
commit 160434b903
6 changed files with 54 additions and 35 deletions

View File

@ -23,7 +23,7 @@ module Rscons
# Remove all generated files # Remove all generated files
def self.clean def self.clean
cache = Cache.new cache = Cache.instance
# remove all built files # remove all built files
cache.targets.each do |target| cache.targets.each do |target|
FileUtils.rm_f(target) FileUtils.rm_f(target)
@ -35,7 +35,7 @@ module Rscons
Dir.rmdir(directory) rescue nil Dir.rmdir(directory) rescue nil
end end
end end
Cache.clear cache.clear
end end
# Return whether the given path is an absolute filesystem path or not # Return whether the given path is an absolute filesystem path or not

View File

@ -2,6 +2,7 @@ require "digest/md5"
require "fileutils" require "fileutils"
require "json" require "json"
require "set" require "set"
require "singleton"
require "rscons/version" require "rscons/version"
module Rscons module Rscons
@ -50,30 +51,25 @@ module Rscons
# }, # },
# } # }
class Cache class Cache
#### Constants include Singleton
# Name of the file to store cache information in # Name of the file to store cache information in
CACHE_FILE = ".rsconscache" CACHE_FILE = ".rsconscache"
#### Class Methods
# Remove the cache file
def self.clear
FileUtils.rm_f(CACHE_FILE)
end
#### Instance Methods
# Create a Cache object and load in the previous contents from the cache # Create a Cache object and load in the previous contents from the cache
# file. # file.
def initialize def initialize
@cache = JSON.load(File.read(CACHE_FILE)) rescue {} initialize!
unless @cache.is_a?(Hash) end
$stderr.puts "Warning: #{CACHE_FILE} was corrupt. Contents:\n#{@cache.inspect}"
@cache = {} # Remove the cache file.
end def clear
@cache["targets"] ||= {} FileUtils.rm_f(CACHE_FILE)
@cache["directories"] ||= {} initialize!
end
# Clear the cached file checksums.
def clear_checksum_cache!
@lookup_checksums = {} @lookup_checksums = {}
end end
@ -194,9 +190,21 @@ module Rscons
@cache["directories"].keys @cache["directories"].keys
end end
# Private Instance Methods
private private
# Create a Cache object and load in the previous contents from the cache
# file.
def initialize!
@cache = JSON.load(File.read(CACHE_FILE)) rescue {}
unless @cache.is_a?(Hash)
$stderr.puts "Warning: #{CACHE_FILE} was corrupt. Contents:\n#{@cache.inspect}"
@cache = {}
end
@cache["targets"] ||= {}
@cache["directories"] ||= {}
@lookup_checksums = {}
end
# Return a file's checksum, or the previously calculated checksum for # Return a file's checksum, or the previously calculated checksum for
# the same file # the same file
# @param file [String] The file name. # @param file [String] The file name.

View File

@ -172,7 +172,8 @@ module Rscons
# called after the block returns. # called after the block returns.
def process def process
clean_target_paths! clean_target_paths!
cache = Cache.new cache = Cache.instance
cache.clear_checksum_cache!
targets_processed = {} targets_processed = {}
process_target = proc do |target| process_target = proc do |target|
targets_processed[target] ||= begin targets_processed[target] ||= begin

View File

@ -5,14 +5,11 @@ module Rscons
end end
def build_from(cache) def build_from(cache)
JSON.should_receive(:load).and_return(cache) JSON.stub(:load) do
Cache.new cache
end end
Cache.instance.tap do |cache|
describe ".clear" do cache.send(:initialize!)
it "removes the cache file" do
FileUtils.should_receive(:rm_f).with(Cache::CACHE_FILE)
Cache.clear
end end
end end
@ -21,11 +18,21 @@ module Rscons
it "prints a warning and defaults to an empty hash" do it "prints a warning and defaults to an empty hash" do
JSON.should_receive(:load).and_return("string") JSON.should_receive(:load).and_return("string")
$stderr.should_receive(:puts).with(/Warning:.*was.corrupt/) $stderr.should_receive(:puts).with(/Warning:.*was.corrupt/)
Cache.new.instance_variable_get(:@cache).is_a?(Hash).should be_true c = Cache.instance
c.send(:initialize!)
c.instance_variable_get(:@cache).is_a?(Hash).should be_true
end end
end end
end end
describe "#clear" do
it "removes the cache file" do
FileUtils.should_receive(:rm_f).with(Cache::CACHE_FILE)
JSON.stub(:load) {{}}
Cache.instance.clear
end
end
describe "#write" do describe "#write" do
it "should fill in 'version' and write to file" do it "should fill in 'version' and write to file" do
cache = {} cache = {}

View File

@ -140,7 +140,8 @@ module Rscons
env.Program("a.out", "main.c") env.Program("a.out", "main.c")
cache = "cache" cache = "cache"
Cache.should_receive(:new).and_return(cache) Cache.should_receive(:instance).and_return(cache)
cache.should_receive(:clear_checksum_cache!)
env.should_receive(:run_builder).with(anything, "a.out", ["main.c"], cache, {}).and_return(true) env.should_receive(:run_builder).with(anything, "a.out", ["main.c"], cache, {}).and_return(true)
cache.should_receive(:write) cache.should_receive(:write)
@ -153,7 +154,8 @@ module Rscons
env.Object("main.o", "other.cc") env.Object("main.o", "other.cc")
cache = "cache" cache = "cache"
Cache.should_receive(:new).and_return(cache) Cache.should_receive(:instance).and_return(cache)
cache.should_receive(:clear_checksum_cache!)
env.should_receive(:run_builder).with(anything, "main.o", ["other.cc"], cache, {}).and_return("main.o") env.should_receive(:run_builder).with(anything, "main.o", ["other.cc"], cache, {}).and_return("main.o")
env.should_receive(:run_builder).with(anything, "a.out", ["main.o"], cache, {}).and_return("a.out") env.should_receive(:run_builder).with(anything, "a.out", ["main.o"], cache, {}).and_return("a.out")
cache.should_receive(:write) cache.should_receive(:write)
@ -167,7 +169,8 @@ module Rscons
env.Object("main.o", "other.cc") env.Object("main.o", "other.cc")
cache = "cache" cache = "cache"
Cache.should_receive(:new).and_return(cache) Cache.should_receive(:instance).and_return(cache)
cache.should_receive(:clear_checksum_cache!)
env.should_receive(:run_builder).with(anything, "main.o", ["other.cc"], cache, {}).and_return(false) env.should_receive(:run_builder).with(anything, "main.o", ["other.cc"], cache, {}).and_return(false)
cache.should_receive(:write) cache.should_receive(:write)

View File

@ -2,7 +2,7 @@ describe Rscons do
describe ".clean" do describe ".clean" do
it "removes all build targets and created directories" do it "removes all build targets and created directories" do
cache = "cache" cache = "cache"
Rscons::Cache.should_receive(:new).and_return(cache) Rscons::Cache.should_receive(:instance).and_return(cache)
cache.should_receive(:targets).and_return(["build/a.out", "build/main.o"]) cache.should_receive(:targets).and_return(["build/a.out", "build/main.o"])
FileUtils.should_receive(:rm_f).with("build/a.out") FileUtils.should_receive(:rm_f).with("build/a.out")
FileUtils.should_receive(:rm_f).with("build/main.o") FileUtils.should_receive(:rm_f).with("build/main.o")
@ -18,7 +18,7 @@ describe Rscons do
Dir.should_receive(:rmdir).with("build") Dir.should_receive(:rmdir).with("build")
File.should_receive(:directory?).with("other").and_return(true) File.should_receive(:directory?).with("other").and_return(true)
Dir.should_receive(:entries).with("other").and_return([".", "..", "other.file"]) Dir.should_receive(:entries).with("other").and_return([".", "..", "other.file"])
Rscons::Cache.should_receive(:clear) cache.should_receive(:clear)
Rscons.clean Rscons.clean
end end