lib/daybreak/record.rb in daybreak-0.0.4 vs lib/daybreak/record.rb in daybreak-0.1.0

- old
+ new

@@ -7,24 +7,32 @@ # Thrown when there is a CRC mismatch between the data from the disk # and what was written to disk previously. class CorruptDataError < Exception; end include Locking + # The mask a record uses to check for deletion. + DELETION_MASK = (1 << 31) + attr_accessor :key, :data - def initialize(key = nil, data = nil) + def initialize(key = nil, data = nil, deleted = false) @key = key @data = data + if deleted + @deleted = DELETION_MASK + else + @deleted = 0 + end end # Read a record from an open io source, check the CRC, and set <tt>@key</tt> # and <tt>@data</tt>. # @param [#read] io an IO instance to read from def read(io) lock io do - @key = read_bytes(io) - @data = read_bytes(io) + @key = read_key(io) + @data = read_data(io) crc = io.read(4) raise CorruptDataError, "CRC mismatch #{crc} should be #{crc_string}" unless crc == crc_string end self end @@ -40,26 +48,40 @@ # @param [#read] io an IO instance to read from def self.read(io) new.read(io) end + def deleted? + @deleted > 0 + end + private def byte_string - @byte_string ||= part(@key) + part(@data) + @byte_string ||= part(@key, @key.bytesize + @deleted) + part(@data, @data.bytesize) end def crc_string [Zlib.crc32(byte_string, 0)].pack('N') end - def read_bytes(io) + def read_data(io) + io.read read32(io) + end + + def read_key(io) + masked = read32 io + @deleted = masked & DELETION_MASK + length = masked & (DELETION_MASK - 1) + io.read length + end + + def read32(io) raw = io.read(4) - length = raw.unpack('N')[0] - io.read(length) + raw.unpack('N')[0] end - def part(data) - [data.bytesize].pack('N') + data + def part(data, length) + [length].pack('N') + data end end end