Exemplo n.º 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);
        }
        private Task ApplyIndexUpdatesEagerly(Type iGrainType,
                                              IIndexableGrain updatedGrain,
                                              IDictionary <string, IMemberUpdate> updates,
                                              UpdateIndexType updateIndexTypes,
                                              bool updateIndexesTentatively)
        {
            IList <Task <bool> > updateIndexTasks = new List <Task <bool> >();

            foreach (KeyValuePair <string, IMemberUpdate> updt in updates.Where(updt => updt.Value.OperationType != IndexOperationType.None))
            {
                var idxInfo = this._grainIndexes[updt.Key];

                if (updateIndexTypes.HasFlag(idxInfo.MetaData.IsUniqueIndex ? UpdateIndexType.Unique : UpdateIndexType.NonUnique))
                {
                    // If the caller asks for the update to be tentative, then it will be wrapped inside a MemberUpdateTentative
                    IMemberUpdate updateToIndex = updateIndexesTentatively ? new MemberUpdateTentative(updt.Value) : updt.Value;

                    // The update task is added to the list of update tasks
                    updateIndexTasks.Add(idxInfo.IndexInterface.ApplyIndexUpdate(this.SiloIndexManager,
                                                                                 updatedGrain, updateToIndex.AsImmutable(), idxInfo.MetaData, BaseSiloAddress));
                }
            }

            // At the end, because the index update should be eager, we wait for all index update tasks to finish
            return(Task.WhenAll(updateIndexTasks));
        }
        private async Task DirectApplyIndexUpdateNonPersistent(IIndexableGrain g, IMemberUpdate updt, bool isUniqueIndex, IndexMetaData idxMetaData, SiloAddress siloAddress)
        {
            //this variable determines whether index was still unavailable
            //when we received a delete operation
            bool fixIndexUnavailableOnDelete = false;

            //the target grain that is updated
            V updatedGrain = g.AsReference <V>(GrainFactory);

            K befImg;
            HashIndexSingleBucketEntry <V> befEntry;

            //Updates the index bucket synchronously
            //(note that no other thread can run concurrently
            //before we reach an await operation, so no concurrency
            //control mechanism (e.g., locking) is required)
            if (!HashIndexBucketUtils.UpdateBucket(updatedGrain, updt, State, isUniqueIndex, idxMetaData, out befImg, out befEntry, out fixIndexUnavailableOnDelete))
            {
                await(await GetNextBucketAndPersist()).DirectApplyIndexUpdate(g, updt.AsImmutable(), isUniqueIndex, idxMetaData, siloAddress);
            }

            //if the index was still unavailable
            //when we received a delete operation
            //if (fixIndexUnavailableOnDelete)
            //{
            //    //create tombstone
            //}
        }
        private Task <bool> DirectApplyIndexUpdate(IIndexableGrain g, IMemberUpdate updt, bool isUniqueIndex, IndexMetaData idxMetaData, SiloAddress siloAddress)
        {
            V updatedGrain = g;

            HashIndexBucketUtils.UpdateBucket(updatedGrain, updt, state, isUniqueIndex, idxMetaData);
            return(Task.FromResult(true));
        }
Exemplo n.º 5
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>
        internal static bool UpdateBucket <K, V>(V updatedGrain, IMemberUpdate iUpdate, HashIndexBucketState <K, V> State, bool isUniqueIndex, IndexMetaData idxMetaData) where V : IIndexableGrain
        {
            K befImg;
            HashIndexSingleBucketEntry <V> befEntry;
            bool fixIndexUnavailableOnDelete;

            return(UpdateBucket(updatedGrain, iUpdate, State, isUniqueIndex, idxMetaData, out befImg, out befEntry, out fixIndexUnavailableOnDelete));
        }
Exemplo n.º 6
0
 private void UpdateFromChangeset(IMemberUpdate c)
 {
     Email     = c.Email;
     FirstName = c.FirstName;
     LastName  = c.LastName;
     Gender    = c.Gender;
     Birthdate = c.Birthdate;
     Phone     = c.Phone;
 }
Exemplo n.º 7
0
 public UpdateCommand(Guid id, IMemberUpdate c)
 {
     Id        = id;
     FirstName = c.FirstName;
     LastName  = c.LastName;
     Phone     = c.Phone;
     Email     = c.Email;
     Birthdate = c.Birthdate;
     Gender    = c.Gender;
 }
