~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-03-06 06:48:25 UTC
  • mfrom: (4070.8.6 debug-config)
  • Revision ID: pqm@pqm.ubuntu.com-20090306064825-kbpwggw21dygeix6
(mbp) debug_flags configuration option

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Knit versionedfile implementation.
18
18
 
103
103
    ConstantMapper,
104
104
    ContentFactory,
105
105
    ChunkedContentFactory,
106
 
    sort_groupcompress,
107
106
    VersionedFile,
108
107
    VersionedFiles,
109
108
    )
299
298
            if self._network_bytes is None:
300
299
                self._create_network_bytes()
301
300
            return self._network_bytes
302
 
        if ('-ft-' in self.storage_kind and
303
 
            storage_kind in ('chunked', 'fulltext')):
304
 
            adapter_key = (self.storage_kind, 'fulltext')
305
 
            adapter_factory = adapter_registry.get(adapter_key)
306
 
            adapter = adapter_factory(None)
307
 
            bytes = adapter.get_bytes(self)
308
 
            if storage_kind == 'chunked':
309
 
                return [bytes]
310
 
            else:
311
 
                return bytes
312
301
        if self._knit is not None:
313
 
            # Not redundant with direct conversion above - that only handles
314
 
            # fulltext cases.
315
302
            if storage_kind == 'chunked':
316
303
                return self._knit.get_lines(self.key[0])
317
304
            elif storage_kind == 'fulltext':
955
942
                lines[-1] = lines[-1] + '\n'
956
943
                line_bytes += '\n'
957
944
 
958
 
        for element in key[:-1]:
 
945
        for element in key:
959
946
            if type(element) != str:
960
947
                raise TypeError("key contains non-strings: %r" % (key,))
961
 
        if key[-1] is None:
962
 
            key = key[:-1] + ('sha1:' + digest,)
963
 
        elif type(key[-1]) != str:
964
 
                raise TypeError("key contains non-strings: %r" % (key,))
965
948
        # Knit hunks are still last-element only
966
949
        version_id = key[-1]
967
950
        content = self._factory.make(lines, version_id)
983
966
        else:
984
967
            options.append('fulltext')
985
968
            # isinstance is slower and we have no hierarchy.
986
 
            if self._factory.__class__ is KnitPlainFactory:
 
969
            if self._factory.__class__ == KnitPlainFactory:
987
970
                # Use the already joined bytes saving iteration time in
988
971
                # _record_to_data.
