/// <inheritdoc />
        public async Task <LockResult> LockAsync(ILock l, CancellationToken cancellationToken)
        {
            ActiveLock newActiveLock;
            var        destinationUrl = BuildUrl(l.Path);

            using (var transaction = await BeginTransactionAsync(cancellationToken).ConfigureAwait(false))
            {
                var locks = await transaction.GetActiveLocksAsync(cancellationToken).ConfigureAwait(false);

                var status           = Find(locks, destinationUrl, l.Recursive, true);
                var conflictingLocks = GetConflictingLocks(status, LockShareMode.Parse(l.ShareMode));
                if (conflictingLocks.Count != 0)
                {
                    if (_logger.IsEnabled(LogLevel.Information))
                    {
                        _logger.LogInformation($"Found conflicting locks for {l}: {string.Join(",", conflictingLocks.GetLocks().Select(x => x.ToString()))}");
                    }
                    return(new LockResult(conflictingLocks));
                }

                newActiveLock = new ActiveLock(l, _rounding.Round(_systemClock.UtcNow), _rounding.Round(l.Timeout));

                await transaction.AddAsync(newActiveLock, cancellationToken).ConfigureAwait(false);

                await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
            }

            OnLockAdded(newActiveLock);

            _cleanupTask.Add(this, newActiveLock);

            return(new LockResult(newActiveLock));
        }
Example #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ActiveLock"/> class.
 /// </summary>
 /// <param name="l">The lock to create this active lock from</param>
 /// <param name="issued">The date/time when this lock was issued</param>
 /// <param name="timeout">Override the timeout from the original lock (to enforce rounding)</param>
 internal ActiveLock([NotNull] ILock l, DateTime issued, TimeSpan timeout)
     : this(
         l.Path,
         l.Href,
         l.Recursive,
         l.GetOwner(),
         LockAccessType.Parse(l.AccessType),
         LockShareMode.Parse(l.ShareMode),
         timeout,
         issued,
         null)
 {
 }
 private static ActiveLock Refresh(IActiveLock activeLock, DateTime lastRefresh, TimeSpan timeout)
 {
     return(new ActiveLock(
                activeLock.Path,
                activeLock.Href,
                activeLock.Recursive,
                activeLock.GetOwner(),
                LockAccessType.Parse(activeLock.AccessType),
                LockShareMode.Parse(activeLock.ShareMode),
                timeout,
                activeLock.Issued,
                lastRefresh,
                activeLock.StateToken));
 }
Example #4
0
        /// <summary>
        /// Creates an <see cref="XElement"/> for a <see cref="IActiveLock"/>
        /// </summary>
        /// <param name="l">The active lock to create the <see cref="XElement"/> for</param>
        /// <param name="omitOwner">Should the owner be omitted?</param>
        /// <param name="omitToken">Should the lock state token be omitted?</param>
        /// <returns>The newly created <see cref="XElement"/> for the active lock</returns>
        public static XElement ToXElement(this IActiveLock l, bool omitOwner = false, bool omitToken = false)
        {
            var timeout   = l.Timeout == TimeoutHeader.Infinite ? "Infinite" : $"Second-{l.Timeout.TotalSeconds:F0}";
            var depth     = l.Recursive ? DepthHeader.Infinity : DepthHeader.Zero;
            var lockScope = LockShareMode.Parse(l.ShareMode);
            var lockType  = LockAccessType.Parse(l.AccessType);
            var owner     = l.GetOwner();
            var result    = new XElement(
                WebDavXml.Dav + "activelock",
                new XElement(
                    WebDavXml.Dav + "lockscope",
                    new XElement(lockScope.Name)),
                new XElement(
                    WebDavXml.Dav + "locktype",
                    new XElement(lockType.Name)),
                new XElement(
                    WebDavXml.Dav + "depth",
                    depth.Value));

            if (owner != null && !omitOwner)
            {
                result.Add(owner);
            }

            result.Add(
                new XElement(
                    WebDavXml.Dav + "timeout",
                    timeout));

            if (!omitToken)
            {
                result.Add(
                    new XElement(
                        WebDavXml.Dav + "locktoken",
                        new XElement(WebDavXml.Dav + "href", l.StateToken)));
            }

            result.Add(
                new XElement(
                    WebDavXml.Dav + "lockroot",
                    new XElement(WebDavXml.Dav + "href", l.Href)));

            return(result);
        }
        private static LockStatus GetConflictingLocks(LockStatus affactingLocks, LockShareMode shareMode)
        {
            if (shareMode == LockShareMode.Exclusive)
            {
                return(affactingLocks);
            }

            return(new LockStatus(
                       affactingLocks
                       .ReferenceLocks
                       .Where(x => LockShareMode.Parse(x.ShareMode) == LockShareMode.Exclusive)
                       .ToList(),
                       affactingLocks
                       .ParentLocks
                       .Where(x => LockShareMode.Parse(x.ShareMode) == LockShareMode.Exclusive)
                       .ToList(),
                       affactingLocks
                       .ChildLocks
                       .Where(x => LockShareMode.Parse(x.ShareMode) == LockShareMode.Exclusive)
                       .ToList()));
        }