diff --git a/lib/daybreak/db.rb b/lib/daybreak/db.rb index dae504c..645b003 100644 --- a/lib/daybreak/db.rb +++ b/lib/daybreak/db.rb @@ -244,8 +244,9 @@ def clear # Compact the database to remove stale commits and reduce the file size. # @return [DB] self - def compact + def compact(options = {}) sync + return self unless compact_needed?(options) with_tmpfile do |path, file| # Compactified database has the same size -> return return self if @pos == file.write(dump) @@ -282,7 +283,15 @@ def closed? private - # The block used in @table for new entries + def compact_needed?(options) + return true if options[:force] + options[:ratio] ||= 2 # Two log records per table record + options[:reduction] ||= 4096 # One filesystem block, otherwise we won't gain + logsize > options[:ratio] * size || # Log size vs table size ratio + bytesize - (bytesize * size / logsize) > options[:reduction] # Estimate log size reduction + end + + # The block used in @table for new records def hash_default(_, key) if @default != nil value = @default.respond_to?(:call) ? @default.call(key) : @default diff --git a/test/test.rb b/test/test.rb index adb1003..ee5b558 100644 --- a/test/test.rb +++ b/test/test.rb @@ -64,7 +64,7 @@ it 'should persist after compact' do @db['1'] = 'xy' @db['1'] = 'z' - assert_equal @db.compact, @db + assert_equal @db.compact(:force => true), @db @db['1'] = '4' @db['4'] = '1' assert_equal @db.close, nil @@ -79,7 +79,7 @@ @db['1'] = 'xy' @db['1'] = 'z' - assert_equal @db.compact, @db + assert_equal @db.compact(:force => true), @db @db['1'] = '4' @db['4'] = '1' assert_equal @db.flush, @db @@ -112,7 +112,7 @@ @db.sync size = File.stat(DB_PATH).size - @db.compact + @db.compact(:force => true) assert_equal @db[1], 1 assert size > File.stat(DB_PATH).size end @@ -154,7 +154,7 @@ @db.lock { 20.times {|i| @db[i] = i } } db2 = Daybreak::DB.new DB_PATH @db.lock { 20.times {|i| @db[i] = i } } - @db.compact + @db.compact(:force => true) db2.sync assert_equal 19, db2['19'] db2.close @@ -293,12 +293,12 @@ end c = Thread.new do db = Daybreak::DB.new DB_PATH - db.compact until stop + db.compact(:force => true) until stop db.close end d = Thread.new do db = Daybreak::DB.new DB_PATH - db.compact until stop + db.compact(:force => true) until stop db.close end stop = true @@ -318,7 +318,7 @@ @db[1] = 2 @db.lock do @db[1] = 2 - @db.compact + @db.compact(:force => true) end end