コード例 #1
0
        public Task <IOrleansQueryResult <V> > Lookup(K key)
        {
            logger.Trace($"Eager index lookup called for key = {key}");

            BucketT targetBucket = GetGrain(IndexUtils.GetIndexGrainPrimaryKey(typeof(V), this._indexName) + "_" + GetBucketIndexFromHashCode(key));

            return(targetBucket.Lookup(key));
        }
コード例 #2
0
        public async Task <bool> DirectApplyIndexUpdateBatch(Immutable <IDictionary <IIndexableGrain, IList <IMemberUpdate> > > iUpdates, bool isUnique, IndexMetaData idxMetaData, SiloAddress siloAddress = null)
        {
            logger.Trace($"Started calling DirectApplyIndexUpdateBatch with the following parameters: isUnique = {isUnique}, siloAddress = {siloAddress}," +
                         $" iUpdates = {MemberUpdate.UpdatesToString(iUpdates.Value)}");

            IDictionary <IIndexableGrain, IList <IMemberUpdate> > updates = iUpdates.Value;
            IDictionary <int, IDictionary <IIndexableGrain, IList <IMemberUpdate> > > bucketUpdates = new Dictionary <int, IDictionary <IIndexableGrain, IList <IMemberUpdate> > >();

            foreach (var kv in updates)
            {
                IIndexableGrain       g        = kv.Key;
                IList <IMemberUpdate> gUpdates = kv.Value;
                foreach (IMemberUpdate update in gUpdates)
                {
                    IndexOperationType opType = update.OperationType;
                    if (opType == IndexOperationType.Update)
                    {
                        int befImgHash = GetBucketIndexFromHashCode(update.GetBeforeImage());
                        int aftImgHash = GetBucketIndexFromHashCode(update.GetAfterImage());

                        if (befImgHash == aftImgHash)
                        {
                            AddUpdateToBucket(bucketUpdates, g, befImgHash, update);
                        }
                        else
                        {
                            AddUpdateToBucket(bucketUpdates, g, befImgHash, new MemberUpdateOverridenOperation(update, IndexOperationType.Delete));
                            AddUpdateToBucket(bucketUpdates, g, aftImgHash, new MemberUpdateOverridenOperation(update, IndexOperationType.Insert));
                        }
                    }
                    else if (opType == IndexOperationType.Insert)
                    {
                        int aftImgHash = GetBucketIndexFromHashCode(update.GetAfterImage());
                        AddUpdateToBucket(bucketUpdates, g, aftImgHash, update);
                    }
                    else if (opType == IndexOperationType.Delete)
                    {
                        int befImgHash = GetBucketIndexFromHashCode(update.GetBeforeImage());
                        AddUpdateToBucket(bucketUpdates, g, befImgHash, update);
                    }
                }
            }

            var results = await Task.WhenAll(bucketUpdates.Select(kv =>
            {
                BucketT bucket = GetGrain(IndexUtils.GetIndexGrainPrimaryKey(typeof(V), this._indexName) + "_" + kv.Key);
                return(bucket.DirectApplyIndexUpdateBatch(kv.Value.AsImmutable(), isUnique, idxMetaData, siloAddress));
            }));

            logger.Trace($"Finished calling DirectApplyIndexUpdateBatch with the following parameters: isUnique = {isUnique}, siloAddress = {siloAddress}," +
                         $" iUpdates = {MemberUpdate.UpdatesToString(iUpdates.Value)}, results = '{string.Join(", ", results)}'");

            return(true);
        }
コード例 #3
0
        /// <summary>
        /// This is a helper method for creating an index on a field of an actor.
        /// </summary>
        /// <param name="idxType">The type of index to be created</param>
        /// <param name="indexName">The index name to be created</param>
        /// <param name="isUniqueIndex">Determines whether this is a unique index that needs to be created</param>
        /// <param name="isEager">Determines whether updates to this index should be applied eagerly or not</param>
        /// <param name="maxEntriesPerBucket">Determines the maximum number of entries in
        /// each bucket of a distributed index, if this index type is a distributed one.</param>
        /// <param name="indexedProperty">the PropertyInfo object for the indexed field.
        /// This object helps in creating a default instance of IndexUpdateGenerator.</param>
        /// <returns>An <see cref="IndexInfo"/> for the specified idxType and indexName.</returns>
        internal IndexInfo CreateIndex(Type idxType, string indexName, bool isUniqueIndex, bool isEager, int maxEntriesPerBucket, PropertyInfo indexedProperty)
        {
            ValidateIndexType(idxType, indexedProperty, out var iIndexGenericType, out var grainInterfaceType);

            // This must call the static Silo(IndexManager) methods because we may not be in the silo.
            var index = typeof(IGrain).IsAssignableFrom(idxType)
                ? (IIndexInterface)this.grainFactory.GetGrain(idxType, IndexUtils.GetIndexGrainPrimaryKey(grainInterfaceType, indexName))
                : idxType.IsClass
                    ? (IIndexInterface)Activator.CreateInstance(idxType, this.indexManager.ServiceProvider, indexName, isUniqueIndex)
                    : throw new IndexException(string.Format("{0} is neither a grain nor a class. Index \"{1}\" cannot be created.", idxType, indexName));

            return(new IndexInfo(index, new IndexMetaData(idxType, indexName, isUniqueIndex, isEager, maxEntriesPerBucket), CreateIndexUpdateGenFromProperty(indexedProperty)));
        }
