view mercurial/dirstateguard.py @ 39491:4ca7a67c94c8

sparse-revlog: add a test checking revlog deltas for a churning file The test repository contains 5000 revisions and is therefore slow to build: five minutes with CHG, over fifteen minutes without. It is too slow to build during the test. Bundling all content produce a sizeable result, 20BM, too large to be committed. Instead, we commit a script to build the expected bundle and the test checks if the bundle is available. Any run of the script will produce the same repository content, using resulting in the same hashes. Using smaller repositories was tried, however, it misses most of the cases we are planning to improve. Having them in a 5000 repository is already nice, we usually see these case in repositories in the order of magnitude of one million revisions. This test will be very useful to check various changes strategy for building delta to store in a sparse-revlog. In this series we will focus our attention on the following metrics: The ones that will impact the final storage performance (size, space): * size of the revlog data file (".hg/store/data/*.d") * chain length info The ones that describe the deltas patterns: * number of snapshot revision (and their level) * size taken by snapshot revision (and their level)
author Boris Feld <boris.feld@octobus.net>
date Mon, 10 Sep 2018 09:08:24 -0700
parents ad24b581e4d9
children b74481038438
line wrap: on
line source

# dirstateguard.py - class to allow restoring dirstate after failure
#
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

from __future__ import absolute_import

from .i18n import _

from . import (
    error,
    narrowspec,
    util,
)

class dirstateguard(util.transactional):
    '''Restore dirstate at unexpected failure.

    At the construction, this class does:

    - write current ``repo.dirstate`` out, and
    - save ``.hg/dirstate`` into the backup file

    This restores ``.hg/dirstate`` from backup file, if ``release()``
    is invoked before ``close()``.

    This just removes the backup file at ``close()`` before ``release()``.
    '''

    def __init__(self, repo, name):
        self._repo = repo
        self._active = False
        self._closed = False
        self._backupname = 'dirstate.backup.%s.%d' % (name, id(self))
        self._narrowspecbackupname = ('narrowspec.backup.%s.%d' %
                                      (name, id(self)))
        repo.dirstate.savebackup(repo.currenttransaction(), self._backupname)
        narrowspec.savebackup(repo, self._narrowspecbackupname)
        self._active = True

    def __del__(self):
        if self._active: # still active
            # this may occur, even if this class is used correctly:
            # for example, releasing other resources like transaction
            # may raise exception before ``dirstateguard.release`` in
            # ``release(tr, ....)``.
            self._abort()

    def close(self):
        if not self._active: # already inactivated
            msg = (_("can't close already inactivated backup: %s")
                   % self._backupname)
            raise error.Abort(msg)

        self._repo.dirstate.clearbackup(self._repo.currenttransaction(),
                                         self._backupname)
        narrowspec.clearbackup(self._repo, self._narrowspecbackupname)
        self._active = False
        self._closed = True

    def _abort(self):
        narrowspec.restorebackup(self._repo, self._narrowspecbackupname)
        self._repo.dirstate.restorebackup(self._repo.currenttransaction(),
                                           self._backupname)
        self._active = False

    def release(self):
        if not self._closed:
            if not self._active: # already inactivated
                msg = (_("can't release already inactivated backup: %s")
                       % self._backupname)
                raise error.Abort(msg)
            self._abort()