Revision 3dbe3ddf lib/locking.py

b/lib/locking.py
727 727
    finally:
728 728
      self.__lock.release()
729 729

  
730
  def downgrade(self):
731
    """Changes the lock mode from exclusive to shared.
732

  
733
    Pending acquires in shared mode on the same priority will go ahead.
734

  
735
    """
736
    self.__lock.acquire()
737
    try:
738
      assert self.__is_owned(), "Lock must be owned"
739

  
740
      if self.__is_exclusive():
741
        # Do nothing if the lock is already acquired in shared mode
742
        self.__exc = None
743
        self.__do_acquire(1)
744

  
745
        # Important: pending shared acquires should only jump ahead if there
746
        # was a transition from exclusive to shared, otherwise an owner of a
747
        # shared lock can keep calling this function to push incoming shared
748
        # acquires
749
        (priority, prioqueue) = self.__find_first_pending_queue()
750
        if prioqueue:
751
          # Is there a pending shared acquire on this priority?
752
          cond = self.__pending_shared.pop(priority, None)
753
          if cond:
754
            assert cond.shared
755
            assert cond in prioqueue
756

  
757
            # Ensure shared acquire is on top of queue
758
            if len(prioqueue) > 1:
759
              prioqueue.remove(cond)
760
              prioqueue.insert(0, cond)
761

  
762
            # Notify
763
            cond.notifyAll()
764

  
765
      assert not self.__is_exclusive()
766
      assert self.__is_sharer()
767

  
768
      return True
769
    finally:
770
      self.__lock.release()
771

  
730 772
  def release(self):
731 773
    """Release a Shared Lock.
732 774

  
......
881 923
    """
882 924
    return "%s/%s" % (self.name, mname)
883 925

  
926
  def _get_lock(self):
927
    """Returns the lockset-internal lock.
928

  
929
    """
930
    return self.__lock
931

  
932
  def _get_lockdict(self):
933
    """Returns the lockset-internal lock dictionary.
934

  
935
    Accessing this structure is only safe in single-thread usage or when the
936
    lockset-internal lock is held.
937

  
938
    """
939
    return self.__lockdict
940

  
884 941
  def _is_owned(self):
885 942
    """Is the current thread a current level owner?"""
886 943
    return threading.currentThread() in self.__owners
......
1122 1179

  
1123 1180
    return acquired
1124 1181

  
1182
  def downgrade(self, names=None):
1183
    """Downgrade a set of resource locks from exclusive to shared mode.
1184

  
1185
    The locks must have been acquired in exclusive mode.
1186

  
1187
    """
1188
    assert self._is_owned(), ("downgrade on lockset %s while not owning any"
1189
                              " lock" % self.name)
1190

  
1191
    # Support passing in a single resource to downgrade rather than many
1192
    if isinstance(names, basestring):
1193
      names = [names]
1194

  
1195
    owned = self._list_owned()
1196

  
1197
    if names is None:
1198
      names = owned
1199
    else:
1200
      names = set(names)
1201
      assert owned.issuperset(names), \
1202
        ("downgrade() on unheld resources %s (set %s)" %
1203
         (names.difference(owned), self.name))
1204

  
1205
    for lockname in names:
1206
      self.__lockdict[lockname].downgrade()
1207

  
1208
    # Do we own the lockset in exclusive mode?
1209
    if self.__lock._is_owned(shared=0):
1210
      # Have all locks been downgraded?
1211
      if not compat.any(lock._is_owned(shared=0)
1212
                        for lock in self.__lockdict.values()):
1213
        self.__lock.downgrade()
1214
        assert self.__lock._is_owned(shared=1)
1215

  
1216
    return True
1217

  
1125 1218
  def release(self, names=None):
1126 1219
    """Release a set of resource locks, at the same level.
1127 1220

  
......
1458 1551
    return self.__keyring[level].acquire(names, shared=shared, timeout=timeout,
1459 1552
                                         priority=priority)
1460 1553

  
1554
  def downgrade(self, level, names=None):
1555
    """Downgrade a set of resource locks from exclusive to shared mode.
1556

  
1557
    You must have acquired the locks in exclusive mode.
1558

  
1559
    @type level: member of locking.LEVELS
1560
    @param level: the level at which the locks shall be downgraded
1561
    @type names: list of strings, or None
1562
    @param names: the names of the locks which shall be downgraded
1563
        (defaults to all the locks acquired at the level)
1564

  
1565
    """
1566
    assert level in LEVELS, "Invalid locking level %s" % level
1567

  
1568
    return self.__keyring[level].downgrade(names=names)
1569

  
1461 1570
  def release(self, level, names=None):
1462 1571
    """Release a set of resource locks, at the same level.
1463 1572

  

Also available in: Unified diff