Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

Hillock.java

Go to the documentation of this file.
00001 package net.threebit.utils.sosc;
00002 
00003 /*
00004         Copyright 2003 Kevin O'Donnell
00005 
00006         This program is free software; you can redistribute it and/or modify
00007         it under the terms of the GNU General Public License as published by
00008         the Free Software Foundation; either version 2 of the License, or
00009         (at your option) any later version.
00010 
00011         This program is distributed in the hope that it will be useful,
00012         but WITHOUT ANY WARRANTY; without even the implied warranty of
00013         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014         GNU General Public License for more details.
00015 
00016         You should have received a copy of the GNU General Public License
00017         along with this program; if not, write to the Free Software
00018         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 */
00020 
00021 import java.sql.*;
00022 import java.util.*;
00023 import java.util.logging.*;
00024 
00029 public class Hillock {
00030 
00034         private static final Logger logger = Logger.getLogger("net.threebit.utils.sosc");
00035 
00039         private static boolean enabled = true;
00040 
00045         private static final ThreadLocal threadLocal = new ThreadLocal();
00046 
00050         private static final LinkedList workQueue = new LinkedList();
00051 
00057         public static void startPath (String name) {
00058                 if (! enabled) { return; }
00059                 Long started = new Long(System.currentTimeMillis());
00060 
00061                 // Make sure any existing path has been ended.
00062                 endPath();
00063 
00064                 HashMap map = local();
00065                 synchronized (map) {
00066                         map.put("started", started);
00067                         map.put("name", name);
00068                         map.put("nodes", new LinkedList());
00069                 }
00070 
00071         }
00072 
00076         public static void endPath() {
00077                 if (! enabled) { return; }
00078 
00079                 Long ended = new Long(System.currentTimeMillis());
00080                 Map work = new HashMap();
00081 
00082                 HashMap map = local();
00083                 synchronized (map) {
00084                         // Nothing to do
00085                         if (map.get("name") == null) { return ; }
00086 
00087                         // Mark the time the path was ended.
00088                         map.put("ended", ended);
00089 
00090                         // Prepare the data object that goes into the worker threads queue
00091                         work.put("name", map.get("name"));
00092                         work.put("started", map.get("started"));
00093                         work.put("ended", map.get("ended"));
00094                         work.put("nodes", map.get("nodes"));
00095 
00096                         // Since the path has ended, no data should stay around
00097                         map.clear();
00098                 }
00099 
00100                 synchronized (workQueue) {
00101                         workQueue.add(work);
00102                         workQueue.notifyAll();
00103                 }
00104 
00105         }
00106 
00110         public static void startNode (String name) {
00111                 if (! enabled) { return; }
00112 
00113                 Long started = new Long(System.currentTimeMillis());
00114                 Map newNode = new HashMap();
00115                 newNode.put("name",name);
00116                 newNode.put("started", started);
00117 
00118                 HashMap map = local();
00119                 synchronized (map) {
00120                         LinkedList nodes = (LinkedList) map.get("nodes");
00121 
00122                         if (nodes.size() == 0) {
00123                                 // Outlier condition; first node in the path.
00124                                 nodes.add(newNode);
00125                                 return;
00126                         }
00127 
00128                         Map node = (Map) nodes.getLast();
00129                         if (node.get("ended") != null) {
00130                                 // 1 dimensional case; just add the node to the end of the list
00131                                 // with a null parent (this is a "top level" node on the path.
00132                                 nodes.add(newNode);
00133                         }
00134                         else {
00135                                 // The top level node is not closed, so this node will be
00136                                 // placed as a leaf somewhere below it.  Search for the appropriate
00137                                 // location.
00138                                 while (true) {
00139                                         LinkedList children = (LinkedList) node.get("children");
00140                                         if (children == null || children.size() == 0) {
00141                                                 // This is the first child added to the node.
00142                                                 if (children == null) { children = new LinkedList(); }
00143                                                 children.add( newNode );
00144                                                 node.put("children",children);
00145                                                 break;
00146                                         }
00147                                         else {
00148                                                 // Some children already exist.  If the last child has ended,
00149                                                 // then the new node is a sibling to it.  If it has not been
00150                                                 // ended, then the new node should be added underneath it.
00151                                                 Map child = (Map) children.getLast();
00152                                                 if (child.get("ended") != null) {
00153                                                         // New node is a sibling
00154                                                         children.add( newNode );
00155                                                         break;
00156                                                 }
00157                                                 else {
00158                                                         // Last child has not ended, so reset "node" to be the 
00159                                                         // last child and loop to continue searching
00160                                                         node = child;
00161                                                 }
00162                                         }
00163                                 }
00164                         }
00165                 }
00166         }
00167 
00171         public static void endNode() {
00172                 if (! enabled) { return; }
00173 
00174                 Long ended = new Long(System.currentTimeMillis());
00175                 HashMap map = local();
00176                 synchronized (map) {
00177                         LinkedList nodes = (LinkedList) map.get("nodes");
00178                         if (nodes == null || nodes.size() == 0) { return; }
00179                         Map node = (Map) nodes.getLast();
00180                         while (true) {
00181                                 LinkedList children = (LinkedList) node.get("children");
00182                                 if (children == null || children.size() == 0) {
00183                                         // This node is being ended
00184                                         if (node.get("ended") != null) { throw new RuntimeException(" Assert failed: tried to 'end' a node twice"); }
00185                                         node.put("ended",ended);
00186                                         break;
00187                                 }
00188                                 else {
00189                                         // This node has children;
00190                                         Map child = (Map) children.getLast();
00191                                         if (child.get("ended") == null) {
00192                                                 // The last child has not ended; reset "node" to be the child and continue
00193                                                 node = child;
00194                                         }
00195                                         else {
00196                                                 // THe last child has ended; therefore, end the current node
00197                                                 node.put("ended",ended);
00198                                                 break;
00199                                         }
00200                                 }
00201                         }
00202                 }
00203         }
00204 
00208         public static void node (String name) {
00209                 startNode(name);
00210                 endNode();
00211         }
00212 
00216         public static HashMap local() {
00217                 synchronized (threadLocal) {
00218                         HashMap m = (HashMap) threadLocal.get();
00219                         if (m == null) {
00220                                 m = new HashMap();
00221                                 threadLocal.set( m );
00222                         }
00223                         return m;
00224                 }
00225         }
00226 
00304         public static DbTool db() throws Exception {
00305                 return new DbTool(jdbcDriverClass(), jdbcURL(), jdbcUserName(), jdbcPassword());
00306         }
00307 
00309         public static String jdbcDriverClass () { return System.getProperty("net.threebit.utils.sosc.Hillock.jdbcDriverClass"); }
00310 
00312         public static String jdbcURL () { return System.getProperty("net.threebit.utils.sosc.Hillock.jdbcURL"); }
00313 
00315         public static String jdbcUserName () { return System.getProperty("net.threebit.utils.sosc.Hillock.jdbcUserName"); }
00316 
00318         public static String jdbcPassword () { return System.getProperty("net.threebit.utils.sosc.Hillock.jdbcPassword"); }
00319 
00320         static {
00321 
00322                 Thread worker = new Thread() {
00326                         public void run() {
00327                                 try {
00328                                         LinkedList workList = new LinkedList();
00329                                         while (true) {
00330         
00331                                                 // check/wait for work.
00332                                                 synchronized (workQueue) {
00333         
00334                                                         // Wait for work to appear if there isnt any already
00335                                                         if (workQueue.size() == 0) { workQueue.wait(); }
00336         
00337                                                         // Copy the work out of workQueue so we can release the 
00338                                                         // lock and continue to the database work.
00339                                                         workList.addAll( workQueue );
00340                                                         workQueue.clear();
00341                                                 }
00342 
00343                                                 DbTool db = null;
00344                                                 try {
00345                                                         db = db();
00346                                                         Connection c = db.getConnection();
00347                                                         c.setAutoCommit(false);
00348                                                         c.setTransactionIsolation( Connection.TRANSACTION_SERIALIZABLE );
00349                                                         PreparedStatement ps = c.prepareStatement(" insert into hillockPaths (name, started, ended) values (?,?,?) ");
00350                                                         PreparedStatement ns = c.prepareStatement(" insert into hillockPathNodes (name, started, ended, path, parent) values (?,?,?,?,?) ");
00351 
00352                                                         for (Iterator i = workList.iterator(); i.hasNext(); ) {
00353                                                                 Map path = (Map) i.next();
00354 
00355                                                                 Long pathEnded = (Long) path.get("ended");
00356                                                                 LinkedList nodes = (LinkedList) path.get("nodes");
00357 
00358                                                                 ps.setString(1,(String) path.get("name"));
00359                                                                 ps.setTimestamp(2,new Timestamp(((Long) path.get("started")).longValue()));
00360                                                                 ps.setTimestamp(3,new Timestamp(((Long) path.get("ended")).longValue()));
00361                                                                 ps.execute();
00362                                                                 ps.clearParameters();
00363                                                                 int pathId = db.getInt(" select max(id) from hillockPaths ");
00364 
00365                                                                 LinkedList stack = new LinkedList();
00366                                                                 stack.addAll( (List) nodes );
00367 
00368                                                                 while (stack.size() > 0) {
00369                                                                         Map node = (Map) stack.removeFirst();
00370 
00371                                                                         Integer parent = (Integer) node.get("parent"); 
00372                                                                         Long nodeEnded = (Long) node.get("ended");
00373                                                                         if (nodeEnded == null) { nodeEnded = pathEnded; }
00374 
00375                                                                         ns.setString(1, (String) node.get("name"));
00376                                                                         ns.setTimestamp(2,new Timestamp(((Long) node.get("started")).longValue()));
00377                                                                         ns.setTimestamp(3,new Timestamp(nodeEnded.longValue()));
00378                                                                         ns.setInt(4, pathId);
00379                                                                         if (parent == null) { ns.setNull(5, Types.INTEGER); }
00380                                                                         else { ns.setInt(5, parent.intValue() ); }
00381                                                                         ns.execute();
00382                                                                         ns.clearParameters();
00383                                                                         Integer nodeId = new Integer(db.getInt(" select max(id) from hillockPathNodes; "));
00384 
00385                                                                         // Put any of this nodes children on the stack, at the start, so
00386                                                                         // they are inserted first.
00387                                                                         LinkedList children = (LinkedList) node.get("children");
00388                                                                         if (children != null) {
00389                                                                                 LinkedList stackAdd = new LinkedList();
00390                                                                                 for (Iterator j = children.iterator(); j.hasNext(); ) {
00391                                                                                         Map child = (Map) j.next();
00392                                                                                         child.put("parent", nodeId);
00393                                                                                         stackAdd.add(child);
00394                                                                                 }
00395                                                                                 stack.addAll(0, stackAdd);
00396                                                                         }
00397                                                                 }
00398                                                         }
00399                                                 }
00400                                                 catch (Exception e) {
00401                                                         logger.throwing("HillockWorker","run",e);
00402                                                 }
00403                                                 finally {
00404                                                         try { if (db != null) { db.commit(); } } catch (Exception e) { logger.throwing("HillockWorker","run",e); }
00405                                                         try { if (db != null) { db.close(); } } catch (Exception e) { logger.throwing("HillockWorker","run",e); }
00406                                                 }
00407                                                 workList.clear();
00408                                         }
00409                                 }
00410                                 catch (Exception e) {
00411                                         enabled = false;
00412                                         logger.throwing("HillockWorker","run",e);
00413                                 }
00414                         }
00415                 };
00416                 worker.start();
00417         } // static worker initialization
00418 }

Generated on Mon Jul 14 17:19:20 2003 for SOSC by doxygen1.2.15