Compare commits
14 Commits
Author | SHA1 | Date |
---|---|---|
Dan Ballard | 15b9abbc4a | |
Dan Ballard | 18d640089e | |
Dan Ballard | 05e650c541 | |
Dan Ballard | 5c5d71e064 | |
Dan Ballard | a3ccd10c8f | |
Dan Ballard | a5b83691e6 | |
Dan Ballard | 9153c0896b | |
Dan Ballard | f84a926317 | |
Dan Ballard | 14f98cba53 | |
Dan Ballard | 922ab08c86 | |
Dan Ballard | 872929e730 | |
Dan Ballard | 27c3dfc692 | |
Dan Ballard | fa74d77158 | |
Dan Ballard | 1123dc8d0e |
|
@ -340,7 +340,7 @@ class ConnHandler implements Runnable {
|
||||||
userAgent = header;
|
userAgent = header;
|
||||||
|
|
||||||
}
|
}
|
||||||
System.out.println(i + ": '" + header + "'");
|
//System.out.println(i + ": '" + header + "'");
|
||||||
i++;
|
i++;
|
||||||
header = sin.readLine();
|
header = sin.readLine();
|
||||||
}
|
}
|
||||||
|
@ -353,6 +353,7 @@ class ConnHandler implements Runnable {
|
||||||
byte[] get_resp= null;
|
byte[] get_resp= null;
|
||||||
String CODE = "200 OK";
|
String CODE = "200 OK";
|
||||||
int resp_length = 0;
|
int resp_length = 0;
|
||||||
|
String content_type = "text/html";
|
||||||
if (type == TYPE_GET) {
|
if (type == TYPE_GET) {
|
||||||
reqLine = reqLine.substring(4);
|
reqLine = reqLine.substring(4);
|
||||||
res.log("GET " + reqLine);
|
res.log("GET " + reqLine);
|
||||||
|
@ -361,6 +362,11 @@ class ConnHandler implements Runnable {
|
||||||
CODE = "404 Not Found";
|
CODE = "404 Not Found";
|
||||||
}
|
}
|
||||||
resp_length = get_resp.length;
|
resp_length = get_resp.length;
|
||||||
|
String end = reqLine.substring(reqLine.length()-4);
|
||||||
|
if (end == ".js")
|
||||||
|
content_type = "text/javascript";
|
||||||
|
else if (end == "css")
|
||||||
|
content_type= "text/css";
|
||||||
} else {
|
} else {
|
||||||
// No forward
|
// No forward
|
||||||
if (reqLine.equals("")) {
|
if (reqLine.equals("")) {
|
||||||
|
@ -385,7 +391,7 @@ class ConnHandler implements Runnable {
|
||||||
SimpleDateFormat formater = new SimpleDateFormat("E, d M y H:m:s z");
|
SimpleDateFormat formater = new SimpleDateFormat("E, d M y H:m:s z");
|
||||||
sout.print("HTTP/1.1 " + CODE + "\r\n"+
|
sout.print("HTTP/1.1 " + CODE + "\r\n"+
|
||||||
"Date: " + formater.format(now) + "\r\n" +
|
"Date: " + formater.format(now) + "\r\n" +
|
||||||
"Content-Type: text/html; charset=UTF-8\r\n" +
|
"Content-Type: " + content_type + "; charset=UTF-8\r\n" +
|
||||||
"Server: Cortex @ " + Integer.toString(res.PORT) + "\r\n");
|
"Server: Cortex @ " + Integer.toString(res.PORT) + "\r\n");
|
||||||
|
|
||||||
// Print response
|
// Print response
|
||||||
|
|
|
@ -146,6 +146,9 @@ class ResManager {
|
||||||
putSite("shell.html", readURL(new URL(baseurl + "shell.html")));
|
putSite("shell.html", readURL(new URL(baseurl + "shell.html")));
|
||||||
putSite("ajax.js", readURL(new URL(baseurl + "ajax.js")));
|
putSite("ajax.js", readURL(new URL(baseurl + "ajax.js")));
|
||||||
|
|
||||||
|
putSite("cortex.js", readURL(new URL(baseurl + "cortex.js")));
|
||||||
|
putSite("basicClient.html", readURL(new URL(baseurl + "basicClient.html")));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>Client</title>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
.page {
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
top: 40px;
|
||||||
|
left: 10px;
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 5px;
|
||||||
|
width: 550px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
border: 1px solid black;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
padding: 0px;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script src="cortex.js" ></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="statusLabel"></div>
|
||||||
|
<div id="numberOfNodes">Number of nodes: <script> document.write(numberOfNodes); </script></div>
|
||||||
|
<div id="connections">Connected to:</div>
|
||||||
|
<div id="dlc">DLC:</div>
|
||||||
|
<input id="networkAddr"><input type="button" value="Join Network" onClick="join_network(document.getElementById('networkAddr').value);"><br/>
|
||||||
|
<br />
|
||||||
|
<b>Log:</b> <input type="checkbox" value="log" id="logCheck"/>Log?<br/>
|
||||||
|
<textarea rows="7" cols="60" id="cortexLog" readonly="true"></textarea>
|
||||||
|
<br/>
|
||||||
|
<input type="button" value="Reload HTML" onclick="reloadHTML()" />
|
||||||
|
<br/><br/>
|
||||||
|
<input type="button" value="Kill Server" onClick="killServer()" />
|
||||||
|
|
||||||
|
<script language="javascript">cortex_start()</script>
|
807
client.html
807
client.html
|
@ -35,16 +35,10 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
var localNodeAddr = '';
|
|
||||||
var originURL = 'Unknown Source';
|
|
||||||
var connected = false;
|
|
||||||
var numberOfNodes = 0;
|
|
||||||
var connections = new Array();
|
|
||||||
|
|
||||||
var tests = new Array();
|
var tests = new Array();
|
||||||
var testLocks = new Array();
|
var testLocks = new Array();
|
||||||
var lockTrys = new Array();
|
|
||||||
var myLocks = new Array();
|
|
||||||
var runningTests = new Array();
|
var runningTests = new Array();
|
||||||
|
|
||||||
var rangeLocks = new Array();
|
var rangeLocks = new Array();
|
||||||
|
@ -54,280 +48,8 @@ var doneStage = 0;
|
||||||
|
|
||||||
var runTry = null;
|
var runTry = null;
|
||||||
|
|
||||||
var dlc = 0;
|
|
||||||
var msgQ = new Array();
|
|
||||||
|
|
||||||
function error(msg) {
|
|
||||||
log("ERROR: " + msg);
|
|
||||||
alert("ERROR: " + msg);
|
|
||||||
clearInterval(cronID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* basic ping function for local node
|
|
||||||
* if successful,
|
|
||||||
* if we haven't greeted the server, we do,
|
|
||||||
* otherwise nothing (just a heartbeat)
|
|
||||||
* if it fails, lets the user know we have lost
|
|
||||||
* connection to the node server
|
|
||||||
*/
|
|
||||||
function ping() {
|
|
||||||
var http = ajaxConnect();
|
|
||||||
|
|
||||||
var retfn = returnfn(http,
|
|
||||||
function(resp) {
|
|
||||||
if (!connected) {
|
|
||||||
connected = true;
|
|
||||||
greet();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function(resp) {
|
|
||||||
connected = false;
|
|
||||||
var html = "Connection to local Node failed. Try reloading from <a href=\"" + originURL + "\" target=\"window\">" + originURL + "</a>";
|
|
||||||
document.getElementById('statusLabel').innerHTML = html;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
ajaxSend(http, "cmd=ping\n\n", retfn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Greets the server
|
|
||||||
* so far just gets the server's IP and origin URL
|
|
||||||
*/
|
|
||||||
function greet() {
|
|
||||||
var http = ajaxConnect();
|
|
||||||
|
|
||||||
var retfn = returnfn(http,
|
|
||||||
function(resp) {
|
|
||||||
var arr = resp.split(" ");
|
|
||||||
localNodeAddr = arr[0];
|
|
||||||
originURL = arr[1];
|
|
||||||
document.getElementById('statusLabel').innerHTML = "I am <b>" + localNodeAddr + "</b>";
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
ajaxSend(http, "cmd=greet\n\n", retfn);
|
|
||||||
}
|
|
||||||
|
|
||||||
function killServer() {
|
|
||||||
announceDead(localNodeAddr);
|
|
||||||
var http = ajaxConnect();
|
|
||||||
|
|
||||||
var retfn = returnfn(http,
|
|
||||||
function(resp) {
|
|
||||||
// got a resp, server not dead
|
|
||||||
killServer();
|
|
||||||
});
|
|
||||||
ajaxSend(http, "cmd=kill\n\n", retfn);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLog() {
|
|
||||||
var http = ajaxConnect();
|
|
||||||
|
|
||||||
|
|
||||||
var retfn = returnfn(http,
|
|
||||||
function(resp) {
|
|
||||||
var log = document.getElementById('log');
|
|
||||||
//alert("getLog() resp: " + resp);
|
|
||||||
log.value = resp + log.value;
|
|
||||||
// Since getLog returns (a call back is called later)
|
|
||||||
// this is tail recursive friendly
|
|
||||||
getLog();
|
|
||||||
});
|
|
||||||
ajaxSend(http, "cmd=getLog\n\n", retfn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// two digits
|
|
||||||
function d2(str) {
|
|
||||||
if (str <10)
|
|
||||||
return "0"+str;
|
|
||||||
else
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTime() {
|
|
||||||
var date = new Date();
|
|
||||||
return d2(date.getHours()) + ":" + d2(date.getMinutes()) + ":" + d2(date.getSeconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
var logCheckElem = null;
|
|
||||||
function log(str) {
|
|
||||||
if (logCheckElem == null)
|
|
||||||
logCheckElem = document.getElementById("logCheck");
|
|
||||||
if (logCheckElem.checked == true) {
|
|
||||||
str = getTime() + ": " + str+"\n";
|
|
||||||
var log = document.getElementById('log');
|
|
||||||
log.value = str + log.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function log2(str) {
|
|
||||||
str = getTime() + ": " + str+"\n";
|
|
||||||
var log = document.getElementById('log');
|
|
||||||
log.value = str + log.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMsgs() {
|
|
||||||
var http = ajaxConnect();
|
|
||||||
var retfn = returnfn(http,
|
|
||||||
function(resp) {
|
|
||||||
//log("getMsgs: len > 0");
|
|
||||||
log("getMsgs: " + resp);
|
|
||||||
queueMsgs(resp);
|
|
||||||
// Since getMsgs returns (a call back is called later)
|
|
||||||
// this is tail recursive friendly
|
|
||||||
getMsgs();
|
|
||||||
});
|
|
||||||
ajaxSend(http, "cmd=getMsgs\n\n", retfn);
|
|
||||||
}
|
|
||||||
|
|
||||||
function connectedTo(addr) {
|
|
||||||
if (addr == localNodeAddr)
|
|
||||||
return true;
|
|
||||||
for(i = 0; i < connections.length; i++) {
|
|
||||||
if (connections[i] == addr)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addConnection(addr) {
|
|
||||||
if(!connectedTo(addr)) {
|
|
||||||
connections[connections.length] = addr;
|
|
||||||
numberOfNodes++;
|
|
||||||
return true;
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function genNodeList() {
|
|
||||||
var str = "";//localNodeAddr+",";
|
|
||||||
for (var i =0; i < connections.length; i++) {
|
|
||||||
str += connections[i] + ",";
|
|
||||||
}
|
|
||||||
if (connections.length > 0)
|
|
||||||
str = str.substring(0,str.length-1);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function advertiseNewNode(addr) {
|
|
||||||
var m = new Object();
|
|
||||||
m['query'] = "newNode";
|
|
||||||
m['addr'] = addr;
|
|
||||||
bcastMsg(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
function announceDead(addr) {
|
|
||||||
var m = new Object();
|
|
||||||
m['query'] = "deadNode";
|
|
||||||
m['addr'] = addr;
|
|
||||||
bcastMsg(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleNewNode(resp, welcome) {
|
|
||||||
|
|
||||||
if (welcome == null)
|
|
||||||
welcome = false;
|
|
||||||
var addr = resp.addr;
|
|
||||||
//log2("handle new node " + addr + " from " + resp.origin);
|
|
||||||
|
|
||||||
// handles re adding if reloaded html
|
|
||||||
//if (!connectedTo(addr))
|
|
||||||
//{
|
|
||||||
var ret = genNodeList();
|
|
||||||
var n = addConnection(addr);
|
|
||||||
if (welcome == true) {
|
|
||||||
sendDLC(addr);
|
|
||||||
sendWelcome(ret, addr);
|
|
||||||
sendLocks(addr);
|
|
||||||
sendTests(addr);
|
|
||||||
}
|
|
||||||
if (n == true) {
|
|
||||||
sendReqs(addr);
|
|
||||||
advertiseNewNode(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendDLC(addr) {
|
|
||||||
var m = new Object();
|
|
||||||
m.query = "DLC";
|
|
||||||
sendMsg(m, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendReqs(addr) {
|
|
||||||
for(i in lockTrys) {
|
|
||||||
var lock = lockTrys[i];
|
|
||||||
if (lock == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var m = new Object();
|
|
||||||
m["query"] = "getLock";
|
|
||||||
m["type"] = i;
|
|
||||||
m["name"] = lock["name"];
|
|
||||||
m["time"] = lock.time;
|
|
||||||
m["addr"] = localNodeAddr;
|
|
||||||
if (i == "range") {
|
|
||||||
m["start"] = lock.start;
|
|
||||||
m["end"] = lock.end;
|
|
||||||
}
|
|
||||||
sendMsg(m, addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendWelcome(addrList, addr) {
|
|
||||||
var m = new Object();
|
|
||||||
m["query"] = "welcome";
|
|
||||||
m["addrList"] = addrList;
|
|
||||||
sendMsg(m, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendLocks(addr) {
|
|
||||||
for (var i in testLocks) {
|
|
||||||
log ("testLog[" + i + "]");
|
|
||||||
var l = testLocks[i];
|
|
||||||
var m = new Object();
|
|
||||||
|
|
||||||
m["query"] = "addLock";
|
|
||||||
m["type"] = "test";
|
|
||||||
m["name"] = l["name"];
|
|
||||||
m["addr"] = l["addr"];
|
|
||||||
m["locked"] = l["locked"];
|
|
||||||
m["perjob"] =
|
|
||||||
|
|
||||||
|
|
||||||
m["time"] = l["time"];
|
|
||||||
if (l.running) {
|
|
||||||
m["running"] = true;
|
|
||||||
m["min"] = l["min"];
|
|
||||||
m["max"] = l["max"];
|
|
||||||
m["perjob"] = l["perjob"];
|
|
||||||
}
|
|
||||||
sendMsg(m, addr);
|
|
||||||
}
|
|
||||||
for (var i in rangeLocks) {
|
|
||||||
var r = rangeLocks[i];
|
|
||||||
while(r) {
|
|
||||||
log("rangeLock[" + i +" [" + r.start + "-" + r.end +"]]");
|
|
||||||
var m = new Object();
|
|
||||||
m["query"] = "addLock";
|
|
||||||
m["type"] = "range";
|
|
||||||
m["name"] = i;
|
|
||||||
m["addr"] = r["addr"]
|
|
||||||
m["locked"] = r["locked"];
|
|
||||||
m["start"] = r["start"];
|
|
||||||
m["end"] = r["end"];
|
|
||||||
m["done"] = r["done"];
|
|
||||||
if (r['results'])
|
|
||||||
m["results"] = r["results"];
|
|
||||||
|
|
||||||
sendMsg(m, addr);
|
|
||||||
r = r.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendTests(addr) {
|
function sendTests(addr) {
|
||||||
for(var i in tests) {
|
for(var i in tests) {
|
||||||
|
@ -336,32 +58,6 @@ function sendTests(addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAddLock(resp) {
|
|
||||||
if(resp['locked'] == null)
|
|
||||||
resp['locked'] = false;
|
|
||||||
// dont add/overwrite if exists?
|
|
||||||
var lock = retrieveLock(resp);
|
|
||||||
|
|
||||||
if (resp['type'] == "test" ) {//&& (lock == null || lock.addr == null)) {
|
|
||||||
var locks = getLockType(resp['type']);
|
|
||||||
|
|
||||||
|
|
||||||
locks[resp['name']] = resp
|
|
||||||
if(resp['running'] == true) {
|
|
||||||
runningTests.push(resp['name']);
|
|
||||||
}
|
|
||||||
} else if(resp['type'] == "range" && lock.addr == null) {
|
|
||||||
log("Add range lock: " + resp['name'] + " (" + resp['start'] + " to " + resp['end'] + ") : ");
|
|
||||||
var lock = getRangeLock(resp['name'], resp['start'], resp['end']);
|
|
||||||
|
|
||||||
lock.addr = resp['addr'];
|
|
||||||
lock.locked = resp['locked'];
|
|
||||||
lock.done = resp['done'];
|
|
||||||
lock.results = resp['results'];
|
|
||||||
lock.name = resp['name'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function packArray(arr) {
|
function packArray(arr) {
|
||||||
if (arr instanceof Object) {
|
if (arr instanceof Object) {
|
||||||
var str = "{";
|
var str = "{";
|
||||||
|
@ -432,108 +128,6 @@ function packResults(res) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
function packObject(m, defaultValue) {
|
|
||||||
|
|
||||||
var str = "";
|
|
||||||
for (var i in m) {
|
|
||||||
if (m[i] == '')
|
|
||||||
{
|
|
||||||
if (defaultValue == null) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
m[i] = defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == "results") {
|
|
||||||
str += i + "=" + packResults(m[i]) + "\n";
|
|
||||||
} else {
|
|
||||||
str += i + "=" + m[i] + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeNodeRangeLocks(addr) {
|
|
||||||
for(var i in rangeLocks) {
|
|
||||||
log("freeing " + i + " locks");
|
|
||||||
var rlock = rangeLocks[i];
|
|
||||||
while (rlock != null) {
|
|
||||||
log("looking at " + i + " (" + rlock.start + " to " + rlock.end + ") : " + rlock.addr);
|
|
||||||
if (rlock.addr == addr) {
|
|
||||||
log("unlocking");
|
|
||||||
rlock.locked = false;
|
|
||||||
}
|
|
||||||
rlock = rlock.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function disconnect(addr) {
|
|
||||||
log("--------------DISCONNECT " + addr + "----------");
|
|
||||||
// remove from connections list
|
|
||||||
for (var i=0; i < connections.length; i++) {
|
|
||||||
if (connections[i] == addr) {
|
|
||||||
connections.splice(i,1);
|
|
||||||
numberOfNodes--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove locks
|
|
||||||
// test locks
|
|
||||||
for(var i in testLocks) {
|
|
||||||
var lock = testLocks[i];
|
|
||||||
if (!lock)
|
|
||||||
continue;
|
|
||||||
if (lock.addr == addr) {
|
|
||||||
lock.locked = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// range locks
|
|
||||||
removeNodeRangeLocks(addr);
|
|
||||||
|
|
||||||
log("disconnect: freeing range locks");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendMsg(m, addr, time, mtype) {
|
|
||||||
if(time == null)
|
|
||||||
time = dlc;
|
|
||||||
if(mtype == null)
|
|
||||||
mtype = "single";
|
|
||||||
|
|
||||||
var str = "cmd=sendMsg\n";
|
|
||||||
str += "origin=" + localNodeAddr + "\n";
|
|
||||||
str += "dlc=" + time + "\n";
|
|
||||||
str += "mtype=" + mtype + "\n";
|
|
||||||
|
|
||||||
str += packObject(m);
|
|
||||||
|
|
||||||
str += "\n";
|
|
||||||
log ("SEND: " + str);
|
|
||||||
|
|
||||||
var http = ajaxConnect();
|
|
||||||
var retfn = returnfn(http, null,
|
|
||||||
function() {
|
|
||||||
disconnect(addr);
|
|
||||||
announceDead(addr);
|
|
||||||
log("ERROR> message to " + addr + " not delivered: '" + str + "'");
|
|
||||||
});
|
|
||||||
|
|
||||||
ajaxSend(http, str, retfn, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
function bcastMsg(m) {
|
|
||||||
if (m.query != "heartBeat")
|
|
||||||
dlc ++;
|
|
||||||
//log("BCAST conLen: " + connections.length);
|
|
||||||
for(var i=0; i < connections.length; i++) {
|
|
||||||
log("bcast "+ i +" " + m.query + " to " + connections[i] + " dlc:" + dlc);
|
|
||||||
sendMsg(m, connections[i], dlc, "bcast");
|
|
||||||
//log("back from sendMsg, i:" + i + " conlen:" + connections.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function encodeStr(str) {
|
function encodeStr(str) {
|
||||||
var res="";
|
var res="";
|
||||||
|
@ -573,69 +167,19 @@ function decodeStr(str) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMsg(resp) {
|
|
||||||
//log("addMsg mdlc: " + resp.dlc + " mqlen: " + msgQ.length + " type:" + resp.mtype + " query: " + resp.query);
|
|
||||||
for(var i=msgQ.length-1; i>=0; i--) {
|
|
||||||
//log("resp.dlc:" + resp.dlc + " msgQ[i].dlc:" + msgQ[i].dlc);
|
|
||||||
if (resp.dlc > msgQ[i].dlc) {
|
|
||||||
//log("moving " + i + " to " + (i+1));
|
|
||||||
msgQ[i+1] = msgQ[i];
|
|
||||||
} else {
|
|
||||||
//log("first, moving " + i + " to " + (i+1));
|
|
||||||
//msgQ[i+1] = msgQ[i];
|
|
||||||
//log("putting msg in " + i + " + 1, RETURN");
|
|
||||||
msgQ[i+1] = resp;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//log("END: putting msg in 0");
|
|
||||||
msgQ[0] = resp;
|
|
||||||
}
|
|
||||||
|
|
||||||
function queueMsgs(mstr) {
|
|
||||||
log("GOT messages: " + mstr);
|
|
||||||
var resps = mstr.split("\n\n");
|
|
||||||
for(var rcount=0; rcount < resps.length; rcount++) {
|
|
||||||
var resp = resps[rcount];
|
|
||||||
if (resp == "")
|
|
||||||
continue;
|
|
||||||
resp = parseResp(resp);
|
|
||||||
if (resp.query == "DLC") {
|
|
||||||
dlc = resp.dlc;
|
|
||||||
//var m = new Object();
|
|
||||||
//m.query = "DLC";
|
|
||||||
//bcastMsg(m);
|
|
||||||
} else {
|
|
||||||
addMsg(resp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var s = "QUEUE: "
|
|
||||||
for (var i =0; i< msgQ.length; i++) {
|
|
||||||
s += msgQ[i].dlc + " ";
|
|
||||||
}
|
|
||||||
log(s);
|
|
||||||
log("mqlen:" + msgQ.length);
|
|
||||||
while (msgQ.length>0 && ((msgQ[msgQ.length-1].dlc - 1) <= dlc)) {
|
|
||||||
var r = msgQ.pop();
|
|
||||||
log("mdlc: " + r.dlc + " dlc: " + dlc + " mqlen: " + msgQ.length + " type:" + r.mtype + " query: " + r.query);
|
|
||||||
if (r.mtype == "bcast")
|
|
||||||
dlc = r.dlc
|
|
||||||
processMsg(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function processMsg(resp) {
|
function processMsg(resp) {
|
||||||
if (resp["query"] == "join_network") {
|
// if (resp["query"] == "join_network") {
|
||||||
log("Message join_network received");
|
// log("Message join_network received");
|
||||||
handleNewNode(resp, true);
|
// handleNewNode(resp, true);
|
||||||
} else if (resp["query"] == "welcome") {
|
// } else if (resp["query"] == "welcome") {
|
||||||
handleWelcome(resp);
|
// handleWelcome(resp);
|
||||||
} else if (resp["query"] == "newNode") {
|
// } else if (resp["query"] == "newNode") {
|
||||||
//addConnection(resp["addr"]);
|
// //addConnection(resp["addr"]);
|
||||||
handleNewNode(resp, false);
|
// handleNewNode(resp, false);
|
||||||
} else if (resp["query"] == "deadNode") {
|
// } else if (resp["query"] == "deadNode") {
|
||||||
disconnect(resp["addr"]);
|
// disconnect(resp["addr"]);
|
||||||
} else if(resp["query"] == "addLock") {
|
} else if(resp["query"] == "addLock") {
|
||||||
handleAddLock(resp);
|
handleAddLock(resp);
|
||||||
} else if (resp["query"] == "getLock") {
|
} else if (resp["query"] == "getLock") {
|
||||||
|
@ -650,120 +194,16 @@ function processMsg(resp) {
|
||||||
handleActivateJob(resp);
|
handleActivateJob(resp);
|
||||||
} else if(resp["query"] == "results") {
|
} else if(resp["query"] == "results") {
|
||||||
handleResults(resp);
|
handleResults(resp);
|
||||||
} else if(resp["query"] == "new_network") {
|
// } else if(resp["query"] == "new_network") {
|
||||||
join_network(resp["addr"], false);
|
// join_network(resp["addr"], false);
|
||||||
} else if(resp["query"] == "heartBeat") {
|
// } else if(resp["query"] == "heartBeat") {
|
||||||
// do nothing;
|
// // do nothing;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
log("Error: Unkown message '" + resp["query"] + "' received from " + resp["origin"]);
|
log("Error: Unkown message '" + resp["query"] + "' received from " + resp["origin"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleWelcome(resp) {
|
|
||||||
log("Welcome message received");
|
|
||||||
//var myNodes = genNodeList();
|
|
||||||
addConnection(resp['origin']);
|
|
||||||
if (resp['addrList']){
|
|
||||||
var nodes = resp['addrList'].split(",");
|
|
||||||
for(var i=0; i < nodes.length; i++){
|
|
||||||
addConnection(nodes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(var i =0; i< connections.length; i++) {
|
|
||||||
var addr = connections[i];
|
|
||||||
if (addr == localNodeAddr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
advertiseNewNode(addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractHost(url) {
|
|
||||||
// http: or file:
|
|
||||||
var host = url.substr(5);
|
|
||||||
while (host.charAt(0) == '/')
|
|
||||||
host = host.substr(1);
|
|
||||||
var end = host.indexOf('/');
|
|
||||||
|
|
||||||
if (end > 0 )
|
|
||||||
host = host.substr(0, end);
|
|
||||||
return host;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function setStatus() {
|
|
||||||
document.getElementById('numberOfNodes').innerHTML = "Number of nodes: " + numberOfNodes;
|
|
||||||
document.getElementById('connections').innerHTML = "Connected to: " + genNodeList();
|
|
||||||
document.getElementById('dlc').innerHTML = "DLC: " + dlc;
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
if (connected == false)
|
|
||||||
return;
|
|
||||||
numberOfNodes = 1;
|
|
||||||
if (originURL.substr(0, 4) == "file") {
|
|
||||||
// we are the first
|
|
||||||
//numberOfNodes = 1; // ourself
|
|
||||||
log("Loaded from file");
|
|
||||||
// now we sit and wait
|
|
||||||
} else { // it was http, so we were loaded from another node
|
|
||||||
log("Loaded from " + originURL);
|
|
||||||
originAddress = extractHost(originURL);
|
|
||||||
|
|
||||||
join_network(originAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseResp(resp) {
|
|
||||||
var lines = resp.split("\n");
|
|
||||||
var arr = [];
|
|
||||||
for(var i=0; i < lines.length; i++) {
|
|
||||||
//var kv = lines[i].split("=");
|
|
||||||
var mid = lines[i].indexOf("=");
|
|
||||||
var kv = new Array();
|
|
||||||
kv[0] = lines[i].substring(0, mid);
|
|
||||||
kv[1] = lines[i].substring(mid+1);
|
|
||||||
if (kv[1] == "true")
|
|
||||||
kv[1] = true;
|
|
||||||
else if(kv[0] == "false")
|
|
||||||
kv[1] = false;
|
|
||||||
else if (kv[0] == "dlc" ||
|
|
||||||
kv[0] == "start" ||
|
|
||||||
kv[0] == "end" ||
|
|
||||||
kv[0] == "min" ||
|
|
||||||
kv[0] == "max")
|
|
||||||
kv[1] = Number(kv[1]);
|
|
||||||
else if (kv[0] == "results")
|
|
||||||
kv[1] = unpackResults(kv[1]);
|
|
||||||
arr[kv[0]] = kv[1];
|
|
||||||
}
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function join_network(address, bcast) {
|
|
||||||
if(bcast == null) {
|
|
||||||
bcast = true;
|
|
||||||
}
|
|
||||||
log("join_network -> " + address);
|
|
||||||
var m = new Object();
|
|
||||||
m["query"] = "join_network";
|
|
||||||
m["addr"] = localNodeAddr;
|
|
||||||
//m["nodes"] = genNodeList();
|
|
||||||
sendMsg(m, address);
|
|
||||||
if (bcast == true) {
|
|
||||||
m = new Object();
|
|
||||||
m["query"] = "new_network";
|
|
||||||
m["addr"] = address;
|
|
||||||
bcastMsg(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var runCount = 0;
|
var runCount = 0;
|
||||||
var workMod = 1;
|
var workMod = 1;
|
||||||
|
@ -816,7 +256,7 @@ function cron() {
|
||||||
if (runCount % 10 == 0) {
|
if (runCount % 10 == 0) {
|
||||||
ping();
|
ping();
|
||||||
//getLog();
|
//getLog();
|
||||||
setStatus();
|
//setStatus();
|
||||||
checkLocks();
|
checkLocks();
|
||||||
updateTestsStatus();
|
updateTestsStatus();
|
||||||
if ( doneStage == 1 ) {
|
if ( doneStage == 1 ) {
|
||||||
|
@ -836,46 +276,16 @@ function cron() {
|
||||||
if (runCount % 20 == 0)
|
if (runCount % 20 == 0)
|
||||||
updateResults();
|
updateResults();
|
||||||
|
|
||||||
if (runCount % 300 == 0)
|
//if (runCount % 300 == 0)
|
||||||
heartBeat();
|
// heartBeat();
|
||||||
|
|
||||||
// 180 seconds, or 3 minutes
|
// 180 seconds, or 3 minutes
|
||||||
if (runCount == 1800)
|
/*if (runCount == 1800)
|
||||||
runCount = 0;
|
runCount = 0;
|
||||||
runCount++;
|
runCount++; */
|
||||||
}
|
}
|
||||||
|
|
||||||
function heartBeat() {
|
|
||||||
var m = new Object();
|
|
||||||
m.query = "heartBeat";
|
|
||||||
bcastMsg(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
function reloadHTML() {
|
|
||||||
var http = ajaxConnect();
|
|
||||||
var retfn = returnfn(http);
|
|
||||||
ajaxSend(http, "cmd=reloadHTML\n\n",retfn);
|
|
||||||
}
|
|
||||||
|
|
||||||
function poke() {
|
|
||||||
var http = ajaxConnect();
|
|
||||||
document.getElementById("pingNodeResp").innerHTML = "";
|
|
||||||
var dest = document.getElementById("pingNode").value;
|
|
||||||
|
|
||||||
var retfn = returnfn(http,
|
|
||||||
function(resp) {
|
|
||||||
document.getElementById("pingNodeResp").innerHTML += resp + "<br>";
|
|
||||||
var retfn = returnfn(http,
|
|
||||||
function(resp) {
|
|
||||||
document.getElementById("pingNodeResp").innerHTML += resp + "<br>";
|
|
||||||
});
|
|
||||||
ajaxSend(http, "cmd=greet\n\n", retfn, dest);
|
|
||||||
});
|
|
||||||
|
|
||||||
ajaxSend(http, "cmd=ping\n\n", retfn, dest);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTestStatus(str, col) {
|
function setTestStatus(str, col) {
|
||||||
var e = document.getElementById('testStatus');
|
var e = document.getElementById('testStatus');
|
||||||
|
@ -895,23 +305,6 @@ function getLockType(type) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLocked(lockType, lockName, start, end) {
|
|
||||||
if (lockType == "range") {
|
|
||||||
var rlock = getRangeLock(lockname, start, end);
|
|
||||||
if (rlock)
|
|
||||||
return rlock.locked;
|
|
||||||
else return false;
|
|
||||||
} else {
|
|
||||||
var locks = getLockType(lockType);
|
|
||||||
if (locks[lockName] == null)
|
|
||||||
return false;
|
|
||||||
else if(locks[lockName].locked != true)
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function loadTest(tname) {
|
function loadTest(tname) {
|
||||||
if(tname == '') {
|
if(tname == '') {
|
||||||
|
@ -933,68 +326,6 @@ function loadTest(tname) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function retrieveLock(struct) {
|
|
||||||
if (struct.type == "test") {
|
|
||||||
return testLocks[struct.name];
|
|
||||||
} else if(struct.type == "range") {
|
|
||||||
var l = getRangeLock(struct.name, struct.start, struct.end);
|
|
||||||
if (l == null)
|
|
||||||
error("retrieveLock for range got null");
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLock(type, name, start, end) {
|
|
||||||
var locks = getLockType(type);
|
|
||||||
var lockTry;
|
|
||||||
|
|
||||||
if (type == "test") {
|
|
||||||
if(locks[name] == null) {
|
|
||||||
locks[name] = new Object();
|
|
||||||
}
|
|
||||||
lockTry = locks[name];
|
|
||||||
} else if (type == "range") {
|
|
||||||
lockTry = getRangeLock(name, start, end);
|
|
||||||
if (!lockTry) {
|
|
||||||
error("Cannot get range lock in getLock(" + name +", "+ start + ", " + end + ")");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
lockTry.time = getTime();
|
|
||||||
lockTry.dlc = dlc+1;
|
|
||||||
lockTry.name = name;
|
|
||||||
lockTry.addr = localNodeAddr;
|
|
||||||
lockTry.type = type;
|
|
||||||
lockTry.okay = 1;
|
|
||||||
lockTry.locked = false;
|
|
||||||
var d = new Date();
|
|
||||||
lockTry.localTime = d.getTime();
|
|
||||||
|
|
||||||
if (type == "test") {
|
|
||||||
lockTrys[type] = lockTry;
|
|
||||||
setTestStatus("Acquiring lock for test '" + name + "' " + lockTry.okay + "/" + numberOfNodes + "...", "yellow");
|
|
||||||
} else if (type == "range") {
|
|
||||||
lockTrys[type] = lockTry;
|
|
||||||
setWorkStatus("Acquiring lock for work '" + name + "' (" + lockTry.start + " to " + lockTry.end + ")" + lockTry.okay + "/" + numberOfNodes + "...", "yellow");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var m = new Object();
|
|
||||||
m["query"] = "getLock";
|
|
||||||
m["type"] = type;
|
|
||||||
m["name"] = name;
|
|
||||||
m["time"] = lockTry.time;
|
|
||||||
m["addr"] = localNodeAddr;
|
|
||||||
if (type == "range") {
|
|
||||||
m["start"] = start;
|
|
||||||
m["end"] = end;
|
|
||||||
}
|
|
||||||
bcastMsg(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
function lessTime(t1, t2) {
|
function lessTime(t1, t2) {
|
||||||
var t1a = t1.split(":");
|
var t1a = t1.split(":");
|
||||||
var t2a = t2.split(":");
|
var t2a = t2.split(":");
|
||||||
|
@ -1033,28 +364,6 @@ function cameFirst(a, b) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function locksEqual(a, b) {
|
|
||||||
if(a == null || b == null)
|
|
||||||
return false;
|
|
||||||
if(a['type'] != b['type'])
|
|
||||||
return false;
|
|
||||||
if(a['type'] == 'test') {
|
|
||||||
if (a.name == b.name)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
} else if (a['type'] == "range") {
|
|
||||||
log("locksEqual? " + a.name + " (" + a.start + " to " + a.end + ") and " + b.name + " (" + b.start + " to " + b.end + ")");
|
|
||||||
if (a.name == b.name && a.start == b.start && a.end == b.end) {
|
|
||||||
log("true");
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
log("false");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function grantLock(resp, lock) {
|
function grantLock(resp, lock) {
|
||||||
removeNodeRangeLocks(resp.origin);
|
removeNodeRangeLocks(resp.origin);
|
||||||
|
@ -1473,24 +782,6 @@ function handleTestUpdate(resp) {
|
||||||
tests[resp['name']]['reducefn'] = decodeStr(resp["reducefn"]);
|
tests[resp['name']]['reducefn'] = decodeStr(resp["reducefn"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function releaseLock(type) {
|
|
||||||
var lock = myLocks[type];
|
|
||||||
myLocks[type] = null;
|
|
||||||
|
|
||||||
lock.locked = false;
|
|
||||||
|
|
||||||
|
|
||||||
var m = new Object();
|
|
||||||
m["query"] = "releaseLock";
|
|
||||||
m["type"] = type;
|
|
||||||
m["name"] = lock.name;
|
|
||||||
if (type == "range") {
|
|
||||||
m["start"] = lock.start;
|
|
||||||
m["end"] = lock.end;
|
|
||||||
}
|
|
||||||
|
|
||||||
bcastMsg(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleLockRelease(resp) {
|
function handleLockRelease(resp) {
|
||||||
//var locks = getLockType(resp['type']);
|
//var locks = getLockType(resp['type']);
|
||||||
|
@ -1536,57 +827,6 @@ function lookForWork() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRangeLock(name, start, end) {
|
|
||||||
log("getRangeLock for (" + name + " from " + start + " to " + end + ")");
|
|
||||||
if (!rangeLocks[name]) {
|
|
||||||
log("no locks for " + name + ", so MAKING");
|
|
||||||
rangeLocks[name] = genRangeCell(name, start, end);
|
|
||||||
return rangeLocks[name];
|
|
||||||
}
|
|
||||||
log("locks exist for " + name + " so SEARCHING forward");
|
|
||||||
var rlock = rangeLocks[name];
|
|
||||||
|
|
||||||
if(end < rlock.start) {
|
|
||||||
log("Space before first lock, MAKING HERE");
|
|
||||||
rangeLocks[name] = genRangeCell(name, start, end);
|
|
||||||
rangeLocks[name].next = rlock;
|
|
||||||
return rangeLocks[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
while(rlock.next && rlock.start < rlock.end+1) {
|
|
||||||
log("looking at (" + rlock.start + " to " + rlock.end + ")");
|
|
||||||
if (rlock.start == start && rlock.end == end) {
|
|
||||||
log("FOUND IT");
|
|
||||||
return rlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rlock.end < start && rlock.next.start > end) {
|
|
||||||
log("GAP between (" + rlock.start + " to " + rlock.end + ") and (" + rlock.next.start + " to " + rlock.next.end + ") where we should be so MAKING THERE");
|
|
||||||
var nlock = rlock.next;
|
|
||||||
rlock.next = genRangeCell(name, start, end);
|
|
||||||
rlock.next.next = nlock;
|
|
||||||
return rlock.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
rlock = rlock.next;
|
|
||||||
}
|
|
||||||
log("SEARCH ended");
|
|
||||||
if (rlock.start == start && rlock.end == end) {
|
|
||||||
log("Found it!");
|
|
||||||
return rlock;
|
|
||||||
} else {
|
|
||||||
if (rlock.end < start) {
|
|
||||||
log("There is space at the end to make what we want");
|
|
||||||
rlock.next = genRangeCell(name, start, end);
|
|
||||||
return rlock.next;
|
|
||||||
} else {
|
|
||||||
log("search ended after what we wanted, FAIL");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeRangeLock(tlock, suggestedSize) {
|
function makeRangeLock(tlock, suggestedSize) {
|
||||||
suggestedSize--;
|
suggestedSize--;
|
||||||
|
|
||||||
|
@ -1639,6 +879,7 @@ function makeRangeLock(tlock, suggestedSize) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
function genRangeCell(name, start, end, next) {
|
function genRangeCell(name, start, end, next) {
|
||||||
var c = new Object();
|
var c = new Object();
|
||||||
c.name = name;
|
c.name = name;
|
||||||
|
@ -1648,7 +889,7 @@ function genRangeCell(name, start, end, next) {
|
||||||
c.locked = false;
|
c.locked = false;
|
||||||
c.done = false;
|
c.done = false;
|
||||||
return c;
|
return c;
|
||||||
}
|
} */
|
||||||
|
|
||||||
var map_test = null;
|
var map_test = null;
|
||||||
var reduce = null;
|
var reduce = null;
|
||||||
|
@ -1851,9 +1092,7 @@ function updateFinalResults() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var cronID = setInterval("cron()", 100);
|
|
||||||
getMsgs();
|
|
||||||
getLog();
|
|
||||||
|
|
||||||
|
|
||||||
function page(p) {
|
function page(p) {
|
||||||
|
|
|
@ -0,0 +1,706 @@
|
||||||
|
/* cortex.js
|
||||||
|
* PURPOSE
|
||||||
|
* AUTHOR
|
||||||
|
* LICENSE
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* HTML elements used
|
||||||
|
* cortexLog - textarea
|
||||||
|
* statusLabel - div
|
||||||
|
* numberOfNodes - div
|
||||||
|
* connections -div
|
||||||
|
* dlc - div
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***** Ajax Basics *****/
|
||||||
|
|
||||||
|
var port = location.href.substring( location.href.substring(7).indexOf(':')+8,
|
||||||
|
location.href.substring(7).indexOf('/')+7);
|
||||||
|
|
||||||
|
// Returns an ajax object
|
||||||
|
function ajaxConnect() {
|
||||||
|
var http = null;
|
||||||
|
if(window.XMLHttpRequest)
|
||||||
|
http = new XMLHttpRequest();
|
||||||
|
else if (window.ActiveXObject)
|
||||||
|
http = new ActiveXObject("Microsoft.XMLHTTP");
|
||||||
|
return http;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns a function that can be passed to http.send
|
||||||
|
* that runs code fn on successful response
|
||||||
|
* Kind of a macro function builder
|
||||||
|
* http: ajax object
|
||||||
|
* fn: function taking one argument, the resp from the server,
|
||||||
|
* this function is run on a successful ajax call
|
||||||
|
* err: OPTIONAL argument that contains a funtion
|
||||||
|
* to be run if the connection failed
|
||||||
|
*/
|
||||||
|
function returnfn(http, fn, err) {
|
||||||
|
if (!fn)
|
||||||
|
fn = function(resp) {};
|
||||||
|
if (!err)
|
||||||
|
err = function() {};
|
||||||
|
return function() {
|
||||||
|
if (http.readyState == 4) {
|
||||||
|
if (http.responseText == '')
|
||||||
|
err();
|
||||||
|
else
|
||||||
|
fn(http.responseText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does ajax magic. Makes ajax call with data and sets up
|
||||||
|
* retfn to be called on response
|
||||||
|
* forward is the final destination address of the call if
|
||||||
|
* it is not this local
|
||||||
|
*/
|
||||||
|
function ajaxSend(http, data, retfn, forward) {
|
||||||
|
if (!forward)
|
||||||
|
forward = '';
|
||||||
|
http.onreadystatechange = retfn;
|
||||||
|
http.open('POST', "http://localhost:"+port+"/"+ forward, true);
|
||||||
|
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||||
|
http.send(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Utility Functions *****/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// make sure a number is two digits long, padding 0 on front
|
||||||
|
function d2(str) {
|
||||||
|
if (str <10)
|
||||||
|
return "0"+str;
|
||||||
|
else
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the time as a string
|
||||||
|
function getTime() {
|
||||||
|
var date = new Date();
|
||||||
|
return d2(date.getHours()) + ":" + d2(date.getMinutes()) + ":" + d2(date.getSeconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractHost(url) {
|
||||||
|
// http: or file:
|
||||||
|
var host = url.substr(5);
|
||||||
|
while (host.charAt(0) == '/')
|
||||||
|
host = host.substr(1);
|
||||||
|
var end = host.indexOf('/');
|
||||||
|
|
||||||
|
if (end > 0 )
|
||||||
|
host = host.substr(0, end);
|
||||||
|
return host;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var logging = true
|
||||||
|
|
||||||
|
function log(str) {
|
||||||
|
//if (logCheckElem == null)
|
||||||
|
// logCheckElem = document.getElementById("logCheck");
|
||||||
|
if (logging) { //logCheckElem.checked == true) {
|
||||||
|
str = getTime() + ": " + str+"\n";
|
||||||
|
var log = document.getElementById('cortexLog');
|
||||||
|
if(log)
|
||||||
|
log.value = str + log.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(msg) {
|
||||||
|
log("ERROR: " + msg);
|
||||||
|
alert("ERROR: " + msg);
|
||||||
|
clearInterval(cronID); // Shuts down cron
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***** Basic Server Communication *****/
|
||||||
|
|
||||||
|
var localNodeAddr = '';
|
||||||
|
var originURL = 'Unknown Source';
|
||||||
|
var connected = false;
|
||||||
|
var numberOfNodes = 0;
|
||||||
|
var connections = new Array();
|
||||||
|
|
||||||
|
var dlc = 0;
|
||||||
|
var msgQ = new Array();
|
||||||
|
|
||||||
|
/* basic ping function for local node
|
||||||
|
* if successful,
|
||||||
|
* if we haven't greeted the server, we do,
|
||||||
|
* otherwise nothing (just a heartbeat)
|
||||||
|
* if it fails, lets the user know we have lost
|
||||||
|
* connection to the node server
|
||||||
|
*/
|
||||||
|
function ping() {
|
||||||
|
var http = ajaxConnect();
|
||||||
|
|
||||||
|
var retfn = returnfn(http,
|
||||||
|
function(resp) {
|
||||||
|
//log("pong!");
|
||||||
|
if (!connected) {
|
||||||
|
connected = true;
|
||||||
|
greet();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function(resp) {
|
||||||
|
connected = false;
|
||||||
|
var html = "Connection to local Node failed. Try reloading from <a href=\"" + originURL + "\" target=\"window\">" + originURL + "</a>";
|
||||||
|
|
||||||
|
stl = document.getElementById('statusLabel');
|
||||||
|
if (stl)
|
||||||
|
stl.innerHTML = html;
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
//log("ping!");
|
||||||
|
ajaxSend(http, "cmd=ping\n\n", retfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
log("init");
|
||||||
|
if (connected == false)
|
||||||
|
return;
|
||||||
|
numberOfNodes = 1;
|
||||||
|
if (originURL.substr(0, 4) == "file") {
|
||||||
|
// we are the first
|
||||||
|
//numberOfNodes = 1; // ourself
|
||||||
|
log("Loaded from file");
|
||||||
|
// now we sit and wait
|
||||||
|
} else { // it was http, so we were loaded from another node
|
||||||
|
log("Loaded from " + originURL);
|
||||||
|
originAddress = extractHost(originURL);
|
||||||
|
join_network(originAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Greets the server
|
||||||
|
* so far just gets the server's IP and origin URL
|
||||||
|
*/
|
||||||
|
function greet() {
|
||||||
|
var http = ajaxConnect();
|
||||||
|
|
||||||
|
var retfn = returnfn(http,
|
||||||
|
function(resp) {
|
||||||
|
log("greet returned");
|
||||||
|
var arr = resp.split(" ");
|
||||||
|
localNodeAddr = arr[0];
|
||||||
|
originURL = arr[1];
|
||||||
|
stl = document.getElementById('statusLabel');
|
||||||
|
if (stl)
|
||||||
|
stl.innerHTML = "I am <b>" + localNodeAddr + "</b>";
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
log("send greet msg");
|
||||||
|
ajaxSend(http, "cmd=greet\n\n", retfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kill the server
|
||||||
|
function killServer() {
|
||||||
|
announceDead(localNodeAddr);
|
||||||
|
var http = ajaxConnect();
|
||||||
|
|
||||||
|
var retfn = returnfn(http,
|
||||||
|
function(resp) {
|
||||||
|
// got a resp, server not dead
|
||||||
|
killServer();
|
||||||
|
});
|
||||||
|
ajaxSend(http, "cmd=kill\n\n", retfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the latest server logs
|
||||||
|
function getLog() {
|
||||||
|
var http = ajaxConnect();
|
||||||
|
|
||||||
|
var retfn = returnfn(http,
|
||||||
|
function(resp) {
|
||||||
|
var log = document.getElementById('cortexLog');
|
||||||
|
if (log)
|
||||||
|
log.value = resp + log.value;
|
||||||
|
// Since getLog returns (a call back is called later)
|
||||||
|
// this is tail recursive friendly
|
||||||
|
getLog();
|
||||||
|
});
|
||||||
|
ajaxSend(http, "cmd=getLog\n\n", retfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Function Registry *****/
|
||||||
|
|
||||||
|
var fnreg = new Array;
|
||||||
|
|
||||||
|
function registerFn(fnname, fn, preplace) {
|
||||||
|
path = fnname.split(".");
|
||||||
|
root = fnreg;
|
||||||
|
for(i=0; i < path.length-1; i++) {
|
||||||
|
if (root[path[i]] == undefined)
|
||||||
|
root[path[i]] = new Array();
|
||||||
|
root = root[path[i]];
|
||||||
|
}
|
||||||
|
if (preplace)
|
||||||
|
root[path[i]] = fn;
|
||||||
|
else {
|
||||||
|
if (root[path[i]] == undefined)
|
||||||
|
root[path[i]] = [fn, null];
|
||||||
|
else {
|
||||||
|
j=0;
|
||||||
|
while(root[path[i]][j] != null)
|
||||||
|
j++;
|
||||||
|
root[path[i]][j] = fn;
|
||||||
|
root[path[i]][j+1] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finds the chain of functions,
|
||||||
|
* calls the nth
|
||||||
|
* stores its return
|
||||||
|
* calls the nth+1 with the return of the nth as well
|
||||||
|
* returns the results of the mth
|
||||||
|
*/
|
||||||
|
function execFn(name, args) {
|
||||||
|
root = fnreg;
|
||||||
|
names = name.split(".");
|
||||||
|
for (i=0; i< names.length; i++) {
|
||||||
|
root = root[names[i]];
|
||||||
|
if (root == undefined)
|
||||||
|
return false; // ERROR, NO FN
|
||||||
|
}
|
||||||
|
i=0;
|
||||||
|
ret = true;
|
||||||
|
while(root[i]) {
|
||||||
|
ret = root[i](args, ret);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***** Messeging between nodes *****/
|
||||||
|
|
||||||
|
|
||||||
|
function addMsgHandler(msgName, handlerFN, handlerReplace) {
|
||||||
|
registerFn("msgHandler." + msgName, handlerFN, handlerReplace);
|
||||||
|
}
|
||||||
|
|
||||||
|
function processMsg(resp) {
|
||||||
|
log("processMsg: " + resp['query']);
|
||||||
|
if (!execFn("msgHandler." + resp["query"], resp))
|
||||||
|
log("Error: Uknnown message '" + resp['query'] + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
function packObject(m, defaultValue) {
|
||||||
|
|
||||||
|
var str = "";
|
||||||
|
for (var i in m) {
|
||||||
|
if (m[i] == '')
|
||||||
|
{
|
||||||
|
if (defaultValue == null) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
m[i] = defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == "results") {
|
||||||
|
str += i + "=" + packResults(m[i]) + "\n";
|
||||||
|
} else {
|
||||||
|
str += i + "=" + m[i] + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendMsg(m, addr, time, mtype) {
|
||||||
|
if(time == null)
|
||||||
|
time = dlc;
|
||||||
|
if(mtype == null)
|
||||||
|
mtype = "single";
|
||||||
|
|
||||||
|
var str = "cmd=sendMsg\n";
|
||||||
|
str += "origin=" + localNodeAddr + "\n";
|
||||||
|
str += "dlc=" + time + "\n";
|
||||||
|
str += "mtype=" + mtype + "\n";
|
||||||
|
|
||||||
|
str += packObject(m);
|
||||||
|
|
||||||
|
str += "\n";
|
||||||
|
//log ("SEND: " + str);
|
||||||
|
|
||||||
|
var http = ajaxConnect();
|
||||||
|
var retfn = returnfn(http, null,
|
||||||
|
function() {
|
||||||
|
disconnect(addr);
|
||||||
|
announceDead(addr);
|
||||||
|
log("ERROR> message to " + addr + " not delivered: '" + str + "'");
|
||||||
|
});
|
||||||
|
//log("sendMsg: " + str);
|
||||||
|
ajaxSend(http, str, retfn, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bcastMsg(m) {
|
||||||
|
if (m.query != "heartBeat")
|
||||||
|
dlc ++;
|
||||||
|
//log("BCAST conLen: " + connections.length);
|
||||||
|
for(var i=0; i < connections.length; i++) {
|
||||||
|
log("bcast "+ i +" " + m.query + " to " + connections[i] + " dlc:" + dlc);
|
||||||
|
sendMsg(m, connections[i], dlc, "bcast");
|
||||||
|
//log("back from sendMsg, i:" + i + " conlen:" + connections.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMsg(resp) {
|
||||||
|
|
||||||
|
for(var i=msgQ.length-1; i>=0; i--) {
|
||||||
|
|
||||||
|
if (resp.dlc > msgQ[i].dlc) {
|
||||||
|
msgQ[i+1] = msgQ[i];
|
||||||
|
} else {
|
||||||
|
msgQ[i+1] = resp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msgQ[0] = resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseResp(resp) {
|
||||||
|
var lines = resp.split("\n");
|
||||||
|
var arr = [];
|
||||||
|
for(var i=0; i < lines.length; i++) {
|
||||||
|
//var kv = lines[i].split("=");
|
||||||
|
var mid = lines[i].indexOf("=");
|
||||||
|
var kv = new Array();
|
||||||
|
kv[0] = lines[i].substring(0, mid);
|
||||||
|
kv[1] = lines[i].substring(mid+1);
|
||||||
|
if (kv[1] == "true")
|
||||||
|
kv[1] = true;
|
||||||
|
else if(kv[0] == "false")
|
||||||
|
kv[1] = false;
|
||||||
|
else if (kv[0] == "dlc" ||
|
||||||
|
kv[0] == "start" ||
|
||||||
|
kv[0] == "end" ||
|
||||||
|
kv[0] == "min" ||
|
||||||
|
kv[0] == "max")
|
||||||
|
kv[1] = Number(kv[1]);
|
||||||
|
else if (kv[0] == "results")
|
||||||
|
kv[1] = unpackResults(kv[1]);
|
||||||
|
arr[kv[0]] = kv[1];
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function queueMsgs(mstr) {
|
||||||
|
log("GOT messages: " + mstr);
|
||||||
|
var resps = mstr.split("\n\n");
|
||||||
|
for(var rcount=0; rcount < resps.length; rcount++) {
|
||||||
|
var resp = resps[rcount];
|
||||||
|
if (resp == "")
|
||||||
|
continue;
|
||||||
|
resp = parseResp(resp);
|
||||||
|
if (resp.query == "DLC") {
|
||||||
|
dlc = resp.dlc;
|
||||||
|
//var m = new Object();
|
||||||
|
//m.query = "DLC";
|
||||||
|
//bcastMsg(m);
|
||||||
|
} else {
|
||||||
|
addMsg(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var s = "QUEUE: "
|
||||||
|
for (var i =0; i< msgQ.length; i++) {
|
||||||
|
s += msgQ[i].dlc + " ";
|
||||||
|
}
|
||||||
|
log(s);
|
||||||
|
log("mqlen:" + msgQ.length);
|
||||||
|
while (msgQ.length>0 && ((msgQ[msgQ.length-1].dlc - 1) <= dlc)) {
|
||||||
|
var r = msgQ.pop();
|
||||||
|
log("mdlc: " + r.dlc + " dlc: " + dlc + " mqlen: " + msgQ.length + " type:" + r.mtype + " query: " + r.query);
|
||||||
|
if (r.mtype == "bcast")
|
||||||
|
dlc = r.dlc
|
||||||
|
processMsg(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMsgs() {
|
||||||
|
var http = ajaxConnect();
|
||||||
|
var retfn = returnfn(http,
|
||||||
|
function(resp) {
|
||||||
|
//log("getMsgs: " + resp);
|
||||||
|
queueMsgs(resp);
|
||||||
|
// Since getMsgs returns (a call back is called later)
|
||||||
|
// this is tail recursive friendly
|
||||||
|
getMsgs();
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
log("ERROR: getMsg RETURN FAIL");
|
||||||
|
});
|
||||||
|
log("getMsgs");
|
||||||
|
ajaxSend(http, "cmd=getMsgs\n\n", retfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***** P2P Network Communication *****/
|
||||||
|
|
||||||
|
function connectedTo(addr) {
|
||||||
|
if (addr == localNodeAddr)
|
||||||
|
return true;
|
||||||
|
for(i = 0; i < connections.length; i++) {
|
||||||
|
if (connections[i] == addr)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addConnection(addr) {
|
||||||
|
if(!connectedTo(addr)) {
|
||||||
|
connections[connections.length] = addr;
|
||||||
|
numberOfNodes++;
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function join_network(address, bcast) {
|
||||||
|
if(bcast == null) {
|
||||||
|
bcast = true;
|
||||||
|
}
|
||||||
|
log("join_network -> " + address);
|
||||||
|
var m = new Object();
|
||||||
|
m["query"] = "join_network";
|
||||||
|
m["addr"] = localNodeAddr;
|
||||||
|
//m["nodes"] = genNodeList();
|
||||||
|
sendMsg(m, address);
|
||||||
|
if (bcast == true) {
|
||||||
|
m = new Object();
|
||||||
|
m["query"] = "new_network";
|
||||||
|
m["addr"] = address;
|
||||||
|
bcastMsg(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function genNodeList() {
|
||||||
|
var str = "";//localNodeAddr+",";
|
||||||
|
for (var i =0; i < connections.length; i++) {
|
||||||
|
str += connections[i] + ",";
|
||||||
|
}
|
||||||
|
if (connections.length > 0)
|
||||||
|
str = str.substring(0,str.length-1);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function advertiseNewNode(addr) {
|
||||||
|
var m = new Object();
|
||||||
|
m['query'] = "newNode";
|
||||||
|
m['addr'] = addr;
|
||||||
|
bcastMsg(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
function announceDead(addr) {
|
||||||
|
var m = new Object();
|
||||||
|
m['query'] = "deadNode";
|
||||||
|
m['addr'] = addr;
|
||||||
|
bcastMsg(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendDLC(addr) {
|
||||||
|
var m = new Object();
|
||||||
|
m.query = "DLC";
|
||||||
|
sendMsg(m, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendWelcome(addrList, addr) {
|
||||||
|
var m = new Object();
|
||||||
|
m["query"] = "welcome";
|
||||||
|
m["addrList"] = addrList;
|
||||||
|
sendMsg(m, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function heartBeat() {
|
||||||
|
var m = new Object();
|
||||||
|
m.query = "heartBeat";
|
||||||
|
bcastMsg(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reloadHTML() {
|
||||||
|
var http = ajaxConnect();
|
||||||
|
var retfn = returnfn(http);
|
||||||
|
ajaxSend(http, "cmd=reloadHTML\n\n",retfn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
function poke() {
|
||||||
|
var http = ajaxConnect();
|
||||||
|
document.getElementById("pingNodeResp").innerHTML = "";
|
||||||
|
var dest = document.getElementById("pingNode").value;
|
||||||
|
|
||||||
|
var retfn = returnfn(http,
|
||||||
|
function(resp) {
|
||||||
|
document.getElementById("pingNodeResp").innerHTML += resp + "<br>";
|
||||||
|
var retfn = returnfn(http,
|
||||||
|
function(resp) {
|
||||||
|
document.getElementById("pingNodeResp").innerHTML += resp + "<br>";
|
||||||
|
});
|
||||||
|
ajaxSend(http, "cmd=greet\n\n", retfn, dest);
|
||||||
|
});
|
||||||
|
|
||||||
|
ajaxSend(http, "cmd=ping\n\n", retfn, dest);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***** Msg Handlers *****/
|
||||||
|
|
||||||
|
function handleNewNode(resp, welcome) {
|
||||||
|
|
||||||
|
if (welcome == null)
|
||||||
|
welcome = false;
|
||||||
|
var addr = resp.addr;
|
||||||
|
//log2("handle new node " + addr + " from " + resp.origin);
|
||||||
|
|
||||||
|
// handles re adding if reloaded html
|
||||||
|
//if (!connectedTo(addr))
|
||||||
|
//{
|
||||||
|
var ret = genNodeList();
|
||||||
|
var n = addConnection(addr);
|
||||||
|
if (welcome == true) {
|
||||||
|
sendDLC(addr);
|
||||||
|
sendWelcome(ret, addr);
|
||||||
|
//sendLocks(addr);
|
||||||
|
//sendTests(addr);
|
||||||
|
}
|
||||||
|
if (n == true) {
|
||||||
|
//sendReqs(addr);
|
||||||
|
advertiseNewNode(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addMsgHandler( "join_network",
|
||||||
|
function (resp) {
|
||||||
|
handleNewNode(resp, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
addMsgHandler( "newNode",
|
||||||
|
function (resp) {
|
||||||
|
handleNewNode(resp, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
addMsgHandler( "welcome",
|
||||||
|
function (resp) {
|
||||||
|
log("Welcome message received");
|
||||||
|
//var myNodes = genNodeList();
|
||||||
|
addConnection(resp['origin']);
|
||||||
|
if (resp['addrList']){
|
||||||
|
var nodes = resp['addrList'].split(",");
|
||||||
|
for(var i=0; i < nodes.length; i++){
|
||||||
|
addConnection(nodes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var i =0; i< connections.length; i++) {
|
||||||
|
var addr = connections[i];
|
||||||
|
if (addr == localNodeAddr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
advertiseNewNode(addr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addMsgHandler( "deadNode",
|
||||||
|
function (resp) {
|
||||||
|
var addr = resp['addr'];
|
||||||
|
log("DISCONNECT " + addr);
|
||||||
|
// remove from connumberOfNodesnections list
|
||||||
|
for (var i=0; i < connections.length; i++) {
|
||||||
|
if (connections[i] == addr) {
|
||||||
|
connections.splice(i,1);
|
||||||
|
numberOfNodes--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addMsgHandler( "new_network",
|
||||||
|
function (resp) {
|
||||||
|
join_network(resp["addr"], false);
|
||||||
|
});
|
||||||
|
|
||||||
|
addMsgHandler( "heartBeat",
|
||||||
|
function (resp) {
|
||||||
|
// do nothing
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/***** CRON System *****/
|
||||||
|
|
||||||
|
// list of intervals
|
||||||
|
var crontabs = new Array();
|
||||||
|
|
||||||
|
/* add a function to be called repeatedly
|
||||||
|
* interval - in 1/10s of a second
|
||||||
|
* fn - function to be called
|
||||||
|
*/
|
||||||
|
function addCronTab(interval, fn) {
|
||||||
|
crontabs[interval] = true;
|
||||||
|
registerFn("cron."+interval, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cronI = 0;
|
||||||
|
|
||||||
|
function cron() {
|
||||||
|
if (connected == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (time in crontabs) {
|
||||||
|
if (cronI % Number(time) == 0) {
|
||||||
|
execFn("cron."+ time, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cronI += 1;
|
||||||
|
// Reset to 0 after a day
|
||||||
|
if (cronI > 864000) {
|
||||||
|
cronI = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addCronTab(10, ping);
|
||||||
|
addCronTab(300, heartBeat);
|
||||||
|
|
||||||
|
|
||||||
|
/***** UI *****/
|
||||||
|
function setStatus() {
|
||||||
|
var nn = document.getElementById('numberOfNodes');
|
||||||
|
if (nn)
|
||||||
|
nn.innerHTML = "Number of nodes: " + numberOfNodes;
|
||||||
|
var c = document.getElementById('connections');
|
||||||
|
if (c)
|
||||||
|
c.innerHTML = "Connected to: " + genNodeList();
|
||||||
|
var dlcE = document.getElementById('dlc');
|
||||||
|
if (dlcE)
|
||||||
|
dlcE.innerHTML = "DLC: " + dlc;
|
||||||
|
}
|
||||||
|
|
||||||
|
addCronTab(10, setStatus);
|
||||||
|
|
||||||
|
/**** INIT *****/
|
||||||
|
|
||||||
|
function cortex_start(debug) {
|
||||||
|
if(debug)
|
||||||
|
logging = true;
|
||||||
|
ping();
|
||||||
|
var cronID = setInterval("cron()", 100);
|
||||||
|
getMsgs();
|
||||||
|
getLog();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********** AND THAT's THE BASIS OF THE CORTEX P2P NETWORK **********/
|
||||||
|
/* We now have dumb do nothing nodes that can connect to each other
|
||||||
|
* and maintain state */
|
||||||
|
/********** NOW TO ADD SOME USEFUL THINGS ON TOP OF IT **********/
|
|
@ -0,0 +1,419 @@
|
||||||
|
/* cortexLocks.js
|
||||||
|
* PURPOSE
|
||||||
|
* AUTHOR
|
||||||
|
* LICENSE
|
||||||
|
*
|
||||||
|
* NOTES
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* locks -> [ class: [type, locks], ] */
|
||||||
|
var locks = new Array();
|
||||||
|
/* -> [ class : lock] (you can only req/acq 1 lock per class */
|
||||||
|
var locksReq = new Array();
|
||||||
|
var locksAcq = new Array();
|
||||||
|
|
||||||
|
function copyobj(arr) {
|
||||||
|
c = new Object();
|
||||||
|
for (i in arr) {
|
||||||
|
c[i] = arr[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function locksClassType(klass) {
|
||||||
|
return locks[klass]['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function locksClassLocks(klass) {
|
||||||
|
return locks[klass]['locks'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerLockFn(ltype, fnName, fn) {
|
||||||
|
registerFn("locks." +ltype+"."+fnName, fn);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
function execLockFn(fnName, args) {
|
||||||
|
type = locksClassType(args['class']);
|
||||||
|
args['type'] = type;
|
||||||
|
locks = locksClassLocks(args['class']);
|
||||||
|
args['locks'] = locks;
|
||||||
|
return execFn("locks."+type+"."+fnName, args);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
function locksInitClass(klass, type) {
|
||||||
|
locks[klass]['type'] = type;
|
||||||
|
locks[klass]['locks'] = new Array();
|
||||||
|
|
||||||
|
locksReq[klass] = new Array();
|
||||||
|
locksAcq[klass] = new Array();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**** Core Lock Functions
|
||||||
|
* get(table, info) BR -> getLock
|
||||||
|
* equal(a, b) - > locksEqual
|
||||||
|
* ?msg(lock)
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getLock(info) {
|
||||||
|
type = locksClassType(info['class']);
|
||||||
|
info['type'] = type;
|
||||||
|
locks = locksClassLocks(info['class']);
|
||||||
|
info['locks'] = locks;
|
||||||
|
return execFn("locks."+type+".get", info);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerLockFn("basic", "get",
|
||||||
|
function (args) {
|
||||||
|
lock = args['locks'][args['name']];
|
||||||
|
if ( ! lock.name) {
|
||||||
|
lock.name =args['name'];
|
||||||
|
lock.locked = false;
|
||||||
|
lock.type = 'basic';
|
||||||
|
}
|
||||||
|
return lock;
|
||||||
|
});
|
||||||
|
|
||||||
|
function genRangeCell(name, start, end, next) {
|
||||||
|
var c = new Object();
|
||||||
|
c.name = name;
|
||||||
|
c.type = 'range';
|
||||||
|
c.start=start;
|
||||||
|
c.end = end;
|
||||||
|
c.next = next;
|
||||||
|
c.locked = false;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRangeLock(rangeLocks, name, start, end) {
|
||||||
|
log("getRangeLock for (" + name + " from " + start + " to " + end + ")");
|
||||||
|
if (!rangeLocks[name]) {
|
||||||
|
log("no locks for " + name + ", so MAKING");
|
||||||
|
rangeLocks[name] = genRangeCell(name, start, end);
|
||||||
|
return rangeLocks[name];
|
||||||
|
}
|
||||||
|
log("locks exist for " + name + " so SEARCHING forward");
|
||||||
|
var rlock = rangeLocks[name];
|
||||||
|
|
||||||
|
if(end < rlock.start) {
|
||||||
|
log("Space before first lock, MAKING HERE");
|
||||||
|
rangeLocks[name] = genRangeCell(name, start, end);
|
||||||
|
rangeLocks[name].next = rlock;
|
||||||
|
return rangeLocks[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
while(rlock.next && rlock.start < rlock.end+1) {
|
||||||
|
log("looking at (" + rlock.start + " to " + rlock.end + ")");
|
||||||
|
if (rlock.start == start && rlock.end == end) {
|
||||||
|
log("FOUND IT");
|
||||||
|
return rlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rlock.end < start && rlock.next.start > end) {
|
||||||
|
log("GAP between (" + rlock.start + " to " + rlock.end + ") and (" + rlock.next.start + " to " + rlock.next.end + ") where we should be so MAKING THERE");
|
||||||
|
var nlock = rlock.next;
|
||||||
|
rlock.next = genRangeCell(name, start, end);
|
||||||
|
rlock.next.next = nlock;
|
||||||
|
return rlock.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
rlock = rlock.next;
|
||||||
|
}
|
||||||
|
log("SEARCH ended");
|
||||||
|
if (rlock.start == start && rlock.end == end) {
|
||||||
|
log("Found it!");
|
||||||
|
return rlock;
|
||||||
|
} else {
|
||||||
|
if (rlock.end < start) {
|
||||||
|
log("There is space at the end to make what we want");
|
||||||
|
rlock.next = genRangeCell(name, start, end);
|
||||||
|
return rlock.next;
|
||||||
|
} else {
|
||||||
|
log("search ended after what we wanted, FAIL");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
registerLockFn("range", "get",
|
||||||
|
function (args) {
|
||||||
|
var l = getRangeLock(arg['locks'] , args['name'], args['start'], args'[end']);
|
||||||
|
if (l == null)
|
||||||
|
error("retrieveLock for range got null");
|
||||||
|
return l;
|
||||||
|
});
|
||||||
|
|
||||||
|
function lockTypesEqual(a, b) {
|
||||||
|
if(a == null || b == null)
|
||||||
|
return false;
|
||||||
|
if(a['type'] != b['type'])
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerLockFn("basic", "equals",
|
||||||
|
function(args) { // locksEqual(a, b)
|
||||||
|
var a = args['a'];
|
||||||
|
var b = arbs['b'];
|
||||||
|
if (!lockTypesEqual(a, b))
|
||||||
|
return false;
|
||||||
|
if (a.name == b.name)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
registerLockFn("range", "equals",
|
||||||
|
function(args) { // locksEqual(a, b)
|
||||||
|
var a = args['a'];
|
||||||
|
var b = arbs['b'];
|
||||||
|
if (!lockTypesEqual(a, b))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
log("locksEqual? " + a.name + " (" + a.start + " to " + a.end + ") and " + b.name + " (" + b.start + " to " + b.end + ")");
|
||||||
|
if (a.name == b.name && a.start == b.start && a.end == b.end) {
|
||||||
|
log("true");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log("false");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
functions locksEqual(a, b) {
|
||||||
|
args = new Array();
|
||||||
|
args['a'] = a;
|
||||||
|
args['b'] = b;
|
||||||
|
return execFn("locks."+a['type']+".equals", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*** Non Networked Lock functions
|
||||||
|
* lock
|
||||||
|
* release
|
||||||
|
* isLocked
|
||||||
|
* removeLocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isLocked(lock) {
|
||||||
|
return lock.locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lock(lock) {
|
||||||
|
lock['locked'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function release(lock) {
|
||||||
|
lock['locked'] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************** REVIEW HERE ******************/
|
||||||
|
|
||||||
|
registerLockFn("basic", "remove",
|
||||||
|
function(args) {
|
||||||
|
for(var i in args['locks']) {
|
||||||
|
var lock = args['locks'][i];
|
||||||
|
if (!lock)
|
||||||
|
continue;
|
||||||
|
if (lock.addr == addr) {
|
||||||
|
lock.locked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
registerLockFn("range", "remove",
|
||||||
|
function(args) {
|
||||||
|
for(var i in args['locks']) {
|
||||||
|
log("freeing " + i + " locks");
|
||||||
|
var rlock = args['locks'][i];
|
||||||
|
while (rlock != null) {
|
||||||
|
log("looking at " + i + " (" + rlock.start + " to " + rlock.end + ") : " + rlock.addr);
|
||||||
|
if (rlock.addr == args['addr']) {
|
||||||
|
log("unlocking");
|
||||||
|
rlock.locked = false;
|
||||||
|
}
|
||||||
|
rlock = rlock.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function genLockTry(lockTry) {
|
||||||
|
lockTry.time = getTime();
|
||||||
|
lockTry.dlc = dlc+1;
|
||||||
|
lockTry.name = name;
|
||||||
|
lockTry.addr = localNodeAddr;
|
||||||
|
lockTry.type = type;
|
||||||
|
lockTry.okay = 1;
|
||||||
|
lockTry.locked = false;
|
||||||
|
var d = new Date();
|
||||||
|
lockTry.localTime = d.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
function genGetLockMsg() {
|
||||||
|
var m = new Object();
|
||||||
|
m["query"] = "getLock";
|
||||||
|
m["time"] = lockTry.time;
|
||||||
|
m["addr"] = localNodeAddr;
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
registerLockFn("basic", "release",
|
||||||
|
function (args) {
|
||||||
|
var lock = myLocks[type];
|
||||||
|
myLocks[type] = null;
|
||||||
|
|
||||||
|
lock.locked = false;
|
||||||
|
|
||||||
|
|
||||||
|
var m = new Object();
|
||||||
|
m["query"] = "releaseLock";
|
||||||
|
m["type"] = type;
|
||||||
|
m["name"] = lock.name;
|
||||||
|
if (type == "range") {
|
||||||
|
m["start"] = lock.start;
|
||||||
|
m["end"] = lock.end;
|
||||||
|
}
|
||||||
|
|
||||||
|
bcastMsg(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**** Netowkr Lock using functions
|
||||||
|
* aquire
|
||||||
|
* grant(resp, lock
|
||||||
|
* deny(resp, lock
|
||||||
|
* handleLockReq
|
||||||
|
* handleLockResp
|
||||||
|
* lockGranted
|
||||||
|
* checkLocks
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
registerLockFn("basic", "aquire",
|
||||||
|
function(args) {
|
||||||
|
var locks = args['locks'];
|
||||||
|
var name = args['name'];
|
||||||
|
var lockTry;
|
||||||
|
|
||||||
|
if(locks[name] == null) {
|
||||||
|
locks[name] = new Object();
|
||||||
|
}
|
||||||
|
lockTry = locks[name];
|
||||||
|
|
||||||
|
genLockTry(lockTry);
|
||||||
|
|
||||||
|
lockTrys[args['family']] = lockTry;
|
||||||
|
setTestStatus("Acquiring lock for test '" + name + "' " + lockTry.okay + "/" + numberOfNodes + "...", "yellow");
|
||||||
|
|
||||||
|
var m = getLockMsg();
|
||||||
|
m["name"] = name;
|
||||||
|
m["type"] = "basic";
|
||||||
|
|
||||||
|
bcastMsg(m);
|
||||||
|
});
|
||||||
|
|
||||||
|
registerLockFn("range", "aquire",
|
||||||
|
function(args) {
|
||||||
|
var name = args['name'];
|
||||||
|
var start = args['start'];
|
||||||
|
var end = args['end'];
|
||||||
|
|
||||||
|
lockTry = getRangeLock(args['locks'], name, start, end);
|
||||||
|
if (!lockTry) {
|
||||||
|
error("Cannot get range lock in getLock(" + name +", "+ start + ", " + end + ")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
genLockTry(lockTry);
|
||||||
|
|
||||||
|
lockTrys[args['family']] = lockTry;
|
||||||
|
setWorkStatus("Acquiring lock for work '" + name + "' (" + lockTry.start + " to " + lockTry.end + ")" + lockTry.okay + "/" + numberOfNodes + "...", "yellow");
|
||||||
|
|
||||||
|
var m = getLockMsg();
|
||||||
|
m["name"] = name;
|
||||||
|
m["type"] = "range";
|
||||||
|
|
||||||
|
|
||||||
|
m["start"] = start;
|
||||||
|
m["end"] = end;
|
||||||
|
|
||||||
|
bcastMsg(m);
|
||||||
|
});
|
||||||
|
|
||||||
|
function sendReqs(addr) {
|
||||||
|
for(ltype in lockTrys) {
|
||||||
|
for (i in lockTrys[ltype]) {
|
||||||
|
var lock = lockTrys[ltype][i];
|
||||||
|
if (lock == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var m = copyobj(lock);
|
||||||
|
m["query"] = "getLock";
|
||||||
|
m["type"] = ltype;
|
||||||
|
sendMsg(m, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendLocks(addr) {
|
||||||
|
for (ltype in locks) {
|
||||||
|
for (var i in locks[ltype]) {
|
||||||
|
log ("testLog[" + i + "]");
|
||||||
|
var l = testLocks[ltype][i];
|
||||||
|
var m = copyobj(l);
|
||||||
|
|
||||||
|
m["query"] = "addLock";
|
||||||
|
m["type"] = ltype;
|
||||||
|
|
||||||
|
sendMsg(m, addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAddLock(resp) {
|
||||||
|
if(resp['locked'] == null)
|
||||||
|
resp['locked'] = false;
|
||||||
|
// dont add/overwrite if exists?
|
||||||
|
var lock = retrieveLock(resp);
|
||||||
|
|
||||||
|
if (resp['type'] == "test" ) {//&& (lock == null || lock.addr == null)) {
|
||||||
|
var locks = getLockType(resp['type']);
|
||||||
|
|
||||||
|
|
||||||
|
locks[resp['name']] = resp
|
||||||
|
if(resp['running'] == true) {
|
||||||
|
runningTests.push(resp['name']);
|
||||||
|
}
|
||||||
|
} else if(resp['type'] == "range" && lock.addr == null) {
|
||||||
|
log("Add range lock: " + resp['name'] + " (" + resp['start'] + " to " + resp['end'] + ") : ");
|
||||||
|
var lock = getRangeLock(LOCKS, resp['name'], resp['start'], resp['end']);
|
||||||
|
|
||||||
|
lock.addr = resp['addr'];
|
||||||
|
lock.locked = resp['locked'];
|
||||||
|
lock.done = resp['done'];
|
||||||
|
lock.results = resp['results'];
|
||||||
|
lock.name = resp['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addMessageHandler("addLock", handlerAddLock());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function removeNodeLocks(addr) {
|
||||||
|
removeNodeRangeLocks(resp['addr']);
|
||||||
|
}
|
||||||
|
|
||||||
|
addMsgHandler("deadNode",
|
||||||
|
function (resp) {
|
||||||
|
BASIC
|
||||||
|
|
||||||
|
removeNodeLocks(resp['addr']);
|
||||||
|
});
|
16
shell.html
16
shell.html
|
@ -3,24 +3,12 @@
|
||||||
<head>
|
<head>
|
||||||
<title>Client</title>
|
<title>Client</title>
|
||||||
|
|
||||||
<script src="ajax.js" ></script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function load() {
|
function load() {
|
||||||
port = document.getElementById('port').value;
|
port = document.getElementById('port').value;
|
||||||
document.getElementById('client').src = "http://localhost:" + port + "/client.html";
|
document.getElementById('client').src = "http://localhost:" + port + "/basicClient.html";
|
||||||
}
|
}
|
||||||
|
|
||||||
function isLoaded() {
|
|
||||||
if(document.getElementById('cortex').isActive())
|
|
||||||
{
|
|
||||||
load();
|
|
||||||
clearInterval();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
Loading…
Reference in New Issue