sapling/mercurial
FUJIWARA Katsunori f850c84e84 localrepo: discard objects in _filecache at transaction failure (issue4876)
'repo.invalidate()' deletes 'filecache'-ed properties by
'filecache.__delete__()' below via 'delattr(unfiltered, k)'. But
cached objects are still kept in 'repo._filecache'.

    def __delete__(self, obj):
        try:
            del obj.__dict__[self.name]
        except KeyError:
            raise AttributeError(self.name)

If 'repo' object is reused even after failure of command execution,
referring 'filecache'-ed property may reuse one kept in
'repo._filecache', even if reloading from a file is expected.

Executing command sequence on command server is a typical case of this
situation (e0a0f9ad3e4c also tried to fix this issue). For example:

  1. start a command execution

  2. 'changelog.delayupdate()' is invoked in a transaction scope

     This replaces own 'opener' by '_divertopener()' for additional
     accessing to '00changelog.i.a' (aka "pending file").

  3. transaction is aborted, and command (1) execution is ended

     After 'repo.invalidate()' at releasing store lock, changelog
     object above (= 'opener' of it is still replaced) is deleted from
     'repo.__dict__', but still kept in 'repo._filecache'.

  4. start next command execution with same 'repo'

  5. referring 'repo.changelog' may reuse changelog object kept in
     'repo._filecache' according to timestamp of '00changelog.i'

     '00changelog.i' is truncated at transaction failure (even though
     this truncation is unintentional one, as described later), and
     'st_mtime' of it is changed. But 'st_mtime' doesn't have enough
     resolution to always detect this truncation, and invalid
     changelog object kept in 'repo._filecache' is reused
     occasionally.

     Then, "No such file or directory" error occurs for
     '00changelog.i.a', which is already removed at (3).

This patch discards objects in '_filecache' other than dirstate at
transaction failure.

Changes in 'invalidate()' can't be simplified by 'self._filecache =
{}', because 'invalidate()' should keep dirstate in 'self._filecache'

'repo.invalidate()' at "hg qpush" failure is removed in this patch,
because now it is redundant.

This patch doesn't make 'repo.invalidate()' always discard objects in
'_filecache', because 'repo.invalidate()' is invoked also at unlocking
store lock.

  - "always discard objects in filecache at unlocking" may cause
    serious performance problem for subsequent procedures at normal
    execution

  - but it is impossible to "discard objects in filecache at unlocking
    only at failure", because 'releasefn' of lock can't know whether a
    lock scope is terminated normally or not

    BTW, using "with" statement described in PEP343 for lock may
    resolve this ?

After this patch, truncation of '00changelog.i' still occurs at
transaction failure, even though newly added revisions exist only in
'00changelog.i.a' and size of '00changelog.i' isn't changed by this
truncation.

Updating 'st_mtime' of '00changelog.i' implied by this redundant
truncation also affects cache behavior as described above.

