Package JACE.netsvcs.Naming

Source Code of JACE.netsvcs.Naming.NameAcceptor

/*************************************************
*
* = PACKAGE
*    netsvcs.Naming
*
* = FILENAME
*    NameAcceptor.java
*
*************************************************/
package JACE.netsvcs.Naming;

import java.io.*;
import java.net.*;
import java.util.*;
import JACE.OS.*;
import JACE.Misc.*;
import JACE.Connection.*;
import JACE.Reactor.*;
import JACE.ASX.TimeValue;
import JACE.netsvcs.Server;

/**
* Server for the naming service. 
* Listens on the specified port (command line option) and launches
* NameHandlers when connections are made. 
* <P>
* The hash table for the mapping and a timer queue are created here.
* Periodically, if it has been changed, the mapping is saved to a file.
* If the data file exists at load time, it is read from disk.  Currently,
* the service stores the entire mapping in one Hashtable (which is probably
* kept in memory at all times).
* <P>
* <B>Valid command line arguments:</B>
* <PRE>
*    -f (file name)    File name of the database
*                      (Default is namedata.dat)
*    -p (port number)  Port to listen on for clients
*    -d                Enable debugging
*    -t (time sec)     How often to save the database (default 60 sec)
*    -a (class name)   Specify ActivateStrategy
*                      (Default is multi-threaded)
* </PRE>
*
*@see NameHandler
*
*@author Everett Anderson
*
*/
public class NameAcceptor extends Server
{
  /**
   * Constructor
   */
  public NameAcceptor ()
  {
    // Set the name in case we are not using the service
    // configurator
    name ("Naming Service");

    // Create the hash table and timer queue
    this.mapping_ = new Hashtable ();
    this.tq_ = new TimerQueue (true);
  }

  /**
   * Simple main program.  See the class description for more
   * information about command line arguments.
   */
  public static void main (String [] args)
  {
    // Simple main program to get things rolling
    NameAcceptor na = new NameAcceptor();

    na.init(args);
  }

  /**
   * Check to see if the mapping has been modified since the last
   * save.
   */
  synchronized boolean modifiedMapping ()
  {
    return mappingWasModified_;
  }

  /**
   * Set the modified state of the mapping.
   */
  synchronized void modifiedMapping (boolean value)
  {
    mappingWasModified_ = value;
  }

  /**
   * Cancels the timer which was used to save the mapping, then delegates
   * to Server.fini ().
   *
   *@return -1 on failure, 0 on success
   */
  public int fini ()
  {
    if (!done () && tq_ != null)
      tq_.cancelTimer (this);

    return super.fini ();
  }

  /**
   * Read the data file (if it exists) and schedule a periodic timer
   * to save it at intervals.  At the end, this delegates to
   * Server.initialize () (which currently sets the default
   * activation scheme if it wasn't defined on the command line).
   *
   *@see Server#initialize
   *@return -1 on failure, 0 on success
   */
  protected int initialize ()
  {
    this.loadTable ();

    this.tq_.scheduleTimer (this,
          null,
          new TimeValue (this.updateInterval_),
          new TimeValue (this.updateInterval_));

    // Use whatever default ActivateStrategy is defined in the
    // Server class (unless specified in parseArgs)
    return super.initialize ();
  }

  /**
   * Create a new NameHandler instance.
   */
  protected SvcHandler makeSvcHandler ()
  {
    return new NameHandler (mapping_);
  }

  /**
   * Prints out the valid command line arguments.  See the class
   * description for more information.  Called by Server.init when
   * parseArgs returns -1.
   */
  protected void printUsage ()
  {
    ACE.ERROR ("Valid options:\n");
    ACE.ERROR ("-f <file name>    File name of the database");
    ACE.ERROR ("                  (Default is namedata.dat)");
    ACE.ERROR ("-p <port number>  Port to listen on for clients");
    ACE.ERROR ("-d                Enable debugging");
    ACE.ERROR ("-t <time sec>     How often to save the database");
    ACE.ERROR ("                  (Default is 60 seconds)");
    ACE.ERROR ("-a <class name>   Specify ActivateStrategy");
    ACE.ERROR ("                  (Default is multi-threaded");
  }

