long now = System.currentTimeMillis ();
    public void run () {	long cleanupSleep = 60000;    // thread sleep interval (fixed)	long scheduleSleep = 60000;  // interval for scheduler invocation	long lastScheduler = 0;	logEvent ("Starting scheduler for "+name);	// as first thing, invoke function onStart in the root object	try {	    eval.invokeFunction ((INode) null, "onStart", new ESValue[0]);	} catch (Exception ignore) {}		while (Thread.currentThread () == worker) {	    // get session timeout	    int sessionTimeout = 30;	    try {	        sessionTimeout = Math.max (0, Integer.parseInt (props.getProperty ("sessionTimeout", "30")));	    } catch (Exception ignore) {} 	    try {	        worker.sleep (cleanupSleep);	    } catch (InterruptedException x) {	        logEvent ("Scheduler for "+name+" interrupted");	        worker = null;	        break;	    }	    try {	        logEvent ("Cleaning up "+name+": " + sessions.size () + " sessions active");	        long now = System.currentTimeMillis ();	        Hashtable cloned = (Hashtable) sessions.clone ();	        for (Enumeration e = cloned.elements (); e.hasMoreElements (); ) {	            User u = (User) e.nextElement ();	            if (now - u.touched () > sessionTimeout * 60000) {	                if (u.uid != null) {	                    try {	                        eval.invokeFunction (u, "onLogout", new ESValue[0]);	                    } catch (Exception ignore) {	                        ignore.printStackTrace ();	                    }	                    activeUsers.remove (u.uid);	                }	                sessions.remove (u.getSessionID ());	                u.setNode (null);	            }	        }	        logEvent ("Cleaned up "+name+": " + sessions.size () + " sessions remaining");	    } catch (Exception cx) {	        logEvent ("Error cleaning up sessions: "+cx);	        cx.printStackTrace ();	    }	    long now = System.currentTimeMillis ();	    if (now - lastScheduler > scheduleSleep) {	        lastScheduler = now;	        ESValue val = null;	        try {	            val = eval.invokeFunction ((INode) null, "scheduler", new ESValue[0]);	        } catch (Exception ignore) {}		        try {	            int ret = val.toInt32 ();	            if (ret < 1000)	                scheduleSleep = 60000l;	            else	                scheduleSleep = ret;	        } catch (Exception ignore) {}	        logEvent ("Called scheduler for "+name+", will sleep for "+scheduleSleep+" millis");	    }	}	logEvent ("Scheduler for "+name+" exiting");    }