This will be fixed by dropping '00changelog.i' at aborting from the
list of files to be truncated in transaction.
2015-10-24 18:58:57 +09:00
..
default.d mergetools.rc: find OSX FileMerge in the new location inside Xcode 4.3 2015-10-16 11:37:34 +02:00
help help: mention alias and revsetalias in description of HGPLAINEXCEPT 2015-10-24 06:59:26 +01:00
hgweb spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
httpclient global: mass rewrite to use modern exception syntax 2015-06-23 22:20:08 -07:00
pure osutil: remove Python 2.4 errno conversion workaround 2015-06-22 10:11:31 -07:00
templates gitweb: visually highlight source lines when hovering over line numbers 2015-10-15 00:04:58 +08:00
__init__.py
ancestor.py ancestor: use absolute_import 2015-08-07 19:45:48 -07:00
archival.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
base85.c base85: fix comparison of an int and a long 2015-08-21 14:29:42 -04:00
bdiff.c bdiff: avoid a memory error on malloc failure 2013-10-30 16:03:42 -05:00
bookmarks.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
branchmap.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
bundle2.py bundle2: attribute remote failures to remote (issue4788) 2015-10-24 00:39:22 +01:00
bundlerepo.py bundlerepo: properly extract compressed changegroup from bundle2 2015-10-19 16:01:55 +02:00
byterange.py global: mass rewrite to use modern exception syntax 2015-06-23 22:20:08 -07:00
changegroup.py hook: centralize passing HG_PENDING to external hook process 2015-10-17 01:15:34 +09:00
changelog.py reachableroots: construct and sort baseset in revset module 2015-08-28 11:14:24 +09:00
cmdutil.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
commands.py debugrevlog: cope with empty revlog files 2015-10-23 11:04:53 -04:00
commandserver.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
config.py config: use absolute_import 2015-08-08 00:28:53 -07:00
context.py dirstate: make dirstate.write() callers pass transaction object to it 2015-10-17 01:15:34 +09:00
copies.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
crecord.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
dagparser.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
dagutil.py dagutil: use absolute_import 2015-08-08 19:04:09 -07:00
demandimport.py demandimport: fix TypeError when importing Python regex library (issue4920) 2015-10-28 16:27:09 +01:00
destutil.py destmerge: extract logic based on branch heads in its own function 2015-10-15 03:15:54 +01:00
diffhelpers.c diffhelpers: fix botched return statement from e48d70075d8a 2015-01-28 13:34:20 -05:00
dirs.c dirs._addpath: reinstate use of Py_CLEAR 2015-04-07 20:43:04 -07:00
dirstate.py dirstate: fix invalid reference to self.ui 2015-10-19 12:07:17 -07:00
discovery.py bookmarks: don't allow pushing new head for existing mark with -B (issue4400) 2015-10-21 16:21:27 -05:00
dispatch.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
dummycert.pem ssl: on OS X, use a dummy cert to trick Python/OpenSSL to use system CA certs 2014-09-26 02:19:48 +02:00
encoding.py global: mass rewrite to use modern exception syntax 2015-06-23 22:20:08 -07:00
error.py error: remove superfluous pass statements 2015-10-15 09:52:32 -04:00
exchange.py bundle2: attribute remote failures to remote (issue4788) 2015-10-24 00:39:22 +01:00
exewrapper.c exewrapper: add comments about PYTHONHOME 2015-10-14 12:23:49 +02:00
extensions.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
fancyopts.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
filelog.py filelog: use absolute_import 2015-08-08 19:11:42 -07:00
filemerge.py merge-tools: allow marking a mergetool as completely disabled 2015-10-14 12:57:33 -04:00
fileset.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
formatter.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
graphmod.py graphmod: compute slow revset query once prior to reachableroots (issue4782) 2015-09-08 23:00:44 +09:00
hbisect.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
help.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
hg.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
hook.py hook: centralize passing HG_PENDING to external hook process 2015-10-17 01:15:34 +09:00
httpconnection.py httpconnection: remove a mutable default argument 2015-09-24 00:54:30 -07:00
httppeer.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
i18n.py i18n: use absolute_import 2015-08-08 19:28:49 -07:00
keepalive.py global: mass rewrite to use modern exception syntax 2015-06-23 22:20:08 -07:00
localrepo.py localrepo: discard objects in _filecache at transaction failure (issue4876) 2015-10-24 18:58:57 +09:00
lock.py lock: add a way to prevent locks from being inherited 2015-10-06 13:13:31 -07:00
lsprof.py profiling: replace '+' markup of nested lines with indentation 2013-02-08 22:54:48 +01:00
lsprofcalltree.py
mail.py mail: drop python 2.5 self.sock.read workaround 2015-10-15 17:24:42 -04:00
manifest.c lazymanifest: prevent leak when updating an entry more than once 2015-04-11 11:56:21 -04:00
manifest.py treemanifest: rework lazy-copying code (issue4840) 2015-09-25 22:54:46 -04:00
match.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
mdiff.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
merge.py merge: improve clarity of table in update docstring 2015-10-23 06:06:22 -04:00
minirst.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
mpatch.c mpatch: rewrite pointer overflow checks 2013-12-11 18:33:42 -06:00
namespaces.py namespaces: use absolute_import 2015-08-08 19:42:58 -07:00
node.py node: use absolute_import 2015-08-08 19:43:24 -07:00
obsolete.py obsstore: make the readonly attribute accessible 2015-10-15 12:45:34 +01:00
osutil.c osutil: mark end of string with null char, not 0 2015-03-25 16:21:58 -07:00
parser.py parser: move unescape helper from templater 2015-09-10 23:25:10 +09:00
parsers.c parsers: suppress warning of signed and unsigned comparison at nt_init 2015-10-18 09:05:04 +09:00
patch.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
pathencode.c pathencode: check result of .digest() method in sha1hash 2015-08-18 16:32:41 -04:00
pathutil.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
peer.py peer: use absolute_import 2015-08-08 19:45:45 -07:00
phases.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
posix.py posix: shellquote do not require quoting for "+" (issue4818) 2015-09-04 11:15:02 -04:00
progress.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
pushkey.py pushkey: use absolute_import 2015-08-08 19:57:27 -07:00
pvec.py pvec: replace 'ctx._repo' with 'ctx.repo()' 2015-03-12 23:18:20 -04:00
py3kcompat.py py3kcompat: drop unused export 2014-05-13 15:22:36 -05:00
repair.py strip: pass source and url to bundle2 processing 2015-10-20 16:01:33 +02:00
repoview.py repoview: use absolute_import 2015-08-08 19:58:05 -07:00
revlog.py revlog: rename bundle to cg to reflect its nature as a cg?unpacker 2015-10-14 11:32:33 -04:00
revset.py l10n: use %d instead of %s for numbers 2015-10-14 22:29:03 -04:00
scmposix.py config: don't read the same config file twice 2014-09-04 21:36:35 +02:00
scmutil.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
scmwindows.py windows: read all global config files, not just the first (issue4491) (BC) 2015-10-12 20:13:12 +02:00
setdiscovery.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
similar.py cleanup: eradicate long lines 2012-05-12 15:54:54 +02:00
simplemerge.py simplemerge: move conflict warning message to filemerge 2015-10-09 13:54:52 -07:00
sshpeer.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
sshserver.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
sslutil.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
statichttprepo.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
store.py l10n: use %d instead of %s for numbers 2015-10-14 22:29:03 -04:00
streamclone.py streamclone: support for producing and consuming stream clone bundles 2015-10-17 11:14:52 -07:00
strutil.py strutil: use absolute_import 2015-08-08 20:01:40 -07:00
subrepo.py spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
tagmerge.py tagmerge: use absolute_import 2015-08-08 20:10:46 -07:00
tags.py tags: use absolute_import 2015-08-08 20:16:56 -07:00
templatefilters.py templater: port localdate filter to a function 2015-09-01 19:15:16 +09:00
templatekw.py templatekw: add {changes}, {distance} and {tag} to the {latesttag} keyword 2015-08-24 23:30:17 -04:00
templater.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
transaction.py spelling: fix typo in transaction error messages 2015-10-17 15:28:02 -05:00
treediscovery.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
ui.py ui: support paths.default-push without paths.default set (issue4914) 2015-10-22 18:59:03 +00:00
unionrepo.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
url.py url: drop support for python2.5 2015-10-15 17:21:08 -04:00
util.h util: fix the check for non-C99 compilers (issue4605) 2015-04-20 22:21:57 -05:00
util.py util: also catch IndexError 2015-10-13 16:05:30 -07:00
verify.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00
win32.py win32: use absolute_import 2015-08-08 18:52:59 -07:00
windows.py windows: insert file positioning call between reads and writes 2015-09-27 18:46:53 -07:00
wireproto.py exchange: advertise if a clone bundle was attempted 2015-10-14 10:36:20 -07:00
worker.py error: get Abort from 'error' instead of 'util' 2015-10-08 12:55:45 -07:00