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)); }
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); }
/// <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))); }
/// <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))); }
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); }
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);
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);
private BucketT GetBucketGrain(int keyValueHash) { var bucketPrimaryKey = IndexUtils.GetIndexGrainPrimaryKey(typeof(V), this._indexName) + "_" + keyValueHash; return(this.indexManager.GrainFactory.GetGrain <BucketT>(bucketPrimaryKey)); }