示例#1
0
 /**
  * Performs general periodic maintenance. This routine handles alle open pages/main and
  * pages/mirror file service requests. These requests are obtained from the netfiles builder. For
  * each file that should be serviced, the filechange method is called. This routine handles a
  * maximum of 10 page/main, and 50 page/mirror service calls each time it is called. The first
  * time this method is call, nothing happens (?)
  *
  * @return <code>true</code> if maintenance was performed, <code>false</code> otherwise
  */
 public boolean probeCall() {
   if (first) {
     // skip first time this method is called
     first = false;
   } else {
     // handle up to 10 pages/main fileservice requests
     try {
       Netfiles bul = (Netfiles) Vwms.getMMBase().getMMObject("netfiles");
       // Enumeration e=bul.search("WHERE service='pages' AND subservice='main' AND
       // status="+Netfiles.STATUS_REQUEST+" ORDER BY number DESC");
       Enumeration e =
           bul.search("service=='pages'+subservice=='main'+status=" + Netfiles.STATUS_REQUEST);
       int i = 0;
       while (e.hasMoreElements() && i < 10) {
         MMObjectNode node = (MMObjectNode) e.nextElement();
         fileChange("" + node.getIntValue("number"), "c");
         i++;
       }
     } catch (Exception e) {
       log.error(Logging.stackTrace(e));
     }
     // handle up to 50 pages/mirror fileservice requests
     try {
       Netfiles bul = (Netfiles) Vwms.getMMBase().getMMObject("netfiles");
       Enumeration e =
           bul.search("service=='pages'+subservice=='mirror'+status=" + Netfiles.STATUS_REQUEST);
       // Enumeration e=bul.search("WHERE service='pages' AND subservice='mirror' AND
       // status="+Netfiles.STATUS_REQUEST+" ORDER BY number DESC");
       int i = 0;
       while (e.hasMoreElements() && i < 50) {
         MMObjectNode node = (MMObjectNode) e.nextElement();
         fileChange("" + node.getIntValue("number"), "c");
         i++;
       }
     } catch (Exception e) {
       log.error(Logging.stackTrace(e));
     }
   }
   return true;
 }
示例#2
0
/**
 * A VWM that manages the files by scheduling them to be send to one or more mirror sites. Requests
 * for scheduling is done in the netfile builder. This VWM handles those netfile requests whose
 * service is 'pages'. Available subservices are 'main' and 'mirror'. Requests for file copy are
 * checked periodically. This results in one or more requests for a 'mirror' service, which then
 * result in a file copy request, which is handled in a separate thread. This VWM also has methods
 * for recalculating pages and handling page changes (which in turn result in a request for file
 * copy.) Entry point for these requests are the FileChange methods from the {@link
 * VwmServiceInterface}.
 *
 * @author Daniel Ockeloen
 * @author Pierre van Rooden (javadocs)
 * @version $Id$
 */
public class PageMaster extends Vwm implements MMBaseObserver, VwmServiceInterface {

  private static final Logger log = Logging.getLoggerInstance(PageMaster.class);

  // field used to skip first probeCall (why???)
  boolean first = true;

  Object syncobj = new Object(); // used in commented code

  /** Queue containing the file-copy tasks that need to be performed by {@link #filecopier} */
  Queue files2copy = new Queue(128);
  /** Thread that handles the actual file transfers. */
  FileCopier filecopier = new FileCopier(files2copy);
  /** Cache for mirror servers */
  Vector mirrornodes;

  // Hashtable properties; (unused)

  /** Constructor for the PageMaster VWM. */
  public PageMaster() {
    log.debug("ready for action");
  }

