/// <summary>
    /// Inits the guard with the action to be performed once
    /// disposal takes place.
    /// </summary>
    /// <param name="item">Encapsulates the locking information.</param>
    /// <param name="repository">The repository that issued the lock.</param>
    /// <exception cref="ArgumentNullException">If any of the parameters
    /// is a null reference.</exception>
    public ResourceLockGuard(LockItem item, IResourceLockRepository repository)
    {
      Ensure.ArgumentNotNull(item, "item");
      Ensure.ArgumentNotNull(repository, "repository");

      Item = item;
      Repository = repository;
    }
        /// <summary>
        /// Inits the guard with the action to be performed once
        /// disposal takes place.
        /// </summary>
        /// <param name="item">Encapsulates the locking information.</param>
        /// <param name="repository">The repository that issued the lock.</param>
        /// <exception cref="ArgumentNullException">If any of the parameters
        /// is a null reference.</exception>
        public ResourceLockGuard(LockItem item, IResourceLockRepository repository)
        {
            Ensure.ArgumentNotNull(item, "item");
            Ensure.ArgumentNotNull(repository, "repository");

            Item       = item;
            Repository = repository;
        }
Beispiel #3
0
        /// <summary>
        /// Tries to acquire an exclusive write
        /// for the resource, and specifies a timeout for the lock. If this operation
        /// succeeds, the lock must be released as soon
        /// as possible through the <see cref="ReleaseWriteLock"/>
        /// method.
        /// </summary>
        /// <param name="timeout">The timeout of the lock.
        /// A value of null requests a lock that doesn't time out.</param>
        /// <returns>A lock that corresponds to the request. If the lock was denied, the
        /// returned item's <see cref="LockItem.LockType"/>
        /// is <see cref="ResourceLockType.Denied"/>.</returns>
        /// <exception cref="ArgumentOutOfRangeException">In case of a negative
        /// timeout.</exception>
        public LockItem TryGetWriteLock(TimeSpan?timeout)
        {
            lock (this)
            {
                if (HasWriteLock || HasReadLocks)
                {
                    return(LockItem.CreateDenied(ResourceId));
                }

                activeWriteLock = LockItem.CreateWrite(ResourceId, timeout);
                return(activeWriteLock);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Releases a previously acquired write lock.
        /// </summary>
        /// <param name="lockId">The <see cref="LockItem.LockId"/>
        /// which identifies the lock to be released.</param>
        /// <returns>True if a matching lock was found and released.
        /// If no lock was found, false.</returns>
        public bool ReleaseWriteLock(string lockId)
        {
            lock (this)
            {
                if (activeWriteLock != null && activeWriteLock.LockId == lockId)
                {
                    //don't check whether lock has expired - invoking party is happy
                    activeWriteLock = null;
                    return(true);
                }

                return(false);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Removes expired locks.
        /// </summary>
        private void Cleanup()
        {
            cleanUpCounter++;
            if (cleanUpCounter % 100 == 0)
            {
                //TODO audit/log expired locks?
                readLocks.RemoveAll(li => li.Expiration.IsExpired());

                if (activeWriteLock != null && activeWriteLock.Expiration.IsExpired())
                {
                    activeWriteLock = null;
                }

                cleanUpCounter = 1;
            }
        }
Beispiel #6
0
        /// <summary>
        /// Releases a previously acquired lock for a given
        /// resource.
        /// </summary>
        /// <param name="item">The lock to be released.</param>
        /// <returns>True if the lock was released. False in case
        /// of an unknown (e.g. automatically removed) lock, or if
        /// the lock is ignored because it's <see cref="LockItem.LockType"/>
        /// is <see cref="ResourceLockType.Denied"/>.</returns>
        public bool ReleaseLock(LockItem item)
        {
            switch (item.LockType)
            {
            case ResourceLockType.Read:
                return(ReleaseReadLock(item.ResourceId, item.LockId));

            case ResourceLockType.Write:
                return(ReleaseWriteLock(item.ResourceId, item.LockId));

            case ResourceLockType.Denied:
                return(false);

            default:
                throw new ArgumentOutOfRangeException("Unsupported lock type: " + item.LockType);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Tries to acquire a shared read lock
        /// for the resource, and specifies a timeout for the lock. If this operation
        /// succeeds, the lock must be released as soon
        /// as possible through the <see cref="ReleaseReadLock"/>
        /// method.
        /// </summary>
        /// <returns>A lock that corresponds to the request. If the lock was denied, the
        /// returned item's <see cref="LockItem.LockType"/>
        /// is <see cref="ResourceLockType.Denied"/>.</returns>
        /// <param name="timeout">The timeout of the lock.
        /// A null value requests a lock that doesn't time out.</param>
        /// <returns>True if the lock was granted.</returns>
        /// <exception cref="ArgumentOutOfRangeException">In case of a negative
        /// timeout.</exception>
        public LockItem TryGetReadLock(TimeSpan?timeout)
        {
            lock (this)
            {
                if (HasWriteLock)
                {
                    return(LockItem.CreateDenied(ResourceId));
                }

                //clean up inactive locks from time to time
                Cleanup();

                var item = LockItem.CreateRead(ResourceId, timeout);
                readLocks.Add(item);
                return(item);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Releases a previously acquired read lock.
        /// </summary>
        /// <param name="lockId">The <see cref="LockItem.LockId"/>
        /// which identifies the lock to be released.</param>
        /// <returns>True if a matching lock was found and released.
        /// If no lock was found, false.</returns>
        public bool ReleaseReadLock(string lockId)
        {
            lock (this)
            {
                for (int i = 0; i < readLocks.Count; i++)
                {
                    LockItem lockItem = readLocks[i];
                    if (lockItem.LockId == lockId)
                    {
                        readLocks.RemoveAt(i);

                        //don't check whether lock has expired - invoking party is happy
                        return(true);
                    }
                }

                return(false);
            }
        }
        /// <summary>
        /// Gets a read lock on all parent folders of a given resource, and rolls back the resources
        /// if the locking fails.
        /// </summary>
        /// <param name="repository">The repository that manages locked resources.</param>
        /// <param name="resourceId">The resource to be locked.</param>
        /// <param name="isWriteLock">Whether to acquire a read or write lock for the resource itself.</param>
        /// <param name="parentFolderIds">Ids of the resource's parent folders, which are being locked one
        /// by one. The list should be ordered, with the first item being the immediate parent of the locked
        /// resource, and the last one the topmost folder to be locked.</param>
        /// <returns>A guard which releases the resource and all folders once it is being disposed.</returns>
        public static ResourceLockGuard GetResourceChainLock(this IResourceLockRepository repository, string resourceId,
                                                             bool isWriteLock, List <string> parentFolderIds)
        {
            LockItem lockItem = isWriteLock ? repository.TryGetWriteLock(resourceId) : repository.TryGetReadLock(resourceId);

            //we couldn't get a lock on the resource itself
            if (!lockItem.IsEnabled)
            {
                return(new ResourceLockGuard(lockItem, repository));
            }

            //get read locks for all parent folders
            List <LockItem> folderLocks = new List <LockItem>();
            LockItem        folderLock  = null;

            foreach (string folderId in parentFolderIds)
            {
                //lock parent folders, one by one for read access (prevents deletion)
                folderLock = repository.TryGetReadLock(folderId);
                if (!folderLock.IsEnabled)
                {
                    break;
                }
                folderLocks.Add(folderLock);
            }

            if (folderLock != null && !folderLock.IsEnabled)
            {
                //roll back all locks...
                repository.ReleaseLock(lockItem);
                folderLocks.ForEach(li => repository.ReleaseLock(li));
                //...and return a dummy lock
                return(new ResourceLockGuard(LockItem.CreateDenied(resourceId), repository));
            }

            return(new ResourceLockGuard(lockItem, repository)
            {
                SecondaryLocks = folderLocks
            });
        }
 /// <summary>
 /// Gets a guard that can be used with a <c>using</c>
 /// statement, which tries to get a read lock and
 /// ensures the lock is being released as soon as
 /// the using block is being exited. Check the
 /// guard's <see cref="ResourceLockGuard.IsLockEnabled"/>
 /// property to verify whether the lock was granted
 /// or not.
 /// </summary>
 /// <returns>A guard that handles management of the
 /// acquired read lock.</returns>
 public ResourceLockGuard GetReadGuard(string resourceId)
 {
     return(new ResourceLockGuard(LockItem.CreateRead(resourceId, null), this));
 }
Beispiel #11
0
    /// <summary>
    /// Removes expired locks.
    /// </summary>
    private void Cleanup()
    {
      cleanUpCounter++;
      if (cleanUpCounter % 100 == 0)
      {
        //TODO audit/log expired locks?
        readLocks.RemoveAll(li => li.Expiration.IsExpired());
        
        if (activeWriteLock != null && activeWriteLock.Expiration.IsExpired())
        {
          activeWriteLock = null;
        }

        cleanUpCounter = 1;
      }
    }
 /// <summary>
 /// Releases a previously acquired lock for a given
 /// resource.
 /// </summary>
 /// <param name="item">The lock to be released.</param>
 /// <returns>True if the lock was released. False in case
 /// of an unknown (e.g. automatically removed) lock, or if
 /// the lock is ignored because it's <see cref="LockItem.LockType"/>
 /// is <see cref="ResourceLockType.Denied"/>.</returns>
 public bool ReleaseLock(LockItem item)
 {
   return true;
 }
 /// <summary>
 /// Tries to acquire an exclusive write lock for the resource
 /// which expires after a given while in order not to block
 /// the resource indefinitely.
 /// If this operation succeeds, the lock must be released as soon
 /// as possible through the <see cref="IResourceLockRepository.ReleaseWriteLock"/>
 /// method.
 /// </summary>
 /// <param name="resourceId">Identifies the locked resource.</param>
 /// <param name="timeout">The specified expiration timeout from now.
 /// Allowed values are null for indefinite locking, or any positive value.</param>
 /// <returns>True if the lock was granted.</returns>
 /// <exception cref="ArgumentOutOfRangeException">In case of a negative
 /// timeout.</exception>sitive value.</param>
 /// <returns>True if the lock was granted.</returns>
 public LockItem TryGetWriteLock(string resourceId, TimeSpan?timeout)
 {
     return(LockItem.CreateWrite(resourceId, timeout));
 }
 /// <summary>
 /// Tries to acquire an exclusive write lock for the resource
 /// which expires after a given time span in order not to block
 /// the resource indefinitely.
 /// If this operation succeeds, the lock must be released as soon
 /// as possible through the <see cref="IResourceLockRepository.ReleaseReadLock"/>
 /// method.
 /// </summary>
 /// <param name="resourceId">Identifies the locked resource.</param>
 /// <param name="timeout">The specified expiration timeout from now.
 /// Allowed values are null for indefinite locking, or any positive value.</param>
 /// <returns>True if the lock was granted.</returns>
 /// <exception cref="ArgumentOutOfRangeException">In case of a negative
 /// timeout.</exception>
 public LockItem TryGetReadLock(string resourceId, TimeSpan?timeout)
 {
     return(LockItem.CreateRead(resourceId, timeout));
 }
 /// <summary>
 /// Gets a guard that can be used with a <c>using</c>
 /// statement, which tries to get a write lock and
 /// ensures the lock is being released as soon as
 /// the using block is being exited. Check the
 /// guard's <see cref="ResourceLockGuard.IsLockEnabled"/>
 /// property to verify whether the lock was granted
 /// or not.
 /// </summary>
 /// <returns>A guard that handles management of the
 /// acquired write lock.</returns>
 public ResourceLockGuard GetWriteGuard(string resourceId)
 {
     return(new ResourceLockGuard(LockItem.CreateWrite(resourceId, null), this));
 }
 /// <summary>
 /// Tries to acquire a shared read lock for a given resource
 /// which never expires.
 /// If this operation succeeds, the lock must be released as soon
 /// as possible through the <see cref="IResourceLockRepository.ReleaseReadLock"/>
 /// method.
 /// </summary>
 /// <returns>A <see cref="LockItem"/> instance which represents
 /// the acquired lock, if any. If no lock was granted, the
 /// returned item's <see cref="LockItem.LockType"/> property
 /// returns <see cref="ResourceLockType.Denied"/>.</returns>
 public LockItem TryGetReadLock(string resourceId)
 {
     return(LockItem.CreateRead(resourceId, null));
 }
 /// <summary>
 /// Releases a previously acquired lock for a given
 /// resource.
 /// </summary>
 /// <param name="item">The lock to be released.</param>
 /// <returns>True if the lock was released. False in case
 /// of an unknown (e.g. automatically removed) lock, or if
 /// the lock is ignored because it's <see cref="LockItem.LockType"/>
 /// is <see cref="ResourceLockType.Denied"/>.</returns>
 public bool ReleaseLock(LockItem item)
 {
   switch (item.LockType)
   {
     case ResourceLockType.Read:
       return ReleaseReadLock(item.ResourceId, item.LockId);
     case ResourceLockType.Write:
       return ReleaseWriteLock(item.ResourceId, item.LockId);
     case ResourceLockType.Denied:
       return false;
     default:
       throw new ArgumentOutOfRangeException("Unsupported lock type: " + item.LockType);
   }
 }
 /// <summary>
 /// Tries to acquire an exclusive write lock for a given resource
 /// which never expires.
 /// If this operation succeeds, the lock must be released as soon
 /// as possible through the <see cref="IResourceLockRepository.ReleaseWriteLock"/>
 /// method.
 /// </summary>
 /// <returns>A <see cref="LockItem"/> instance which represents
 /// the acquired lock, if any. If no lock was granted, the
 /// returned item's <see cref="LockItem.LockType"/> property
 /// returns <see cref="ResourceLockType.Denied"/>.</returns>
 public LockItem TryGetWriteLock(string resourceId)
 {
     return(LockItem.CreateWrite(resourceId, null));
 }
Beispiel #19
0
    /// <summary>
    /// Tries to acquire an exclusive write
    /// for the resource, and specifies a timeout for the lock. If this operation
    /// succeeds, the lock must be released as soon
    /// as possible through the <see cref="ReleaseWriteLock"/>
    /// method.
    /// </summary>
    /// <param name="timeout">The timeout of the lock.
    /// A value of null requests a lock that doesn't time out.</param>
    /// <returns>A lock that corresponds to the request. If the lock was denied, the
    /// returned item's <see cref="LockItem.LockType"/>
    /// is <see cref="ResourceLockType.Denied"/>.</returns>
    /// <exception cref="ArgumentOutOfRangeException">In case of a negative
    /// timeout.</exception>
    public LockItem TryGetWriteLock(TimeSpan? timeout)
    {
      lock (this)
      {
        if (HasWriteLock || HasReadLocks)
        {
          return LockItem.CreateDenied(ResourceId);
        }

        activeWriteLock = LockItem.CreateWrite(ResourceId, timeout);
        return activeWriteLock;
      }
    }
 /// <summary>
 /// Releases a previously acquired lock for a given
 /// resource.
 /// </summary>
 /// <param name="item">The lock to be released.</param>
 /// <returns>True if the lock was released. False in case
 /// of an unknown (e.g. automatically removed) lock, or if
 /// the lock is ignored because it's <see cref="LockItem.LockType"/>
 /// is <see cref="ResourceLockType.Denied"/>.</returns>
 public bool ReleaseLock(LockItem item)
 {
     return(true);
 }
Beispiel #21
0
    /// <summary>
    /// Releases a previously acquired write lock.
    /// </summary>
    /// <param name="lockId">The <see cref="LockItem.LockId"/>
    /// which identifies the lock to be released.</param>
    /// <returns>True if a matching lock was found and released.
    /// If no lock was found, false.</returns>
    public bool ReleaseWriteLock(string lockId)
    {
      lock (this)
      {
        if(activeWriteLock != null && activeWriteLock.LockId == lockId)
        {
          //don't check whether lock has expired - invoking party is happy
          activeWriteLock = null;
          return true;
        }

        return false;
      }
    }