1509
1498
if source is parent_maps[0]:
1510
1499
# this KnitVersionedFiles
1511
1500
records = [(key, positions[key][1]) for key in keys]
1512
for key, raw_data in self._read_records_iter_unchecked(records):
1501
for key, raw_data, sha1 in self._read_records_iter_raw(records):
1513
1502
(record_details, index_memo, _) = positions[key]
1514
1503
yield KnitContentFactory(key, global_map[key],
1515
record_details, None, raw_data, self._factory.annotated, None)
1504
record_details, sha1, raw_data, self._factory.annotated, None)
1517
vf = self._immediate_fallback_vfs[parent_maps.index(source) - 1]
1506
vf = self._fallback_vfs[parent_maps.index(source) - 1]
1518
1507
for record in vf.get_record_stream(keys, ordering,
1519
1508
include_delta_closure):
1975
1954
:param key: The key of the record. Currently keys are always serialised
1976
1955
using just the trailing component.
1977
1956
:param dense_lines: The bytes of lines but in a denser form. For
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.
1957
instance, if lines is a list of 1000 bytestrings each ending in \n,
1958
dense_lines may be a list with one line in it, containing all the
1959
1000's lines and their \n's. Using dense_lines if it is already
1960
known is a win because the string join to create bytes in this
1961
function spends less time resizing the final string.
1983
1962
:return: (len, a StringIO instance with the raw data ready to read.)
1985
1964
chunks = ["version %s %d %s\n" % (key[-1], len(lines), digest)]
3194
class _DirectPackAccess(object):
3195
"""Access to data in one or more packs with less translation."""
3197
def __init__(self, index_to_packs, reload_func=None, flush_func=None):
3198
"""Create a _DirectPackAccess object.
3200
:param index_to_packs: A dict mapping index objects to the transport
3201
and file names for obtaining data.
3202
:param reload_func: A function to call if we determine that the pack
3203
files have moved and we need to reload our caches. See
3204
bzrlib.repo_fmt.pack_repo.AggregateIndex for more details.
3206
self._container_writer = None
3207
self._write_index = None
3208
self._indices = index_to_packs
3209
self._reload_func = reload_func
3210
self._flush_func = flush_func
3212
def add_raw_records(self, key_sizes, raw_data):
3213
"""Add raw knit bytes to a storage area.
3215
The data is spooled to the container writer in one bytes-record per
3218
:param sizes: An iterable of tuples containing the key and size of each
3220
:param raw_data: A bytestring containing the data.
3221
:return: A list of memos to retrieve the record later. Each memo is an
3222
opaque index memo. For _DirectPackAccess the memo is (index, pos,
3223
length), where the index field is the write_index object supplied
3224
to the PackAccess object.
3226
if type(raw_data) is not str:
3227
raise AssertionError(
3228
'data must be plain bytes was %s' % type(raw_data))
3231
for key, size in key_sizes:
3232
p_offset, p_length = self._container_writer.add_bytes_record(
3233
raw_data[offset:offset+size], [])
3235
result.append((self._write_index, p_offset, p_length))
3239
"""Flush pending writes on this access object.
3241
This will flush any buffered writes to a NewPack.
3243
if self._flush_func is not None:
3246
def get_raw_records(self, memos_for_retrieval):
3247
"""Get the raw bytes for a records.
3249
:param memos_for_retrieval: An iterable containing the (index, pos,
3250
length) memo for retrieving the bytes. The Pack access method
3251
looks up the pack to use for a given record in its index_to_pack
3253
:return: An iterator over the bytes of the records.
3255
# first pass, group into same-index requests
3257
current_index = None
3258
for (index, offset, length) in memos_for_retrieval:
3259
if current_index == index:
3260
current_list.append((offset, length))
3262
if current_index is not None:
3263
request_lists.append((current_index, current_list))
3264
current_index = index
3265
current_list = [(offset, length)]
3266
# handle the last entry
3267
if current_index is not None:
3268
request_lists.append((current_index, current_list))
3269
for index, offsets in request_lists:
3271
transport, path = self._indices[index]
3273
# A KeyError here indicates that someone has triggered an index
3274
# reload, and this index has gone missing, we need to start
3276
if self._reload_func is None:
3277
# If we don't have a _reload_func there is nothing that can
3280
raise errors.RetryWithNewPacks(index,
3281
reload_occurred=True,
3282
exc_info=sys.exc_info())
3284
reader = pack.make_readv_reader(transport, path, offsets)
3285
for names, read_func in reader.iter_records():
3286
yield read_func(None)
3287
except errors.NoSuchFile:
3288
# A NoSuchFile error indicates that a pack file has gone
3289
# missing on disk, we need to trigger a reload, and start over.
3290
if self._reload_func is None:
3292
raise errors.RetryWithNewPacks(transport.abspath(path),
3293
reload_occurred=False,
3294
exc_info=sys.exc_info())
3296
def set_writer(self, writer, index, transport_packname):
3297
"""Set a writer to use for adding data."""
3298
if index is not None:
3299
self._indices[index] = transport_packname
3300
self._container_writer = writer
3301
self._write_index = index
3303
def reload_or_raise(self, retry_exc):
3304
"""Try calling the reload function, or re-raise the original exception.
3306
This should be called after _DirectPackAccess raises a
3307
RetryWithNewPacks exception. This function will handle the common logic
3308
of determining when the error is fatal versus being temporary.
3309
It will also make sure that the original exception is raised, rather
3310
than the RetryWithNewPacks exception.
3312
If this function returns, then the calling function should retry
3313
whatever operation was being performed. Otherwise an exception will
3316
:param retry_exc: A RetryWithNewPacks exception.
3319
if self._reload_func is None:
3321
elif not self._reload_func():
3322
# The reload claimed that nothing changed
3323
if not retry_exc.reload_occurred:
3324
# If there wasn't an earlier reload, then we really were
3325
# expecting to find changes. We didn't find them, so this is a
3329
exc_class, exc_value, exc_traceback = retry_exc.exc_info
3330
raise exc_class, exc_value, exc_traceback
3333
# Deprecated, use PatienceSequenceMatcher instead
3334
KnitSequenceMatcher = patiencediff.PatienceSequenceMatcher
3213
3337
def annotate_knit(knit, revision_id):
3214
3338
"""Annotate a knit with no cached annotations.