comparison mercurial/revlog.py @ 30001:b5e5ddf48bd2

revlog: specify checkambig at writing to avoid file stat ambiguity This allows revlog-style files to be written out with checkambig=True easily. Because avoiding file stat ambiguity is needed only for filecache-ed manifest and changelog, this patch does: - use False for default value of checkambig - focus only on writing changes of index file out This patch also adds optional argument checkambig to _divert/_delay for changelog, to safely accept checkambig specified in revlog layer. But this argument can be fully ignored, because: - changes are written into other than index file, if name != target - changes are never written into index file, otherwise (into pending file by _divert, or into in-memory buffer by _delay) This is a part of ExactCacheValidationPlan. https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Thu, 22 Sep 2016 21:51:58 +0900
parents 92ac2baaea86
children d81fe5af92b8
comparison
equal deleted inserted replaced
30000:9766d88c2465 30001:b5e5ddf48bd2
210 210
211 Both pieces of the revlog are written to in an append-only 211 Both pieces of the revlog are written to in an append-only
212 fashion, which means we never need to rewrite a file to insert or 212 fashion, which means we never need to rewrite a file to insert or
213 remove data, and can use some simple techniques to avoid the need 213 remove data, and can use some simple techniques to avoid the need
214 for locking while reading. 214 for locking while reading.
215
216 If checkambig, indexfile is opened with checkambig=True at
217 writing, to avoid file stat ambiguity.
215 """ 218 """
216 def __init__(self, opener, indexfile): 219 def __init__(self, opener, indexfile, checkambig=False):
217 """ 220 """
218 create a revlog object 221 create a revlog object
219 222
220 opener is a function that abstracts the file opening operation 223 opener is a function that abstracts the file opening operation
221 and can be used to implement COW semantics or the like. 224 and can be used to implement COW semantics or the like.
222 """ 225 """
223 self.indexfile = indexfile 226 self.indexfile = indexfile
224 self.datafile = indexfile[:-2] + ".d" 227 self.datafile = indexfile[:-2] + ".d"
225 self.opener = opener 228 self.opener = opener
229 # When True, indexfile is opened with checkambig=True at writing, to
230 # avoid file stat ambiguity.
231 self._checkambig = checkambig
226 # 3-tuple of (node, rev, text) for a raw revision. 232 # 3-tuple of (node, rev, text) for a raw revision.
227 self._cache = None 233 self._cache = None
228 # Maps rev to chain base rev. 234 # Maps rev to chain base rev.
229 self._chainbasecache = util.lrucachedict(100) 235 self._chainbasecache = util.lrucachedict(100)
230 # 2-tuple of (offset, data) of raw data from the revlog at an offset. 236 # 2-tuple of (offset, data) of raw data from the revlog at an offset.
1274 for r in self: 1280 for r in self:
1275 df.write(self._chunkraw(r, r)[1]) 1281 df.write(self._chunkraw(r, r)[1])
1276 finally: 1282 finally:
1277 df.close() 1283 df.close()
1278 1284
1279 fp = self.opener(self.indexfile, 'w', atomictemp=True) 1285 fp = self.opener(self.indexfile, 'w', atomictemp=True,
1286 checkambig=self._checkambig)
1280 self.version &= ~(REVLOGNGINLINEDATA) 1287 self.version &= ~(REVLOGNGINLINEDATA)
1281 self._inline = False 1288 self._inline = False
1282 for i in self: 1289 for i in self:
1283 e = self._io.packentry(self.index[i], self.node, self.version, i) 1290 e = self._io.packentry(self.index[i], self.node, self.version, i)
1284 fp.write(e) 1291 fp.write(e)
1317 return node 1324 return node
1318 1325
1319 dfh = None 1326 dfh = None
1320 if not self._inline: 1327 if not self._inline:
1321 dfh = self.opener(self.datafile, "a+") 1328 dfh = self.opener(self.datafile, "a+")
1322 ifh = self.opener(self.indexfile, "a+") 1329 ifh = self.opener(self.indexfile, "a+", checkambig=self._checkambig)
1323 try: 1330 try:
1324 return self._addrevision(node, text, transaction, link, p1, p2, 1331 return self._addrevision(node, text, transaction, link, p1, p2,
1325 REVIDX_DEFAULT_FLAGS, cachedelta, ifh, dfh) 1332 REVIDX_DEFAULT_FLAGS, cachedelta, ifh, dfh)
1326 finally: 1333 finally:
1327 if dfh: 1334 if dfh:
1565 1572
1566 r = len(self) 1573 r = len(self)
1567 end = 0 1574 end = 0
1568 if r: 1575 if r:
1569 end = self.end(r - 1) 1576 end = self.end(r - 1)
1570 ifh = self.opener(self.indexfile, "a+") 1577 ifh = self.opener(self.indexfile, "a+", checkambig=self._checkambig)
1571 isize = r * self._io.size 1578 isize = r * self._io.size
1572 if self._inline: 1579 if self._inline:
1573 transaction.add(self.indexfile, end + isize, r) 1580 transaction.add(self.indexfile, end + isize, r)
1574 dfh = None 1581 dfh = None
1575 else: 1582 else:
1639 if not dfh and not self._inline: 1646 if not dfh and not self._inline:
1640 # addrevision switched from inline to conventional 1647 # addrevision switched from inline to conventional
1641 # reopen the index 1648 # reopen the index
1642 ifh.close() 1649 ifh.close()
1643 dfh = self.opener(self.datafile, "a+") 1650 dfh = self.opener(self.datafile, "a+")
1644 ifh = self.opener(self.indexfile, "a+") 1651 ifh = self.opener(self.indexfile, "a+",
1652 checkambig=self._checkambig)
1645 finally: 1653 finally:
1646 if dfh: 1654 if dfh:
1647 dfh.close() 1655 dfh.close()
1648 ifh.close() 1656 ifh.close()
1649 1657