  /**
   * Performs general periodic maintenance. This routine handles alle open pages/main and
   * pages/mirror file service requests. These requests are obtained from the netfiles builder. For
   * each file that should be serviced, the filechange method is called. This routine handles a
   * maximum of 10 page/main, and 50 page/mirror service calls each time it is called. The first
   * time this method is call, nothing happens (?)
   *
   * @return <code>true</code> if maintenance was performed, <code>false</code> otherwise
   */
  public boolean probeCall() {
    if (first) {
      // skip first time this method is called
      first = false;
    } else {
      // handle up to 10 pages/main fileservice requests
      try {
        Netfiles bul = (Netfiles) Vwms.getMMBase().getMMObject("netfiles");
        // Enumeration e=bul.search("WHERE service='pages' AND subservice='main' AND
        // status="+Netfiles.STATUS_REQUEST+" ORDER BY number DESC");
        Enumeration e =
            bul.search("service=='pages'+subservice=='main'+status=" + Netfiles.STATUS_REQUEST);
        int i = 0;
        while (e.hasMoreElements() && i < 10) {
          MMObjectNode node = (MMObjectNode) e.nextElement();
          fileChange("" + node.getIntValue("number"), "c");
          i++;
        }
      } catch (Exception e) {
        log.error(Logging.stackTrace(e));
      }
      // handle up to 50 pages/mirror fileservice requests
      try {
        Netfiles bul = (Netfiles) Vwms.getMMBase().getMMObject("netfiles");
        Enumeration e =
            bul.search("service=='pages'+subservice=='mirror'+status=" + Netfiles.STATUS_REQUEST);
        // Enumeration e=bul.search("WHERE service='pages' AND subservice='mirror' AND
        // status="+Netfiles.STATUS_REQUEST+" ORDER BY number DESC");
        int i = 0;
        while (e.hasMoreElements() && i < 50) {
          MMObjectNode node = (MMObjectNode) e.nextElement();
          fileChange("" + node.getIntValue("number"), "c");
          i++;
        }
      } catch (Exception e) {
        log.error(Logging.stackTrace(e));
      }
    }
    return true;
  }

  /**
   * Called when a remote node is changed.
   *
   * @param machine Name of the machine that changed the node.
   * @param number Number of the changed node as a <code>String</code>
   * @param builder type of the changed node
   * @param ctype command type, 'c'=changed, 'd'=deleted', 'r'=relations changed, 'n'=new
   * @return <code>true</code>
   */
  public boolean nodeRemoteChanged(String machine, String number, String builder, String ctype) {
    return nodeChanged(machine, number, builder, ctype);
  }

  /**
   * Called when a local node is changed.
   *
   * @param machine Name of the machine that changed the node.
   * @param number Number of the changed node as a <code>String</code>
   * @param builder type of the changed node
   * @param ctype command type, 'c'=changed, 'd'=deleted', 'r'=relations changed, 'n'=new
   * @return <code>true</code>
   */
  public boolean nodeLocalChanged(String machine, String number, String builder, String ctype) {
    return nodeChanged(machine, number, builder, ctype);
  }

  /**
   * Called when a local or remote node is changed. Does not take any action.
   *
   * @param machine Name of the machine that changed the node.
   * @param number Number of the changed node as a <code>String</code>
   * @param builder type of the changed node
   * @param ctype command type, 'c'=changed, 'd'=deleted', 'r'=relations changed, 'n'=new
   * @return <code>true</code>
   */
  public boolean nodeChanged(String machine, String number, String builder, String ctype) {
    // log.debug("sees that : "+number+" has changed type="+ctype);
    return true;
  }

  /**
   * Schedules a service-request on a file. Only "pages/main" services are handled. The
   * service-request is later handled through the {@link #probeCall} method.
   *
   * @param service the service to be performed
   * @param subservice the subservice to be performed
   * @param filename the filename to service
   * @return <code>true</code> if maintenance was performed, <code>false</code> otherwise
   */
  public boolean fileChange(String service, String subservice, String filename) {
    log.debug("frontend change -> " + filename);
    log.service("s=" + service + " sub=" + subservice + "file=" + filename);
    // jump to correct subhandles based on the subservice
    if (subservice.equals("main")) {
      handleMainCheck(service, subservice, filename);
    }
    return true;
  }

  /**
   * Handles a service-request on a file, registered in the netfiles builder. Depending on the
   * subservice requested, this routine calls {@link #handleMirror} or {@link #handleMain}.
   *
   * @param number Number of the node in the netfiles buidler than contain service request
   *     information.
   * @param ctype the type of change on that node ("c" : node was changed)
   * @return <code>true</code>
   */
  public boolean fileChange(String number, String ctype) {
    // log.debug("fileChange="+number+" "+ctype);
    // first get the change node so we can see what is the matter with it.
    Netfiles bul = (Netfiles) Vwms.getMMBase().getMMObject("netfiles");
    MMObjectNode filenode = bul.getNode(number);
    if (filenode != null) {
      // obtain all the basic info on the file.
      String service = filenode.getStringValue("service");
      String subservice = filenode.getStringValue("subservice");
      int status = filenode.getIntValue("status");

      // jump to correct subhandles based on the subservice
      if (subservice.equals("main")) {
        return handleMain(filenode, status, ctype);
      } else if (subservice.equals("mirror")) {
        return handleMirror(filenode, status, ctype);
      }
    }
    return true;
  }

