Class: Rubcask::DataFile

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/rubcask/data_file.rb

Overview

DataFile is a file where the key and values are actually stored

Defined Under Namespace

Classes: AppendResult

Constant Summary collapse

HEADER_SIZE =
4 + 8 + 2 + 4
HEADER_WITHOUT_CRC_FORMAT =
"Q>nN"
HEADER_FORMAT =
"N#{HEADER_WITHOUT_CRC_FORMAT}"
EXPIRE_MASK =
~(1 << 63)
DELETED_MASK =
(1 << 63)
MAX_EXPIRE_VALUE =
DELETED_MASK - 1

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file, file_size) ⇒ DataFile

Returns a new instance of DataFile.

Parameters:

  • file (File)

    File with the data

  • file_size (Integer)

    Current size of file in bytes



26
27
28
29
# File 'lib/rubcask/data_file.rb', line 26

def initialize(file, file_size)
  @file = file
  @write_pos = file_size
end

Instance Attribute Details

#write_posObject (readonly)

Returns the value of attribute write_pos.



13
14
15
# File 'lib/rubcask/data_file.rb', line 13

def write_pos
  @write_pos
end

Instance Method Details

#[](offset, size = nil) ⇒ DataEntry?

Note:

Calling this method might change pos of the file

Fetch entry at given offset. With optional size parameter we can do less I/O operations.

Parameters:

  • offset (Integer)

    File offset in bytes

  • size (Integer, nil) (defaults to: nil)

    Entry size in bytes

Returns:

  • (DataEntry)
  • (nil)

    if at the end of file

Raises:



48
49
50
51
52
53
54
# File 'lib/rubcask/data_file.rb', line 48

def [](offset, size = nil)
  if size.nil?
    seek(offset)
    return read
  end
  pread(offset, size)
end

#append(entry) ⇒ AppendResult

Note:

Calling this method will not change pos of the file

Append an entry at the end of the file

Parameters:

  • entry (DataEntry)

    Entry to write to the file

Returns:

  • (AppendResult)

    struct containing position and size of the entry



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/rubcask/data_file.rb', line 96

def append(entry)
  current_pos = @write_pos

  key_size = entry.key.bytesize
  value_size = entry.value.bytesize
  timestamp_with_deleted = entry.expire_timestamp
  timestamp_with_deleted |= DELETED_MASK if entry.deleted?
  crc = Zlib.crc32([
    timestamp_with_deleted,
    key_size,
    value_size
  ].pack(HEADER_WITHOUT_CRC_FORMAT) + entry.key + entry.value)
  @write_pos += @file.write(
    [crc, timestamp_with_deleted, key_size, value_size].pack(HEADER_FORMAT),
    entry.key,
    entry.value
  )
  @file.flush
  AppendResult.new(current_pos, @write_pos - current_pos)
end

#each {|data_entry| ... } ⇒ Enumerator

Note:

Calling this method might change pos of the file

yields each entry in the file

Yield Parameters:

  • data_entry (DataEntry)

    Entry from the file

Returns:

  • (Enumerator)

    if no block given



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rubcask/data_file.rb', line 60

def each
  return to_enum(__method__) unless block_given?

  seek(0)

  loop do
    val = read
    break unless val
    yield val
  end
end

#pread(offset, size) ⇒ DataEntry?

Note:

Calling this method will not change pos of the file

Fetch an entry at given offset and with provided size

Parameters:

  • offset (Integer)

    File offset in bytes

  • size (Integer)

    Entry size in bytes

Returns:

  • (DataEntry)
  • (nil)

    if at the end of file

Raises:



87
88
89
# File 'lib/rubcask/data_file.rb', line 87

def pread(offset, size)
  read_from_io(StringIO.new(@file.pread(size, offset)))
end

#read(size = nil) ⇒ DataEntry?

Note:

Calling this method might change pos of the file

Read an entry at the current file position

Parameters:

  • size (Integer, nil) (defaults to: nil)

    Entry size in bytes

Returns:

  • (DataEntry)
  • (nil)

    if at the end of file

Raises:



76
77
78
79
80
# File 'lib/rubcask/data_file.rb', line 76

def read(size = nil)
  read_from_io(
    size ? StringIO.new(@file.read(size)) : @file
  )
end