Exemplo n.º 8
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;
            }
        }
        private IDictionary <string, IMemberUpdate> GenerateMemberUpdates(TProperties indexableProperties, bool isOnActivate, bool onlyUpdateActiveIndexes, out bool updateIndexesEagerly,
                                                                          ref bool onlyUniqueIndexesWereUpdated, out int numberOfUniqueIndexesUpdated)
        {
            KeyValuePair <string, IndexInfo>?kvpFirstIndex = null;

            numberOfUniqueIndexesUpdated = 0;

            IDictionary <string, IMemberUpdate> updates = new Dictionary <string, IMemberUpdate>();

            {
                IDictionary <string, object> befImgs = this._beforeImages.Value;
                foreach (var kvp in this._grainIndexes)
                {
                    var idxInfo = kvp.Value;
                    if (!onlyUpdateActiveIndexes || !(idxInfo.IndexInterface is ITotalIndex))
                    {
                        IMemberUpdate mu = isOnActivate ? idxInfo.UpdateGenerator.CreateMemberUpdate(befImgs[kvp.Key])
                                                        : idxInfo.UpdateGenerator.CreateMemberUpdate(indexableProperties, befImgs[kvp.Key]);
                        if (mu.OperationType != IndexOperationType.None)
                        {
                            updates.Add(kvp.Key, mu);
                            var indexMetaData = kvp.Value.MetaData;

                            if (!kvpFirstIndex.HasValue)
                            {
                                kvpFirstIndex = kvp;
                            }
                            else if (kvpFirstIndex.Value.Value.MetaData.IsEager != indexMetaData.IsEager)
                            {
                                throw new InvalidOperationException($"Inconsistent index eagerness specification on grain implementation {this.GetType().FullName} properties {typeof(TProperties).FullName}." +
                                                                    $" Index {kvpFirstIndex.Value.Key} specified {kvpFirstIndex.Value.Value.MetaData.IsEager} while" +
                                                                    $" index {kvp.Key} specified {kvp.Value.MetaData.IsEager}. This misconfiguration should have been detected on silo startup.");
                            }

                            if (indexMetaData.IsUniqueIndex)
                            {
                                ++numberOfUniqueIndexesUpdated;
                            }
                            else
                            {
                                onlyUniqueIndexesWereUpdated = false;
                            }
                        }
                    }
                }
            }

            updateIndexesEagerly = kvpFirstIndex.HasValue ? kvpFirstIndex.Value.Value.MetaData.IsEager : false;
            return(updates);
        }
        internal static string ToString(IMemberUpdate update)
        {
            switch (update.OperationType)
            {
            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);
        }
Exemplo n.º 12
0
        private async Task DirectApplyIndexUpdateNonPersistent(IIndexableGrain g, IMemberUpdate updt, bool isUniqueIndex, IndexMetaData idxMetaData, SiloAddress siloAddress)
        {
            // The target grain that is updated
            V updatedGrain = g.AsReference <V>(this.SiloIndexManager);

            // Updates the index bucket synchronously (note that no other thread can run concurrently before we reach an await operation,
            // when execution is yielded back to the Orleans scheduler, so no concurrency control mechanism (e.g., locking) is required).
            // 'fixIndexUnavailableOnDelete' indicates whether the index was still unavailable when we received a delete operation.
            if (!HashIndexBucketUtils.UpdateBucketState(updatedGrain, updt, this.State, isUniqueIndex, idxMetaData, out K befImg, out HashIndexSingleBucketEntry <V> befEntry, out bool fixIndexUnavailableOnDelete))
            {
                await(await GetNextBucketAndPersist()).DirectApplyIndexUpdate(g, updt.AsImmutable(), isUniqueIndex, idxMetaData, siloAddress);
            }

            // TODO if the index was still unavailable when we received a delete operation
            //if (fixIndexUnavailableOnDelete)
            //{
            //    //create tombstone
            //}
        }
        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);
        }
        private Task ApplyIndexUpdatesEagerly(Type iGrainType,
                                              IIndexableGrain updatedGrain,
                                              IDictionary <string, IMemberUpdate> updates,
                                              bool onlyUpdateUniqueIndexes,
                                              bool onlyUpdateNonUniqueIndexes,
                                              bool updateIndexesTentatively)
        {
            IList <Task <bool> > updateIndexTasks = new List <Task <bool> >();

            foreach (KeyValuePair <string, IMemberUpdate> updt in updates)
            {
                //if the update is not a no-operation
                if (updt.Value.GetOperationType() != IndexOperationType.None)
                {
                    var idxInfo       = _iUpdateGens[updt.Key];
                    var isUniqueIndex = ((IndexMetaData)idxInfo.Item2).IsUniqueIndex();

                    //the actual update happens if either the corresponding index is not a unique index
                    //and the caller asks for only updating non-unique indexes, or the corresponding
                    //index is a unique index and the caller asks for only updating unqiue indexes.
                    if ((onlyUpdateNonUniqueIndexes && !isUniqueIndex) || (onlyUpdateUniqueIndexes && isUniqueIndex))
                    {
                        IMemberUpdate updateToIndex = updt.Value;
                        //if the caller asks for the update to be tentative, then
                        //it will be wrapped inside a MemberUpdateTentative
                        if (updateIndexesTentatively)
                        {
                            updateToIndex = new MemberUpdateTentative(updateToIndex);
                        }

                        //the update task is added to the list of update tasks
                        updateIndexTasks.Add(((IndexInterface)idxInfo.Item1).ApplyIndexUpdate(updatedGrain, updateToIndex.AsImmutable(), isUniqueIndex, (IndexMetaData)idxInfo.Item2, RuntimeAddress));
                    }
                }
            }

            //at the end, because the index update should be eager, we wait for
            //all index update tasks to finish
            return(Task.WhenAll(updateIndexTasks));
        }
