1987
1975
:param key: The key of the record. Currently keys are always serialised
1988
1976
using just the trailing component.
1989
1977
:param dense_lines: The bytes of lines but in a denser form. For
1990
instance, if lines is a list of 1000 bytestrings each ending in \n,
1991
dense_lines may be a list with one line in it, containing all the
1992
1000's lines and their \n's. Using dense_lines if it is already
1993
known is a win because the string join to create bytes in this
1994
function spends less time resizing the final string.
1978
instance, if lines is a list of 1000 bytestrings each ending in
1979
\\n, dense_lines may be a list with one line in it, containing all
1980
the 1000's lines and their \\n's. Using dense_lines if it is
1981
already known is a win because the string join to create bytes in
1982
this function spends less time resizing the final string.
1995
1983
:return: (len, a StringIO instance with the raw data ready to read.)
1997
1985
chunks = ["version %s %d %s\n" % (key[-1], len(lines), digest)]
3225
class _DirectPackAccess(object):
3226
"""Access to data in one or more packs with less translation."""
3228
def __init__(self, index_to_packs, reload_func=None, flush_func=None):
3229
"""Create a _DirectPackAccess object.
3231
:param index_to_packs: A dict mapping index objects to the transport
3232
and file names for obtaining data.
3233
:param reload_func: A function to call if we determine that the pack
3234
files have moved and we need to reload our caches. See
3235
bzrlib.repo_fmt.pack_repo.AggregateIndex for more details.
3237
self._container_writer = None
3238
self._write_index = None
3239
self._indices = index_to_packs
3240
self._reload_func = reload_func
3241
self._flush_func = flush_func
3243
def add_raw_records(self, key_sizes, raw_data):
3244
"""Add raw knit bytes to a storage area.
3246
The data is spooled to the container writer in one bytes-record per
3249
:param sizes: An iterable of tuples containing the key and size of each
3251
:param raw_data: A bytestring containing the data.
3252
:return: A list of memos to retrieve the record later. Each memo is an
3253
opaque index memo. For _DirectPackAccess the memo is (index, pos,
3254
length), where the index field is the write_index object supplied
3255
to the PackAccess object.
3257
if type(raw_data) is not str:
3258
raise AssertionError(
3259
'data must be plain bytes was %s' % type(raw_data))
3262
for key, size in key_sizes:
3263
p_offset, p_length = self._container_writer.add_bytes_record(
3264
raw_data[offset:offset+size], [])
3266
result.append((self._write_index, p_offset, p_length))
3270
"""Flush pending writes on this access object.
3272
This will flush any buffered writes to a NewPack.
3274
if self._flush_func is not None:
3277
def get_raw_records(self, memos_for_retrieval):
3278
"""Get the raw bytes for a records.
3280
:param memos_for_retrieval: An iterable containing the (index, pos,
3281
length) memo for retrieving the bytes. The Pack access method
3282
looks up the pack to use for a given record in its index_to_pack
3284
:return: An iterator over the bytes of the records.
3286
# first pass, group into same-index requests
3288
current_index = None
3289
for (index, offset, length) in memos_for_retrieval:
3290
if current_index == index:
3291
current_list.append((offset, length))
3293
if current_index is not None:
3294
request_lists.append((current_index, current_list))
3295
current_index = index
3296
current_list = [(offset, length)]
3297
# handle the last entry
3298
if current_index is not None:
3299
request_lists.append((current_index, current_list))
3300
for index, offsets in request_lists:
3302
transport, path = self._indices[index]
3304
# A KeyError here indicates that someone has triggered an index
3305
# reload, and this index has gone missing, we need to start
3307
if self._reload_func is None:
3308
# If we don't have a _reload_func there is nothing that can
3311
raise errors.RetryWithNewPacks(index,
3312
reload_occurred=True,
3313
exc_info=sys.exc_info())
3315
reader = pack.make_readv_reader(transport, path, offsets)
3316
for names, read_func in reader.iter_records():
3317
yield read_func(None)
3318
except errors.NoSuchFile:
3319
# A NoSuchFile error indicates that a pack file has gone
3320
# missing on disk, we need to trigger a reload, and start over.
3321
if self._reload_func is None:
3323
raise errors.RetryWithNewPacks(transport.abspath(path),
3324
reload_occurred=False,
3325
exc_info=sys.exc_info())
3327
def set_writer(self, writer, index, transport_packname):
3328
"""Set a writer to use for adding data."""
3329
if index is not None:
3330
self._indices[index] = transport_packname
3331
self._container_writer = writer
3332
self._write_index = index
3334
def reload_or_raise(self, retry_exc):
3335
"""Try calling the reload function, or re-raise the original exception.
3337
This should be called after _DirectPackAccess raises a
3338
RetryWithNewPacks exception. This function will handle the common logic
3339
of determining when the error is fatal versus being temporary.
3340
It will also make sure that the original exception is raised, rather
3341
than the RetryWithNewPacks exception.
3343
If this function returns, then the calling function should retry
3344
whatever operation was being performed. Otherwise an exception will
3347
:param retry_exc: A RetryWithNewPacks exception.
3350
if self._reload_func is None:
3352
elif not self._reload_func():
3353
# The reload claimed that nothing changed
3354
if not retry_exc.reload_occurred:
3355
# If there wasn't an earlier reload, then we really were
3356
# expecting to find changes. We didn't find them, so this is a
3360
exc_class, exc_value, exc_traceback = retry_exc.exc_info
3361
raise exc_class, exc_value, exc_traceback
3364
3213
def annotate_knit(knit, revision_id):
3365
3214
"""Annotate a knit with no cached annotations.