Module: Higgs::Block

Includes:
Exceptions
Included in:
Index, JournalLogger
Defined in:
lib/higgs/block.rb

Overview

block header format

 0..15  : Z16  : magic symbol
16..19  : V    : body length
20..31  : x12  : (reserved)
32..33  : v    : format version
34..35  : x2   : (reserved)
36..37  : v    : head cksum
38..39  : x2   : (reserved)
40..55  : Z16  : body hash type
56..57  : v    : body hash length
58..71  : x14  : (reserved)
73..511 : a440 : body hash binary

Defined Under Namespace

Classes: BrokenError

Constant Summary collapse

CVS_ID =

for ident(1)

'$Id: block.rb 841 2008-12-24 09:23:20Z toki $'
BLOCK_SIZE =
512
FMT_VERSION =
0x00_00
HEAD_CKSUM_BITS =
16
HEAD_CKSUM_POS =
36..37
HEAD_CKSUM_FMT =
'v'
BODY_HASH =
{}
BODY_HASH_BIN =
{}
HEAD_FMT =
[
  'Z16',                    # magic symbol
  'V',                      # body length
  'x12',                    # (reserved)
  'v',                      # format version
  'x2',                     # (reserved)
  HEAD_CKSUM_FMT,           # head cksum
  'x2',                     # (reserved)
  'Z16',                    # body hash type
  'v',                      # body hash length
  'x14',                    # (reserved)
  'a440'                    # body hash binary
].join('')

Class Method Summary collapse

Class Method Details

.block_read(io, magic_symbol) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/higgs/block.rb', line 130

def block_read(io, magic_symbol)
  body_len, body_hash_type, body_hash_bin = head_read(io, magic_symbol)
  unless (body_len) then
    return
  end

  body = io.read(body_len) or raise BrokenError, 'unexpected EOF'
  if (body.length != body_len) then
    raise BrokenError, 'short read'
  end

  unless (hash_proc = BODY_HASH_BIN[body_hash_type]) then
    raise BrokenError, "unknown body hash type: #{body_hash_type}"
  end

  if (hash_proc.call(body) != body_hash_bin) then
    raise BrokenError, 'body hash error'
  end

  padding_size = padding_size(body_len)
  padding = io.read(padding_size) or raise BrokenError, 'unexpected EOF'
  if (padding.size != padding_size) then
    raise BrokenError, 'short read'
  end

  body
end

.block_write(io, magic_symbol, body, body_hash_type = :MD5) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/higgs/block.rb', line 159

def block_write(io, magic_symbol, body, body_hash_type=:MD5)
  hash_proc = BODY_HASH[body_hash_type.to_sym] or
    raise ArgumentError, "unknown body hash type: #{body_hash_type}"
  body_hash = hash_proc.call(body)
  head_write(io, magic_symbol, body.length, body_hash_type.to_s, body_hash)

  bytes = io.write(body)
  if (bytes != body.size) then
    raise BrokenError, 'short write'
  end

  padding_size = padding_size(body.length)
  bytes = io.write("\0" * padding_size)
  if (bytes != padding_size) then
    raise BrokenError, 'short write'
  end

  body.size + padding_size
end

.head_read(io, magic_symbol) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/higgs/block.rb', line 80

def head_read(io, magic_symbol)
  head_block = io.read(BLOCK_SIZE) or return
  if (head_block.size != BLOCK_SIZE) then
    raise BrokenError, 'short read'
  end

  _magic_symbol, body_len, fmt_version, head_cksum,
    body_hash_type, body_hash_len, body_hash_bucket = head_block.unpack(HEAD_FMT)

  head_block[HEAD_CKSUM_POS] = "\000\000"
  if (head_block.sum(HEAD_CKSUM_BITS) != head_cksum) then
    raise BrokenError, 'broken head block'
  end

  if (_magic_symbol != magic_symbol) then
    raise BrokenError, "unknown magic symbol: #{_magic_symbol}"
  end

  if (fmt_version != FMT_VERSION) then
    raise BrokenError, format('unknown format version: 0x%04F', fmt_version)
  end

  body_hash_bin = body_hash_bucket[0, body_hash_len]

  return body_len, body_hash_type, body_hash_bin
end

.head_write(io, magic_symbol, body_len, body_hash_type, body_hash_bin) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/higgs/block.rb', line 108

def head_write(io, magic_symbol, body_len, body_hash_type, body_hash_bin)
  head_block = [
    magic_symbol,
    body_len,
    FMT_VERSION,
    0,
    body_hash_type,
    body_hash_bin.length,
    body_hash_bin
  ].pack(HEAD_FMT)

  head_cksum = head_block.sum(HEAD_CKSUM_BITS)
  head_block[HEAD_CKSUM_POS] = [ head_cksum ].pack(HEAD_CKSUM_FMT)

  bytes = io.write(head_block)
  if (bytes != head_block.size) then
    raise BrokenError, 'short write'
  end
  bytes
end

.padding_size(bytes) ⇒ Object



74
75
76
77
# File 'lib/higgs/block.rb', line 74

def padding_size(bytes)
  r = bytes % BLOCK_SIZE
  (r > 0) ? BLOCK_SIZE - r : 0
end