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 / serverInfo.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  13.7 KB  |  569 lines

  1. /*
  2.  *   $RCSfile: serverInfo.C,v $  
  3.  *   $Revision: 1.2 $  
  4.  *   $Date: 1996/05/04 23:51:44 $      
  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 "Pool.h"
  39. #include "HashTable.h"
  40. #include "resources.h"
  41.  
  42. #include "sysdefs.h"
  43. #include "ess.h"
  44. #include "checking.h"
  45. #include "trace.h"
  46. #include "error.h"
  47. #include "list.h"
  48. #include "tid.h"
  49. #include "io.h"
  50. #include "lock.h"
  51. #include "object.h"
  52. #include "msgdefs.h"
  53. #include "host.h"
  54. #include "bf.h"
  55. #include "serverinfo.h"
  56. #include "bitvec.h"
  57. #include "link.h"
  58. #include "chunk.h"
  59. #include "lsn.h"
  60. #include "loginfo.h"
  61. #include "volume.h"
  62. #include "softwareVersion.h"
  63. #include "bf_extfuncs.h"
  64. #include "msg_funcs.h"
  65. #include "msg_globals.h"
  66. #include "sm_globals.h"
  67. #include "util_funcs.h"
  68. #include "sm_state.h"
  69. #include "trans_funcs.h"
  70. #include "trans_globals.h"
  71. #include "io_extfuncs.h"
  72. #include "clog.h"
  73. #include "bf_macro.h"
  74. #include "clog_extfuncs.h"
  75.  
  76. class SOCKADDRCLASS {
  77. public:
  78.     SOCKADDR    p;
  79.     int            hashFunc() const {
  80. #if defined(hpux) || defined(sgi) || defined(linux)
  81.                 return (int)(this->p.sin_addr.s_addr);
  82. #else
  83.                 return (int)(this->p.sin_addr.S_un.S_addr);
  84. #endif
  85.     }
  86.     BOOL         equalFunc (SOCKADDRCLASS *other) const { 
  87.                 return ((this->p.sin_family == other->p.sin_family) &&
  88.                     (this->p.sin_port == other->p.sin_port) &&
  89. #if defined(hpux) || defined(sgi) || defined(linux)
  90.                     (this->p.sin_addr.s_addr == other->p.sin_addr.s_addr));
  91. #else
  92.                     (this->p.sin_addr.S_un.S_addr == other->p.sin_addr.S_un.S_addr));
  93. #endif
  94.     }
  95. };
  96.  
  97. void 
  98. SERVERINFO::Init() {
  99.     this->ReInit();
  100.     initializeListElement(&(this->list), this);
  101.     initializeList(&(this->transList));
  102.     bzero(this->hostName, sizeof(this->hostName));
  103.     this->hostEnt = NULL;
  104.     bzero(this->name, sizeof(this->name));
  105.     bzero((char *)&(this->connectAddr), sizeof(this->connectAddr));
  106. }
  107.  
  108. /* ReInit called on pool->Get() -- AND explicitly on disconnect! 
  109. * We NEVER put serverInfos back into the pool!
  110. */
  111. void 
  112. SERVERINFO:: ReInit() {
  113.     if(this->logInfo.tailBuffer != NULL) {
  114.         /* true only when server disconnects an inactive client after a timeout.
  115.         SM_ASSERT(LEVEL_1, (PAGE_IS_CLEAN(this->logInfo.tailBuffer)));
  116.         */
  117.         this->logInfo.tailBuffer = NULL;
  118.     }
  119.     this->socket = NOSOCKET;
  120.  
  121.     /*
  122.      *    old way: this->flags = SERV_NOTCONNECTED;
  123.     *   new way: turn off all flags except SERV_CONTACTED_IN_PAST
  124.     */
  125.     this->flags = (this->flags & SERV_CONTACTED_IN_PAST) | SERV_NOTCONNECTED;
  126.                 /* SERV_NOTCONNECTED is zero so this is for readability only */
  127.  
  128.     this->logInfo.writeGroup = NULL;
  129.     this->logInfo.page2size = 0;
  130.     this->nMounted = 0;
  131. }
  132.  
  133. SOCKADDRCLASS *
  134. SERVERINFO::keylocation(int unique, SOCKADDRCLASS **unused) {
  135.     TRPRINT(TR_TRANS, TR_LEVEL_1, (" ", unique));
  136.     SM_ASSERT(LEVEL_1, 
  137.         (unique == SERVERINFO_POOL) || (unique == SERVERINFO_TABLE));
  138.     return (SOCKADDRCLASS *)&(this->connectAddr);
  139. }
  140. LISTELEMENT *
  141. SERVERINFO::listlocation(int unique) {
  142.     TRPRINT(TR_TRANS, TR_LEVEL_1, (" ", unique));
  143.     SM_ASSERT(LEVEL_1, 
  144.         (unique == SERVERINFO_POOL) || (unique == SERVERINFO_TABLE));
  145.     return &(this->list);
  146. }
  147. BOOL    
  148. SERVERINFO::Dump(FILE *f) {
  149.     fprintf(f, "SERVERINFO for %s.%d (%s)\n",
  150.         inet_ntoa(this->connectAddr.sin_addr),
  151.         this->connectAddr.sin_port,
  152.         this->hostName);
  153.     fprintf(f, "\tsocket %d, %d volumes mounted, flags 0x%x\n",
  154.         this->socket, this->nMounted, this->flags);
  155.     fprintf(f, "\tloggingEnabled %d\n", 
  156.         this->flags & SERV_LOGGING_INITD);
  157.     return FALSE;
  158. }
  159.  
  160.  
  161. Pool<SERVERINFO> *serverInfoPool = NULL;
  162. HashTable<SOCKADDRCLASS,SERVERINFO> *serverInfoTable = NULL;
  163. static char localHostName[MAX_HOSTNAME];
  164.  
  165. static BOOL initialized = FALSE;
  166.  
  167. int
  168. initServerInfo() 
  169. {
  170.     if(initialized)
  171.         return esmNOERROR;
  172.  
  173.     TRACE(TR_MSG, TR_LEVEL_1);
  174.  
  175.     serverInfoPool = new Pool<SERVERINFO> ( "serverInfo", 
  176.         SERVERINFO_POOL, ServerInfoPoolSize, POOL_NOMORE_GETMORE );
  177.     if(serverInfoPool == NULL) {
  178.         SM_ERROR(TYPE_SYS, esmMALLOCFAILED);
  179.         return esmFAILURE;
  180.     }
  181.     /*
  182.     serverInfoPool->Stats(stderr);
  183.     */
  184.  
  185.     serverInfoTable = new HashTable<SOCKADDRCLASS,SERVERINFO> (
  186.         "serverInfoTable", SERVERINFO_TABLE, ServerInfoTableSize);
  187.     if(serverInfoTable == NULL) {
  188.         SM_ERROR(TYPE_SYS, esmMALLOCFAILED);
  189.         return esmFAILURE;
  190.     }
  191.     /*
  192.     serverInfoTable->Stats(stderr);
  193.     */
  194.  
  195.     if (gethostname(localHostName, MAX_HOSTNAME) < 0)    {
  196.         SM_ERROR(TYPE_SYS, errno);
  197.         return esmFAILURE;
  198.     }
  199.     initialized = TRUE;
  200.     return esmNOERROR;
  201. }
  202.  
  203. void
  204. shutServerInfo() 
  205. {
  206.     if( !initialized )
  207.         return;
  208.  
  209.     TRACE(TR_MSG, TR_LEVEL_1);
  210.  
  211.     serverForEach(1, detectedDisconnect, 0,0,0 );
  212.  
  213.     delete serverInfoPool;
  214.     delete serverInfoTable;
  215.  
  216.     initialized = FALSE;
  217. }
  218.  
  219.  SERVERINFO*
  220. getServerInfo (
  221.     char*    serverHost,     /* name of the machine running sm_server     */
  222.     char*    serverName   /* /etc/services port name of the sm_server*/
  223. )
  224. {
  225.     SERVENT                *_servent= NULL;
  226.     HOSTENT                *_hostent= NULL;
  227.     SERVERINFO            *serverInfo;
  228.     SOCKADDRCLASS        sockaddrc;
  229.     short                port;
  230.  
  231.     TRACE(TR_MSG, TR_LEVEL_1);
  232.  
  233.     if(!initialized)
  234.         initServerInfo();
  235.  
  236.     if (serverHost == NULL) {
  237.         serverHost = localHostName;
  238.     }
  239.     if(strlen(serverHost)>MAX_HOSTNAME) {
  240.         serverHost[MAX_HOSTNAME-1] = '\0';
  241.     }
  242.     TRPRINT(TR_MSG, TR_LEVEL_1, ("looking up host:%s", serverHost));
  243.  
  244.     if(isalpha(*serverHost)) {
  245.         if ((_hostent = gethostbyname(serverHost)) == NULL)    {
  246.             SM_ERROR(TYPE_USER, esmUNKNOWNHOSTNAME);
  247.             return NULL;
  248.         }
  249.         bcopy( _hostent->h_addr, 
  250.             (char *) &(sockaddrc.p.sin_addr), _hostent->h_length );
  251.         TRPRINT(TR_MSG, TR_LEVEL_1, ("official host name:%s", _hostent->h_name));
  252.     } else {
  253. #if defined(hpux) || defined(sgi) || defined(linux)
  254.         sockaddrc.p.sin_addr.s_addr  = inet_addr(serverHost); 
  255.             /* returned net byte order*/
  256.         if( sockaddrc.p.sin_addr.s_addr == (unsigned long) -1) {
  257.             SM_ERROR(TYPE_USER, esmUNKNOWNHOSTNAME);
  258.             return NULL;
  259.         }
  260. #else
  261.         sockaddrc.p.sin_addr.S_un.S_addr  = inet_addr(serverHost); 
  262.             /* returned net byte order*/
  263.         if( sockaddrc.p.sin_addr.S_un.S_addr == (unsigned long) -1) {
  264.             SM_ERROR(TYPE_USER, esmUNKNOWNHOSTNAME);
  265.             return NULL;
  266.         }
  267. #endif 
  268.     }
  269.  
  270.     /*
  271.      * get the server name, using the one provided, or if that's null,
  272.      * the default, SERVENAME
  273.      */
  274.     if (!strcmp(serverName,"")) 
  275.         strcpy(serverName, SERVENAME);
  276.  
  277.     if(strlen(serverName)>MAX_HOSTNAME) {
  278.         serverName[MAX_HOSTNAME-1] = '\0';
  279.     }
  280.  
  281.     /*
  282.      * If the server name starts with digit, treat it as a port number.
  283.      */
  284.     if(isdigit(serverName[0])) {
  285.         port = htons((short)(atoi(serverName)));
  286.         if(port==0) {
  287.             SM_ERROR(TYPE_LOG, EADDRNOTAVAIL);
  288.             return NULL;
  289.         }
  290.     } else if ((_servent = getservbyname(serverName, "tcp")) != NULL) {
  291.         TRPRINT(TR_MSG, TR_LEVEL_1, 
  292.             ("port:%d", ntohs(_servent->s_port)));
  293.         /* returned in network byte order */
  294.         port = (short) _servent->s_port;
  295.     } else {
  296.         SM_ERROR(TYPE_LOG, EADDRNOTAVAIL);
  297.         return NULL;
  298.     }
  299.  
  300.     /*
  301.      *    initialize the address
  302.      */
  303.     sockaddrc.p.sin_family = AF_INET;
  304.     sockaddrc.p.sin_port = port;
  305.     TRPRINT(TR_MSG, TR_LEVEL_1, ("host inet addr:%s:%d",
  306.         inet_ntoa(*(struct in_addr *)&sockaddrc.p.sin_addr),
  307.         ntohs(sockaddrc.p.sin_port)));
  308.  
  309.     serverInfo = serverInfoTable->Find(&sockaddrc);
  310.     if(serverInfo==NULL) {
  311.         serverInfo = serverInfoPool->Get();
  312.         strcpy(serverInfo->hostName, serverHost);
  313.         strcpy(serverInfo->name,     serverName);
  314.         serverInfo->connectAddr = sockaddrc.p;
  315.         serverInfoTable->Insert(serverInfo);
  316.     }
  317.     return serverInfo;
  318. }
  319.  
  320.  
  321.  SERVERINFO *
  322. findServerInfo (
  323.     VOLID    volid 
  324. )
  325. {
  326.     /* TODO: have THIS fun put the volrec into the SM_State -
  327.      * need to pass in a ptr  so we aren't doing so many
  328.      * find volid lookups
  329.      */
  330.     VOLREC    *volRec;
  331.  
  332.     TRPRINT(TR_IO, TR_LEVEL_1, ("volid:%d", volid));
  333.  
  334.     volRec = io_FindVolId(volid);
  335.     if (volRec == NULL) {
  336.         return NULL;
  337.     }
  338.  
  339.     return volRec->serverInfo;
  340. }
  341.  
  342.  int
  343. server_beginTrans(
  344.     SERVERINFO     *serverInfo,
  345.     TID            *tidp
  346. )
  347. {
  348.     TID    tid; 
  349.     int error;
  350.  
  351.     TRACE(TR_SM|TR_TRANS, TR_LEVEL_1);
  352.  
  353.     INIT_SMSTATE(&SM_State);
  354.  
  355.     if ( !(serverInfo->flags & SERV_ESTAB) ) {
  356.         SM_ERROR(TYPE_USER, esmNOTCONNECTED);
  357.     }
  358.     if (error = beginTrans(serverInfo, &tid))    {
  359.         return error;
  360.     } 
  361.  
  362.     /*
  363.      *    First we need to set the server state so that lower
  364.      *    levels know what server to talk to.  This is a temporary
  365.      *    hack to do this.
  366.      */
  367.     SM_State.serverInfo = serverInfo;
  368.     SM_State.serverTid = tid;
  369.     SM_State.logInfo = &(serverInfo->logInfo);
  370.     SM_State.logLevel = LOG_ALL;
  371.     SM_State.defaultLogLevel = LOG_ALL;
  372.  
  373.     /* set up logging for the transaction */
  374.     if (error = (int)clog_BeginTransaction()) {
  375.         return error ;
  376.     }
  377.     if(tidp)
  378.         *tidp = tid;
  379.     return esmNOERROR;
  380. }
  381.  
  382. void
  383. serverForEach(
  384.     int     nargs,
  385.     void *func, 
  386.     void *arg1,
  387.     void *arg2, 
  388.     void *arg3,
  389.     void *arg4,
  390.     void *arg5,
  391.     void *arg6
  392. )
  393. {
  394.     SM_ASSERT(LEVEL_1, (nargs <= 7));
  395.     SM_ASSERT(LEVEL_1, (nargs >= 1));
  396.  
  397. #ifdef __GNUC__
  398.     serverInfoTable->ForEach(nargs,func,arg1,arg2,arg3,arg4,arg5,arg6);
  399. #else __GNUC__
  400.     serverInfoTable->ForEach(nargs,(FOREACHFUNC)func,arg1,
  401.         arg2,arg3,arg4,arg5,arg6);
  402. #endif __GNUC__
  403. }
  404.  
  405. int
  406. msg_initClient (
  407.     SERVERINFO    *serverInfo,
  408.     BOOL        isAdminClient
  409. )
  410. {
  411.  
  412.     if ( !(serverInfo->flags & SERV_ESTAB) ) {
  413.         MESSAGE        message;
  414.  
  415.         /* get initialization information from the server */
  416.         message.header.type = INIT_CLIENT;
  417.         message.header.replyRequested = TRUE;
  418.  
  419.         message.body.init.slottedPage2size = SLOTTED_PAGE2SIZE ;
  420.         message.body.init.lgPage2size = LG_PAGE2SIZE ;
  421.         message.body.init.lgDataPage2size = LGDATA_PAGE2SIZE ;
  422.         message.body.init.btreePage2size = BTREE_PAGE2SIZE ;
  423.         message.body.init.indexDescPage2size = INDEXDESC_PAGE2SIZE ;
  424.         message.body.init.minPage2size = MIN_PAGE2SIZE ;
  425.         message.body.init.softwareVersion = SOFTWARE_VERSION ;
  426.  
  427.         if (callServer(serverInfo, &message, NULL, 0 ) != esmNOERROR)       {
  428.             extern int PrintUser;
  429.             if( PrintUser) {
  430.                 if( message.body.init.softwareVersion != SOFTWARE_VERSION) {
  431.                     fprintf(stderr, 
  432.                     "Client version is incompatible with server version.\n");
  433.                 } else {
  434.                     fprintf(stderr, 
  435.                     "Client page sizes do not match server page sizes\n");
  436.                 }
  437.             }
  438.             return esmFAILURE;
  439.         }
  440.         serverInfo->logInfo.volid         = message.body.init.volid;
  441.         serverInfo->logInfo.page2size   = message.body.init.logPage2size;
  442.         serverInfo->logInfo.initLRCisLSN  = message.body.init.initLRCisLSN;
  443.         serverInfo->flags |= SERV_ESTAB;
  444.  
  445.         if(serverInfo->logInfo.tailBuffer != NULL) {
  446.             SM_ASSERT(LEVEL_1, 
  447.             (serverInfo->logInfo.tailBuffer->hashList.hashPid.volid 
  448.             == serverInfo->logInfo.volid));
  449.         }
  450.     }
  451.  
  452.     if(isAdminClient) 
  453.         return esmNOERROR;
  454.  
  455.     if (clog_serverInitialize(serverInfo)) {
  456.         return esmFAILURE;
  457.     }
  458.  
  459.     return esmNOERROR;
  460. }
  461.  
  462.  int
  463. server_connectInit (
  464.     SERVERINFO    *serverInfo,
  465.     BOOL    isAdminClient    /* true if this is called from an administrative
  466.                                 function (has no log or buffer pool) */
  467. )
  468. {
  469.  
  470.     if (!(serverInfo->flags & SERV_CONNECTED)) {
  471.         if (connectServer(serverInfo) == esmFAILURE)    {
  472.             return esmFAILURE;
  473.         }
  474.     }
  475.     if (msg_initClient(serverInfo,isAdminClient) != esmNOERROR ) {
  476.         detectedDisconnect(serverInfo);
  477.         return esmFAILURE;
  478.     }
  479.     return esmNOERROR;
  480. }
  481.  
  482.  int
  483. connectInit (
  484.     char    *serverHost,    /* name of machine running sm_server     */
  485.     char    *serverName,        /* /etc/services name of the sm_server    */
  486.     BOOL    isAdminClient    /* true if this is called from an administrative
  487.                                 function (has no log or buffer pool) */
  488. )
  489. {
  490.     SERVERINFO    *serverInfo;
  491.  
  492.     serverInfo = getServerInfo( serverHost, serverName);
  493.  
  494.     if (serverInfo->flags & SERV_ESTAB) {
  495.         SM_ERROR(TYPE_USER, esmALREADYCONNECTED);
  496.         return esmFAILURE;
  497.     }
  498.     return server_connectInit(serverInfo, isAdminClient);
  499. }
  500.  
  501. #ifdef JUNK
  502. /* not used at the moment */
  503. static BOOL
  504. helperfunc(
  505.     TRANSREC     *transRec,
  506.     SERVERINFO    *serverInfo
  507. {
  508.     SERVERTRANSREC *stl;
  509.  
  510.     for(stl = (SERVERTRANSREC *)FIRST_LIST_ELEMENT(&(transRec->participants));
  511.         stl!=NULL;
  512.         stl = (SERVERTRANSREC *)NEXT_LIST_ELEMENT(&(stl->participants)) ) {
  513.  
  514.         if( stl->serverInfo == serverInfo )  {
  515.             CLIENT_ABORT_TRANS(transRec);
  516.         }
  517.     }
  518.     return FALSE;
  519. }
  520. #endif JUNK
  521.  
  522.  BOOL
  523. detectedDisconnect (
  524.     SERVERINFO    *serverInfo
  525. )
  526. {
  527.     if(serverInfo->flags & SERV_CONNECTED) {
  528.         SM_ASSERT(LEVEL_1, (serverInfo->socket != NOSOCKET));
  529.         serverAbortedTrans(serverInfo, NULL_TID);
  530.         serverDied((void *) serverInfo);
  531.     
  532.         /* record the reason for the abort */
  533.         sm_reason = esmNOTCONNECTED;
  534.  
  535.         if (close(serverInfo->socket) != 0) {
  536.             SM_ERROR(TYPE_LOG, errno);
  537.         }
  538.  
  539.         /*
  540.          *    clear the link
  541.          */
  542.         clearLink(&(Links[serverInfo->socket]));
  543.     } else {
  544.         SM_ASSERT(LEVEL_1, (serverInfo->socket == NOSOCKET));
  545.         SM_ASSERT(LEVEL_1, 
  546.         ((serverInfo->flags & ~SERV_CONTACTED_IN_PAST) == SERV_NOTCONNECTED));
  547.     }
  548.  
  549.     /* only if the group was opened: */
  550.     if( serverInfo->logInfo.writeGroup != NULL )
  551.         (void) bf_DiscardGroup(serverInfo->logInfo.writeGroup);
  552.  
  553.     serverInfo->ReInit();
  554.  
  555.     return FALSE; /* used in forEach, so it must be BOOL */
  556. }
  557.  
  558. int
  559. initMask()
  560. {
  561.     int        i;
  562.  
  563.     for (i = 0; i < BVL; i++)   {
  564.         SelectMask.bv_data[i] = 0;
  565.     }
  566.     return esmNOERROR;
  567. }
  568.