[patch 5/7] Automatic nesting into running transactions in the same repository.

Chris Mason mason at suse.com
Mon Aug 22 12:44:39 CDT 2005


# HG changeset patch
# User mason at suse.com
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)

Index: mine/mercurial/hg.py
===================================================================
--- mine.orig/mercurial/hg.py	2005-08-22 09:55:28.000000000 -0400
+++ mine/mercurial/hg.py	2005-08-22 09:56:38.000000000 -0400
@@ -11,7 +11,7 @@ from revlog import *
 from demandload import *
 demandload(globals(), "re lock urllib urllib2 transaction time socket")
 demandload(globals(), "tempfile httprangereader bdiff urlparse")
-demandload(globals(), "bisect errno select stat")
+demandload(globals(), "bisect errno select stat weakref")
 
 class filelog(revlog):
     def __init__(self, opener, path):
@@ -619,6 +619,8 @@ def opener(base):
 class RepoError(Exception): pass
 
 class localrepository:
+    def __del__(self):
+        self.transhandle = None
     def __init__(self, ui, path=None, create=0):
         self.remote = 0
         if path and path.startswith("http://"):
@@ -650,6 +652,7 @@ class localrepository:
         self.changelog = changelog(self.opener)
         self.tagscache = None
         self.nodetagscache = None
+        self.transhandle = None
 
         if not self.remote:
             self.dirstate = dirstate(self.opener, ui, self.root)
@@ -772,6 +775,11 @@ class localrepository:
         return self.wopener(f, mode)
 
     def transaction(self):
+        if self.transhandle:
+            tr = self.transhandle()
+            if tr != None and tr.running():
+                return tr.nest()
+
         # save dirstate for undo
         try:
             ds = self.opener("dirstate").read()
@@ -780,12 +788,16 @@ class localrepository:
         self.opener("journal.dirstate", "w").write(ds)
 
         def after():
+            self.transhandle = None
             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,
+        tr = transaction.transaction(self.ui.warn, self.opener,
                                        self.join("journal"), after)
+        # a weak reference is used to avoid a circular ref
+        self.transhandle = weakref.ref(tr)
+        return tr
 
     def recover(self):
         lock = self.lock()
Index: mine/mercurial/transaction.py
===================================================================
--- mine.orig/mercurial/transaction.py	2005-08-02 21:42:03.000000000 -0400
+++ mine/mercurial/transaction.py	2005-08-22 09:55:30.000000000 -0400
@@ -22,6 +22,7 @@ class transaction:
         if os.path.exists(journal):
             raise "journal already exists - run hg recover"
 
+        self.count = 1
         self.report = report
         self.opener = opener
         self.after = after
@@ -46,7 +47,17 @@ class transaction:
         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:

--


More information about the Mercurial mailing list