public bool Put(QueryKey key, ICacheAssembler[] returnTypes, IList result, bool isNaturalKeyLookup, ISessionImplementor session)
		{
			if (isNaturalKeyLookup && result.Count == 0)
				return false;

			long ts = session.Timestamp;

			if (Log.IsDebugEnabled)
				Log.DebugFormat("caching query results in region: '{0}'; {1}", _regionName, key);

			IList cacheable = new List<object>(result.Count + 1) {ts};
			for (int i = 0; i < result.Count; i++)
			{
				if (returnTypes.Length == 1 && !key.HasResultTransformer)
				{
					cacheable.Add(returnTypes[0].Disassemble(result[i], session, null));
				}
				else
				{
					cacheable.Add(TypeHelper.Disassemble((object[]) result[i], returnTypes, null, session, null));
				}
			}

			_queryCache.Put(key, cacheable);

			return true;
		}
Exemplo n.º 2
0
		public IList Get(QueryKey key, ICacheAssembler[] returnTypes, Iesi.Collections.Generic.ISet<string> spaces, ISessionImplementor session)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug("checking cached query results in region: " + regionName);
			}
			IList cacheable = (IList) queryCache.Get(key);
			if (cacheable == null)
			{
				log.Debug("query results were not found in cache");
				return null;
			}
			IList result = new ArrayList(cacheable.Count - 1);
			long timestamp = (long) cacheable[0];
			log.Debug("Checking query spaces for up-to-dateness [" + spaces + "]");
			if (! IsUpToDate(spaces, timestamp))
			{
				log.Debug("cached query results were not up to date");
				return null;
			}
			log.Debug("returning cached query results");
			for (int i = 1; i < cacheable.Count; i++)
			{
				if (returnTypes.Length == 1)
				{
					result.Add(returnTypes[0].Assemble(cacheable[i], session, null));
				}
				else
				{
					result.Add(TypeFactory.Assemble((object[]) cacheable[i], returnTypes, session, null));
				}
			}
			return result;
		}
Exemplo n.º 3
0
        bool IQueryCache.Put(QueryKey key, ICacheAssembler[] returnTypes, IList result, bool isNaturalKeyLookup, ISessionImplementor session)
        {
            //if the returntypes contains simple values, assume it's a projection:
            if (returnTypes.OfType<IType>().Any(t => t.ReturnedClass != null && (t.ReturnedClass.IsValueType || t.ReturnedClass.IsPrimitive || t.ReturnedClass == typeof(String))))
                return false;

            return this.Put(key, returnTypes, result, isNaturalKeyLookup, session);
        }
Exemplo n.º 4
0
		/// <summary>
		/// Apply the <see cref="ICacheAssembler.Assemble" /> operation across a series of values.
		/// </summary>
		/// <param name="row">The values</param>
		/// <param name="types">The value types</param>
		/// <param name="session">The originating session</param>
		/// <param name="owner">The entity "owning" the values</param>
		/// <returns></returns>
		public static object[] Assemble(object[] row, ICacheAssembler[] types, ISessionImplementor session, object owner)
		{
			object[] assembled = new object[row.Length];
			for (int i = 0; i < row.Length; i++)
			{
				assembled[i] = types[i].Assemble(row[i], session, owner);
			}
			return assembled;
		}
