예제 #1
0
        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}");
        }
예제 #2
0
        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);
        }
예제 #3
0
 private NamedIndexMap EnsureGrainIndexes()
 {
     if (__grainIndexes == null)
     {
         __grainIndexes    = _siloIndexManager.IndexFactory.GetGrainIndexes(_grainInterfaceType);
         _hasAnyTotalIndex = __grainIndexes.HasAnyTotalIndex;
     }
     return(__grainIndexes);
 }
예제 #4
0
        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);
        }
예제 #5
0
 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()));
        }
예제 #7
0
 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}");
 }
예제 #8
0
 internal InterfaceIndexes(NamedIndexMap indexes) => this.NamedIndexes = indexes;