Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/artifacts/CollectionMonitor.java @ 7471:fff862f4ef76
Experimental caching of datacage recommendations. The respective hook is called a lot and running the datacage over and over again when loading data can be expensive. So the generated recommendations are cached for some time.
Hopefully this improves the overall speed of loading data from the datacage.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Wed, 30 Oct 2013 15:26:21 +0100 |
parents | f16dce7a2407 |
children | f8e1af4e2f69 |
comparison
equal
deleted
inserted
replaced
7470:e590599031d8 | 7471:fff862f4ef76 |
---|---|
10 | 10 |
11 import java.util.HashMap; | 11 import java.util.HashMap; |
12 import java.util.List; | 12 import java.util.List; |
13 import java.util.Map; | 13 import java.util.Map; |
14 | 14 |
15 import net.sf.ehcache.Cache; | |
16 | |
15 import org.w3c.dom.Document; | 17 import org.w3c.dom.Document; |
16 import org.w3c.dom.Element; | 18 import org.w3c.dom.Element; |
17 import org.w3c.dom.Node; | 19 import org.w3c.dom.Node; |
18 import org.w3c.dom.NodeList; | 20 import org.w3c.dom.NodeList; |
19 | 21 |
20 import org.dive4elements.artifacts.Artifact; | 22 import org.dive4elements.artifacts.Artifact; |
21 import org.dive4elements.artifacts.ArtifactNamespaceContext; | 23 import org.dive4elements.artifacts.ArtifactNamespaceContext; |
22 import org.dive4elements.artifacts.CallContext; | 24 import org.dive4elements.artifacts.CallContext; |
23 import org.dive4elements.artifacts.Hook; | 25 import org.dive4elements.artifacts.Hook; |
24 | 26 |
27 import org.dive4elements.artifacts.common.utils.XMLUtils; | |
25 import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; | 28 import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; |
26 | 29 |
27 import org.dive4elements.artifactdatabase.state.Output; | 30 import org.dive4elements.artifactdatabase.state.Output; |
28 | 31 |
32 import org.dive4elements.river.artifacts.cache.CacheFactory; | |
29 import org.dive4elements.river.artifacts.datacage.Recommendations; | 33 import org.dive4elements.river.artifacts.datacage.Recommendations; |
30 | 34 |
31 /** Monitors collection changes. */ | 35 /** Monitors collection changes. */ |
32 public class CollectionMonitor implements Hook { | 36 public class CollectionMonitor implements Hook { |
37 | |
38 public static final String CACHE_NAME = "recommendations"; | |
33 | 39 |
34 @Override | 40 @Override |
35 public void setup(Node cfg) { | 41 public void setup(Node cfg) { |
36 } | 42 } |
37 | 43 |
53 return; | 59 return; |
54 } | 60 } |
55 | 61 |
56 Element result = (Element)results.item(0); | 62 Element result = (Element)results.item(0); |
57 | 63 |
64 result.appendChild(getRecommendedElement(flys, context, doc)); | |
65 } | |
66 | |
67 protected Element getRecommendedElement( | |
68 D4EArtifact artifact, | |
69 CallContext context, | |
70 Document doc | |
71 ) { | |
72 String [] outs = extractOutputNames(artifact, context); | |
73 | |
74 Element recommendations = null; | |
75 | |
76 Cache cache = CacheFactory.getCache(CACHE_NAME); | |
77 | |
78 if (cache != null) { | |
79 String key = generateCacheKey(artifact, outs); | |
80 | |
81 net.sf.ehcache.Element ce = cache.get(key); | |
82 if (ce != null) { // Found in cache. | |
83 Element e = (Element)ce.getValue(); | |
84 // Sync to avoid thread issues with XML DOM docs. | |
85 synchronized (e.getOwnerDocument()) { | |
86 recommendations = (Element)doc.importNode(e, true); | |
87 } | |
88 } else { // Not found in cache -> generate it. | |
89 Element r = createElement(XMLUtils.newDocument()); | |
90 | |
91 Recommendations.getInstance().recommend( | |
92 artifact, null, outs, | |
93 getNoneUserSpecificParameters(artifact, context), r); | |
94 | |
95 recommendations = (Element)doc.importNode(r, true); | |
96 | |
97 cache.put(new net.sf.ehcache.Element(key, r)); | |
98 } | |
99 } else { // No cache configured -> append directly. | |
100 | |
101 recommendations = createElement(doc); | |
102 | |
103 Recommendations.getInstance().recommend( | |
104 artifact, null, outs, | |
105 getNoneUserSpecificParameters(artifact, context), | |
106 recommendations); | |
107 } | |
108 | |
109 return recommendations; | |
110 } | |
111 | |
112 private static final Element createElement(Document doc) { | |
58 ElementCreator creator = new ElementCreator( | 113 ElementCreator creator = new ElementCreator( |
59 doc, | 114 doc, |
60 ArtifactNamespaceContext.NAMESPACE_URI, | 115 ArtifactNamespaceContext.NAMESPACE_URI, |
61 ArtifactNamespaceContext.NAMESPACE_PREFIX); | 116 ArtifactNamespaceContext.NAMESPACE_PREFIX); |
62 | 117 |
63 Element recommended = creator.create("recommended-artifacts"); | 118 return creator.create("recommended-artifacts"); |
119 } | |
64 | 120 |
65 String[] outs = extractOutputNames(flys, context); | 121 private static final String generateCacheKey(D4EArtifact artifact, String [] outs) { |
66 Map<String, Object> params = getNoneUserSpecificParameters(flys, context); | 122 StringBuilder sb = new StringBuilder(artifact.hash()); |
67 | 123 // XXX: The hash really should be unique enough. |
68 Recommendations rec = Recommendations.getInstance(); | 124 for (String out: outs) { |
69 | 125 sb.append(';').append(out); |
70 // TODO For newer official-lines recommendations we actually | 126 } |
71 // need user-id (null here). | 127 return sb.toString(); |
72 rec.recommend(flys, null, outs, params, recommended); | |
73 | |
74 result.appendChild(recommended); | |
75 } | 128 } |
76 | 129 |
77 | 130 |
78 /** | 131 /** |
79 * Get outputnames from current state (only the ones for which | 132 * Get outputnames from current state (only the ones for which |
80 * facets exist). | 133 * facets exist). |
81 */ | 134 */ |
82 public static String[] extractOutputNames( | 135 private static final String [] extractOutputNames( |
83 D4EArtifact flys, | 136 D4EArtifact flys, |
84 CallContext context) | 137 CallContext context) |
85 { | 138 { |
86 if (flys instanceof ChartArtifact) { | 139 if (flys instanceof ChartArtifact) { |
87 return new String[0]; | 140 return new String[0]; |
102 | 155 |
103 | 156 |
104 /** | 157 /** |
105 * Creates Map from Strings "recommended" to "true". | 158 * Creates Map from Strings "recommended" to "true". |
106 */ | 159 */ |
107 protected Map<String, Object> getNoneUserSpecificParameters( | 160 private static final Map<String, Object> getNoneUserSpecificParameters( |
108 D4EArtifact flys, | 161 D4EArtifact flys, |
109 CallContext context) | 162 CallContext context) |
110 { | 163 { |
111 Map<String, Object> params = new HashMap<String, Object>(1); | 164 Map<String, Object> params = new HashMap<String, Object>(); |
112 params.put("recommended", "true"); | 165 params.put("recommended", "true"); |
113 | 166 |
114 return params; | 167 return params; |
115 } | 168 } |
116 } | 169 } |