# HG changeset patch # User mason@suse.com # Date 1141151094 21600 # Node ID a2c69737e65ed91c3c4d787ddbe636e9d6d27369 # Parent 2af98c4b258713946046ec903cd77d36c7f2e205 Automatic nesting into running transactions in the same repository. This associates a transaction handle with a given repository object, and any additional calls to start new transactions reuse that transaction. For the 2700 patch import run, this brings the system time down from 1m20s to 50s, mostly by skipping backups of the dirstate file. (note, this patch does not change hg import to use the nested transaction, mq is the only user right now) diff -r 2af98c4b2587 -r a2c69737e65e mercurial/localrepo.py --- a/mercurial/localrepo.py Tue Feb 28 11:49:35 2006 -0600 +++ b/mercurial/localrepo.py Tue Feb 28 12:24:54 2006 -0600 @@ -13,6 +13,8 @@ demandload(globals(), "re lock transaction tempfile stat mdiff errno") class localrepository(object): + def __del__(self): + self.transhandle = None def __init__(self, ui, path=None, create=0): if not path: p = os.getcwd() @@ -37,6 +39,7 @@ self.nodetagscache = None self.encodepats = None self.decodepats = None + self.transhandle = None if create: os.mkdir(self.path) @@ -215,6 +218,10 @@ return self.wopener(filename, 'w').write(data) def transaction(self): + tr = self.transhandle + if tr != None and tr.running(): + return tr.nest() + # save dirstate for undo try: ds = self.opener("dirstate").read() @@ -222,13 +229,11 @@ ds = "" self.opener("journal.dirstate", "w").write(ds) - def after(): - util.rename(self.join("journal"), self.join("undo")) - util.rename(self.join("journal.dirstate"), - self.join("undo.dirstate")) - - return transaction.transaction(self.ui.warn, self.opener, - self.join("journal"), after) + tr = transaction.transaction(self.ui.warn, self.opener, + self.join("journal"), + aftertrans(self.path)) + self.transhandle = tr + return tr def recover(self): l = self.lock() @@ -1879,3 +1884,13 @@ if errors[0]: self.ui.warn(_("%d integrity errors encountered!\n") % errors[0]) return 1 + +# used to avoid circular references so destructors work +def aftertrans(base): + p = base + def a(): + util.rename(os.path.join(p, "journal"), os.path.join(p, "undo")) + util.rename(os.path.join(p, "journal.dirstate"), + os.path.join(p, "undo.dirstate")) + return a + diff -r 2af98c4b2587 -r a2c69737e65e mercurial/transaction.py --- a/mercurial/transaction.py Tue Feb 28 11:49:35 2006 -0600 +++ b/mercurial/transaction.py Tue Feb 28 12:24:54 2006 -0600 @@ -22,6 +22,7 @@ if os.path.exists(journal): raise AssertionError(_("journal already exists - run hg recover")) + self.count = 1 self.report = report self.opener = opener self.after = after @@ -46,7 +47,17 @@ self.file.write("%s\0%d\n" % (file, offset)) self.file.flush() + def nest(self): + self.count += 1 + return self + + def running(self): + return self.count > 0 + def close(self): + self.count -= 1 + if self.count != 0: + return self.file.close() self.entries = [] if self.after: