Compare commits

..

14 Commits

9 changed files with 1214 additions and 821 deletions

View File

@ -340,7 +340,7 @@ class ConnHandler implements Runnable {
userAgent = header;
}
System.out.println(i + ": '" + header + "'");
//System.out.println(i + ": '" + header + "'");
i++;
header = sin.readLine();
}
@ -353,6 +353,7 @@ class ConnHandler implements Runnable {
byte[] get_resp= null;
String CODE = "200 OK";
int resp_length = 0;
String content_type = "text/html";
if (type == TYPE_GET) {
reqLine = reqLine.substring(4);
res.log("GET " + reqLine);
@ -361,6 +362,11 @@ class ConnHandler implements Runnable {
CODE = "404 Not Found";
}
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 {
// No forward
if (reqLine.equals("")) {
@ -385,7 +391,7 @@ class ConnHandler implements Runnable {
SimpleDateFormat formater = new SimpleDateFormat("E, d M y H:m:s z");
sout.print("HTTP/1.1 " + CODE + "\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");
// Print response

20
LICENSE
View File

@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright (c) 2010 Dan Ballard
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2
README
View File

@ -1,6 +1,6 @@
Cortex: P2P in JavaScript
Dan Ballard (2010-2011) <dan@mindstab.net>
https://danballard.com/projects/cortex/
cortex.mindstab.net
Cortex is a P2P framework that runs without installation in your web browser. It's one small part Java Applet (HTTP server) and one large part JavaScript. The JavaScript is all the P2P networking code and utilities you need to get off the ground and go.

View File

@ -146,6 +146,9 @@ class ResManager {
putSite("shell.html", readURL(new URL(baseurl + "shell.html")));
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) {

52
basicClient.html Normal file
View File

@ -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>

View File

@ -35,16 +35,10 @@
<script>
var localNodeAddr = '';
var originURL = 'Unknown Source';
var connected = false;
var numberOfNodes = 0;
var connections = new Array();
var tests = new Array();
var testLocks = new Array();
var lockTrys = new Array();
var myLocks = new Array();
var runningTests = new Array();
var rangeLocks = new Array();
@ -54,280 +48,8 @@ var doneStage = 0;
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) {
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) {
if (arr instanceof Object) {
var str = "{";
@ -432,108 +128,6 @@ function packResults(res) {
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) {
var res="";
@ -573,69 +167,19 @@ function decodeStr(str) {
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) {
if (resp["query"] == "join_network") {
log("Message join_network received");
handleNewNode(resp, true);
} else if (resp["query"] == "welcome") {
handleWelcome(resp);
} else if (resp["query"] == "newNode") {
//addConnection(resp["addr"]);
handleNewNode(resp, false);
} else if (resp["query"] == "deadNode") {
disconnect(resp["addr"]);
// if (resp["query"] == "join_network") {
// log("Message join_network received");
// handleNewNode(resp, true);
// } else if (resp["query"] == "welcome") {
// handleWelcome(resp);
// } else if (resp["query"] == "newNode") {
// //addConnection(resp["addr"]);
// handleNewNode(resp, false);
// } else if (resp["query"] == "deadNode") {
// disconnect(resp["addr"]);
} else if(resp["query"] == "addLock") {
handleAddLock(resp);
} else if (resp["query"] == "getLock") {
@ -650,120 +194,16 @@ function processMsg(resp) {
handleActivateJob(resp);
} else if(resp["query"] == "results") {
handleResults(resp);
} else if(resp["query"] == "new_network") {
join_network(resp["addr"], false);
} else if(resp["query"] == "heartBeat") {
// do nothing;
// } else if(resp["query"] == "new_network") {
// join_network(resp["addr"], false);
// } else if(resp["query"] == "heartBeat") {
// // do nothing;
return;
} else {
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 workMod = 1;
@ -816,7 +256,7 @@ function cron() {
if (runCount % 10 == 0) {
ping();
//getLog();
setStatus();
//setStatus();
checkLocks();
updateTestsStatus();
if ( doneStage == 1 ) {
@ -836,46 +276,16 @@ function cron() {
if (runCount % 20 == 0)
updateResults();
if (runCount % 300 == 0)
heartBeat();
//if (runCount % 300 == 0)
// heartBeat();
// 180 seconds, or 3 minutes
if (runCount == 1800)
/*if (runCount == 1800)
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) {
var e = document.getElementById('testStatus');
@ -895,23 +305,6 @@ function getLockType(type) {
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) {
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) {
var t1a = t1.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) {
removeNodeRangeLocks(resp.origin);
@ -1473,24 +782,6 @@ function handleTestUpdate(resp) {
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) {
//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) {
suggestedSize--;
@ -1639,6 +879,7 @@ function makeRangeLock(tlock, suggestedSize) {
}
}
/*
function genRangeCell(name, start, end, next) {
var c = new Object();
c.name = name;
@ -1648,7 +889,7 @@ function genRangeCell(name, start, end, next) {
c.locked = false;
c.done = false;
return c;
}
} */
var map_test = null;
var reduce = null;
@ -1851,9 +1092,7 @@ function updateFinalResults() {
var cronID = setInterval("cron()", 100);
getMsgs();
getLog();
function page(p) {

706
cortex.js Normal file
View File

@ -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 **********/

419
cortexLocks.js Normal file
View File

@ -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']);
});

View File

@ -3,24 +3,12 @@
<head>
<title>Client</title>
<script src="ajax.js" ></script>
<script>
function load() {
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>
</head>
<body>