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); }
public async Task <bool> DirectApplyIndexUpdateBatch(Immutable <IDictionary <IIndexableGrain, IList <IMemberUpdate> > > iUpdates, bool isUnique, IndexMetaData idxMetaData, SiloAddress siloAddress = null) { if (logger.IsVerbose) { logger.Verbose("Started calling DirectApplyIndexUpdateBatch with the following parameters: isUnique = {0}, siloAddress = {1}, iUpdates = {2}", isUnique, siloAddress, 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.GetOperationType(); if (opType == IndexOperationType.Update) { int befImgHash = update.GetBeforeImage().GetHashCode(); int aftImgHash = update.GetAfterImage().GetHashCode(); 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 = update.GetAfterImage().GetHashCode(); AddUpdateToBucket(bucketUpdates, g, aftImgHash, update); } else if (opType == IndexOperationType.Delete) { int befImgHash = update.GetBeforeImage().GetHashCode(); AddUpdateToBucket(bucketUpdates, g, befImgHash, update); } } } List <Task> updateTasks = new List <Task>(); int i = 0; foreach (var kv in bucketUpdates) { BucketT bucket = InsideRuntimeClient.Current.InternalGrainFactory.GetGrain <BucketT>( IndexUtils.GetIndexGrainID(typeof(V), _indexName) + "_" + kv.Key ); updateTasks.Add(bucket.DirectApplyIndexUpdateBatch(kv.Value.AsImmutable(), isUnique, idxMetaData, siloAddress)); ++i; } await Task.WhenAll(updateTasks); if (logger.IsVerbose) { logger.Verbose("Finished calling DirectApplyIndexUpdateBatch with the following parameters: isUnique = {0}, siloAddress = {1}, iUpdates = {2}", isUnique, siloAddress, MemberUpdate.UpdatesToString(iUpdates.Value)); } return(true); }
private static void ValidateSingleIndex(IndexAttribute indexAttr, Type userDefinedIGrain, Type userDefinedGrainImpl, Type propertiesArgType, PropertyInfo propInfo, bool?grainIndexesAreEager, bool isEager, bool isUnique) { bool isFaultTolerant = IsSubclassOfRawGenericType(typeof(IndexableGrain <,>), userDefinedGrainImpl); Type indexType = (Type)indexTypeProperty.GetValue(indexAttr); bool isTotalIndex = typeof(ITotalIndex).IsAssignableFrom(indexType); if (indexAttr is ActiveIndexAttribute && isUnique) { // See comments in ActiveIndexAttribute for details of why this is disallowed. throw new InvalidOperationException($"An active Index cannot be configured to be unique, because multiple activations, persisting, and deactivations can create duplicates." + $" Active Index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be unique on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(userDefinedIGrain)} grain interface."); } if (isTotalIndex && isEager) { throw new InvalidOperationException($"A Total Index cannot be configured to be updated eagerly. The only option for updating a Total Index is lazy updating." + $" Total Index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated eagerly on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(userDefinedIGrain)} grain interface."); } if (isFaultTolerant && isEager) { throw new InvalidOperationException($"A fault-tolerant grain implementation cannot be configured to eagerly update its indexes." + $" The only option for updating the indexes of a fault-tolerant indexable grain is lazy updating." + $" The index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated eagerly on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(userDefinedGrainImpl)} grain implementation class."); } if (grainIndexesAreEager.HasValue && grainIndexesAreEager.Value != isEager) { throw new InvalidOperationException($"Some indexes on {IndexUtils.GetFullTypeName(userDefinedGrainImpl)} grain implementation class are defined as eager while others are lazy." + $" The index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated {(isEager ? "eagerly" : "lazily")} on property { propInfo.Name}" + $" of property class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(userDefinedIGrain)} grain interface," + $" while previous indexs have been configured to be updated {(isEager ? "lazily" : "eagerly")}." + $" You must fix this by configuring all indexes to be updated lazily or eagerly." + $" Note: If you have at least one Total Index among your indexes, this must be lazy, and thus all other indexes must be lazy also."); } if (!VerifyNullValue(propInfo, isUnique, out string convertErrMsg)) { throw new InvalidOperationException($"The index of type {IndexUtils.GetFullTypeName(indexType)} on {IndexUtils.GetFullTypeName(userDefinedGrainImpl)} grain implementation class" + $" failed verification. " + convertErrMsg); } }
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);
private static void GetIndexesForASingleGrainType(ApplicationPartsIndexableGrainLoader loader, IndexRegistry registry, Type grainClassType) { // First see if any indexed interfaces on this grain were already encountered on another grain (unless we're // in validation mode, which doesn't create the indexes). var indexedInterfacesAndProperties = EnumerateIndexedInterfacesForAGrainClassType(grainClassType).ToList(); var indexedInterfaces = loader != null ? new HashSet <Type>(indexedInterfacesAndProperties.Select(tup => tup.interfaceType).Where(itfType => registry.ContainsKey(itfType))) : new HashSet <Type>(); var grainIndexesAreEager = indexedInterfaces.Count > 0 ? registry[indexedInterfaces.First()].HasAnyEagerIndex : default(bool?); var consistencyScheme = grainClassType.GetConsistencyScheme(); // Now find all indexed interfaces we're seeing for the first time (again, unless we're in validation mode). foreach (var(grainInterfaceType, propertiesClassType) in indexedInterfacesAndProperties) { if (!indexedInterfaces.Contains(grainInterfaceType)) { grainIndexesAreEager = CreateIndexesForASingleInterface(loader, registry, propertiesClassType, grainInterfaceType, grainClassType, consistencyScheme, grainIndexesAreEager); indexedInterfaces.Add(grainInterfaceType); } } IReadOnlyDictionary <string, object> getNullValuesDictionary() { IEnumerable <(string propName, (string itfName, object nullValue))> getNullPropertyValuesForInterface(Type interfaceType) => registry[interfaceType].PropertiesClassType.GetProperties() .Select(info => (name: info.Name, nullSpec: (itfname: interfaceType.Name, nullValue: IndexUtils.GetNullValue(info)))) .Where(p => p.nullSpec.nullValue != null); Dictionary <string, (string, object)> addToDict(Dictionary <string, (string, object)> dict, (string propName, (string itfName, object nullValue)nullSpec) current) { bool isInDict(string propName) { return(dict.TryGetValue(propName, out (string itfName, object nullValue)prevNullSpec) ? (prevNullSpec.nullValue.Equals(current.nullSpec.nullValue) ? true : throw new IndexConfigurationException($"Property {propName} has conflicting NullValues defined on interfaces {prevNullSpec.itfName} and {current.nullSpec.itfName}")) : false); } if (!isInDict(current.propName)) { dict[current.propName] = current.nullSpec; } return(dict); } return(indexedInterfaces.SelectMany(itf => getNullPropertyValuesForInterface(itf)) .Aggregate(new Dictionary <string, (string itfName, object nullValue)>(), (dict, pair) => addToDict(dict, pair)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value.nullValue)); } if (indexedInterfaces.Count > 0) { registry.SetGrainIndexes(grainClassType, indexedInterfaces.ToArray(), getNullValuesDictionary()); } }
internal override IIndexInterface <K, V> GetNextBucket() { var NextBucket = this.GrainFactory.GetGrain <IActiveHashIndexSingleBucket <K, V> >(IndexUtils.GetNextIndexBucketIdInChain(this.AsWeaklyTypedReference())); this.State.NextBucket = NextBucket.AsWeaklyTypedReference(); return(NextBucket); }
public Task <V> LookupUnique(K key) { if (!(state.IndexStatus == IndexStatus.Available)) { var e = new Exception(string.Format("Index is not still available.")); logger.Error(IndexingErrorCode.IndexingIndexIsNotReadyYet_GrainServiceBucket3, $"ParentIndex {_parentIndexName}: {e.Message}", e); throw e; } if (state.IndexMap.TryGetValue(key, out HashIndexSingleBucketEntry <V> entry) && !entry.IsTentative) { if (entry.Values.Count() == 1) { return(Task.FromResult(entry.Values.GetEnumerator().Current)); } var e = new Exception(string.Format("There are {0} values for the unique lookup key \"{1}\" does not exist on index \"{2}->{3}\".", entry.Values.Count(), key, _parentIndexName, IndexUtils.GetIndexNameFromIndexGrain(this))); logger.Error(IndexingErrorCode.IndexingIndexIsNotReadyYet_GrainServiceBucket4, $"ParentIndex {_parentIndexName}: {e.Message}", e); throw e; } var ex = new Exception(string.Format("The lookup key \"{0}\" does not exist on index \"{1}->{2}\".", key, _parentIndexName, IndexUtils.GetIndexNameFromIndexGrain(this))); logger.Error(IndexingErrorCode.IndexingIndexIsNotReadyYet_GrainServiceBucket5, $"ParentIndex {_parentIndexName}: {ex.Message}", ex); throw ex; }
private async static Task GetIndexesForASingleGrainType(ApplicationPartsIndexableGrainLoader loader, IndexRegistry registry, Type grainClassType) { if (!typeof(IIndexableGrain).IsAssignableFrom(grainClassType)) { return; } if (registry.ContainsGrainType(grainClassType)) { throw new InvalidOperationException($"Grain class type {grainClassType.Name} has already been added to the registry"); } bool?grainIndexesAreEager = null; var indexedInterfaces = new List <Type>(); var consistencyScheme = grainClassType.GetConsistencyScheme(); foreach (var(grainInterfaceType, propertiesClassType) in EnumerateIndexedInterfacesForAGrainClassType(grainClassType).Where(tup => !registry.ContainsKey(tup.interfaceType))) { grainIndexesAreEager = await CreateIndexesForASingleInterface(loader, registry, propertiesClassType, grainInterfaceType, grainClassType, consistencyScheme, grainIndexesAreEager); indexedInterfaces.Add(grainInterfaceType); } IReadOnlyDictionary <string, object> getNullValuesDictionary() { IEnumerable <(string propName, (string itfName, object nullValue))> getNullPropertyValuesForInterface(Type interfaceType) => registry[interfaceType].PropertiesClassType.GetProperties() .Select(info => (name: info.Name, nullSpec: (itfname: interfaceType.Name, nullValue: IndexUtils.GetNullValue(info)))) .Where(p => p.nullSpec.nullValue != null); Dictionary <string, (string, object)> addToDict(Dictionary <string, (string, object)> dict, (string propName, (string itfName, object nullValue)nullSpec) current) { bool isInDict(string propName) { return(dict.TryGetValue(propName, out (string itfName, object nullValue)prevNullSpec) ? (prevNullSpec.nullValue.Equals(current.nullSpec.nullValue) ? true : throw new IndexConfigurationException($"Property {propName} has conflicting NullValues defined on interfaces {prevNullSpec.itfName} and {current.nullSpec.itfName}")) : false); } if (!isInDict(current.propName)) { dict[current.propName] = current.nullSpec; } return(dict); } return(indexedInterfaces.SelectMany(itf => getNullPropertyValuesForInterface(itf)) .Aggregate(new Dictionary <string, (string itfName, object nullValue)>(), (dict, pair) => addToDict(dict, pair)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value.nullValue)); } registry.SetGrainIndexes(grainClassType, indexedInterfaces.ToArray(), getNullValuesDictionary()); }
public Task <V> LookupUnique(K key) { if (!(State.IndexStatus == IndexStatus.Available)) { var e = new Exception(string.Format("Index is not still available.")); logger.Error((int)ErrorCode.IndexingIndexIsNotReadyYet_SystemTargetBucket3, e.Message, e); throw e; } HashIndexSingleBucketEntry <V> entry; if (State.IndexMap.TryGetValue(key, out entry) && !entry.isTentative()) { if (entry.Values.Count() == 1) { return(Task.FromResult(entry.Values.GetEnumerator().Current)); } else { var e = new Exception(string.Format("There are {0} values for the unique lookup key \"{1}\" does not exist on index \"{2}->{3}\".", entry.Values.Count(), key, _parentIndexName, IndexUtils.GetIndexNameFromIndexGrain(this))); logger.Error((int)ErrorCode.IndexingIndexIsNotReadyYet_SystemTargetBucket4, e.Message, e); throw e; } } else { var e = new Exception(string.Format("The lookup key \"{0}\" does not exist on index \"{1}->{2}\".", key, _parentIndexName, IndexUtils.GetIndexNameFromIndexGrain(this))); logger.Error((int)ErrorCode.IndexingIndexIsNotReadyYet_SystemTargetBucket5, e.Message, e); throw e; } }
public async Task <V> LookupUnique(K key) { if (!(this.State.IndexStatus == IndexStatus.Available)) { throw LogException("Index is not still available", IndexingErrorCode.IndexingIndexIsNotReadyYet_GrainBucket2); } if (this.State.IndexMap.TryGetValue(key, out HashIndexSingleBucketEntry <V> entry)) { return((entry.Values.Count == 1 && !entry.IsTentative) ? entry.Values.GetEnumerator().Current : throw LogException($"There are {entry.Values.Count} values for the unique lookup key \"{key}\" on index" + $" \"{IndexUtils.GetIndexNameFromIndexGrain(this)}\", and the entry is{(entry.IsTentative ? "" : " not")} tentative.", IndexingErrorCode.IndexingIndexIsNotReadyYet_GrainBucket3)); } return((this.State.NextBucket != null) ? await((IHashIndexInterface <K, V>)GetNextBucket()).LookupUnique(key) : throw LogException($"The lookup key \"{key}\" does not exist on index \"{IndexUtils.GetIndexNameFromIndexGrain(this)}\".", IndexingErrorCode.IndexingIndexIsNotReadyYet_GrainBucket4)); }
private static GrainId GetAHashIndexPartitionedPerSiloGrainID(string indexName, Type iGrainType) { return(GrainId.GetSystemTargetGrainId(Constants.HASH_INDEX_PARTITIONED_PER_SILO_BUCKET_SYSTEM_TARGET_TYPE_CODE, IndexUtils.GetIndexGrainID(iGrainType, indexName))); }
internal override GrainReference GetNextBucket(out IIndexInterface <K, V> nextBucketIndexInterface) { var nextBucket = GrainFactory.GetGrain <ITotalHashIndexSingleBucket <K, V> >(IndexUtils.GetNextIndexBucketIdInChain(this.AsWeaklyTypedReference())); nextBucketIndexInterface = nextBucket; return(nextBucket.AsWeaklyTypedReference()); }
public override async Task ObserveResults(IAsyncBatchObserver <TIGrain> observer) { IndexInterface index = GetGrainFactory().GetIndex(_indexName, typeof(TIGrain)); IAsyncStream <TIGrain> resultStream = GetStreamProvider().GetStream <TIGrain>(Guid.NewGuid(), IndexUtils.GetIndexGrainID(typeof(TIGrain), _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 await index.Lookup(result.Cast <IIndexableGrain>(), _param); }
private static GrainId GetGrainID(string indexName) { return(GrainId.GetSystemTargetGrainId(Constants.HASH_INDEX_PARTITIONED_PER_SILO_BUCKET_SYSTEM_TARGET_TYPE_CODE, IndexUtils.GetIndexGrainID(typeof(V), indexName))); }
private BucketT GetBucketGrain(int keyValueHash) { var bucketPrimaryKey = IndexUtils.GetIndexGrainPrimaryKey(typeof(V), this._indexName) + "_" + keyValueHash; return(this.indexManager.GrainFactory.GetGrain <BucketT>(bucketPrimaryKey)); }
private async static Task <bool?> CreateIndexesForASingleInterface(ApplicationPartsIndexableGrainLoader loader, IndexRegistry registry, Type propertiesClassType, Type grainInterfaceType, Type grainClassType, ConsistencyScheme consistencyScheme, bool?grainIndexesAreEager) { // All the properties in TProperties are scanned for Index annotation. // If found, the index is created using the information provided in the annotation. var indexesOnInterface = new NamedIndexMap(propertiesClassType); var interfaceHasLazyIndex = false; // Use a separate value from grainIndexesAreEager in case we change to allow mixing eager and lazy on a single grain. foreach (var propInfo in propertiesClassType.GetProperties()) { var indexAttrs = propInfo.GetCustomAttributes <IndexAttribute>(inherit: false); foreach (var indexAttr in indexAttrs) { var indexName = IndexUtils.PropertyNameToIndexName(propInfo.Name); if (indexesOnInterface.ContainsKey(indexName)) { throw new InvalidOperationException($"An index named {indexName} already exists for user-defined grain interface {grainInterfaceType.Name}"); } var indexType = (Type)indexTypeProperty.GetValue(indexAttr); if (indexType.IsGenericTypeDefinition) { // For the (Active|Total) constructors that take (Active|Total)IndexType parameters, leaving the indexType's key type and interface type // generic arguments as "<,>", this fills them in. indexType = indexType.MakeGenericType(propInfo.PropertyType, grainInterfaceType); } // If it's not eager, then it's configured to be lazily updated var isEager = (bool)isEagerProperty.GetValue(indexAttr); if (!isEager) { interfaceHasLazyIndex = true; } if (!grainIndexesAreEager.HasValue) { grainIndexesAreEager = isEager; } var isUnique = (bool)isUniqueProperty.GetValue(indexAttr); ValidateSingleIndex(indexAttr, grainInterfaceType, grainClassType, propertiesClassType, propInfo, grainIndexesAreEager, consistencyScheme, isEager: isEager, isUnique: isUnique); // Multiple bools, so use param names for safety var maxEntriesPerBucket = (int)maxEntriesPerBucketProperty.GetValue(indexAttr); if (loader != null) { await loader.CreateIndex(propertiesClassType, grainInterfaceType, indexesOnInterface, propInfo, indexName, indexType, isEager, isUnique, maxEntriesPerBucket); } else { IndexFactory.ValidateIndexType(indexType, propInfo, out _, out _); } } } registry[grainInterfaceType] = indexesOnInterface; if (interfaceHasLazyIndex && loader != null) { await loader.RegisterWorkflowQueues(grainInterfaceType, grainClassType, consistencyScheme == ConsistencyScheme.FaultTolerantWorkflow); } return(grainIndexesAreEager); }
public static string CreateIndexWorkflowQueuePrimaryKey(Type grainInterfaceType, int queueSeqNum) => IndexUtils.GetFullTypeName(grainInterfaceType) + "-" + queueSeqNum;
public async Task <V> LookupUnique(K key) { if (!(State.IndexStatus == IndexStatus.Available)) { var e = new Exception(string.Format("Index is not still available.")); GetLogger().Error((int)ErrorCode.IndexingIndexIsNotReadyYet_GrainBucket2, e.Message, e); throw e; } HashIndexSingleBucketEntry <V> entry; if (State.IndexMap.TryGetValue(key, out entry) && !entry.isTentative()) { if (entry.Values.Count() == 1) { return(entry.Values.GetEnumerator().Current); } else { var e = new Exception(string.Format("There are {0} values for the unique lookup key \"{1}\" does not exist on index \"{2}\".", entry.Values.Count(), key, IndexUtils.GetIndexNameFromIndexGrain(this))); GetLogger().Error((int)ErrorCode.IndexingIndexIsNotReadyYet_GrainBucket3, e.Message, e); throw e; } } else if (State.NextBucket != null) { return(await((HashIndexInterface <K, V>)GetNextBucket()).LookupUnique(key)); } else { var e = new Exception(string.Format("The lookup key \"{0}\" does not exist on index \"{1}\".", key, IndexUtils.GetIndexNameFromIndexGrain(this))); GetLogger().Error((int)ErrorCode.IndexingIndexIsNotReadyYet_GrainBucket4, e.Message, e); throw e; } }
internal IStorage <TGrainState> GetStorageBridge <TGrainState>(Grain grain, string storageName) where TGrainState : class, new() => new StateStorageBridge <TGrainState>(grain.GetType().FullName, grain.GrainReference, IndexUtils.GetGrainStorage(this.ServiceProvider, storageName), this.LoggerFactory);
public IndexUpdateGenerator(PropertyInfo prop) { this.prop = prop; this.nullValue = IndexUtils.GetNullValue(prop); }
public Task <V> LookupUniqueAsync(K key) { if (!(state.IndexStatus == IndexStatus.Available)) { throw LogException($"ParentIndex {_parentIndexName}: Index is not still available.", IndexingErrorCode.IndexingIndexIsNotReadyYet_GrainServiceBucket3); } if (state.IndexMap.TryGetValue(key, out HashIndexSingleBucketEntry <V> entry) && !entry.IsTentative) { return((entry.Values.Count == 1) ? Task.FromResult(entry.Values.GetEnumerator().Current) : throw LogException($"ParentIndex {_parentIndexName}: There are {entry.Values.Count} values for the unique lookup key \"{key}\" on index \"{IndexUtils.GetIndexNameFromIndexGrain(this)}\".", IndexingErrorCode.IndexingIndexIsNotReadyYet_GrainServiceBucket4)); } throw LogException($"ParentIndex {_parentIndexName}The lookup key \"{key}\" does not exist on index \"{IndexUtils.GetIndexNameFromIndexGrain(this)}\".", IndexingErrorCode.IndexingIndexIsNotReadyYet_GrainServiceBucket5); }
internal static IndexRegistry GetIndexRegistry(ApplicationPartsIndexableGrainLoader loader, IEnumerable <Type> grainClassTypes) { var registry = new IndexRegistry(); foreach (var grainClassType in grainClassTypes) { if (registry.ContainsGrainType(grainClassType)) { throw new InvalidOperationException($"Precondition violated: GetIndexRegistry should not encounter a duplicate grain class type ({IndexUtils.GetFullTypeName(grainClassType)})"); } GetIndexesForASingleGrainType(loader, registry, grainClassType); } return(registry); }
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 static void ValidateSingleIndex(IndexAttribute indexAttr, Type grainInterfaceType, Type grainClassType, Type propertiesArgType, PropertyInfo propInfo, bool?grainIndexesAreEager, ConsistencyScheme consistencyScheme, bool isEager, bool isUnique) { var indexType = (Type)indexTypeProperty.GetValue(indexAttr); var isTotalIndex = indexType.IsTotalIndex(); var isPerSiloIndex = indexType.IsPartitionedPerSiloIndex(); var isFaultTolerantWorkflow = consistencyScheme == ConsistencyScheme.FaultTolerantWorkflow; var isTransactional = consistencyScheme == ConsistencyScheme.Transactional; if (indexAttr is ActiveIndexAttribute && isUnique) { // See comments in ActiveIndexAttribute for details of why this is disallowed. throw new InvalidOperationException($"An active Index cannot be configured to be unique, because multiple activations, persisting, and deactivations can create duplicates." + $" Active Index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be unique on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on the {IndexUtils.GetFullTypeName(grainInterfaceType)} grain interface."); } if (isPerSiloIndex && isUnique) { throw new InvalidOperationException($"Unique indexes cannot be partitioned per silo because uniqueness across silos is currently not enforced." + $" Partitioned Per Silo Index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be unique on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on the {IndexUtils.GetFullTypeName(grainInterfaceType)} grain interface."); } if (isFaultTolerantWorkflow && isEager) { throw new InvalidOperationException($"A workflow-fault-tolerant consistency scheme cannot be configured to eagerly update its indexes." + $" The only option for updating the indexes of a fault-tolerant indexable grain is lazy updating." + $" The index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated eagerly on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on the {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class."); } if (isFaultTolerantWorkflow && indexType.IsActiveIndex()) { throw new InvalidOperationException($"A workflow-fault-tolerant consistency scheme cannot be used with an Active index, because it will continually be reactivated as part of the fault-tolerant workflow." + $" An Active index of type {IndexUtils.GetFullTypeName(indexType)} is defined on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on the {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class" + $" which uses workflow-fault-tolerant indexing."); } if (isTransactional && !isEager) { throw new InvalidOperationException($"A transactional consistency scheme must be configured to eagerly update its indexes." + $" The index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated eagerly on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class."); } if (isTransactional && indexType.IsActiveIndex()) { throw new InvalidOperationException($"A transactional consistency scheme cannot be used with an Active index, because activation and deactivation do not always run in a transactional context." + $" An Active index of type {IndexUtils.GetFullTypeName(indexType)} is defined on property {propInfo.Name}" + $" of class {IndexUtils.GetFullTypeName(propertiesArgType)} on the {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class" + $" which uses transactional indexing."); } if (grainIndexesAreEager.HasValue && grainIndexesAreEager.Value != isEager) { throw new InvalidOperationException($"Some indexes on {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class are defined as eager while others are lazy." + $" The index of type {IndexUtils.GetFullTypeName(indexType)} is defined to be updated {(isEager ? "eagerly" : "lazily")} on property { propInfo.Name}" + $" of property class {IndexUtils.GetFullTypeName(propertiesArgType)} on {IndexUtils.GetFullTypeName(grainInterfaceType)} grain interface," + $" while previous indexes have been configured to be updated {(isEager ? "lazily" : "eagerly")}." + $" You must fix this by configuring all indexes to be updated lazily or eagerly." + $" Note: If you have at least one Total Index among your indexes, this must be lazy, and thus all other indexes must be lazy also."); } if (!VerifyNullValue(propInfo, isUnique, out string convertErrMsg)) { throw new InvalidOperationException($"The index of type {IndexUtils.GetFullTypeName(indexType)} on {IndexUtils.GetFullTypeName(grainClassType)} grain implementation class" + $" failed verification. " + convertErrMsg); } }
internal override GrainReference GetNextBucket(out IIndexInterface <K, V> nextBucketIndexInterface) { var nextBucket = GrainFactory.GetGrain <TotalHashIndexPartitionedPerKeyBucketImplTransactional <K, V> >(IndexUtils.GetNextIndexBucketIdInChain(this.AsWeaklyTypedReference())); nextBucketIndexInterface = nextBucket; return(nextBucket.AsWeaklyTypedReference()); }
internal override IIndexInterface <K, V> GetNextBucket() { var NextBucket = GrainFactory.GetGrain <TotalHashIndexPartitionedPerKeyBucketImpl <K, V> >(IndexUtils.GetNextIndexBucketIdInChain(this.AsWeaklyTypedReference())); State.NextBucket = NextBucket.AsWeaklyTypedReference(); return(NextBucket); }
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)); }
internal async static Task <IndexRegistry> GetIndexRegistry(ApplicationPartsIndexableGrainLoader loader, Type[] grainTypes) { var registry = new IndexRegistry(); foreach (var grainType in grainTypes) { if (registry.ContainsKey(grainType)) { throw new InvalidOperationException($"Precondition violated: GetGrainClassIndexes should not encounter a duplicate type ({IndexUtils.GetFullTypeName(grainType)})"); } await GetIndexesForASingleGrainType(loader, registry, grainType); } return(registry); }
protected virtual void SetStateToNullValues() { IndexUtils.SetNullValues(base.State); }