public void TestMethod1() { RootCache rootCache = new RootCache(); uint id = 1; TestParentEntity parent = new TestParentEntity(); parent.RecId = id++; parent.Version = 1; parent.property = "PropertyText"; parent.fieldExtern = "FieldExternText"; parent.SetFieldIntern("FieldInternText"); IList <TestChildEntity> children = new List <TestChildEntity>(); for (int a = 3; a-- > 0;) { TestChildEntity child = new TestChildEntity(); child.RecId = id++; child.Version = 1; child.Parent = parent; children.Add(child); } parent.Children = children; rootCache.Put(parent); TestParentEntity result1 = (TestParentEntity)rootCache.GetObject(typeof(TestParentEntity), parent.RecId); Assert.IsInstanceOfType(result1, typeof(TestParentEntity)); Assert.AreEqual(((TestParentEntity)result1).RecId, parent.RecId); Assert.AreEqual(((TestParentEntity)result1).Version, parent.Version); result1.Children[0].Property = "test0"; TestParentEntity result2 = (TestParentEntity)rootCache.GetObject(typeof(TestParentEntity), parent.RecId); Assert.IsFalse(Object.ReferenceEquals(result1, result2), "RootCache does not clone results!"); Assert.IsFalse(((IValueHolder)result2.Children).IsInitialized, "ValueHolder must be uninitialized at their beginning!"); Assert.IsFalse(Object.Equals(result1.Children[0].Property, result2.Children[0].Property), "RootCache does not preserve root data state!"); ChildCache childCache = new ChildCache(); childCache.Parent = rootCache; TestParentEntity cacheResult1 = (TestParentEntity)childCache.GetObject(typeof(TestParentEntity), parent.RecId); TestParentEntity cacheResult2 = (TestParentEntity)childCache.GetObject(typeof(TestParentEntity), parent.RecId); Assert.IsTrue(Object.ReferenceEquals(cacheResult1, cacheResult2), "ChildCache does not return same results!"); }
protected void DisposeCurrentRootCache(ThreadLocal <RootCache> currentTL) { RootCache rootCache = currentTL.Value; currentTL.Value = null; if (rootCache == null) { return; } if (OfflineListenerExtendable != null) { OfflineListenerExtendable.RemoveOfflineListener(rootCache); } // Cut reference to persistence layer rootCache.Dispose(); }
protected IRootCache AcquireRootCache(bool privileged, ThreadLocal <RootCache> currentRootCacheTL, ICacheRetriever cacheRetriever, Lock readLock, Lock writeLock) { IBeanRuntime <RootCache> rootCacheBR = ServiceContext.RegisterBean <RootCache>() // .PropertyValue("CacheRetriever", cacheRetriever) // .PropertyValue("BoundThread", Thread.CurrentThread); if (readLock != null) { rootCacheBR.PropertyValue("ReadLock", readLock); } if (writeLock != null) { rootCacheBR.PropertyValue("WriteLock", writeLock); } RootCache rootCache = PostProcessRootCacheConfiguration(rootCacheBR).PropertyValue("Privileged", privileged).Finish(); if (OfflineListenerExtendable != null) { OfflineListenerExtendable.AddOfflineListener(rootCache); } currentRootCacheTL.Value = rootCache; return(rootCache); }
protected virtual void RevertChangesIntern(IRevertChangesSavepoint savepoint, IList <Object> objectsToRevert, bool globally, RevertChangesFinishedCallback revertChangesFinishedCallback) { // Store the RevertChangesFinishedCallback from this thread on the stack and set the property null (for following calls): if (objectsToRevert == null || objectsToRevert.Count == 0) { if (revertChangesFinishedCallback != null) { revertChangesFinishedCallback.Invoke(true); } return; } if (globally) { GuiThreadHelper.InvokeOutOfGui(delegate() { bool success = false; try { DataChangeEvent dataChange = new DataChangeEvent(); dataChange.IsLocalSource = true; dataChange.Inserts = new List <IDataChangeEntry>(0); dataChange.Updates = new List <IDataChangeEntry>(); dataChange.Deletes = new List <IDataChangeEntry>(); for (int a = objectsToRevert.Count; a-- > 0;) { Object objectToRevert = objectsToRevert[a]; IEntityMetaData metaData = ((IEntityMetaDataHolder)objectToRevert).Get__EntityMetaData(); Object id = metaData.IdMember.GetValue(objectToRevert, false); if (id == null) { dataChange.Deletes.Add(new DirectDataChangeEntry(objectToRevert)); continue; } dataChange.Updates.Add(new DataChangeEntry(metaData.EntityType, ObjRef.PRIMARY_KEY_INDEX, id, null)); } EventDispatcher.DispatchEvent(dataChange, DateTime.Now, -1); success = true; } finally { if (revertChangesFinishedCallback != null) { revertChangesFinishedCallback.Invoke(success); } } }); } else { // Commented the following part from Ambeth 0.130 and use the part from Ambeth 0.129 due to a deadlock in the merge process: //GuiThreadHelper.InvokeOutOfGui(delegate() //{ // bool success1 = false; // try // { // IList<IDataChangeEntry> directObjectDeletes = new List<IDataChangeEntry>(); // IList<Object> initializedObjects = MergeController.ScanForInitializedObjects(objectsToRevert, true, null); // IList<IObjRef> orisToRevert = new List<IObjRef>(); // ISet<Object> persistedObjectsToRevert = new IdentityHashSet<Object>(); // for (int a = initializedObjects.Count; a-- > 0; ) // { // Object objectToRevert = initializedObjects[a]; // IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(objectToRevert.GetType()); // Object id = metaData.IdMember.GetValue(objectToRevert, false); // if (id == null) // { // directObjectDeletes.Add(new DirectDataChangeEntry(objectToRevert)); // continue; // } // persistedObjectsToRevert.Add(objectToRevert); // orisToRevert.Add(new ObjRef(metaData.EntityType, ObjRef.PRIMARY_KEY_INDEX, id, null)); // } // IList<Object> hardRefsToRootCacheValues = RootCache.GetObjects(orisToRevert, CacheDirective.CacheValueResult | CacheDirective.ReturnMisses); // for (int a = orisToRevert.Count; a-- > 0; ) // { // if (hardRefsToRootCacheValues[a] == null) // { // // Object could not be loaded/retrieved any more. So the ori refers to an invalid object // // We can not revert invalid objects and currently ignore them. They will raise exceptions if they will // // be tried to persist in a merge process any time in the future // orisToRevert.RemoveAt(a); // } // } // // We do nothing with the hardRef-list from the RootCache. It is only necessary to keep track of the instance reference on the stack // // To prohibit GC any potential WeakReferences in the meantime.... // GuiThreadHelper.InvokeInGuiAndWait(delegate() // { // IProcessResumeItem processResumeItem = WaitEventToResume(); // try // { // bool oldCacheModificationValue = CacheModification.IsActive; // CacheModification.IsActive = true; // bool oldFailEarlyModeActive = AbstractCache<Object>.FailEarlyModeActive; // AbstractCache<Object>.FailEarlyModeActive = true; // try // { // IList<IWritableCache> firstLevelCaches = FirstLevelCacheManager.SelectFirstLevelCaches(); // IList<Object> hardRefsToRootCacheValuesHere = hardRefsToRootCacheValues; // foreach (IWritableCache firstLevelCache in firstLevelCaches) // { // IList<Object> persistedObjectsInThisCache = firstLevelCache.GetObjects(orisToRevert, CacheDirective.FailEarly); // for (int a = persistedObjectsInThisCache.Count; a-- > 0; ) // { // Object persistedObjectInThisCache = persistedObjectsInThisCache[a]; // if (!persistedObjectsToRevert.Contains(persistedObjectInThisCache)) // { // continue; // } // RootCache.ApplyValues(persistedObjectInThisCache, (ICacheIntern)firstLevelCache); // } // } // for (int a = objectsToRevert.Count; a-- > 0; ) // { // Object objectToRevert = objectsToRevert[a]; // if (objectToRevert is IDataObject) // { // // Objects which are specified to be reverted loose their delete flag // ((IDataObject)objectToRevert).ToBeDeleted = false; // } // } // } // finally // { // AbstractCache<Object>.FailEarlyModeActive = oldFailEarlyModeActive; // CacheModification.IsActive = oldCacheModificationValue; // } // } // finally // { // if (processResumeItem != null) // { // processResumeItem.ResumeProcessingFinished(); // processResumeItem = null; // } // } // }); // if (directObjectDeletes.Count > 0) // { // DataChangeEvent dataChange = DataChangeEvent.Create(0, 0, 0); // dataChange.Deletes = directObjectDeletes; // EventDispatcher.DispatchEvent(dataChange, DateTime.Now, -1); // } // success1 = true; // } // finally // { // if (revertChangesFinishedCallback != null) // { // revertChangesFinishedCallback.Invoke(success1); // } // } //}); // Here comes the part from Ambeth 0.129: GuiThreadHelper.InvokeOutOfGui(delegate() { bool success1 = false; bool?success2 = null; bool?success3 = null; try { IList <IDataChangeEntry> directObjectDeletes = new List <IDataChangeEntry>(); List <IObjRef> objRefs = new List <IObjRef>(); List <ValueHolderRef> valueHolderKeys = new List <ValueHolderRef>(); IList <Object> initializedObjects = MergeController.ScanForInitializedObjects(objectsToRevert, true, null, objRefs, valueHolderKeys); IList <IObjRef> orisToRevert = new List <IObjRef>(); ISet <Object> persistedObjectsToRevert = new IdentityHashSet <Object>(); for (int a = initializedObjects.Count; a-- > 0;) { Object objectToRevert = initializedObjects[a]; IEntityMetaData metaData = ((IEntityMetaDataHolder)objectToRevert).Get__EntityMetaData(); Object id = metaData.IdMember.GetValue(objectToRevert, false); if (id == null) { directObjectDeletes.Add(new DirectDataChangeEntry(objectToRevert)); continue; } persistedObjectsToRevert.Add(objectToRevert); orisToRevert.Add(new ObjRef(metaData.EntityType, ObjRef.PRIMARY_KEY_INDEX, id, null)); } IList <Object> hardRefsToRootCacheValues = RootCache.GetObjects(orisToRevert, CacheDirective.CacheValueResult | CacheDirective.ReturnMisses); for (int a = orisToRevert.Count; a-- > 0;) { if (hardRefsToRootCacheValues[a] == null) { // Object could not be loaded/retrieved any more. So the ori refers to an invalid object // We can not revert invalid objects and currently ignore them. They will raise exceptions if they will // be tried to persist in a merge process any time in the future orisToRevert.RemoveAt(a); } } // We do nothing with the hardRef-list from the RootCache. It is only necessary to keep track of the instance reference on the stack // To prohibit GC any potential WeakReferences in the meantime.... success2 = false; GuiThreadHelper.InvokeInGui(delegate(Object state) { WaitEventToResume(delegate(IProcessResumeItem processResumeItem) { try { bool oldCacheModificationValue = CacheModification.Active; CacheModification.Active = true; bool oldFailEarlyModeActive = AbstractCache.FailInCacheHierarchyModeActive; AbstractCache.FailInCacheHierarchyModeActive = true; try { IList <IWritableCache> firstLevelCaches = FirstLevelCacheManager.SelectFirstLevelCaches(); IList <Object> hardRefsToRootCacheValuesHere = hardRefsToRootCacheValues; foreach (IWritableCache firstLevelCache in firstLevelCaches) { IList <Object> persistedObjectsInThisCache = firstLevelCache.GetObjects(orisToRevert, CacheDirective.FailEarly); for (int a = persistedObjectsInThisCache.Count; a-- > 0;) { Object persistedObjectInThisCache = persistedObjectsInThisCache[a]; if (!persistedObjectsToRevert.Contains(persistedObjectInThisCache)) { continue; } RootCache.ApplyValues(persistedObjectInThisCache, (ICacheIntern)firstLevelCache, null); } } for (int a = objectsToRevert.Count; a-- > 0;) { Object objectToRevert = objectsToRevert[a]; if (objectToRevert is IDataObject) { // Objects which are specified to be reverted loose their flags ((IDataObject)objectToRevert).ToBeDeleted = false; } } if (directObjectDeletes.Count == 0) { success2 = true; return; } } finally { AbstractCache.FailInCacheHierarchyModeActive = oldFailEarlyModeActive; CacheModification.Active = oldCacheModificationValue; } } finally { if (processResumeItem != null) { processResumeItem.ResumeProcessingFinished(); } } success3 = false; GuiThreadHelper.InvokeOutOfGui(delegate() { try { DataChangeEvent dataChange = DataChangeEvent.Create(0, 0, 0); dataChange.Deletes = directObjectDeletes; EventDispatcher.DispatchEvent(dataChange, DateTime.Now, -1); success3 = true; } finally { if (revertChangesFinishedCallback != null) { revertChangesFinishedCallback.Invoke(success3.Value); } } }); success2 = true; }, delegate(Exception e) { if (revertChangesFinishedCallback != null && success3 == null) { revertChangesFinishedCallback.Invoke(success2.Value); } }); }, null); success1 = true; } finally { if (revertChangesFinishedCallback != null && success2 == null && success3 == null) { revertChangesFinishedCallback.Invoke(success1); } } }); } }
public IndirectValueHolderRef(RootCacheValue cacheValue, RelationMember member, RootCache rootCache, bool objRefsOnly) : base(cacheValue, member, objRefsOnly) { this.rootCache = rootCache; }
public IndirectValueHolderRef(RootCacheValue cacheValue, RelationMember member, RootCache rootCache) : base(cacheValue, member) { this.rootCache = rootCache; }
public void AfterPropertiesSet(IBeanContextFactory beanContextFactory) { ParamChecker.AssertNotNull(ProxyFactory, "ProxyFactory"); IBeanConfiguration serviceResultcache = beanContextFactory.RegisterBean <ServiceResultCache>().Autowireable <IServiceResultCache>(); beanContextFactory.Link(serviceResultcache, "HandleClearAllCaches").To <IEventListenerExtendable>().With(typeof(ClearAllCachesEvent)); beanContextFactory.RegisterBean <ValueHolderIEC>().Autowireable(typeof(ValueHolderIEC), typeof(IProxyHelper)); beanContextFactory.RegisterBean <CacheHelper>().Autowireable(typeof(ICacheHelper), typeof(ICachePathHelper), typeof(IPrefetchHelper)); IBeanConfiguration prioMembersProvider = beanContextFactory.RegisterBean <PrioMembersProvider>().Autowireable <IPrioMembersProvider>(); beanContextFactory.Link(prioMembersProvider, PrioMembersProvider.handleMetaDataAddedEvent).To <IEventListenerExtendable>() .With(typeof(IEntityMetaDataEvent)); beanContextFactory.RegisterBean <CacheWalker>().Autowireable <ICacheWalker>(); beanContextFactory.RegisterAutowireableBean <ICacheMapEntryTypeProvider, CacheMapEntryTypeProvider>(); beanContextFactory.RegisterAutowireableBean <IRootCacheValueFactory, RootCacheValueFactory>(); //IBeanConfiguration rootCache = beanContextFactory.registerBean<RootCache>("rootCache").autowireable(typeof(RootCache), typeof(IWritableCache)); //if (IsUseSingleChildCache) //{ // beanContextFactory.registerBean<SingletonCacheFactory>("cacheFactory") // .propertyRefs("singletonChildCache") // .autowireable<ICacheFactory>(); // IWritableCache childCache = (IWritableCache)beanContextFactory.registerBean<ChildCache>("singletonChildCache") // .propertyRefs("rootCache") // .autowireable(typeof(ICache)).GetInstance(); // ((RootCache)rootCache.GetInstance()).AddChildCache(childCache); //} //else //{ // rootCache.autowireable(typeof(ICache), typeof(IWritableCache), typeof(ICacheFactory)); //} //beanContextFactory.registerBean<RootCache>(ROOT_CACHE).autowireable<RootCache>(); //beanContextFactory.Link("rootCache").To<IOfflineListenerExtendable>(); beanContextFactory.RegisterBean <CacheRetrieverRegistry>(ROOT_CACHE_RETRIEVER).Autowireable(typeof(ICacheServiceByNameExtendable), typeof(ICacheRetrieverExtendable)); beanContextFactory.RegisterBean <FirstLevelCacheManager>("firstLevelCacheManager").Autowireable(typeof(IFirstLevelCacheExtendable), typeof(IFirstLevelCacheManager)); String rootCacheBridge = "rootCacheBridge"; beanContextFactory.RegisterBean <RootCacheBridge>(rootCacheBridge).PropertyRefs(COMMITTED_ROOT_CACHE, ROOT_CACHE_RETRIEVER); TransactionalRootCacheInterceptor txRcInterceptor = new TransactionalRootCacheInterceptor(); beanContextFactory.RegisterWithLifecycle("txRootCacheInterceptor", txRcInterceptor).PropertyRefs(COMMITTED_ROOT_CACHE, rootCacheBridge) .Autowireable(typeof(ITransactionalRootCache), typeof(ISecondLevelCacheManager)); Object txRcProxy = ProxyFactory.CreateProxy(new Type[] { typeof(IRootCache), typeof(ICacheIntern), typeof(IOfflineListener) }, txRcInterceptor); beanContextFactory.RegisterExternalBean(ROOT_CACHE, txRcProxy).Autowireable(typeof(IRootCache), typeof(ICacheIntern)); if (IsSecondLevelCacheActive) { // One single root cache instance for whole context beanContextFactory.RegisterBean <RootCache>(COMMITTED_ROOT_CACHE).PropertyRef("CacheRetriever", ROOT_CACHE_RETRIEVER) .PropertyValue("Privileged", true); beanContextFactory.Link(CacheModule.COMMITTED_ROOT_CACHE).To <IOfflineListenerExtendable>(); } else { // One root cache instance per thread sequence. Most often used in server environment where the "deactivated" // second level cache means that each thread hold his own, isolated root cache (which gets cleared with each service // request. Effectively this means that the root cache itself only lives per-request and does not hold a longer state IInterceptor threadLocalRootCacheInterceptor = (IInterceptor)beanContextFactory .RegisterBean <ThreadLocalRootCacheInterceptor>("threadLocalRootCacheInterceptor") .PropertyRef("StoredCacheRetriever", CacheModule.ROOT_CACHE_RETRIEVER).PropertyValue("Privileged", true).GetInstance(); RootCache rootCacheProxy = ProxyFactory.CreateProxy <RootCache>(threadLocalRootCacheInterceptor); beanContextFactory.RegisterExternalBean(CacheModule.COMMITTED_ROOT_CACHE, rootCacheProxy).Autowireable <RootCache>(); } beanContextFactory.RegisterBean <CacheEventTargetExtractor>("cacheEventTargetExtractor"); beanContextFactory.Link("cacheEventTargetExtractor").To <IEventTargetExtractorExtendable>().With(typeof(ICache)); beanContextFactory.RegisterBean <CacheFactory>().Autowireable <ICacheFactory>(); IInterceptor cacheProviderInterceptor = (IInterceptor)beanContextFactory .RegisterBean <CacheProviderInterceptor>("cacheProviderInterceptor") .Autowireable(typeof(ICacheProviderExtendable), typeof(ICacheProvider), typeof(ICacheContext)).GetInstance(); ICache cacheProxy = ProxyFactory.CreateProxy <ICache>(new Type[] { typeof(ICacheProvider), typeof(IWritableCache) }, cacheProviderInterceptor); beanContextFactory.RegisterExternalBean("cache", cacheProxy).Autowireable <ICache>(); beanContextFactory.RegisterBean <PagingQueryServiceResultProcessor>("pagingQuerySRP"); beanContextFactory.Link("pagingQuerySRP").To <IServiceResultProcessorExtendable>().With(typeof(IPagingResponse)); beanContextFactory.RegisterBean <CacheProvider>(CacheNamedBeans.CacheProviderSingleton).PropertyValue("CacheType", CacheType.SINGLETON); beanContextFactory.RegisterBean <CacheProvider>(CacheNamedBeans.CacheProviderThreadLocal).PropertyValue("CacheType", CacheType.THREAD_LOCAL); beanContextFactory.RegisterBean <CacheProvider>(CacheNamedBeans.CacheProviderPrototype).PropertyValue("CacheType", CacheType.PROTOTYPE); String defaultCacheProviderBeanName; switch (DefaultCacheType) { case CacheType.PROTOTYPE: { defaultCacheProviderBeanName = CacheNamedBeans.CacheProviderPrototype; break; } case CacheType.SINGLETON: { defaultCacheProviderBeanName = CacheNamedBeans.CacheProviderSingleton; break; } case CacheType.THREAD_LOCAL: { defaultCacheProviderBeanName = CacheNamedBeans.CacheProviderThreadLocal; break; } case CacheType.DEFAULT: { defaultCacheProviderBeanName = CacheNamedBeans.CacheProviderThreadLocal; break; } default: throw new Exception("Not supported type: " + DefaultCacheType); } beanContextFactory.Link(defaultCacheProviderBeanName).To <ICacheProviderExtendable>(); // CacheContextPostProcessor must be registered AFTER CachePostProcessor... Object cachePostProcessor = beanContextFactory.RegisterBean <CachePostProcessor>().GetInstance(); beanContextFactory.RegisterBean <CacheContextPostProcessor>().PropertyValue("CachePostProcessor", cachePostProcessor); if (IsNetworkClientMode && IsCacheServiceBeanActive) { IBeanConfiguration remoteCacheService = beanContextFactory.RegisterBean <ClientServiceBean>(CacheModule.EXTERNAL_CACHE_SERVICE) .PropertyValue("Interface", typeof(ICacheService)) .PropertyValue("SyncRemoteInterface", typeof(ICacheServiceWCF)) .PropertyValue("AsyncRemoteInterface", typeof(ICacheClient)).Autowireable <ICacheService>(); beanContextFactory.RegisterAlias(CacheModule.DEFAULT_CACHE_RETRIEVER, CacheModule.EXTERNAL_CACHE_SERVICE); // register to all entities in a "most-weak" manner beanContextFactory.Link(remoteCacheService).To <ICacheRetrieverExtendable>().With(typeof(Object)); //beanContextFactory.RegisterAlias(CacheModule.ROOT_CACHE_RETRIEVER, CacheModule.EXTERNAL_CACHE_SERVICE); //beanContextFactory.registerBean<CacheServiceDelegate>("cacheService").autowireable<ICacheService>(); } beanContextFactory.RegisterBean <DataObjectMixin>().Autowireable <DataObjectMixin>(); beanContextFactory.RegisterBean <EntityEqualsMixin>().Autowireable <EntityEqualsMixin>(); beanContextFactory.RegisterBean <EmbeddedTypeMixin>().Autowireable <EmbeddedTypeMixin>(); beanContextFactory.RegisterBean <PropertyChangeMixin>().Autowireable(typeof(PropertyChangeMixin), typeof(IPropertyChangeExtensionExtendable), typeof(ICollectionChangeExtensionExtendable)); beanContextFactory.RegisterBean <ValueHolderContainerMixin>().Autowireable <ValueHolderContainerMixin>(); }