Skip to content

Instantly share code, notes, and snippets.

@autoletics
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save autoletics/e8a7509b81a46bf5fefe to your computer and use it in GitHub Desktop.
Save autoletics/e8a7509b81a46bf5fefe to your computer and use it in GitHub Desktop.
j.s.p.strategy.enabled=true
j.s.p.strategies=mp
j.s.p.strategy.mp.factory.class=com.jinspired.jxinsight.probes.strategy.multipass.StrategyFactory
j.s.p.strategy.mp.factory.classpath=/Users/wlouth/IdeaProjects/multipass-probes-strategy/classes/
j.s.p.strategy.mp.environment.imports=label,file,write
j.s.p.strategy.mp.environment.import.label=!managed
j.s.p.strategy.mp.environment.import.label.type=string
j.s.p.strategy.mp.environment.import.file=multipass.config
j.s.p.strategy.mp.environment.import.file.type=string
j.s.p.strategy.mp.environment.import.write=true
j.s.p.strategy.mp.environment.import.write.type=boolean
package com.jinspired.jxinsight.probes.strategy.multipass;
import org.jinspired.probes.Probes;
import org.jinspired.probes.strategy.ProbesStrategy;
import org.jinspired.probes.strategy.ProbesStrategyFactory;
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static java.text.MessageFormat.format;
import static org.jinspired.probes.Probes.label;
import static org.jinspired.probes.Probes.name;
import static org.jinspired.probes.Probes.parse;
/**
* Created by william@autoletics.com on 08/03/2015.
*/
public final class StrategyFactory extends Thread
implements ProbesStrategyFactory {
static final Integer YES_INT = new Integer(1);
static final Integer NO_INT = new Integer(-1);
static final String YES_TAG = YES_INT.toString();
static final String NO_TAG = NO_INT.toString();
Options options;
static final ConcurrentHashMap<Probes.Name, Integer> global
= new ConcurrentHashMap<>();
@Override
public void init(Probes.Environment env) {
final Options o = new Options(
label(env.getString(name("label"))), // the matching label
env.getString(name("file")), // the voting file
env.getBoolean(name("write"))); // write voting file
final File f = new File(o.file);
// check whether the file is present
// it might not be if this is a first
// run of the playback with strategy
if(f.exists()) {
// we use a properties file for persistence
// of votes to allow use inspection & edit
final Properties p = new Properties();
try {
final ConcurrentHashMap<Probes.Name, Integer> m = global;
p.load(new FileInputStream(o.file));
// iterate over probe names loaded from file
final Iterator<Map.Entry<Object,Object>> it
= p.entrySet().iterator();
while(it.hasNext()) {
final Map.Entry e = it.next();
// place past result in map
m.put(
parse(e.getKey().toString()),
e.getValue().equals(YES_TAG) ? YES_INT : NO_INT);
}
} catch(IOException e) {
e.printStackTrace();
}
}
options = o;
// has (re)writing been enabled
if(o.write) {
// register a thread shutdown hook
// which when called writes out the
// name=vote to a properties file
Runtime.getRuntime().addShutdownHook(this);
}
}
@Override
public void run() {
// iterate through map writing out
// name=vote based on label match
final Iterator<Map.Entry<Probes.Name,Integer>> it
= global.entrySet().iterator();
final Properties p = new Properties();
while(it.hasNext()) {
final Map.Entry<Probes.Name, Integer> e
= it.next();
final Probes.Name n = e.getKey();
p.setProperty(
n.toString(),
e.getValue() == YES_INT && n.contains(options.label) ? YES_TAG : NO_TAG);
}
try {
final Options o = options;
// write contents of properties
// table to the filesystem
p.store(new FileOutputStream(o.file),
format("label={0}, file={1}, write={2}",
o.label,
o.file,
o.write));
} catch(IOException e) {
e.printStackTrace();
}
}
/**
* Returns an implementation of a strategy used in deciding whether a probe (method) is metered
*
* @param ctx the thread context
* @return the strategy used for probe metering voting purposes
*/
@Override
public ProbesStrategy create(Probes.Context ctx) {
return new Strategy(options);
}
/**
* A thread specific (i.e threadsafe) strategy implementation class that
* stores past recollections within a properties file for retreival
* across multi passes through the same simulated playback (memory recall)
*/
static final class Strategy implements ProbesStrategy {
final Options options;
final IdentityHashMap<Probes.Name, Integer> local = new IdentityHashMap();
Strategy( Options options ) {this.options = options;}
@Override
public int vote(Probes.Probe p) {
final Probes.Name n = p.getName();
Integer v;
// check whether the thread has
// seen this probe name before
if((v = local.get(n)) == null) {
// check whether the probe name
// is mapped globally already
if((v = global.get(n)) == null) {
// start off with a YES vote
// though must recheck at
// end of run in case the
// probe name was disabled
global.putIfAbsent(n, v = YES_INT);
}
// put the result into the
// local name->vote map
local.put(n, v);
}
return v;
}
}
/**
* A class holding strategy configuration
*/
static final class Options {
final Probes.Label label;
final String file;
final boolean write;
Options(Probes.Label label,
String file,
boolean write) {
this.file = file;
this.label = label;
this.write = write;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment