/*
  pgrep_s.c
  Jim Garlick

  This file is the slave portion of the pgrep program. When it first executes
  it sends a message back to the master saying that it's available for use. 
  The master then sends the data that will be searched through. Once complete, the
  slave will return the number of matches with a message saying that it's ready
  for another batch. The master is responsible for killing all of the slaves.

 Notes
  The architecture of the code allows the slave program to be recycled in that 
  new search strings can be specified with the buffers. I would like to add
  dynamic buffer sizes, but that'll have to wait for later.
*/

#include <stdio.h>
#include <ctype.h>
#include "pvm3.h"
#include "pgrep.h"

int main (int argc, char *argv[]) {

   /* Task info */
  int mytid, parent_id, bufid, msg, tid;

  /* Program Specific info */
  char buf[BUF_SIZE+1], searchString[STR_SIZE];
  int bufLength, searchStringLength, count;

    /* Get the task id of me and the parent process */
  mytid = pvm_mytid();
  parent_id = pvm_parent();

  /*
    The architecture is as follows: The parent will send signals to this slave.
    The signals will be "WORK_ON_THIS", "WAIT", and "DIE". If the message is 
    "WORK_ON_THIS", unpack the search string and buffer and search it. If the 
    message is "WAIT", send the availability signal back and wait for a signal. 
    If the message is "DIE", then quit PVM and exit.
  */
  while (1) {
      /* Intercept a message from the parent process */
    bufid = pvm_recv(parent_id, -1);
      /* Determine what that message is */
    pvm_bufinfo(bufid, 0, &msg, &tid);

    switch (msg) {
      /* If the master wants us to work... */
    case WORK_ON_THIS:
        /* Unpack search string and buffer */
      pvm_upkstr(searchString);
      pvm_upkstr(buf);

        /* Search for for the search string */
      count = 0;
      cryptocount(buf, searchString, &count);

        /* Pack up the number of matches and send the "DONE" message */
      pvm_initsend(PvmDataDefault);
      pvm_pkint(&count, 1, 1);
      pvm_send(parent_id, DONE);
      break;

      /* If the master wants us to wait... */
    case WAIT:
        /* Tell the parent we're available */
      pvm_initsend(PvmDataDefault);
      pvm_send(parent_id, AVAILABLE);
      break;

      /* If the master wants us dead... */
    case DIE:
        /* Die. */
      pvm_exit();
      exit();
      break;
    }
  }
}
