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 }

http://dive4elements.wald.intevation.org