module Buryspam::Hashbase

The Hashbase is like a crude database that is used to load/save the metadata/counts mboxes caches as well as the word_file containing the word probabilities, white list and blacklist IP addresses.

Public Class Methods

load(filename) click to toggle source

Load/return the hash file from the given filename. Returns nil if there was a problem.

# File buryspam.rb, line 1846
def load(filename)
  return nil unless File.exist?(filename)
  result = nil
  Lockfile.open(filename) { |f|
    Logger.debug("Loading '#{filename}'")
    result = Marshal.load(f.read) rescue nil
  }
  result
end
save(file_contents) click to toggle source

Save the specified contents in the give file. file_contents is actually a hash of file names and the hash contents:

{
  "file1" => data,
  "file2" => data,
  ...
}

This allows all related files to be removed, if interrupted.

# File buryspam.rb, line 1864
def save(file_contents)
  file_contents.each { |filename, contents|
    Logger.debug("Saving '#{filename}'")
    begin
      if contents.nil?
        remove_file(filename)
      else
        write_file(filename, contents)
      end
    # Want to catch *all* exceptions, especially 'Interrupt'
    rescue Exception
      remove_related_files(file_contents.keys)
      raise
    end
  }
end

Private Class Methods

remove_file(filename) click to toggle source

Remove cache related files that are no longer useful.

# File buryspam.rb, line 1893
def remove_file(filename)
  # Never remove the word_file because all subsequent filtering will fail!
  return if filename == Config.word_file
  FileUtils.rm_f(filename)
  Logger.debug("Removed unneeded file '#{filename}'.")
end
write_file(filename, contents) click to toggle source

Marshal the data contents and write it to the given filename. The file is initially written to a backup file first, which is then renamed to the desired filename.

# File buryspam.rb, line 1903
def write_file(filename, contents)
  # XXX Probably should use a tempfile instead.
  backup_filename = filename + ".bak"
  # Write to a backup file so as to leave the original intact
  # in case of errors during the dump/write
  Lockfile.open(backup_filename, File::LOCK_EX) { |f|
    f.print(Marshal.dump(contents))
  }
  File.rename(backup_filename, filename)
end