##// END OF EJS Templates
restructure changelog file appending...
Matt Mackall -
r4261:cd7b36b7 default
parent child Browse files
Show More
@@ -26,10 +26,89 b' def _string_escape(text):'
26 def _string_unescape(text):
26 def _string_unescape(text):
27 return text.decode('string_escape')
27 return text.decode('string_escape')
28
28
29 class appender:
30 '''the changelog index must be update last on disk, so we use this class
31 to delay writes to it'''
32 def __init__(self, fp, buf):
33 self.data = buf
34 self.fp = fp
35 self.offset = fp.tell()
36 self.size = util.fstat(fp).st_size
37
38 def end(self):
39 return self.size + len("".join(self.data))
40 def tell(self):
41 return self.offset
42 def flush(self):
43 pass
44 def close(self):
45 close(self.fp)
46
47 def seek(self, offset, whence=0):
48 '''virtual file offset spans real file and data'''
49 if whence == 0:
50 self.offset = offset
51 elif whence == 1:
52 self.offset += offset
53 elif whence == 2:
54 self.offset = self.end() + offset
55 if self.offset < self.size:
56 self.fp.seek(self.offset)
57
58 def read(self, count=-1):
59 '''only trick here is reads that span real file and data'''
60 ret = ""
61 old_offset = self.offset
62 if self.offset < self.size:
63 s = self.fp.read(count)
64 ret = s
65 self.offset += len(s)
66 if count > 0:
67 count -= len(s)
68 if count != 0:
69 doff = self.offset - self.size
70 self.data.insert(0, "".join(self.data))
71 del self.data[1:]
72 s = self.data[0][doff:doff+count]
73 self.offset += len(s)
74 ret += s
75 return ret
76
77 def write(self, s):
78 self.data.append(s)
79 self.offset += len(s)
80
29 class changelog(revlog):
81 class changelog(revlog):
30 def __init__(self, opener):
82 def __init__(self, opener):
31 revlog.__init__(self, opener, "00changelog.i")
83 revlog.__init__(self, opener, "00changelog.i")
32
84
85 def delayupdate(self):
86 "delay visibility of index updates to other readers"
87 self._realopener = self.opener
88 self.opener = self._appendopener
89 self._delaybuf = []
90
91 def finalize(self, tr):
92 "finalize index updates"
93 self.opener = self._realopener
94 if self._delaybuf:
95 fp = self.opener(self.indexfile, 'a')
96 fp.write("".join(self._delaybuf))
97 fp.close()
98 del self._delaybuf
99 self.checkinlinesize(tr)
100
101 def _appendopener(self, name, mode='r'):
102 fp = self._realopener(name, mode)
103 if not name == self.indexfile:
104 return fp
105 return appender(fp, self._delaybuf)
106
107 def checkinlinesize(self, tr, fp=None):
108 if self.opener == self._appendopener:
109 return
110 return revlog.checkinlinesize(self, tr, fp)
111
33 def decode_extra(self, text):
112 def decode_extra(self, text):
34 extra = {}
113 extra = {}
35 for l in text.split('\0'):
114 for l in text.split('\0'):
@@ -7,7 +7,7 b''
7
7
8 from node import *
8 from node import *
9 from i18n import _
9 from i18n import _
10 import repo, appendfile, changegroup
10 import repo, changegroup
11 import changelog, dirstate, filelog, manifest, context
11 import changelog, dirstate, filelog, manifest, context
12 import re, lock, transaction, tempfile, stat, mdiff, errno, ui
12 import re, lock, transaction, tempfile, stat, mdiff, errno, ui
13 import os, revlog, time, util
13 import os, revlog, time, util
@@ -1782,52 +1782,45 b' class localrepository(repo.repository):'
1782
1782
1783 # write changelog data to temp files so concurrent readers will not see
1783 # write changelog data to temp files so concurrent readers will not see
1784 # inconsistent view
1784 # inconsistent view
1785 cl = None
1785 cl = self.changelog
1786 try:
1786 cl.delayupdate()
1787 cl = appendfile.appendchangelog(self.sopener)
1787 oldheads = len(cl.heads())
1788 oldheads = len(cl.heads())
1788
1789 # pull off the changeset group
1790 self.ui.status(_("adding changesets\n"))
1791 cor = cl.count() - 1
1792 chunkiter = changegroup.chunkiter(source)
1793 if cl.addgroup(chunkiter, csmap, tr, 1) is None:
1794 raise util.Abort(_("received changelog group is empty"))
1795 cnr = cl.count() - 1
1796 changesets = cnr - cor
1789
1797
1790 # pull off the changeset group
1798 # pull off the manifest group
1791 self.ui.status(_("adding changesets\n"))
1799 self.ui.status(_("adding manifests\n"))
1792 cor = cl.count() - 1
1800 chunkiter = changegroup.chunkiter(source)
1793 chunkiter = changegroup.chunkiter(source)
1801 # no need to check for empty manifest group here:
1794 if cl.addgroup(chunkiter, csmap, tr, 1) is None:
1802 # if the result of the merge of 1 and 2 is the same in 3 and 4,
1795 raise util.Abort(_("received changelog group is empty"))
1803 # no new manifest will be created and the manifest group will
1796 cnr = cl.count() - 1
1804 # be empty during the pull
1797 changesets = cnr - cor
1805 self.manifest.addgroup(chunkiter, revmap, tr)
1798
1806
1799 # pull off the manifest group
1807 # process the files
1800 self.ui.status(_("adding manifests\n"))
1808 self.ui.status(_("adding file changes\n"))
1809 while 1:
1810 f = changegroup.getchunk(source)
1811 if not f:
1812 break
1813 self.ui.debug(_("adding %s revisions\n") % f)
1814 fl = self.file(f)
1815 o = fl.count()
1801 chunkiter = changegroup.chunkiter(source)
1816 chunkiter = changegroup.chunkiter(source)
1802 # no need to check for empty manifest group here:
1817 if fl.addgroup(chunkiter, revmap, tr) is None:
1803 # if the result of the merge of 1 and 2 is the same in 3 and 4,
1818 raise util.Abort(_("received file revlog group is empty"))
1804 # no new manifest will be created and the manifest group will
1819 revisions += fl.count() - o
1805 # be empty during the pull
1820 files += 1
1806 self.manifest.addgroup(chunkiter, revmap, tr)
1807
1808 # process the files
1809 self.ui.status(_("adding file changes\n"))
1810 while 1:
1811 f = changegroup.getchunk(source)
1812 if not f:
1813 break
1814 self.ui.debug(_("adding %s revisions\n") % f)
1815 fl = self.file(f)
1816 o = fl.count()
1817 chunkiter = changegroup.chunkiter(source)
1818 if fl.addgroup(chunkiter, revmap, tr) is None:
1819 raise util.Abort(_("received file revlog group is empty"))
1820 revisions += fl.count() - o
1821 files += 1
1822
1823 cl.writedata()
1824 finally:
1825 if cl:
1826 cl.cleanup()
1827
1821
1828 # make changelog see real files again
1822 # make changelog see real files again
1829 self.changelog = changelog.changelog(self.sopener)
1823 cl.finalize(tr)
1830 self.changelog.checkinlinesize(tr)
1831
1824
1832 newheads = len(self.changelog.heads())
1825 newheads = len(self.changelog.heads())
1833 heads = ""
1826 heads = ""
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now