#!/usr/local/bin/tops -i -s /usr/local/tops/sys -u /opt/mytops/usr/
/* File tops_rtccon  February 2010

   Copyright (C) 2010-2011  Dale R. Williamson

   Control the jobs running real time collections from remote machines.
   The running jobs being controlled use script tops_rtc.

   This script operates as a toggle, and is run from the root menu:
      If any collection jobs are running, they are all closed and this
      program exits.

      If no jobs have been closed, this program keeps running and does
      the following (this is a work in progress; some items have not 
      been implemented):
         Close any earlier versions of this program running.
         Collect files from remotes that are missing.
         Start all the collection jobs to receive files from remotes.
         Install itself as a daemon running DSERVER forever.
         Monitor the health of the collection jobs.
         Receive notification that dial up connection is going down or
         has come up.
         Close all collection jobs before dial up goes down and restart
           them all when dial up connection comes up.

   To develop and test this file interactively, run:
      ready > "tops_rtccon" psource

//----------------------------------------------------------------------

   Updates:

   Fri May  6 14:23:26 PDT 2011.  If this program is started with com-
      mand line switch -start1 (the 1 is zero-based), it will simply 
      close collector 2 (the 2 is one-based) and start another collec-
      tor 2.  The same applies for -start2 and collector 3.

      This program and these switches are used by tops_rtc when it needs
      to restart itself.

//----------------------------------------------------------------------

   Notes:

      Watch out for zero-based numbering:
         Collector numbering is one-based, but some collector items use
         zero-based numbering.  Note zero-based numbering for collector
         items M, KD, and RUN.  Thus collector 2 (2 is one-based) uses 
         zero-based 1 in the following phrases:
            M = "RTC1_SERVER";
            KD = "tops_rtc -collect 1";
            RUN="tail -f $HOME/tops_rtc1.log"
            /usr/local/tops/usr/tops_rtc -collect 1

      How does N in rtc1() get the latest date?
         In words rtc1() (and rtc2, etc.), N is defined when the word
         runs to get the latest date.  But how is rtc1() run when it 
         is just an argument into rtc_close()?  

         Word rtc1() is run because it is used in the call statement
         without quotes, as in: 

            closed_1 = rtc_close(rtc1);

         When rtc1() runs it simply puts its name (rtc1) on the stack,
         just as running "rtc1" would, but also in running it executes
         the line

            N = (<< " Closing data collector 1, " date + >>);

         and so N is set to the latest date.

         If rtc1() were not run, another way to make the date of N cur-
         rent would be to make N a macro within the brace region of 
         rtc1() where items are set up as function rtc1() is created: 

            macro("' Closing data collector 1, ' date +", "N");

         which would run later when infix dot form rtc.N runs word yank
         in the rtc_close() phrase:

            nl(dot(rtc.N));

         This approach is used in rtc2() to verify that it works too.

      This is a work in progress.  Notes and ideas for things that
      have to be done:

         March 30, 2010:
         Running on a non-web machine (not plunger), the daemon should 
         connect to a web machine at the end of day and look for new 
         mdat.tgz, fetch it and untar it (or have the web-machine con-
         nect and send it).
*/

//----------------------------------------------------------------------