コード例 #4
0
        /// <summary>
        /// This is a helper method for creating an index on a field of an actor.
        /// </summary>
        /// <param name="idxType">The type of index to be created</param>
        /// <param name="indexName">The index name to be created</param>
        /// <param name="isUniqueIndex">Determines whether this is a unique index that needs to be created</param>
        /// <param name="isEager">Determines whether updates to this index should be applied eagerly or not</param>
        /// <param name="maxEntriesPerBucket">Determines the maximum number of entries in
        /// each bucket of a distributed index, if this index type is a distributed one.</param>
        /// <param name="indexedProperty">the PropertyInfo object for the indexed field.
        /// This object helps in creating a default instance of IndexUpdateGenerator.</param>
        /// <returns>An <see cref="IndexInfo"/> for the specified idxType and indexName.</returns>
        internal async Task <IndexInfo> CreateIndex(Type idxType, string indexName, bool isUniqueIndex, bool isEager, int maxEntriesPerBucket, PropertyInfo indexedProperty)
        {
            Type iIndexType = idxType.GetGenericType(typeof(IIndexInterface <,>));

            if (iIndexType == null)
            {
                throw new NotSupportedException(string.Format("Adding an index that does not implement IndexInterface<K,V> is not supported yet. Your requested index ({0}) is invalid.", idxType.ToString()));
            }

            Type[] indexTypeArgs = iIndexType.GetGenericArguments();
            Type   keyType       = indexTypeArgs[0];
            Type   grainType     = indexTypeArgs[1];

            IIndexInterface index;

            if (typeof(IGrain).IsAssignableFrom(idxType))
            {
                // This must call the static Silo methods because we may not be InSilo.
                index = (IIndexInterface)Silo.GetGrain(this.grainFactory, IndexUtils.GetIndexGrainPrimaryKey(grainType, indexName), idxType, idxType);

                if (this.IsInSilo)
                {
                    var idxImplType = this.indexManager.CachedTypeResolver.ResolveType(
                        TypeCodeMapper.GetImplementation(this.siloIndexManager.GrainTypeResolver, idxType).GrainClass);
                    if (idxImplType.IsGenericTypeDefinition)
                    {
                        idxImplType = idxImplType.MakeGenericType(iIndexType.GetGenericArguments());
                    }

                    var initPerSiloMethodInfo = idxImplType.GetMethod("InitPerSilo", BindingFlags.Static | BindingFlags.NonPublic);
                    if (initPerSiloMethodInfo != null)  // Static method so cannot use an interface
                    {
                        var initPerSiloMethod = (Func <SiloIndexManager, string, bool, Task>)Delegate.CreateDelegate(typeof(Func <SiloIndexManager, string, bool, Task>), initPerSiloMethodInfo);
                        await initPerSiloMethod(this.siloIndexManager, indexName, isUniqueIndex);
                    }
                }
            }
            else
            {
                index = idxType.IsClass
                    ? (IIndexInterface)Activator.CreateInstance(idxType, this.indexManager.ServiceProvider, indexName, isUniqueIndex)
                    : throw new IndexException(string.Format("{0} is neither a grain nor a class. Index \"{1}\" cannot be created.", idxType, indexName));
            }

            return(new IndexInfo(index, new IndexMetaData(idxType, isUniqueIndex, isEager, maxEntriesPerBucket), CreateIndexUpdateGenFromProperty(indexedProperty)));
        }
