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
This commit is contained in:
FUJIWARA Katsunori 2015-05-25 01:26:19 +09:00
parent 3ca8d79bef
commit e07aa6e441

View File

@ -16,7 +16,7 @@ import match as matchmod
import merge as mergemod
import tags as tagsmod
from lock import release
import weakref, errno, os, time, inspect
import weakref, errno, os, time, inspect, random
import branchmap, pathutil
import namespaces
propertycache = util.propertycache
@ -960,6 +960,8 @@ class localrepository(object):
_("abandoned transaction found"),
hint=_("run 'hg recover' to clean up transaction"))
idbase = "%.40f#%f" % (random.random(), time.time())
txnid = 'TXN:' + util.sha1(idbase).hexdigest()
self.hook('pretxnopen', throw=True, txnname=desc)
self._writejournal(desc)
@ -984,8 +986,7 @@ class localrepository(object):
self.store.createmode,
validator=validate)
trid = 'TXN:' + util.sha1("%s#%f" % (id(tr), time.time())).hexdigest()
tr.hookargs['txnid'] = trid
tr.hookargs['txnid'] = txnid
# note: writing the fncache only during finalize mean that the file is
# outdated when running hooks. As fncache is used for streaming clone,
# this is not expected to break anything that happen during the hooks.