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);
        }
Example #3
0
        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);
Example #5
0
        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());
        }
Example #9
0
        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;
            }
        }
Example #10
0
 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));
 }
Example #11
0
 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);
        }
Example #17
0
 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;
            }
        }
Example #19
0
 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);
 }
Example #21
0
 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);
 }
Example #22
0
        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);
Example #24
0
        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);
            }
        }
Example #25
0
        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());
        }
Example #26
0
        internal override IIndexInterface <K, V> GetNextBucket()
        {
            var NextBucket = GrainFactory.GetGrain <TotalHashIndexPartitionedPerKeyBucketImpl <K, V> >(IndexUtils.GetNextIndexBucketIdInChain(this.AsWeaklyTypedReference()));

            State.NextBucket = NextBucket.AsWeaklyTypedReference();
            return(NextBucket);
        }
Example #27
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));
        }
Example #28
0
        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);
 }