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 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); }
/// <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()); }