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