protected CacheDependencyNode BuildCacheDependency() { IRootCache privilegedSecondLevelCache = SecondLevelCacheManager.SelectPrivilegedSecondLevelCache(true); IRootCache nonPrivilegedSecondLevelCache = SecondLevelCacheManager.SelectNonPrivilegedSecondLevelCache(false); IList <IWritableCache> selectedFirstLevelCaches = FirstLevelCacheManager.SelectFirstLevelCaches(); IdentityHashMap <IRootCache, CacheDependencyNode> secondLevelCacheToNodeMap = new IdentityHashMap <IRootCache, CacheDependencyNode>(); if (privilegedSecondLevelCache != null) { CacheDependencyNodeFactory.AddRootCache(privilegedSecondLevelCache.CurrentRootCache, secondLevelCacheToNodeMap); } if (nonPrivilegedSecondLevelCache != null) { CacheDependencyNodeFactory.AddRootCache(nonPrivilegedSecondLevelCache.CurrentRootCache, secondLevelCacheToNodeMap); } for (int a = selectedFirstLevelCaches.Count; a-- > 0;) { ChildCache childCache = (ChildCache)selectedFirstLevelCaches[a]; IRootCache parent = ((IRootCache)childCache.Parent).CurrentRootCache; CacheDependencyNode node = CacheDependencyNodeFactory.AddRootCache(parent, secondLevelCacheToNodeMap); node.directChildCaches.Add(childCache); } return(CacheDependencyNodeFactory.BuildRootNode(secondLevelCacheToNodeMap)); }
protected IDisposableCache CreateIntern(CacheFactoryDirective cacheFactoryDirective, bool privileged, bool foreignThreadAware, bool?useWeakEntries, String name) { IBeanRuntime <ChildCache> firstLevelCacheBC = BeanContext.RegisterBean <ChildCache>(); if (!foreignThreadAware) { // Do not inject EventQueue because caches without foreign interest will never receive async DCEs firstLevelCacheBC.IgnoreProperties("EventQueue"); } if (useWeakEntries.HasValue) { firstLevelCacheBC.PropertyValue("WeakEntries", useWeakEntries.Value); } if (name != null) { firstLevelCacheBC.PropertyValue("Name", name); } firstLevelCacheBC.PropertyValue("Privileged", privileged); ChildCache firstLevelCache = firstLevelCacheBC.Finish(); FirstLevelCacheExtendable.RegisterFirstLevelCache(firstLevelCache, cacheFactoryDirective, foreignThreadAware, name); return(firstLevelCache); }
protected void ChangeFirstLevelCachesIntern(CacheDependencyNode node, ISet <IObjRef> intermediateDeletes) { List <CacheDependencyNode> childNodes = node.childNodes; for (int a = childNodes.Count; a-- > 0;) { ChangeFirstLevelCachesIntern(childNodes[a], intermediateDeletes); } CacheChangeItem[] cacheChangeItems = node.cacheChangeItems; if (cacheChangeItems == null) { return; } IRootCache parentCache = node.rootCache; // RootCache readlock must be acquired before individual writelock to the child caches due to deadlock reasons Lock parentCacheReadLock = parentCache.ReadLock; parentCacheReadLock.Lock(); try { HashMap <IObjRef, CacheValueAndPrivilege> objRefToCacheValueMap = node.objRefToCacheValueMap; for (int a = cacheChangeItems.Length; a-- > 0;) { CacheChangeItem cci = cacheChangeItems[a]; if (cci == null) { continue; } ChildCache childCache = node.directChildCaches[a]; IList <IObjRef> deletedObjRefs = cci.DeletedObjRefs; IList <Object> objectsToUpdate = cci.UpdatedObjects; IList <IObjRef> objRefsToUpdate = cci.UpdatedObjRefs; IRootCache parent = ((IRootCache)childCache.Parent).CurrentRootCache; Lock writeLock = childCache.WriteLock; writeLock.Lock(); try { if (deletedObjRefs != null && deletedObjRefs.Count > 0) { childCache.Remove(deletedObjRefs); } foreach (IObjRef intermediateDeleteObjRef in intermediateDeletes) { childCache.Remove(intermediateDeleteObjRef); } if (objectsToUpdate != null && objectsToUpdate.Count > 0) { List <IObjRef> objRefsToForget = null; for (int b = objectsToUpdate.Count; b-- > 0;) { Object objectInCache = objectsToUpdate[b]; IObjRef objRefInCache = objRefsToUpdate[b]; // Check if the objects still have their id. They may have lost them concurrently because this // method here may be called from another thread (e.g. UI thread) IEntityMetaData metaData = ((IEntityMetaDataHolder)objectInCache).Get__EntityMetaData(); Object id = metaData.IdMember.GetValue(objectInCache, false); if (id == null) { continue; } CacheValueAndPrivilege cacheValueP = objRefToCacheValueMap.Get(objRefInCache); if (cacheValueP == null) { if (objRefsToForget == null) { objRefsToForget = new List <IObjRef>(); } objRefsToForget.Add(objRefInCache); foreach (PrimitiveMember member in metaData.PrimitiveMembers) { member.SetValue(objectInCache, null); } RelationMember[] relationMembers = metaData.RelationMembers; for (int relationIndex = relationMembers.Length; relationIndex-- > 0;) { ((IValueHolderContainer)objectInCache).Set__Uninitialized(relationIndex, null); } continue; } if (!parentCache.ApplyValues(objectInCache, childCache, cacheValueP.privilege)) { if (Log.WarnEnabled) { Log.Warn("No entry for object '" + objectInCache + "' found in second level cache"); } } } if (objRefsToForget != null) { childCache.Remove(objRefsToForget); } } } finally { writeLock.Unlock(); } } } finally { parentCacheReadLock.Unlock(); } }
protected void BuildCacheChangeItems(CacheDependencyNode node, List <IObjRef> deletesToSearchInCache, List <IObjRef> changesToSearchInCache, List <IObjRef> changesWithVersion) { List <ChildCache> directChildCaches = node.directChildCaches; for (int flcIndex = directChildCaches.Count; flcIndex-- > 0;) { ChildCache childCache = directChildCaches[flcIndex]; List <IObjRef> objectRefsToDelete = new List <IObjRef>(); List <IObjRef> objectRefsToUpdate = new List <IObjRef>(); List <Object> objectsToUpdate = new List <Object>(); Lock readLock = childCache.ReadLock; readLock.Lock(); try { IList <Object> deletesInCache = childCache.GetObjects(deletesToSearchInCache, CacheDirective.FailEarly | CacheDirective.ReturnMisses); for (int a = deletesToSearchInCache.Count; a-- > 0;) { Object result = deletesInCache[a]; if (result == null) { // not in this cache continue; } objectRefsToDelete.Add(deletesToSearchInCache[a]); } IList <Object> changesInCache = childCache.GetObjects(changesToSearchInCache, CacheDirective.FailEarly | CacheDirective.ReturnMisses); for (int a = changesToSearchInCache.Count; a-- > 0;) { Object result = changesInCache[a]; if (result == null) { // not in this cache continue; } // Attach version to ORI. We can not do this before because then we would have had a // cache miss in the childCache above. We need the version now because our second level cache // has to refresh its entries IObjRef objRefWithVersion = changesWithVersion[a]; node.hardRefObjRefsToLoad.Add(objRefWithVersion); if (result is IDataObject) { IDataObject dataObject = (IDataObject)result; if (dataObject.ToBeUpdated || dataObject.ToBeDeleted) { continue; } } if (objRefWithVersion.Version != null) { IEntityMetaData metaData = ((IEntityMetaDataHolder)result).Get__EntityMetaData(); Object versionInCache = metaData.VersionMember != null?metaData.VersionMember.GetValue(result, false) : null; if (versionInCache != null && ((IComparable)objRefWithVersion.Version).CompareTo(versionInCache) <= 0) { continue; } } objectsToUpdate.Add(result); node.objRefsToLoad.Add(objRefWithVersion); // scanForInitializedObjects(result, alreadyScannedObjects, hardRefOrisToLoad); objectRefsToUpdate.Add(objRefWithVersion); } } finally { readLock.Unlock(); } if (objectRefsToDelete.Count == 0 && objectsToUpdate.Count == 0) { continue; } CacheChangeItem cci = new CacheChangeItem(); cci.Cache = childCache; cci.DeletedObjRefs = objectRefsToDelete; cci.UpdatedObjRefs = objectRefsToUpdate; cci.UpdatedObjects = objectsToUpdate; node.PushPendingChangeOnAnyChildCache(flcIndex, cci); } List <CacheDependencyNode> childNodes = node.childNodes; for (int a = childNodes.Count; a-- > 0;) { BuildCacheChangeItems(childNodes[a], deletesToSearchInCache, changesToSearchInCache, changesWithVersion); } }