/*
 *========================================================================
 * $Id: pids.c 96 2006-07-20 17:56:16Z rgb $
 *
 * See copyright in copyright.h and the accompanying file COPYING
 *========================================================================
 */

#include <wulfware/libwulf.h>

void init_pids(Host *hostptr)
{

 /* Generic loop indices, and node limit */
 int i,numnodes;
 unsigned long seconds,useconds;

 xmlXPathContextPtr xp_hostdoc;
 xmlNodePtr cur = NULL;
 /* xml (path) objects) */
 xmlXPathObjectPtr xp_op = NULL;

 /* To facilitate addition of hosts */
 Pid newpid;

 /* To hold the pid attribute */
 char *pid_string;

 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: Starting init_pids().\n");
   
 }

 /* 
  * pids - tv_sec and tv_usec timestamps.
  */
 /* <pids tv_sec=?> */
 if(xtract_attribute(LONG,&seconds,value_xpath[PIDS],
                      "tv_sec",hostptr->xp_doc) > 1){
    fprintf(OUTFP,"update_values() Warning: %s not unique content tag.\n",
          value_xpath[PIDS]);
 }
 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: seconds = %d\n",seconds);
 }
 hostptr->val.pids_tv_sec = seconds;

 /* <pids tv_usec=?> */
 if(xtract_attribute(LONG,&useconds,value_xpath[PIDS],
                     "tv_usec",hostptr->xp_doc) > 1){
  fprintf(OUTFP,"update_values() Warning: %s not unique content tag.\n",
        value_xpath[PIDS]);
 }
 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: useconds = %d\n",useconds);
 }
 hostptr->val.pids_tv_usec = useconds;
 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: pids_tv_sec = %ul pids_tv_usec = %ul\n",hostptr->val.pids_tv_sec,hostptr->val.pids_tv_usec);
 }

 /*
  * Process the <pid> tag.
  */
 xp_hostdoc = hostptr->xp_doc;
 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: xp_hostdoc (ContextPtr) = %x\n",xp_hostdoc);
   fprintf(OUTFP,"D_VALUES: Now to eval all paths to /pids/pid.\n");
   
 }
 xp_op = xmlXPathEval((const xmlChar *)"/xmlsysd/pids/pid",xp_hostdoc);

 /* Did we get an xpath object at all for this path? */
 if( xp_op == NULL ) {
   fprintf(OUTFP,"xpath cannot parse xp_hostdoc.\n");
   
   return;
 }

 /* If we did, is it a nodeset? */
 if( xp_op->type != XPATH_NODESET ){
   fprintf(OUTFP,"No running pid nodes found by xpath on %s.\n",hostptr->hostname);
   
   return;
 }

 /*
  * We have to start with an empty pidlist
  */
 delete_list(hostptr->pidlist);

 /*
  * xp_op now contains an xpath object pointer to the /pids/pid
  * list in no particular order.
  *
  * Time to walk the dog-ument and pull out the hosts.
  * This loop sets cur to point to each <pids><pid> in turn,
  * and puts the results into a linked list that can be used
  * to make the displays in display_values.
  */
 numnodes = xp_op->nodesetval->nodeNr;
 for(i = 0 ; i < numnodes; i++){
   /*
    * START by allocating room for the next pid and adding it to
    * the linked pidlist.
    */
   cur = xp_op->nodesetval->nodeTab[i];
   pid_string = (char *)xmlGetProp(cur,(xmlChar*)"pid");
   /*
    * Start with newpid a blank slate so any missing tags/fields
    * get a default value of NULL.
    */
   bzero(&newpid,sizeof(newpid));
   newpid.pid = atoi(pid_string);
   free(pid_string);
   if((verbose == D_ALL) || (verbose == D_VALUES)){
     fprintf(OUTFP,"D_VALUES: pid = %d\n",newpid.pid);
     
   }

   cur = xp_op->nodesetval->nodeTab[i]->xmlChildrenNode;
   /*
   if((verbose == D_ALL) || (verbose == D_VALUES)){
     fprintf(OUTFP,"D_VALUES: Ready to walk document from point = %x\n",cur);
     
   }
   */
   while (cur != NULL) {
     if((verbose == D_ALL) || (verbose == D_VALUES)){
       fprintf(OUTFP,"D_VALUES: tag name is %s\n",cur->name);
       
     }

     /*
      * Extract the "cmdline" tag contents.  This WILL be missing on older
      * xmlsysd's, and we don't want to barf, so we null it above first so bad
      * things don't happen if it is missing.  We really should null the whole
      * struct, of course.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "cmdline") == 0) {
       snprintf(newpid.cmdline,K,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: cmdline = %s\n",newpid.cmdline);
       }
     }

     /*
      * Extract the "taskname" tag contents.
      */
     bzero(newpid.taskname,128);
     if( xmlStrcmp(cur->name, (const xmlChar *) "taskname") == 0) {
       snprintf(newpid.taskname,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: taskname = %s\n",newpid.taskname);
       }
     }

     /*
      * Extract the "state" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "state") == 0) {
       snprintf(newpid.state,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: state = %s\n",newpid.state);
	 
       }
     }

     /*
      * Extract the "user" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "user") == 0) {
       snprintf(newpid.user,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: user = %s\n",newpid.user);
	 
       }
     }


     /*
      * Extract the "uid" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "uid") == 0) {
       newpid.uid = atoi((char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: uid = %d\n",newpid.uid);
	 
       }
     }

     /*
      * Extract the "time" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "time") == 0) {
       snprintf(newpid.time,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: time = %s\n",newpid.time);
	 
       }
     }

     /*
      * Extract the "nice" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "nice") == 0) {
       newpid.nice = atoi((char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: nice = %d\n",newpid.nice);
	 
       }
     }

     /*
      * Extract the "vsize" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "vsize") == 0) {
       snprintf(newpid.vsize,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: vsize = %s\n",newpid.vsize);
	 
       }
     }

     /*
      * Extract the "rss" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "rss") == 0) {
       snprintf(newpid.rss,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: rss = %s\n",newpid.rss);
	 
       }
     }

     cur = cur->next;

   }

   if((verbose == D_ALL) || (verbose == D_VALUES)){
     fprintf(OUTFP,"D_VALUES: Adding task %s, pid = %d to pidlist\n",newpid.taskname,newpid.pid);
     
   }
   add_list(hostptr->pidlist,&newpid,sizeof(Pid));

   if((verbose == D_ALL) || (verbose == D_VALUES)){
     fprintf(OUTFP,"D_VALUES: Done!  On to the next task...\n");
     
   }
 }

}

void update_pids(Host *hostptr)
{

 /* Generic loop indices, and node limit */
 int i,numnodes;
 long seconds,useconds;

 xmlXPathContextPtr xp_hostdoc;
 xmlNodePtr cur = NULL;
 /* xml (path) objects) */
 xmlXPathObjectPtr xp_op = NULL;

 /* To facilitate addition of hosts */
 Pid newpid;

 /* To hold the pid attribute */
 char *pid_string;

 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: Starting update_pids().\n");
   
 }

 /* 
  * cpuinfo - tv_sec and tv_usec timestamps.
  */
 /* <pids tv_sec=?> */
 if(xtract_attribute(LONG,&seconds,value_xpath[PIDS],
                      "tv_sec",hostptr->xp_doc) > 1){
    fprintf(OUTFP,"update_values() Warning: %s not unique content tag.\n",
          value_xpath[PIDS]);
 }
 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: seconds = %d\n",seconds);
 }
 hostptr->val.pids_tv_sec = seconds;

 /* <pids tv_usec=?> */
 if(xtract_attribute(LONG,&useconds,value_xpath[PIDS],
                     "tv_usec",hostptr->xp_doc) > 1){
  fprintf(OUTFP,"update_values() Warning: %s not unique content tag.\n",
        value_xpath[PIDS]);
 }
 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: useconds = %d\n",useconds);
 }
 hostptr->val.pids_tv_usec = useconds;
 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: pids_tv_sec = %ul pids_tv_usec = %ul\n",hostptr->val.pids_tv_sec,hostptr->val.pids_tv_usec);
 }

 /*
  * Process the <pid> tag.
  */
 xp_hostdoc = hostptr->xp_doc;
 if((verbose == D_ALL) || (verbose == D_VALUES)){
   fprintf(OUTFP,"D_VALUES: xp_hostdoc (ContextPtr) = %x\n",xp_hostdoc);
   fprintf(OUTFP,"D_VALUES: Now to eval all paths to /pids/pid.\n");
   
 }
 xp_op = xmlXPathEval((const xmlChar *)"/xmlsysd/pids/pid",xp_hostdoc);

 /* Did we get an xpath object at all for this path? */
 if( xp_op == NULL ) {
   fprintf(OUTFP,"xpath cannot parse xp_hostdoc.\n");
   
   return;
 }

 /* If we did, is it a nodeset? */
 if( xp_op->type != XPATH_NODESET ){
   fprintf(OUTFP,"No running pid nodes found by xpath on %s.\n",hostptr->hostname);
   
   return;
 }

 /*
  * We have to start with an empty pidlist
  */
 delete_list(hostptr->pidlist);

 /*
  * xp_op now contains an xpath object pointer to the /pids/pid
  * list in no particular order.
  *
  * Time to walk the dog-ument and pull out the hosts.
  * This loop sets cur to point to each <pids><pid> in turn,
  * and puts the results into a linked list that can be used
  * to make the displays in display_values.
  */
 numnodes = xp_op->nodesetval->nodeNr;
 for(i = 0 ; i < numnodes; i++){
   /*
    * START by allocating room for the next pid and adding it to
    * the linked pidlist.
    */
   cur = xp_op->nodesetval->nodeTab[i];
   pid_string = (char *)xmlGetProp(cur,(xmlChar*) "pid");
   /*
    * Start with newpid a blank slate so any missing tags/fields
    * get a default value of NULL.
    */
   bzero(&newpid,sizeof(newpid));
   newpid.pid = atoi(pid_string);
   free(pid_string);
   if((verbose == D_ALL) || (verbose == D_VALUES)){
     fprintf(OUTFP,"D_VALUES: pid = %d\n",newpid.pid);
     
   }

   cur = xp_op->nodesetval->nodeTab[i]->xmlChildrenNode;
   /*
   if((verbose == D_ALL) || (verbose == D_VALUES)){
     fprintf(OUTFP,"D_VALUES: Ready to walk document from point = %x\n",cur);
   }
   */
   while (cur != NULL) {
     if((verbose == D_ALL) || (verbose == D_VALUES)){
       fprintf(OUTFP,"D_VALUES: tag name is %s\n",cur->name);
       
     }

     /*
      * Extract the "cmdline" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "cmdline") == 0) {
       snprintf(newpid.cmdline,K,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: cmdline = %s\n",newpid.cmdline);
	 
       }
     }
     
     /*
      * Extract the "taskname" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "taskname") == 0) {
       snprintf(newpid.taskname,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: taskname = %s\n",newpid.taskname);
	 
       }
     }

     /*
      * Extract the "state" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "state") == 0) {
       snprintf(newpid.state,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: state = %s\n",newpid.state);
	 
       }
     }

     /*
      * Extract the "user" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "user") == 0) {
       snprintf(newpid.user,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: user = %s\n",newpid.user);
	 
       }
     }


     /*
      * Extract the "uid" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "uid") == 0) {
       newpid.uid = atoi((char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: uid = %d\n",newpid.uid);
	 
       }
     }

     /*
      * Extract the "time" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "time") == 0) {
       snprintf(newpid.time,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: time = %s\n",newpid.time);
	 
       }
     }

     /*
      * Extract the "nice" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "nice") == 0) {
       newpid.nice = atoi((char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: nice = %d\n",newpid.nice);
	 
       }
     }

     /*
      * Extract the "vsize" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "vsize") == 0) {
       snprintf(newpid.vsize,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: vsize = %s\n",newpid.vsize);
	 
       }
     }

     /*
      * Extract the "rss" tag contents.
      */
     if( xmlStrcmp(cur->name, (const xmlChar *) "rss") == 0) {
       snprintf(newpid.rss,128,"%s",(char *)cur->xmlChildrenNode->content);
       if((verbose == D_ALL) || (verbose == D_VALUES)){
         fprintf(OUTFP,"D_VALUES: rss = %s\n",newpid.rss);
	 
       }
     }

     cur = cur->next;

   }

   if((verbose == D_ALL) || (verbose == D_VALUES)){
     fprintf(OUTFP,"D_VALUES: Adding task %s, pid = %d to pidlist\n",newpid.taskname,newpid.pid);
     
   }
   add_list(hostptr->pidlist,&newpid,sizeof(Pid));

   if((verbose == D_ALL) || (verbose == D_VALUES)){
     fprintf(OUTFP,"D_VALUES: Done!  On to the next task...\n");
     
   }
 }

}

