180
180
combine mem with the first and second indexes, creating a new one of
181
181
size 4x. On the fifth create a single new one, etc.
183
iterators_to_combine = [self._iter_mem_nodes()]
185
for pos, backing in enumerate(self._backing_indices):
189
iterators_to_combine.append(backing.iter_all_entries())
190
backing_pos = pos + 1
191
new_backing_file, size = \
192
self._write_nodes(self._iter_smallest(iterators_to_combine))
183
if self._combine_backing_indices:
184
(new_backing_file, size,
185
backing_pos) = self._spill_mem_keys_and_combine()
187
new_backing_file, size = self._spill_mem_keys_without_combining()
193
188
dir_path, base_name = osutils.split(new_backing_file.name)
194
189
# Note: The transport here isn't strictly needed, because we will use
195
190
# direct access to the new_backing._file object
198
193
# GC will clean up the file
199
194
new_backing._file = new_backing_file
200
if len(self._backing_indices) == backing_pos:
201
self._backing_indices.append(None)
202
self._backing_indices[backing_pos] = new_backing
203
for pos in range(backing_pos):
204
self._backing_indices[pos] = None
195
if self._combine_backing_indices:
196
if len(self._backing_indices) == backing_pos:
197
self._backing_indices.append(None)
198
self._backing_indices[backing_pos] = new_backing
199
for backing_pos in range(backing_pos):
200
self._backing_indices[backing_pos] = None
202
self._backing_indices.append(new_backing)
205
203
self._keys = set()
207
205
self._nodes_by_key = None
207
def _spill_mem_keys_without_combining(self):
208
return self._write_nodes(self._iter_mem_nodes(), allow_optimize=False)
210
def _spill_mem_keys_and_combine(self):
211
iterators_to_combine = [self._iter_mem_nodes()]
213
for pos, backing in enumerate(self._backing_indices):
217
iterators_to_combine.append(backing.iter_all_entries())
218
backing_pos = pos + 1
219
new_backing_file, size = \
220
self._write_nodes(self._iter_smallest(iterators_to_combine),
221
allow_optimize=False)
222
return new_backing_file, size, backing_pos
209
224
def add_nodes(self, nodes):
210
225
"""Add nodes to the index.
262
277
except StopIteration:
263
278
current_values[pos] = None
265
def _add_key(self, string_key, line, rows):
280
def _add_key(self, string_key, line, rows, allow_optimize=True):
266
281
"""Add a key to the current chunk.
268
283
:param string_key: The key to add.
269
284
:param line: The fully serialised key and value.
285
:param allow_optimize: If set to False, prevent setting the optimize
286
flag when writing out. This is used by the _spill_mem_keys_to_disk
271
289
if rows[-1].writer is None:
272
290
# opening a new leaf chunk;
277
295
length = _PAGE_SIZE
278
296
if internal_row.nodes == 0:
279
297
length -= _RESERVED_HEADER_BYTES # padded
299
optimize_for_size = self._optimize_for_size
301
optimize_for_size = False
280
302
internal_row.writer = chunk_writer.ChunkWriter(length, 0,
281
optimize_for_size=self._optimize_for_size)
303
optimize_for_size=optimize_for_size)
282
304
internal_row.writer.write(_INTERNAL_FLAG)
283
305
internal_row.writer.write(_INTERNAL_OFFSET +
284
306
str(rows[pos + 1].nodes) + "\n")
322
344
new_row.writer.write(_INTERNAL_OFFSET +
323
345
str(rows[1].nodes - 1) + "\n")
324
346
new_row.writer.write(key_line)
325
self._add_key(string_key, line, rows)
347
self._add_key(string_key, line, rows, allow_optimize=allow_optimize)
327
def _write_nodes(self, node_iterator):
349
def _write_nodes(self, node_iterator, allow_optimize=True):
328
350
"""Write node_iterator out as a B+Tree.
330
352
:param node_iterator: An iterator of sorted nodes. Each node should
331
353
match the output given by iter_all_entries.
354
:param allow_optimize: If set to False, prevent setting the optimize
355
flag when writing out. This is used by the _spill_mem_keys_to_disk
332
357
:return: A file handle for a temporary file containing a B+Tree for
354
379
string_key, line = _btree_serializer._flatten_node(node,
355
380
self.reference_lists)
356
self._add_key(string_key, line, rows)
381
self._add_key(string_key, line, rows, allow_optimize=allow_optimize)
357
382
for row in reversed(rows):
358
383
pad = (type(row) != _LeafBuilderRow)
359
384
row.finish_node(pad=pad)
360
result = tempfile.NamedTemporaryFile()
385
result = tempfile.NamedTemporaryFile(prefix='bzr-index-')
361
386
lines = [_BTSIGNATURE]
362
387
lines.append(_OPTION_NODE_REFS + str(self.reference_lists) + '\n')
363
388
lines.append(_OPTION_KEY_ELEMENTS + str(self._key_length) + '\n')