コード例 #5
0
        public async Task <bool> DirectApplyIndexUpdate(IIndexableGrain g, Immutable <IMemberUpdate> iUpdate, bool isUniqueIndex, IndexMetaData idxMetaData, SiloAddress siloAddress)
        {
            IMemberUpdate      update = iUpdate.Value;
            IndexOperationType opType = update.OperationType;

            if (opType == IndexOperationType.Update)
            {
                int     befImgHash   = GetBucketIndexFromHashCode(update.GetBeforeImage());
                int     aftImgHash   = GetBucketIndexFromHashCode(update.GetAfterImage());
                BucketT befImgBucket = GetGrain(IndexUtils.GetIndexGrainPrimaryKey(typeof(V), this._indexName) + "_" + befImgHash);
                if (befImgHash == aftImgHash)
                {
                    return(await befImgBucket.DirectApplyIndexUpdate(g, iUpdate, isUniqueIndex, idxMetaData));
                }

                BucketT aftImgBucket = GetGrain(IndexUtils.GetIndexGrainPrimaryKey(typeof(V), this._indexName) + "_" + aftImgHash);
                var     befTask      = befImgBucket.DirectApplyIndexUpdate(g, new MemberUpdateOverridenOperation(iUpdate.Value, IndexOperationType.Delete).AsImmutable <IMemberUpdate>(), isUniqueIndex, idxMetaData);
                var     aftTask      = aftImgBucket.DirectApplyIndexUpdate(g, new MemberUpdateOverridenOperation(iUpdate.Value, IndexOperationType.Insert).AsImmutable <IMemberUpdate>(), isUniqueIndex, idxMetaData);
                bool[]  results      = await Task.WhenAll(befTask, aftTask);

                return(results[0] && results[1]);
            }
            else if (opType == IndexOperationType.Insert)
            {
                int     aftImgHash   = GetBucketIndexFromHashCode(update.GetAfterImage());
                BucketT aftImgBucket = GetGrain(IndexUtils.GetIndexGrainPrimaryKey(typeof(V), this._indexName) + "_" + aftImgHash);
                return(await aftImgBucket.DirectApplyIndexUpdate(g, iUpdate, isUniqueIndex, idxMetaData));
            }
            else if (opType == IndexOperationType.Delete)
            {
                int     befImgHash   = GetBucketIndexFromHashCode(update.GetBeforeImage());
                BucketT befImgBucket = GetGrain(IndexUtils.GetIndexGrainPrimaryKey(typeof(V), this._indexName) + "_" + befImgHash);
                return(await befImgBucket.DirectApplyIndexUpdate(g, iUpdate, isUniqueIndex, idxMetaData));
            }
            return(true);
        }
コード例 #6
0
 private static GrainReference GetAHashIndexPartitionedPerSiloGrainReference(SiloIndexManager siloIndexManager, string indexName, Type grainInterfaceType, SiloAddress siloAddress)
 => siloIndexManager.MakeGrainServiceGrainReference(IndexingConstants.HASH_INDEX_PARTITIONED_PER_SILO_BUCKET_GRAIN_SERVICE_TYPE_CODE,
                                                    IndexUtils.GetIndexGrainPrimaryKey(grainInterfaceType, indexName), siloAddress);
コード例 #7
0
        public override async Task ObserveResults(IAsyncBatchObserver <TIGrain> observer)
        {
            IIndexInterface        index        = base.IndexFactory.GetIndex(typeof(TIGrain), this._indexName);
            IAsyncStream <TIGrain> resultStream = base.StreamProvider.GetStream <TIGrain>(Guid.NewGuid(), IndexUtils.GetIndexGrainPrimaryKey(typeof(TIGrain), this._indexName));

            IOrleansQueryResultStream <TIGrain> result = new OrleansQueryResultStream <TIGrain>(resultStream);

            //the observer is attached to the query result
            await result.SubscribeAsync(observer);

            //the actual lookup for the query result to be streamed to the observer
            var castResult = result.Cast <IIndexableGrain>();

            await(index is ITransactionalLookupIndex transactionalLookupIndex
                                                                ? transactionalLookupIndex.LookupTransactionalAsync(castResult, this._param)
                                                                : index.LookupAsync(castResult, this._param));
        }
 private static GrainReference GetGrainReference(SiloIndexManager siloIndexManager, string indexName, SiloAddress siloAddress = null)
 => siloIndexManager.MakeGrainServiceGrainReference(IndexingConstants.HASH_INDEX_PARTITIONED_PER_SILO_BUCKET_GRAIN_SERVICE_TYPE_CODE,
                                                    IndexUtils.GetIndexGrainPrimaryKey(typeof(V), indexName), siloAddress ?? siloIndexManager.SiloAddress);
コード例 #9
0
        private BucketT GetBucketGrain(int keyValueHash)
        {
            var bucketPrimaryKey = IndexUtils.GetIndexGrainPrimaryKey(typeof(V), this._indexName) + "_" + keyValueHash;

            return(this.indexManager.GrainFactory.GetGrain <BucketT>(bucketPrimaryKey));
        }