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

cms_in.cc

Go to the documentation of this file.
00001 /*****************************************************************************
00002 * File: cms_in.cc
00003 * Author(s): Will Shackleford
00004 * Purpose: Provides the internal interface of CMS to the buffer.
00005 *
00006 * NOTES:
00007 * The following applies to the member functions in this file:
00008 * They work through a handle to a shared physical memory object.
00009 * They should only be called when this process has sole access to
00010  this shared physical memory object. This is normally achieved by taking
00011  a mutual-exclusion semaphore before calling the internal_access function
00012  above from the main_access function of a derived class.
00013 * If they begin with "queue" then they are for buffers where messages are
00014  to be queued, other wise they are for buffers with will have only 1
00015  message at a time.*
00016 * Queuing buffers store a CMS_QUEUING_HEADER at the beginning and a
00017  CMS_HEADER before each message. Non-queuing buffers have only a
00018  CMS_HEADER before the only message.
00019 * If they end in "encoded" they are for buffers that will neutrally encoded
00020  in some processor architecture independant data format such as XDR
00021  (eXternal Data Representation), otherwise the buffer must be in the
00022  format used by the same compiler as this is compiled in and for the same
00023  processor architecture and the function name will end in "raw".
00024 *****************************************************************************/
00025 
00026 /* Include Files */
00027 #include "cms.hh"               /* class CMS  */
00028 #include "cmsdiag.hh"           // class CMS_DIAG_PROC_INFO, CMS_DIAG_HEADER
00029 #include "rcs_prnt.hh"          /* rcs_print_error() */
00030 #include "physmem.hh"           /* class PHYSMEM_HANDLE  */
00031 
00032 /* CMS Member Functions. */
00033 
00034 
00035 int cms_print_queue_free_space = 0;
00036 int cms_print_queue_full_messages = 1;
00037 
00038 
00039 /*************************************************************************
00040 * This function should be called by functions overloading main_access()
00041 * It uses a dummy physmem handle so that reads and writes work on
00042 * the memory at _global.
00043 * Parameters:
00044 * _local - Address of local buffer where user has stored messages in or will
00045 * read messages from whithin this process.
00046 * _global - Address of shared or global memory buffer used to communicate with
00047 * other  process.
00048 ************************************************************************/
00049 CMS_STATUS
00050   CMS::internal_access (void *_global, long _global_size, void *_local)
00051 {
00052   /* Don't bother trying to create a physmem handle for a NULL pointer. */
00053   if (NULL == _global)
00054     {
00055       return (status = CMS_INTERNAL_ACCESS_ERROR);
00056     }
00057 
00058   /* Create a dummy physmem handle if I don't already have one. */
00059   if (NULL == dummy_handle)
00060     {
00061       dummy_handle = new PHYSMEM_HANDLE;
00062     }
00063 
00064   /* Check for problem allocating memory. */
00065   if (NULL == dummy_handle)
00066     {
00067       rcs_print_error ("CMS: Couldn't create PHYSMEM_HANDLE.\n");
00068       return (status = CMS_INTERNAL_ACCESS_ERROR);
00069     }
00070 
00071   dummy_handle->set_to_ptr (_global, _global_size);
00072   internal_access (dummy_handle, _local);
00073   return (status);
00074 }
00075 
00076 /* This function should be called by classes which overload the */
00077 /* main_access function. */
00078 CMS_STATUS
00079 CMS::internal_access (PHYSMEM_HANDLE * _global, void *_local)
00080 {
00081   status = CMS_STATUS_NOT_SET;
00082   if (NULL == _global)
00083     {
00084       rcs_print_error ("CMS: Handle to global memory is NULL.\n");
00085       return (status = CMS_INTERNAL_ACCESS_ERROR);
00086     }
00087   handle_to_global_data = _global;
00088 
00089   if (CMS_CLEAR_ACCESS == internal_access_type)
00090     {
00091       internal_clear ();
00092       return (status);
00093     }
00094 
00095   if (min_compatible_version > 2.58 || min_compatible_version < 1E-6)
00096     {
00097       handle_to_global_data->offset += skip_area;
00098     }
00099 
00100 
00101   if (CMS_GET_DIAG_INFO_ACCESS == internal_access_type)
00102     {
00103       internal_retrieve_diag_info (handle_to_global_data, _local);
00104       return (status);
00105     }
00106 
00107   long orig_offset = handle_to_global_data->offset;
00108   if (enable_diagnostics)
00109     {
00110       handle_to_global_data->offset +=
00111         sizeof (CMS_DIAG_HEADER) +
00112         total_connections * sizeof (CMS_DIAG_PROC_INFO);
00113       handle_to_global_data->enable_byte_counting = 1;
00114       pre_op_total_bytes_moved = handle_to_global_data->total_bytes_moved;
00115     }
00116 
00117   char was_read_byte;
00118   write_just_completed = 0;
00119   int
00120     read_only = ((internal_access_type == CMS_CHECK_IF_READ_ACCESS) ||
00121                  (internal_access_type == CMS_READ_ACCESS) ||
00122                  (internal_access_type == CMS_PEEK_ACCESS));
00123 
00124   long offset_before_split = handle_to_global_data->offset;
00125 
00126   if (total_subdivisions >= 1 && current_subdivision > 0
00127       && current_subdivision < total_subdivisions)
00128     {
00129       handle_to_global_data->offset += (current_subdivision * subdiv_size);
00130       handle_to_global_data->size = ((current_subdivision + 1) * subdiv_size);
00131       if (handle_to_global_data->size > size)
00132         {
00133           handle_to_global_data->size = size;
00134         }
00135     }
00136 
00137 
00138   if (split_buffer)
00139     {
00140       if (internal_access_type == CMS_WRITE_IF_READ_ACCESS)
00141         {
00142           handle_to_global_data->offset++;
00143           handle_to_global_data->read (&was_read_byte, 1);
00144           handle_to_global_data->offset--;
00145           header.was_read = (was_read_byte == toggle_bit + 1);
00146           if (!header.was_read)
00147             {
00148               status = CMS_WRITE_WAS_BLOCKED;
00149               return (status);
00150             }
00151           internal_access_type = CMS_WRITE_ACCESS;
00152         }
00153       if (read_only == toggle_bit)
00154         {
00155           handle_to_global_data->offset += 2;
00156           handle_to_global_data->size = half_size;
00157         }
00158       else
00159         {
00160           handle_to_global_data->offset += half_offset;
00161           handle_to_global_data->size = size;
00162         }
00163     }
00164 
00165   if (!queuing_enabled)
00166     {
00167       if (neutral)
00168         {
00169           switch (internal_access_type)
00170             {
00171             case CMS_CHECK_IF_READ_ACCESS:
00172               check_if_read_encoded ();
00173               break;
00174             case CMS_READ_ACCESS:
00175               read_encoded ();
00176               break;
00177             case CMS_PEEK_ACCESS:
00178               peek_encoded ();
00179               break;
00180             case CMS_WRITE_ACCESS:
00181               write_encoded ();
00182               break;
00183             case CMS_WRITE_IF_READ_ACCESS:
00184               write_if_read_encoded ();
00185               break;
00186             default:
00187               return (status = CMS_INTERNAL_ACCESS_ERROR);
00188             }
00189         }
00190       else
00191         {
00192           switch (internal_access_type)
00193             {
00194             case CMS_CHECK_IF_READ_ACCESS:
00195               check_if_read_raw ();
00196               break;
00197             case CMS_READ_ACCESS:
00198               read_raw ();
00199               break;
00200             case CMS_PEEK_ACCESS:
00201               peek_raw ();
00202               break;
00203             case CMS_WRITE_ACCESS:
00204               write_raw (_local);
00205               break;
00206             case CMS_WRITE_IF_READ_ACCESS:
00207               write_if_read_raw (_local);
00208               break;
00209             default:
00210               return (status = CMS_INTERNAL_ACCESS_ERROR);
00211             }
00212         }
00213     }
00214   else
00215     {
00216       if (neutral)
00217         {
00218           switch (internal_access_type)
00219             {
00220             case CMS_CHECK_IF_READ_ACCESS:
00221               queue_check_if_read_encoded ();
00222               break;
00223             case CMS_READ_ACCESS:
00224               queue_read_encoded ();
00225               break;
00226             case CMS_PEEK_ACCESS:
00227               queue_peek_encoded ();
00228               break;
00229             case CMS_WRITE_ACCESS:
00230               queue_write_encoded ();
00231               break;
00232             case CMS_WRITE_IF_READ_ACCESS:
00233               queue_write_if_read_encoded ();
00234               break;
00235             default:
00236               return (status = CMS_INTERNAL_ACCESS_ERROR);
00237             }
00238         }
00239       else
00240         {
00241           switch (internal_access_type)
00242             {
00243             case CMS_CHECK_IF_READ_ACCESS:
00244               queue_check_if_read_raw ();
00245               break;
00246             case CMS_READ_ACCESS:
00247               queue_read_raw ();
00248               break;
00249             case CMS_PEEK_ACCESS:
00250               queue_peek_raw ();
00251               break;
00252             case CMS_WRITE_ACCESS:
00253               queue_write_raw (_local);
00254               break;
00255             case CMS_WRITE_IF_READ_ACCESS:
00256               queue_write_if_read_raw (_local);
00257               break;
00258             default:
00259               return (status = CMS_INTERNAL_ACCESS_ERROR);
00260             }
00261         }
00262     }
00263 
00264   if (split_buffer)
00265     {
00266       handle_to_global_data->offset = offset_before_split + 1;
00267       if (internal_access_type == CMS_READ_ACCESS)
00268         {
00269           was_read_byte = 1;
00270         }
00271       else if (!read_only)
00272         {
00273           was_read_byte = 0;
00274         }
00275       if (-1 == handle_to_global_data->write (&was_read_byte, 1))
00276         {
00277           rcs_print_error ("CMS: can not set was read flag.\n");
00278         }
00279     }
00280 
00281 
00282   if (enable_diagnostics)
00283     {
00284       handle_to_global_data->offset = orig_offset;
00285       calculate_and_store_diag_info (handle_to_global_data, _local);
00286     }
00287   return (status);
00288 }
00289 
00290 /* Clear the shared or global memory. */
00291 CMS_STATUS
00292 CMS::internal_clear ()
00293 {
00294   in_buffer_id = 0;
00295 
00296   /* Check that the handle to global memory exists. */
00297   if (NULL == handle_to_global_data)
00298     {
00299       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00300       return (status = CMS_INTERNAL_ACCESS_ERROR);
00301     }
00302 
00303   if (-1 == handle_to_global_data->clear_memory ())
00304     {
00305       rcs_print_error ("CMS: Can't clear global_memory.\n");
00306       return (status = CMS_INTERNAL_ACCESS_ERROR);
00307     }
00308   int temp_offset = handle_to_global_data->offset;
00309   handle_to_global_data->offset = 0;
00310   if (-1 == handle_to_global_data->write (BufferName, 32))
00311     {
00312       rcs_print_error ("CMS: Can't clear reset name in global memory.\n");
00313       return (status = CMS_INTERNAL_ACCESS_ERROR);
00314     }
00315   handle_to_global_data->offset = temp_offset;
00316 
00317   return (status = CMS_CLEAR_OK);
00318 }
00319 
00320 /* Determine whether the message in the buffer has been read at least once. */
00321 int
00322 CMS::check_if_read_raw ()
00323 {
00324   /* Check that the handle to global memory exists. */
00325   if (NULL == handle_to_global_data)
00326     {
00327       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00328       status = CMS_INTERNAL_ACCESS_ERROR;
00329       return 0;
00330     }
00331 
00332   /* Read the header for the message. */
00333   if (-1 == handle_to_global_data->read (&header, sizeof (CMS_HEADER)))
00334     {
00335       rcs_print_error
00336         ("CMS: Error reading from global memory for %s at %s:%d", BufferName,
00337          __FILE__, __LINE__);
00338       status = CMS_INTERNAL_ACCESS_ERROR;
00339       return 0;
00340     }
00341   return ((int) header.was_read);
00342 }
00343 
00344 /* Determine if all of the messages in the buffer have been read. */
00345 /* This means the queue is empty. */
00346 int
00347 CMS::queue_check_if_read_raw ()
00348 {
00349   /* Check that the handle to global memory exists. */
00350   if (NULL == handle_to_global_data)
00351     {
00352       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00353       status = CMS_INTERNAL_ACCESS_ERROR;
00354       return 0;
00355     }
00356 
00357   /* Read the header for the buffer. */
00358   if (-1 == handle_to_global_data->read (&queuing_header,
00359                                          sizeof (CMS_QUEUING_HEADER)))
00360     {
00361       rcs_print_error
00362         ("CMS: Error reading from global memory for %s at %s:%d\n",
00363          BufferName, __FILE__, __LINE__);
00364       status = CMS_INTERNAL_ACCESS_ERROR;
00365       return 0;
00366     }
00367 
00368   return ((int) (queuing_header.queue_length == 0));
00369 }
00370 
00371 /* Determine whether the message in the buffer has been read at least once. */
00372 int
00373 CMS::check_if_read_encoded ()
00374 {
00375   /* Check that the handle to global memory exists. */
00376   if (NULL == handle_to_global_data)
00377     {
00378       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00379       status = CMS_INTERNAL_ACCESS_ERROR;
00380       return 0;
00381     }
00382 
00383   /* Read the header for the buffer. */
00384   if (-1 == handle_to_global_data->read (encoded_header, encoded_header_size))
00385     {
00386       rcs_print_error
00387         ("CMS: Error reading from global memory for %s at %s:%d\n",
00388          BufferName, __FILE__, __LINE__);
00389       status = CMS_INTERNAL_ACCESS_ERROR;
00390       return 0;
00391     }
00392 
00393   /* Decode the header and store in header structure. */
00394   decode_header ();
00395 
00396   return ((int) header.was_read);
00397 }
00398 
00399 /* Determine if all of the messages in the buffer have been read. */
00400 /* This means the queue is empty. */
00401 int
00402 CMS::queue_check_if_read_encoded ()
00403 {
00404   /* Check that the handle to global memory exists. */
00405   if (NULL == handle_to_global_data)
00406     {
00407       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00408       status = CMS_INTERNAL_ACCESS_ERROR;
00409       return 0;
00410     }
00411 
00412   /* Read the header for the buffer. */
00413   if (-1 == handle_to_global_data->read (encoded_queuing_header,
00414                                          encoded_queuing_header_size))
00415     {
00416       rcs_print_error
00417         ("CMS: Error reading from global memory for %s at %s:%d\n",
00418          BufferName, __FILE__, __LINE__);
00419       status = CMS_INTERNAL_ACCESS_ERROR;
00420       return 0;
00421     }
00422 
00423   /* Decode the header and store in queuing_header structure. */
00424   decode_queuing_header ();
00425 
00426   return ((int) (queuing_header.queue_length == 0));
00427 }
00428 
00429 /* It takes several steps to perform a read operation. */
00430 /* 1. Read the header. */
00431 /* 2. Check the id and size. */
00432 /* 3. If id and size are ok, then read the message and update the header. */
00433 CMS_STATUS
00434 CMS::read_raw ()
00435 {
00436   /* Produce error message if process does not have permission to read. */
00437   if (!read_permission_flag)
00438     {
00439       rcs_print_error ("CMS: %s was not configured to read %s\n",
00440                        ProcessName, BufferName);
00441       return (status = CMS_PERMISSIONS_ERROR);
00442     }
00443 
00444 
00445   /* Check that the handle to global memory exists. */
00446   if (NULL == handle_to_global_data)
00447     {
00448       rcs_print_error ("CMS:(%s) handle_to_global_data is NULL.\n",
00449                        BufferName);
00450       return (status = CMS_INTERNAL_ACCESS_ERROR);
00451     }
00452 
00453   /* Read the header for the message. */
00454   if (-1 == handle_to_global_data->read (&header, sizeof (CMS_HEADER)))
00455     {
00456       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00457                        BufferName, __FILE__, __LINE__);
00458       return (status = CMS_INTERNAL_ACCESS_ERROR);
00459     }
00460 
00461   /* Set status to CMS_READ_OLD or CMS_READ_OK */
00462   if (check_id (header.write_id) == CMS_READ_OK)
00463     {
00464       /* Check the size of the message. */
00465       if (header.in_buffer_size > max_message_size)
00466         {
00467           rcs_print_error
00468             ("CMS:(%s) Message size of %ld exceeds maximum of %ld\n",
00469              BufferName, header.in_buffer_size, max_message_size);
00470           return (status = CMS_INTERNAL_ACCESS_ERROR);
00471         }
00472 
00473 
00474       /* Read the message. */
00475       handle_to_global_data->offset += sizeof (CMS_HEADER);
00476       if (-1 ==
00477           handle_to_global_data->read (subdiv_data,
00478                                        (long) header.in_buffer_size))
00479         {
00480           rcs_print_error
00481             ("CMS:(%s) Error reading from global memory at %s:%d\n",
00482              BufferName, __FILE__, __LINE__);
00483           return (status = CMS_INTERNAL_ACCESS_ERROR);
00484         }
00485       handle_to_global_data->offset -= sizeof (CMS_HEADER);
00486     }
00487 
00488   /* Update the header. */
00489   header.was_read = 1;
00490   if (-1 == handle_to_global_data->write (&header, sizeof (CMS_HEADER)))
00491     {
00492       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
00493                        BufferName, __FILE__, __LINE__);
00494       return (status = CMS_INTERNAL_ACCESS_ERROR);
00495     }
00496 
00497   return (status);
00498 }
00499 
00500 /* It takes several steps to perform a read operation when queuing is enabled. */
00501 /* 1. Read the queuing_header at the beginning of the buffer. */
00502 /* 2. Get the head of the queue from the queuing_header. */
00503 /* 3. Read the message header at the head of the queue. */
00504 /* 4. Check the id and size. */
00505 /* 5. If id and size are ok, */
00506  /* then read the message and */
00507  /* update both the queuing header and message header. */
00508 CMS_STATUS
00509 CMS::queue_read_raw ()
00510 {
00511   long queuing_header_offset;
00512 
00513   /* Produce error message if process does not have permission to read. */
00514   if (!read_permission_flag)
00515     {
00516       rcs_print_error ("CMS: %s was not configured to read %s\n",
00517                        ProcessName, BufferName);
00518       return (status = CMS_PERMISSIONS_ERROR);
00519     }
00520 
00521 
00522   /* Check that the handle to global memory exists. */
00523   if (NULL == handle_to_global_data)
00524     {
00525       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00526       return (status = CMS_INTERNAL_ACCESS_ERROR);
00527     }
00528 
00529   /* Store the original offset so that we can update the header later. */
00530   queuing_header_offset = handle_to_global_data->offset;
00531 
00532   /* Read the queuing header for the buffer. */
00533   if (-1 == handle_to_global_data->read (&queuing_header,
00534                                          sizeof (CMS_QUEUING_HEADER)))
00535     {
00536       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00537                        BufferName, __FILE__, __LINE__);
00538       return (status = CMS_INTERNAL_ACCESS_ERROR);
00539     }
00540 
00541   /* Check to see if there are any unread messages. */
00542   if (queuing_header.queue_length == 0)
00543     {
00544       return (status = CMS_READ_OLD);
00545     }
00546 
00547   /* Read the header for the message. */
00548   handle_to_global_data->offset += queuing_header.head;
00549   if (-1 == handle_to_global_data->read (&header, sizeof (CMS_HEADER)))
00550     {
00551       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00552                        BufferName, __FILE__, __LINE__);
00553       return (status = CMS_INTERNAL_ACCESS_ERROR);
00554     }
00555 
00556   /* Check the size of the message. */
00557   if (header.in_buffer_size > max_message_size)
00558     {
00559       rcs_print_error
00560         ("CMS:(%s) Message size of %ld exceeds maximum of %ld\n", BufferName,
00561          header.in_buffer_size, max_message_size);
00562       return (status = CMS_INTERNAL_ACCESS_ERROR);
00563     }
00564 
00565   /* Update the message header. */
00566   header.was_read = 1;
00567   if (-1 == handle_to_global_data->write (&header, sizeof (CMS_HEADER)))
00568     {
00569       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
00570                        BufferName, __FILE__, __LINE__);
00571       return (status = CMS_INTERNAL_ACCESS_ERROR);
00572     }
00573 
00574   /* Read the message. */
00575   handle_to_global_data->offset += sizeof (CMS_HEADER);
00576   if (-1 ==
00577       handle_to_global_data->read (subdiv_data, (long) header.in_buffer_size))
00578     {
00579       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00580                        BufferName, __FILE__, __LINE__);
00581       return (status = CMS_INTERNAL_ACCESS_ERROR);
00582     }
00583 
00584   /* Update the queuing header for the buffer. */
00585   queuing_header.head += header.in_buffer_size + sizeof (CMS_HEADER);
00586   if (queuing_header.head >= queuing_header.end_queue_space &&
00587       queuing_header.queue_length > 1)
00588     {
00589       queuing_header.head = sizeof (CMS_QUEUING_HEADER);
00590     }
00591   queuing_header.queue_length--;
00592   handle_to_global_data->offset = queuing_header_offset;
00593   if (-1 == handle_to_global_data->write (&queuing_header,
00594                                           sizeof (CMS_QUEUING_HEADER)))
00595     {
00596       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
00597                        BufferName, __FILE__, __LINE__);
00598       return (status = CMS_INTERNAL_ACCESS_ERROR);
00599     }
00600 
00601   /* Check_id so that debug variables for messages missed can be set. */
00602   check_id (header.write_id);
00603 
00604   return (status);
00605 }
00606 
00607 /* It takes several steps to perform a read operation on an neutral buffer.*/
00608 /* 1. Read the encoded  header. */
00609 /* 2. Decode the header. */
00610 /* 3. Check the id and size. */
00611 /* 4. If id and size are ok, then read the message and update the header. */
00612 CMS_STATUS
00613 CMS::read_encoded ()
00614 {
00615   /* Produce error message if process does not have permission to read. */
00616   if (!read_permission_flag)
00617     {
00618       rcs_print_error ("CMS: %s was not configured to read %s\n",
00619                        ProcessName, BufferName);
00620       return (status = CMS_PERMISSIONS_ERROR);
00621     }
00622 
00623 
00624   /* Check that the handle to the global memory object exists. */
00625   if (NULL == handle_to_global_data)
00626     {
00627       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00628       return (status = CMS_INTERNAL_ACCESS_ERROR);
00629     }
00630 
00631   /* Read the encoded header for the message. */
00632   if (-1 == handle_to_global_data->read (encoded_header, encoded_header_size))
00633     {
00634       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00635                        BufferName, __FILE__, __LINE__);
00636       return (status = CMS_INTERNAL_ACCESS_ERROR);
00637     }
00638 
00639   /* Decode the header and  store in header structure. */
00640   decode_header ();
00641 
00642   /* Determine if the message in the buffer is new to this process. */
00643   if (check_id (header.write_id) == CMS_READ_OK)
00644     {
00645       /* Check the size of the message. */
00646       if (header.in_buffer_size > max_message_size)
00647         {
00648           rcs_print_error
00649             ("CMS:(%s) Message size of %ld exceeds maximum of %ld\n",
00650              BufferName, header.in_buffer_size, max_message_size);
00651           return (status = CMS_INTERNAL_ACCESS_ERROR);
00652         }
00653 
00654       /* Read the message. */
00655       handle_to_global_data->offset += encoded_header_size;
00656       if (-1 == handle_to_global_data->read (encoded_data,
00657                                              (long) header.in_buffer_size))
00658         {
00659           rcs_print_error
00660             ("CMS:(%s) Error writing to global memory at %s:%d\n", BufferName,
00661              __FILE__, __LINE__);
00662           return (status = CMS_INTERNAL_ACCESS_ERROR);
00663         }
00664       handle_to_global_data->offset -= encoded_header_size;
00665     }
00666 
00667   /* Update the header. */
00668   header.was_read = 1;
00669 
00670   encode_header ();
00671   if (-1 ==
00672       handle_to_global_data->write (encoded_header, encoded_header_size))
00673     {
00674       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
00675                        BufferName, __FILE__, __LINE__);
00676       return (status = CMS_INTERNAL_ACCESS_ERROR);
00677     }
00678 
00679   return (status);
00680 }
00681 
00682 /* It takes several steps to perform a read operation */
00683  /* when queuing is enabled on a neutral buffer. */
00684 /* 1. Read the encoded queuing_header at the beginning of the buffer. */
00685 /* 2. Decode the queuing_header for the buffer. */
00686 /* 3. Get the head of the queue from the queuing_header. */
00687 /* 4. Read the message header at the head of the queue. */
00688 /* 5. Decode the message header. */
00689 /* 6. Check the id and size. */
00690 /* 7. If id and size are ok, */
00691  /* then read the message */
00692 CMS_STATUS
00693 CMS::queue_read_encoded ()
00694 {
00695   long queuing_header_offset;
00696 
00697   /* Produce error message if process does not have permission to read. */
00698   if (!read_permission_flag)
00699     {
00700       rcs_print_error ("CMS: %s was not configured to read %s\n",
00701                        ProcessName, BufferName);
00702       return (status = CMS_PERMISSIONS_ERROR);
00703     }
00704 
00705 
00706   /* Check that the handle to global memory exists. */
00707   if (NULL == handle_to_global_data)
00708     {
00709       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00710       return (status = CMS_INTERNAL_ACCESS_ERROR);
00711     }
00712 
00713   /* Store the original offset so we can update the queuing header later. */
00714   queuing_header_offset = handle_to_global_data->offset;
00715 
00716   /* Read the encoded header for the buffer. */
00717   if (-1 == handle_to_global_data->read (encoded_queuing_header,
00718                                          encoded_queuing_header_size))
00719     {
00720       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00721                        BufferName, __FILE__, __LINE__);
00722       return (status = CMS_INTERNAL_ACCESS_ERROR);
00723     }
00724 
00725   /* Decode the queuing header and store in the queuing_header structrure. */
00726   decode_queuing_header ();
00727 
00728   /* Determine if there are any unread messages. */
00729   if (queuing_header.queue_length == 0)
00730     {
00731       return (status = CMS_READ_OLD);
00732     }
00733 
00734   /* Read the header for the message. */
00735   handle_to_global_data->offset += queuing_header.head;
00736   if (-1 == handle_to_global_data->read (encoded_header, encoded_header_size))
00737     {
00738       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00739                        BufferName, __FILE__, __LINE__);
00740       return (status = CMS_INTERNAL_ACCESS_ERROR);
00741     }
00742 
00743   /* Decode the message header and store in the header structure. */
00744   decode_header ();
00745 
00746   /* Check the size of the message. */
00747   if (header.in_buffer_size > max_message_size)
00748     {
00749       rcs_print_error
00750         ("CMS:(%s) Message size of %ld exceeds maximum of %ld\n", BufferName,
00751          header.in_buffer_size, max_message_size);
00752       return (status = CMS_INTERNAL_ACCESS_ERROR);
00753     }
00754 
00755   /* Update the message header. */
00756   header.was_read = 1;
00757   encode_header ();
00758   if (-1 ==
00759       handle_to_global_data->write (encoded_header, encoded_header_size))
00760     {
00761       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
00762                        BufferName, __FILE__, __LINE__);
00763       return (status = CMS_INTERNAL_ACCESS_ERROR);
00764     }
00765 
00766   /* Read the message. */
00767   handle_to_global_data->offset += encoded_header_size;
00768   if (-1 ==
00769       handle_to_global_data->read (encoded_data,
00770                                    (long) header.in_buffer_size))
00771     {
00772       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00773                        BufferName, __FILE__, __LINE__);
00774       return (status = CMS_INTERNAL_ACCESS_ERROR);
00775     }
00776 
00777 
00778   /* Update the buffer header. */
00779   queuing_header.head += header.in_buffer_size + encoded_header_size;
00780   if (queuing_header.head >= queuing_header.end_queue_space &&
00781       queuing_header.queue_length > 1)
00782     {
00783       queuing_header.head = encoded_queuing_header_size;
00784     }
00785   queuing_header.queue_length--;
00786   encode_queuing_header ();
00787   handle_to_global_data->offset = queuing_header_offset;
00788   if (-1 == handle_to_global_data->write (&queuing_header,
00789                                           sizeof (CMS_QUEUING_HEADER)))
00790     {
00791       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
00792                        BufferName, __FILE__, __LINE__);
00793       return (status = CMS_INTERNAL_ACCESS_ERROR);
00794     }
00795 
00796   /* Check_id so that debug variables for messages missed can be set. */
00797   check_id (header.write_id);
00798 
00799   return (status);
00800 }
00801 
00802 /****************************************************************
00803 * Peek operations are the same as reads,
00804  except that the header(s) are not updated.
00805 ****************************************************************/
00806 
00807 /* It takes several steps to perform a peek operation. */
00808 /* 1. Read the header. */
00809 /* 2. Check the id and size. */
00810 /* 3. If id and size are ok, then read the message. */
00811 CMS_STATUS
00812 CMS::peek_raw ()
00813 {
00814   /* Produce error message if process does not have permission to read. */
00815   if (!read_permission_flag)
00816     {
00817       rcs_print_error ("CMS: %s was not configured to read %s\n",
00818                        ProcessName, BufferName);
00819       return (status = CMS_PERMISSIONS_ERROR);
00820     }
00821 
00822   /* Check that the handle to global memory exists. */
00823   if (NULL == handle_to_global_data)
00824     {
00825       rcs_print_error ("CMS:(%s) handle_to_global_data is NULL.\n",
00826                        BufferName);
00827       return (status = CMS_INTERNAL_ACCESS_ERROR);
00828     }
00829 
00830   /* Read the header for the message. */
00831   if (-1 == handle_to_global_data->read (&header, sizeof (CMS_HEADER)))
00832     {
00833       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00834                        BufferName, __FILE__, __LINE__);
00835       return (status = CMS_INTERNAL_ACCESS_ERROR);
00836     }
00837 
00838   /* Set status to CMS_READ_OLD or CMS_READ_OK */
00839   if (check_id (header.write_id) == CMS_READ_OLD)
00840     {
00841       return (status);          /* Don't bother copying out an old message. */
00842     }
00843 
00844   /* Check the size of the message. */
00845   if (header.in_buffer_size > max_message_size)
00846     {
00847       rcs_print_error
00848         ("CMS:(%s) Message size of %ld exceeds maximum of %ld\n", BufferName,
00849          header.in_buffer_size, max_message_size);
00850       return (status = CMS_INTERNAL_ACCESS_ERROR);
00851     }
00852 
00853   /* Read the message. */
00854   handle_to_global_data->offset += sizeof (CMS_HEADER);
00855   if (-1 ==
00856       handle_to_global_data->read (subdiv_data, (long) header.in_buffer_size))
00857     {
00858       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00859                        BufferName, __FILE__, __LINE__);
00860       return (status = CMS_INTERNAL_ACCESS_ERROR);
00861     }
00862 
00863   return (status);
00864 }
00865 
00866 /* It takes several steps to perform a peek  operation when queuing is enabled. */
00867 /* 1. Read the queuing_header at the beginning of the buffer. */
00868 /* 2. Get the head of the queue from the queuing_header. */
00869 /* 3. Read the message header at the head of the queue. */
00870 /* 4. Check the id and size. */
00871 /* 5. If id and size are ok, */
00872  /* then read the message */
00873 CMS_STATUS
00874 CMS::queue_peek_raw ()
00875 {
00876   long queuing_header_offset;
00877 
00878   /* Produce error message if process does not have permission to read. */
00879   if (!read_permission_flag)
00880     {
00881       rcs_print_error ("CMS: %s was not configured to read %s\n",
00882                        ProcessName, BufferName);
00883       return (status = CMS_PERMISSIONS_ERROR);
00884     }
00885 
00886   /* Check that the handle to global memory exists. */
00887   if (NULL == handle_to_global_data)
00888     {
00889       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00890       return (status = CMS_INTERNAL_ACCESS_ERROR);
00891     }
00892 
00893   /* Store the original offset so that we can update the header later. */
00894   queuing_header_offset = handle_to_global_data->offset;
00895 
00896   /* Read the queuing header for the buffer. */
00897   if (-1 == handle_to_global_data->read (&queuing_header,
00898                                          sizeof (CMS_QUEUING_HEADER)))
00899     {
00900       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00901                        BufferName, __FILE__, __LINE__);
00902       return (status = CMS_INTERNAL_ACCESS_ERROR);
00903     }
00904 
00905   /* Check to see if there are any unread messages. */
00906   if (queuing_header.queue_length == 0)
00907     {
00908       return (status = CMS_READ_OLD);
00909     }
00910 
00911   /* Read the header for the message. */
00912   handle_to_global_data->offset += queuing_header.head;
00913   if (-1 == handle_to_global_data->read (&header, sizeof (CMS_HEADER)))
00914     {
00915       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00916                        BufferName, __FILE__, __LINE__);
00917       return (status = CMS_INTERNAL_ACCESS_ERROR);
00918     }
00919 
00920   /* Check the size of the message. */
00921   if (header.in_buffer_size > max_message_size)
00922     {
00923       rcs_print_error
00924         ("CMS:(%s) Message size of %ld exceeds maximum of %ld\n", BufferName,
00925          header.in_buffer_size, max_message_size);
00926       return (status = CMS_INTERNAL_ACCESS_ERROR);
00927     }
00928 
00929   /* Read the message. */
00930   handle_to_global_data->offset += sizeof (CMS_HEADER);
00931   if (-1 ==
00932       handle_to_global_data->read (subdiv_data, (long) header.in_buffer_size))
00933     {
00934       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00935                        BufferName, __FILE__, __LINE__);
00936       return (status = CMS_INTERNAL_ACCESS_ERROR);
00937     }
00938 
00939   /* Check_id so that debug variables for messages missed can be set. */
00940   check_id (header.write_id);
00941 
00942   return (status);
00943 }
00944 
00945 
00946 /* It takes several steps to perform a peek operation on an neutral buffer.*/
00947 /* 1. Read the encoded  header. */
00948 /* 2. Decode the header. */
00949 /* 3. Check the id and size. */
00950 /* 4. If id and size are ok, then read the message. */
00951 CMS_STATUS
00952 CMS::peek_encoded ()
00953 {
00954   /* Produce error message if process does not have permission to read. */
00955   if (!read_permission_flag)
00956     {
00957       rcs_print_error ("CMS: %s was not configured to read %s\n",
00958                        ProcessName, BufferName);
00959       return (status = CMS_PERMISSIONS_ERROR);
00960     }
00961 
00962 
00963   /* Check that the handle to the global memory object exists. */
00964   if (NULL == handle_to_global_data)
00965     {
00966       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
00967       return (status = CMS_INTERNAL_ACCESS_ERROR);
00968     }
00969 
00970   /* Read the encoded header for the message. */
00971   if (-1 == handle_to_global_data->read (encoded_header, encoded_header_size))
00972     {
00973       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
00974                        BufferName, __FILE__, __LINE__);
00975       return (status = CMS_INTERNAL_ACCESS_ERROR);
00976     }
00977 
00978   /* Decode the header and  store in header structure. */
00979   decode_header ();
00980 
00981   /* Determine if the message in the buffer is new to this process. */
00982   if (CMS_READ_OLD == check_id (header.write_id))
00983     {
00984       return (CMS_READ_OLD);    /* Don't bother reading an old message. */
00985     }
00986 
00987   /* Check the size of the message. */
00988   if (header.in_buffer_size > max_message_size)
00989     {
00990       rcs_print_error
00991         ("CMS:(%s) Message size of %ld exceeds maximum of %ld\n", BufferName,
00992          header.in_buffer_size, max_message_size);
00993       return (status = CMS_INTERNAL_ACCESS_ERROR);
00994     }
00995 
00996   /* Read the message. */
00997   handle_to_global_data->offset += encoded_header_size;
00998   if (-1 == handle_to_global_data->read (encoded_data,
00999                                          (long) header.in_buffer_size))
01000     {
01001       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01002                        BufferName, __FILE__, __LINE__);
01003       return (status = CMS_INTERNAL_ACCESS_ERROR);
01004     }
01005 
01006   return (status);
01007 }
01008 
01009 /* It takes several steps to perform a peek operation */
01010  /* when queuing is enabled on a neutral buffer. */
01011 /* 1. Read the encoded queuing_header at the beginning of the buffer. */
01012 /* 2. Decode the queuing_header for the buffer. */
01013 /* 3. Get the head of the queue from the queuing_header. */
01014 /* 4. Read the message header at the head of the queue. */
01015 /* 5. Decode the message header. */
01016 /* 6. Check the id and size. */
01017 /* 7. If id and size are ok, */
01018  /* then read the message */
01019 CMS_STATUS
01020 CMS::queue_peek_encoded ()
01021 {
01022   long queuing_header_offset;
01023 
01024   /* Produce error message if process does not have permission to read. */
01025   if (!read_permission_flag)
01026     {
01027       rcs_print_error ("CMS: %s was not configured to read %s\n",
01028                        ProcessName, BufferName);
01029       return (status = CMS_PERMISSIONS_ERROR);
01030     }
01031 
01032   /* Check that the handle to global memory exists. */
01033   if (NULL == handle_to_global_data)
01034     {
01035       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
01036       return (status = CMS_INTERNAL_ACCESS_ERROR);
01037     }
01038 
01039   /* Store the original offset so we can update the queuing header later. */
01040   queuing_header_offset = handle_to_global_data->offset;
01041 
01042   /* Read the encoded header for the buffer. */
01043   if (-1 == handle_to_global_data->read (encoded_queuing_header,
01044                                          encoded_queuing_header_size))
01045     {
01046       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01047                        BufferName, __FILE__, __LINE__);
01048       return (status = CMS_INTERNAL_ACCESS_ERROR);
01049     }
01050 
01051   /* Decode the queuing header and store in the queuing_header structrure. */
01052   decode_queuing_header ();
01053 
01054   /* Determine if there are any unread messages. */
01055   if (queuing_header.queue_length == 0)
01056     {
01057       return (status = CMS_READ_OLD);
01058     }
01059 
01060   /* Read the header for the message. */
01061   handle_to_global_data->offset += queuing_header.head;
01062   if (-1 == handle_to_global_data->read (encoded_header, encoded_header_size))
01063     {
01064       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01065                        BufferName, __FILE__, __LINE__);
01066       return (status = CMS_INTERNAL_ACCESS_ERROR);
01067     }
01068 
01069   /* Decode the message header and store in the header structure. */
01070   decode_header ();
01071 
01072   /* Check the size of the message. */
01073   if (header.in_buffer_size > max_message_size)
01074     {
01075       rcs_print_error
01076         ("CMS:(%s) Message size of %ld exceeds maximum of %ld\n", BufferName,
01077          header.in_buffer_size, max_message_size);
01078       return (status = CMS_INTERNAL_ACCESS_ERROR);
01079     }
01080 
01081   /* Read the message. */
01082   handle_to_global_data->offset += encoded_header_size;
01083   if (-1 ==
01084       handle_to_global_data->read (encoded_data,
01085                                    (long) header.in_buffer_size))
01086     {
01087       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01088                        BufferName, __FILE__, __LINE__);
01089       return (status = CMS_INTERNAL_ACCESS_ERROR);
01090     }
01091 
01092   /* Check_id so that debug variables for messages missed can be set. */
01093   check_id (header.write_id);
01094 
01095   return (status);
01096 }
01097 
01098 /* It takes several steps to perform a write operation. */
01099 /* 1. Read the header. */
01100 /* 2. Update the header. */
01101 /* 3. Write the message. */
01102 /* Parameters: */
01103  /* user_data - pointer to where the user stored the message to be written. */
01104 CMS_STATUS
01105 CMS::write_raw (void *user_data)
01106 {
01107   long current_header_in_buffer_size;
01108 
01109   /* Produce error message if process does not have permission to read. */
01110   if (!write_permission_flag)
01111 
01112     {
01113       rcs_print_error ("CMS: %s was not configured to write to %s\n",
01114                        ProcessName, BufferName);
01115       return (status = CMS_PERMISSIONS_ERROR);
01116     }
01117 
01118   /* Store the header information to use after reading the header in the buffer. */
01119   current_header_in_buffer_size = header.in_buffer_size;
01120 
01121   /* Check that handle to global memory object exists. */
01122   if (NULL == handle_to_global_data)
01123     {
01124       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
01125       return (status = CMS_INTERNAL_ACCESS_ERROR);
01126     }
01127 
01128 #if 0
01129   /* Check that buffer is large enough for this message. */
01130   if (header.in_buffer_size > max_message_size)
01131     {
01132       rcs_print_error
01133         ("CMS:(%s) Message size %ld exceeds maximum for this buffer of %ld.\n",
01134          BufferName, header.in_buffer_size, max_message_size);
01135       return (status = CMS_INTERNAL_ACCESS_ERROR);
01136     }
01137 #endif
01138 
01139   /* Read the header. */
01140   if (-1 == handle_to_global_data->read (&header, sizeof (header)))
01141     {
01142       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01143                        BufferName, __FILE__, __LINE__);
01144       return (status = CMS_INTERNAL_ACCESS_ERROR);
01145     }
01146 
01147   /* Update the header. */
01148   header.was_read = 0;
01149   header.write_id++;
01150   if (split_buffer)
01151     {
01152       if ((header.write_id & 1) != toggle_bit)
01153         {
01154           header.write_id++;
01155         }
01156     }
01157   header.in_buffer_size = current_header_in_buffer_size;
01158   if (-1 == handle_to_global_data->write (&header, sizeof (header)))
01159     {
01160       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01161                        BufferName, __FILE__, __LINE__);
01162       return (status = CMS_INTERNAL_ACCESS_ERROR);
01163     }
01164 
01165   /* Write the message. */
01166   if (!disable_final_write_raw_for_dma)
01167     {
01168       handle_to_global_data->offset += sizeof (CMS_HEADER);
01169       if (-1 == handle_to_global_data->write (user_data,
01170                                               (long)
01171                                               current_header_in_buffer_size))
01172         {
01173           rcs_print_error
01174             ("CMS:(%s) Error writing %ld bytes to global memory at offset %X\n (See  %s line %d.)\n",
01175              BufferName, header.in_buffer_size, user_data, __FILE__,
01176              __LINE__);
01177           return (status = CMS_INTERNAL_ACCESS_ERROR);
01178         }
01179     }
01180 
01181   return (status = CMS_WRITE_OK);
01182 }
01183 
01184 /* It takes several steps to perform a write operation when queuing is enabled. */
01185 /* 1. Read the qeuing header at the begining of the buffer. */
01186 /* 2. Determine the amount of free space and where the next node can be placed.*/
01187 /* 3. Set up message header from info in the queuing header. */
01188 /* 4. Write the message header and message  at the tail of the queue. */
01189 /* 5. Update the queuing header. */
01190 /* Parameters: */
01191  /* user_data - pointer to where the user stored the message to be written. */
01192 CMS_STATUS
01193 CMS::queue_write_raw (void *user_data)
01194 {
01195   CMS_HEADER current_header;
01196   long free_space;
01197   long queuing_header_offset;
01198   long original_tail;
01199 
01200   /* Produce error message if process does not have permission to read. */
01201   if (!write_permission_flag)
01202 
01203     {
01204       rcs_print_error ("CMS: %s was not configured to write to %s\n",
01205                        ProcessName, BufferName);
01206       return (status = CMS_PERMISSIONS_ERROR);
01207     }
01208 
01209 
01210   /* Store the header information to use after reading the header in the buffer. */
01211   current_header = header;
01212 
01213   /* Check that the handle to the global memory object exists. */
01214   if (NULL == handle_to_global_data)
01215     {
01216       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
01217       return (status = CMS_INTERNAL_ACCESS_ERROR);
01218     }
01219 
01220   /* Store the original offset so we can update the queuing header later. */
01221   queuing_header_offset = handle_to_global_data->offset;
01222 
01223   /* Read the queuing header at the beginning of the buffer. */
01224   if (-1 == handle_to_global_data->read (&queuing_header,
01225                                          sizeof (CMS_QUEUING_HEADER)))
01226     {
01227       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01228                        BufferName, __FILE__, __LINE__);
01229       return (status = CMS_INTERNAL_ACCESS_ERROR);
01230     }
01231 
01232   /* Determine amount of free space and location of next node. */
01233   if (queuing_header.tail == queuing_header.head)
01234     {
01235       if (queuing_header.queue_length == 0)
01236         {
01237           queuing_header.head = queuing_header.tail =
01238             sizeof (CMS_QUEUING_HEADER);
01239           queuing_header.queue_length = 0;
01240           queuing_header.end_queue_space = queuing_header.tail;
01241           free_space = handle_to_global_data->size
01242             - sizeof (CMS_QUEUING_HEADER) - queuing_header_offset;
01243         }
01244       else
01245         {
01246           free_space = 0;
01247         }
01248     }
01249   else if (handle_to_global_data->size - queuing_header.tail >
01250            ((long) (header.in_buffer_size + sizeof (CMS_HEADER))) &&
01251            queuing_header.tail > queuing_header.head)
01252     {
01253       free_space = handle_to_global_data->size - queuing_header.tail;
01254     }
01255   else if (queuing_header.tail < queuing_header.head)
01256     {
01257       free_space = queuing_header.tail - queuing_header.head;
01258     }
01259   else if (queuing_header.head >
01260            ((long) (queuing_header_offset + sizeof (CMS_QUEUING_HEADER) +
01261                     (header.in_buffer_size + sizeof (CMS_HEADER)))))
01262     {
01263       queuing_header.end_queue_space = queuing_header.tail;
01264       queuing_header.tail = sizeof (CMS_QUEUING_HEADER);
01265       free_space =
01266         queuing_header.head - sizeof (CMS_QUEUING_HEADER) -
01267         queuing_header_offset;
01268     }
01269   else
01270     {
01271       free_space = 0;
01272     }
01273   if (cms_print_queue_free_space)
01274     {
01275       rcs_print ("queue free space = %d\n", free_space);
01276     }
01277 
01278   /* Check to see if there is enough free space. */
01279   if (free_space < ((long) (header.in_buffer_size + sizeof (CMS_HEADER))))
01280     {
01281       if (cms_print_queue_free_space || cms_print_queue_full_messages)
01282         {
01283           rcs_print_error ("CMS: %s message queue is full.\n", BufferName);
01284           rcs_print_error
01285             ("(continued) CMS: Message requires %ld bytes but only %ld bytes are left.\n",
01286              header.in_buffer_size, free_space);
01287         }
01288       return (status = CMS_QUEUE_FULL);
01289     }
01290 
01291   /* Store original tail so we'll know where to store the message. */
01292   original_tail = queuing_header.tail;
01293 
01294   /* Update the queuing header. */
01295   queuing_header.tail += header.in_buffer_size + sizeof (CMS_HEADER);
01296   queuing_header.queue_length++;
01297   queuing_header.write_id++;
01298   if (queuing_header.end_queue_space < queuing_header.tail)
01299     {
01300       queuing_header.end_queue_space = queuing_header.tail;
01301     }
01302   if (-1 == handle_to_global_data->write (&queuing_header,
01303                                           sizeof (CMS_QUEUING_HEADER)))
01304     {
01305       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01306                        BufferName, __FILE__, __LINE__);
01307       return (status = CMS_INTERNAL_ACCESS_ERROR);
01308     }
01309 
01310   /* Setup message header. */
01311   header.write_id = queuing_header.write_id;
01312   header.was_read = 0;
01313   header.in_buffer_size = current_header.in_buffer_size;
01314 
01315   /* Write the message header. */
01316   handle_to_global_data->offset += original_tail;
01317   if (-1 == handle_to_global_data->write (&header, sizeof (header)))
01318     {
01319       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01320                        BufferName, __FILE__, __LINE__);
01321       return (status = CMS_INTERNAL_ACCESS_ERROR);
01322     }
01323 
01324   /* Write the message. */
01325   handle_to_global_data->offset += sizeof (CMS_HEADER);
01326   if (-1 == handle_to_global_data->write (user_data,
01327                                           (long) header.in_buffer_size))
01328     {
01329       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01330                        BufferName, __FILE__, __LINE__);
01331       return (status = CMS_INTERNAL_ACCESS_ERROR);
01332     }
01333 
01334   return (status = CMS_WRITE_OK);
01335 }
01336 
01337 /* It takes several steps to perform a write operation on a neutral buffer. */
01338 /* 1. Read the header. */
01339 /* 2. Update the header. */
01340 /* 3. Write the message. */
01341 CMS_STATUS
01342 CMS::write_encoded ()
01343 {
01344   CMS_HEADER current_header;
01345 
01346   /* Produce error message if process does not have permission to read. */
01347   if (!write_permission_flag)
01348 
01349     {
01350       rcs_print_error ("CMS: %s was not configured to write to %s\n",
01351                        ProcessName, BufferName);
01352       return (status = CMS_PERMISSIONS_ERROR);
01353     }
01354 
01355 
01356   /* Store the header information to use after reading the header in the buffer. */
01357   current_header = header;
01358 
01359   /* Check that handle to global memory object exists. */
01360   if (NULL == handle_to_global_data)
01361     {
01362       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
01363       return (status = CMS_INTERNAL_ACCESS_ERROR);
01364     }
01365 
01366   /* Check that buffer is large enough for this message. */
01367   if (header.in_buffer_size > max_message_size)
01368     {
01369       rcs_print_error
01370         ("CMS:(%s) Message size %ld exceeds maximum for this buffer of %ld.\n",
01371          BufferName, header.in_buffer_size, max_message_size);
01372       return (status = CMS_INTERNAL_ACCESS_ERROR);
01373     }
01374 
01375   /* Read the header. */
01376   if (-1 == handle_to_global_data->read (encoded_header, encoded_header_size))
01377     {
01378       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01379                        BufferName, __FILE__, __LINE__);
01380       return (status = CMS_INTERNAL_ACCESS_ERROR);
01381     }
01382   /* Decode the header and store in the header structure. */
01383   decode_header ();
01384 
01385   /* Update the header. */
01386   header.was_read = 0;
01387   header.write_id++;
01388   if (split_buffer && (header.write_id % 2) != toggle_bit)
01389     {
01390       header.write_id++;
01391     }
01392   header.in_buffer_size = current_header.in_buffer_size;
01393   encode_header ();
01394   if (-1 ==
01395       handle_to_global_data->write (encoded_header, encoded_header_size))
01396     {
01397       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01398                        BufferName, __FILE__, __LINE__);
01399       return (status = CMS_INTERNAL_ACCESS_ERROR);
01400     }
01401 
01402   /* Write the message. */
01403   handle_to_global_data->offset += encoded_header_size;
01404   if (-1 == handle_to_global_data->write (encoded_data,
01405                                           (long) header.in_buffer_size))
01406     {
01407       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01408                        BufferName, __FILE__, __LINE__);
01409       return (status = CMS_INTERNAL_ACCESS_ERROR);
01410     }
01411 
01412   return (status = CMS_WRITE_OK);
01413 }
01414 
01415 /* It takes several steps to perform a write operation when queuing is enabled. */
01416 /* 1. Read the qeuing header at the begining of the buffer. */
01417 /* 2. Determine the amount of free space and where the next node can be placed.*/
01418 /* 3. Set up message header from info in the queuing header. */
01419 /* 4. Write the message header and message  at the tail of the queue. */
01420 /* 5. Update the queuing header. */
01421 /* Parameters: */
01422  /* user_data - pointer to where the user stored the message to be written. */
01423 CMS_STATUS
01424 CMS::queue_write_encoded ()
01425 {
01426   CMS_HEADER current_header;
01427   long free_space;
01428   long queuing_header_offset;
01429   long original_tail;
01430 
01431   /* Produce error message if process does not have permission to read. */
01432   if (!write_permission_flag)
01433 
01434     {
01435       rcs_print_error ("CMS: %s was not configured to write to %s\n",
01436                        ProcessName, BufferName);
01437       return (status = CMS_PERMISSIONS_ERROR);
01438     }
01439 
01440 
01441   /* Store the header information to use after reading the header in the buffer. */
01442   current_header = header;
01443 
01444   /* Check that the handle to the global memory object exists. */
01445   if (NULL == handle_to_global_data)
01446     {
01447       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
01448       return (status = CMS_INTERNAL_ACCESS_ERROR);
01449     }
01450 
01451   /* Store the original offset so we can update the queuing header later. */
01452   queuing_header_offset = handle_to_global_data->offset;
01453 
01454   /* Read the queuing header at the beginning of the buffer. */
01455   if (-1 == handle_to_global_data->read (encoded_queuing_header,
01456                                          encoded_queuing_header_size))
01457     {
01458       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01459                        BufferName, __FILE__, __LINE__);
01460       return (status = CMS_INTERNAL_ACCESS_ERROR);
01461     }
01462   /* Decode queuing header and store in queuing_header structure. */
01463   decode_queuing_header ();
01464 
01465   /* Determine amount of free space and location of next node. */
01466   if (queuing_header.tail == queuing_header.head)
01467     {
01468       if (queuing_header.queue_length == 0)
01469         {
01470           queuing_header.head = queuing_header.tail =
01471             encoded_queuing_header_size;
01472           queuing_header.queue_length = 0;
01473           queuing_header.end_queue_space = queuing_header.tail;
01474           free_space = handle_to_global_data->size
01475             - encoded_queuing_header_size - queuing_header_offset;
01476         }
01477       else
01478         {
01479           free_space = 0;
01480         }
01481     }
01482   else if (handle_to_global_data->size - queuing_header.tail >
01483            header.in_buffer_size + encoded_header_size &&
01484            queuing_header.tail > queuing_header.head)
01485     {
01486       free_space = handle_to_global_data->size - queuing_header.tail;
01487     }
01488   else if (queuing_header.tail < queuing_header.head)
01489     {
01490       free_space = queuing_header.tail - queuing_header.head;
01491     }
01492   else if (queuing_header.head >
01493            encoded_header_size + queuing_header_offset +
01494            header.in_buffer_size + encoded_queuing_header_size)
01495     {
01496       queuing_header.end_queue_space = queuing_header.tail;
01497       queuing_header.tail = encoded_queuing_header_size;
01498       free_space =
01499         queuing_header.head - encoded_queuing_header_size -
01500         queuing_header_offset;
01501     }
01502   else
01503     {
01504       free_space = 0;
01505     }
01506 
01507   if (cms_print_queue_free_space)
01508     {
01509       rcs_print ("queue free space = %d\n", free_space);
01510     }
01511 
01512   /* Check to see if there is enough free space. */
01513   if (free_space < header.in_buffer_size + encoded_header_size)
01514     {
01515       if (cms_print_queue_free_space || cms_print_queue_full_messages)
01516         {
01517           rcs_print_error ("CMS: %s message queue is full.\n", BufferName);
01518           rcs_print_error
01519             ("(continued) CMS: Message requires %ld bytes but only %ld bytes are left.\n",
01520              header.in_buffer_size, free_space);
01521         }
01522       return (status = CMS_QUEUE_FULL);
01523     }
01524 
01525   /* Store original tail so we'll know where to store the message. */
01526   original_tail = queuing_header.tail;
01527 
01528   /* Update the queuing header. */
01529   queuing_header.tail += header.in_buffer_size + encoded_header_size;
01530   queuing_header.queue_length++;
01531   queuing_header.write_id++;
01532   if (queuing_header.end_queue_space < queuing_header.tail)
01533     {
01534       queuing_header.end_queue_space = queuing_header.tail;
01535     }
01536   encode_queuing_header ();
01537   if (-1 == handle_to_global_data->write (encoded_queuing_header,
01538                                           encoded_queuing_header_size))
01539     {
01540       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01541                        BufferName, __FILE__, __LINE__);
01542       return (status = CMS_INTERNAL_ACCESS_ERROR);
01543     }
01544 
01545   /* Setup message header. */
01546   header.write_id = queuing_header.write_id;
01547   header.was_read = 0;
01548   header.in_buffer_size = current_header.in_buffer_size;
01549 
01550   /* Re-encode the  header. */
01551   encode_header ();
01552 
01553   /* Write the message header. */
01554   handle_to_global_data->offset += original_tail;
01555   if (-1 ==
01556       handle_to_global_data->write (encoded_header, encoded_header_size))
01557     {
01558       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01559                        BufferName, __FILE__, __LINE__);
01560       return (status = CMS_INTERNAL_ACCESS_ERROR);
01561     }
01562 
01563   /* Write the message. */
01564   handle_to_global_data->offset += encoded_header_size;
01565   if (-1 == handle_to_global_data->write (encoded_data,
01566                                           (long) header.in_buffer_size))
01567     {
01568       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01569                        BufferName, __FILE__, __LINE__);
01570       return (status = CMS_INTERNAL_ACCESS_ERROR);
01571     }
01572 
01573   return (status = CMS_WRITE_OK);
01574 }
01575 
01576 /* It takes several steps to perform a write operation. */
01577 /* 1. Read the header. */
01578 /* 2. Update the header. */
01579 /* 3. Write the message. */
01580 /* Parameters: */
01581  /* user_data - pointer to where the user stored the message to be written. */
01582 CMS_STATUS
01583 CMS::write_if_read_raw (void *user_data)
01584 {
01585   CMS_HEADER current_header;
01586 
01587   /* Produce error message if process does not have permission to read. */
01588   if (!write_permission_flag)
01589 
01590     {
01591       rcs_print_error ("CMS: %s was not configured to write to %s\n",
01592                        ProcessName, BufferName);
01593       return (status = CMS_PERMISSIONS_ERROR);
01594     }
01595 
01596   /* Store the header information to use after reading the header in the buffer. */
01597   current_header = header;
01598 
01599   /* Check that handle to global memory object exists. */
01600   if (NULL == handle_to_global_data)
01601     {
01602       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
01603       return (status = CMS_INTERNAL_ACCESS_ERROR);
01604     }
01605 
01606   /* Check that buffer is large enough for this message. */
01607   if (header.in_buffer_size > max_message_size)
01608     {
01609       rcs_print_error
01610         ("CMS:(%s) Message size %ld exceeds maximum for this buffer of %ld.\n",
01611          BufferName, header.in_buffer_size, max_message_size);
01612       return (status = CMS_INTERNAL_ACCESS_ERROR);
01613     }
01614 
01615   /* Read the header. */
01616   if (-1 == handle_to_global_data->read (&header, sizeof (header)))
01617     {
01618       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01619                        BufferName, __FILE__, __LINE__);
01620       return (status = CMS_INTERNAL_ACCESS_ERROR);
01621     }
01622 
01623   /* Check if the message in the buffer has been read. */
01624   if (!header.was_read)
01625     {
01626       return (status = CMS_WRITE_WAS_BLOCKED);
01627     }
01628 
01629   /* Update the header. */
01630   header.was_read = 0;
01631   header.write_id++;
01632   if (split_buffer && (header.write_id % 2) != toggle_bit)
01633     {
01634       header.write_id++;
01635     }
01636   header.in_buffer_size = current_header.in_buffer_size;
01637   if (-1 == handle_to_global_data->write (&header, sizeof (header)))
01638     {
01639       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01640                        BufferName, __FILE__, __LINE__);
01641       return (status = CMS_INTERNAL_ACCESS_ERROR);
01642     }
01643 
01644   /* Write the message. */
01645   handle_to_global_data->offset += sizeof (CMS_HEADER);
01646   if (-1 == handle_to_global_data->write (user_data,
01647                                           (long) header.in_buffer_size))
01648     {
01649       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01650                        BufferName, __FILE__, __LINE__);
01651       return (status = CMS_INTERNAL_ACCESS_ERROR);
01652     }
01653 
01654   return (status = CMS_WRITE_OK);
01655 }
01656 
01657 /* It takes several steps to perform a write operation when queuing is enabled. */
01658 /* 1. Read the qeuing header at the begining of the buffer. */
01659 /* 2. Determine the amount of free space and where the next node can be placed.*/
01660 /* 3. Set up message header from info in the queuing header. */
01661 /* 4. Write the message header and message  at the tail of the queue. */
01662 /* 5. Update the queuing header. */
01663 /* Parameters: */
01664  /* user_data - pointer to where the user stored the message to be written. */
01665 CMS_STATUS
01666 CMS::queue_write_if_read_raw (void *user_data)
01667 {
01668   CMS_HEADER current_header;
01669   long free_space;
01670   long queuing_header_offset;
01671   long original_tail;
01672 
01673   /* Produce error message if process does not have permission to read. */
01674   if (!write_permission_flag)
01675 
01676     {
01677       rcs_print_error ("CMS: %s was not configured to write to %s\n",
01678                        ProcessName, BufferName);
01679       return (status = CMS_PERMISSIONS_ERROR);
01680     }
01681 
01682 
01683 
01684   /* Store the header information to use after reading the header in the buffer. */
01685   current_header = header;
01686 
01687   /* Check that the handle to the global memory object exists. */
01688   if (NULL == handle_to_global_data)
01689     {
01690       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
01691       return (status = CMS_INTERNAL_ACCESS_ERROR);
01692     }
01693 
01694   /* Store the original offset so we can update the queuing header later. */
01695   queuing_header_offset = handle_to_global_data->offset;
01696 
01697   /* Read the queuing header at the beginning of the buffer. */
01698   if (-1 == handle_to_global_data->read (&queuing_header,
01699                                          sizeof (CMS_QUEUING_HEADER)))
01700     {
01701       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01702                        BufferName, __FILE__, __LINE__);
01703       return (status = CMS_INTERNAL_ACCESS_ERROR);
01704     }
01705 
01706   /* Check if all the messages in the buffer have been read. */
01707   if (0 != queuing_header.queue_length)
01708     {
01709       return (status = CMS_WRITE_WAS_BLOCKED);
01710     }
01711 
01712   /* Determine amount of free space and location of next node. */
01713   if (queuing_header.tail == queuing_header.head)
01714     {
01715       if (queuing_header.queue_length == 0)
01716         {
01717           queuing_header.head = queuing_header.tail =
01718             sizeof (CMS_QUEUING_HEADER);
01719           queuing_header.queue_length = 0;
01720           queuing_header.end_queue_space = queuing_header.tail;
01721           free_space = handle_to_global_data->size
01722             - sizeof (CMS_QUEUING_HEADER) - queuing_header_offset;
01723         }
01724       else
01725         {
01726           free_space = 0;
01727         }
01728     }
01729   else if (handle_to_global_data->size - queuing_header.tail >
01730            ((long) (header.in_buffer_size + sizeof (CMS_HEADER))) &&
01731            queuing_header.tail > queuing_header.head)
01732     {
01733       free_space = handle_to_global_data->size - queuing_header.tail;
01734     }
01735   else if (queuing_header.tail < queuing_header.head)
01736     {
01737       free_space = queuing_header.tail - queuing_header.head;
01738     }
01739   else if (queuing_header.head >
01740            ((long) (queuing_header_offset + sizeof (CMS_QUEUING_HEADER) +
01741                     header.in_buffer_size + sizeof (CMS_HEADER))))
01742     {
01743       queuing_header.end_queue_space = queuing_header.tail;
01744       queuing_header.tail = sizeof (CMS_QUEUING_HEADER);
01745       free_space =
01746         queuing_header.head - sizeof (CMS_QUEUING_HEADER) -
01747         queuing_header_offset;
01748     }
01749   else
01750     {
01751       free_space = 0;
01752     }
01753 
01754   if (cms_print_queue_free_space)
01755     {
01756       rcs_print ("queue free space = %d\n", free_space);
01757     }
01758 
01759   /* Check to see if there is enough free space. */
01760   if (free_space < ((long) (header.in_buffer_size + sizeof (CMS_HEADER))))
01761     {
01762       if (cms_print_queue_free_space || cms_print_queue_full_messages)
01763         {
01764           rcs_print_error ("CMS: %s message queue is full.\n", BufferName);
01765           rcs_print_error
01766             ("(continued) CMS: Message requires %ld bytes but only %ld bytes are left.\n",
01767              header.in_buffer_size, free_space);
01768         }
01769       return (status = CMS_QUEUE_FULL);
01770     }
01771 
01772   /* Store original tail so we'll know where to store the message. */
01773   original_tail = queuing_header.tail;
01774 
01775   /* Update the queuing header. */
01776   queuing_header.tail += header.in_buffer_size + sizeof (CMS_HEADER);
01777   queuing_header.queue_length++;
01778   queuing_header.write_id++;
01779   if (queuing_header.end_queue_space < queuing_header.tail)
01780     {
01781       queuing_header.end_queue_space = queuing_header.tail;
01782     }
01783   if (-1 == handle_to_global_data->write (&queuing_header,
01784                                           sizeof (CMS_QUEUING_HEADER)))
01785     {
01786       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01787                        BufferName, __FILE__, __LINE__);
01788       return (status = CMS_INTERNAL_ACCESS_ERROR);
01789     }
01790 
01791   /* Setup message header. */
01792   header.write_id = queuing_header.write_id;
01793   header.was_read = 0;
01794   header.in_buffer_size = current_header.in_buffer_size;
01795 
01796   /* Write the message header. */
01797   handle_to_global_data->offset += original_tail;
01798   if (-1 == handle_to_global_data->write (&header, sizeof (header)))
01799     {
01800       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01801                        BufferName, __FILE__, __LINE__);
01802       return (status = CMS_INTERNAL_ACCESS_ERROR);
01803     }
01804 
01805   /* Write the message. */
01806   handle_to_global_data->offset += sizeof (CMS_HEADER);
01807   if (-1 == handle_to_global_data->write (user_data,
01808                                           (long) header.in_buffer_size))
01809     {
01810       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01811                        BufferName, __FILE__, __LINE__);
01812       return (status = CMS_INTERNAL_ACCESS_ERROR);
01813     }
01814 
01815   return (status = CMS_WRITE_OK);
01816 }
01817 
01818 /* It takes several steps to perform a write operation on a neutral buffer. */
01819 /* 1. Read the header. */
01820 /* 2. Update the header. */
01821 /* 3. Write the message. */
01822 CMS_STATUS
01823 CMS::write_if_read_encoded ()
01824 {
01825   CMS_HEADER current_header;
01826 
01827   /* Produce error message if process does not have permission to read. */
01828   if (!write_permission_flag)
01829 
01830     {
01831       rcs_print_error ("CMS: %s was not configured to write to %s\n",
01832                        ProcessName, BufferName);
01833       return (status = CMS_PERMISSIONS_ERROR);
01834     }
01835 
01836   /* Store the header information to use after reading the header in the buffer. */
01837   current_header = header;
01838 
01839   /* Check that handle to global memory object exists. */
01840   if (NULL == handle_to_global_data)
01841     {
01842       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
01843       return (status = CMS_INTERNAL_ACCESS_ERROR);
01844     }
01845 
01846   /* Check that buffer is large enough for this message. */
01847   if (header.in_buffer_size > max_message_size)
01848     {
01849       rcs_print_error
01850         ("CMS:(%s) Message size %ld exceeds maximum for this buffer of %ld.\n",
01851          BufferName, header.in_buffer_size, max_message_size);
01852       return (status = CMS_INTERNAL_ACCESS_ERROR);
01853     }
01854 
01855   /* Read the header. */
01856   if (-1 == handle_to_global_data->read (encoded_header, encoded_header_size))
01857     {
01858       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01859                        BufferName, __FILE__, __LINE__);
01860       return (status = CMS_INTERNAL_ACCESS_ERROR);
01861     }
01862   /* Decode the header and store in the header structure. */
01863   decode_header ();
01864 
01865   /* Check if the message in the buffer has been read. */
01866   if (!header.was_read)
01867     {
01868       return (status = CMS_WRITE_WAS_BLOCKED);
01869     }
01870 
01871   /* Update the header. */
01872   header.was_read = 0;
01873   header.write_id++;
01874   if (split_buffer && (header.write_id % 2) != toggle_bit)
01875     {
01876       header.write_id++;
01877     }
01878   header.in_buffer_size = current_header.in_buffer_size;
01879   encode_header ();
01880   if (-1 ==
01881       handle_to_global_data->write (encoded_header, encoded_header_size))
01882     {
01883       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01884                        BufferName, __FILE__, __LINE__);
01885       return (status = CMS_INTERNAL_ACCESS_ERROR);
01886     }
01887 
01888   /* Write the message. */
01889   handle_to_global_data->offset += encoded_header_size;
01890   if (-1 == handle_to_global_data->write (encoded_data,
01891                                           (long) header.in_buffer_size))
01892     {
01893       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
01894                        BufferName, __FILE__, __LINE__);
01895       return (status = CMS_INTERNAL_ACCESS_ERROR);
01896     }
01897 
01898   return (status = CMS_WRITE_OK);
01899 }
01900 
01901 /* It takes several steps to perform a write operation when queuing is enabled. */
01902 /* 1. Read the qeuing header at the begining of the buffer. */
01903 /* 2. Determine the amount of free space and where the next node can be placed.*/
01904 /* 3. Set up message header from info in the queuing header. */
01905 /* 4. Write the message header and message  at the tail of the queue. */
01906 /* 5. Update the queuing header. */
01907 /* Parameters: */
01908  /* user_data - pointer to where the user stored the message to be written. */
01909 CMS_STATUS
01910 CMS::queue_write_if_read_encoded ()
01911 {
01912   CMS_HEADER current_header;
01913   long free_space;
01914   long queuing_header_offset;
01915   long original_tail;
01916 
01917   /* Produce warning message if process does not have permission to read. */
01918   if (!write_permission_flag)
01919 
01920     {
01921       rcs_print_error ("CMS: %s was not configured to write to %s\n",
01922                        ProcessName, BufferName);
01923       return (status = CMS_PERMISSIONS_ERROR);
01924     }
01925 
01926   /* Store the header information to use after reading the header in the buffer. */
01927   current_header = header;
01928 
01929   /* Check that the handle to the global memory object exists. */
01930   if (NULL == handle_to_global_data)
01931     {
01932       rcs_print_error ("CMS: handle_to_global_data is NULL.\n");
01933       return (status = CMS_INTERNAL_ACCESS_ERROR);
01934     }
01935 
01936   /* Store the original offset so we can update the queuing header later. */
01937   queuing_header_offset = handle_to_global_data->offset;
01938 
01939   /* Read the queuing header at the beginning of the buffer. */
01940   if (-1 == handle_to_global_data->read (encoded_queuing_header,
01941                                          encoded_queuing_header_size))
01942     {
01943       rcs_print_error ("CMS:(%s) Error reading from global memory at %s:%d\n",
01944                        BufferName, __FILE__, __LINE__);
01945       return (status = CMS_INTERNAL_ACCESS_ERROR);
01946     }
01947   /* Decode queuing header and store in queuing_header structure. */
01948   decode_queuing_header ();
01949 
01950   /* Check if all the messages in the buffer have been read. */
01951   if (0 != queuing_header.queue_length)
01952     {
01953       return (status = CMS_WRITE_WAS_BLOCKED);
01954     }
01955   /* Determine amount of free space and location of next node. */
01956   if (queuing_header.tail == queuing_header.head)
01957     {
01958       if (queuing_header.queue_length == 0)
01959         {
01960           queuing_header.head = queuing_header.tail =
01961             encoded_queuing_header_size;
01962           queuing_header.queue_length = 0;
01963           queuing_header.end_queue_space = queuing_header.tail;
01964           free_space = handle_to_global_data->size
01965             - encoded_queuing_header_size - queuing_header_offset;
01966         }
01967       else
01968         {
01969           free_space = 0;
01970         }
01971     }
01972   else if (handle_to_global_data->size - queuing_header.tail >
01973            header.in_buffer_size + encoded_header_size &&
01974            queuing_header.tail > queuing_header.head)
01975     {
01976       free_space = handle_to_global_data->size - queuing_header.tail;
01977     }
01978   else if (queuing_header.tail < queuing_header.head)
01979     {
01980       free_space = queuing_header.tail - queuing_header.head;
01981     }
01982   else if (queuing_header.head >
01983            encoded_header_size + queuing_header_offset +
01984            header.in_buffer_size + encoded_queuing_header_size)
01985     {
01986       queuing_header.end_queue_space = queuing_header.tail;
01987       queuing_header.tail = encoded_queuing_header_size;
01988       free_space =
01989         queuing_header.head - encoded_queuing_header_size -
01990         queuing_header_offset;
01991     }
01992   else
01993     {
01994       free_space = 0;
01995     }
01996 
01997   if (cms_print_queue_free_space)
01998     {
01999       rcs_print ("queue free space = %d\n", free_space);
02000     }
02001 
02002   /* Check to see if there is enough free space. */
02003   if (free_space < header.in_buffer_size + encoded_header_size)
02004     {
02005       if (cms_print_queue_free_space || cms_print_queue_full_messages)
02006         {
02007           rcs_print_error ("CMS: %s message queue is full.\n", BufferName);
02008           rcs_print_error
02009             ("(continued) CMS: Message requires %ld bytes but only %ld bytes are left.\n",
02010              header.in_buffer_size, free_space);
02011         }
02012       return (status = CMS_QUEUE_FULL);
02013     }
02014 
02015   /* Store original tail so we'll know where to store the message. */
02016   original_tail = queuing_header.tail;
02017 
02018   /* Update the queuing header. */
02019   queuing_header.tail += header.in_buffer_size + encoded_header_size;
02020   queuing_header.queue_length++;
02021   queuing_header.write_id++;
02022   if (queuing_header.end_queue_space < queuing_header.tail)
02023     {
02024       queuing_header.end_queue_space = queuing_header.tail;
02025     }
02026   encode_queuing_header ();
02027   if (-1 == handle_to_global_data->write (encoded_queuing_header,
02028                                           encoded_queuing_header_size))
02029     {
02030       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
02031                        BufferName, __FILE__, __LINE__);
02032       return (status = CMS_INTERNAL_ACCESS_ERROR);
02033     }
02034 
02035   /* Setup message header. */
02036   header.write_id = queuing_header.write_id;
02037   header.was_read = 0;
02038   header.in_buffer_size = current_header.in_buffer_size;
02039 
02040   /* Re-encode the  header. */
02041   encode_header ();
02042 
02043   /* Write the message header. */
02044   handle_to_global_data->offset += original_tail;
02045   if (-1 ==
02046       handle_to_global_data->write (encoded_header, encoded_header_size))
02047     {
02048       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
02049                        BufferName, __FILE__, __LINE__);
02050       return (status = CMS_INTERNAL_ACCESS_ERROR);
02051     }
02052 
02053   /* Write the message. */
02054   handle_to_global_data->offset += encoded_header_size;
02055   if (-1 == handle_to_global_data->write (encoded_data,
02056                                           (long) header.in_buffer_size))
02057     {
02058       rcs_print_error ("CMS:(%s) Error writing to global memory at %s:%d\n",
02059                        BufferName, __FILE__, __LINE__);
02060       return (status = CMS_INTERNAL_ACCESS_ERROR);
02061     }
02062 
02063   return (status = CMS_WRITE_OK);
02064 }

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