- getMsgs and getLog now both long pull. Much faster and more effecient

- New server class as a subthread of the applet
- The applet can now draw itself, and shows port and online status
This commit is contained in:
Dan 2010-12-31 09:42:12 -05:00
parent 5ce2a651ef
commit aa6681c03f
6 changed files with 162 additions and 130 deletions

View File

@ -72,8 +72,7 @@ class ConnHandler implements Runnable {
//InetAddress addr = new InetSocketAddress("127.0.0.1");
if (!client.isConnected())
res.error("failed to connect!!!!!!!");
//"127.0.0.1", 2600); //dest, res.PORT);
//client.connect(addr, 2600);
out = new PrintWriter(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
} catch (Exception e) {
@ -92,13 +91,14 @@ class ConnHandler implements Runnable {
"Keep-Alive: 300\r\n" +
"Connection: keep-alive\r\n" +
"Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n" +
"Referer: http://localhost:2600/client.html\r\n" +
"Referer: " + getIPAddress() + ":" + Integer.toString(res.PORT) + "/client.html\r\n" +
"Content-Length: " + (all.length()+2) + "\r\n" +
"Pragma: no-cache\r\n" +
"Cache-Control: no-cache\r\n" +
"\r\n");
out.print(all + "\n\n");
out.flush();
//res.alert("SENT: " + all);
//res.log("sent message");
//out.close();
@ -110,10 +110,12 @@ class ConnHandler implements Runnable {
// read http header
//res.log("Reading resp header");
try {
String header = in.readLine();
while (header.length() >= 3) {
//res.log("header: " + header);
header = in.readLine();
if (in.ready()) {
String header = in.readLine();
if (header.length() >= 3) {
//res.log("header: " + header);
header = in.readLine();
}
}
} catch (Exception e) {
res.error("Exception in ajaxCall (reading HTTP response header): " + e.toString());
@ -223,7 +225,14 @@ class ConnHandler implements Runnable {
} else if (cmd.equals("greet")) {
response = getIPAddress() + ":" + res.PORT + " " + res.getNodeData("originURL") ;
} else if (cmd.equals("getLog")) {
res.debug("getLog");
ArrayList<String> l = res.getLog();
if (l.size() == 0) {
res.debug("logWait");
res.logWait();
l = res.getLog();
}
res.debug("process Log");
response = "";
for (int i = l.size()-1; i >= 0; i--) {
response += l.get(i) + "\n";
@ -237,7 +246,14 @@ class ConnHandler implements Runnable {
res.queueMsg(req.get("req"));
response = "received on " + res.PORT;
} else if (cmd.equals("getMsgs")) {
res.debug("getMsgs");
ArrayList<String> mq = res.getMsgs();
if (mq.size() == 0) {
res.debug("mqWait");
res.mqWait();
mq = res.getMsgs();
}
res.debug("mq process");
for(int i =0; i < mq.size(); i++) {
response += mq.get(i) + "\n\n";
}

View File

@ -1,5 +1,5 @@
import java.applet.*;
//import java.awt.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.Timer;
import java.awt.image.*;
@ -18,71 +18,58 @@ import javax.swing.JOptionPane.*;
public class Cortex extends Applet {
//private final int PORT = 2600; // in ResManager now
private ServerSocket server;
private Server server;
private ResManager res = new ResManager(this);
private ResManager res = new ResManager();
public void update(Graphics g)
{
paint(g);
}
public void paint(Graphics g) {
Dimension size = getSize();
g.setColor(Color.black);
g.fillRect(0, 0, (int) size.getWidth(), (int) size.getHeight());
g.setColor(new Color(223, 200, 255));
g.drawString("Cortex Server",8,12);
if(!res.killSwitch) {
g.setColor(new Color(40, 255, 80));
g.drawString("Online on port",2, 28);
g.drawString(Integer.toString(res.PORT), 35, 42);
/*if (res.mqSize() > 0) {
g.setColor(Color.green);
g.drawString(".", 80, 42);
} else {
g.setColor(Color.red);
g.drawString(".", 80, 42);
}*/
} else {
g.setColor(Color.red);
g.drawString("Offline", 25,28);
}
}
/*URL getCodeBase() throws Exception {
return new URL("file:///home/dan/src/school/cpsc416/cortex/");
}*/
/* main
* Main HTTP server. Accepts connections on PORT and passes them to threads
* in the form of ConnHandlers to deal with
*/
public void init() {
//javax.swing.JOptionPane.showMessageDialog(null, "APPLET STARTING!!!!");
//res.alert("Starting...");
res.putNodeData("originURL", getCodeBase().toString());
res.reloadSite();
//server =
new Thread(new Server(res, getCodeBase().toString(), this)).start();
//res.alert("Loaded site");
boolean bound = false;
while(!bound)
{
try {
server = new ServerSocket(res.PORT);
bound = true;
} catch (IOException e) {
res.PORT++;
}
}
/*
// be reasonably sure we've secured a valid port
try {
server = new ServerSocket(res.PORT);
} catch (IOException e) {
res.error( "It appears another Cortex Node is already running on this computer, making this one superfulous.\nShutting down...");
}*/
Thread.sleep(100);
} catch (Exception e) { /* meh */ }
repaint();
/*try {
JSObject win = JSObject.getWindow(this);
win.eval("load();");
} catch(Exception e) {
res.error(e.toString());
}*/
try {
//res.alert("running server");
while (!res.killSwitch) {
Socket sock = server.accept();
//res.alert("ACCEPTED!");
new Thread(new ConnHandler(sock, res)).start();
//handler.run();
//res.alert("RESTARTING LOOP");
}
server.close();
} catch (IOException e) {
System.out.println("IOException in init(): " + e.toString());
res.error( "IOException in init(): " + e.toString());
}
// HANDLE QUIT?
//res.error("QUITING!");
}
}

View File

@ -1,5 +1,5 @@
Cortex.jar: Cortex.class ConnHandler.class ResManager.class
jar cvf Cortex.jar Cortex.class ConnHandler.class ResManager.class
jar cvf Cortex.jar Cortex.class Server.class ConnHandler.class ResManager.class
jarsigner Cortex.jar cortex_cert
ResManager.class: ResManager.java
@ -8,6 +8,9 @@ ResManager.class: ResManager.java
ConnHandler.class: ConnHandler.java
javac ConnHandler.java
Server.class: Server.java
javac Server.java
Cortex.class: Cortex.java
javac Cortex.java

View File

@ -1,3 +1,4 @@
import java.applet.*;
import java.util.HashMap;
import javax.swing.JOptionPane.*;
import java.util.ArrayList;
@ -11,20 +12,27 @@ import java.net.*;
class ResManager {
public /*final*/ int PORT = 2600;
private Applet applet;
FileWriter debugFW = null;
BufferedWriter debugOut = null;
private HashMap<String, byte[]> site = new HashMap<String, byte[]>();
private HashMap<String, String> nodeData = new HashMap<String, String>();
// Internal Activity Log
private ArrayList<String> log = new ArrayList<String>();
private boolean logLock = false;
//private boolean logLock = false;
private DateFormat logDateFormat = new SimpleDateFormat("HH:mm:ss");
private boolean mqLock = false;
// Message Queue
//private boolean mqLock = false;
private ArrayList<String> msgQueue = new ArrayList<String>();
public boolean killSwitch = false;
public ResManager() {
public ResManager(Applet a) {
applet = a;
}
public void putSite(String key, byte[] val) {
@ -43,62 +51,74 @@ class ResManager {
return nodeData.get(key);
}
private synchronized void logLock() {
while (logLock == true) {
public void log(String l) {
synchronized (log) {
Date d = new Date();
log.add(logDateFormat.format(d) + ": " + l);
log.notifyAll();
if (debugOut != null) {
try {
wait();
} catch (Exception e) {
error("logLock: " + e.toString());
debugOut.write(logDateFormat.format(d) + ": " + l + "\n");
debugOut.flush();
} catch (IOException e) {
// Fail
}
}
}
logLock = true;
//javax.swing.JOptionPane.showMessageDialog(null, " Locked");
}
private synchronized void logUnlock() {
logLock = false;
//javax.swing.JOptionPane.showMessageDialog(null, " UnLocked");
}
public synchronized void log(String l) {
logLock();
Date d = new Date();
log.add(logDateFormat.format(d) + ": " + l);
logUnlock();
}
private synchronized void mqLock() {
while(mqLock == true) {
try {
wait();
} catch (Exception e) {
error("mqLock: " + e.toString());
public void debug(String l) {
synchronized (log) {
Date d = new Date();
try {
debugOut.write(logDateFormat.format(d) + ": " + l + "\n");
debugOut.flush();
} catch (IOException e) {
// Fail
}
}
mqLock = true;
}
private synchronized void mqUnlock() {
mqLock = false;
public void logWait() {
synchronized(log) {
try {
log.wait();
} catch (Exception e) { }
}
}
public synchronized void queueMsg(String m) {
mqLock();
msgQueue.add(m);
mqUnlock();
public void queueMsg(String m) {
synchronized (msgQueue) {
msgQueue.add(m);
msgQueue.notifyAll();
}
//applet.repaint();
}
public synchronized ArrayList<String> getMsgs() {
mqLock();
ArrayList<String> mq = msgQueue;
msgQueue = new ArrayList<String>();
mqUnlock();
public void mqWait() {
synchronized(msgQueue) {
try {
msgQueue.wait();
} catch (Exception e) { }
}
}
public ArrayList<String> getMsgs() {
ArrayList<String> mq;
synchronized(msgQueue) {
mq = msgQueue;
msgQueue = new ArrayList<String>();
}
//applet.repaint();
return mq;
}
public int mqSize() {
return msgQueue.size();
}
public void alert(String a) {
javax.swing.JOptionPane.showMessageDialog(null, a);
javax.swing.JOptionPane.showMessageDialog(null, Integer.toString(PORT) + ": " + a);
log("ALERT> " + a);
}
@ -108,13 +128,13 @@ class ResManager {
}
// returns the current log and RESETS it
public synchronized ArrayList<String> getLog()
public ArrayList<String> getLog()
{
logLock();
ArrayList<String> tmp = log;
log = new ArrayList<String>();
logUnlock();
return tmp;
synchronized(log) {
ArrayList<String> tmp = log;
log = new ArrayList<String>();
return tmp;
}
}
public void reloadSite() {
@ -158,22 +178,18 @@ class ResManager {
}
}
/*
public synchronized void put(String key, String val) {
//javax.swing.JOptionPane.showMessageDialog(null, "putting: '" + key + "'");
//javax.swing.JOptionPane.showMessageDialog(null, val);
//data.put(key, val);
}
public synchronized String get(String key) {
//javax.swing.JOptionPane.showMessageDialog(null, "getting: '" + key + "'");
//javax.swing.JOptionPane.showMessageDialog(null, "from: " + data.keySet().toString());
//return data.get(key);
}*/
public void openDebugLog(String ip) {
String fname = "cortex." + ip + ":" + Integer.toString(PORT) + ".log";
//FileWriter debugFileW = new FileWriter("/tmp/" + fname);
try {
debugFW = new FileWriter("/tmp/" + fname);
debugOut = new BufferedWriter(debugFW);
} catch (IOException e) {
debugFW = null;
debugOut = null;
error("Failed to open debug log");
}
}
}

View File

@ -131,6 +131,9 @@ function getLog() {
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);
}
@ -170,7 +173,11 @@ function getMsgs() {
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);
}
@ -801,14 +808,14 @@ function cron() {
}
if (runCount % 5 == 0) {
/*if (runCount % 5 == 0) {
getMsgs();
}
}*/
// once a second
if (runCount % 10 == 0) {
ping();
getLog();
//getLog();
setStatus();
checkLocks();
updateTestsStatus();
@ -1845,6 +1852,9 @@ function updateFinalResults() {
var cronID = setInterval("cron()", 100);
getMsgs();
getLog();
function page(p) {
// turn off all pages

View File

@ -29,7 +29,7 @@
<input type="button" value="Load" onClick="load()" />
<input id="port" size="4" value="2600" />
<applet code="Cortex.class" archive="Cortex.jar" width="50" height="50" id="cortex"></applet>
<applet code="Cortex.class" archive="Cortex.jar" width="100" height="50" id="cortex"></applet>
<b>Coretex Client</b><br/>
<iframe height="400" width="600" id="client" name="client">