Exemple #1
0
        private async Task <Dictionary <IIndexableGrain, HashSet <Guid> > > GetActiveWorkflowsListsFromGrains(IndexWorkflowRecordNode currentWorkflow)
        {
            var result = new Dictionary <IIndexableGrain, HashSet <Guid> >();
            var grains = new List <IIndexableGrain>();
            var activeWorkflowsSetsTasks = new List <Task <Immutable <HashSet <Guid> > > >();

            while (!currentWorkflow.IsPunctuation())
            {
                IIndexableGrain g = currentWorkflow.WorkflowRecord.Grain;
                foreach (var updates in currentWorkflow.WorkflowRecord.MemberUpdates)
                {
                    IMemberUpdate updt = updates.Value;
                    if (updt.GetOperationType() != IndexOperationType.None && !result.ContainsKey(g))
                    {
                        result.Add(g, EMPTY_HASHSET);
                        grains.Add(g);
                        activeWorkflowsSetsTasks.Add(g.AsReference <IIndexableGrain>(InsideRuntimeClient.Current.ConcreteGrainFactory, _iGrainType).GetActiveWorkflowIdsList());
                    }
                }
                currentWorkflow = currentWorkflow.Next;
            }

            if (activeWorkflowsSetsTasks.Count() > 0)
            {
                Immutable <HashSet <Guid> >[] activeWorkflowsSets = await Task.WhenAll(activeWorkflowsSetsTasks);

                for (int i = 0; i < activeWorkflowsSets.Length; ++i)
                {
                    result[grains[i]] = activeWorkflowsSets[i].Value;
                }
            }

            return(result);
        }
