239
239
except StopIteration:
240
240
current_values[pos] = None
242
def _add_key(self, string_key, key_line, rows):
242
def _add_key(self, string_key, line, rows):
243
243
"""Add a key to the current chunk.
245
245
:param string_key: The key to add.
246
:param key_line: The fully serialised key and value.
246
:param line: The fully serialised key and value.
248
248
if rows[-1].writer is None:
249
249
# opening a new leaf chunk;
250
250
for pos, internal_row in enumerate(rows[:-1]):
251
251
# flesh out any internal nodes that are needed to
252
# preserve the high of the tree
252
# preserve the height of the tree
253
253
if internal_row.writer is None:
254
254
length = _PAGE_SIZE
255
255
if internal_row.nodes == 0:
256
256
length -= _RESERVED_HEADER_BYTES # padded
257
internal_row.writer = chunk_writer.ChunkWriter(
257
internal_row.writer = chunk_writer.ChunkWriter(length, 0)
259
258
internal_row.writer.write(_INTERNAL_FLAG)
260
259
internal_row.writer.write(_INTERNAL_OFFSET +
261
260
str(rows[pos + 1].nodes) + "\n")
265
264
length -= _RESERVED_HEADER_BYTES # padded
266
265
rows[-1].writer = chunk_writer.ChunkWriter(length)
267
266
rows[-1].writer.write(_LEAF_FLAG)
268
if rows[-1].writer.write(key_line):
267
if rows[-1].writer.write(line):
269
268
# this key did not fit in the node:
270
269
rows[-1].finish_node()
271
next_key_line = string_key + "\n"
270
key_line = string_key + "\n"
273
272
for row in reversed(rows[:-1]):
274
273
# Mark the start of the next node in the node above. If it
275
274
# doesn't fit then propogate upwards until we find one that
276
275
# it does fit into.
277
if row.writer.write(next_key_line):
276
if row.writer.write(key_line):
278
277
row.finish_node()
280
279
# We've found a node that can handle the pointer.
296
295
new_row.writer.write(_INTERNAL_FLAG)
297
296
new_row.writer.write(_INTERNAL_OFFSET +
298
297
str(rows[1].nodes - 1) + "\n")
299
new_row.writer.write(next_key_line)
300
self._add_key(string_key, key_line, rows)
298
new_row.writer.write(key_line)
299
self._add_key(string_key, line, rows)
302
301
def _write_nodes(self, node_iterator):
303
302
"""Write node_iterator out as a B+Tree.
326
325
# First key triggers the first row
327
326
rows.append(_LeafBuilderRow())
328
# TODO: Flattening the node into a string key and a line should
329
# probably be put into a pyrex function. We can do a quick
330
# iter over all the entries to determine the final length,
331
# and then do a single malloc() rather than lots of
332
# intermediate mallocs as we build everything up.
333
# ATM 3 / 13s are spent flattening nodes (10s is compressing)
329
334
if self.reference_lists:
330
335
flattened_references = ['\r'.join(['\x00'.join(reference)
331
336
for reference in ref_list])