lib/daybreak/db.rb in daybreak-0.1.1 vs lib/daybreak/db.rb in daybreak-0.1.2
- old
+ new
@@ -12,14 +12,15 @@
# @param default the default value to store and return when a key is
# not yet in the database.
# @yield [key] a block that will return the default value to store.
# @yieldparam [String] key the key to be stored.
def initialize(file, default=nil, &blk)
+ @table = {}
@file_name = file
- reset!
- @default = default
- @default = blk if block_given?
+ @reader = Reader.new(@file_name)
+ @writer = Writer.new(@file_name)
+ @default = block_given? ? blk : default
read!
end
# Set a key in the database to be written at some future date. If the data
# needs to be persisted immediately, call <tt>db.set(key, value, true)</tt>.
@@ -62,26 +63,21 @@
def [](key)
key = key.to_s
if @table.has_key? key
@table[key]
elsif default?
- if @default.is_a? Proc
- value = @default.call(key)
- else
- value = @default
- end
- set key, value
+ set key, Proc === @default ? @default.call(key) : @default
end
end
alias_method :get, :"[]"
# Iterate over the key, value pairs in the database.
# @yield [key, value] blk the iterator for each key value pair.
# @yieldparam [String] key the key.
# @yieldparam value the value from the database.
- def each(&blk)
- keys.each { |k| blk.call(k, get(k)) }
+ def each
+ keys.each { |k| yield(k, get(k)) }
end
# Does this db have a default value.
def default?
!@default.nil?
@@ -102,10 +98,11 @@
# Return the number of stored items.
# @return [Integer]
def length
@table.keys.length
end
+ alias_method :size, :length
# Serialize the data for writing to disk, if you don't want to use <tt>Marshal</tt>
# overwrite this method.
# @param value the value to be serialized
# @return [String]
@@ -119,78 +116,66 @@
# @return [String]
def parse(value)
Marshal.load(value)
end
- # Reset and empty the database file.
+ # Empty the database file.
def empty!
@writer.truncate!
- close!
- reset!
+ @table.clear
read!
end
alias_method :clear, :empty!
# Force all queued commits to be written to disk.
def flush!
@writer.flush!
end
- # Reset the state of the database, you should call <tt>read!</tt> after calling this.
- def reset!
- @table = {}
- @writer = Daybreak::Writer.new(@file_name)
- @reader = Daybreak::Reader.new(@file_name)
- end
-
# Close the database for reading and writing.
def close!
@writer.close!
- @reader.close!
end
# Compact the database to remove stale commits and reduce the file size.
def compact!
- # Create a new temporary file
- tmp_file = Tempfile.new File.basename(@file_name)
- copy_db = self.class.new tmp_file.path
+ # Create a new temporary database
+ tmp_file = @file_name + "-#{$$}-#{Thread.current.object_id}"
+ copy_db = self.class.new tmp_file
# Copy the database key by key into the temporary table
- each do |key|
+ each do |key, value|
copy_db.set(key, get(key))
end
copy_db.close!
- # Empty this database
- empty!
close!
# Move the copy into place
- tmp_file.close
- FileUtils.mv tmp_file.path, @file_name
- tmp_file.unlink
+ File.rename tmp_file, @file_name
- # Reset this database
- reset!
+ # Reopen this database
+ @writer = Writer.new(@file_name)
+ @table.clear
read!
end
# Read all values from the log file. If you want to check for changed data
# call this again.
def read!
- @reader.read do |record|
- if record.deleted?
- @table.delete record.key
+ @reader.read do |(key, data, deleted)|
+ if deleted
+ @table.delete key
else
- @table[record.key] = parse(record.data)
+ @table[key] = parse(data)
end
end
end
private
def write(key, value, sync = false, delete = false)
- @writer.write(Record.new(key, serialize(value), delete))
+ @writer.write([key, serialize(value), delete])
flush! if sync
end
end
end