summaryrefslogtreecommitdiffstats
path: root/lib/puppet/util/autoload/file_cache.rb
blob: b55547362eb49bce3af952a700d21f21265ec30e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
module Puppet::Util::Autoload::FileCache
  @found_files = {}
  @missing_files = {}
  class << self
    attr_reader :found_files, :missing_files
  end

  # Only used for testing.
  def self.clear
    @found_files.clear
    @missing_files.clear
  end

  def found_files
    Puppet::Util::Autoload::FileCache.found_files
  end

  def missing_files
    Puppet::Util::Autoload::FileCache.missing_files
  end

  def directory_exist?(path)
    cache = cached_data?(path, :directory?)
    return cache unless cache.nil?

    protect(path) do
      stat = File.lstat(path)
      if stat.directory?
        found_file(path, stat)
        return true
      else
        missing_file(path)
        return false
      end
    end
  end

  def file_exist?(path)
    cache = cached_data?(path)
    return cache unless cache.nil?

    protect(path) do
      stat = File.lstat(path)
      found_file(path, stat)
      return true
    end
  end

  def found_file?(path, type = nil)
    if data = found_files[path] and ! data_expired?(data[:time])
      return(type and ! data[:stat].send(type)) ? false : true
    else
      return false
    end
  end

  def found_file(path, stat)
    found_files[path] = {:stat => stat, :time => Time.now}
  end

  def missing_file?(path)
    !!(time = missing_files[path] and ! data_expired?(time))
  end

  def missing_file(path)
    missing_files[path] = Time.now
  end

  private

  def cached_data?(path, type = nil)
    if found_file?(path, type)
      return true
    elsif missing_file?(path)
      return false
    else
      return nil
    end
  end

  def data_expired?(time)
    Time.now - time > 15
  end

  def protect(path)
      yield
  rescue => detail
      raise unless detail.class.to_s.include?("Errno")
      missing_file(path)
      return false
  end
end