aplcache

added detection of cacheable parameters as a dependency and

6/10/2019 3:55:05 AM

Details

pom.xml 5(+5 -0)

diff --git a/pom.xml b/pom.xml
index 4cd24c9..5689d62 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,11 @@
             <artifactId>Trace</artifactId>
             <version>1.0</version>
         </dependency>
+        <dependency>
+            <groupId>br.ufrgs.inf.prosoft.jsonserialiser</groupId>
+            <artifactId>JSONSerialiser</artifactId>
+            <version>1.0</version>
+        </dependency>
     </dependencies>
     
     <build>
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java b/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java
new file mode 100644
index 0000000..30ae0c7
--- /dev/null
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java
@@ -0,0 +1,107 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package br.ufrgs.inf.prosoft.aplcache.caching;
+
+import br.ufrgs.inf.prosoft.jsonserialiser.JSONSerialiser;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ *
+ * @author romulo
+ */
+public class APLCache {
+
+    private static final Logger LOGGER = Logger.getLogger(APLCache.class.getName());
+    private static String APLCACHE_CACHEABLE_PARAMETERS = System.getenv("APLCACHE_CACHEABLE_PARAMETERS");
+    private static final Map<String, Collection<String>> APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS = new HashMap<>();
+    private static final String APLCACHE_LOG = System.getenv("APLCACHE_LOG");
+
+    private static void loadCacheableParameters() {
+        if (APLCACHE_CACHEABLE_PARAMETERS == null) {
+            return;
+        }
+        try (FileReader fileReader = new FileReader(APLCACHE_CACHEABLE_PARAMETERS)) {
+            JsonParser jsonParser = new JsonParser();
+            JsonObject jsonObject = jsonParser.parse(fileReader).getAsJsonObject();
+            jsonObject.entrySet().forEach(entry -> {
+                Collection<String> parameters = new ArrayList<>();
+                entry.getValue().getAsJsonArray().forEach(parameter -> {
+                    parameters.add(parameter.getAsString());
+                });
+                APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.put(entry.getKey(), parameters);
+            });
+            LOGGER.log(Level.INFO, "cache file loaded");
+        } catch (FileNotFoundException ex) {
+            LOGGER.log(Level.SEVERE, "invalid cache file");
+        } catch (IOException ex) {
+            LOGGER.log(Level.SEVERE, "invalid cache file");
+        }
+        APLCACHE_CACHEABLE_PARAMETERS = null;
+    }
+
+    public static boolean isCacheable(Thread currentThread, Object... parameters) {
+        StackTraceElement[] stackTrace = currentThread.getStackTrace();
+        StackTraceElement stackTraceElement = null;
+        try {
+            stackTraceElement = stackTrace[2];
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            stackTraceElement = stackTrace[0];
+        }
+        return isCacheable(stackTraceElement, parameters);
+    }
+
+    public static boolean isCacheable(StackTraceElement stackTraceElement, Object... parameters) {
+        try {
+            String methodName = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName();
+            return isCacheable(methodName, parameters);
+        } catch (Exception ex) {
+            return false;
+        }
+    }
+
+    public static boolean isCacheable(String method, Object... parameters) {
+        loadCacheableParameters();
+        if (APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.isEmpty()) {
+            LOGGER.log(Level.WARNING, "no method is cacheable");
+            return false;
+        }
+        Collection<String> cacheableParameters = APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.get(method);
+        if (cacheableParameters == null) {
+            LOGGER.log(Level.WARNING, "method not cacheable: {0}", method);
+            return false;
+        }
+        String serialisedParameters = Stream.of(parameters).map(JSONSerialiser::serialise)
+                .collect(Collectors.joining(",", "[", "]"));
+        if (cacheableParameters.contains(serialisedParameters)) {
+            return true;
+        }
+        log("uncacheable " + method + " : " + serialisedParameters);
+        return false;
+    }
+    
+        private static void log(String message) {
+        if (APLCACHE_LOG == null) {
+            return;
+        }
+        try (FileWriter fileWriter = new FileWriter(APLCACHE_LOG, true)) {
+            fileWriter.write(message + "\n");
+        } catch (IOException ex) {
+        }
+    }
+}
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcache/metadata/Method.java b/src/main/java/br/ufrgs/inf/prosoft/aplcache/metadata/Method.java
index 59de0d7..1b18644 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcache/metadata/Method.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcache/metadata/Method.java
@@ -6,8 +6,8 @@
 package br.ufrgs.inf.prosoft.aplcache.metadata;
 
 import br.ufrgs.inf.prosoft.aplcache.flowchart.metrics.CacheabilityPatternDecider;
+import com.google.gson.Gson;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -25,6 +25,7 @@ import java.util.stream.Collectors;
 public class Method {
 
     private static final Logger LOGGER = Logger.getLogger(Method.class.getName());
+    private static final boolean TRACER_VERBOSE = System.getenv("TRACER_VERBOSE") == null || !System.getenv("TRACER_VERBOSE").equals("false");
 
     private final String name;
     private final List<Occurrence> occurrences;
@@ -61,19 +62,25 @@ public class Method {
         LOGGER.log(Level.INFO, "Grouping by parameters {0} occurrences of {1}", new Object[]{this.name, this.occurrences.size()});
         Map<String, GroupOfOccurrences> groupByParameter = new HashMap<>();
         this.occurrences.stream().parallel().forEach(new Consumer<Occurrence>() {
-            int i = 0;
+
+            private int i;
+            private final Gson gson;
+
+            {
+                this.i = 0;
+                this.gson = new Gson();
+            }
 
             @Override
             public void accept(Occurrence occurrence) {
-                String verbose = System.getenv("TRACER_VERBOSE");
-                if (verbose != null && verbose.equals("true")) {
+                if (TRACER_VERBOSE) {
                     System.out.print(".");
                     System.out.flush();
-                    if (++i % 100 == 0) {
+                    if (++this.i % 100 == 0) {
                         System.out.println();
                     }
                 }
-                String parameters = Arrays.toString(occurrence.getParameters());
+                String parameters = this.gson.toJson(occurrence.getParameters());
                 synchronized (groupByParameter) {
                     try {
                         groupByParameter.get(parameters).addOccurrence(occurrence);