Commit 1db62ed6 authored by David Johnson's avatar David Johnson

Bunch of bug fixes.

parent be95cc12
......@@ -7,7 +7,8 @@ import java.io.*;
public class MoteLogger {
private int debug;
public static int debug;
private File classDir;
private String[] classNames;
private File aclDir;
......@@ -15,7 +16,7 @@ public class MoteLogger {
private String pid;
private String eid;
private String[] motes;
private SynchQueue packetQueue;
private LinkedList packetQueue;
private String dbURL = "jdbc.DriverMysql";
private String dbUser = "root";
private String dbPass = "";
......@@ -35,6 +36,16 @@ public class MoteLogger {
parseArgsAndRun(args);
}
public static void globalDebug(int level,String msg) {
if (MoteLogger.debug >= level) {
System.out.println("DEBUG: " + msg);
}
}
public static void globalError(String msg) {
System.err.println("ERROR: " + msg);
}
public static void parseArgsAndRun(String args[]) {
File classDir = null;
String[] classNames = null;
......@@ -42,7 +53,6 @@ public class MoteLogger {
String pid = null;
String eid = null;
File aclDir = new File("/var/log/tiplogs");
int debug = 0;
String[] motes = null;
int i;
......@@ -102,7 +112,7 @@ public class MoteLogger {
}
}
else if (args[i].equals("-d")) {
++debug;
++MoteLogger.debug;
}
else if (args[i].startsWith("-")) {
System.err.println("Improper option '" + args[i] + "'!");
......@@ -124,9 +134,14 @@ public class MoteLogger {
//this.motes = motes;
if (tag == null || tag.length() == 0) {
// gen a random num
tag = "" + (int)(Math.random()*9999);
}
// startup
MoteLogger ml = new MoteLogger(classDir,classNames,aclDir,motes,
pid,eid,tag,debug);
pid,eid,tag);
ml.run();
}
......@@ -151,18 +166,25 @@ public class MoteLogger {
public MoteLogger(File classDir,String[] classNames,
File aclDir,String[] motes,String pid,
String eid,String tag,int debug) {
String eid,String tag) {
this.classDir = classDir;
this.classNames = classNames;
this.aclDir = aclDir;
this.pid = pid;
this.eid = eid;
this.logTag = tag;
this.debug = debug;
this.motes = motes;
this.classes = new Hashtable();
}
private void debug(int level,String msg) {
MoteLogger.globalDebug(level,"MoteLogger: " + msg);
}
private void error(String msg) {
MoteLogger.globalError("MoteLogger: " + msg);
}
// I know, not a thread, but who cares
public void run() {
if (motes == null || motes.length == 0) {
......@@ -190,17 +212,18 @@ public class MoteLogger {
}
if (motes == null || motes.length == 0) {
System.out.println("Could not find any mote ACL files; exiting.");
error("could not find any mote ACL files; exiting.");
System.exit(0);
}
// load classfiles and create Class objs so we can do instance objs
// on incoming packet data
// first, have to discover the classfiles, if they weren't specified.
File[] classFiles = null;
if (this.classNames == null || classNames.length == 0) {
// try to read the classFile directory and use the XXX.class
// names as the classes -- will fail if classes are in package.
File[] classFiles = classDir.listFiles( new FilenameFilter() {
classFiles = classDir.listFiles( new FilenameFilter() {
public boolean accept(File dir, String name) {
if (name != null && name.endsWith(".class")) {
return true;
......@@ -222,7 +245,7 @@ public class MoteLogger {
}
if (classFiles == null || classFiles.length == 0) {
System.out.println("Could not find any classfiles; exiting.");
error("could not find any classfiles; exiting.");
System.exit(0);
}
......@@ -237,7 +260,7 @@ public class MoteLogger {
this.logTag));
}
catch (Exception e) {
System.err.println("Problem loading class " + classNames[i] +
error("problem loading class " + classNames[i] +
":");
e.printStackTrace();
}
......@@ -251,23 +274,23 @@ public class MoteLogger {
acls.put(motes[i],ma);
}
catch (Exception e) {
System.err.println("Problem reading ACL for " + motes[i]);
error("problem reading ACL for " + motes[i]);
e.printStackTrace();
}
}
// setup queue
packetQueue = new SynchQueue();
packetQueue = new LinkedList();
// connect to the database
Connection conn = null;
java.sql.Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:" +
conn = java.sql.DriverManager.getConnection("jdbc:mysql:" +
"//localhost/test?user=root");
}
catch (Exception e) {
System.err.println("FATAL -- couldn't connect to the database: " +
error("FATAL -- couldn't connect to the database: " +
e.getMessage());
e.printStackTrace();
......@@ -278,7 +301,7 @@ public class MoteLogger {
for (Enumeration e1 = acls.keys(); e1.hasMoreElements(); ) {
String vNN = (String)e1.nextElement();
ElabACL acl = (ElabACL)acls.get(vNN);
(new MoteThread(acl,packetQueue)).start();
(new MoteThread(vNN,acl,packetQueue)).start();
}
// now, process the packet queue forever.
......@@ -286,7 +309,9 @@ public class MoteLogger {
LogPacket lp = null;
synchronized(packetQueue) {
while(packetQueue.peek() == null) {
debug(1,"Waiting for packets...");
while(packetQueue.size() == 0) {
try {
packetQueue.wait();
}
......@@ -296,63 +321,99 @@ public class MoteLogger {
}
// once we get a packet...
lp = packetQueue.queueRemove();
lp = (LogPacket)packetQueue.removeLast();
}
debug(2,"Dumping packet to db:");
// dump it out to database:
// this is the real work:
try {
// first match the packet:
SQLGenerator sq = null;
boolean foundMatch = false;
for (Enumeration e1 = classes.keys();
!foundMatch && e1.hasMoreElements(); ) {
Class cc = (Class)e1.nextElement();
sq = (SQLGenerator)classes.get(cc);
// Need to create a BaseTOSMsg
// and extract the 'type' field... which is the am type
// ... and then match this with the amType() method of the
// invoked class.
// XXX: note that this must be changed depending on the
// architecture of the motes we're connecting to, in order
// to decode using the correct host byte order assumption.
// i.e., net.tinyos.message.telos.*
//
if (true) {
net.tinyos.message.avrmote.BaseTOSMsg btm =
new net.tinyos.message.avrmote.BaseTOSMsg(lp.getData());
if (lp.amType() == sq.getAMType()) {
// class match
// invoke the byte[] data constructor on the data
// from the basetosmsg:
Constructor ccc = cc.getConstructor( new Class[] {
byte[].class } );
Object msgObj = ccc.newInstance( new Object[] {
btm.get_data() } );
lp.setMsgObject(msgObj);
// ready to log!!!
foundMatch = true;
if (lp != null) {
try {
// first match the packet:
SQLGenerator sq = null;
boolean foundMatch = false;
Object msgObj = null;
for (Enumeration e1 = classes.keys();
!foundMatch && e1.hasMoreElements(); ) {
Class cc = (Class)e1.nextElement();
sq = (SQLGenerator)classes.get(cc);
// Need to create a BaseTOSMsg
// and extract the 'type' field... which is the am type
// ... and then match this with the amType() method of
// the invoked class.
// XXX: note that this must be changed depending on the
// architecture of the motes we're connecting to, in
// order to decode using the correct host byte order
// assumption.
// i.e., net.tinyos.message.telos.*
//
if (true) {
net.tinyos.message.avrmote.BaseTOSMsg btm =
new net.tinyos.message.avrmote.BaseTOSMsg(lp.getData());
debug(1,"lp data size = " + lp.getData().length);
// XXX: this is some nasty hack!!! the BaseTosMsg
// doesn't seem to want to let me call get_data.
// However, I want to remove the basic
// AM fields at the front... which are 5 bytes
// (at least for mica2!)
int PREBYTE_REMOVE = 5;
int realLen = lp.getData().length-PREBYTE_REMOVE;
byte[] realdata = new byte[realLen];
System.arraycopy(lp.getData(),PREBYTE_REMOVE,
realdata,0,realLen);
if (btm.get_type() == sq.getAMType()) {
// class match
// invoke the byte[] data constructor on the
// data from the basetosmsg:
Constructor ccc = cc.getConstructor( new Class[] {
byte[].class } );
msgObj = ccc.newInstance( new Object[] {
//btm.get_data() } );
//lp.getData() } );
realdata } );
lp.setMsgObject(msgObj);
// ready to log!!!
foundMatch = true;
debug(2,"found packet type match with type " +
btm.get_type());
}
else {
debug(2,"btm.amType=" + btm.get_type() +
"; sq.getAMType=" + sq.getAMType());
}
}
}
// do the db insert:
if (foundMatch) {
sq.storeMessage(lp,conn);
}
else {
error("NO match for packet!");
}
// that's all, folks!
}
catch (Exception e) {
error("error while logging packet: ");
e.printStackTrace();
}
// do the db insert:
sq.storeMessage(msgObj,conn);
// that's all, folks!
}
catch (Exception e) {
System.err.println("Error while logging packet: ");
e.printStackTrace();
else {
error("got a null packet from the PacketReader!");
}
}
......@@ -362,29 +423,37 @@ public class MoteLogger {
class MoteThread extends Thread {
private String vNodeName;
private ElabACL acl;
private SynchQueue q;
private LinkedList q;
private Socket sock;
public MoteLogThread(String vNodeName,ElabACL acl,
SynchQueue packetQueue) {
public MoteThread(String vNodeName,ElabACL acl,
LinkedList packetQueue) {
this.vNodeName = vNodeName;
this.acl = acl;
this.q = packetQueue;
}
private void debug(int level,String msg) {
MoteLogger.globalDebug(level,
"MoteThread (" + vNodeName + "): " + msg);
}
private void error(String msg) {
MoteLogger.globalError("MoteThread (" + vNodeName + "): " + msg);
}
public void run() {
sock = null;
try {
// isn't java just wonderful
sock = new Socket(acl.getHost(),acl.getPort());
System.out.println("Connected to " + sock.getInetAddress() +
":" + sock.getPort() + " for " +
acl.getVnodeName());
debug(1,"connected to " +
sock.getInetAddress() + ":" + sock.getPort());
}
catch (Exception e) {
System.err.println("Couldn't connect to " + acl.getHost() +
":" + acl.getPort());
error("couldn't connect to " + acl.getHost() +
":" + acl.getPort());
e.printStackTrace();
return;
}
......@@ -418,9 +487,9 @@ public class MoteLogger {
//bkey[0] = 0;
//bkey[255] = 0;
System.out.println("Sending keylen " + keylen + " and key " +
key + " bytearraylen = "+key.getBytes().length +
" \n realkey = '"+new String(authBytes)+"'");
debug(4,"sending keylen " + keylen + " and key " +
key + " bytearraylen = "+key.getBytes().length +
" \n realkey = '"+new String(authBytes)+"'");
try {
OutputStream out = sock.getOutputStream();
......@@ -453,15 +522,15 @@ public class MoteLogger {
msg = "failure (" + retval +").";
}
System.out.println("Result of authentication: " + msg);
debug(2,"result of authentication: " + msg);
if (retval != 0) {
return;
}
}
catch (Exception e) {
System.err.println("Problem authenticating for " +
acl.getVnodeName());
error("problem authenticating for " +
acl.getVnodeName());
e.printStackTrace();
return;
}
......@@ -482,15 +551,15 @@ public class MoteLogger {
lp = null;
try {
lp = pr.readPacket();
synchronized(packetQueue) {
packetQueue.queueAdd(lp);
packetQueue.notifyAll();
synchronized(q) {
q.addFirst(lp);
q.notifyAll();
}
}
catch (Exception e) {
System.err.println("Problem while reading from " +
acl.getVnodeName());
error("problem while reading from " +
acl.getVnodeName());
e.printStackTrace();
}
}
......
......@@ -52,7 +52,7 @@ public final class PacketReader {
/* see http://www.tinyos.net/tinyos-1.x/doc/serialcomm/description.html */
final static int SYNC_BYTE = 0x7e;
final static int SYNC_BYTE = 0x7e;
final static int ESCAPE_BYTE = 0x7d;
final static int MTU = 256;
// don't need this cause we're not responding.
......@@ -71,6 +71,14 @@ public final class PacketReader {
this.in = in;
}
private void debug(int level,String msg) {
MoteLogger.globalDebug(level,"PacketReader: " + msg);
}
private void error(String msg) {
MoteLogger.globalError("PacketReader: " + msg);
}
// this method is meant to be called repeatedly, at a high rate.
// if "arrangements" in the caller (like synchronization with a queue)
// make fast, repetitious calls impossible, the timestamps will get off.
......@@ -84,6 +92,8 @@ public final class PacketReader {
// byte by byte for now -- ick!
// obviously, this method is NOT thread-safe.
debug(3,"trying to read a packet");
byte[] buf = new byte[MTU];
int currentOffset = 0;
boolean isEscaped = false;
......@@ -96,10 +106,13 @@ public final class PacketReader {
buf[i] = 0;
}
currentOffset = 0;
sync = false;
isEscaped = false;
}
// read byte -- let the exception fly through to the caller
byte b = (byte)in.read();
int b = (int)in.read();
debug(4,"read byte: "+b);
if (b == ESCAPE_BYTE) {
isEscaped = true;
......@@ -108,7 +121,8 @@ public final class PacketReader {
if (isEscaped && sync) {
// ex-xor it
b ^= 0x20;
buf[currentOffset++] = b;
buf[currentOffset++] = (byte)b;
isEscaped = false;
}
else if (isEscaped) {
// we're trying to sync via an escaped data byte, bad us
......@@ -116,9 +130,11 @@ public final class PacketReader {
}
else if (sync) {
// end of packet
debug(3,"saw end sync byte");
break;
}
else {
debug(3,"saw first sync byte");
sync = true;
}
}
......@@ -126,9 +142,10 @@ public final class PacketReader {
// normal data byte:
if (isEscaped) {
b ^= 0x20;
isEscaped = false;
}
buf[currentOffset++] = b;
buf[currentOffset++] = (byte)b;
}
}
......@@ -147,14 +164,18 @@ public final class PacketReader {
if (buf[0] == P_PACKET_NO_ACK) {
// no "prefix" byte
retval = new byte[buf.length-3];
retval = new byte[currentOffset-3];
System.arraycopy(buf,1,retval,0,retval.length);
debug(2,"recv no ack pkt; length="+retval.length);
return new LogPacket(vNodeName,t,retval,packetType,crc);
}
else if (buf[0] == P_PACKET_ACK) {
retval = new byte[buf.length-4];
System.arraycopy(buf,2,retval,0,retval.length);
debug(2,"recv ack pkt; length="+retval.length);
return new LogPacket(vNodeName,t,retval,packetType,crc);
}
......@@ -162,9 +183,13 @@ public final class PacketReader {
// do nothing for now; this is only sent by receiver on
// receipt of an unknown packet type anyway
;
debug(2,"recv ack/unknown pkt!");
}
else {
// XXX: might want to log these in the future...
debug(2,"recv TOTALLY unknown pkt!");
}
return null;
......
......@@ -32,7 +32,8 @@ public class SQLGenerator {
private ArrayList[] insertInfo;
private String className;
private String msgSpec;
private Class classInfo;
private String msgSpec[];
private String tag;
private int amType;
......@@ -47,6 +48,9 @@ public class SQLGenerator {
this.tag = tag;
Class c = Class.forName(className);
this.classInfo = c;
//debug(3,"sqlgen constructor for '"+name+"'");
// grab the am type first!
Object msgObj = c.newInstance();
......@@ -57,7 +61,7 @@ public class SQLGenerator {
// now figure out the methods. Basically, we figure out which
// get_* methods correspond to which arrays by finding the longest
// common substring following the get_ part of the string.
Methods[] m = c.getMethods();
Method[] m = c.getMethods();
Vector flatFieldMethods = new Vector();
Vector arrayFieldMethods = new Vector();
......@@ -111,9 +115,9 @@ public class SQLGenerator {
;
}
else {
// simple, one-table layout with two views.
// simple, n-table layout with two views; one master table.
int numTables = 1 + arrayFields.length;
int tableIndex = 1;
int tableIdx = 1;
tableCreates = new String[numTables];
inserts = new String[numTables];
......@@ -123,10 +127,10 @@ public class SQLGenerator {
// main table
String tableName = className + "__data_" + tag;
parentTableName = tableName;
String parentTableName = tableName;
tableCreates[0] = "" +
"CREATE TABLE " + tableName + " " +
"CREATE TABLE IF NOT EXISTS " + tableName + " " +
"(" + "id INT PRIMARY KEY AUTO_INCREMENT, " +
"time DATETIME, " +
"amType INT, " +
......@@ -134,6 +138,8 @@ public class SQLGenerator {
inserts[0] = "insert into " + tableName +
" values (NULL,?," + this.amType + ",?";
insertInfo[0] = new ArrayList();
insertInfo[0].add( new String[] { "date",null,null } );
// now get this statically.
......@@ -147,11 +153,11 @@ public class SQLGenerator {
String mn = ma[i].getName();
if (mn.startsWith("get_")) {
String mnSansGet = mn.subString(4,mnSansGet.length());
String mnSansGet = mn.substring(4,mn.length());
Method signMethod = null;
try {
signMethod = c.getMethod("isSigned_" + mnSansGet);
signMethod = c.getMethod("isSigned_" + mnSansGet,null);
}
catch (Exception e) {
// no big deal
......@@ -186,8 +192,8 @@ public class SQLGenerator {
// we add the table now:
String aTableName = mnSansGet + "__data_" + tag;
tableCreates[tableIdx] = "" +
"CREATE TABLE " + aTableName + " (" +
"ppid INT PRIMARY KEY NOT NULL, " +
"CREATE TABLE IF NOT EXISTS " + aTableName +
" (" + "ppid INT PRIMARY KEY NOT NULL, " +
"idx INT NOT NULL, " +
"" + mnSansGet + " " + internalArraySQLType +
")";
......@@ -225,10 +231,23 @@ public class SQLGenerator {
inserts[0] += ")";
}
for (int k = 0; k < tableCreates.length; ++k) {