Exemplo n.º 1
0
        public async Task ReleaseAsync(CacheKey key, ISoftLock clientLock, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (await _lockObjectAsync.LockAsync())
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("Releasing: " + key);
                }

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

                    ILockable lockable = (ILockable)await(cache.GetAsync(key, cancellationToken)).ConfigureAwait(false);
                    if (IsUnlockable(clientLock, lockable))
                    {
                        await(DecrementLockAsync(key, (CacheLock)lockable, cancellationToken)).ConfigureAwait(false);
                    }
                    else
                    {
                        await(HandleLockExpiryAsync(key, cancellationToken)).ConfigureAwait(false);
                    }
                }
                finally
                {
                    await(cache.UnlockAsync(key, cancellationToken)).ConfigureAwait(false);
                }
            }
        }
Exemplo n.º 2
0
        public async Task ReleaseAsync(CacheKey key, ISoftLock clientLock, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (await(_asyncReaderWriterLock.WriteLockAsync()).ConfigureAwait(false))
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("Releasing: {0}", key);
                }

                var lockValue = await(_cache.LockAsync(key, cancellationToken)).ConfigureAwait(false);
                try
                {
                    ILockable lockable = (ILockable)await(Cache.GetAsync(key, cancellationToken)).ConfigureAwait(false);
                    if (IsUnlockable(clientLock, lockable))
                    {
                        await(DecrementLockAsync(key, (CacheLock)lockable, cancellationToken)).ConfigureAwait(false);
                    }
                    else
                    {
                        await(HandleLockExpiryAsync(key, cancellationToken)).ConfigureAwait(false);
                    }
                }
                finally
                {
                    await(_cache.UnlockAsync(key, lockValue, cancellationToken)).ConfigureAwait(false);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// If the class to be loaded has been configured with a cache, then lock
        /// given id in that cache and then perform the load.
        /// </summary>
        /// <returns> The loaded entity </returns>
        protected virtual object LockAndLoad(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options, ISessionImplementor source)
        {
            ISoftLock sLock = null;
            CacheKey  ck;

            if (persister.HasCache)
            {
                ck    = source.GenerateCacheKey(@event.EntityId, persister.IdentifierType, persister.RootEntityName);
                sLock = persister.Cache.Lock(ck, null);
            }
            else
            {
                ck = null;
            }

            object entity;

            try
            {
                entity = Load(@event, persister, keyToLoad, options);
            }
            finally
            {
                if (persister.HasCache)
                {
                    persister.Cache.Release(ck, sLock);
                }
            }

            object proxy = @event.Session.PersistenceContext.ProxyFor(persister, keyToLoad, entity);

            return(proxy);
        }
Exemplo n.º 4
0
        public void Release(CacheKey key, ISoftLock clientLock)
        {
            lock (_lockObject)
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("Releasing: {0}", key);
                }

                try
                {
                    cache.Lock(key);

                    ILockable lockable = (ILockable)cache.Get(key);
                    if (IsUnlockable(clientLock, lockable))
                    {
                        DecrementLock(key, (CacheLock)lockable);
                    }
                    else
                    {
                        HandleLockExpiry(key);
                    }
                }
                finally
                {
                    cache.Unlock(key);
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// If the class to be loaded has been configured with a cache, then lock
        /// given id in that cache and then perform the load.
        /// </summary>
        /// <returns> The loaded entity </returns>
        protected virtual async Task <object> LockAndLoadAsync(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options, ISessionImplementor source, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            ISoftLock sLock = null;
            CacheKey  ck;

            if (persister.HasCache)
            {
                ck    = source.GenerateCacheKey(@event.EntityId, persister.IdentifierType, persister.RootEntityName);
                sLock = await(persister.Cache.LockAsync(ck, null, cancellationToken)).ConfigureAwait(false);
            }
            else
            {
                ck = null;
            }

            object entity;

            try
            {
                entity = await(LoadAsync(@event, persister, keyToLoad, options, cancellationToken)).ConfigureAwait(false);
            }
            finally
            {
                if (persister.HasCache)
                {
                    await(persister.Cache.ReleaseAsync(ck, sLock, cancellationToken)).ConfigureAwait(false);
                }
            }

            object proxy = @event.Session.PersistenceContext.ProxyFor(persister, keyToLoad, entity);

            return(proxy);
        }
		/// <summary></summary>
		public override void Execute()
		{
			CacheKey ck = null;
			if (Persister.HasCache)
			{
				ck = new CacheKey(
					Id,
					Persister.IdentifierType,
					(string) Persister.IdentifierSpace,
					Session.Factory
					);
				_lock = Persister.Cache.Lock(ck, lastVersion);
			}
			Persister.Update(Id, state, dirtyFields, hasDirtyCollection, previousState, lastVersion, Instance, Session);
			
			EntityEntry entry = Session.GetEntry(Instance);
			if (entry == null)
			{
				throw new AssertionFailure("possible nonthreadsafe access to session");
			}

			if (entry.Status == Status.Loaded || Persister.IsVersionPropertyGenerated)
			{
				// get the updated snapshot of the entity state by cloning current state;
				// it is safe to copy in place, since by this time no-one else (should have)
				// has a reference  to the array
				TypeFactory.DeepCopy(
						state,
						Persister.PropertyTypes,
						Persister.PropertyCheckability,
						state);
				if (Persister.HasUpdateGeneratedProperties)
				{
					// this entity defines proeprty generation, so process those generated
					// values...
					Persister.ProcessUpdateGeneratedProperties(Id, Instance, state, Session);
					if (Persister.IsVersionPropertyGenerated)
					{
						nextVersion = Versioning.GetVersion(state, Persister);
					}
				}
				// have the entity entry perform post-update processing, passing it the
				// update state and the new version (if one).
				entry.PostUpdate(Instance, state, nextVersion);
			}

			if (Persister.HasCache)
			{
				if (Persister.IsCacheInvalidationRequired || entry.Status != Status.Loaded)
				{
					Persister.Cache.Evict(ck);
				}
				else
				{
					// TODO: Inefficient if that cache is just going to ignore the updated state!
					cacheEntry = new CacheEntry(Instance, Persister, Session);
					Persister.Cache.Update(ck, cacheEntry);
				}
			}
		}
Exemplo n.º 7
0
 /// <summary>
 /// Is the client's lock commensurate with the item in the cache?
 /// If it is not, we know that the cache expired the original
 /// lock.
 /// </summary>
 private bool IsUnlockable(ISoftLock clientLock, ILockable myLock)
 {
     //null clientLock is remotely possible but will never happen in practice
     return(myLock != null &&
            myLock.IsLock &&
            clientLock != null &&
            ((CacheLock)clientLock).Id == ((CacheLock)myLock).Id);
 }
		/// <summary></summary>
		public override void Execute()
		{
			if( Persister.HasCache )
			{
				lck = Persister.Cache.Lock( Id, version );
			}
			Persister.Delete( Id, version, Instance, Session );
			Session.PostDelete( Instance );
		}
 /// <summary></summary>
 public override void Execute()
 {
     if (Persister.HasCache)
     {
         lck = Persister.Cache.Lock(Id, version);
     }
     Persister.Delete(Id, version, Instance, Session);
     Session.PostDelete(Instance);
 }
Exemplo n.º 10
0
        /// <summary>
        /// Invalidate the item (again, for safety).
        /// </summary>
        public void Release(CacheKey key, ISoftLock @lock)
        {
            if (log.IsDebugEnabled)
            {
                log.Debug("Invalidating (again): " + key);
            }

            cache.Remove(key);
        }
 /// <summary>
 ///
 /// </summary>
 public void BeforeExecutions( )
 {
     // we need to obtain the lock before any actions are
     // executed, since this may be an inverse="true"
     // bidirectional association and it is one of the
     // earlier entity actions which actually updates
     // the database (this action is resposible for
     // second-level cache invalidation only)
     if (persister.HasCache)
     {
         lck = persister.Cache.Lock(id, null);                   //collections don't have version numbers :-(
     }
 }
Exemplo n.º 12
0
 /// <summary> Called before executing any actions</summary>
 public virtual void BeforeExecutions()
 {
     // we need to obtain the lock before any actions are
     // executed, since this may be an inverse="true"
     // bidirectional association and it is one of the
     // earlier entity actions which actually updates
     // the database (this action is responsible for
     // second-level cache invalidation only)
     if (persister.HasCache)
     {
         CacheKey ck = session.GenerateCacheKey(key, persister.KeyType, persister.Role);
         softLock = persister.Cache.Lock(ck, null);
     }
 }
		/// <summary></summary>
		public override void Execute()
		{
			if (Persister.HasCache)
			{
				CacheKey ck = new CacheKey(
					Id,
					Persister.IdentifierType,
					(string) Persister.IdentifierSpace,
					Session.Factory
					);
				lck = Persister.Cache.Lock(ck, version);
			}
			Persister.Delete(Id, version, Instance, Session);
			Session.PostDelete(Instance);
		}
Exemplo n.º 14
0
 /// <summary>
 /// Unsupported!
 /// </summary>
 public Task ReleaseAsync(CacheKey key, ISoftLock @lock, CancellationToken cancellationToken)
 {
     if (cancellationToken.IsCancellationRequested)
     {
         return(Task.FromCanceled <object>(cancellationToken));
     }
     try
     {
         Release(key, @lock);
         return(Task.CompletedTask);
     }
     catch (Exception ex)
     {
         return(Task.FromException <object>(ex));
     }
 }
Exemplo n.º 15
0
        /// <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);
                }
            }
        }
        /// <summary>
        /// Invalidate the item (again, for safety).
        /// </summary>
        public Task ReleaseAsync(CacheKey key, ISoftLock @lock, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled <object>(cancellationToken));
            }
            try
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("Invalidating (again): {0}", key);
                }

                return(cache.RemoveAsync(key, cancellationToken));
            }
            catch (Exception ex)
            {
                return(Task.FromException <object>(ex));
            }
        }
		/// <summary></summary>
		public override void Execute()
		{
			if( Persister.HasCache )
			{
				_lock = Persister.Cache.Lock( Id, lastVersion );
			}
			Persister.Update( Id, fields, dirtyFields, oldFields, lastVersion, Instance, Session );
			Session.PostUpdate( Instance, updatedState, nextVersion );

			if ( Persister.HasCache )
			{
				if ( Persister.IsCacheInvalidationRequired )
				{
					Persister.Cache.Evict( Id );
				}
				else
				{
					// TODO: Inefficient if that cache is just going to ignore the updated state!
					cacheEntry = new CacheEntry( Instance, Persister, Session );
					Persister.Cache.Update( Id, cacheEntry );
				}
			}
		}
Exemplo n.º 18
0
        /// <summary></summary>
        public override void Execute()
        {
            if (Persister.HasCache)
            {
                _lock = Persister.Cache.Lock(Id, lastVersion);
            }
            Persister.Update(Id, fields, dirtyFields, oldFields, lastVersion, Instance, Session);
            Session.PostUpdate(Instance, updatedState, nextVersion);

            if (Persister.HasCache)
            {
                if (Persister.IsCacheInvalidationRequired)
                {
                    Persister.Cache.Evict(Id);
                }
                else
                {
                    // TODO: Inefficient if that cache is just going to ignore the updated state!
                    cacheEntry = new CacheEntry(Instance, Persister, Session);
                    Persister.Cache.Update(Id, cacheEntry);
                }
            }
        }
 /// <summary>
 /// Invalidate the item (again, for safety).
 /// </summary>
 public async Task <bool> AfterUpdateAsync(CacheKey key, object value, object version, ISoftLock @lock, CancellationToken cancellationToken)
 {
     cancellationToken.ThrowIfCancellationRequested();
     await(ReleaseAsync(key, @lock, cancellationToken)).ConfigureAwait(false);
     return(false);
 }
		/// <summary>
		/// 
		/// </summary>
		/// <param name="key"></param>
		/// <param name="clientLock"></param>
		public void Release( object key, ISoftLock clientLock )
		{
			lock( _lockObject )
			{
				if( log.IsDebugEnabled )
				{
					log.Debug( "Releasing: " + key );
				}

				try
				{
					cache.Lock( key );

					ILockable lockable = ( ILockable ) cache.Get( key );
					if( IsUnlockable( clientLock, lockable ) )
					{
						DecrementLock( key, ( CacheLock ) lockable );
					}
					else
					{
						HandleLockExpiry( key );
					}
				}
				finally
				{
					cache.Unlock( key );
				}
			}
		}
Exemplo n.º 21
0
 /// <summary>
 /// Invalidate the item (again, for safety).
 /// </summary>
 public bool AfterUpdate(CacheKey key, object value, object version, ISoftLock @lock)
 {
     Release(key, @lock);
     return(false);
 }
Exemplo n.º 22
0
		/// <summary>
		/// Invalidate the item (again, for safety).
		/// </summary>
		public bool AfterUpdate(CacheKey key, object value, object version, ISoftLock @lock)
		{
			Release(key, @lock);
			return false;
		}
Exemplo n.º 23
0
        public override void Execute()
        {
            ISessionImplementor session = Session;
            object           id         = Id;
            IEntityPersister persister  = Persister;
            object           instance   = Instance;

            bool      statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            Stopwatch stopwatch    = null;

            if (statsEnabled)
            {
                stopwatch = Stopwatch.StartNew();
            }

            bool veto = PreUpdate();

            ISessionFactoryImplementor factory = Session.Factory;

            if (persister.IsVersionPropertyGenerated)
            {
                // we need to grab the version value from the entity, otherwise
                // we have issues with generated-version entities that may have
                // multiple actions queued during the same flush
                previousVersion = persister.GetVersion(instance);
            }

            CacheKey ck = null;

            if (persister.HasCache)
            {
                ck    = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
                slock = persister.Cache.Lock(ck, previousVersion);
            }

            if (!veto)
            {
                persister.Update(id, state, dirtyFields, hasDirtyCollection, previousState, previousVersion, instance, null, session);
            }

            EntityEntry entry = Session.PersistenceContext.GetEntry(instance);

            if (entry == null)
            {
                throw new AssertionFailure("Possible nonthreadsafe access to session");
            }

            if (entry.Status == Status.Loaded || persister.IsVersionPropertyGenerated)
            {
                // get the updated snapshot of the entity state by cloning current state;
                // it is safe to copy in place, since by this time no-one else (should have)
                // has a reference  to the array
                TypeHelper.DeepCopy(state, persister.PropertyTypes, persister.PropertyCheckability, state, Session);
                if (persister.HasUpdateGeneratedProperties)
                {
                    // this entity defines property generation, so process those generated
                    // values...
                    persister.ProcessUpdateGeneratedProperties(id, instance, state, Session);
                    if (persister.IsVersionPropertyGenerated)
                    {
                        nextVersion = Versioning.GetVersion(state, persister);
                    }
                }
                // have the entity entry perform post-update processing, passing it the
                // update state and the new version (if one).
                entry.PostUpdate(instance, state, nextVersion);
            }

            if (persister.HasCache)
            {
                if (persister.IsCacheInvalidationRequired || entry.Status != Status.Loaded)
                {
                    persister.Cache.Evict(ck);
                }
                else
                {
                    CacheEntry ce = CacheEntry.Create(state, persister, nextVersion, Session, instance);
                    cacheEntry = persister.CacheEntryStructure.Structure(ce);

                    bool put = persister.Cache.Update(ck, cacheEntry, nextVersion, previousVersion);

                    if (put && factory.Statistics.IsStatisticsEnabled)
                    {
                        factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName);
                    }
                }
            }

            PostUpdate();

            if (statsEnabled && !veto)
            {
                stopwatch.Stop();
                factory.StatisticsImplementor.UpdateEntity(Persister.EntityName, stopwatch.Elapsed);
            }
        }
Exemplo n.º 24
0
		/// <summary>
		/// Unsupported!
		/// </summary>
		public void AfterUpdate(CacheKey key, object value, object version, ISoftLock @lock)
		{
			log.Error("Application attempted to edit read only item: " + key);
			throw new InvalidOperationException("Can't write to a readonly object");
		}
Exemplo n.º 25
0
 /// <summary>
 /// Unsupported!
 /// </summary>
 /// <param name="key"></param>
 /// <param name="value"></param>
 /// <param name="version"></param>
 /// <param name="lock"></param>
 public void AfterUpdate(object key, object value, object version, ISoftLock @lock)
 {
     log.Error("Application attempted to edit read only item: " + key);
     throw new InvalidOperationException("Can't write to a readonly object");
 }
Exemplo n.º 26
0
		public override void Execute()
		{
			ISessionImplementor session = Session;
			object id = Id;
			IEntityPersister persister = Persister;
			object instance = Instance;

			bool statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
			Stopwatch stopwatch = null;
			if (statsEnabled)
			{
				stopwatch = Stopwatch.StartNew();
			}

			bool veto = PreUpdate();

			ISessionFactoryImplementor factory = Session.Factory;

			if (persister.IsVersionPropertyGenerated)
			{
				// we need to grab the version value from the entity, otherwise
				// we have issues with generated-version entities that may have
				// multiple actions queued during the same flush
				previousVersion = persister.GetVersion(instance, session.EntityMode);
			}

			CacheKey ck = null;
			if (persister.HasCache)
			{
				ck = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
				slock = persister.Cache.Lock(ck, previousVersion);
			}

			if (!veto)
			{
				persister.Update(id, state, dirtyFields, hasDirtyCollection, previousState, previousVersion, instance, null, session);
			}

			EntityEntry entry = Session.PersistenceContext.GetEntry(instance);
			if (entry == null)
			{
				throw new AssertionFailure("Possible nonthreadsafe access to session");
			}

			if (entry.Status == Status.Loaded || persister.IsVersionPropertyGenerated)
			{
				// get the updated snapshot of the entity state by cloning current state;
				// it is safe to copy in place, since by this time no-one else (should have)
				// has a reference  to the array
				TypeHelper.DeepCopy(state, persister.PropertyTypes, persister.PropertyCheckability, state, Session);
				if (persister.HasUpdateGeneratedProperties)
				{
					// this entity defines property generation, so process those generated
					// values...
					persister.ProcessUpdateGeneratedProperties(id, instance, state, Session);
					if (persister.IsVersionPropertyGenerated)
					{
						nextVersion = Versioning.GetVersion(state, persister);
					}
				}
				// have the entity entry perform post-update processing, passing it the
				// update state and the new version (if one).
				entry.PostUpdate(instance, state, nextVersion);
			}

			if (persister.HasCache)
			{
				if (persister.IsCacheInvalidationRequired || entry.Status != Status.Loaded)
				{
					persister.Cache.Evict(ck);
				}
				else
				{
					CacheEntry ce = new CacheEntry(state, persister, persister.HasUninitializedLazyProperties(instance, session.EntityMode), nextVersion, Session, instance);
					cacheEntry = persister.CacheEntryStructure.Structure(ce);

					bool put = persister.Cache.Update(ck, cacheEntry, nextVersion, previousVersion);

					if (put && factory.Statistics.IsStatisticsEnabled)
					{
						factory.StatisticsImplementor.SecondLevelCachePut(Persister.Cache.RegionName);
					}
				}
			}

			PostUpdate();

			if (statsEnabled && !veto)
			{
				stopwatch.Stop();
				factory.StatisticsImplementor.UpdateEntity(Persister.EntityName, stopwatch.Elapsed);
			}
		}
Exemplo n.º 27
0
 /// <summary>
 /// Unsupported!
 /// </summary>
 /// <param name="key"></param>
 /// <param name="lock"></param>
 public void Release(object key, ISoftLock @lock)
 {
     log.Error("Application attempted to edit read only item: " + key);
     //throw new InvalidOperationException( "Can't write to a readonly object" );
 }
		/// <summary>
		/// Is the client's lock commensurate with the item in the cache?
		/// If it is not, we know that the cache expired the original
		/// lock.
		/// </summary>
		private bool IsUnlockable( ISoftLock clientLock, ILockable myLock )
		{
			//null clientLock is remotely possible but will never happen in practice
			return myLock != null &&
				myLock.IsLock &&
				clientLock != null &&
				( ( CacheLock ) clientLock ).Id == ( ( CacheLock ) myLock ).Id;
		}
		/// <summary>
		/// Re-cache the updated state, if and only if there there are
		/// no other concurrent soft locks. Release our lock.
		/// </summary>
		/// <param name="key"></param>
		/// <param name="value"></param>
		/// <param name="version"></param>
		/// <param name="clientLock"></param>
		public void AfterUpdate( object key, object value, object version, ISoftLock clientLock )
		{
			lock( _lockObject )
			{
				if( log.IsDebugEnabled )
				{
					log.Debug( "Updating: " + 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, new CachedItem( value, cache.NextTimestamp(), version ) );
							if( log.IsDebugEnabled )
							{
								log.Debug( "Updated: " + key );
							}
						}
					}
					else
					{
						HandleLockExpiry( key );
					}
				}
				finally
				{
					cache.Unlock( key );
				}
			}
		}
Exemplo n.º 30
0
 /// <summary>
 /// Unsupported!
 /// </summary>
 public bool AfterUpdate(CacheKey key, object value, object version, ISoftLock @lock)
 {
     log.Error("Application attempted to edit read only item: " + key);
     throw new InvalidOperationException("ReadOnlyCache: Can't write to a readonly object " + key.EntityOrRoleName);
 }
Exemplo n.º 31
0
 /// <summary>
 /// Unsupported!
 /// </summary>
 public void Release(CacheKey key, ISoftLock @lock)
 {
     log.Error("Application attempted to edit read only item: " + key);
 }
		/// <summary>
		/// 
		/// </summary>
		public void BeforeExecutions()
		{
			// we need to obtain the lock before any actions are
			// executed, since this may be an inverse="true"
			// bidirectional association and it is one of the
			// earlier entity actions which actually updates
			// the database (this action is resposible for
			// second-level cache invalidation only)
			if (persister.HasCache)
			{
				CacheKey ck = new CacheKey(
					id,
					persister.KeyType,
					persister.Role,
					session.Factory
					);
				lck = persister.Cache.Lock(ck, null); //collections don't have version numbers :-(
			}
		}
Exemplo n.º 33
0
		/// <summary>
		/// Invalidate the item (again, for safety).
		/// </summary>
		public void Release(CacheKey key, ISoftLock @lock)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug("Invalidating (again): " + key);
			}

			cache.Remove(key);
		}
		public override void Execute()
		{
			object id = Id;
			IEntityPersister persister = Persister;
			ISessionImplementor session = Session;
			object instance = Instance;

			bool statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
			Stopwatch stopwatch = null;
			if (statsEnabled)
			{
				stopwatch = Stopwatch.StartNew();
			}

			bool veto = PreDelete();

			object tmpVersion = version;
			if (persister.IsVersionPropertyGenerated)
			{
				// we need to grab the version value from the entity, otherwise
				// we have issues with generated-version entities that may have
				// multiple actions queued during the same flush
				tmpVersion = persister.GetVersion(instance, session.EntityMode);
			}

			CacheKey ck;
			if (persister.HasCache)
			{
				ck = session.GenerateCacheKey(id, persister.IdentifierType, persister.RootEntityName);
				sLock = persister.Cache.Lock(ck, version);
			}
			else
			{
				ck = null;
			}

			if (!isCascadeDeleteEnabled && !veto)
			{
				persister.Delete(id, tmpVersion, instance, session);
			}

			//postDelete:
			// After actually deleting a row, record the fact that the instance no longer 
			// exists on the database (needed for identity-column key generation), and
			// remove it from the session cache
			IPersistenceContext persistenceContext = session.PersistenceContext;

			EntityEntry entry = persistenceContext.RemoveEntry(instance);
			if (entry == null)
			{
				throw new AssertionFailure("Possible nonthreadsafe access to session");
			}
			entry.PostDelete();

			EntityKey key = session.GenerateEntityKey(entry.Id, entry.Persister);
			persistenceContext.RemoveEntity(key);
			persistenceContext.RemoveProxy(key);

			if (persister.HasCache)
				persister.Cache.Evict(ck);

			PostDelete();

			if (statsEnabled && !veto)
			{
				stopwatch.Stop();
				Session.Factory.StatisticsImplementor.DeleteEntity(Persister.EntityName, stopwatch.Elapsed);
			}
		}
Exemplo n.º 35
0
        public void DoTestCache(ICacheProvider cacheProvider)
        {
            ICache cache = cacheProvider.BuildCache(typeof(String).FullName, new Dictionary <string, string>());

            long longBefore = Timestamper.Next();

            Thread.Sleep(15);

            long before = Timestamper.Next();

            Thread.Sleep(15);

            ICacheConcurrencyStrategy ccs = new ReadWriteCache();

            ccs.Cache = cache;

            // cache something
            CacheKey fooKey = CreateCacheKey("foo");

            Assert.IsTrue(ccs.Put(fooKey, "foo", before, null, null, false));

            Thread.Sleep(15);

            long after = Timestamper.Next();

            Assert.IsNull(ccs.Get(fooKey, longBefore));
            Assert.AreEqual("foo", ccs.Get(fooKey, after));
            Assert.IsFalse(ccs.Put(fooKey, "foo", before, null, null, false));

            // update it;

            ISoftLock fooLock = ccs.Lock(fooKey, null);

            Assert.IsNull(ccs.Get(fooKey, after));
            Assert.IsNull(ccs.Get(fooKey, longBefore));
            Assert.IsFalse(ccs.Put(fooKey, "foo", before, null, null, false));

            Thread.Sleep(15);

            long whileLocked = Timestamper.Next();

            Assert.IsFalse(ccs.Put(fooKey, "foo", whileLocked, null, null, false));

            Thread.Sleep(15);

            ccs.Release(fooKey, fooLock);

            Assert.IsNull(ccs.Get(fooKey, after));
            Assert.IsNull(ccs.Get(fooKey, longBefore));
            Assert.IsFalse(ccs.Put(fooKey, "bar", whileLocked, null, null, false));
            Assert.IsFalse(ccs.Put(fooKey, "bar", after, null, null, false));

            Thread.Sleep(15);

            long longAfter = Timestamper.Next();

            Assert.IsTrue(ccs.Put(fooKey, "baz", longAfter, null, null, false));
            Assert.IsNull(ccs.Get(fooKey, after));
            Assert.IsNull(ccs.Get(fooKey, whileLocked));

            Thread.Sleep(15);

            long longLongAfter = Timestamper.Next();

            Assert.AreEqual("baz", ccs.Get(fooKey, longLongAfter));

            // update it again, with multiple locks

            ISoftLock fooLock1 = ccs.Lock(fooKey, null);
            ISoftLock fooLock2 = ccs.Lock(fooKey, null);

            Assert.IsNull(ccs.Get(fooKey, longLongAfter));

            Thread.Sleep(15);

            whileLocked = Timestamper.Next();

            Assert.IsFalse(ccs.Put(fooKey, "foo", whileLocked, null, null, false));

            Thread.Sleep(15);

            ccs.Release(fooKey, fooLock2);

            Thread.Sleep(15);

            long betweenReleases = Timestamper.Next();

            Assert.IsFalse(ccs.Put(fooKey, "bar", betweenReleases, null, null, false));
            Assert.IsNull(ccs.Get(fooKey, betweenReleases));

            Thread.Sleep(15);

            ccs.Release(fooKey, fooLock1);

            Assert.IsFalse(ccs.Put(fooKey, "bar", whileLocked, null, null, false));

            Thread.Sleep(15);

            longAfter = Timestamper.Next();

            Assert.IsTrue(ccs.Put(fooKey, "baz", longAfter, null, null, false));
            Assert.IsNull(ccs.Get(fooKey, whileLocked));

            Thread.Sleep(15);

            longLongAfter = Timestamper.Next();

            Assert.AreEqual("baz", ccs.Get(fooKey, longLongAfter));
        }
        public async Task DoTestCacheAsync(ICacheProvider cacheProvider, CancellationToken cancellationToken = default(CancellationToken))
        {
            ICache cache = cacheProvider.BuildCache(typeof(String).FullName, new Dictionary <string, string>());

            long longBefore = Timestamper.Next();

            await(Task.Delay(15, cancellationToken));

            long before = Timestamper.Next();

            await(Task.Delay(15, cancellationToken));

            ICacheConcurrencyStrategy ccs = new ReadWriteCache();

            ccs.Cache = cache;

            // cache something
            CacheKey fooKey = CreateCacheKey("foo");

            Assert.IsTrue(await(ccs.PutAsync(fooKey, "foo", before, null, null, false, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            long after = Timestamper.Next();

            Assert.IsNull(await(ccs.GetAsync(fooKey, longBefore, cancellationToken)));
            Assert.AreEqual("foo", await(ccs.GetAsync(fooKey, after, cancellationToken)));
            Assert.IsFalse(await(ccs.PutAsync(fooKey, "foo", before, null, null, false, cancellationToken)));

            // update it;

            ISoftLock fooLock = await(ccs.LockAsync(fooKey, null, cancellationToken));

            Assert.IsNull(await(ccs.GetAsync(fooKey, after, cancellationToken)));
            Assert.IsNull(await(ccs.GetAsync(fooKey, longBefore, cancellationToken)));
            Assert.IsFalse(await(ccs.PutAsync(fooKey, "foo", before, null, null, false, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            long whileLocked = Timestamper.Next();

            Assert.IsFalse(await(ccs.PutAsync(fooKey, "foo", whileLocked, null, null, false, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            await(ccs.ReleaseAsync(fooKey, fooLock, cancellationToken));

            Assert.IsNull(await(ccs.GetAsync(fooKey, after, cancellationToken)));
            Assert.IsNull(await(ccs.GetAsync(fooKey, longBefore, cancellationToken)));
            Assert.IsFalse(await(ccs.PutAsync(fooKey, "bar", whileLocked, null, null, false, cancellationToken)));
            Assert.IsFalse(await(ccs.PutAsync(fooKey, "bar", after, null, null, false, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            long longAfter = Timestamper.Next();

            Assert.IsTrue(await(ccs.PutAsync(fooKey, "baz", longAfter, null, null, false, cancellationToken)));
            Assert.IsNull(await(ccs.GetAsync(fooKey, after, cancellationToken)));
            Assert.IsNull(await(ccs.GetAsync(fooKey, whileLocked, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            long longLongAfter = Timestamper.Next();

            Assert.AreEqual("baz", await(ccs.GetAsync(fooKey, longLongAfter, cancellationToken)));

            // update it again, with multiple locks

            ISoftLock fooLock1 = await(ccs.LockAsync(fooKey, null, cancellationToken));
            ISoftLock fooLock2 = await(ccs.LockAsync(fooKey, null, cancellationToken));

            Assert.IsNull(await(ccs.GetAsync(fooKey, longLongAfter, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            whileLocked = Timestamper.Next();

            Assert.IsFalse(await(ccs.PutAsync(fooKey, "foo", whileLocked, null, null, false, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            await(ccs.ReleaseAsync(fooKey, fooLock2, cancellationToken));

            await(Task.Delay(15, cancellationToken));

            long betweenReleases = Timestamper.Next();

            Assert.IsFalse(await(ccs.PutAsync(fooKey, "bar", betweenReleases, null, null, false, cancellationToken)));
            Assert.IsNull(await(ccs.GetAsync(fooKey, betweenReleases, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            await(ccs.ReleaseAsync(fooKey, fooLock1, cancellationToken));

            Assert.IsFalse(await(ccs.PutAsync(fooKey, "bar", whileLocked, null, null, false, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            longAfter = Timestamper.Next();

            Assert.IsTrue(await(ccs.PutAsync(fooKey, "baz", longAfter, null, null, false, cancellationToken)));
            Assert.IsNull(await(ccs.GetAsync(fooKey, whileLocked, cancellationToken)));

            await(Task.Delay(15, cancellationToken));

            longLongAfter = Timestamper.Next();

            Assert.AreEqual("baz", await(ccs.GetAsync(fooKey, longLongAfter, cancellationToken)));
        }
Exemplo n.º 37
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(_asyncReaderWriterLock.WriteLockAsync()).ConfigureAwait(false))
            {
                if (log.IsDebugEnabled())
                {
                    log.Debug("Updating: {0}", key);
                }

                var lockValue = await(_cache.LockAsync(key, cancellationToken)).ConfigureAwait(false);
                try
                {
                    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, CachedItem.Create(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, lockValue, cancellationToken)).ConfigureAwait(false);
                }
            }
        }
		/// <summary>
		/// Invalidate the item (again, for safety).
		/// </summary>
		public void AfterUpdate(CacheKey key, object value, object version, ISoftLock @lock)
		{
			Release(key, @lock);
		}
		/// <summary>
		/// Unsupported!
		/// </summary>
		public bool AfterUpdate(CacheKey key, object value, object version, ISoftLock @lock)
		{
			log.Error("Application attempted to edit read only item: " + key);
			throw new InvalidOperationException("ReadOnlyCache: Can't write to a readonly object " + key.EntityOrRoleName);
		}
Exemplo n.º 40
0
		/// <summary>
		/// Unsupported!
		/// </summary>
		public void Release(CacheKey key, ISoftLock @lock)
		{
			log.Error("Application attempted to edit read only item: " + key);
			//throw new InvalidOperationException( "Can't write to a readonly object" );
		}
Exemplo n.º 41
0
        public override void Execute()
        {
            object              id        = Id;
            IEntityPersister    persister = Persister;
            ISessionImplementor session   = Session;
            object              instance  = Instance;

            bool      statsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            Stopwatch stopwatch    = null;

            if (statsEnabled)
            {
                stopwatch = Stopwatch.StartNew();
            }

            bool veto = PreDelete();

            object tmpVersion = version;

            if (persister.IsVersionPropertyGenerated)
            {
                // we need to grab the version value from the entity, otherwise
                // we have issues with generated-version entities that may have
                // multiple actions queued during the same flush
                tmpVersion = persister.GetVersion(instance, session.EntityMode);
            }

            CacheKey ck;

            if (persister.HasCache)
            {
                ck    = new CacheKey(id, persister.IdentifierType, persister.RootEntityName, session.EntityMode, session.Factory);
                sLock = persister.Cache.Lock(ck, version);
            }
            else
            {
                ck = null;
            }

            if (!isCascadeDeleteEnabled && !veto)
            {
                persister.Delete(id, tmpVersion, instance, session);
            }

            //postDelete:
            // After actually deleting a row, record the fact that the instance no longer
            // exists on the database (needed for identity-column key generation), and
            // remove it from the session cache
            IPersistenceContext persistenceContext = session.PersistenceContext;

            EntityEntry entry = persistenceContext.RemoveEntry(instance);

            if (entry == null)
            {
                throw new AssertionFailure("Possible nonthreadsafe access to session");
            }
            entry.PostDelete();

            EntityKey key = new EntityKey(entry.Id, entry.Persister, session.EntityMode);

            persistenceContext.RemoveEntity(key);
            persistenceContext.RemoveProxy(key);

            if (persister.HasCache)
            {
                persister.Cache.Evict(ck);
            }

            PostDelete();

            if (statsEnabled && !veto)
            {
                stopwatch.Stop();
                Session.Factory.StatisticsImplementor.DeleteEntity(Persister.EntityName, stopwatch.Elapsed);
            }
        }
		/// <summary>
		/// Unsupported!
		/// </summary>
		public void Release(CacheKey key, ISoftLock @lock)
		{
			log.Error("Application attempted to edit read only item: " + key);
		}
Exemplo n.º 43
0
 /// <summary>
 /// Unsupported!
 /// </summary>
 public Task <bool> AfterUpdateAsync(CacheKey key, object value, object version, ISoftLock @lock, CancellationToken cancellationToken)
 {
     if (cancellationToken.IsCancellationRequested)
     {
         return(Task.FromCanceled <bool>(cancellationToken));
     }
     try
     {
         return(Task.FromResult <bool>(AfterUpdate(key, value, version, @lock)));
     }
     catch (Exception ex)
     {
         return(Task.FromException <bool>(ex));
     }
 }
Exemplo n.º 44
0
 /// <summary>
 /// Invalidate the item (again, for safety).
 /// </summary>
 /// <param name="key"></param>
 /// <param name="value"></param>
 /// <param name="version"></param>
 /// <param name="lock"></param>
 public void AfterUpdate(object key, object value, object version, ISoftLock @lock)
 {
     Release(key, @lock);
 }