Skip to content

Instantly share code, notes, and snippets.

@ender672
Created June 26, 2009 19:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ender672/136677 to your computer and use it in GitHub Desktop.
Save ender672/136677 to your computer and use it in GitHub Desktop.
a sha1 based key/value in the filesystem store.
require 'digest/sha1'
class Sha1File
attr_reader :path
def initialize(sha1, base)
@base = base
@path = sha1_path sha1, base
@dir = File.dirname @path
end
# If a block is given, then we yield the file opened for writing. Otherwise
# we write the value parameter into the file.
def write(value=nil)
Dir.mkdir @base unless File.directory? @base
Dir.mkdir @dir unless File.directory? @dir
File.open(@path, 'wb') do |f|
block_given? ? yield(f) : f << value
end
end
def read
File.open(@path, 'r').read if file_exists?
end
def delete
value = read
if file_exists?
File.delete @path
Dir.unlink @dir if dir_empty?
end
return value
end
def self.clear(base)
dir_glob = File.join base, '??'
file_glob = File.join dir_glob, '*'
Dir.glob(file_glob).each{|f| File.unlink f}
Dir.glob(dir_glob).each{|d| Dir.unlink d}
end
private
def dir_empty?
!Dir.foreach(@dir){|e| break true unless /^.\.?$/ =~ e}
end
def file_exists?
File.file?(@path)
end
def sha1_path(sha1, base)
File.join base, sha1[0..1], sha1[2..-1]
end
end
# The sha1 of the key is calculated and the value is stored under that sha1
class KeyValueStore
def initialize(options={})
@base = options[:base] || 'key_value_store'
end
def [](key)
Sha1File.new(sha1(key), @base).read
end
def path(key)
Sha1File.new(sha1(key), @base).path
end
def []=(key, value)
Sha1File.new(sha1(key), @base).write value
end
def delete(key)
Sha1File.new(sha1(key), @base).delete
end
def clear
Sha1File.clear @base
end
private
def sha1(key)
Digest::SHA1.hexdigest key
end
end
# The sha1 of the value is calculated and the value is stored under that sha1
class ObjectStore
def initialize(options={})
@base = options[:base] || 'key_value_store'
end
def store(value)
sha1 = Digest::SHA1.hexdigest value
Sha1File.new(sha1, @base).write value
return sha1
end
def retrieve(sha1, with_data_validation=nil)
value = Sha1File.new(sha1, @base).read
if with_data_validation
sha1_validation = Digest::SHA1.hexdigest value
if sha1 != sha1_validation
raise StandardError, "The object with sha1 #{sha1} is invalid. The data on the filesystem has sha1 #{sha1_validation}."
end
end
return value
end
def delete(sha1)
Sha1File.new(sha1, @base).delete
end
def clear
Sha1File.clear @base
end
end
if $0 == __FILE__
s = KeyValueStore.new :base => 'temp/sha'
s['hay'] = 'is for horses'
s['you'] = 'are my hero'
p s['hay']
p s['you']
p s['uhoh']
s.delete('hay')
s.delete('uhoh')
s.clear
o = ObjectStore.new :base => 'temp/obj'
sha1_a = o.store 'Ob la di Ob la Da'
sha1_b = o.store 'Life goes on... ra!'
p o.retrieve(sha1_a, true)
#o.delete sha1_a
#o.clear
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment