protected void WriteRUI(IRelationUpdateItem rui, IWriter writer, IncrementalMergeState state) { if (rui == null) { return; } IObjRef[] addedORIs = rui.AddedORIs; IObjRef[] removedORIs = rui.RemovedORIs; if (addedORIs != null) { writer.WriteStartElement(rui.MemberName); writer.WriteAttribute("add", addedORIs.Length); writer.WriteStartElementEnd(); WriteObjRefs(addedORIs, writer, state); writer.WriteCloseElement(rui.MemberName); } if (removedORIs != null) { writer.WriteStartElement(rui.MemberName); writer.WriteAttribute("remove", removedORIs.Length); writer.WriteStartElementEnd(); WriteObjRefs(removedORIs, writer, state); writer.WriteCloseElement(rui.MemberName); } }
protected void WriteObjRefs(IObjRef[] objRefs, IWriter writer, IncrementalMergeState incrementalState) { IConversionHelper conversionHelper = ConversionHelper; IObjRef[] clone = (IObjRef[])objRefs.Clone(); Array.Sort(clone, incrementalState.objRefComparator); foreach (IObjRef item in clone) { writer.WriteStartElement("Entity"); StateEntry stateEntry = incrementalState.objRefToStateMap.Get(item); if (stateEntry != null) { writer.WriteAttribute("idx", stateEntry.index); writer.WriteEndElement(); continue; } IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(item.RealType); writer.WriteAttribute("type", metaData.EntityType.FullName); PrimitiveMember idMember = metaData.GetIdMemberByIdIndex(item.IdNameIndex); writer.WriteAttribute(idMember.Name, conversionHelper.ConvertValueToType <String>(item.Id)); if (item.Version != null) { writer.WriteAttribute("version", conversionHelper.ConvertValueToType <String>(item.Version)); } writer.WriteEndElement(); } }
protected void WriteRUIs(IRelationUpdateItem[] fullRUIs, IWriter writer, IncrementalMergeState state) { if (fullRUIs == null) { return; } foreach (IRelationUpdateItem rui in fullRUIs) { WriteRUI(rui, writer, state); } }
protected void WriteCUDResult(ICUDResult cudResult, IWriter writer, IncrementalMergeState state) { IList <IChangeContainer> allChanges = cudResult.AllChanges; List <CreateContainer> creates = new List <CreateContainer>(); List <UpdateContainer> updates = new List <UpdateContainer>(); List <DeleteContainer> deletes = new List <DeleteContainer>(); for (int a = allChanges.Count; a-- > 0;) { IChangeContainer changeContainer = allChanges[a]; if (changeContainer is CreateContainer) { creates.Add((CreateContainer)changeContainer); } else if (changeContainer is UpdateContainer) { updates.Add((UpdateContainer)changeContainer); } else { deletes.Add((DeleteContainer)changeContainer); } } creates.Sort(createContainerComparator); updates.Sort(updateContainerComparator); deletes.Sort(deleteContainerComparator); writer.WriteStartElement("CUDResult"); writer.WriteAttribute("size", allChanges.Count); writer.WriteAttribute("creates", creates.Count); writer.WriteAttribute("updates", updates.Count); writer.WriteAttribute("deletes", deletes.Count); writer.WriteStartElementEnd(); WriteChangeContainers(creates, writer, "Creates", state); WriteChangeContainers(updates, writer, "Updates", state); WriteChangeContainers(deletes, writer, "Deletes", state); writer.WriteCloseElement("CUDResult"); }
protected ICUDResult WhatIfMerged(ICUDResult cudResult, IMethodDescription methodDescription, List <MergeOperation> mergeOperationSequence, IncrementalMergeState incrementalState) { IList <MergeOperation> lastMergeOperationSequence; while (true) { IMap <Type, IList <IChangeContainer> > sortedChanges = BucketSortChanges(cudResult.AllChanges); lastMergeOperationSequence = CreateMergeOperationSequence(sortedChanges); ParamHolder <bool> hasAtLeastOneImplicitChange = new ParamHolder <bool>(false); IList <MergeOperation> fLastMergeOperationSequence = lastMergeOperationSequence; cudResult = CacheContext.ExecuteWithCache(incrementalState.GetStateCache(), delegate(ICUDResult cudResult2) { for (int a = 0, size = fLastMergeOperationSequence.Count; a < size; a++) { MergeOperation mergeOperation = fLastMergeOperationSequence[a]; IMergeServiceExtension mergeServiceExtension = mergeOperation.MergeServiceExtension; ICUDResult explAndImplCudResult = mergeServiceExtension.EvaluateImplicitChanges(cudResult2, incrementalState); cudResult2 = MergeCudResult(cudResult2, explAndImplCudResult, mergeServiceExtension, hasAtLeastOneImplicitChange, incrementalState); } return(cudResult2); }, cudResult); foreach (IMergeListener mergeListener in mergeListeners.GetExtensions()) { ICUDResult explAndImplCudResult = mergeListener.PreMerge(cudResult, incrementalState.GetStateCache()); cudResult = MergeCudResult(cudResult, explAndImplCudResult, mergeListener, hasAtLeastOneImplicitChange, incrementalState); } if (!hasAtLeastOneImplicitChange.Value) { break; } } mergeOperationSequence.AddRange(lastMergeOperationSequence); return(cudResult); }
protected ICUDResult MergeCudResult(ICUDResult cudResult, ICUDResult explAndImplCudResult, Object implyingHandle, ParamHolder <Boolean> hasAtLeastOneImplicitChange, IncrementalMergeState state) { if (explAndImplCudResult == null || Object.ReferenceEquals(cudResult, explAndImplCudResult)) { return(cudResult); } ICUDResult diffCUDResult = CudResultComparer.DiffCUDResult(cudResult, explAndImplCudResult); if (diffCUDResult == null) { return(cudResult); } hasAtLeastOneImplicitChange.Value = true; CudResultApplier.ApplyCUDResultOnEntitiesOfCache(diffCUDResult, false, state); if (Log.DebugEnabled) { Object currHandle = implyingHandle; if (currHandle is IProxyTargetAccessor) { IInterceptor interceptor = ((IProxyTargetAccessor)currHandle).GetInterceptors()[0]; while (interceptor is CascadedInterceptor) { Object target = ((CascadedInterceptor)interceptor).Target; if (target is IInterceptor) { interceptor = ((IInterceptor)target); continue; } currHandle = target; break; } } if (currHandle == null) { currHandle = implyingHandle; } if (CudResultPrinter != null) { Log.Debug("Incremental merge [" + RuntimeHelpers.GetHashCode(state) + "] (" + currHandle.GetType().Name + "):\n" + CudResultPrinter.PrintCUDResult(diffCUDResult, state)); } else { Log.Debug("Incremental merge [" + RuntimeHelpers.GetHashCode(state) + "] (" + currHandle.GetType().Name + "). No Details printable"); } } return(explAndImplCudResult); }
protected IOriCollection Intern(ICUDResult cudResult, IMethodDescription methodDescription, IList <MergeOperation> mergeOperationSequence, IncrementalMergeState state) { IList <IChangeContainer> allChanges = cudResult.AllChanges; IList <Object> originalRefs = cudResult.GetOriginalRefs(); IdentityHashMap <IChangeContainer, int> changeToChangeIndexDict = new IdentityHashMap <IChangeContainer, int>(); for (int a = allChanges.Count; a-- > 0;) { changeToChangeIndexDict.Put(allChanges[a], a); } IObjRef[] objRefs = new IObjRef[allChanges.Count]; long[] allChangedOn = new long[allChanges.Count]; String[] allChangedBy = new String[allChanges.Count]; CHashSet <long> changedOnSet = new CHashSet <long>(); CHashSet <String> changedBySet = new CHashSet <String>(); for (int a = 0, size = mergeOperationSequence.Count; a < size; a++) { MergeOperation mergeOperation = mergeOperationSequence[a]; IMergeServiceExtension mergeServiceExtension = mergeOperation.MergeServiceExtension; IList <IChangeContainer> changesForMergeService = mergeOperation.ChangeContainer; ICUDResult msCudResult = BuildCUDResult(changesForMergeService, changeToChangeIndexDict, originalRefs); IOriCollection msOriCollection = mergeServiceExtension.Merge(msCudResult, methodDescription); MergeController.ApplyChangesToOriginals(msCudResult, msOriCollection, state.GetStateCache()); IList <IObjRef> allChangeORIs = msOriCollection.AllChangeORIs; long? msDefaultChangedOn = msOriCollection.ChangedOn; String msDefaultChangedBy = msOriCollection.ChangedBy; long[] msAllChangedOn = msOriCollection.AllChangedOn; String[] msAllChangedBy = msOriCollection.AllChangedBy; for (int b = changesForMergeService.Count; b-- > 0;) { int index = changeToChangeIndexDict.Get(changesForMergeService[b]); objRefs[index] = allChangeORIs[b]; if (msAllChangedOn != null) { long msChangedOn = msAllChangedOn[b]; allChangedOn[index] = msChangedOn; changedOnSet.Add(msChangedOn); } else { allChangedOn[index] = msDefaultChangedOn.Value; } if (msAllChangedBy != null) { String msChangedBy = msAllChangedBy[b]; allChangedBy[index] = msChangedBy; changedBySet.Add(msChangedBy); } else { allChangedBy[index] = msDefaultChangedBy; } } if (msDefaultChangedOn != null) { changedOnSet.Add(msDefaultChangedOn.Value); } if (msDefaultChangedBy != null) { changedBySet.Add(msDefaultChangedBy); } } OriCollection oriCollection = new OriCollection(); oriCollection.AllChangeORIs = new List <IObjRef>(objRefs); if (changedBySet.Count == 1) { Iterator <String> iter = changedBySet.Iterator(); iter.MoveNext(); oriCollection.ChangedBy = iter.Current; } else { oriCollection.AllChangedBy = allChangedBy; } if (changedOnSet.Count == 1) { Iterator <long> iter = changedOnSet.Iterator(); iter.MoveNext(); oriCollection.ChangedOn = iter.Current; } else { oriCollection.AllChangedOn = allChangedOn; } foreach (IMergeListener mergeListener in mergeListeners.GetExtensions()) { mergeListener.PostMerge(cudResult, objRefs); } if (originalRefs != null) { // Set each original ref to null in order to suppress a post-processing in a potentially calling IMergeProcess for (int a = originalRefs.Count; a-- > 0;) { originalRefs[a] = null; } } // TODO DCE must be fired HERE <--- return(oriCollection); }
protected IOriCollection MergeIntern(ICUDResult cudResultOriginal, IMethodDescription methodDescription) { IResultingBackgroundWorkerDelegate <IOriCollection> runnable = new IResultingBackgroundWorkerDelegate <IOriCollection>(delegate() { IDisposableCache childCache = CacheFactory.CreatePrivileged(CacheFactoryDirective.SubscribeTransactionalDCE, false, false, "MergeServiceRegistry.STATE"); try { IncrementalMergeState state = null; ICUDResult cudResultOfCache; if (MergeProcess.IsAddNewlyPersistedEntities() || (Log.DebugEnabled && CudResultPrinter != null)) { childCache = CacheFactory.CreatePrivileged(CacheFactoryDirective.SubscribeTransactionalDCE, false, false, "MergeServiceRegistry.STATE"); state = (IncrementalMergeState)CudResultApplier.AcquireNewState(childCache); cudResultOfCache = CudResultApplier.ApplyCUDResultOnEntitiesOfCache(cudResultOriginal, true, state); } else { cudResultOfCache = cudResultOriginal; } if (Log.DebugEnabled) { if (CudResultPrinter != null) { Log.Debug("Initial merge [" + RuntimeHelpers.GetHashCode(state) + "]:\n" + CudResultPrinter.PrintCUDResult(cudResultOfCache, state)); } else { Log.Debug("Initial merge [" + RuntimeHelpers.GetHashCode(state) + "]. No Details available"); } } List <MergeOperation> mergeOperationSequence = new List <MergeOperation>(); ICUDResult extendedCudResult = WhatIfMerged(cudResultOfCache, methodDescription, mergeOperationSequence, state); if (Log.DebugEnabled) { Log.Debug("Merge finished [" + RuntimeHelpers.GetHashCode(state) + "]"); } if (MergeSecurityManager != null) { SecurityActive.ExecuteWithSecurityDirective(SecurityDirective.ENABLE_ENTITY_CHECK, delegate() { MergeSecurityManager.CheckMergeAccess(extendedCudResult, methodDescription); }); } List <Object> originalRefsOfCache = new List <Object>(cudResultOfCache.GetOriginalRefs()); List <Object> originalRefsExtended = new List <Object>(extendedCudResult.GetOriginalRefs()); IOriCollection oriCollExtended = Intern(extendedCudResult, methodDescription, mergeOperationSequence, state); IList <IChangeContainer> allChangesOriginal = cudResultOriginal.AllChanges; IList <IObjRef> allChangedObjRefsExtended = oriCollExtended.AllChangeORIs; IObjRef[] allChangedObjRefsResult = new IObjRef[allChangesOriginal.Count]; IdentityHashMap <Object, int?> originalRefOfCacheToIndexMap = new IdentityHashMap <Object, int?>(); for (int a = originalRefsOfCache.Count; a-- > 0;) { originalRefOfCacheToIndexMap.Put(originalRefsOfCache[a], a); } for (int a = originalRefsExtended.Count; a-- > 0;) { int?indexOfCache = originalRefOfCacheToIndexMap.Get(originalRefsExtended[a]); if (indexOfCache == null) { // this is a change implied by a rule or an persistence-implicit change // we do not know about it in the outer original CUDResult continue; } IObjRef objRefExtended = allChangedObjRefsExtended[a]; IObjRef objRefOriginal = allChangesOriginal[indexOfCache.Value].Reference; if (objRefExtended == null) { // entity has been deleted objRefOriginal.Id = null; objRefOriginal.Version = null; } else { objRefOriginal.Id = objRefExtended.Id; objRefOriginal.Version = objRefExtended.Version; } if (objRefOriginal is IDirectObjRef) { ((IDirectObjRef)objRefOriginal).Direct = null; } allChangedObjRefsResult[indexOfCache.Value] = objRefOriginal; } OriCollection oriCollection = new OriCollection(new List <IObjRef>(allChangedObjRefsResult)); return(oriCollection); } finally { childCache.Dispose(); } }); if (SecurityActive == null || !SecurityActive.FilterActivated) { return(runnable()); } else { return(SecurityActive.ExecuteWithoutFiltering(runnable)); } }
protected void WriteChangeContainer(IChangeContainer changeContainer, IWriter writer, IncrementalMergeState incrementalState) { IObjRef objRef = changeContainer.Reference; writer.WriteStartElement("Entity"); writer.WriteAttribute("type", objRef.RealType.FullName); writer.WriteAttribute("id", ConversionHelper.ConvertValueToType <String>(objRef.Id)); if (objRef.Version != null) { writer.WriteAttribute("version", ConversionHelper.ConvertValueToType <String>(objRef.Version)); } StateEntry stateEntry = incrementalState.objRefToStateMap.Get(objRef); if (stateEntry == null) { throw new Exception(); } writer.WriteAttribute("idx", stateEntry.index); if (changeContainer is DeleteContainer) { writer.WriteEndElement(); return; } ICreateOrUpdateContainer createOrUpdate = (ICreateOrUpdateContainer)changeContainer; WritePUIs(createOrUpdate.GetFullPUIs(), writer); WriteRUIs(createOrUpdate.GetFullRUIs(), writer, incrementalState); writer.WriteCloseElement("Entity"); }
protected void WriteChangeContainers <V>(IList <V> changes, IWriter writer, String elementName, IncrementalMergeState state) where V : IChangeContainer { if (changes.Count == 0) { return; } writer.WriteStartElement(elementName); writer.WriteStartElementEnd(); for (int a = 0, size = changes.Count; a < size; a++) { WriteChangeContainer(changes[a], writer, state); } writer.WriteCloseElement(elementName); }
public CloneState(IdentityHashMap <IObjRef, StateEntry> newObjRefToStateEntryMap, IncrementalMergeState incrementalState) { this.newObjRefToStateEntryMap = newObjRefToStateEntryMap; this.incrementalState = incrementalState; }
protected ICUDResult ApplyIntern(ICUDResult cudResult, bool checkBaseState, IncrementalMergeState incrementalState) { ICache stateCache = incrementalState.GetStateCache(); IList <IChangeContainer> allChanges = cudResult.AllChanges; IList <Object> originalRefs = cudResult.GetOriginalRefs(); IList <Object> allObjects = GetAllExistingObjectsFromCache(stateCache, allChanges); List <Object> hardRefs = new List <Object>(); hardRefs.Add(allObjects); // add list as item intended. adding each item of the source is NOT needed List <IObjRef> toFetchFromCache = new List <IObjRef>(); List <DirectValueHolderRef> toPrefetch = new List <DirectValueHolderRef>(); List <IBackgroundWorkerDelegate> runnables = new List <IBackgroundWorkerDelegate>(); IEntityFactory entityFactory = this.EntityFactory; IdentityHashMap <IObjRef, StateEntry> newObjRefToStateEntryMap = new IdentityHashMap <IObjRef, StateEntry>(); IdentityHashMap <IChangeContainer, IChangeContainer> alreadyClonedMap = new IdentityHashMap <IChangeContainer, IChangeContainer>(); List <IChangeContainer> newAllChanges = new List <IChangeContainer>(allChanges.Count); for (int a = 0, size = allChanges.Count; a < size; a++) { IChangeContainer changeContainer = allChanges[a]; Object originalEntity = originalRefs[a]; StateEntry stateEntry = incrementalState.entityToStateMap.Get(originalEntity); IChangeContainer newChangeContainer; if (changeContainer is CreateContainer) { newChangeContainer = new CreateContainer(); } else if (changeContainer is UpdateContainer) { newChangeContainer = new UpdateContainer(); } else { newChangeContainer = new DeleteContainer(); } newAllChanges.Add(newChangeContainer); alreadyClonedMap.Put(changeContainer, newChangeContainer); if (!(changeContainer is CreateContainer)) { Object stateCacheEntity2 = allObjects[a]; stateEntry = incrementalState.entityToStateMap.Get(stateCacheEntity2); if (stateEntry == null) { stateEntry = new StateEntry(stateCacheEntity2, changeContainer.Reference, incrementalState.entityToStateMap.Count + 1); incrementalState.entityToStateMap.Put(stateCacheEntity2, stateEntry); incrementalState.objRefToStateMap.Put(stateEntry.objRef, stateEntry); } // delete & update do not need further handling continue; } Type realType = changeContainer.Reference.RealType; Object stateCacheEntity; if (stateEntry == null) { stateCacheEntity = entityFactory.CreateEntity(realType); DirectObjRef directObjRef = new DirectObjRef(realType, stateCacheEntity); directObjRef.CreateContainerIndex = a; stateEntry = new StateEntry(stateCacheEntity, directObjRef, incrementalState.entityToStateMap.Count + 1); incrementalState.entityToStateMap.Put(stateCacheEntity, stateEntry); incrementalState.objRefToStateMap.Put(stateEntry.objRef, stateEntry); newObjRefToStateEntryMap.Put(changeContainer.Reference, stateEntry); } else { stateCacheEntity = stateEntry.entity; } allObjects[a] = stateCacheEntity; } cloneStateTL.Value = new CloneState(newObjRefToStateEntryMap, incrementalState); try { for (int a = allChanges.Count; a-- > 0;) { IChangeContainer changeContainer = allChanges[a]; IObjRefContainer entity = (IObjRefContainer)allObjects[a]; changeContainer = FillClonedChangeContainer(changeContainer, alreadyClonedMap); IPrimitiveUpdateItem[] puis; IRelationUpdateItem[] ruis; if (changeContainer is CreateContainer) { CreateContainer createContainer = (CreateContainer)changeContainer; puis = createContainer.Primitives; ruis = createContainer.Relations; } else if (changeContainer is UpdateContainer) { UpdateContainer updateContainer = (UpdateContainer)changeContainer; puis = updateContainer.Primitives; ruis = updateContainer.Relations; } else { ((IDataObject)entity).ToBeDeleted = true; continue; } IEntityMetaData metaData = ((IEntityMetaDataHolder)entity).Get__EntityMetaData(); ApplyPrimitiveUpdateItems(entity, puis, metaData); if (ruis != null) { bool isUpdate = changeContainer is UpdateContainer; foreach (IRelationUpdateItem rui in ruis) { ApplyRelationUpdateItem(entity, rui, isUpdate, metaData, toPrefetch, toFetchFromCache, checkBaseState, runnables); } } } while (toPrefetch.Count > 0 || toFetchFromCache.Count > 0 || runnables.Count > 0) { if (toPrefetch.Count > 0) { PrefetchHelper.Prefetch(toPrefetch); toPrefetch.Clear(); } if (toFetchFromCache.Count > 0) { IList <Object> fetchedObjects = stateCache.GetObjects(toFetchFromCache, CacheDirective.None); hardRefs.Add(fetchedObjects); // add list as item intended. adding each item of the source is NOT needed toFetchFromCache.Clear(); } IBackgroundWorkerDelegate[] runnableArray = runnables.ToArray(); runnables.Clear(); foreach (IBackgroundWorkerDelegate runnable in runnableArray) { runnable(); } } List <Object> newObjects = new List <Object>(allObjects.Count); List <DirectValueHolderRef> changedRelationRefs = new List <DirectValueHolderRef>(); for (int a = allObjects.Count; a-- > 0;) { IChangeContainer newChange = newAllChanges[a]; IRelationUpdateItem[] ruis = null; Object entity = allObjects[a]; if (newChange is CreateContainer) { newObjects.Add(entity); ruis = ((CreateContainer)newChange).Relations; } else if (newChange is UpdateContainer) { ruis = ((UpdateContainer)newChange).Relations; } if (ruis == null) { continue; } IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(entity.GetType()); foreach (IRelationUpdateItem rui in ruis) { Member member = metaData.GetMemberByName(rui.MemberName); changedRelationRefs.Add(new DirectValueHolderRef((IObjRefContainer)entity, (RelationMember)member)); } } if (newObjects.Count > 0) { ((IWritableCache)stateCache).Put(newObjects); } if (changedRelationRefs.Count > 0) { PrefetchHelper.Prefetch(changedRelationRefs); } return(new CUDResult(newAllChanges, allObjects)); } finally { cloneStateTL.Value = null; } }