// Words. 

   catmsg(no);

   function (f) = rtc_close(rtc) { // close collector rtc.M
   /* Incoming rtc is the word that contains the library of the 
      collector to be closed. */
      { SEC = 5; 
        RESTART = no;
      }
      S = -1;
      IF(chars((PORT=msgPeek(rtc.M)))>0);
         msgGet(rtc.M); // remove message
         IF(port_listening(abs((P=@numerate(PORT)))));
            IF(P<0) // sign bit on means SSL
               ssl_connect(yes);
            THEN
            S = CLIENT(IPloop, abs(P));
            IF(S>0)
               nl(dot(rtc.N));
               remoterun("CLOSE", S); // close collector
               sclose(S);
               idle(SEC);
            ELSE RESTART=no; // must close log window too
               << " rtc_close: cannot connect to " . rtc . nl >>
            THEN
         THEN
      THEN
      R = grepr(pidtable, rtc.KW);
      IF(rows(R)>0);
         if(!RESTART) killjob(rtc.KW); // close log window
         idle(SEC);
         killjob(rtc.KD); // close collector if still running
         f = yes;
      ELSE
         f = no;
      THEN;
      RESTART = no; // always reset to no
   }

   function (w) = rtc1() { // collector 1
      {  ssl = "";

         W = defname;
         M = "RTC0_SERVER";
         KD = usrpath + "tops_rtc " + ssl + "-collect 0";
         KW = "data collector 1";
      } 
      N = (<< " Closing data collector 1, " date + >>);
      w = W;
   }

   function (w) = rtc2() { // collector 2
      {  ssl = "";

         W = defname;
         M = "RTC1_SERVER";
         KD = usrpath + "tops_rtc " + ssl + "-collect 1";
         KW = "data collector 2";
         macro("' Closing data collector 2, ' date +", "N");
      }
      w = W;
   }

   function (w) = rtc3() { // collector 3
      {  ssl = "-ssl ";
       
         W = defname;
         M = "RTC2_SERVER";
         KD = usrpath + "tops_rtc " + ssl + "-collect 2";
         KW = "data collector 3";
      } 
      N = (<< " Closing data collector 3, " date + >>);
      w = W;
   }

   function () = SHELL(script) { // run system shell script
      { TMP = ftemp(_bin.tmppath + runid + _SHELL_);
        deleteif(TMP);
      }
      save(script, TMP); // script to temp file
      chmod(TMP, 448);   // make file executable
      shell(TMP);        // run script
      deleteif(TMP);     // delete temp file
   }

   {"
      #!/bin/bash
      # File xterm_rtc1
      # Start data collector 1
      # February 2010

      DAT="plunger: data collector 1"
      WIN="-bg black -fg white -cr Salmon3 -fn 7x14 -sb -sl 4096"
      GEO="100x7+0+0"

      # See /etc/sysconfig/network-scripts for example shell scripts.

      if [ "$HOSTNAME" = "plunger" ]; then
         RUN="tail -f $HOME/COLLECT.LOG"
         /usr/local/tops/usr/topse

      else
         RUN="tail -f $HOME/tops_rtc0.log"
         KD 
      fi
      sleep 3

      /usr/X11R6/bin/rxvt $WIN -geometry $GEO -title "$DAT" -e $RUN &
   "} 
   << chop noblanklines "KD" "rtc1" "KD" yank strp "xterm_rtc1" book >>

   {"
      #!/bin/bash
      # File xterm_rtc2
      # Start data collector 2
      # February 2010

      DAT="rilefile.com: data collector 2"
      WIN="-bg PaleTurquoise4 -fg Black -cr FireBrick4 -fn 7x14 \
         -sb -sl 4096"
      GEO="100x7+0+133"
      RUN="tail -f $HOME/tops_rtc1.log"

      KD
      sleep 3

      /usr/X11R6/bin/rxvt $WIN -geometry $GEO -title "$DAT" -e $RUN &
   "} 
   << chop noblanklines "KD" "rtc2" "KD" yank strp "xterm_rtc2" book >>

   {"
      #!/bin/bash
      # File xterm_rtc3
      # Start data collector 3
      # February 2010

      DAT="fortycoupe.com: data collector 3"
      WIN="-bg Aquamarine4 -fg Black -cr FireBrick4 -fn 7x14 \
         -sb -sl 4096"
      GEO="100x7+0+266"
      RUN="tail -f $HOME/tops_rtc2.log"

      KD
      sleep 3

      /usr/X11R6/bin/rxvt $WIN -geometry $GEO -title "$DAT" -e $RUN &
   "}
   << chop noblanklines "KD" "rtc3" "KD" yank strp "xterm_rtc3" book >>

//----------------------------------------------------------------------

   IF(!keys?) // not running interactively?

      LOG_RTCCON = catpath(env("HOME"), "tops_rtccon.log");
      set_sysout(LOG_RTCCON);

   // Write the first lines in LOG_RTCCON file:
      nl(dot(cats("-", 72), nl));
      nl(dot(<< "PID " getpid intstr + spaced date + >>));

      NIST_DELTA();

      IF(chars(argv("-start1"))) // start1 is zero-based
     // If here, tops_rtc collector 2 needs to be restarted.
         rtc_close.RESTART = yes; // won't close the tail -f window
         rtc_close(rtc2);
         nl(dot(<< " Starting data collector 2 " date + >>));
         SHELL(rtc2.KD);
         nl(dot(<< " This program is closing " date + >>));
         exit();
      THEN;

      IF(chars(argv("-start2"))) 
     // If here, tops_rtc collector 3 needs to be restarted.
         rtc_close.RESTART = yes; // won't close the tail -f window
         rtc_close(rtc3);
         nl(dot(<< " Starting data collector 3 " date + >>));
         SHELL(rtc3.KD);
         nl(dot(<< " This program is closing " date + >>));
         exit();
      THEN;

   THEN

/*
   Here, if there is already a job like this running, kill it and its 
   window.

   Then open a window where the new log file will be seen.  Write a
   script like xterm_rtc3 above.

*/
   closed_3 = rtc_close(rtc3);

   closed_2 = rtc_close(rtc2);

   IF(host!="plunger")
      closed_1 = rtc_close(rtc1);
   ELSE // never close rtc on plunger
      R = rows(grepr(pidtable, "data collector 1"))==0; 
      IF(R)
         nl(dot(<< " Plunger data collector 1 is closed " 
            date + >>));
      ELSE
         nl(dot(<< " Plunger data collector 1 not closed " 
            date + >>));
      THEN
      closed_1 = no; // fake
   THEN

//----------------------------------------------------------------------

// If no jobs were closed, then this is a run to start all the jobs.
   START = (closed_1==no && closed_2==no && closed_3==no);

   IF(START) 

/*
      Here, check for updates from the three machines.  Read tops_rtc
      but stop before it can connect (as it does for keys? = yes).
      Connect to a machine, set DIR for it and fetch missing files.

      After have missing files, continue below to set up the collectors.
*/
      IF(host=="plunger") // start plunger if plunger is closed
         R = rows(grepr(pidtable, "data collector 1"))==0; 
         IF(R) 
            nl(dot(<< " Starting plunger data collector 1 " date + >>));
            SHELL(xterm_rtc1);
         ELSE
            nl(dot(<< " Plunger data collector 1 is running " 
               date + >>));
         THEN
      ELSE 
         nl(dot(<< " Starting data collector 1 " date + >>));
         SHELL(xterm_rtc1);
      THEN

      nl(dot(<< " Starting data collector 2 " date + >>));
      SHELL(xterm_rtc2);

      nl(dot(<< " Starting data collector 3 " date + >>));
      SHELL(xterm_rtc3);

/* 
   Start a SERVER that allows login, for maintenance and debugging,
   to this running daemon.
   
   This job should have no clients at this point.
*/

   ELSE
/*
      Jobs have been stopped.  Now, close the window opened above
      and exit this program.
*/
   THEN

   IF(!keys?) 
      nl(dot(<< " This program is closing " date + >>));
      exit();
   THEN;



