class ActiveSupport::Cache::FileStore

an in-memory cache inside of a block.
FileStore implements the Strategy::LocalCache strategy which implements
A cache store implementation which stores everything on the filesystem.

def self.supports_cache_versioning?

Advertise cache versioning support.
def self.supports_cache_versioning?
  true
end

def cleanup(options = nil)

Preemptively iterates through all stored keys and removes the ones which have expired.
def cleanup(options = nil)
  options = merged_options(options)
  search_dir(cache_path) do |fname|
    entry = read_entry(fname, **options)
    delete_entry(fname, **options) if entry && entry.expired?
  end
end

def clear(options = nil)

config file when using +FileStore+ because everything in that directory will be deleted.
file store directory except for .keep or .gitkeep. Be careful which directory is specified in your
Deletes all items from the cache. In this case it deletes all the entries in the specified
def clear(options = nil)
  root_dirs = (Dir.children(cache_path) - GITKEEP_FILES)
  FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
rescue Errno::ENOENT, Errno::ENOTEMPTY
end

def decrement(name, amount = 1, options = nil)

If the key is not found nothing is done.
Decrements an already existing integer value that is stored in the cache.
def decrement(name, amount = 1, options = nil)
  modify_value(name, -amount, options)
end

def delete_empty_directories(dir)

Delete empty directories in the cache.
def delete_empty_directories(dir)
  return if File.realpath(dir) == File.realpath(cache_path)
  if Dir.children(dir).empty?
    Dir.delete(dir) rescue nil
    delete_empty_directories(File.dirname(dir))
  end
end

def delete_entry(key, **options)

def delete_entry(key, **options)
  if File.exist?(key)
    begin
      File.delete(key)
      delete_empty_directories(File.dirname(key))
      true
    rescue
      # Just in case the error was caused by another process deleting the file first.
      raise if File.exist?(key)
      false
    end
  end
end

def delete_matched(matcher, options = nil)

def delete_matched(matcher, options = nil)
  options = merged_options(options)
  instrument(:delete_matched, matcher.inspect) do
    matcher = key_matcher(matcher, options)
    search_dir(cache_path) do |path|
      key = file_path_key(path)
      delete_entry(path, **options) if key.match(matcher)
    end
  end
end

def ensure_cache_path(path)

Make sure a file path's directories exist.
def ensure_cache_path(path)
  FileUtils.makedirs(path) unless File.exist?(path)
end

def file_path_key(path)

Translate a file path into a key.
def file_path_key(path)
  fname = path[cache_path.to_s.size..-1].split(File::SEPARATOR, 4).last
  URI.decode_www_form_component(fname, Encoding::UTF_8)
end

def increment(name, amount = 1, options = nil)

If the key is not found nothing is done.
Increments an already existing integer value that is stored in the cache.
def increment(name, amount = 1, options = nil)
  modify_value(name, amount, options)
end

def initialize(cache_path, **options)

def initialize(cache_path, **options)
  super(options)
  @cache_path = cache_path.to_s
end

def lock_file(file_name, &block)

Lock a file for a block so only one process can modify it at a time.
def lock_file(file_name, &block)
  if File.exist?(file_name)
    File.open(file_name, "r+") do |f|
      f.flock File::LOCK_EX
      yield
    ensure
      f.flock File::LOCK_UN
    end
  else
    yield
  end
end

def modify_value(name, amount, options)

If the key is not found nothing is done.
Modifies the amount of an already existing integer value that is stored in the cache.
def modify_value(name, amount, options)
  file_name = normalize_key(name, options)
  lock_file(file_name) do
    options = merged_options(options)
    if num = read(name, options)
      num = num.to_i + amount
      write(name, num, options)
      num
    end
  end
end

def normalize_key(key, options)

Translate a key into a file path.
def normalize_key(key, options)
  key = super
  fname = URI.encode_www_form_component(key)
  if fname.size > FILEPATH_MAX_SIZE
    fname = ActiveSupport::Digest.hexdigest(key)
  end
  hash = Zlib.adler32(fname)
  hash, dir_1 = hash.divmod(0x1000)
  dir_2 = hash.modulo(0x1000)
  # Make sure file name doesn't exceed file system limits.
  if fname.length < FILENAME_MAX_SIZE
    fname_paths = fname
  else
    fname_paths = []
    begin
      fname_paths << fname[0, FILENAME_MAX_SIZE]
      fname = fname[FILENAME_MAX_SIZE..-1]
    end until fname.blank?
  end
  File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, fname_paths)
end

def read_entry(key, **options)

def read_entry(key, **options)
  if payload = read_serialized_entry(key, **options)
    entry = deserialize_entry(payload)
    entry if entry.is_a?(Cache::Entry)
  end
end

def read_serialized_entry(key, **)

def read_serialized_entry(key, **)
  File.binread(key) if File.exist?(key)
rescue => error
  logger.error("FileStoreError (#{error}): #{error.message}") if logger
  nil
end

def search_dir(dir, &callback)

def search_dir(dir, &callback)
  return if !File.exist?(dir)
  Dir.each_child(dir) do |d|
    name = File.join(dir, d)
    if File.directory?(name)
      search_dir(name, &callback)
    else
      callback.call name
    end
  end
end

def write_entry(key, entry, **options)

def write_entry(key, entry, **options)
  write_serialized_entry(key, serialize_entry(entry, **options), **options)
end

def write_serialized_entry(key, payload, **options)

def write_serialized_entry(key, payload, **options)
  return false if options[:unless_exist] && File.exist?(key)
  ensure_cache_path(File.dirname(key))
  File.atomic_write(key, cache_path) { |f| f.write(payload) }
  true
end