  /**
   * Handles a pages/mirror service request. Places a page in the file2copy queue, so it will be
   * sent to a mirror site by the FileCopier.
   *
   * @param filenode the filenet node that contains the service request
   * @param status the current status of the node
   * @param ctype the type of change on that node ("c" : node was changed)
   * @return <code>true</code>
   */
  public boolean handleMirror(MMObjectNode filenode, int status, String ctype) {
    switch (status) {
      case Netfiles.STATUS_REQUEST: // Request
        // register the node as being On Its Way
        filenode.setValue("status", Netfiles.STATUS_ON_ITS_WAY);
        filenode.commit();
        String filename = filenode.getStringValue("filename");
        String dstserver = filenode.getStringValue("mmserver");
        // recover the correct source/dest properties for this mirror
        //
        // why does it say "demoserver" ??
        //
        String sshpath = getProperty("demoserver", "sshpath");
        log.debug("sshpath=" + sshpath);
        String srcpath = getProperty("demoserver", "path");
        log.debug("srcpath=" + srcpath);
        String dstuser = getProperty(dstserver, "user");
        log.debug("dstuser="******"host");
        log.debug("dsthost=" + dsthost);
        String dstpath = getProperty(dstserver, "path");
        log.debug("dstpath=" + dstpath);

        /* this code can be dropped as it is handled in FileCopier

                SCPcopy scpcopy=new SCPcopy(sshpath,dstuser,dsthost,dstpath);

                synchronized(syncobj) {
                    scpcopy.copy(srcpath,filename);
                }
        */
        // create a new file2copy object and add it to the queue,
        // so the FileCopier thread will handle it.
        files2copy.append(new aFile2Copy(dstuser, dsthost, dstpath, srcpath, filename, sshpath));

        // register the node as being Done
        filenode.setValue("status", Netfiles.STATUS_DONE);
        filenode.commit();
        break;
      case Netfiles.STATUS_ON_ITS_WAY: // On its way
        break;
      case Netfiles.STATUS_DONE: // Done
        break;
    }
    return true;
  }

  /**
   * Handles a pages/main service request. The events handled are:<br>
   * - requests for handling: schedules requests to mirror this page using {@link #doMainRequest}
   * <br>
   * - changed: page is scheduled to be recalculated<br>
   * - recaculate" page is recaclcutated and scheduled to be handled<br>
   *
   * @param filenode the netfiles node that contains the service request
   * @param status the current status of the node
   * @param ctype the type of change on that node ("c" : node was changed)
   * @return <code>true</code>
   */
  public boolean handleMain(MMObjectNode filenode, int status, String ctype) {
    switch (status) {
      case Netfiles.STATUS_REQUEST: // Request
        // register the node as being On Its Way
        filenode.setValue("status", Netfiles.STATUS_ON_ITS_WAY);
        filenode.commit();
        // do stuff
        doMainRequest(filenode);
        // register the node as being Done
        filenode.setValue("status", Netfiles.STATUS_DONE);
        filenode.commit();
        break;
      case Netfiles.STATUS_ON_ITS_WAY: // On Its Way
        break;
      case Netfiles.STATUS_DONE: // Done
        break;
      case Netfiles.STATUS_CHANGED: // Dirty (?)
        filenode.setValue("status", Netfiles.STATUS_CALC_PAGE);
        filenode.commit();
        break;
      case Netfiles.STATUS_CALC_PAGE: // Recalculate Page
        String filename = filenode.getStringValue("filename");
        calcPage(filename);
        filenode.setValue("status", Netfiles.STATUS_REQUEST);
        filenode.commit();
        break;
    }
    return true;
  }

  /**
   * Handles a main subservice on a page. The page is scheduled to be sent to all appropriate
   * mirrorsites for this service, by setting the request status in the associated mirror nodes. If
   * no mirror nodes are associated with this page, nothing happens.
   *
   * @param filenode the netfiles node with the original (main) request
   */
  public boolean doMainRequest(MMObjectNode filenode) {
    // so this file has changed probably, check if the file is ready on
    // disk and set the mirrors to request.
    String filename = filenode.getStringValue("filename");

    // find and change all the mirror nodes so they get resend
    Netfiles bul = (Netfiles) Vwms.getMMBase().getMMObject("netfiles");
    Enumeration e =
        bul.search("WHERE filename='" + filename + "' AND service='pages' AND subservice='mirror'");
    while (e.hasMoreElements()) {
      MMObjectNode mirrornode = (MMObjectNode) e.nextElement();
      mirrornode.setValue("status", Netfiles.STATUS_REQUEST);
      mirrornode.commit();
    }
    return true;
  }