Exemplo n.º 5
0
		/// <summary>Apply the <see cref="ICacheAssembler.BeforeAssemble" /> operation across a series of values.</summary>
		/// <param name="row">The values</param>
		/// <param name="types">The value types</param>
		/// <param name="session">The originating session</param>
		public static void BeforeAssemble(object[] row, ICacheAssembler[] types, ISessionImplementor session)
		{
			for (int i = 0; i < types.Length; i++)
			{
				if (row[i] != LazyPropertyInitializer.UnfetchedProperty && row[i] != BackrefPropertyAccessor.Unknown)
				{
					types[i].BeforeAssemble(row[i], session);
				}
			}
		}
        private static ICacheAssembler[] GuessTypes(IList cacheable)
        {
            var firstRow    = cacheable[0];
            var colCount    = (cacheable[0] as object[])?.Length ?? 1;
            var returnTypes = new ICacheAssembler[colCount];

            if (colCount == 1)
            {
                foreach (var obj in cacheable)
                {
                    if (obj == null)
                    {
                        continue;
                    }
                    returnTypes[0] = NHibernateUtil.GuessType(obj);
                    break;
                }
            }
            else
            {
                var foundTypes = 0;
                foreach (object[] row in cacheable)
                {
                    for (var i = 0; i < colCount; i++)
                    {
                        if (row[i] != null && returnTypes[i] == null)
                        {
                            returnTypes[i] = NHibernateUtil.GuessType(row[i]);
                            foundTypes++;
                        }
                    }
                    if (foundTypes == colCount)
                    {
                        break;
                    }
                }
            }
            // If a column value was null for all rows, its type is still null: put a type which will just yield null
            // on null value.
            for (var i = 0; i < colCount; i++)
            {
                if (returnTypes[i] == null)
                {
                    returnTypes[i] = NHibernateUtil.String;
                }
            }
            return(returnTypes);
        }
		/// <summary>
		/// Apply the <see cref="ICacheAssembler.Assemble" /> operation across a series of values.
		/// </summary>
		/// <param name="row">The values</param>
		/// <param name="types">The value types</param>
		/// <param name="session">The originating session</param>
		/// <param name="owner">The entity "owning" the values</param>
		/// <returns></returns>
		public static object[] Assemble(object[] row, ICacheAssembler[] types, ISessionImplementor session, object owner)
		{
			var assembled = new object[row.Length];
			for (int i = 0; i < row.Length; i++)
			{
				if (row[i] == LazyPropertyInitializer.UnfetchedProperty || row[i] == BackrefPropertyAccessor.Unknown)
				{
					assembled[i] = row[i];
				}
				else
				{
					assembled[i] = types[i].Assemble(row[i], session, owner);
				}
			}
			return assembled;
		}
Exemplo n.º 8
0
        private async Task GetCachedResultsAsync(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            var statisticsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            var queriesByCaches   = GetQueriesByCaches(ci => ci.CanGetFromCache);

            foreach (var queriesByCache in queriesByCaches)
            {
                var queryInfos  = queriesByCache.ToArray();
                var cache       = queriesByCache.Key;
                var keys        = new QueryKey[queryInfos.Length];
                var parameters  = new QueryParameters[queryInfos.Length];
                var returnTypes = new ICacheAssembler[queryInfos.Length][];
                var spaces      = new ISet <string> [queryInfos.Length];
                for (var i = 0; i < queryInfos.Length; i++)
                {
                    var queryInfo = queryInfos[i];
                    keys[i]        = queryInfo.CacheKey;
                    parameters[i]  = queryInfo.Parameters;
                    returnTypes[i] = queryInfo.Parameters.HasAutoDiscoverScalarTypes
                                                ? null
                                                : queryInfo.CacheKey.ResultTransformer.GetCachedResultTypes(queryInfo.GetCacheTypes());
                    spaces[i] = queryInfo.QuerySpaces;
                }

                var results = await(cache.GetManyAsync(keys, parameters, returnTypes, spaces, Session, cancellationToken)).ConfigureAwait(false);

                for (var i = 0; i < queryInfos.Length; i++)
                {
                    var queryInfo = queryInfos[i];
                    queryInfo.SetCachedResult(results[i]);

                    if (statisticsEnabled)
                    {
                        var queryIdentifier = queryInfo.QueryIdentifier;
                        if (results[i] == null)
                        {
                            Session.Factory.StatisticsImplementor.QueryCacheMiss(queryIdentifier, cache.RegionName);
                        }
                        else
                        {
                            Session.Factory.StatisticsImplementor.QueryCacheHit(queryIdentifier, cache.RegionName);
                        }
                    }
                }
            }
        }
Exemplo n.º 9
0
        private void GetCachedResults()
        {
            var statisticsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            var queriesByCaches   = GetQueriesByCaches(ci => ci.CanGetFromCache);

            foreach (var queriesByCache in queriesByCaches)
            {
                var queryInfos  = queriesByCache.ToArray();
                var cache       = queriesByCache.Key;
                var keys        = new QueryKey[queryInfos.Length];
                var parameters  = new QueryParameters[queryInfos.Length];
                var returnTypes = new ICacheAssembler[queryInfos.Length][];
                var spaces      = new ISet <string> [queryInfos.Length];
                for (var i = 0; i < queryInfos.Length; i++)
                {
                    var queryInfo = queryInfos[i];
                    keys[i]        = queryInfo.CacheKey;
                    parameters[i]  = queryInfo.Parameters;
                    returnTypes[i] = queryInfo.Parameters.HasAutoDiscoverScalarTypes
                                                ? null
                                                : queryInfo.CacheKey.ResultTransformer.GetCachedResultTypes(queryInfo.ResultTypes);
                    spaces[i] = queryInfo.QuerySpaces;
                }

                var results = cache.GetMany(keys, parameters, returnTypes, spaces, Session);

                for (var i = 0; i < queryInfos.Length; i++)
                {
                    queryInfos[i].SetCachedResult(results[i]);

                    if (statisticsEnabled)
                    {
                        var queryIdentifier = queryInfos[i].QueryIdentifier;
                        if (results[i] == null)
                        {
                            Session.Factory.StatisticsImplementor.QueryCacheMiss(queryIdentifier, cache.RegionName);
                        }
                        else
                        {
                            Session.Factory.StatisticsImplementor.QueryCacheHit(queryIdentifier, cache.RegionName);
                        }
                    }
                }
            }
        }
Exemplo n.º 10
0
		/// <summary>Apply the <see cref="ICacheAssembler.Disassemble" /> operation across a series of values.</summary>
		/// <param name="row">The values</param>
		/// <param name="types">The value types</param>
		/// <param name="nonCacheable">An array indicating which values to include in the disassembled state</param>
		/// <param name="session">The originating session</param>
		/// <param name="owner">The entity "owning" the values</param>
		/// <returns> The disassembled state</returns>
		public static object[] Disassemble(object[] row, ICacheAssembler[] types, bool[] nonCacheable, ISessionImplementor session, object owner)
		{
			object[] disassembled = new object[row.Length];
			for (int i = 0; i < row.Length; i++)
			{
				if (nonCacheable != null && nonCacheable[i])
				{
					disassembled[i] = LazyPropertyInitializer.UnfetchedProperty;
				}
				else if (row[i] == LazyPropertyInitializer.UnfetchedProperty || row[i] == BackrefPropertyAccessor.Unknown)
				{
					disassembled[i] = row[i];
				}
				else
				{
					disassembled[i] = types[i].Disassemble(row[i], session, owner);
				}
			}
			return disassembled;
		}
		public void Put(QueryKey key, ICacheAssembler[] returnTypes, IList result, ISessionImplementor session)
		{
			if (log.IsDebugEnabled)
			{
				log.Debug("caching query results in region: " + regionName);
			}
			IList cacheable = new ArrayList(result.Count + 1);
			cacheable.Add(session.Timestamp);
			for (int i = 0; i < result.Count; i++)
			{
				if (returnTypes.Length == 1)
				{
					cacheable.Add(returnTypes[0].Disassemble(result[i], session));
				}
				else
				{
					cacheable.Add(TypeFactory.Disassemble((object[]) result[i], returnTypes, session));
				}
			}
			queryCache.Put(key, cacheable);
		}
Exemplo n.º 12
0
        private async Task PutCacheableResultsAsync(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            var statisticsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            var queriesByCaches   = GetQueriesByCaches(ci => ci.ResultToCache != null);

            foreach (var queriesByCache in queriesByCaches)
            {
                var queryInfos  = queriesByCache.ToArray();
                var cache       = queriesByCache.Key;
                var keys        = new QueryKey[queryInfos.Length];
                var parameters  = new QueryParameters[queryInfos.Length];
                var returnTypes = new ICacheAssembler[queryInfos.Length][];
                var results     = new IList[queryInfos.Length];
                for (var i = 0; i < queryInfos.Length; i++)
                {
                    var queryInfo = queryInfos[i];
                    keys[i]        = queryInfo.CacheKey;
                    parameters[i]  = queryInfo.Parameters;
                    returnTypes[i] = queryInfo.CacheKey.ResultTransformer.GetCachedResultTypes(queryInfo.GetCacheTypes());
                    results[i]     = queryInfo.ResultToCache;
                }

                var putted = await(cache.PutManyAsync(keys, parameters, returnTypes, results, Session, cancellationToken)).ConfigureAwait(false);

                if (!statisticsEnabled)
                {
                    continue;
                }

                for (var i = 0; i < queryInfos.Length; i++)
                {
                    if (putted[i])
                    {
                        Session.Factory.StatisticsImplementor.QueryCachePut(
                            queryInfos[i].QueryIdentifier, cache.RegionName);
                    }
                }
            }
        }
Exemplo n.º 13
0
        private void PutCacheableResults()
        {
            var statisticsEnabled = Session.Factory.Statistics.IsStatisticsEnabled;
            var queriesByCaches   = GetQueriesByCaches(ci => ci.ResultToCache != null);

            foreach (var queriesByCache in queriesByCaches)
            {
                var queryInfos  = queriesByCache.ToArray();
                var cache       = queriesByCache.Key;
                var keys        = new QueryKey[queryInfos.Length];
                var parameters  = new QueryParameters[queryInfos.Length];
                var returnTypes = new ICacheAssembler[queryInfos.Length][];
                var results     = new IList[queryInfos.Length];
                for (var i = 0; i < queryInfos.Length; i++)
                {
                    var queryInfo = queryInfos[i];
                    keys[i]        = queryInfo.CacheKey;
                    parameters[i]  = queryInfo.Parameters;
                    returnTypes[i] = queryInfo.CacheKey.ResultTransformer.GetCachedResultTypes(queryInfo.GetCacheTypes());
                    results[i]     = queryInfo.ResultToCache;
                }

                var putted = cache.PutMany(keys, parameters, returnTypes, results, Session);

                if (!statisticsEnabled)
                {
                    continue;
                }

                for (var i = 0; i < queryInfos.Length; i++)
                {
                    if (putted[i])
                    {
                        Session.Factory.StatisticsImplementor.QueryCachePut(
                            queryInfos[i].QueryIdentifier, cache.RegionName);
                    }
                }
            }
        }