Exemplo n.º 15
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> > > >();
            var workflowIds = new HashSet <Guid>();

            while (!currentWorkflow.IsPunctuation())
            {
                workflowIds.Add(currentWorkflow.WorkflowRecord.WorkflowId);
                IIndexableGrain g = currentWorkflow.WorkflowRecord.Grain;
                foreach (var updates in currentWorkflow.WorkflowRecord.MemberUpdates)
                {
                    IMemberUpdate updt = updates.Value;
                    if (updt.OperationType != IndexOperationType.None && !result.ContainsKey(g))
                    {
                        result.Add(g, emptyHashset);
                        grains.Add(g);
                        activeWorkflowsSetsTasks.Add(g.AsReference <IIndexableGrain>(_siloIndexManager, _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)
                {
                    // Do not include workflowIds that are not in our work queue.
                    result[grains[i]] = new HashSet <Guid>(activeWorkflowsSets[i].Value.Intersect(workflowIds));
                }
            }

            return(result);
        }
        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 = this.GetBucketGrain(befImgHash);
                if (befImgHash == aftImgHash)
                {
                    return(await befImgBucket.DirectApplyIndexUpdate(g, iUpdate, isUniqueIndex, idxMetaData));
                }

                BucketT aftImgBucket = this.GetBucketGrain(aftImgHash);
                var     befTask      = befImgBucket.DirectApplyIndexUpdate(g, new MemberUpdateOverriddenOperation(iUpdate.Value, IndexOperationType.Delete).AsImmutable <IMemberUpdate>(), isUniqueIndex, idxMetaData);
                var     aftTask      = aftImgBucket.DirectApplyIndexUpdate(g, new MemberUpdateOverriddenOperation(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 = this.GetBucketGrain(aftImgHash);
                return(await aftImgBucket.DirectApplyIndexUpdate(g, iUpdate, isUniqueIndex, idxMetaData));
            }
            else if (opType == IndexOperationType.Delete)
            {
                int     befImgHash   = GetBucketIndexFromHashCode(update.GetBeforeImage());
                BucketT befImgBucket = this.GetBucketGrain(befImgHash);
                return(await befImgBucket.DirectApplyIndexUpdate(g, iUpdate, isUniqueIndex, idxMetaData));
            }
            return(true);
        }
 public MemberUpdateReverseTentative(IMemberUpdate update) => this._update = update;
 public MemberUpdateOverridenOperation(IMemberUpdate update, IndexOperationType opType)
 {
     _update = update;
     _opType = opType;
 }
Exemplo n.º 19
0
 public MemberUpdateWithMode(IMemberUpdate update, IndexUpdateMode indexUpdateMode)
 {
     this._update    = update;
     this.UpdateMode = indexUpdateMode;
 }
        /// <summary>
        /// This method contains the common functionality for updating the 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="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="idxMetaData">the index metadata</param>
        /// <param name="fixIndexUnavailableOnDelete">output parameter: this variable determines whether
        ///             the index was still unavailable when we received a delete operation</param>
        internal static bool UpdateBucketState <K, V>(V updatedGrain, IMemberUpdate update, HashIndexBucketState <K, V> state, bool isUniqueIndex,
                                                      IndexMetaData idxMetaData, out bool fixIndexUnavailableOnDelete) where V : IIndexableGrain
        {
            fixIndexUnavailableOnDelete = false;

            var indexUpdateMode = update.UpdateMode;
            var opType          = update.OperationType;
            HashIndexSingleBucketEntry <V> aftEntry;

            // Insert is done for both IndexOperationType.Update and IndexOperationType.Update, so use a local function.
            bool doInsert(K afterImage, out bool uniquenessViolation)
            {
                uniquenessViolation = false;
                if (state.IndexMap.TryGetValue(afterImage, out aftEntry))
                {
                    if (!aftEntry.Values.Contains(updatedGrain))
                    {
                        if (isUniqueIndex && aftEntry.Values.Count > 0)
                        {
                            uniquenessViolation = true;
                            return(false);
                        }
                        aftEntry.Add(updatedGrain, indexUpdateMode, isUniqueIndex);
                    }
                    else if (indexUpdateMode == IndexUpdateMode.Tentative)
                    {
                        aftEntry.SetTentativeInsert();
                    }
                    else
                    {
                        aftEntry.ClearTentativeFlag();
                    }
                    return(true);
                }

                // Add a new entry
                if (idxMetaData.IsCreatingANewBucketNecessary(state.IndexMap.Count))
                {
                    return(false);  // the bucket is full
                }

                aftEntry = new HashIndexSingleBucketEntry <V>();
                aftEntry.Add(updatedGrain, indexUpdateMode, isUniqueIndex);
                state.IndexMap.Add(afterImage, aftEntry);
                return(true);
            }

            if (opType == IndexOperationType.Update)
            {
                K   aftImg = (K)update.GetAfterImage();
                var befImg = (K)update.GetBeforeImage();
                if (state.IndexMap.TryGetValue(befImg, out var befEntry) && befEntry.Values.Contains(updatedGrain))
                {
                    // Delete and Insert
                    if (state.IndexMap.TryGetValue(aftImg, out aftEntry))
                    {
                        if (aftEntry.Values.Contains(updatedGrain))
                        {
                            if (indexUpdateMode == IndexUpdateMode.Tentative)
                            {
                                aftEntry.SetTentativeInsert();
                            }
                            else
                            {
                                aftEntry.ClearTentativeFlag();
                                befEntry.Remove(updatedGrain, indexUpdateMode, isUniqueIndex);
                            }
                        }
                        else
                        {
                            if (isUniqueIndex && aftEntry.Values.Count > 0)
                            {
                                throw new UniquenessConstraintViolatedException(
                                          $"The uniqueness property of index {idxMetaData.IndexName} is would be violated for an update operation" +
                                          $" for before-image = {befImg}, after-image = {aftImg} and grain = {updatedGrain.GetPrimaryKey()}");
                            }
                            befEntry.Remove(updatedGrain, indexUpdateMode, isUniqueIndex);
                            aftEntry.Add(updatedGrain, indexUpdateMode, isUniqueIndex);
                        }
                    }
                    else
                    {
                        aftEntry = new HashIndexSingleBucketEntry <V>();
                        befEntry.Remove(updatedGrain, indexUpdateMode, isUniqueIndex);
                        aftEntry.Add(updatedGrain, indexUpdateMode, isUniqueIndex);
                        state.IndexMap.Add(aftImg, aftEntry);
                    }
                }
                else
                {
                    // Insert-only, because Delete was not found. If there's a NextBucket so return false to search it;
                    // otherwise, the desired Delete result is met (the previous value is not present), so proceed to Insert.
                    if (idxMetaData.IsChainedBuckets && state.NextBucket != null)
                    {
                        return(false);
                    }

                    if (!doInsert(aftImg, out bool uniquenessViolation))
                    {
                        return(uniquenessViolation
                            ? throw new UniquenessConstraintViolatedException(
                                   $"The uniqueness property of index {idxMetaData.IndexName} would be violated for an update operation" +
                                   $" for (not found before-image = {befImg}), after-image = {aftImg} and grain = {updatedGrain.GetPrimaryKey()}")
                            : false);    // The bucket is full
                    }
                }
            }
            else if (opType == IndexOperationType.Insert)
            {
                if (!doInsert((K)update.GetAfterImage(), out bool uniquenessViolation))
                {
                    return(uniquenessViolation
                        ? throw new UniquenessConstraintViolatedException(
                               $"The uniqueness property of index {idxMetaData.IndexName} would be violated for an insert operation" +
                               $" for after-image = {(K)update.GetAfterImage()} and grain = {updatedGrain.GetPrimaryKey()}")
                        : false);
                }
            }
            else if (opType == IndexOperationType.Delete)
            {
                var befImg = (K)update.GetBeforeImage();

                if (state.IndexMap.TryGetValue(befImg, out var befEntry) && befEntry.Values.Contains(updatedGrain))
                {
                    befEntry.Remove(updatedGrain, indexUpdateMode, isUniqueIndex);
                    if (state.IndexStatus != IndexStatus.Available)
                    {
                        fixIndexUnavailableOnDelete = true;
                    }
                }
                else if (idxMetaData.IsChainedBuckets)
                {
                    // Not found in this bucket. If there's a NextBucket, return false to search it;
                    // otherwise, the desired Delete result is met (the value is not present), so return true.
                    return(state.NextBucket == null);
                }
            }
            return(true);
        }
 /// <summary>
 /// This method contains the common functionality for updating the 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="iUpdate">the update information</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="idxMetaData">the index metadata</param>
 internal static bool UpdateBucketState <K, V>(V updatedGrain, IMemberUpdate iUpdate, HashIndexBucketState <K, V> state, bool isUniqueIndex,
                                               IndexMetaData idxMetaData) where V : IIndexableGrain
 => UpdateBucketState(updatedGrain, iUpdate, state, isUniqueIndex, idxMetaData, out bool _);
Exemplo n.º 22
0
 private Task <bool> DirectApplyIndexUpdate(V updatedGrain, IMemberUpdate updt, bool isUniqueIndex, IndexMetaData idxMetaData, SiloAddress siloAddress)
 // Updates the index bucket synchronously (note that no other thread can run concurrently before we reach an await operation,
 // when execution is yielded back to the Orleans scheduler, so no concurrency control mechanism (e.g., locking) is required).
 => Task.FromResult(HashIndexBucketUtils.UpdateBucketState(updatedGrain, updt, state, isUniqueIndex, idxMetaData));
 public MemberUpdateOverriddenMode(IMemberUpdate update, IndexUpdateMode indexUpdateMode)
 {
     this._update    = update;
     this.UpdateMode = indexUpdateMode;
 }
 public MemberUpdateOverriddenOperation(IMemberUpdate update, IndexOperationType opType)
 {
     this._update       = update;
     this.OperationType = opType;
 }
Exemplo n.º 25
0
 public void Update(IMemberUpdate c)
 {
     UpdateFromChangeset(c);
     OnUpdated(new MemberEvent.Updated(this));
 }
 public MemberUpdateReverseTentative(IMemberUpdate update)
 {
     _update = update;
 }
Exemplo n.º 27
0
 public Member(IMemberUpdate c)
 {
     UpdateFromChangeset(c);
     OnCreated(new MemberEvent.Created(this));
 }
 /// <summary>
 /// Adds an grain update to the bucketUpdates dictionary
 /// </summary>
 /// <param name="bucketUpdates">the bucketUpdates dictionary</param>
 /// <param name="g">target grain</param>
 /// <param name="bucket">the bucket index</param>
 /// <param name="update">the update to be added</param>
 private void AddUpdateToBucket(IDictionary <int, IDictionary <IIndexableGrain, IList <IMemberUpdate> > > bucketUpdates, IIndexableGrain g, int bucket, IMemberUpdate update)
 {
     if (bucketUpdates.TryGetValue(bucket, out IDictionary <IIndexableGrain, IList <IMemberUpdate> > tmpBucketUpdatesMap))
     {
         if (!tmpBucketUpdatesMap.TryGetValue(g, out IList <IMemberUpdate> tmpUpdateList))
         {
             tmpUpdateList = new List <IMemberUpdate>(new[] { update });
             tmpBucketUpdatesMap.Add(g, tmpUpdateList);
         }
         else
         {
             tmpUpdateList.Add(update);
         }
     }
     else
     {
         tmpBucketUpdatesMap = new Dictionary <IIndexableGrain, IList <IMemberUpdate> >
         {
             { g, new List <IMemberUpdate>(new[] { update }) }
         };
         bucketUpdates.Add(bucket, tmpBucketUpdatesMap);
     }
 }
Exemplo n.º 29
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);
        }