  /**
   * Schedules a netfile object to be send to its mirror sites. The routine searches the appropriate
   * netfile node, and sets its status to 'request'. If a node does not exits, a new node is
   * created. In the latter case, the system also creates mirrornodes for each mirrorsite associated
   * with this service.
   *
   * @param service the service to be performed
   * @param subservice the subservice to be performed
   * @param filename the filename to service
   */
  public void handleMainCheck(String service, String subservice, String filename) {
    log.debug("Reached handleMainCheck");
    Netfiles bul = (Netfiles) Vwms.getMMBase().getMMObject("netfiles");
    Enumeration e =
        bul.search(
            "WHERE filename='"
                + filename
                + "' AND service='"
                + service
                + "' AND subservice='"
                + subservice
                + "'");
    if (e.hasMoreElements()) {
      MMObjectNode mainnode = (MMObjectNode) e.nextElement();
      mainnode.setValue("status", Netfiles.STATUS_REQUEST);
      mainnode.commit();
    } else {
      MMObjectNode mainnode = bul.getNewNode("system");
      mainnode.setValue("filename", filename);
      mainnode.setValue("mmserver", Vwms.getMMBase().getMachineName());
      mainnode.setValue("service", service);
      mainnode.setValue("subservice", subservice);
      mainnode.setValue("status", Netfiles.STATUS_REQUEST);
      mainnode.setValue("filesize", -1);
      bul.insert("system", mainnode);

      Enumeration f = getMirrorNodes(service).elements();
      while (f.hasMoreElements()) {
        MMObjectNode n2 = (MMObjectNode) f.nextElement();
        // hack hack also have to create mirror nodes !
        mainnode = bul.getNewNode("system");
        mainnode.setValue("filename", filename);
        mainnode.setValue("mmserver", n2.getStringValue("name"));
        mainnode.setValue("service", service);
        mainnode.setValue("subservice", "mirror");
        mainnode.setValue("status", Netfiles.STATUS_DONE);
        mainnode.setValue("filesize", -1);
        bul.insert("system", mainnode);
      }
    }
  }

  /**
   * Retrieves a named property of a server.
   *
   * @param machine name of the server
   * @param key name of the property to retrieve
   * @return the property value
   */
  public String getProperty(String machine, String key) {
    MMServers mmservers = (MMServers) Vwms.getMMBase().getMMObject("mmservers");
    return mmservers.getMMServerProperty(machine, key);
  }

  /**
   * Recalculate a page. Invokes the SCAN parser (which will re-cache the page through the scancache
   * module) Only works for SCAN.
   *
   * @param url of the page to cache
   */
  public void calcPage(String url) {
    scanparser m = (scanparser) Vwms.getMMBase().getModule("SCANPARSER");
    url = url.substring(0, url.length() - 5);
    url = url.replace(':', '?');
    log.debug("getPage=" + url);
    if (m != null) {
      scanpage sp = new scanpage();
      m.calcPage(url, sp, 0);
    }
  }

  /**
   * Retrieves a list of Mirror Servers. This is done by obtaining a fileserver node and retrieving
   * associated mmserver nodes. This method should be renamed and moved to the netfilesrv builder.
   *
   * @param service preseumably the service to query for. Unused.
   * @return a <code>Vector</code> containing mmserver nodes that act as mirror server for this
   *     service
   */
  public Vector getMirrorNodes(String service) {
    if (mirrornodes != null) return mirrornodes;
    NetFileSrv bul = (NetFileSrv) Vwms.getMMBase().getMMObject("netfilesrv");
    if (bul != null) {
      Enumeration e = bul.search("service=='pages'+subservice=='mirror'");
      if (e.hasMoreElements()) {
        MMObjectNode n1 = (MMObjectNode) e.nextElement();
        mirrornodes = n1.getRelatedNodes("mmservers");
        if (mirrornodes != null) return mirrornodes;
      }
    }
    mirrornodes = new Vector();
    return mirrornodes;
  }
}