public void Set(string key, object data, TimeSpan cacheTime) { DataCacheLockHandle handle = null; handle = RetryHelper.Execute( () => { DataCacheLockHandle innerHandle = null; var output = _cache.GetAndLock(key, TimeSpan.FromSeconds(240), out innerHandle); return(innerHandle); }, (ex) => true, 50, false, 50); DataCacheItemVersion version = null; if (handle == null) { version = _cache.Put(key, data, cacheTime); } else { version = _cache.PutAndUnlock(key, data, handle, cacheTime); } OnObjectPut(new ObjectPutEventArgs() { Key = key, Version = version }); }
/// <summary> /// Attempts to lock the key in the locks region and stores a reference to the lock handle in memory. /// If the lock region doesn't exists, it will attempt to create it. /// </summary> /// <param name="key">The key to lock.</param> /// <param name="createMissingRegion">A flag to determine whether or not to create the lock region if it doesn't /// exist.</param> private void Lock(object key, bool createMissingRegion) { DataCacheLockHandle lockHandle = null; try { _locksCache.GetAndLock(key.ToString(), TimeSpan.FromMilliseconds(Timeout), out lockHandle, LocksRegionName, true); lock (_lockHandles) { _lockHandles.Add(key.ToString(), lockHandle); } } catch (DataCacheException ex) { if (ex.ErrorCode == DataCacheErrorCode.RegionDoesNotExist && createMissingRegion) { CreateLocksRegion(b => Lock(key, false)); } else { throw new CacheException(ex); } } }
public void Remove(string key) { try { DataCacheLockHandle handle = null; handle = RetryHelper.Execute( () => { DataCacheLockHandle innerHandle = null; var output = _cache.GetAndLock(key, TimeSpan.FromSeconds(30), out innerHandle); return(innerHandle); }, (ex) => true, 50, false, 50); if (handle != null) { _cache.Remove(key, handle); //_cache.Unlock(key, handle); } } catch (DataCacheException ex) { if (ex.ErrorCode != DataCacheErrorCode.KeyDoesNotExist) { EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error); } } }
/// <summary> /// 锁 /// </summary> /// <param name="key"></param> /// <returns></returns> public override bool LockCache(string key, int timeout) { var cachekey = key; var lockobject = Get(cachekey); if (lockobject == null) { Insert(cachekey, false); } DataCacheLockHandle lockHandle = null; try { GetAppfabricCache(); Insert(cachekey, true); lockobject = _memCache.GetAndLock(cachekey, TimeSpan.FromMinutes(timeout), out lockHandle); } catch//异常为此缓存已被加锁 { return(false); } if (_lockHandles.ContainsKey(key)) { _lockHandles.Remove(key); } _lockHandles.Add(key, lockHandle); return(true); }
public override bool Obtain() { bool hasLock = _lockHandle != null; if (!hasLock) { try { _persistantCache.GetAndLock(_lockName, TimeSpan.FromSeconds(30), out _lockHandle, _cacheRegion, true); hasLock = true; } catch (DataCacheException ex) { if (ex.ErrorCode == (int)DataCacheErrorCode.KeyDoesNotExist) { // Put is not effected by locks _persistantCache.Put(_lockName, true, _cacheRegion); hasLock = true; } else if (ex.ErrorCode == (int)DataCacheErrorCode.ObjectLocked) { // make sure out lock handle isn't set _lockHandle = null; } } } return hasLock; }
/// <summary> /// Unlocks the specified name. /// </summary> /// <param name="name">The name.</param> /// <param name="lockHandle">The lock handle.</param> /// <param name="timeout">The timeout.</param> public void Unlock(string name, DataCacheLockHandle lockHandle, TimeSpan timeout) { string region; if (!Settings.TryGetRegion(ref name, out region)) { Cache.Unlock(name, lockHandle, timeout); } else { Cache.Unlock(name, lockHandle, timeout); } }
public override void Release() { if (_lockHandle != null) { _persistantCache.PutAndUnlock(_lockName, false, _lockHandle, _cacheRegion); _lockHandle = null; // Try to get rid of the lock entirely try { _persistantCache.Remove(_lockName, _cacheRegion); } catch { /* Eat the exception here */ } } }
public T Get <T>(string key, out IConcurrencyHandle handle) where T : new() { var retryPolicy = new LockRetryPolicy(); DataCacheLockHandle lockHandle = null; object item = null; HandleBadDataCacheBug(() => retryPolicy.Handle(() => { item = _dataCache.GetAndLock(key, TimeSpan.FromSeconds(1), out lockHandle, true); })); handle = new AzureLockHandle { Instance = lockHandle }; return((T)item); }
/// <summary> /// Unlocks the specified name. /// </summary> /// <param name="name">The name.</param> /// <param name="lockHandle">The lock handle.</param> /// <param name="timeout">The timeout.</param> public void Unlock(string name, DataCacheLockHandle lockHandle, TimeSpan timeout) { string region; if (!Settings.TryGetRegion(ref name, out region)) Cache.Unlock(name, lockHandle, timeout); else Cache.Unlock(name, lockHandle, timeout); }
/// <summary> /// Gets the and lock. /// </summary> /// <param name="name">The name.</param> /// <param name="timeout">The timeout.</param> /// <param name="lockHandle">The lock handle.</param> /// <param name="forceLock">if set to <c>true</c> [force lock].</param> /// <returns></returns> public object GetAndLock(string name, TimeSpan timeout, out DataCacheLockHandle lockHandle, bool forceLock) { string region; return (!Settings.TryGetRegion(ref name, out region) ? Cache.GetAndLock(name, timeout, out lockHandle, forceLock) : Cache.GetAndLock(name, timeout, out lockHandle, region, forceLock)); }
/// <summary> /// Gets the and lock. /// </summary> /// <param name="name">The name.</param> /// <param name="timeout">The timeout.</param> /// <param name="lockHandle">The lock handle.</param> /// <param name="forceLock">if set to <c>true</c> [force lock].</param> /// <returns></returns> public object GetAndLock(string name, TimeSpan timeout, out DataCacheLockHandle lockHandle, bool forceLock) { string region; return(!Settings.TryGetRegion(ref name, out region) ? Cache.GetAndLock(name, timeout, out lockHandle, forceLock) : Cache.GetAndLock(name, timeout, out lockHandle, region, forceLock)); }
/// <summary> /// Updates an existing key in the cache. /// <para> /// The cache manager will make sure the update will always happen on the most recent version. /// </para> /// <para> /// If version conflicts occur, if for example multiple cache clients try to write the same /// key, and during the update process, someone else changed the value for the key, the /// cache manager will retry the operation. /// </para> /// <para> /// The <paramref name="updateValue"/> function will get invoked on each retry with the most /// recent value which is stored in cache. /// </para> /// </summary> /// <param name="key">The key to update.</param> /// <param name="region">The cache region.</param> /// <param name="updateValue">The function to perform the update.</param> /// <param name="config">The cache configuration used to specify the update behavior.</param> /// <returns>The update result which is interpreted by the cache manager.</returns> /// <exception cref="System.ArgumentNullException">If updateValue or config are null.</exception> /// <remarks> /// If the cache does not use a distributed cache system. Update is doing exactly the same /// as Get plus Put. /// </remarks> public override UpdateItemResult <TCacheValue> Update(string key, string region, Func <TCacheValue, TCacheValue> updateValue, UpdateItemConfig config) { if (updateValue == null) { throw new ArgumentNullException("updateValue"); } if (config == null) { throw new ArgumentNullException("config"); } DataCacheLockHandle lockHandle = null; CacheItem <TCacheValue> item = null; var retry = false; // indicate lock = version conflict var hasVersionConflict = false; var tries = 0; do { tries++; retry = false; try { if (string.IsNullOrWhiteSpace(region)) { item = this.cache.GetAndLock(key, TimeSpan.FromMilliseconds(100), out lockHandle) as CacheItem <TCacheValue>; } else { RegisterRegion(region); item = this.cache.GetAndLock(key, TimeSpan.FromMilliseconds(100), out lockHandle, region) as CacheItem <TCacheValue>; } } catch (DataCacheException ex) { if (ex.ErrorCode == DataCacheErrorCode.ObjectLocked) { // object seems to be locked so we have a version conflict and we'll retry... retry = true; hasVersionConflict = true; } else if (IsTransientError(ex)) { retry = true; Task.Delay(DefaultRetryWaitTimeout).Wait(); } else { throw; } } }while (retry && tries <= config.MaxRetries); if (item == null) { return(new UpdateItemResult <TCacheValue>(default(TCacheValue), hasVersionConflict, false, tries)); } do { // fix: never actually updated the item next retry... item = item.WithValue(updateValue(item.Value)); tries++; retry = false; try { if (string.IsNullOrWhiteSpace(item.Region)) { if (item.ExpirationTimeout != TimeSpan.Zero) { this.cache.PutAndUnlock(item.Key, item, lockHandle, item.ExpirationTimeout); } else { this.cache.PutAndUnlock(item.Key, item, lockHandle); } } else { if (item.ExpirationTimeout != TimeSpan.Zero) { this.cache.PutAndUnlock(item.Key, item, lockHandle, item.ExpirationTimeout, item.Region); } else { this.cache.PutAndUnlock(item.Key, item, lockHandle, item.Region); } } return(new UpdateItemResult <TCacheValue>(item.Value, hasVersionConflict, true, tries)); } catch (DataCacheException ex) { if (ex.ErrorCode == DataCacheErrorCode.ObjectNotLocked || ex.ErrorCode == DataCacheErrorCode.InvalidCacheLockHandle || ex.ErrorCode == DataCacheErrorCode.KeyDoesNotExist) { return(new UpdateItemResult <TCacheValue>(default(TCacheValue), hasVersionConflict, false, tries)); } else if (IsTransientError(ex)) { Task.Delay(DefaultRetryWaitTimeout).Wait(); retry = true; } else { // return new UpdateItemResult(hasVersionConflict, false, tries); throw; // shell we throw the exception? Usually we just return false... } } }while (retry && tries <= config.MaxRetries); return(new UpdateItemResult <TCacheValue>(default(TCacheValue), hasVersionConflict, false, tries)); }