package org.fi;
import jol.core.JolSystem;
import jol.core.Runtime;
import jol.types.basic.BasicTupleSet;
import jol.types.basic.Tuple;
import jol.types.basic.TupleSet;
import jol.types.exception.JolRuntimeException;
import jol.types.exception.UpdateException;
import jol.types.table.TableName;
import jol.types.table.Table.Callback;
import jol.types.table.Table;
import org.fi.*;
import java.io.*;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
public class FrogServer {
public static final int JOL_LOAD_PORT = 6501;
private JolSystem system;
private static String fnAd = FrogServer.getAddress();
private int violationId = 0;
public final static String sdir
= FMLogic.HADOOP_STORAGE_DIR + "dfs/name1/current/";
public final static String imageFile = sdir + "fsimage";
public final static String editsFile = sdir + "edits";
public final static String editsNewFile = sdir + "edits.new";
public final static String imageCkptFile = sdir + "fsimage.ckpt";
public final static String frogOutputFile = FMLogic.TMPFI + "frogOutput.txt";
public final static String RESET_FROG_FLAG_FILE = FMLogic.TMPFI + "resetFrogFlag";
private static PrintStream ps;
BufferedReader stdin = new BufferedReader
(new InputStreamReader(System.in));
// ##################################################################
// ##################################################################
// ## ##
// ## S E T U P S T U F F ##
// ## ##
// ##################################################################
// ##################################################################
// *********************************
public FrogServer() {
try {
// startup core stuffs
this.system = Runtime.create(Runtime.DEBUG_WATCH, System.out, JOL_LOAD_PORT);
install("model.olg");
install("spec.olg");
this.system.start();
// setup print stream
resetFrog();
// print initial
PrintTable.start(system);
// testManual();
Thread.sleep(500);
Util.MESSAGE(ps, "FrogServer is ready (after sleeping for 0.5 second) !!!");
} catch (Exception e) {
Util.EXCEPTION(ps, "FrogServer.new()", e);
System.exit(0);
}
}
// *********************************
public void processFrogEvent(FMJoinPoint fjp, FMStackTrace fst, FrogEvent fev) {
// processFrogEvent is the only main entrance to the
// JOL spec, so we reset everything here
checkResetFrog();
printProcessHeader(fev);
Util.scheduleEvent(fjp, fst, ps, system, fev.pn, fev.tn, fev.tuple);
Util.scheduleDirectEvent(ps, system, "spec", "manual_eval", Util.r());
// then I need to print all tables here
PrintTable.printAllTables();
checkAllViolations(fjp, fst, fev);
}
// **************************************
public void printProcessHeader(FrogEvent fev) {
String buf = String.format("# [new frog event][" + fev + "] \n");
Util.print(ps, "\n");
Util.print(ps, "\n");
Util.print(ps, "# ########################################################\n");
Util.print(ps, "# ########################################################\n");
Util.print(ps, buf);
Util.print(ps, "# ########################################################\n");
Util.print(ps, "# ########################################################\n");
Util.print(ps, "\n");
Util.print(ps, "\n");
}
// *********************************
// This is a stupid but fast way to check if we need to
// reset frog or not. The "good" way is to use FMAdmin
// so that we can send a reset command from the command line
// but the problem is that, if we want to do that we must
// use bin/hadoop FMAdmin which is slow and must use RPC
// to the FI server. So let's just use file existence to do
// this
private void checkResetFrog() {
File f = new File(RESET_FROG_FLAG_FILE);
if (!f.exists())
return;
// if this flag exists, then someone has told me to
resetFrog();
// delete the file
try { f.delete(); } catch (Exception e) {
Util.ERROR(ps, "problem in reset frog");
}
}
// *********************************
private void resetFrog() {
// clear some stuffs up, so let's do that
resetPrintStream();
// clear frog tables
resetFrogTables();
// then print let's see what we have
PrintTable.printAllTables();
}
// *********************************
private void resetPrintStream() {
try {
if (ps != null) {
ps.flush();
ps.close();
}
FileOutputStream fos = new FileOutputStream(frogOutputFile);
ps = new PrintStream(fos);
Util.MESSAGE(ps, "new frog output");
} catch (Exception e) {
Util.EXCEPTION("Can't open " + frogOutputFile, e);
System.exit(-1);
}
}
// *********************************
private void resetFrogTables() {
// delete all ...
Util.scheduleDirectEvent(ps, system, "model", "reset", Util.r4());
// then run init again ...
Util.scheduleDirectEvent(ps, system, "spec", "spec_init", "Fn");
}
// *********************************
public static PrintStream getPs() {
return ps;
}
// *********************************
private void install(String olgPath) throws JolRuntimeException {
this.system.install("model", ClassLoader.getSystemResource(olgPath));
this.system.evaluate();
}
// *********************************
private static String getAddress() {
return "tcp:localhost:" + JOL_LOAD_PORT;
}
// *********************************
private void checkAllViolations(FMJoinPoint fjp, FMStackTrace fst, FrogEvent fev) {
// manual
checkLostState(fjp, fst, fev);
// automatic (per table in spec)
checkViolation(fjp, fst, fev, "spec", "failover_violation");
}
// *********************************
// check violation automatically, given progName pn and tableName tn
private void checkViolation(FMJoinPoint fjp, FMStackTrace fst,
FrogEvent fev, String pn, String tn) {
SortedMap<String,String> sm_ss = null;
// if table is empty, no violation, return
if (Util.isTableEmpty(system, pn, tn))
return;
// check each table that represents violation
if (tn.equals("failover_violation"))
sm_ss = PrintTable.getTableMap(pn, tn);
if (sm_ss == null)
return;
reportViolation(fjp, fst, fev, tn, sm_ss);
}
// *********************************
// check consistency manually here
private void checkLostState(FMJoinPoint fjp, FMStackTrace fst, FrogEvent fev) {
// let's pull server state first
Table tbl;
SortedMap<String,String> server_state = new TreeMap<String, String>();
SortedMap<String,String> user_state = new TreeMap<String, String>();
SortedMap<String,String> lost_state = new TreeMap<String, String>();
tbl = Util.getTable(system, "spec", "server_state");
for (Tuple t : tbl.tuples())
server_state.put((String) t.value(0), (String) t.value(1));
tbl = Util.getTable(system, "model", "user_state");
for (Tuple t : tbl.tuples())
user_state.put((String) t.value(0), (String) "");
Set s = user_state.entrySet();
Iterator itr = s.iterator();
while(itr.hasNext()) {
String path = (String) ((Map.Entry)itr.next()).getKey();
if (!server_state.containsKey(path)) {
lost_state.put(path, "");
}
}
if (lost_state.size() != 0) {
reportViolation(fjp, fst, fev, "lost_state", lost_state);
}
}
// *********************************
private void reportViolation(FMJoinPoint fjp, FMStackTrace fst, FrogEvent fev,
String tableName, SortedMap<String,String> tableMap) {
String buf = "";
buf += String.format("\n\n");
buf += String.format("## ################################################\n");
buf += String.format("## Failed Specification : %s \n", tableName);
buf += String.format("## ################################################\n");
buf += String.format("## \n");
buf += String.format("## Violated state (table map): \n");
int i = 0;
Set s = tableMap.entrySet();
Iterator itr = s.iterator();
while(itr.hasNext()) {
buf += String.format(" [%02d] %s \n", i++, ((Map.Entry)itr.next()).getValue());
}
buf += String.format("## \n");
buf += String.format("## FMJoinPoint: \n %s \n", fjp);
buf += String.format("## \n");
buf += String.format("## FrogEvent: \n %s \n", fev);
buf += String.format("## \n");
buf += String.format("## FMStackTrace: \n%s \n", fst);
buf += String.format("## \n");
buf += String.format("## ################################################ END\n\n");
Util.print(ps, buf);
}
// *********************************
private void testManualNiceExampleForNeil()
throws InterruptedException, JolRuntimeException, IOException {
// Util.scheduleEvent(ps, system, "model", "user_state", "/dir1");
// Util.scheduleEvent(ps, system, "model", "user_state", "/dir2");
// Util.scheduleEvent(ps, system, "spec", "server_state", "/dir1", "bla");
// PrintTable.printAllTables();
// stdin.readLine();
// I have to manually run eval here ..
// Util.scheduleEvent(ps, system, "spec", "manual_eval", Util.r());
// PrintTable.printAllTables();
// stdin.readLine();
// Util.scheduleEvent(ps, system, "spec", "server_state", "/dir2", "bla");
// PrintTable.printAllTables();
// stdin.readLine();
// but this time it doesn't work. lost_state is still 0
// Util.scheduleEvent(ps, system, "spec", "manual_eval", Util.r());
// PrintTable.printAllTables();
// stdin.readLine();
// stop();
// System.exit(0);
}
// *********************************
private void testManual()
throws InterruptedException, JolRuntimeException, IOException {
// Util.scheduleEvent(ps, system, "model", "user_state", "/dir1");
// Util.scheduleEvent(ps, system, "model", "user_state", "/dir2");
// Util.scheduleEvent(ps, system, "spec", "server_state", "/dir1", "bla");
// Util.scheduleEvent(ps, system, "spec", "manual_eval", Util.r());
// PrintTable.printAllTables();
// stdin.readLine();
// Util.scheduleEvent(ps, system, "model", "user_state", "/dir3");
// Util.scheduleEvent(ps, system, "model", "user_state", "/dir4");
// Util.scheduleEvent(ps, system, "spec", "server_state", "/dir2", "bla");
// Util.scheduleEvent(ps, system, "spec", "manual_eval", Util.r());
// PrintTable.printAllTables();
// I have to manually run eval here ..
// stdin.readLine();
// Util.scheduleEvent(ps, system, "spec", "server_state", "/dir2", "bla");
// PrintTable.printAllTables();
// stdin.readLine();
// but this time it doesn't work. lost_state is still 0
// Util.scheduleEvent(ps, system, "spec", "manual_eval", Util.r());
// PrintTable.printAllTables();
// stdin.readLine();
// stop();
// System.exit(0);
}
// *********************************
private void stop() {
this.system.shutdown();
}
}