Example #1
0
        /// <summary>
        /// Stop any other transactions reading or writing this item to/from
        /// the cache. Send them straight to the database instead. (The lock
        /// does time out eventually.) This implementation tracks concurrent
        /// locks by transactions which simultaneously attempt to write to an
        /// item.
        /// </summary>
        public async Task <ISoftLock> LockAsync(CacheKey key, object version, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (await _lockObjectAsync.LockAsync())
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("Invalidating: {0}", key);
                }

                try
                {
                    await(cache.LockAsync(key, cancellationToken)).ConfigureAwait(false);

                    ILockable lockable = (ILockable)await(cache.GetAsync(key, cancellationToken)).ConfigureAwait(false);
                    long      timeout  = cache.NextTimestamp() + cache.Timeout;
                    CacheLock @lock    = lockable == null ?
                                         new CacheLock(timeout, NextLockId(), version) :
                                         lockable.Lock(timeout, NextLockId());
                    await(cache.PutAsync(key, @lock, cancellationToken)).ConfigureAwait(false);
                    return(@lock);
                }
                finally
                {
                    await(cache.UnlockAsync(key, cancellationToken)).ConfigureAwait(false);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Stop any other transactions reading or writing this item to/from
        /// the cache. Send them straight to the database instead. (The lock
        /// does time out eventually.) This implementation tracks concurrent
        /// locks by transactions which simultaneously attempt to write to an
        /// item.
        /// </summary>
        public async Task <ISoftLock> LockAsync(CacheKey key, object version, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (await(_asyncReaderWriterLock.WriteLockAsync()).ConfigureAwait(false))
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("Invalidating: {0}", key);
                }

                var lockValue = await(_cache.LockAsync(key, cancellationToken)).ConfigureAwait(false);
                try
                {
                    ILockable lockable = (ILockable)await(Cache.GetAsync(key, cancellationToken)).ConfigureAwait(false);
                    long      timeout  = Cache.NextTimestamp() + Cache.Timeout;
                    CacheLock @lock    = lockable == null?
                                         CacheLock.Create(timeout, NextLockId(), version) :
                                             lockable.Lock(timeout, NextLockId());

                    await(Cache.PutAsync(key, @lock, cancellationToken)).ConfigureAwait(false);
                    return(@lock);
                }
                finally
                {
                    await(_cache.UnlockAsync(key, lockValue, cancellationToken)).ConfigureAwait(false);
                }
            }
        }
        /// <summary>
        /// Stop any other transactions reading or writing this item to/from
        /// the cache. Send them straight to the database instead. (The lock
        /// does time out eventually.) This implementation tracks concurrent
        /// locks by transactions which simultaneously attempt to write to an
        /// item.
        /// </summary>
        public ISoftLock Lock(CacheKey key, object version)
        {
            lock (_lockObject)
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("Invalidating: {0}", key);
                }

                try
                {
                    cache.Lock(key);

                    ILockable lockable = (ILockable)cache.Get(key);
                    long      timeout  = cache.NextTimestamp() + cache.Timeout;
                    CacheLock @lock    = lockable == null?
                                         CacheLock.Create(timeout, NextLockId(), version) :
                                             lockable.Lock(timeout, NextLockId());

                    cache.Put(key, @lock);
                    return(@lock);
                }
                finally
                {
                    cache.Unlock(key);
                }
            }
        }
        internal void HandleLockExpiry(object key)
        {
            log.Warn("An item was expired by the cache while it was locked (increase your cache timeout): {0}", key);
            long ts = cache.NextTimestamp() + cache.Timeout;
            // create new lock that times out immediately
            CacheLock @lock = CacheLock.Create(ts, NextLockId(), null);

            @lock.Unlock(ts);
            cache.Put(key, @lock);
        }
Example #5
0
        /// <summary>
        /// Re-cache the updated state, if and only if there there are
        /// no other concurrent soft locks. Release our lock.
        /// </summary>
        public async Task <bool> AfterUpdateAsync(CacheKey key, object value, object version, ISoftLock clientLock, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (await _lockObjectAsync.LockAsync())
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("Updating: {0}", key);
                }

                try
                {
                    await(cache.LockAsync(key, cancellationToken)).ConfigureAwait(false);

                    ILockable lockable = (ILockable)await(cache.GetAsync(key, cancellationToken)).ConfigureAwait(false);
                    if (IsUnlockable(clientLock, lockable))
                    {
                        CacheLock @lock = (CacheLock)lockable;
                        if (@lock.WasLockedConcurrently)
                        {
                            // just decrement the lock, don't recache
                            // (we don't know which transaction won)
                            await(DecrementLockAsync(key, @lock, cancellationToken)).ConfigureAwait(false);
                        }
                        else
                        {
                            //recache the updated state
                            await(cache.PutAsync(key, new CachedItem(value, cache.NextTimestamp(), version), cancellationToken)).ConfigureAwait(false);
                            if (log.IsDebugEnabled())
                            {
                                log.Debug("Updated: {0}", key);
                            }
                        }
                        return(true);
                    }
                    else
                    {
                        await(HandleLockExpiryAsync(key, cancellationToken)).ConfigureAwait(false);
                        return(false);
                    }
                }
                finally
                {
                    await(cache.UnlockAsync(key, cancellationToken)).ConfigureAwait(false);
                }
            }
        }
Example #6
0
 /// <summary>
 /// decrement a lock and put it back in the cache
 /// </summary>
 private Task DecrementLockAsync(object key, CacheLock @lock, CancellationToken cancellationToken)
 {
     if (cancellationToken.IsCancellationRequested)
     {
         return(Task.FromCanceled <object>(cancellationToken));
     }
     try
     {
         //decrement the lock
         @lock.Unlock(Cache.NextTimestamp());
         return(Cache.PutAsync(key, @lock, cancellationToken));
     }
     catch (System.Exception ex)
     {
         return(Task.FromException <object>(ex));
     }
 }
        /// <summary>
        /// Re-cache the updated state, if and only if there there are
        /// no other concurrent soft locks. Release our lock.
        /// </summary>
        public bool AfterUpdate(CacheKey key, object value, object version, ISoftLock clientLock)
        {
            lock (_lockObject)
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("Updating: {0}", key);
                }

                try
                {
                    cache.Lock(key);

                    ILockable lockable = (ILockable)cache.Get(key);
                    if (IsUnlockable(clientLock, lockable))
                    {
                        CacheLock @lock = (CacheLock)lockable;
                        if (@lock.WasLockedConcurrently)
                        {
                            // just decrement the lock, don't recache
                            // (we don't know which transaction won)
                            DecrementLock(key, @lock);
                        }
                        else
                        {
                            //recache the updated state
                            cache.Put(key, CachedItem.Create(value, cache.NextTimestamp(), version));
                            if (log.IsDebugEnabled())
                            {
                                log.Debug("Updated: {0}", key);
                            }
                        }
                        return(true);
                    }
                    else
                    {
                        HandleLockExpiry(key);
                        return(false);
                    }
                }
                finally
                {
                    cache.Unlock(key);
                }
            }
        }
Example #8
0
 internal Task HandleLockExpiryAsync(object key, CancellationToken cancellationToken)
 {
     if (cancellationToken.IsCancellationRequested)
     {
         return(Task.FromCanceled <object>(cancellationToken));
     }
     try
     {
         log.Warn("An item was expired by the cache while it was locked (increase your cache timeout): {0}", key);
         long ts = Cache.NextTimestamp() + Cache.Timeout;
         // create new lock that times out immediately
         CacheLock @lock = CacheLock.Create(ts, NextLockId(), null);
         @lock.Unlock(ts);
         return(Cache.PutAsync(key, @lock, cancellationToken));
     }
     catch (System.Exception ex)
     {
         return(Task.FromException <object>(ex));
     }
 }
		internal void HandleLockExpiry( object key )
		{
			log.Warn( "An item was expired by the cache while it was locked (increase your cache timeout): " + key );
			long ts = cache.NextTimestamp() + cache.Timeout;
			// create new lock that times out immediately
			CacheLock @lock = new CacheLock( ts, NextLockId(), null );
			@lock.Unlock( ts );
			cache.Put( key, @lock );
		}
		/// <summary>
		/// decrement a lock and put it back in the cache
		/// </summary>
		private void DecrementLock( object key, CacheLock @lock )
		{
			//decrement the lock
			@lock.Unlock( cache.NextTimestamp() );
			cache.Put( key, @lock );
		}
 /// <summary>
 /// decrement a lock and put it back in the cache
 /// </summary>
 private void DecrementLock(object key, CacheLock @lock)
 {
     //decrement the lock
     @lock.Unlock(cache.NextTimestamp());
     cache.Put(key, @lock);
 }