org/objectweb/proactive/p2p/daemon/Daemon.java

00001 /* 
00002  * ################################################################
00003  * 
00004  * ProActive: The Java(TM) library for Parallel, Distributed, 
00005  *            Concurrent computing with Security and Mobility
00006  * 
00007  * Copyright (C) 1997-2007 INRIA/University of Nice-Sophia Antipolis
00008  * Contact: proactive@objectweb.org
00009  * 
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or any later version.
00014  *  
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  * 
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00023  * USA
00024  *  
00025  *  Initial developer(s):               The ProActive Team
00026  *                        http://www.inria.fr/oasis/ProActive/contacts.html
00027  *  Contributor(s): 
00028  * 
00029  * ################################################################
00030  */ 
00031 package org.objectweb.proactive.p2p.daemon;
00032 
00033 import java.io.BufferedReader;
00034 import java.io.File;
00035 import java.io.FileReader;
00036 import java.io.IOException;
00037 import java.io.InputStream;
00038 import java.io.InputStreamReader;
00039 import java.io.OutputStream;
00040 import java.io.Reader;
00041 import java.net.InetAddress;
00042 import java.net.MalformedURLException;
00043 import java.net.ServerSocket;
00044 import java.net.Socket;
00045 import java.net.UnknownHostException;
00046 import java.util.ArrayList;
00047 import java.util.Calendar;
00048 import java.util.Collection;
00049 import java.util.GregorianCalendar;
00050 import java.util.HashSet;
00051 import java.util.Iterator;
00052 import java.util.List;
00053 import java.util.ListIterator;
00054 import java.util.Random;
00055 import java.util.Stack;
00056 import java.util.Vector;
00057 
00058 import org.apache.log4j.Appender;
00059 import org.apache.log4j.Layout;
00060 import org.apache.log4j.Logger;
00061 import org.apache.log4j.PatternLayout;
00062 import org.apache.log4j.RollingFileAppender;
00063 import org.apache.log4j.WriterAppender;
00064 import org.apache.log4j.nt.NTEventLogAppender;
00065 import org.objectweb.proactive.core.ProActiveException;
00066 import org.objectweb.proactive.core.util.log.Loggers;
00067 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00068 import org.objectweb.proactive.core.xml.handler.BasicUnmarshaller;
00069 import org.objectweb.proactive.core.xml.io.Attributes;
00070 import org.objectweb.proactive.core.xml.io.StreamReader;
00071 import org.objectweb.proactive.p2p.service.StartP2PService;
00072 import org.xml.sax.ErrorHandler;
00073 import org.xml.sax.InputSource;
00074 import org.xml.sax.SAXException;
00075 import org.xml.sax.SAXParseException;
00076 
00077 
00078 /*
00079  * Exit codes : 0 => OK, restart the daemon
00080  *              1 => Error, don't restart
00081  *              2 => Restart but wait for the next period
00082  *          other => Error, restart
00083  *
00084  * These exit codes must be synchronized with the C code
00085  */
00086 class Moment implements Comparable {
00087     private static final int[][] CONV_INT = {
00088             { Calendar.MONDAY, 0 },
00089             { Calendar.TUESDAY, 1 },
00090             { Calendar.WEDNESDAY, 2 },
00091             { Calendar.THURSDAY, 3 },
00092             { Calendar.FRIDAY, 4 },
00093             { Calendar.SATURDAY, 5 },
00094             { Calendar.SUNDAY, 6 }
00095         };
00096     private static final Object[][] CONV_STR = {
00097             { "monday", new Integer(0) },
00098             { "tuesday", new Integer(1) },
00099             { "wednesday", new Integer(2) },
00100             { "thursday", new Integer(3) },
00101             { "friday", new Integer(4) },
00102             { "saturday", new Integer(5) },
00103             { "sunday", new Integer(6) }
00104         };
00105     public static final Moment END_OF_WEEK = new Moment(6, 23, 59);
00106     public static final Moment START_OF_WEEK = new Moment(0, 0, 0);
00107     public static final int MINUTES_IN_WEEK = 7 * 24 * 60;
00108     private int day;
00109     private int hour;
00110     private int minute;
00111     private int absoluteMinutes;
00112     private boolean valid;
00113 
00114     public Moment() {
00115         GregorianCalendar now = new GregorianCalendar();
00116         day = convertDay(now.get(Calendar.DAY_OF_WEEK));
00117         hour = now.get(Calendar.HOUR_OF_DAY);
00118         minute = now.get(Calendar.MINUTE);
00119         init();
00120     }
00121 
00122     public Moment(int day, int hour, int minute) {
00123         this.day = day;
00124         this.hour = hour;
00125         this.minute = minute;
00126         init();
00127     }
00128 
00129     public Moment(Attributes a) {
00130         this.day = convertDay(a.getValue(0));
00131         this.hour = Integer.parseInt(a.getValue(1));
00132         this.minute = Integer.parseInt(a.getValue(2));
00133         init();
00134     }
00135 
00136     private static int convertDay(int day) {
00137         for (int i = 0; i < CONV_INT.length; i++)
00138             if (CONV_INT[i][0] == day) {
00139                 return CONV_INT[i][1];
00140             }
00141 
00142         return -1;
00143     }
00144 
00145     private static int convertDay(String day) {
00146         for (int i = 0; i < CONV_STR.length; i++)
00147             if (CONV_STR[i][0].equals(day)) {
00148                 return ((Integer) CONV_STR[i][1]).intValue();
00149             }
00150 
00151         return -1;
00152     }
00153 
00154     private void init() {
00155         validate();
00156         absoluteMinutes = (((day * 24) + hour) * 60) + minute;
00157     }
00158 
00159     private void validate() {
00160         valid = true;
00161         valid = valid && (day >= 0);
00162         valid = valid && (day < 7);
00163         valid = valid && (hour >= 0);
00164         valid = valid && (hour < 24);
00165         valid = valid && (minute >= 0);
00166         valid = valid && (minute < 60);
00167     }
00168 
00169     public boolean isValid() {
00170         return valid;
00171     }
00172 
00173     public int compareTo(Object o) {
00174         Moment m = (Moment) o;
00175 
00176         return absoluteMinutes - m.absoluteMinutes;
00177     }
00178 
00179     public boolean equals(Object o) {
00180         return compareTo(o) == 0;
00181     }
00182 
00183     public int minutesFromNow() {
00184         Moment now = new Moment();
00185 
00186         return absoluteMinutes - now.absoluteMinutes;
00187     }
00188 
00189     /* <Debug> */
00190     public String toString() {
00191         return "<" + day + ", " + hour + ", " + minute + ">";
00192     }
00193 
00194     /* </Debug> */
00195 }
00196 
00197 
00198 class IntervalTime implements Comparable {
00199     /* <Debug> */
00200     private static Random random = new Random();
00201     private Moment start;
00202     private Moment end;
00203     private boolean valid;
00204 
00205     public IntervalTime(Moment start, Moment end) {
00206         this.start = start;
00207         this.end = end;
00208         validate();
00209     }
00210 
00211     private void validate() {
00212         valid = true;
00213         valid = valid && start.isValid();
00214         valid = valid && end.isValid();
00215         valid = valid && (start.compareTo(end) < 0);
00216     }
00217 
00218     public boolean isValid() {
00219         return valid;
00220     }
00221 
00222     public boolean contains(Moment moment) {
00223         return (start.compareTo(moment) <= 0) && (end.compareTo(moment) >= 0);
00224     }
00225 
00226     public boolean contains(IntervalTime interval) {
00227         return (start.compareTo(interval.start) <= 0) &&
00228         (end.compareTo(interval.getEnd()) >= 0);
00229     }
00230 
00231     public boolean intersect(IntervalTime interval) {
00232         return contains(interval.start) || contains(interval.end) ||
00233         interval.contains(start) || interval.contains(end);
00234     }
00235 
00236     public int compareTo(Object o) {
00237         IntervalTime it = (IntervalTime) o;
00238 
00239         return start.compareTo(it.start);
00240     }
00241 
00242     public boolean equals(Object o) {
00243         IntervalTime interval = (IntervalTime) o;
00244 
00245         return start.equals(interval.start) && end.equals(interval.end);
00246     }
00247 
00248     public Moment getEnd() {
00249         return end;
00250     }
00251 
00252     public void setEnd(Moment end) {
00253         this.end = end;
00254     }
00255 
00256     public Moment getStart() {
00257         return start;
00258     }
00259 
00260     public void setStart(Moment start) {
00261         this.start = start;
00262     }
00263 
00264     public String toString() {
00265         return "[" + start + " - " + end + "]";
00266     }
00267 
00268     public static IntervalTime randomIntervalTime() {
00269         return new IntervalTime(new Moment(random.nextInt(7),
00270                 random.nextInt(24), random.nextInt(60)),
00271             new Moment(random.nextInt(8), random.nextInt(25), random.nextInt(61)));
00272     }
00273 
00274     /* </Debug> */
00275 }
00276 
00277 
00278 class WorkTime {
00279     private List<IntervalTime> intervals;
00280 
00281     public WorkTime() {
00282         intervals = new ArrayList<IntervalTime>();
00283     }
00284 
00285     private boolean handleIntersection(ListIterator<IntervalTime> iter,
00286         IntervalTime intersected, IntervalTime interval) {
00287         if (interval.compareTo(intersected) < 0) {
00288             intersected.setStart(interval.getStart());
00289         }
00290 
00291         if (interval.getEnd().compareTo(intersected.getEnd()) > 0) {
00292             intersected.setEnd(interval.getEnd());
00293 
00294             List<IntervalTime> toDelete = new ArrayList<IntervalTime>();
00295 
00296             while (iter.hasNext()) {
00297                 IntervalTime next = iter.next();
00298 
00299                 if (intersected.contains(next)) {
00300                     toDelete.add(next);
00301                 } else if (intersected.intersect(next)) {
00302                     intersected.setEnd(next.getEnd());
00303                     toDelete.add(next);
00304                 } else {
00305                     break;
00306                 }
00307             }
00308 
00309             Iterator<IntervalTime> toDeleteIter = toDelete.iterator();
00310 
00311             while (toDeleteIter.hasNext()) {
00312                 IntervalTime toDeleteItem = toDeleteIter.next();
00313                 intervals.remove(toDeleteItem);
00314             }
00315         }
00316 
00317         return true;
00318     }
00319 
00320     private boolean addInterval(IntervalTime interval) {
00321         if (!interval.isValid()) {
00322             return false;
00323         }
00324 
00325         ListIterator<IntervalTime> iter = intervals.listIterator();
00326 
00327         while (iter.hasNext()) {
00328             IntervalTime inList = iter.next();
00329 
00330             if (inList.intersect(interval)) {
00331                 if (inList.contains(interval)) {
00332                     return true;
00333                 }
00334 
00335                 return handleIntersection(iter, inList, interval);
00336             }
00337 
00338             if (interval.compareTo(inList) < 0) {
00339                 iter.previous();
00340 
00341                 break;
00342             }
00343         }
00344 
00345         iter.add(interval);
00346 
00347         return true;
00348     }
00349 
00350     public boolean addInterval(Moment start, Moment end) {
00351         if (!start.isValid() || !end.isValid()) {
00352             return false;
00353         }
00354 
00355         if (start.compareTo(end) <= 0) {
00356             return addInterval(new IntervalTime(start, end));
00357         }
00358 
00359         addInterval(new IntervalTime(start, Moment.END_OF_WEEK));
00360         addInterval(new IntervalTime(Moment.START_OF_WEEK, end));
00361 
00362         return true;
00363     }
00364 
00365     public IntervalTime getCurrentWorkInterval() {
00366         Moment now = new Moment();
00367         Iterator<IntervalTime> iter = intervals.iterator();
00368 
00369         while (iter.hasNext()) {
00370             IntervalTime interval = iter.next();
00371 
00372             if (interval.getEnd().equals(now)) {
00373                 continue;
00374             }
00375 
00376             if (interval.contains(now)) {
00377                 return interval;
00378             }
00379 
00380             if (interval.getStart().compareTo(now) > 0) {
00381                 break;
00382             }
00383         }
00384 
00385         return null;
00386     }
00387 
00388     public IntervalTime getNextWorkInterval() {
00389         Moment now = new Moment();
00390         Iterator<IntervalTime> iter = intervals.iterator();
00391 
00392         while (iter.hasNext()) {
00393             IntervalTime interval = iter.next();
00394 
00395             if (interval.getStart().compareTo(now) >= 0) {
00396                 return interval;
00397             }
00398         }
00399 
00400         return intervals.get(0);
00401     }
00402 
00403     public int computeDuration(IntervalTime work) {
00404         Moment end = work.getEnd();
00405 
00406         if (!end.equals(Moment.END_OF_WEEK)) {
00407             return end.minutesFromNow();
00408         }
00409 
00410         if (work.getStart().equals(Moment.START_OF_WEEK)) {
00411             /* Infinite */
00412             return -1;
00413         }
00414 
00415         IntervalTime first = intervals.get(0);
00416 
00417         if (!first.getStart().equals(Moment.START_OF_WEEK)) {
00418             return end.minutesFromNow();
00419         }
00420 
00421         return first.getEnd().minutesFromNow() + Moment.MINUTES_IN_WEEK;
00422     }
00423 
00424     public boolean isEmpty() {
00425         return intervals.isEmpty();
00426     }
00427 
00428     /* <Debug> */
00429     public boolean isValid() {
00430         Iterator<IntervalTime> iter = intervals.iterator();
00431         IntervalTime previous = null;
00432         IntervalTime current = null;
00433 
00434         while (iter.hasNext()) {
00435             previous = current;
00436             current = iter.next();
00437 
00438             if (!current.isValid()) {
00439                 return false;
00440             }
00441 
00442             if (previous != null) {
00443                 if (previous.getEnd().compareTo(current.getStart()) >= 0) {
00444                     return false;
00445                 }
00446             }
00447         }
00448 
00449         return true;
00450     }
00451 
00452     public String toString() {
00453         if (intervals.isEmpty()) {
00454             return "()";
00455         }
00456 
00457         String res = "(" + intervals.get(0);
00458 
00459         Iterator<IntervalTime> iter = intervals.iterator();
00460         iter.next();
00461 
00462         while (iter.hasNext()) {
00463             IntervalTime current = iter.next();
00464             res += (", " + current);
00465         }
00466 
00467         return res + ")";
00468     }
00469 
00470     public void test() {
00471         IntervalTime interval = IntervalTime.randomIntervalTime();
00472         System.out.println("\nAjout de : " + interval);
00473         System.out.println("Reussi   : " + addInterval(interval));
00474         System.out.println("Resultat : " + this);
00475         System.out.println("isValid  : " + isValid());
00476     }
00477 
00478     /* </Debug> */
00479 }
00480 
00481 
00482 class XMLConfig extends BasicUnmarshaller implements ErrorHandler {
00483     private static final String CONFIG_PREFIX = ".." + File.separator +
00484         "config" + File.separator;
00485     private static String hostname = null;
00486     private WorkTime work;
00487     private Vector<String> url;
00488 
00489     /* Used when parsing */
00490     private boolean rightHost;
00491     private boolean rightConfig;
00492     private Stack<File> currentConfigFile;
00493     private Moment start;
00494     private Moment end;
00495     private boolean parsed;
00496     private Collection<String> parsedXML;
00497 
00498     public XMLConfig(WorkTime work, Vector<String> url) {
00499         this.work = work;
00500         this.url = url;
00501     }
00502 
00503     public static String getLocalHostName() {
00504         if (hostname == null) {
00505             try {
00506                 hostname = InetAddress.getLocalHost().getCanonicalHostName()
00507                                       .toLowerCase();
00508             } catch (UnknownHostException e) {
00509                 e.printStackTrace();
00510                 hostname = "localhost";
00511             }
00512         }
00513 
00514         return hostname;
00515     }
00516 
00517     public void error(SAXParseException e) throws SAXException {
00518         throw new SAXException(e);
00519     }
00520 
00521     public void fatalError(SAXParseException e) throws SAXException {
00522         throw new SAXException(e);
00523     }
00524 
00525     public void warning(SAXParseException e) throws SAXException {
00526         /* Ignore the warning */
00527     }
00528 
00529     public void startElement(String name, Attributes attributes)
00530         throws SAXException {
00531         if (parsed) {
00532             return;
00533         }
00534 
00535         if (rightConfig) {
00536             if (name.equals("start")) {
00537                 start = new Moment(attributes);
00538             } else if (name.equals("end")) {
00539                 end = new Moment(attributes);
00540                 work.addInterval(start, end);
00541             } else if (name.equals("registry")) {
00542                 url.add(attributes.getValue("url"));
00543             }
00544         }
00545 
00546         if (name.equals("loadconfig")) {
00547             String path = attributes.getValue("path")
00548                                     .replace('/', File.separatorChar);
00549 
00550             if (!new File(path).isAbsolute()) {
00551                 File current = currentConfigFile.peek();
00552                 path = new File(current.getParentFile(), path).getAbsolutePath();
00553             }
00554 
00555             parseConfigFile(path);
00556         } else if (name.equals("host")) {
00557             if (attributes.getValue("name").equalsIgnoreCase(getLocalHostName())) {
00558                 rightHost = true;
00559             }
00560         } else if (name.equals("default")) {
00561             rightConfig = true;
00562         } else if (name.equals("configForHost")) {
00563             if (rightHost) {
00564                 rightConfig = true;
00565             }
00566         }
00567     }
00568 
00569     public void endElement(String name) throws SAXException {
00570         if (parsed) {
00571             return;
00572         }
00573 
00574         if (name.equals("configForHost") || name.equals("default") ||
00575                 name.equals("p2pconfig")) {
00576             if (rightConfig) {
00577                 parsed = true;
00578                 rightConfig = false;
00579             }
00580         }
00581     }
00582 
00583     private static java.net.URL getXMLSchema() {
00584         java.net.URL url = null;
00585 
00586         try {
00587             url = (new java.io.File(CONFIG_PREFIX + "proactivep2p.xsd")).toURI().toURL();
00588         } catch (MalformedURLException e) {
00589             // TODO Auto-generated catch block
00590             e.printStackTrace();
00591         }
00592 
00593         return url;
00594     }
00595 
00596     private static String getDefaultConfig(boolean hostDependant) {
00597         String prefix = CONFIG_PREFIX + "proactivep2p.";
00598 
00599         if (hostDependant) {
00600             prefix += (getLocalHostName() + ".");
00601         }
00602 
00603         return prefix + "xml";
00604     }
00605 
00606     /*
00607      * true --> config file read
00608      * false --> file not found or something like that --> config not loaded
00609      * SAXException --> Schema not validated
00610      */
00611     private boolean parseConfigFile(String configFile)
00612         throws SAXException {
00613         if ((configFile == null) || parsedXML.contains(configFile)) {
00614             return false;
00615         }
00616 
00617         StreamReader stream;
00618 
00619         try {
00620             File file = new File(configFile);
00621             Reader reader = new FileReader(file);
00622             stream = new StreamReader(new InputSource(reader), this,
00623                     getXMLSchema(), this);
00624         } catch (IOException ioe) {
00625             return false;
00626         }
00627 
00628         currentConfigFile.push(new File(configFile));
00629         parsedXML.add(configFile);
00630 
00631         try {
00632             stream.read();
00633         } catch (IOException e) {
00634             throw new SAXException(e);
00635         } finally {
00636             currentConfigFile.pop();
00637         }
00638 
00639         return true;
00640     }
00641 
00642     public void parse() throws SAXException {
00643         currentConfigFile = new Stack<File>();
00644         rightHost = false;
00645         rightConfig = false;
00646         parsed = false;
00647         parsedXML = new HashSet<String>();
00648 
00649         if (parseConfigFile(getDefaultConfig(true)) ||
00650                 parseConfigFile(getDefaultConfig(false))) {
00651             /* Nothing */
00652         }
00653 
00654         currentConfigFile = null;
00655         parsedXML = null;
00656     }
00657 }
00658 
00659 
00660 public class Daemon {
00661     private static Logger logger = ProActiveLogger.getLogger(Loggers.P2P_DAEMON);
00662 
00663     /* Logging */
00664     private static final String LOG_DIR = ".." + File.separator + "logs" +
00665         File.separator;
00666     private static final String MAX_SIZE = "100KB";
00667     private static final String LOG_PATTERN = "%d %c %x %m\n\n";
00668     private static WriterAppender writerAppender;
00669 
00670     static {
00671         configureLogging();
00672     }
00673 
00674     /* Shared with the native daemon */
00675     private static final int DAEMON_PORT = 9015;
00676     private static final String LOG_HEADER = "[P2P] ";
00677     private static final String RESTART_CMD = "restart";
00678     private static final String STOP_CMD = "stop";
00679     private static final String KILL_CMD = "killdaemon";
00680     private static final String ALIVE_CMD = "alive";
00681     private static final String FLUSH_CMD = "flush";
00682     private WorkTime work;
00683     private Vector<String> url;
00684 
00685     private Daemon(boolean nextRun) {
00686         work = new WorkTime();
00687         url = new Vector<String>();
00688 
00689         try {
00690             new XMLConfig(work, url).parse();
00691         } catch (SAXException e) {
00692             log(e.getMessage(), true);
00693             System.exit(1);
00694         }
00695 
00696         try {
00697             startCommandListener();
00698         } catch (Exception e) {
00699             flush("Cannot create command listener");
00700             System.exit(1);
00701         }
00702 
00703         if (work.isEmpty()) {
00704             log("No work time scheduled", false);
00705 
00706             /* Wait for a command from p2pctl */
00707             try {
00708                 Thread.currentThread().join();
00709             } catch (InterruptedException ie) {
00710                 System.exit(3);
00711             }
00712         }
00713 
00714         IntervalTime current = work.getCurrentWorkInterval();
00715 
00716         if ((current == null) || nextRun) {
00717             IntervalTime next = work.getNextWorkInterval();
00718             int minutes;
00719 
00720             if (nextRun && (current == next)) {
00721                 log("No sleep moment to use", false);
00722                 minutes = 24 * 60; /* 2424 => sleep one day */
00723             } else {
00724                 minutes = next.getStart().minutesFromNow();
00725 
00726                 if (minutes < 0) {
00727                     minutes += Moment.MINUTES_IN_WEEK; /* Next week */
00728                 }
00729             }
00730 
00731             log("Waiting for " + minutes + " minutes before working", false);
00732             sleep(minutes);
00733             current = next;
00734         }
00735 
00736         int minutes = work.computeDuration(current);
00737 
00738         try {
00739             setDestructionTimeout(minutes);
00740         } catch (Exception e) {
00741             flush("Cannot set the destruction timeout");
00742             System.exit(1);
00743         }
00744 
00745         startWorking();
00746     }
00747 
00748     static void log(String msg, boolean isError) {
00749         msg = LOG_HEADER + msg;
00750 
00751         try {
00752             if (isError) {
00753                 logger.error(msg);
00754             } else {
00755                 logger.info(msg);
00756             }
00757         } catch (Exception e) {
00758             /* Log the logging exception ;-) */
00759             System.out.println(e.getMessage() + " when logging : " + msg);
00760         }
00761     }
00762 
00763     private static void configureLogging() {
00764         Appender appender;
00765 
00766         try {
00767             appender = new NTEventLogAppender("ProActiveP2P");
00768         } catch (java.lang.UnsatisfiedLinkError e) {
00769             String hostname = XMLConfig.getLocalHostName();
00770 
00771             Layout layout = new PatternLayout(LOG_PATTERN);
00772             String filename = LOG_DIR + hostname;
00773             RollingFileAppender rfa;
00774 
00775             try {
00776                 new File(LOG_DIR).mkdir();
00777                 rfa = new RollingFileAppender(layout, filename, true);
00778             } catch (IOException ioe) {
00779                 ioe.printStackTrace();
00780 
00781                 return;
00782             }
00783 
00784             rfa.setMaxBackupIndex(0);
00785             rfa.setMaxFileSize(MAX_SIZE);
00786             rfa.setImmediateFlush(false);
00787             writerAppender = rfa;
00788             appender = rfa;
00789         }
00790 
00791         Logger root = Logger.getRootLogger();
00792         root.addAppender(appender);
00793 
00794         /* First message :) */
00795         log("Starting P2P Daemon", false);
00796     }
00797 
00798     static void sleep(long minutes) {
00799         try {
00800             Thread.sleep(minutes * 60 * 1000);
00801         } catch (InterruptedException ie) {
00802             System.exit(3);
00803         }
00804     }
00805 
00806     private static void flush(String message) {
00807         if (writerAppender != null) {
00808             writerAppender.setImmediateFlush(true);
00809         }
00810 
00811         log(message, false);
00812 
00813         if (writerAppender != null) {
00814             writerAppender.setImmediateFlush(false);
00815         }
00816     }
00817 
00818     static String readCommand(BufferedReader reader) {
00819         char[] tab = new char[256];
00820         int offset = 0;
00821 
00822         do {
00823             try {
00824                 int nbRead = reader.read(tab, offset, tab.length - offset);
00825 
00826                 if (nbRead <= 0) {
00827                     break;
00828                 }
00829 
00830                 offset += nbRead;
00831             } catch (IOException ioe) {
00832                 break;
00833             }
00834 
00835             String line = new String(tab);
00836             String trimmed = line.trim();
00837 
00838             if (!trimmed.equals(line)) {
00839                 return trimmed;
00840             }
00841         } while (offset < 256);
00842 
00843         return null;
00844     }
00845 
00846     void handleCommand(Socket client, String command) {
00847         if (!KILL_CMD.equals(command) && !STOP_CMD.equals(command) &&
00848                 !RESTART_CMD.equals(command) && !ALIVE_CMD.equals(command) &&
00849                 !FLUSH_CMD.equals(command)) {
00850             return;
00851         }
00852 
00853         try {
00854             OutputStream out = client.getOutputStream();
00855             out.write("OK".getBytes("US-ASCII"));
00856             out.close();
00857         } catch (IOException e) {
00858             /* The client left, we won't process its request */
00859             return;
00860         }
00861 
00862         if (KILL_CMD.equals(command)) {
00863             flush(command);
00864             System.exit(220);
00865         }
00866 
00867         if (STOP_CMD.equals(command)) {
00868             flush(command);
00869             System.exit(2);
00870         }
00871 
00872         if (RESTART_CMD.equals(command)) {
00873             flush(command);
00874             System.exit(0);
00875         }
00876 
00877         if (FLUSH_CMD.equals(command)) {
00878             flush(command);
00879         }
00880     }
00881 
00882     private void startCommandListener() {
00883         new Thread(new Runnable() {
00884                 public void run() {
00885                     ServerSocket server;
00886 
00887                     try {
00888                         server = new ServerSocket(DAEMON_PORT);
00889                     } catch (IOException ioe) {
00890                         log(ioe.getMessage(), true);
00891                         System.exit(1);
00892 
00893                         return; /* To avoid a javac error */
00894                     }
00895 
00896                     for (;;) {
00897                         try {
00898                             Socket client = server.accept();
00899 
00900                             /*
00901                              * TODO: When the experimenting phase is done we should allow connections only from localhost
00902                              */
00903                             InputStream stream = client.getInputStream();
00904                             InputStreamReader ireader = new InputStreamReader(stream);
00905                             BufferedReader reader = new BufferedReader(ireader);
00906                             String line = readCommand(reader);
00907                             handleCommand(client, line);
00908 
00909                             stream.close();
00910                             client.close();
00911                         } catch (IOException ioe) {
00912                             ioe.printStackTrace();
00913                         }
00914                     }
00915                 }
00916             }).start();
00917     }
00918 
00919     private static void setDestructionTimeout(final int minutes) {
00920         if (minutes >= 0) {
00921             log("Killing the JVM in " + minutes + " minutes", false);
00922             new Thread(new Runnable() {
00923                     public void run() {
00924                         sleep(minutes);
00925                         System.exit(0);
00926                     }
00927                 }).start();
00928         } else {
00929             log("Never killing the JVM", false);
00930         }
00931     }
00932 
00933     private void startWorking() {
00934         log("Start to work", false);
00935 
00936         StartP2PService service = new StartP2PService(url);
00937 
00938         try {
00939             service.start();
00940         } catch (ProActiveException e) {
00941             logger.warn("Couldn't start the P2P Service", e);
00942         }
00943     }
00944 
00945     public static void main(String[] args) {
00946         try {
00947             boolean nextRun = false;
00948 
00949             for (int i = 0; i < args.length; i++)
00950                 if ("-n".equals(args[i])) {
00951                     nextRun = true;
00952                 }
00953 
00954             new Daemon(nextRun);
00955         } catch (Throwable t) {
00956             logger.error("Throwable:", t);
00957             System.exit(3);
00958         }
00959     }
00960 
00961     /* <Debug> */
00962     public void test() {
00963         for (int i = 0; i < 100; i++)
00964             work.test();
00965     }
00966 
00967     /* </Debug> */
00968 }

Generated on Mon Jan 22 15:16:11 2007 for ProActive by  doxygen 1.5.1