~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/dirstate.py

  • Committer: James Westby
  • Date: 2007-02-22 22:45:49 UTC
  • mto: (2255.5.1 dirstate)
  • mto: This revision was merged to the branch mainline in revision 2322.
  • Revision ID: jw+debian@jameswestby.net-20070222224549-16u0yxrdrqg3vgpg
(broken) Add the locking methods.

  * Callers should now use lock_read and lock_write before they do
    anything with dirstate.
  * You can only grab a single lock on the object, and can't unlock it
    if not locked.
  * initialize now returns a writelocked object to the caller.
  * This breaks the tests massively, sorry, as they need to do locking now.
    - Currently the main problem is the dirstate never being flushed to disk,
      so all tests trip the assertion that the header is incorrect.

Show diffs side-by-side

added added

removed removed

Lines of Context:
201
201
 
202
202
from bzrlib import (
203
203
    errors,
 
204
    lock,
204
205
    trace,
205
206
    )
206
207
import bzrlib.inventory
272
273
        self._dirblocks = []
273
274
        self._ghosts = []
274
275
        self._parents = []
275
 
        self._state_file=None
276
 
        self._filename=path
 
276
        self._state_file = None
 
277
        self._filename = path
 
278
        self._lock_token = None
277
279
 
278
280
    def add(self, path, file_id, kind, stat, link_or_sha1):
279
281
        """Add a path to be tracked.
743
745
        The new dirstate will be an empty tree - that is it has no parents,
744
746
        and only a root node - which has id ROOT_ID.
745
747
 
 
748
        The object will be write locked when returned to the caller,
 
749
        unless there was an exception in the writing, in which case it
 
750
        will be unlocked.
 
751
 
746
752
        :param path: The name of the file for the dirstate.
747
753
        :return: A DirState object.
748
754
        """
752
758
        # and no parents. Finally it calls save() to ensure that this data will
753
759
        # persist.
754
760
        result = DirState(path)
755
 
        result._state_file = open(result._filename, 'wb+')
756
761
        # root dir and root dir contents with no children.
757
762
        empty_tree_dirblocks = [('', []), ('', [])]
758
763
        # a new root directory, with a NULLSTAT.
760
765
            (('', '', bzrlib.inventory.ROOT_ID), [
761
766
                ('d', '', 0, False, DirState.NULLSTAT),
762
767
            ]))
763
 
        result._set_data([], empty_tree_dirblocks)
 
768
        result.lock_write()
764
769
        try:
 
770
            result._set_data([], empty_tree_dirblocks)
765
771
            result.save()
766
772
        except:
767
 
            result._state_file.close()
 
773
            result.unlock()
768
774
            raise
769
775
        return result
770
776
 
843
849
    def on_file(path):
844
850
        """Construct a DirState on the file at path path."""
845
851
        result = DirState(path)
846
 
        result._state_file = open(result._filename, 'rb+')
847
852
        return result
848
853
 
849
854
    def _read_dirblocks_if_needed(self):
971
976
 
972
977
    def _read_header_if_needed(self):
973
978
        """Read the header of the dirstate file if needed."""
 
979
        # inline this as it will be called a lot
 
980
        if not self._lock_token:
 
981
            raise errors.ObjectNotLocked(self)
974
982
        if self._header_state == DirState.NOT_IN_MEMORY:
975
983
            self._read_header()
976
984
 
1428
1436
        self._dirblock_state = DirState.IN_MEMORY_MODIFIED
1429
1437
 
1430
1438
 
 
1439
    def _wipe_state(self):
 
1440
        """Forget all state information about the dirstate."""
 
1441
        self._header_state = DirState.NOT_IN_MEMORY
 
1442
        self._dirblock_state = DirState.NOT_IN_MEMORY
 
1443
        self._parents = []
 
1444
        self._ghosts = []
 
1445
        self._dirblocks = []
 
1446
 
 
1447
    def lock_read(self):
 
1448
        """Acquire a read lock on the dirstate"""
 
1449
        if self._lock_token is not None:
 
1450
            raise errors.LockContention(self._lock_token)
 
1451
        self._lock_token = lock.ReadLock(self._filename)
 
1452
        self._state_file = open(self._filename, 'rb')
 
1453
        self._wipe_state()
 
1454
        
 
1455
    def lock_write(self):
 
1456
        """Acquire a write lock on the dirstate"""
 
1457
        if self._lock_token is not None:
 
1458
            raise errors.LockContention(self._lock_token)
 
1459
        self._lock_token = lock.WriteLock(self._filename)
 
1460
        self._state_file = open(self._filename, 'rb+')
 
1461
        self._wipe_state()
 
1462
 
 
1463
    def unlock(self):
 
1464
        """Drop any locks held on the dirstate"""
 
1465
        if self._lock_token is None:
 
1466
            raise errors.LockNotHeld(self)
 
1467
        self._state_file.close()
 
1468
        self._lock_token.unlock()
 
1469
        self._lock_token = None
 
1470
 
 
1471
    def _requires_lock(self):
 
1472
        """Checks that a lock is currently held by someone on the dirstate"""
 
1473
        if not self._lock_token:
 
1474
            raise errors.ObjectNotLocked(self)
1431
1475
 
1432
1476
def pack_stat(st, _encode=base64.encodestring, _pack=struct.pack):
1433
1477
    """Convert stat values into a packed representation."""