comparison mercurial/revlog.py @ 14296:62e25c63fb3a

revlog: fix bug in chainbase cache The bug didn't cause corruption, and thus wasn't caught in hg verify or in tests. It could lead to delta chains longer than normally allowed, by affecting the code that decides when to add a full revision. This could, in turn, lead to performance regression.
author Sune Foldager <cryo@cyanite.org>
date Thu, 12 May 2011 13:47:17 +0200
parents c97d8485b5fa
children f94993769c87
comparison
equal deleted inserted replaced
14295:bb7e3b3e6e11 14296:62e25c63fb3a
216 """ 216 """
217 self.indexfile = indexfile 217 self.indexfile = indexfile
218 self.datafile = indexfile[:-2] + ".d" 218 self.datafile = indexfile[:-2] + ".d"
219 self.opener = opener 219 self.opener = opener
220 self._cache = None 220 self._cache = None
221 self._basecache = None 221 self._basecache = (0, 0)
222 self._chunkcache = (0, '') 222 self._chunkcache = (0, '')
223 self.index = [] 223 self.index = []
224 self._pcache = {} 224 self._pcache = {}
225 self._nodecache = {nullid: nullrev} 225 self._nodecache = {nullid: nullrev}
226 self._nodepos = None 226 self._nodepos = None
1008 t = buildtext() 1008 t = buildtext()
1009 ptext = self.revision(self.node(rev)) 1009 ptext = self.revision(self.node(rev))
1010 delta = mdiff.textdiff(ptext, t) 1010 delta = mdiff.textdiff(ptext, t)
1011 data = compress(delta) 1011 data = compress(delta)
1012 l = len(data[1]) + len(data[0]) 1012 l = len(data[1]) + len(data[0])
1013 basecache = self._basecache 1013 if basecache[0] == rev:
1014 if basecache and basecache[0] == rev:
1015 chainbase = basecache[1] 1014 chainbase = basecache[1]
1016 else: 1015 else:
1017 chainbase = self.chainbase(rev) 1016 chainbase = self.chainbase(rev)
1018 dist = l + offset - self.start(chainbase) 1017 dist = l + offset - self.start(chainbase)
1019 if self._generaldelta: 1018 if self._generaldelta:
1020 base = rev 1019 base = rev
1021 else: 1020 else:
1022 base = chainbase 1021 base = chainbase
1023 return dist, l, data, base 1022 return dist, l, data, base, chainbase
1024 1023
1025 curr = len(self) 1024 curr = len(self)
1026 prev = curr - 1 1025 prev = curr - 1
1027 base = curr 1026 base = chainbase = curr
1028 offset = self.end(prev) 1027 offset = self.end(prev)
1029 flags = 0 1028 flags = 0
1030 d = None 1029 d = None
1030 basecache = self._basecache
1031 p1r, p2r = self.rev(p1), self.rev(p2) 1031 p1r, p2r = self.rev(p1), self.rev(p2)
1032 1032
1033 # should we try to build a delta? 1033 # should we try to build a delta?
1034 if prev != nullrev: 1034 if prev != nullrev:
1035 if self._generaldelta: 1035 if self._generaldelta:
1036 d = builddelta(p1r) 1036 d = builddelta(p1r)
1037 else: 1037 else:
1038 d = builddelta(prev) 1038 d = builddelta(prev)
1039 dist, l, data, base = d 1039 dist, l, data, base, chainbase = d
1040 1040
1041 # full versions are inserted when the needed deltas 1041 # full versions are inserted when the needed deltas
1042 # become comparable to the uncompressed text 1042 # become comparable to the uncompressed text
1043 if text is None: 1043 if text is None:
1044 textlen = mdiff.patchedsize(self.rawsize(cachedelta[0]), 1044 textlen = mdiff.patchedsize(self.rawsize(cachedelta[0]),
1047 textlen = len(text) 1047 textlen = len(text)
1048 if d is None or dist > textlen * 2: 1048 if d is None or dist > textlen * 2:
1049 text = buildtext() 1049 text = buildtext()
1050 data = compress(text) 1050 data = compress(text)
1051 l = len(data[1]) + len(data[0]) 1051 l = len(data[1]) + len(data[0])
1052 base = curr 1052 base = chainbase = curr
1053 1053
1054 e = (offset_type(offset, flags), l, textlen, 1054 e = (offset_type(offset, flags), l, textlen,
1055 base, link, p1r, p2r, node) 1055 base, link, p1r, p2r, node)
1056 self.index.insert(-1, e) 1056 self.index.insert(-1, e)
1057 self.nodemap[node] = curr 1057 self.nodemap[node] = curr
1073 ifh.write(data[1]) 1073 ifh.write(data[1])
1074 self.checkinlinesize(transaction, ifh) 1074 self.checkinlinesize(transaction, ifh)
1075 1075
1076 if type(text) == str: # only accept immutable objects 1076 if type(text) == str: # only accept immutable objects
1077 self._cache = (node, curr, text) 1077 self._cache = (node, curr, text)
1078 self._basecache = (curr, base) 1078 self._basecache = (curr, chainbase)
1079 return node 1079 return node
1080 1080
1081 def group(self, nodelist, bundler): 1081 def group(self, nodelist, bundler):
1082 """Calculate a delta group, yielding a sequence of changegroup chunks 1082 """Calculate a delta group, yielding a sequence of changegroup chunks
1083 (strings). 1083 (strings).