989
972
                size, bytes = self._record_to_data(key, digest,
1026
1009
    def _check_add(self, key, lines, random_id, check_content):
1027
1010
        """check that version_id and lines are safe to add."""
1028
1011
        version_id = key[-1]
1029
 
        if version_id is not None:
1030
 
            if contains_whitespace(version_id):
1031
 
                raise InvalidRevisionId(version_id, self)
1032
 
            self.check_not_reserved_id(version_id)
 
1012
        if contains_whitespace(version_id):
 
1013
            raise InvalidRevisionId(version_id, self)
 
1014
        self.check_not_reserved_id(version_id)
1033
1015
        # TODO: If random_id==False and the key is already present, we should
1034
1016
        # probably check that the existing content is identical to what is
1035
1017
        # being inserted, and otherwise raise an exception.  This would make
1315
1297
        if cur_keys:
1316
1298
            result.append((cur_keys, cur_non_local))
1317
1299
            sizes.append(cur_size)
 
1300
        trace.mutter('Collapsed %d keys into %d requests w/ %d file_ids'
 
1301
                     ' w/ sizes: %s', total_keys, len(result),
 
1302
                     len(prefix_split_keys), sizes)
1318
1303
        return result
1319
1304
 
1320
1305
    def get_record_stream(self, keys, ordering, include_delta_closure):
1334
1319
        if not keys:
1335
1320
            return
1336
1321
        if not self._index.has_graph:
1337
 
            # Cannot sort when no graph has been stored.
 
1322
            # Cannot topological order when no graph has been stored.
1338
1323
            ordering = 'unordered'
1339
1324
 
1340
1325
        remaining_keys = keys
1396
1381
                    needed_from_fallback.add(key)
1397
1382
        # Double index lookups here : need a unified api ?
1398
1383
        global_map, parent_maps = self._get_parent_map_with_sources(keys)
1399
 
        if ordering in ('topological', 'groupcompress'):
1400
 
            if ordering == 'topological':
1401
 
                # Global topological sort
1402
 
                present_keys = tsort.topo_sort(global_map)
1403
 
            else:
1404
 
                present_keys = sort_groupcompress(global_map)
 
1384
        if ordering == 'topological':
 
1385
            # Global topological sort
 
1386
            present_keys = tsort.topo_sort(global_map)
1405
1387
            # Now group by source:
1406
1388
            source_keys = []
1407
1389
            current_source = None
1417
1399
        else:
1418
1400
            if ordering != 'unordered':
1419
1401
                raise AssertionError('valid values for ordering are:'
1420
 
                    ' "unordered", "groupcompress" or "topological" not: %r'
 
1402
                    ' "unordered" or "topological" not: %r'
1421
1403
                    % (ordering,))
1422
1404
            # Just group by source; remote sources first.
1423
1405
            present_keys = []
1614
1596
                # KnitVersionedFiles doesn't permit deltas (_max_delta_chain ==
1615
1597
                # 0) or because it depends on a base only present in the
1616
1598
                # fallback kvfs.
1617
 
                self._access.flush()
1618
1599
                try:
1619
1600
                    # Try getting a fulltext directly from the record.
1620
1601
                    bytes = record.get_bytes_as('fulltext')
1680
1661
         * If a requested key did not change any lines (or didn't have any
1681
1662
           lines), it may not be mentioned at all in the result.
1682
1663
 
1683
 
        :param pb: Progress bar supplied by caller.
1684
1664
        :return: An iterator over (line, key).
1685
1665
        """
1686
1666
        if pb is None:
1700
1680
                        key_records.append((key, details[0]))
1701
1681
                records_iter = enumerate(self._read_records_iter(key_records))
1702
1682
                for (key_idx, (key, data, sha_value)) in records_iter:
1703
 
                    pb.update('Walking content', key_idx, total)
 
1683
                    pb.update('Walking content.', key_idx, total)
1704
1684
                    compression_parent = build_details[key][1]
1705
1685
                    if compression_parent is None:
1706
1686
                        # fulltext
1736
1716
                source_keys.add(key)
1737
1717
                yield line, key
1738
1718
            keys.difference_update(source_keys)
1739
 
        pb.update('Walking content', total, total)
 
1719
        pb.update('Walking content.', total, total)
1740
1720
 
1741
1721
    def _make_line_delta(self, delta_seq, new_content):
1742
1722
        """Generate a line delta from delta_seq and new_content."""
3055
3035
            result.append((key, base, size))
3056
3036
        return result
3057
3037
 
3058
 
    def flush(self):
3059
 
        """Flush pending writes on this access object.
3060
 
        
3061
 
        For .knit files this is a no-op.
3062
 
        """
3063
 
        pass
3064
 
 
3065
3038
    def get_raw_records(self, memos_for_retrieval):
3066
3039
        """Get the raw bytes for a records.
3067
3040
 
3092
3065
class _DirectPackAccess(object):
3093
3066
    """Access to data in one or more packs with less translation."""
3094
3067
 
3095
 
    def __init__(self, index_to_packs, reload_func=None, flush_func=None):
 
3068
    def __init__(self, index_to_packs, reload_func=None):
3096
3069
        """Create a _DirectPackAccess object.
3097
3070
 
3098
3071
        :param index_to_packs: A dict mapping index objects to the transport
3105
3078
        self._write_index = None
3106
3079
        self._indices = index_to_packs
3107
3080
        self._reload_func = reload_func
3108
 
        self._flush_func = flush_func
3109
3081
 
3110
3082
    def add_raw_records(self, key_sizes, raw_data):
3111
3083
        """Add raw knit bytes to a storage area.
3133
3105
            result.append((self._write_index, p_offset, p_length))
3134
3106
        return result
3135
3107
 
3136
 
    def flush(self):
3137
 
        """Flush pending writes on this access object.
3138
 
 
3139
 
        This will flush any buffered writes to a NewPack.
3140
 
        """
3141
 
        if self._flush_func is not None:
3142
 
            self._flush_func()
3143
 
            
3144
3108
    def get_raw_records(self, memos_for_retrieval):
3145
3109
        """Get the raw bytes for a records.
3146
3110