cachinghierarchymanager.java
来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 841 行 · 第 1/2 页
JAVA
841 行
/** * {@inheritDoc} */ public void nodeRemoved(NodeState state, QName name, int index, NodeId id) { // Optimization: ignore notifications for nodes that are not in the cache synchronized (cacheMonitor) { if (idCache.containsKey(state.getNodeId())) { try { Path path = Path.create(getPath(state.getNodeId()), name, index, true); remove(path, id); } catch (PathNotFoundException e) { log.warn("Unable to get path of node " + state.getNodeId() + ", event ignored."); } catch (MalformedPathException e) { log.warn("Unable to create path of " + id, e); } catch (ItemNotFoundException e) { log.warn("Unable to get path of " + state.getNodeId(), e); } catch (RepositoryException e) { log.warn("Unable to get path of " + state.getNodeId(), e); } } } } //------------------------------------------------------< private methods > /** * Return a cached element in the path map, given its id * * @param id node id * @return cached element, <code>null</code> if not found */ private PathMap.Element get(ItemId id) { synchronized (cacheMonitor) { LRUEntry entry = (LRUEntry) idCache.get(id); if (entry != null) { entry.touch(); return entry.getElement(); } return null; } } /** * Return the nearest cached element in the path map, given a path. * The returned element is guaranteed to have an associated object that * is not <code>null</code>. * * @param path path * @return cached element, <code>null</code> if not found */ private PathMap.Element map(Path path) { synchronized (cacheMonitor) { PathMap.Element element = pathCache.map(path, false); while (element != null) { LRUEntry entry = (LRUEntry) element.get(); if (entry != null) { entry.touch(); return element; } element = element.getParent(); } return null; } } /** * Cache an item in the hierarchy given its id and path. Adds a listener * for this item state to get notified about changes. * * @param state node state * @param path path to item */ private void cache(NodeState state, Path path) { NodeId id = state.getNodeId(); synchronized (cacheMonitor) { if (idCache.get(id) != null) { return; } if (idCache.size() >= upperLimit) { /** * Remove least recently used item. Scans the LRU list from head to tail * and removes the first item that has no children. */ LRUEntry entry = head; while (entry != null) { PathMap.Element element = entry.getElement(); if (element.getChildrenCount() == 0) { evict(entry, true); return; } entry = entry.getNext(); } } PathMap.Element element = pathCache.put(path); if (element.get() != null) { if (!id.equals(((LRUEntry) element.get()).getId())) { log.warn("overwriting PathMap.Element"); } } LRUEntry entry = new LRUEntry(id, element); element.set(entry); idCache.put(id, entry); } } /** * Return a flag indicating whether a certain element is cached. * * @param id item id * @return <code>true</code> if the item is already cached; * <code>false</code> otherwise */ private boolean isCached(ItemId id) { synchronized (cacheMonitor) { return idCache.get(id) != null; } } /** * Remove item from cache. Removes the associated <code>LRUEntry</code> * and the <code>PathMap.Element</code> with it. Indexes of same name * sibling elements are shifted! * * @param id item id */ private void remove(ItemId id) { synchronized (cacheMonitor) { LRUEntry entry = (LRUEntry) idCache.get(id); if (entry != null) { remove(entry, true); } } } /** * Remove item from cache. Index of same name sibling items are shifted! * * @param entry LRU entry * @param removeFromPathCache whether to remove from path cache */ private void remove(LRUEntry entry, boolean removeFromPathCache) { // assert: synchronized (cacheMonitor) if (removeFromPathCache) { PathMap.Element element = entry.getElement(); remove(element); element.remove(); } else { idCache.remove(entry.getId()); entry.remove(); } } /** * Evict item from cache. Index of same name sibling items are <b>not</b> * shifted! * * @param entry LRU entry * @param removeFromPathCache whether to remove from path cache */ private void evict(LRUEntry entry, boolean removeFromPathCache) { // assert: synchronized (cacheMonitor) if (removeFromPathCache) { PathMap.Element element = entry.getElement(); element.traverse(new PathMap.ElementVisitor() { public void elementVisited(PathMap.Element element) { evict((LRUEntry) element.get(), false); } }, false); element.remove(false); } else { idCache.remove(entry.getId()); entry.remove(); } } /** * Evict item from cache. Evicts the associated <code>LRUEntry</code> * and the <code>PathMap.Element</code> with it. Indexes of same name * sibling elements are <b>not</b> shifted! * * @param id item id */ private void evict(ItemId id) { synchronized (cacheMonitor) { LRUEntry entry = (LRUEntry) idCache.get(id); if (entry != null) { evict(entry, true); } } } /** * Remove path map element from cache. This will traverse all children * of this element and remove the objects associated with them. * Index of same name sibling items are shifted! * * @param element path map element */ private void remove(PathMap.Element element) { // assert: synchronized (cacheMonitor) element.traverse(new PathMap.ElementVisitor() { public void elementVisited(PathMap.Element element) { remove((LRUEntry) element.get(), false); } }, false); } /** * Insert a node into the cache. This will automatically shift * all indexes of sibling nodes having index greater or equal. * * @param path child path * @param id node id * * @throws PathNotFoundException if the path was not found */ private void insert(Path path, ItemId id) throws PathNotFoundException { synchronized (cacheMonitor) { PathMap.Element element = null; LRUEntry entry = (LRUEntry) idCache.get(id); if (entry != null) { element = entry.getElement(); element.remove(); } PathMap.Element parent = pathCache.map(path.getAncestor(1), true); if (parent != null) { parent.insert(path.getNameElement()); } if (element != null) { pathCache.put(path, element); /* Remember this as a move */ movedIds.add(id); } } } /** * Remove an item from the cache in order to shift the indexes * of items following this item. * * @param path child path * @param id node id * * @throws PathNotFoundException if the path was not found */ private void remove(Path path, ItemId id) throws PathNotFoundException { synchronized (cacheMonitor) { /* If we remembered this as a move, ignore this event */ if (movedIds.remove(id)) { return; } PathMap.Element parent = pathCache.map(path.getAncestor(1), true); if (parent != null) { PathMap.Element element = parent.remove(path.getNameElement()); if (element != null) { remove(element); } } } } /** * Dump contents of path map and elements included to <code>PrintStream</code> given. * * @param ps print stream to dump to */ public void dump(final PrintStream ps) { pathCache.traverse(new PathMap.ElementVisitor() { public void elementVisited(PathMap.Element element) { StringBuffer line = new StringBuffer(); for (int i = 0; i < element.getDepth(); i++) { line.append("--"); } line.append(element.getName()); int index = element.getIndex(); if (index != 0 && index != 1) { line.append('['); line.append(index); line.append(']'); } line.append(" "); line.append(element.get()); ps.println(line.toString()); } }, true); } /** * Entry in the LRU list */ private class LRUEntry { /** * Previous entry */ private LRUEntry previous; /** * Next entry */ private LRUEntry next; /** * Node id */ private final NodeId id; /** * Element in path map */ private final PathMap.Element element; /** * Create a new instance of this class * * @param id node id * @param element the path map element for this entry */ public LRUEntry(NodeId id, PathMap.Element element) { this.id = id; this.element = element; append(); } /** * Append entry to end of LRU list */ public void append() { if (tail == null) { head = this; tail = this; } else { previous = tail; tail.next = this; tail = this; } } /** * Remove entry from LRU list */ public void remove() { if (previous != null) { previous.next = next; } if (next != null) { next.previous = previous; } if (head == this) { head = next; } if (tail == this) { tail = previous; } previous = null; next = null; } /** * Touch entry. Removes it from its current position in the LRU list * and moves it to the end. */ public void touch() { remove(); append(); } /** * Return previous LRU entry * * @return previous LRU entry */ public LRUEntry getPrevious() { return previous; } /** * Return next LRU entry * * @return next LRU entry */ public LRUEntry getNext() { return next; } /** * Return node ID * * @return node ID */ public NodeId getId() { return id; } /** * Return element in path map * * @return element in path map */ public PathMap.Element getElement() { return element; } /** * {@inheritDoc} */ public String toString() { return id.toString(); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?