Exemple #2
0
        private void PopulateUpdatesToIndexes(IndexWorkflowRecordNode currentWorkflow, Dictionary <string, IDictionary <IIndexableGrain, IList <IMemberUpdate> > > updatesToIndexes, Dictionary <IIndexableGrain, HashSet <Guid> > grainsToActiveWorkflows)
        {
            bool faultTolerant = IsFaultTolerant;

            while (!currentWorkflow.IsPunctuation())
            {
                IndexWorkflowRecord workflowRec = currentWorkflow.WorkflowRecord;
                IIndexableGrain     g           = workflowRec.Grain;
                bool existsInActiveWorkflows    = false;
                if (faultTolerant)
                {
                    HashSet <Guid> activeWorkflowRecs = null;
                    if (grainsToActiveWorkflows.TryGetValue(g, out activeWorkflowRecs))
                    {
                        if (activeWorkflowRecs.Contains(workflowRec.WorkflowId))
                        {
                            existsInActiveWorkflows = true;
                        }
                    }
                }

                foreach (var updates in currentWorkflow.WorkflowRecord.MemberUpdates)
                {
                    IMemberUpdate updt = updates.Value;
                    if (updt.GetOperationType() != IndexOperationType.None)
                    {
                        string index          = updates.Key;
                        var    updatesToIndex = updatesToIndexes[index];
                        IList <IMemberUpdate> updatesList;
                        if (!updatesToIndex.TryGetValue(g, out updatesList))
                        {
                            updatesList = new List <IMemberUpdate>();
                            updatesToIndex.Add(g, updatesList);
                        }

                        if (!faultTolerant || existsInActiveWorkflows)
                        {
                            updatesList.Add(updt);
                        }
                        //if the workflow record does not exist in the list of active work-flows
                        //and the index is fault-tolerant, we should make sure that tentative updates
                        //to unique indexes are undone
                        else if (((IndexMetaData)Indexes[index].Item2).IsUniqueIndex())
                        {
                            //reverse a possible remaining tentative record from the index
                            updatesList.Add(new MemberUpdateReverseTentative(updt));
                        }
                    }
                }
                currentWorkflow = currentWorkflow.Next;
            }
        }
        public IndexOperationType GetOperationType()
        {
            IndexOperationType op = _update.GetOperationType();

            switch (op)
            {
            case IndexOperationType.Delete: return(IndexOperationType.Insert);

            case IndexOperationType.Insert: return(IndexOperationType.Delete);

            default: return(op);
            }
        }
        internal static string ToString(IMemberUpdate update)
        {
            switch (update.GetOperationType())
            {
            case IndexOperationType.None: return(update.GetType().Name + ": No operation");

            case IndexOperationType.Insert: return(update.GetType().Name + ": Inserted " + update.GetAfterImage());

            case IndexOperationType.Delete: return(update.GetType().Name + ": Deleted " + update.GetBeforeImage());

            case IndexOperationType.Update: return(update.GetType().Name + ": Updated " + update.GetBeforeImage() + " into " + update.GetAfterImage());

            default: return(update.GetType().Name + ": Unsupported operation");
            }
        }
        public async Task <bool> DirectApplyIndexUpdate(IIndexableGrain g, Immutable <IMemberUpdate> iUpdate, bool isUniqueIndex, IndexMetaData idxMetaData, SiloAddress siloAddress)
        {
            IMemberUpdate      update = iUpdate.Value;
            IndexOperationType opType = update.GetOperationType();

            if (opType == IndexOperationType.Update)
            {
                int     befImgHash   = update.GetBeforeImage().GetHashCode();
                int     aftImgHash   = update.GetAfterImage().GetHashCode();
                BucketT befImgBucket = InsideRuntimeClient.Current.InternalGrainFactory.GetGrain <BucketT>(
                    IndexUtils.GetIndexGrainID(typeof(V), _indexName) + "_" + befImgHash
                    );
                if (befImgHash == aftImgHash)
                {
                    return(await befImgBucket.DirectApplyIndexUpdate(g, iUpdate, isUniqueIndex, idxMetaData));
                }
                else
                {
                    BucketT aftImgBucket = InsideRuntimeClient.Current.InternalGrainFactory.GetGrain <BucketT>(
                        IndexUtils.GetIndexGrainID(typeof(V), _indexName) + "_" + befImgHash
                        );
                    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   = update.GetAfterImage().GetHashCode();
                BucketT aftImgBucket = InsideRuntimeClient.Current.InternalGrainFactory.GetGrain <BucketT>(
                    IndexUtils.GetIndexGrainID(typeof(V), _indexName) + "_" + aftImgHash
                    );
                return(await aftImgBucket.DirectApplyIndexUpdate(g, iUpdate, isUniqueIndex, idxMetaData));
            }
            else if (opType == IndexOperationType.Delete)
            {
                int     befImgHash   = update.GetBeforeImage().GetHashCode();
                BucketT befImgBucket = InsideRuntimeClient.Current.InternalGrainFactory.GetGrain <BucketT>(
                    IndexUtils.GetIndexGrainID(typeof(V), _indexName) + "_" + befImgHash
                    );
                return(await befImgBucket.DirectApplyIndexUpdate(g, iUpdate, isUniqueIndex, idxMetaData));
            }
            return(true);
        }
        private IDictionary <string, IMemberUpdate> GeneratMemberUpdates(TProperties indexableProperties, bool isOnActivate, bool onlyUpdateActiveIndexes, out bool updateIndexesEagerly, ref bool onlyUniqueIndexesWereUpdated, out int numberOfUniqueIndexesUpdated)
        {
            updateIndexesEagerly         = false;
            numberOfUniqueIndexesUpdated = 0;

            IDictionary <string, IMemberUpdate> updates = new Dictionary <string, IMemberUpdate>();
            IDictionary <string, Tuple <object, object, object> > iUpdateGens = _iUpdateGens;

            {
                IDictionary <string, object> befImgs = _beforeImages.Value;
                foreach (KeyValuePair <string, Tuple <object, object, object> > kvp in iUpdateGens)
                {
                    var idxInfo = kvp.Value;
                    if (!onlyUpdateActiveIndexes || !(idxInfo.Item1 is TotalIndex))
                    {
                        IMemberUpdate mu = isOnActivate ? ((IIndexUpdateGenerator)idxInfo.Item3).CreateMemberUpdate(befImgs[kvp.Key])
                                                        : ((IIndexUpdateGenerator)idxInfo.Item3).CreateMemberUpdate(indexableProperties, befImgs[kvp.Key]);
                        if (mu.GetOperationType() != IndexOperationType.None)
                        {
                            updates.Add(kvp.Key, mu);
                            IndexMetaData indexMetaData = (IndexMetaData)kvp.Value.Item2;

                            //this flag should be the same for all indexes defined
                            //on a grain and that's why we do not accumulate the
                            //changes from different indexes
                            updateIndexesEagerly = indexMetaData.IsEager();

                            //update unique index related output flags and counters
                            bool isUniqueIndex = indexMetaData.IsUniqueIndex();
                            onlyUniqueIndexesWereUpdated = onlyUniqueIndexesWereUpdated && isUniqueIndex;
                            if (isUniqueIndex)
                            {
                                ++numberOfUniqueIndexesUpdated;
                            }
                        }
                    }
                }
            }

            return(updates);
        }
Exemple #7
0
        /// <summary>
        /// This method contains the common functionality for updating
        /// hash-index bucket.
        /// </summary>
        /// <typeparam name="K">key type</typeparam>
        /// <typeparam name="V">value type</typeparam>
        /// <param name="updatedGrain">the updated grain that is being indexed</param>
        /// <param name="update">the update information</param>
        /// <param name="opType">the update operation type, which might be different
        /// from the update operation type inside the update parameter</param>
        /// <param name="State">the index bucket to be updated</param>
        /// <param name="isUniqueIndex">a flag to indicate whether the
        /// hash-index has a uniqueness constraint</param>
        /// <param name="befImg">output parameter: the before-image</param>
        /// <param name="befEntry">output parameter: the index entry containing the before-image</param>
        /// <param name="fixIndexUnavailableOnDelete">output parameter: this variable determines whether
        /// index was still unavailable when we received a delete operation</param>
        internal static bool UpdateBucket <K, V>(V updatedGrain, IMemberUpdate update, HashIndexBucketState <K, V> State, bool isUniqueIndex, IndexMetaData idxMetaData, out K befImg, out HashIndexSingleBucketEntry <V> befEntry, out bool fixIndexUnavailableOnDelete) where V : IIndexableGrain
        {
            fixIndexUnavailableOnDelete = false;
            befImg   = default(K);
            befEntry = null;

            bool isTentativeUpdate = isUniqueIndex && (update is MemberUpdateTentative);
            IndexOperationType             opType = update.GetOperationType();
            HashIndexSingleBucketEntry <V> aftEntry;

            if (opType == IndexOperationType.Update)
            {
                befImg = (K)update.GetBeforeImage();
                K aftImg = (K)update.GetAfterImage();
                if (State.IndexMap.TryGetValue(befImg, out befEntry) && befEntry.Values.Contains(updatedGrain))
                {   //Delete and Insert
                    if (State.IndexMap.TryGetValue(aftImg, out aftEntry))
                    {
                        if (aftEntry.Values.Contains(updatedGrain))
                        {
                            if (isTentativeUpdate)
                            {
                                aftEntry.setTentativeInsert();
                            }
                            else
                            {
                                aftEntry.clearTentativeFlag();
                                befEntry.Remove(updatedGrain, isTentativeUpdate, isUniqueIndex);
                            }
                        }
                        else
                        {
                            if (isUniqueIndex && aftEntry.Values.Count > 0)
                            {
                                throw new UniquenessConstraintViolatedException(string.Format("The uniqueness property of index is violated after an update operation for before-image = {0}, after-image = {1} and grain = {2}", befImg, aftImg, updatedGrain.GetPrimaryKey()));
                            }
                            befEntry.Remove(updatedGrain, isTentativeUpdate, isUniqueIndex);
                            aftEntry.Add(updatedGrain, isTentativeUpdate, isUniqueIndex);
                        }
                    }
                    else
                    {
                        aftEntry = new HashIndexSingleBucketEntry <V>();
                        befEntry.Remove(updatedGrain, isTentativeUpdate, isUniqueIndex);
                        aftEntry.Add(updatedGrain, isTentativeUpdate, isUniqueIndex);
                        State.IndexMap.Add(aftImg, aftEntry);
                    }
                }
                else
                {
                    if (idxMetaData.IsChainedBuckets())
                    {
                        return(false); //not found in this bucket
                    }
                    //Insert
                    if (State.IndexMap.TryGetValue(aftImg, out aftEntry))
                    {
                        if (!aftEntry.Values.Contains(updatedGrain))
                        {
                            if (isUniqueIndex && aftEntry.Values.Count > 0)
                            {
                                throw new UniquenessConstraintViolatedException(string.Format("The uniqueness property of index is violated after an update operation for (not found before-image = {0}), after-image = {1} and grain = {2}", befImg, aftImg, updatedGrain.GetPrimaryKey()));
                            }
                            aftEntry.Add(updatedGrain, isTentativeUpdate, isUniqueIndex);
                        }
                        else if (isTentativeUpdate)
                        {
                            aftEntry.setTentativeInsert();
                        }
                        else
                        {
                            aftEntry.clearTentativeFlag();
                        }
                    }
                    else
                    {
                        if (idxMetaData.IsCreatingANewBucketNecessary(State.IndexMap.Count()))
                        {
                            return(false);
                        }
                        aftEntry = new HashIndexSingleBucketEntry <V>();
                        aftEntry.Add(updatedGrain, isTentativeUpdate, isUniqueIndex);
                        State.IndexMap.Add(aftImg, aftEntry);
                    }
                }
            }
            else if (opType == IndexOperationType.Insert)
            { // Insert
                K aftImg = (K)update.GetAfterImage();
                if (State.IndexMap.TryGetValue(aftImg, out aftEntry))
                {
                    if (!aftEntry.Values.Contains(updatedGrain))
                    {
                        if (isUniqueIndex && aftEntry.Values.Count > 0)
                        {
                            throw new UniquenessConstraintViolatedException(string.Format("The uniqueness property of index is violated after an insert operation for after-image = {0} and grain = {1}", aftImg, updatedGrain.GetPrimaryKey()));
                        }
                        aftEntry.Add(updatedGrain, isTentativeUpdate, isUniqueIndex);
                    }
                    else if (isTentativeUpdate)
                    {
                        aftEntry.setTentativeInsert();
                    }
                    else
                    {
                        aftEntry.clearTentativeFlag();
                    }
                }
                else
                {
                    if (idxMetaData.IsCreatingANewBucketNecessary(State.IndexMap.Count()))
                    {
                        return(false);  //the bucket is full
                    }
                    aftEntry = new HashIndexSingleBucketEntry <V>();
                    aftEntry.Add(updatedGrain, isTentativeUpdate, isUniqueIndex);
                    State.IndexMap.Add(aftImg, aftEntry);
                }
            }
            else if (opType == IndexOperationType.Delete)
            { // Delete
                befImg = (K)update.GetBeforeImage();

                if (State.IndexMap.TryGetValue(befImg, out befEntry) && befEntry.Values.Contains(updatedGrain))
                {
                    befEntry.Remove(updatedGrain, isTentativeUpdate, isUniqueIndex);
                    if (State.IndexStatus != IndexStatus.Available)
                    {
                        fixIndexUnavailableOnDelete = true;
                    }
                }
                else if (idxMetaData.IsChainedBuckets())
                {
                    return(false); //not found in this bucket
                }
            }
            return(true);
        }
 public IndexOperationType GetOperationType()
 {
     return(_update.GetOperationType());
 }