protected void CheckCascadeRefreshNeeded(CacheDependencyNode node) { CacheChangeItem[] cacheChangeItems = node.cacheChangeItems; if (cacheChangeItems == null) { return; } HashMap <IObjRef, CacheValueAndPrivilege> objRefToCacheValueMap = node.objRefToCacheValueMap; for (int c = cacheChangeItems.Length; c-- > 0;) { CacheChangeItem cci = cacheChangeItems[c]; if (cci == null) { continue; } IList <IObjRef> objectRefsToUpdate = cci.UpdatedObjRefs; IList <Object> objectsToUpdate = cci.UpdatedObjects; for (int a = objectRefsToUpdate.Count; a-- > 0;) { IObjRef objRefToUpdate = objectRefsToUpdate[a]; Object objectToUpdate = objectsToUpdate[a]; CacheValueAndPrivilege cacheValueAndPrivilege = objRefToCacheValueMap.Get(objRefToUpdate); if (cacheValueAndPrivilege == null) { // Current value in childCache is not in our interest here continue; } IEntityMetaData metaData = ((IEntityMetaDataHolder)objectToUpdate).Get__EntityMetaData(); RelationMember[] relationMembers = metaData.RelationMembers; if (relationMembers.Length == 0) { continue; } RootCacheValue cacheValue = cacheValueAndPrivilege.cacheValue; IObjRefContainer vhc = (IObjRefContainer)objectToUpdate; for (int relationIndex = relationMembers.Length; relationIndex-- > 0;) { if (ValueHolderState.INIT != vhc.Get__State(relationIndex)) { continue; } // the object which has to be updated has initialized relations. So we have to ensure // that these relations are in the RootCache at the time the target object will be updated. // This is because initialized relations have to remain initialized after update but the relations // may have been updated, too BatchPendingRelations(cacheValue, relationMembers[relationIndex], cacheValue.GetRelation(relationIndex), node); } } } }
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(); } }