From 5ee36f25234a07747e0d1b90de72141f7abdbbd8 Mon Sep 17 00:00:00 2001 From: Gerd Behrmann Date: Mon, 17 Nov 2014 14:39:50 +0100 Subject: [PATCH] Fix NPE in httpd service The patch fixes the following NPE: 17 nov. 2014 11:52:48 (poolCollector) [] RuntimeException while executing runnable com.google.common.util.concurrent.Futures$5@2437e8e6 with executor com.google.common.util.concurrent.MoreExecuto rs$SameThreadExecutorService@3f726b8a java.lang.NullPointerException: null at java.util.TreeMap.rotateLeft(TreeMap.java:2220) ~[na:1.8.0_25] at java.util.TreeMap.fixAfterInsertion(TreeMap.java:2287) ~[na:1.8.0_25] at java.util.TreeMap.put(TreeMap.java:582) ~[na:1.8.0_25] at diskCacheV111.services.web.PoolCellQueryContainer.put(PoolCellQueryContainer.java:57) ~[dcache-core-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at diskCacheV111.services.web.PoolInfoObserverV3$2.onSuccess(PoolInfoObserverV3.java:140) ~[dcache-core-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at diskCacheV111.services.web.PoolInfoObserverV3$2.onSuccess(PoolInfoObserverV3.java:134) ~[dcache-core-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at com.google.common.util.concurrent.Futures$5.run(Futures.java:1231) ~[guava-17.0.jar:na] at com.google.common.util.concurrent.MoreExecutors$SameThreadExecutorService.execute(MoreExecutors.java:297) [guava-17.0.jar:na] at com.google.common.util.concurrent.ExecutionList.executeListener(ExecutionList.java:156) [guava-17.0.jar:na] at com.google.common.util.concurrent.ExecutionList.execute(ExecutionList.java:145) [guava-17.0.jar:na] at com.google.common.util.concurrent.AbstractFuture.set(AbstractFuture.java:185) [guava-17.0.jar:na] at org.dcache.cells.CellStub$CallbackFuture.set(CellStub.java:594) [dcache-core-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at org.dcache.cells.CellStub$CallbackFuture.answerArrived(CellStub.java:616) [dcache-core-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at dmg.cells.nucleus.CellNucleus$CallbackTask.innerRun(CellNucleus.java:1050) [cells-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at dmg.cells.nucleus.CellNucleus$AbstractNucleusTask.run(CellNucleus.java:1005) [cells-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at com.google.common.util.concurrent.MoreExecutors$SameThreadExecutorService.execute(MoreExecutors.java:297) [guava-17.0.jar:na] at dmg.cells.nucleus.CellNucleus.addToEventQueue(CellNucleus.java:813) [cells-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at dmg.cells.nucleus.CellGlue.sendMessage(CellGlue.java:557) [cells-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at dmg.cells.nucleus.CellNucleus.sendMessage(CellNucleus.java:371) [cells-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at dmg.cells.nucleus.CellAdapter.messageArrived(CellAdapter.java:831) [cells-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at dmg.cells.nucleus.CellNucleus$DeliverMessageTask.innerRun(CellNucleus.java:1095) [cells-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at dmg.cells.nucleus.CellNucleus$AbstractNucleusTask.run(CellNucleus.java:1005) [cells-2.12.0-SNAPSHOT.jar:2.12.0-SNAPSHOT] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_25] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_25] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25] The patch also changes a few return types from Set to List, as the code is more concerned about the ordering that uniqueness (and the items in the list are still unique). Changed a TreeMap to a more efficient HashMap. Target: trunk Request: 2.11 Request: 2.10 Request: 2.9 Require-notes: yes Require-book: no Acked-by: Paul Millar Acked-by: Karsten Schwank Patch: https://rb.dcache.org/r/7510/ --- .../services/web/PoolCellQueryContainer.java | 31 +++++++++---------- .../web/PoolInfoObserverEngineV2.java | 24 +++++++------- .../services/web/PoolInfoObserverV3.java | 3 -- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/modules/dcache/src/main/java/diskCacheV111/services/web/PoolCellQueryContainer.java b/modules/dcache/src/main/java/diskCacheV111/services/web/PoolCellQueryContainer.java index ffdb8ee3544..4cb77f340c9 100644 --- a/modules/dcache/src/main/java/diskCacheV111/services/web/PoolCellQueryContainer.java +++ b/modules/dcache/src/main/java/diskCacheV111/services/web/PoolCellQueryContainer.java @@ -2,7 +2,11 @@ package diskCacheV111.services.web; +import com.google.common.collect.Ordering; + import java.io.Serializable; +import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; @@ -48,40 +52,39 @@ public boolean isOk() public class PoolCellQueryContainer implements Serializable { private static final long serialVersionUID = 1883299694718571158L; - private SortedMap _infoMap = - new TreeMap<>(); + private Map _infoMap = new HashMap<>(); private Map>> _topology; - public void put(String name, PoolCellQueryInfo info) + public synchronized void put(String name, PoolCellQueryInfo info) { _infoMap.put(name, info); } - public PoolCellQueryInfo getInfoByName(String name) + public synchronized PoolCellQueryInfo getInfoByName(String name) { return _infoMap.get(name); } - public void setTopology(Map>> topology) + public synchronized void setTopology(Map>> topology) { _topology = topology; } - public Set getPoolClassSet() + public synchronized List getPoolClasses() { - return _topology.keySet(); + return Ordering.natural().sortedCopy(_topology.keySet()); } - public Set getPoolGroupSetByClassName(String className) + public synchronized List getPoolGroupSetByClassName(String className) { Map> map = _topology.get(className); if (map == null) { return null; } - return map.keySet(); + return Ordering.natural().sortedCopy(map.keySet()); } - public Map + public synchronized Map getPoolMap(String className, String groupName) { Map> groupMap = @@ -94,13 +97,7 @@ public Set getPoolGroupSetByClassName(String className) return groupMap.get(groupName); } - public Map>> - getTopology() - { - return _topology; - } - - public String toString() + public synchronized String toString() { StringBuilder sb = new StringBuilder(); diff --git a/modules/dcache/src/main/java/diskCacheV111/services/web/PoolInfoObserverEngineV2.java b/modules/dcache/src/main/java/diskCacheV111/services/web/PoolInfoObserverEngineV2.java index 3723fabb191..ee02452ccc2 100644 --- a/modules/dcache/src/main/java/diskCacheV111/services/web/PoolInfoObserverEngineV2.java +++ b/modules/dcache/src/main/java/diskCacheV111/services/web/PoolInfoObserverEngineV2.java @@ -6,8 +6,8 @@ import java.io.PrintWriter; import java.util.Collection; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; -import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; @@ -173,37 +173,37 @@ private void printCells(HTMLWriter html, Map poolMap) private void printClassMenu(HTMLWriter pw, String className) { - Set classSet = _container.getPoolClassSet(); + List classes = _container.getPoolClasses(); pw.println("

Pool Views

"); - printMenuTable(pw, classSet, "/pools/list/", className); + printMenuTable(pw, classes, "/pools/list/", className); } private void printGroupMenu(HTMLWriter pw, String className, String groupName) { - Set groupSet = + List groups = _container.getPoolGroupSetByClassName(className); - if (groupSet != null) { + if (groups != null) { pw.println("

Pool groups of " + className + "

"); - printMenuTable(pw, groupSet, + printMenuTable(pw, groups, "/pools/list/" + className + "/", groupName); } } private void printGroupList(HTMLWriter html, String className) { - Set groupSet = + List groups = _container.getPoolGroupSetByClassName(className); - if (groupSet != null) { + if (groups != null) { html.println("

Pool groups of " + className + "

"); SortedMap> info = new TreeMap<>(); - for (String group : groupSet) { + for (String group : groups) { info.put(group, _container.getPoolMap(className, group).values()); } @@ -214,15 +214,15 @@ private void printGroupList(HTMLWriter html, String className) } } - private void printMenuTable(HTMLWriter html, Set itemSet, + private void printMenuTable(HTMLWriter html, Collection items, String linkBase, String currentItem) { html.beginTable("menu"); - if (!itemSet.isEmpty()) { + if (!items.isEmpty()) { html.beginRow(); int n = 0; - for (Object o: itemSet) { + for (Object o: items) { if (n > 0 && (n % _menuColumns) == 0) { html.endRow(); html.beginRow(); diff --git a/modules/dcache/src/main/java/diskCacheV111/services/web/PoolInfoObserverV3.java b/modules/dcache/src/main/java/diskCacheV111/services/web/PoolInfoObserverV3.java index 96a12153ae2..b4522f6cd1c 100644 --- a/modules/dcache/src/main/java/diskCacheV111/services/web/PoolInfoObserverV3.java +++ b/modules/dcache/src/main/java/diskCacheV111/services/web/PoolInfoObserverV3.java @@ -5,8 +5,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; - import java.io.PrintWriter; import java.util.Map; import java.util.Set; @@ -21,7 +19,6 @@ import dmg.cells.nucleus.CellPath; import org.dcache.cells.AbstractCell; -import org.dcache.cells.AbstractMessageCallback; import org.dcache.cells.CellStub; import org.dcache.cells.Option; import org.dcache.util.Args;