home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / client / msg / receive.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  6.5 KB  |  280 lines

  1. /*
  2.  *   $RCSfile: receive.c,v $  
  3.  *   $Revision: 1.1.1.1 $  
  4.  *   $Date: 1996/05/04 21:55:27 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37.  
  38. #include "sysdefs.h"
  39. #include "ess.h"
  40. #include "checking.h"
  41. #include "trace.h"
  42. #include "error.h"
  43. #include "list.h"
  44. #include "tid.h"
  45. #include "io.h"
  46. #include "lock.h"
  47. #include "object.h"
  48. #include "msgdefs.h"
  49. #include "host.h"
  50. #include "trans.h"
  51. #include "bf.h"
  52. #include "lsn.h"
  53. #include "loginfo.h"
  54. #include "serverinfo.h"
  55. #include "link.h"
  56. #include "bitvec.h"
  57. #include "msg_globals.h"
  58. #include "sm_globals.h"
  59. #include "trans_globals.h"
  60. #include "msg_funcs.h"
  61.  
  62.  
  63. extern int        errno;
  64.  
  65.  
  66.  
  67.  
  68.  int
  69. receive (
  70.  
  71.     SERVERINFO    *serverInfo,
  72.     char        *buffer,
  73.     int            readBytes 
  74. )
  75. {
  76.  
  77.     int            numReady;
  78.     int            readyIndex;
  79.     int            bytesRead;
  80.     int            remainBytes;
  81.     int            totalBytes;
  82.     LINK        *link;
  83.     SERVERINFO    *readyServerInfo;
  84.  
  85.  
  86.     TRPRINT(TR_MSG, TR_LEVEL_1, ("reading bytes:%d", readBytes));
  87.  
  88.     if (readBytes == 0) 
  89.         return esmNOERROR;
  90.  
  91.     /*
  92.      *    do a select on all the servers - this is necessary 
  93.      *    because unless the client detects broken connections
  94.      *    and does a close on its side, servers will not be able
  95.      *    to get their ports upon recovery
  96.      */
  97.     for (;;) {
  98. select_again:
  99.  
  100.         ReadMask = SelectMask;
  101. #ifdef hpux
  102.         numReady = select(SelectBits, (int*)&ReadMask, NULL, NULL, NULL);
  103. #else
  104.         numReady = select(SelectBits, (fd_set*)&ReadMask, NULL, NULL, NULL);
  105. #endif
  106.  
  107.         if (numReady<0) {
  108.             /*
  109.              *  See if the error was caused by an interupted select.
  110.              */
  111.             if (errno == EINTR) {
  112.                 /* Just try select again */
  113.                 numReady = 0;
  114.                 TRPRINT(TR_MSG|TR_DISK, TR_LEVEL_2,
  115.                          ("select interrupted: restart"));
  116.                 goto select_again;
  117.             } else {
  118.                 /*
  119.                  *    TODO: clean this up
  120.                  */
  121.                 SM_ERROR(TYPE_CRASH, errno);
  122.             }
  123.         }
  124.     
  125.         while ((readyIndex = selectReceive( &ReadMask )) >= 0) {
  126.     
  127.             /*
  128.              *    remove this link from the readmask so that
  129.              *    we'll not visit it until the next select
  130.              */
  131.             bic( &ReadMask, readyIndex );
  132.             link = &(Links[readyIndex]);
  133.     
  134.             if (readyIndex != serverInfo->socket) {
  135.     
  136.                 /*
  137.                  *    get the serverInfo for this link
  138.                  */
  139.                 readyServerInfo = link->serverInfo;
  140.     
  141.                 SM_ASSERT(LEVEL_1, (readyServerInfo != NULL));
  142.     
  143.                 /*
  144.                  *    try to read from this link
  145.                  *    use the given buffer since we'll overwrite it when
  146.                  *    the real response comes back
  147.                  */
  148.                 for (totalBytes = 0; totalBytes < 1; totalBytes += bytesRead) {
  149.     
  150.                     bytesRead = read(readyServerInfo->socket, buffer,1);
  151.     
  152.                     /*
  153.                      *    make sure that no bytes were received since
  154.                      *    we are not expecting a message from this server
  155.                      *    NB: this may change if callbacks are introduced
  156.                      */
  157.                     SM_ASSERT(LEVEL_1, (bytesRead <= 0));
  158.     
  159.                     if (bytesRead < 0)    {
  160.                         SM_ERROR(TYPE_LOG, errno);
  161.     
  162.                         switch(errno) {
  163.                         case ENETDOWN: 
  164.                         case ENETUNREACH: 
  165.                         case ENETRESET:
  166.                         case ECONNABORTED:
  167.                         case ECONNRESET:
  168.         
  169.                             (void) detectedDisconnect(readyServerInfo);
  170.  
  171.                             /*
  172.                              *    exit the loop
  173.                              */
  174.                             totalBytes = 1;
  175.     
  176.                             break;
  177.         
  178.                         case EINTR:
  179.                         
  180.                             /* 
  181.                              * The read was interupted, no bytes were 
  182.                              * read. Start the read over by continuing.
  183.                              */
  184.                             continue;
  185.     
  186.                         default:
  187.                             /* unsupported error */
  188.                             break;
  189.                         }
  190.                     } else {
  191.                         (void) detectedDisconnect(readyServerInfo);
  192.  
  193.                         /*
  194.                          *    exit the loop
  195.                          */
  196.                         totalBytes = 1;
  197.                     }
  198.                 }
  199.             } else {
  200.     
  201.                 /*
  202.                  *    read the messages, repeatedly perhaps
  203.                  */
  204.                 for (totalBytes = 0; totalBytes < readBytes; totalBytes += bytesRead)    {
  205.     
  206.                     /*
  207.                      *    calculate remaining bytes
  208.                      */
  209.                     remainBytes = readBytes - totalBytes;
  210.                     TRPRINT(TR_MSG, TR_LEVEL_1, ("want to read:%d", remainBytes));
  211.     
  212.                     /*
  213.                      *    read the remaining bytes
  214.                      */
  215.                     bytesRead = read(serverInfo->socket, buffer + totalBytes, (int) remainBytes);
  216.     
  217.                     TRPRINT(TR_MSG, TR_LEVEL_1, ("bytesRead:%d", bytesRead));
  218.     
  219.                     /*
  220.                      *    check to see if the read succeeded
  221.                      */
  222.                     if (bytesRead < 0)    {
  223.                         SM_ERROR(TYPE_LOG, errno);
  224.     
  225.                         switch(errno) {
  226.                         case ENETDOWN: 
  227.                         case ENETUNREACH: 
  228.                         case ENETRESET:
  229.                         case ECONNABORTED:
  230.                         case ECONNRESET:
  231.             
  232.                             (void) detectedDisconnect(serverInfo);
  233.         
  234.                             break;
  235.         
  236.                         case EINTR:
  237.                         
  238.                             /* 
  239.                              * The read was interupted, no bytes were read. 
  240.                              * Start the read over by continuing.
  241.                              */
  242.                             bytesRead = 0;
  243.                             continue;
  244.         
  245.                         default:
  246.                             /* unsupported error */
  247.                             break;
  248.                         }
  249.  
  250.                         return esmFAILURE;
  251.                     }
  252.     
  253.                     /*
  254.                      *    If no bytes were read, then the server (or connection) died
  255.                      */
  256.                     if (bytesRead == 0)    {
  257.                 
  258.                         SM_ERROR(TYPE_LOG, esmSERVERDIED);
  259.                         (void) detectedDisconnect(serverInfo);
  260.                         return esmFAILURE;
  261.                     }
  262.                     if ( (bytesRead < remainBytes) && !(serverInfo->flags & SERV_ESTAB) ){
  263.                         /* We did not get all we asked for, and we were in the 
  264.                          * process of doing an INIT_CLIENT, so we had better check
  265.                          * for an error in the protocol version
  266.                          */
  267.                         if( *((SHORT_MAGIC *) buffer) != MESSAGE_VERSION ) {
  268.                             return esmPROTOCOLVERSION;
  269.                         }
  270.                     }
  271.                 }
  272.  
  273.                 incPages(readBytes, RECEIVED, readBytes==sizeof(MESSAGE)?TRUE:FALSE); /* grot */
  274.  
  275.                 return esmNOERROR;
  276.             }
  277.         }
  278.     }
  279. }
  280.