コード例 #1
0
ファイル: CacheDependencyNode.cs プロジェクト: vogelb/ambeth
 public void PushPendingChangeOnAnyChildCache(int index, CacheChangeItem cci)
 {
     if (cacheChangeItems == null)
     {
         cacheChangeItems = new CacheChangeItem[directChildCaches.Count];
     }
     cacheChangeItems[index] = cci;
     PushPendingChangeOnAnyChildCacheIntern();
 }
コード例 #2
0
        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);
                    }
                }
            }
        }
コード例 #3
0
        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();
            }
        }
コード例 #4
0
        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);
            }
        }