Mercurial > hg
comparison mercurial/localrepo.py @ 25267:69c5cab0b893 stable
transaction: separate calculating TXNID from creating transaction object
Before this patch, transaction ID (TXNID) is calculated from
`transaction` object itself by `id()`, but this prevents TXNID from
being passed to `pretxnopen` hooks, which should be executed before
starting transaction processing (also any preparations for it, like
writing journal files out).
As a preparation for passing TXNID to `pretxnopen` hooks, this patch
separates calculation of TXNID from creation of `transaction` object.
This patch uses "random" library for reasonable unique ID. "uuid"
library can't be used, because it was introduced since Python 2.5 and
isn't suitable for Mercurial 3.4.x stable line.
`%f` formatting for `random.random()` is used with explicit precision
number 40, because default precision for `%f` is 6. 40 should be long
enough, even if 10**9 transactions are executed in a short time (a
second or less).
On the other hand, `time.time()` is used to ensures uniqueness of
TXNID in a long time, for safety.
BTW, platform not providing `/dev/urandom` or so may cause failure of
`import random` itself with some Python versions (see Python
issue15340 for detail http://bugs.python.org/issue15340).
But this patch uses "random" without any workaround, because:
- "random" is already used directly in some code paths,
- such platforms are very rare (e.g. Tru64 and HPUX), and
http://bugs.python.org/issue15340#msg170000
- updating Python runtime can avoid this issue
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Mon, 25 May 2015 01:26:19 +0900 |
parents | 2664f536a97e |
children | a973b050621d |
comparison
equal
deleted
inserted
replaced
25266:38117278f295 | 25267:69c5cab0b893 |
---|---|
14 import scmutil, util, extensions, hook, error, revset | 14 import scmutil, util, extensions, hook, error, revset |
15 import match as matchmod | 15 import match as matchmod |
16 import merge as mergemod | 16 import merge as mergemod |
17 import tags as tagsmod | 17 import tags as tagsmod |
18 from lock import release | 18 from lock import release |
19 import weakref, errno, os, time, inspect | 19 import weakref, errno, os, time, inspect, random |
20 import branchmap, pathutil | 20 import branchmap, pathutil |
21 import namespaces | 21 import namespaces |
22 propertycache = util.propertycache | 22 propertycache = util.propertycache |
23 filecache = scmutil.filecache | 23 filecache = scmutil.filecache |
24 | 24 |
958 if self.svfs.exists("journal"): | 958 if self.svfs.exists("journal"): |
959 raise error.RepoError( | 959 raise error.RepoError( |
960 _("abandoned transaction found"), | 960 _("abandoned transaction found"), |
961 hint=_("run 'hg recover' to clean up transaction")) | 961 hint=_("run 'hg recover' to clean up transaction")) |
962 | 962 |
963 idbase = "%.40f#%f" % (random.random(), time.time()) | |
964 txnid = 'TXN:' + util.sha1(idbase).hexdigest() | |
963 self.hook('pretxnopen', throw=True, txnname=desc) | 965 self.hook('pretxnopen', throw=True, txnname=desc) |
964 | 966 |
965 self._writejournal(desc) | 967 self._writejournal(desc) |
966 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()] | 968 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()] |
967 if report: | 969 if report: |
982 "undo", | 984 "undo", |
983 aftertrans(renames), | 985 aftertrans(renames), |
984 self.store.createmode, | 986 self.store.createmode, |
985 validator=validate) | 987 validator=validate) |
986 | 988 |
987 trid = 'TXN:' + util.sha1("%s#%f" % (id(tr), time.time())).hexdigest() | 989 tr.hookargs['txnid'] = txnid |
988 tr.hookargs['txnid'] = trid | |
989 # note: writing the fncache only during finalize mean that the file is | 990 # note: writing the fncache only during finalize mean that the file is |
990 # outdated when running hooks. As fncache is used for streaming clone, | 991 # outdated when running hooks. As fncache is used for streaming clone, |
991 # this is not expected to break anything that happen during the hooks. | 992 # this is not expected to break anything that happen during the hooks. |
992 tr.addfinalize('flush-fncache', self.store.write) | 993 tr.addfinalize('flush-fncache', self.store.write) |
993 def txnclosehook(tr2): | 994 def txnclosehook(tr2): |