Exemplo n.º 14
0
		public IList Get(QueryKey key, ICacheAssembler[] returnTypes, bool isNaturalKeyLookup, Iesi.Collections.Generic.ISet<string> spaces,
		                 ISessionImplementor session)
		{
			if (Log.IsDebugEnabled)
				Log.DebugFormat("checking cached query results in region: '{0}'; {1}", _regionName, key);

			var cacheable = (IList)_queryCache.Get(key);
			if (cacheable == null)
			{
				Log.DebugFormat("query results were not found in cache: {0}", key);
				return null;
			}

			var timestamp = (long)cacheable[0];

			if (Log.IsDebugEnabled)
				Log.DebugFormat("Checking query spaces for up-to-dateness [{0}]", StringHelper.CollectionToString((ICollection)spaces));

			if (!isNaturalKeyLookup && !IsUpToDate(spaces, timestamp))
			{
				Log.DebugFormat("cached query results were not up to date for: {0}", key);
				return null;
			}

			Log.DebugFormat("returning cached query results for: {0}", key);
			for (int i = 1; i < cacheable.Count; i++)
			{
				if (returnTypes.Length == 1 && !key.HasResultTransformer)
				{
					returnTypes[0].BeforeAssemble(cacheable[i], session);
				}
				else
				{
					TypeHelper.BeforeAssemble((object[])cacheable[i], returnTypes, session);
				}
			}

			IList result = new List<object>(cacheable.Count - 1);
			for (int i = 1; i < cacheable.Count; i++)
			{
				try
				{
					if (returnTypes.Length == 1 && !key.HasResultTransformer)
					{
						result.Add(returnTypes[0].Assemble(cacheable[i], session, null));
					}
					else
					{
						result.Add(TypeHelper.Assemble((object[])cacheable[i], returnTypes, session, null));
					}
				}
				catch (UnresolvableObjectException)
				{
					if (isNaturalKeyLookup)
					{
						//TODO: not really completely correct, since
						//      the UnresolvableObjectException could occur while resolving
						//      associations, leaving the PC in an inconsistent state
						Log.Debug("could not reassemble cached result set");
						_queryCache.Remove(key);
						return null;
					}

					throw;
				}
			}

			return result;
		}
        /// <inheritdoc />
        public async Task <IList[]> GetManyAsync(
            QueryKey[] keys,
            QueryParameters[] queryParameters,
            ICacheAssembler[][] returnTypes,
            ISet <string>[] spaces,
            ISessionImplementor session, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            if (Log.IsDebugEnabled())
            {
                Log.Debug("checking cached query results in region: '{0}'; {1}", _regionName, StringHelper.CollectionToString(keys));
            }

            var cacheables = (await(_cache.GetManyAsync(keys, cancellationToken)).ConfigureAwait(false)).Cast <IList>().ToArray();

            var spacesToCheck          = new List <ISet <string> >();
            var checkedSpacesIndexes   = new HashSet <int>();
            var checkedSpacesTimestamp = new List <long>();

            for (var i = 0; i < keys.Length; i++)
            {
                var cacheable = cacheables[i];
                if (cacheable == null)
                {
                    Log.Debug("query results were not found in cache: {0}", keys[i]);
                    continue;
                }

                var querySpaces = spaces[i];
                if (queryParameters[i].NaturalKeyLookup || querySpaces.Count == 0)
                {
                    continue;
                }

                spacesToCheck.Add(querySpaces);
                checkedSpacesIndexes.Add(i);
                // The timestamp is the first element of the cache result.
                checkedSpacesTimestamp.Add((long)cacheable[0]);
                if (Log.IsDebugEnabled())
                {
                    Log.Debug("Checking query spaces for up-to-dateness [{0}]", StringHelper.CollectionToString(querySpaces));
                }
            }

            var upToDates = spacesToCheck.Count > 0
                                ? await(_updateTimestampsCache.AreUpToDateAsync(spacesToCheck.ToArray(), checkedSpacesTimestamp.ToArray(), cancellationToken)).ConfigureAwait(false)
                                : Array.Empty <bool>();

            var upToDatesIndex      = 0;
            var persistenceContext  = session.PersistenceContext;
            var defaultReadOnlyOrig = persistenceContext.DefaultReadOnly;
            var results             = new IList[keys.Length];
            var finalReturnTypes    = new ICacheAssembler[keys.Length][];

            try
            {
                session.PersistenceContext.BatchFetchQueue.InitializeQueryCacheQueue();

                for (var i = 0; i < keys.Length; i++)
                {
                    var cacheable = cacheables[i];
                    if (cacheable == null)
                    {
                        continue;
                    }

                    var key = keys[i];
                    if (checkedSpacesIndexes.Contains(i) && !upToDates[upToDatesIndex++])
                    {
                        Log.Debug("cached query results were not up to date for: {0}", key);
                        continue;
                    }

                    var queryParams = queryParameters[i];
                    if (queryParams.IsReadOnlyInitialized)
                    {
                        persistenceContext.DefaultReadOnly = queryParams.ReadOnly;
                    }
                    else
                    {
                        queryParams.ReadOnly = persistenceContext.DefaultReadOnly;
                    }

                    Log.Debug("returning cached query results for: {0}", key);

                    finalReturnTypes[i] = GetReturnTypes(key, returnTypes[i], cacheable);
                    await(PerformBeforeAssembleAsync(finalReturnTypes[i], session, cacheable, cancellationToken)).ConfigureAwait(false);
                }

                for (var i = 0; i < keys.Length; i++)
                {
                    if (finalReturnTypes[i] == null)
                    {
                        continue;
                    }

                    var queryParams = queryParameters[i];
                    // Adjust the session cache mode, as PerformAssemble assemble types which may cause
                    // entity loads, which may interact with the cache.
                    using (session.SwitchCacheMode(queryParams.CacheMode))
                    {
                        try
                        {
                            results[i] = await(PerformAssembleAsync(keys[i], finalReturnTypes[i], queryParams.NaturalKeyLookup, session, cacheables[i], cancellationToken)).ConfigureAwait(false);
                        }
                        finally
                        {
                            persistenceContext.DefaultReadOnly = defaultReadOnlyOrig;
                        }
                    }
                }

                for (var i = 0; i < keys.Length; i++)
                {
                    if (finalReturnTypes[i] == null)
                    {
                        continue;
                    }

                    var queryParams = queryParameters[i];
                    // Adjust the session cache mode, as InitializeCollections will initialize collections,
                    // which may interact with the cache.
                    using (session.SwitchCacheMode(queryParams.CacheMode))
                    {
                        try
                        {
                            await(InitializeCollectionsAsync(finalReturnTypes[i], session, results[i], cacheables[i], cancellationToken)).ConfigureAwait(false);
                        }
                        finally
                        {
                            persistenceContext.DefaultReadOnly = defaultReadOnlyOrig;
                        }
                    }
                }
            }
            finally
            {
                session.PersistenceContext.BatchFetchQueue.TerminateQueryCacheQueue();
            }

            return(results);
        }