private async Task CreateIndex(Type propertiesArg, Type userDefinedIGrain, NamedIndexMap indexesOnGrain, PropertyInfo property, string indexName, Type indexType, bool isEager, bool isUnique, int maxEntriesPerBucket) { indexesOnGrain[indexName] = await this.indexManager.IndexFactory.CreateIndex(indexType, indexName, isUnique, isEager, maxEntriesPerBucket, property); this.logger.Info($"Index created: Interface = {userDefinedIGrain.Name}, property = {propertiesArg.Name}, index = {indexName}"); }
private static 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); 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 (consistencyScheme == ConsistencyScheme.Transactional) { var transactionalVariantAttr = indexType.GetCustomAttribute <TransactionalIndexVariantAttribute>(); if (transactionalVariantAttr != null) { indexType = transactionalVariantAttr.TransactionalIndexType; } } 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 (!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) { loader.CreateIndex(propertiesClassType, grainInterfaceType, indexesOnInterface, propInfo, indexName, indexType, isEager, isUnique, maxEntriesPerBucket); } else { IndexFactory.ValidateIndexType(indexType, propInfo, out _, out _); } } } registry[grainInterfaceType] = indexesOnInterface; return(grainIndexesAreEager); }
private NamedIndexMap EnsureGrainIndexes() { if (__grainIndexes == null) { __grainIndexes = _siloIndexManager.IndexFactory.GetGrainIndexes(_grainInterfaceType); _hasAnyTotalIndex = __grainIndexes.HasAnyTotalIndex; } return(__grainIndexes); }
private async static Task <bool?> CreateIndexesForASingleInterface(ApplicationPartsIndexableGrainLoader loader, IndexRegistry registry, Type propertiesArgType, Type userDefinedIGrain, Type userDefinedGrainImpl, 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. NamedIndexMap indexesOnGrain = new NamedIndexMap(); var interfaceHasLazyIndex = false; // Use a separate value from grainIndexesAreEager in case we change to allow mixing eager and lazy on a single grain. foreach (PropertyInfo propInfo in propertiesArgType.GetProperties()) { var indexAttrs = propInfo.GetCustomAttributes <IndexAttribute>(inherit: false); foreach (var indexAttr in indexAttrs) { string indexName = "__" + propInfo.Name; if (indexesOnGrain.ContainsKey(indexName)) { throw new InvalidOperationException($"An index named {indexName} already exists for user-defined grain interface {userDefinedIGrain.Name}"); } Type indexType = (Type)indexTypeProperty.GetValue(indexAttr); if (indexType.IsGenericTypeDefinition) { indexType = indexType.MakeGenericType(propInfo.PropertyType, userDefinedIGrain); } // If it's not eager, then it's configured to be lazily updated bool isEager = (bool)isEagerProperty.GetValue(indexAttr); if (!isEager) { interfaceHasLazyIndex = true; } if (!grainIndexesAreEager.HasValue) { grainIndexesAreEager = isEager; } bool isUnique = (bool)isUniqueProperty.GetValue(indexAttr); ValidateSingleIndex(indexAttr, userDefinedIGrain, userDefinedGrainImpl, propertiesArgType, propInfo, grainIndexesAreEager, isEager, isUnique); int maxEntriesPerBucket = (int)maxEntriesPerBucketProperty.GetValue(indexAttr); if (loader != null) { await loader.CreateIndex(propertiesArgType, userDefinedIGrain, indexesOnGrain, propInfo, indexName, indexType, isEager, isUnique, maxEntriesPerBucket); } } } registry[userDefinedIGrain] = indexesOnGrain; if (interfaceHasLazyIndex && loader != null) { await loader.RegisterWorkflowQueues(userDefinedIGrain, userDefinedGrainImpl); } return(grainIndexesAreEager); }
internal IndexWorkflowQueueHandlerBase(SiloIndexManager siloIndexManager, Type grainInterfaceType, int queueSeqNum, SiloAddress silo, bool isDefinedAsFaultTolerantGrain, Func <GrainReference> parentFunc) { _grainInterfaceType = grainInterfaceType; _queueSeqNum = queueSeqNum; _isDefinedAsFaultTolerantGrain = isDefinedAsFaultTolerantGrain; _hasAnyTotalIndex = false; __grainIndexes = null; __workflowQueue = null; _silo = silo; _siloIndexManager = siloIndexManager; _lazyParent = new Lazy <GrainReference>(parentFunc, true); }
/// <summary> /// Upon activation, the list of index update generators is retrieved from the index handler. It is cached in /// this grain for use in creating before-images, and also for later calls to UpdateIndexes. /// /// Then, the before-images are created and stored in memory. /// </summary> public override Task OnActivateAsync() { this.Logger.Trace($"Activating indexable grain {base.GrainReference} of type {this.GetIIndexableGrainTypes()[0]} in silo {this.SiloIndexManager.SiloAddress}."); // Load indexes this._grainIndexes = this.SiloIndexManager.IndexFactory.GetGrainIndexes(GetIIndexableGrainTypes()[0]); this._isThereAnyUniqueIndex = this._grainIndexes.HasAnyUniqueIndex; // Initialize before images this._beforeImages = new Dictionary <string, object>().AsImmutable <IDictionary <string, object> >(); AddMissingBeforeImages(); // Insert the current grain to the active indexes defined on this grain and at the same time call OnActivateAsync of the base class return(Task.WhenAll(InsertIntoActiveIndexes(), base.OnActivateAsync())); }
private void CreateIndex(Type propertiesArg, Type grainInterfaceType, NamedIndexMap indexesOnGrain, PropertyInfo property, string indexName, Type indexType, bool isEager, bool isUnique, int maxEntriesPerBucket) { indexesOnGrain[indexName] = this.indexManager.IndexFactory.CreateIndex(indexType, indexName, isUnique, isEager, maxEntriesPerBucket, property); this.logger.Info($"Index created: Interface = {grainInterfaceType.Name}, property = {propertiesArg.Name}, index = {indexName}"); }
internal InterfaceIndexes(NamedIndexMap indexes) => this.NamedIndexes = indexes;