Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

nodelink.cc

Go to the documentation of this file.
00001 /*********************************************************************
00002 * File: nodelink.cc                                                  *
00003 * Description: C++ File for the RCS Systems Team's Library           *
00004 * Purpose:                                                           *
00005 *      NODE_LINK objects form links between NODEs and their          *
00006 * subordinates or NODEs that provide them with WM info.              *
00007 *********************************************************************/
00008 #include "rcs_defs.hh"          /* EXTERN_C_STD_HEADERS */
00009 
00010 /* Include Files */
00011 #ifdef EXTERN_C_STD_HEADERS
00012 extern "C"
00013 {
00014 #endif
00015 
00016 #include <stdlib.h>             /* malloc(), free() */
00017 #include <string.h>             /* strcpy(), strlen(), strcat() */
00018 
00019 #ifdef EXTERN_C_STD_HEADERS
00020 }
00021 #endif
00022 
00023 #include "nml.hh"               /* class NML */
00024 #include "nmlmsg.hh"            /* class NMLmsg */
00025 #include "cmd_msg.hh"           /* class RCS_CMD_MSG, RCS_CMD_CHANNEL, */
00026                                 /* class RCS_GENERIC_CMD */
00027 #include "stat_msg.hh"          /* class RCS_STAT_MSG, RCS_STAT_CHANNEL */
00028 #include "wm_msg.hh"            /* class RCS_WM_MSG, RCS_WM_CHANNEL */
00029 #include "node.hh"              /* class NODE */
00030 #include "linklist.hh"          /* class RCS_LINKED_LIST */
00031 #include "nodelink.hh"          /* class NODE_LINK */
00032 #include "rcs_prnt.hh"          /* rcs_print_error(), rcs_print_debug() */
00033 
00034 /* Constructors and Destructors */
00035 
00036 /*******************************************************************
00037 * Class: NODE_LINK                                                 *
00038 * Function: (Constructor)                                          *
00039 * Parameters:                                                      *
00040 *    NML_FORMAT_PTR format_ptr; - pointer to a function which      *
00041 *         handles the neutral data format encoding and decoding    *
00042 *         for the buffers used by this node. (See NML Doc.)        *
00043 *    char *n; - string including the name of this node             *
00044 *          (The names of the buffers connecting to this name are   *
00045 *           computed from my_name by adding suffixes like "_cmd".) *
00046 *    char *file; - name of NML configuration file.                 *
00047 *    NODE *node; - pointer to the node that is using this NODE_LINK*
00048 *             (Normally node constructors should use "this" as     *
00049 *              the node. )                                         *
00050 * Purpose: To initialize a new NODE_LINK object.                   *
00051 * NOTES: node->valid will be set to 0 if the NODE_LINK was not     *
00052 * properly initialized.                                            *
00053 * Returns: NONE.                                                   *
00054 *******************************************************************/
00055 NODE_LINK::NODE_LINK (NML_FORMAT_PTR f_ptr, char *n, char *file, NODE * node,
00056                       NODE_LINK_TYPE link_type)
00057 {
00058   char *command_buffer;
00059   char *status_buffer;
00060   char *wm_buffer;
00061 
00062   /* Set pointers to dynamically allocated memory buffers to NULL */
00063   /* so the destructor */
00064   /* doesn't delete them unless they are actually created. */
00065   name = NULL;
00066   cmd = NULL;
00067   status = NULL;
00068   wm = NULL;
00069   parent_node = node;
00070 
00071 
00072   if (NULL == node)
00073     {
00074       rcs_print_error
00075         ("NODE_LINK::Constructor - parent node must not be NULL.\n");
00076       return;
00077     }
00078 
00079   if (!node->valid)
00080     {
00081       return;
00082     }
00083 
00084   type_of_link = link_type;
00085 
00086 
00087   /* Store the name in a new place. */
00088   name = (char *) malloc (strlen (n) + 1);
00089   if (NULL == name)
00090     {
00091       node->valid = 0;
00092       rcs_print_error ("%s: Error constructing NODE_LINK %s.\n", node->name,
00093                        n);
00094       return;
00095     }
00096   strcpy (name, n);
00097 
00098   if ((NODE_SUBORDINATE_ONLY == link_type)
00099       || (NODE_WM_AND_SUBORDINATE == link_type))
00100     {
00101       if (-1 ==
00102           (sub_list_id =
00103            parent_node->sub_list->store_at_tail (this, sizeof (NODE_LINK),
00104                                                  0)))
00105         {
00106           parent_node->valid = 0;
00107           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00108                            node->name, n);
00109           return;
00110         }
00111 
00112       /* Compute command buffer name and create NML channel to it. */
00113       command_buffer =
00114         (char *) malloc (strlen (name) + RCS_COMMAND_SUFFIX_LENGTH + 1);
00115       if (NULL == command_buffer)
00116         {
00117           node->valid = 0;
00118           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00119                            node->name, name);
00120           return;
00121         }
00122       strcpy (command_buffer, name);
00123       strcat (command_buffer, RCS_COMMAND_SUFFIX);      /* append suffix */
00124       cmd = new RCS_CMD_CHANNEL (f_ptr, command_buffer, node->name, file);
00125       free (command_buffer);
00126 
00127       if (NULL == cmd)
00128         {
00129           node->valid = 0;
00130           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00131                            node->name, name);
00132           return;
00133         }
00134       if (!cmd->valid ())
00135         {
00136           node->valid = 0;
00137           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00138                            node->name, name);
00139           return;
00140         }
00141 
00142       /* Create buffer to use for generic Commands(init, halt, etc.) */
00143       generic_command = new RCS_GENERIC_CMD;
00144       if (NULL == generic_command)
00145         {
00146           node->valid = 0;
00147           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00148                            node->name, name);
00149           return;
00150         }
00151 
00152       /* Compute status buffer name and create NML channel to it. */
00153       status_buffer =
00154         (char *) malloc (strlen (name) + RCS_STATUS_SUFFIX_LENGTH + 1);
00155       if (NULL == status_buffer)
00156         {
00157           node->valid = 0;
00158           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00159                            node->name, name);
00160           return;
00161         }
00162       strcpy (status_buffer, name);
00163       strcat (status_buffer, RCS_STATUS_SUFFIX);        /* append suffix */
00164       status = new RCS_STAT_CHANNEL (f_ptr, status_buffer, node->name, file);
00165       free (status_buffer);
00166       if (NULL == status)
00167         {
00168           node->valid = 0;
00169           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00170                            node->name, name);
00171           return;
00172         }
00173       if (!status->valid ())
00174         {
00175           node->valid = 0;
00176           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00177                            node->name, name);
00178           return;
00179         }
00180 
00181       node->num_of_subord++;
00182     }
00183 
00184   if ((NODE_WM_ONLY == link_type) || (NODE_WM_AND_SUBORDINATE == link_type))
00185     {
00186       if (-1 ==
00187           (wm_list_id =
00188            parent_node->wm_in_list->store_at_tail (this, sizeof (NODE_LINK),
00189                                                    0)))
00190         {
00191           parent_node->valid = 0;
00192           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00193                            node->name, n);
00194           return;
00195         }
00196 
00197       /* Compute command buffer name and create NML channel to it. */
00198       wm_buffer = (char *) malloc (strlen (name) + RCS_WM_SUFFIX_LENGTH + 1);
00199       if (NULL == wm_buffer)
00200         {
00201           node->valid = 0;
00202           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00203                            node->name, name);
00204           return;
00205         }
00206       strcpy (wm_buffer, name);
00207       strcat (wm_buffer, RCS_WM_SUFFIX);        /* append suffix */
00208       wm = new RCS_WM_CHANNEL (f_ptr, wm_buffer, node->name, file);
00209       free (wm_buffer);
00210 
00211       if (NULL == wm)
00212         {
00213           node->valid = 0;
00214           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00215                            node->name, name);
00216           return;
00217         }
00218       if (!wm->valid ())
00219         {
00220           node->valid = 0;
00221           rcs_print_error ("%s: Error constructing NODE_LINK to %s.\n",
00222                            node->name, name);
00223           return;
00224         }
00225     }
00226 
00227   serial_number = 0;
00228   new_cmd = 0;
00229 
00230 }
00231 
00232 /*******************************************************************
00233 * Class: NODE_LINK                                                 *
00234 * Function: (Destructor)                                           *
00235 * Parameters: NONE.                                                *
00236 * Purpose: To deallocate and close a  NODE_LINK object.            *
00237 * Returns: NONE.                                                   *
00238 *******************************************************************/
00239 NODE_LINK::~NODE_LINK ()
00240 {
00241   if (NULL != parent_node)
00242     {
00243       if (NULL != parent_node->sub_list)
00244         {
00245           if ((NODE_SUBORDINATE_ONLY == type_of_link)
00246               || (NODE_WM_AND_SUBORDINATE == type_of_link))
00247             {
00248               parent_node->sub_list->delete_node (sub_list_id);
00249             }
00250           if ((NODE_WM_ONLY == type_of_link)
00251               || (NODE_WM_AND_SUBORDINATE == type_of_link))
00252             {
00253               parent_node->wm_in_list->delete_node (wm_list_id);
00254             }
00255         }
00256     }
00257   if (NULL != cmd)
00258     {
00259       delete cmd;
00260       cmd = NULL;
00261     }
00262   if (NULL != status)
00263     {
00264       delete status;
00265       status = NULL;
00266     }
00267   if (NULL != wm)
00268     {
00269       delete wm;
00270       wm = NULL;
00271     }
00272   if (NULL != name)
00273     {
00274       free (name);
00275       name = NULL;
00276     }
00277 }
00278 
00279 /*******************************************************************
00280 * Class: NODE_LINK                                                  *
00281 * Function: get_status                                             *
00282 * Parameters: NONE.                                                *
00283 * Outputs:                                                         *
00284 *  RCS_STAT_MSG *status_msg; - set to point to the last status     *
00285 *   message recieved.                                              *
00286 *  NODE_STATUS node_status; - set to node_status of last status    *
00287 *   message recieved unless the serial number doesn't match the    *
00288 *   serial number of the last command sent.                        *
00289 * Returns: 0 for success.                                          *
00290 *          -1 if an error occured.                                 *
00291 *******************************************************************/
00292 int
00293 NODE_LINK::get_status ()
00294 {
00295   if (NULL == status)
00296     {
00297       return (-1);
00298     }
00299 
00300   if (-1 == (status_type = status->read ()))
00301     {
00302       node_status = NODE_ERROR;
00303       return (-1);
00304     }
00305   else if (0 != status_type)
00306     {
00307       status_msg = status->get_address ();
00308       node_status = (NODE_STATUS_TYPE) status_msg->node_status;
00309       if ((node_status == NODE_DONE) &&
00310           (serial_number != status_msg->serial_number))
00311         {
00312           node_status = NODE_WAITING;
00313         }
00314 
00315       rcs_print_debug (PRINT_STATUS_RECIEVED,
00316                        "%s: Recieved new status from %s.\n",
00317                        parent_node->name, name);
00318       rcs_print_debug (PRINT_STATUS_RECIEVED,
00319                        "  (type = %ld (0x%lX), serial_num = %d,",
00320                        status_msg->type,
00321                        status_msg->type, status_msg->serial_number);
00322       rcs_print_debug (PRINT_STATUS_RECIEVED, " status = %d)\n", node_status);
00323       status_new = 1;
00324     }
00325   else
00326     {
00327       status_new = 0;
00328     }
00329 
00330   return (0);
00331 }
00332 
00333 /*******************************************************************
00334 * Class: NODE_LINK                                                 *
00335 * Function: read_wm                                                *
00336 * Parameters: NONE.                                                *
00337 * Outputs:                                                         *
00338 *  RCS_STAT_MSG *status_msg; - set to point to the last status     *
00339 *   message recieved.                                              *
00340 *  NODE_STATUS node_status; - set to node_status of last status    *
00341 *   message recieved unless the serial number doesn't match the    *
00342 *   serial number of the last command sent.                        *
00343 * Returns: 0 for success.                                          *
00344 *          -1 if an error occured.                                 *
00345 *******************************************************************/
00346 int
00347 NODE_LINK::read_wm ()
00348 {
00349   if (NULL == wm)
00350     {
00351       return (-1);
00352     }
00353 
00354   if (-1 == (wm_type = wm->read ()))
00355     {
00356       node_status = NODE_ERROR;
00357       return (-1);
00358     }
00359   else if (0 != wm_type)
00360     {
00361       wm_msg = wm->get_address ();
00362       new_wm = 1;
00363       rcs_print_debug (PRINT_NEW_WM,
00364                        "%s: Recieved new world model data from %s.\n",
00365                        parent_node->name, name);
00366       rcs_print_debug (PRINT_NEW_WM, " (type = %ld (0x%lX))", wm_msg->type,
00367                        wm_msg->type);
00368     }
00369   else
00370     {
00371       new_wm = 0;
00372     }
00373 
00374   return (0);
00375 }
00376 
00377 /*******************************************************************
00378 * Class: NODE_LINK                                                  *
00379 * Function: send_command                                           *
00380 * Parameters: NONE.                                                *
00381 * Outputs:                                                         *
00382 * int serial_number; - incremented when a new command is sent.     *
00383 * Returns: 0 for success.                                          *
00384 *          -1 if an error occured.                                 *
00385 *******************************************************************/
00386 int
00387 NODE_LINK::send_command ()
00388 {
00389   if ((NULL == cmd) || (NULL == parent_node))
00390     {
00391       return (-1);
00392     }
00393 
00394   if (new_cmd)
00395     {
00396       serial_number++;
00397       cmd_msg->serial_number = serial_number;
00398 
00399       rcs_print_debug (PRINT_COMMANDS_SENT,
00400                        "%s: Sent new command to %s.\n", parent_node->name,
00401                        name);
00402       rcs_print_debug (PRINT_COMMANDS_SENT,
00403                        "  (type = %ld (0x%lX), serial_num = %d)\n",
00404                        cmd_msg->type, cmd_msg->type, serial_number);
00405       node_status = NODE_WAITING;
00406       if (parent_node->config_flags & NODE_WAIT_FOR_COMMANDS_TO_BE_READ)
00407         {
00408           if (-1 == cmd->write_if_read (cmd_msg))
00409             {
00410               if (cmd->error_type == NML_BUFFER_NOT_READ)
00411                 {
00412                   return (0);
00413                 }
00414               else
00415                 {
00416                   node_status = NODE_ERROR;
00417                   return (-1);
00418                 }
00419             }
00420         }
00421       else
00422         {
00423           if (-1 == cmd->write (cmd_msg))
00424             {
00425               node_status = NODE_ERROR;
00426               return (-1);
00427             }
00428         }
00429       new_cmd = 0;
00430     }
00431 
00432   return (0);
00433 }
00434 
00435 /*******************************************************************
00436 * Class: NODE_LINK                                                  *
00437 * Function: new_command                                            *
00438 * Parameters:                                                      *
00439 * RCS_CMD_MSG *new_cmd_msg; - pointer to the command you want      *
00440 *     sent to the subordinate at the next time send_command is     *
00441 *     called.                                                      *
00442 * Outputs:                                                         *
00443 *  RCS_CMD_MSG *cmd_msg; - set to parameter.                       *
00444 *  int new_cmd; - set to one.
00445 * Returns: NONE.                                                   *
00446 *******************************************************************/
00447 void
00448 NODE_LINK::new_command (RCS_CMD_MSG * new_cmd_msg)
00449 {
00450   cmd_msg = new_cmd_msg;
00451   new_cmd = 1;
00452   node_status = NODE_WAITING;
00453 }
00454 
00455 
00456 /*******************************************************************
00457 * Class: NODE_LINK                                                  *
00458 * Function: new_command                                            *
00459 * Parameters:                                                      *
00460 * RCS_GENERIC_COMMAND_ID    new_id - the id of a new command like  *
00461 * init or halt for which a generic command exists.                 *
00462 * Outputs:                                                         *
00463 *  RCS_CMD_MSG *cmd_msg; - set to parameter.                       *
00464 *  int new_cmd; - set to one.
00465 * Returns: NONE.                                                   *
00466 *******************************************************************/
00467 void
00468 NODE_LINK::new_command (RCS_GENERIC_CMD_ID new_id)
00469 {
00470   generic_command->gen_id = new_id;
00471   cmd_msg = generic_command;
00472   new_cmd = 1;
00473 }

Generated on Sun Dec 2 15:56:51 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001