  /**
   * Parses the command line arguments.  See the class description
   * for more information.
   *
   *@param args command line arguments
   *@return -1 on failure, 0 on success
   */
  protected int parseArgs (String [] args)
  {
    int c = 0;
    String s;
    GetOpt opt = new GetOpt (args, "p:f:t:da:", true);

    try {

      while ((c = opt.next ()) != -1) {
  switch (c)
    {
    case 'f':
      this.filename_ = opt.optarg ();
      break;
    case 't':
      try {
        this.updateInterval_ = Integer.parseInt (opt.optarg ());
      } catch (NumberFormatException e) {
        ACE.ERROR ("Invalid interval specified: " + e.getMessage ());
        return -1;
      }
      break;
    case 'd':
      ACE.enableDebugging ();
      ACE.DEBUG ("Debugging is enabled");
      break;
    case 'p':
      if (!port (opt.optarg ()))
        return -1;
      break;
    case 'a':
      Object strategy = newStrategyInstance (opt.optarg (),
               "ActivateStrategy");
      if (strategy == null)
        return -1;
     
      activateStrategy ((ActivateStrategy) strategy);
      break
    default:
      ACE.ERROR ("Unknown argument: " + (char)c);
      return -1;
    }
      }
    } catch (ArrayIndexOutOfBoundsException e) {
      ACE.ERROR ("Option -" + (char)c + " requires an argument");
      return -1;
    }
   
    return 0;
  }

  /**
   * Loads the hash table into memory from the specified
   * file.  Uses ObjectInputStream.
   */
  protected void loadTable ()
  {
    File file = new File(this.filename_);
    FileInputStream fis;
    ObjectInputStream ois;

    Hashtable ht = null;

    try {

      if ((file.exists()) && (file.canRead())) {

  fis = new FileInputStream (file);

  ois = new ObjectInputStream(fis);

  ht = (Hashtable)ois.readObject();
      } else
  return;
    } catch (ClassNotFoundException e) {
      ACE.ERROR(e);
    } catch (StreamCorruptedException e) {
      ACE.ERROR(e);
    } catch (SecurityException e) {
      ACE.ERROR(e);
    } catch (IOException e) {
      ACE.ERROR(e);
    }

    if (ht != null)
      this.mapping_ = ht;

  }

  /**
   * Writes the table out to the specified file if it has been modified.
   */
  protected void saveTable ()
  {
    if (!modifiedMapping ())
      return;

    FileOutputStream fos;
    ObjectOutputStream oos;

    try {

      fos = new FileOutputStream(this.filename_);
      oos = new ObjectOutputStream(fos);

      synchronized (this.mapping_) {
  oos.writeObject(this.mapping_);

  modifiedMapping (false);
      }

      oos.flush();

      oos.close();

    } catch (OptionalDataException e) {
      ACE.ERROR(e);
    } catch (NotSerializableException e) {
      ACE.ERROR(e);
    } catch (IOException e) {
      ACE.ERROR(e);
    }
  }

  /**
   * Call back for the TimerQueue.  This calls the method to save the
   * hash table.  The default time out is 60 seconds.
   */
  public int handleTimeout (TimeValue tv, Object obj)
  {
    this.saveTable();

    return 0;
  }

  // Mapping data structure
  Hashtable mapping_ = null;

  // Default file name
  String filename_ = "namedata.dat";

  // How often to save the table (seconds)
  int updateInterval_ = 60;

  // Calls handleTimeout at updateInterval_ intervals
  TimerQueue tq_ = null;

  boolean mappingWasModified_ = false;
}
TOP

Related Classes of JACE.netsvcs.Naming.NameAcceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.