windows-server-ping-20060216
[openafs.git] / src / WINNT / afsd / cm_server.c
index a9102d9..e94e348 100644 (file)
@@ -29,6 +29,106 @@ osi_rwlock_t cm_serverLock;
 
 cm_server_t *cm_allServersp;
 
+void 
+cm_PingServer(cm_server_t *tsp)
+{
+    long code;
+    int wasDown = 0;
+    cm_conn_t *connp;
+    struct rx_connection * callp;
+    long secs;
+    long usecs;
+    Capabilities caps = {0, 0};
+    char hoststr[16];
+
+    lock_ObtainMutex(&tsp->mx);
+    if (tsp->flags & CM_SERVERFLAG_PINGING) {
+       tsp->waitCount++;
+       osi_SleepM((LONG_PTR)tsp, &tsp->mx);
+       lock_ObtainMutex(&tsp->mx);
+       tsp->waitCount--;
+       if (tsp->waitCount == 0)
+           tsp->flags &= ~CM_SERVERFLAG_PINGING;
+       else 
+           osi_Wakeup((LONG_PTR)tsp);
+       lock_ReleaseMutex(&tsp->mx);
+       return;
+    }
+    tsp->flags |= CM_SERVERFLAG_PINGING;
+    wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
+    afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr);
+    lock_ReleaseMutex(&tsp->mx);
+
+    code = cm_ConnByServer(tsp, cm_rootUserp, &connp);
+    if (code == 0) {
+       /* now call the appropriate ping call.  Drop the timeout if
+       * the server is known to be down, so that we don't waste a
+       * lot of time retiming out down servers.
+       */
+
+       osi_Log4(afsd_logp, "cm_PingServer server %s (%s) was %s with caps 0x%x",
+                 osi_LogSaveString(afsd_logp, hoststr), 
+                 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
+                 wasDown ? "down" : "up",
+                 tsp->capabilities);
+
+       if (wasDown)
+           rx_SetConnDeadTime(connp->callp, 10);
+       if (tsp->type == CM_SERVER_VLDB) {
+           code = VL_ProbeServer(connp->callp);
+       }
+       else {
+           /* file server */
+           callp = cm_GetRxConn(connp);
+           code = RXAFS_GetCapabilities(callp, &caps);
+           if (code == RXGEN_OPCODE)
+               code = RXAFS_GetTime(callp, &secs, &usecs);
+           rx_PutConnection(callp);
+       }
+       if (wasDown)
+           rx_SetConnDeadTime(connp->callp, ConnDeadtimeout);
+       cm_PutConn(connp);
+    }  /* got an unauthenticated connection to this server */
+
+    lock_ObtainMutex(&tsp->mx);
+    if (code >= 0) {
+       /* mark server as up */
+       tsp->flags &= ~CM_SERVERFLAG_DOWN;
+
+       /* we currently handle 32-bits of capabilities */
+       if (caps.Capabilities_len > 0) {
+           tsp->capabilities = caps.Capabilities_val[0];
+           free(caps.Capabilities_val);
+           caps.Capabilities_len = 0;
+           caps.Capabilities_val = 0;
+       } else {
+           tsp->capabilities = 0;
+       }
+
+       osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is up with caps 0x%x",
+                 osi_LogSaveString(afsd_logp, hoststr), 
+                 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
+                 tsp->capabilities);
+    } else {
+       /* mark server as down */
+       tsp->flags |= CM_SERVERFLAG_DOWN;
+       if (code != VRESTARTING)
+           cm_ForceNewConnections(tsp);
+
+       osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is down with caps 0x%x",
+                 osi_LogSaveString(afsd_logp, hoststr), 
+                 tsp->type == CM_SERVER_VLDB ? "vldb" : "file",
+                 tsp->capabilities);
+    }
+
+    if (tsp->waitCount == 0)
+       tsp->flags &= ~CM_SERVERFLAG_PINGING;
+    else 
+       osi_Wakeup((LONG_PTR)tsp);
+    lock_ReleaseMutex(&tsp->mx);
+}
+
+
 void cm_CheckServers(long flags, cm_cell_t *cellp)
 {
     /* ping all file servers, up or down, with unauthenticated connection,
@@ -36,15 +136,8 @@ void cm_CheckServers(long flags, cm_cell_t *cellp)
      * Also, ping down VLDBs.
      */
     cm_server_t *tsp;
-    long code;
-    long secs;
-    long usecs;
     int doPing;
-    int serverType;
-    unsigned long now;
-    int wasDown;
-    cm_conn_t *connp;
-    struct rx_connection * callp;
+    int isDown;
 
     lock_ObtainWrite(&cm_serverLock);
     for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
@@ -54,21 +147,16 @@ void cm_CheckServers(long flags, cm_cell_t *cellp)
         /* now process the server */
         lock_ObtainMutex(&tsp->mx);
 
-        /* what time is it? */
-        now = osi_Time();
-
-        serverType = tsp->type;
         doPing = 0;
-        wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
+        isDown = tsp->flags & CM_SERVERFLAG_DOWN;
 
         /* only do the ping if the cell matches the requested cell, or we're
          * matching all cells (cellp == NULL), and if we've requested to ping
          * this type of {up, down} servers.
          */
         if ((cellp == NULL || cellp == tsp->cellp) &&
-             ((wasDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) ||
-               (!wasDown && (flags & CM_FLAG_CHECKUPSERVERS)))) {
-
+             ((isDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) ||
+               (!isDown && (flags & CM_FLAG_CHECKUPSERVERS)))) {
             doPing = 1;
         }      /* we're supposed to check this up/down server */
         lock_ReleaseMutex(&tsp->mx);
@@ -76,40 +164,8 @@ void cm_CheckServers(long flags, cm_cell_t *cellp)
         /* at this point, we've adjusted the server state, so do the ping and
          * adjust things.
          */
-        if (doPing) {
-            code = cm_ConnByServer(tsp, cm_rootUserp, &connp);
-            if (code == 0) {
-                /* now call the appropriate ping call.  Drop the timeout if
-                 * the server is known to be down, so that we don't waste a
-                 * lot of time retiming out down servers.
-                 */
-                if (wasDown)
-                    rx_SetConnDeadTime(connp->callp, 10);
-                if (serverType == CM_SERVER_VLDB) {
-                    code = VL_ProbeServer(connp->callp);
-                }
-                else {
-                    /* file server */
-                    callp = cm_GetRxConn(connp);
-                    code = RXAFS_GetTime(callp, &secs, &usecs);
-                    rx_PutConnection(callp);
-                }
-                if (wasDown)
-                    rx_SetConnDeadTime(connp->callp, ConnDeadtimeout);
-                cm_PutConn(connp);
-            }  /* got an unauthenticated connection to this server */
-
-            lock_ObtainMutex(&tsp->mx);
-            if (code == 0) {
-                /* mark server as up */
-                tsp->flags &= ~CM_SERVERFLAG_DOWN;
-            }
-            else {
-                /* mark server as down */
-                tsp->flags |= CM_SERVERFLAG_DOWN;
-            }
-            lock_ReleaseMutex(&tsp->mx);
-        }
+        if (doPing) 
+           cm_PingServer(tsp);
 
         /* also, run the GC function for connections on all of the
          * server's connections.
@@ -163,62 +219,56 @@ void cm_SetServerPrefs(cm_server_t * serverp)
     unsigned long      netMask;
     int                i;
 
-    /* implement server prefs for fileservers only */
-    if ( serverp->type == CM_SERVER_FILE )
+    int cm_noIPAddr;         /* number of client network interfaces */
+    int cm_IPAddr[CM_MAXINTERFACE_ADDR];    /* client's IP address in host order */
+    int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
+    int cm_NetMtu[CM_MAXINTERFACE_ADDR];    /* client's MTU sizes */
+    int cm_NetFlags[CM_MAXINTERFACE_ADDR];  /* network flags */
+    long code;
+
+    /* get network related info */
+    cm_noIPAddr = CM_MAXINTERFACE_ADDR;
+    code = syscfg_GetIFInfo(&cm_noIPAddr,
+                           cm_IPAddr, cm_SubnetMask,
+                           cm_NetMtu, cm_NetFlags);
+
+    serverAddr = ntohl(serverp->addr.sin_addr.s_addr);
+    serverp->ipRank  = CM_IPRANK_LOW;  /* default setings */
+
+    for ( i=0; i < cm_noIPAddr; i++)
     {
-        int cm_noIPAddr;         /* number of client network interfaces */
-        int cm_IPAddr[CM_MAXINTERFACE_ADDR];    /* client's IP address in host order */
-        int cm_SubnetMask[CM_MAXINTERFACE_ADDR];/* client's subnet mask in host order*/
-        int cm_NetMtu[CM_MAXINTERFACE_ADDR];    /* client's MTU sizes */
-        int cm_NetFlags[CM_MAXINTERFACE_ADDR];  /* network flags */
-        long code;
-
-        /* get network related info */
-        cm_noIPAddr = CM_MAXINTERFACE_ADDR;
-        code = syscfg_GetIFInfo(&cm_noIPAddr,
-                                 cm_IPAddr, cm_SubnetMask,
-                                 cm_NetMtu, cm_NetFlags);
-
-        serverAddr = ntohl(serverp->addr.sin_addr.s_addr);
-        serverp->ipRank  = CM_IPRANK_LOW;      /* default setings */
-
-        for ( i=0; i < cm_noIPAddr; i++)
-        {
-            /* loop through all the client's IP address and compare
-            ** each of them against the server's IP address */
-
-            myAddr = cm_IPAddr[i];
-            if ( IN_CLASSA(myAddr) )
-                netMask = IN_CLASSA_NET;
-            else if ( IN_CLASSB(myAddr) )
-                netMask = IN_CLASSB_NET;
-            else if ( IN_CLASSC(myAddr) )
-                netMask = IN_CLASSC_NET;
-            else
-                netMask = 0;
-
-            myNet    =  myAddr & netMask;
-            mySubnet =  myAddr & cm_SubnetMask[i];
-
-            if ( (serverAddr & netMask) == myNet ) 
-            {
-                if ( (serverAddr & cm_SubnetMask[i]) == mySubnet)
-                {
-                    if ( serverAddr == myAddr ) 
-                        serverp->ipRank = min(serverp->ipRank,
-                                               CM_IPRANK_TOP);/* same machine */
-                    else serverp->ipRank = min(serverp->ipRank,
-                                                CM_IPRANK_HI); /* same subnet */
-                }
-                else serverp->ipRank = min(serverp->ipRank,CM_IPRANK_MED);
-                /* same net */
-            }  
-            /* random between 0..15*/
-            serverp->ipRank += min(serverp->ipRank, rand() % 0x000f);
-        } /* and of for loop */
-    }
-    else 
-        serverp->ipRank = 10000 + (rand() % 0x00ff); /* VL server */
+       /* loop through all the client's IP address and compare
+       ** each of them against the server's IP address */
+
+       myAddr = cm_IPAddr[i];
+       if ( IN_CLASSA(myAddr) )
+           netMask = IN_CLASSA_NET;
+       else if ( IN_CLASSB(myAddr) )
+           netMask = IN_CLASSB_NET;
+       else if ( IN_CLASSC(myAddr) )
+           netMask = IN_CLASSC_NET;
+       else
+           netMask = 0;
+
+       myNet    =  myAddr & netMask;
+       mySubnet =  myAddr & cm_SubnetMask[i];
+
+       if ( (serverAddr & netMask) == myNet ) 
+       {
+           if ( (serverAddr & cm_SubnetMask[i]) == mySubnet)
+           {
+               if ( serverAddr == myAddr ) 
+                   serverp->ipRank = min(serverp->ipRank,
+                                          CM_IPRANK_TOP);/* same machine */
+               else serverp->ipRank = min(serverp->ipRank,
+                                           CM_IPRANK_HI); /* same subnet */
+           }
+           else serverp->ipRank = min(serverp->ipRank,CM_IPRANK_MED);
+           /* same net */
+       }       
+       /* random between 0..15*/
+       serverp->ipRank += min(serverp->ipRank, rand() % 0x000f);
+    } /* and of for loop */
 }
 
 cm_server_t *cm_NewServer(struct sockaddr_in *socketp, int type, cm_cell_t *cellp) {
@@ -233,14 +283,16 @@ cm_server_t *cm_NewServer(struct sockaddr_in *socketp, int type, cm_cell_t *cell
     tsp->refCount = 1;
     lock_InitializeMutex(&tsp->mx, "cm_server_t mutex");
     tsp->addr = *socketp;
+    tsp->flags = CM_SERVERFLAG_DOWN;   /* assume down; ping will mark up if available */
 
     cm_SetServerPrefs(tsp); 
 
-    lock_ObtainWrite(&cm_serverLock); /* get server lock */
+    lock_ObtainWrite(&cm_serverLock);  /* get server lock */
     tsp->allNextp = cm_allServersp;
     cm_allServersp = tsp;
-    lock_ReleaseWrite(&cm_serverLock); /* release server lock */
+    lock_ReleaseWrite(&cm_serverLock);         /* release server lock */
 
+    cm_PingServer(tsp);                        /* Obtain Capabilities and check up/down state */
     return tsp;
 }
 
@@ -283,9 +335,9 @@ cm_serverRef_t *cm_NewServerRef(cm_server_t *serverp)
     return tsrp;
 }
 
-long cm_ChecksumServerList(cm_serverRef_t *serversp)
+LONG_PTR cm_ChecksumServerList(cm_serverRef_t *serversp)
 {
-    long sum = 0;
+    LONG_PTR sum = 0;
     int first = 1;
     cm_serverRef_t *tsrp;
 
@@ -295,7 +347,7 @@ long cm_ChecksumServerList(cm_serverRef_t *serversp)
             first = 0;
         else
             sum <<= 1;
-        sum ^= (long) tsrp->server;
+        sum ^= (LONG_PTR) tsrp->server;
     }
 
     lock_ReleaseWrite(&cm_serverLock);
@@ -438,21 +490,24 @@ void cm_FreeServer(cm_server_t* serverp)
          */
         cm_GCConnections(serverp);  /* connsp */
 
-        lock_FinalizeMutex(&serverp->mx);
-        if ( cm_allServersp == serverp )
-            cm_allServersp = serverp->allNextp;
-        else {
-            cm_server_t *tsp;
-
-            for(tsp = cm_allServersp; tsp->allNextp; tsp=tsp->allNextp) {
-                if ( tsp->allNextp == serverp ) {
-                    tsp->allNextp = serverp->allNextp;
-                    break;
-                }
+       if (!(serverp->flags & CM_SERVERFLAG_PREF_SET)) {
+           lock_FinalizeMutex(&serverp->mx);
+           if ( cm_allServersp == serverp )
+               cm_allServersp = serverp->allNextp;
+           else {
+               cm_server_t *tsp;
+
+               for(tsp = cm_allServersp; tsp->allNextp; tsp=tsp->allNextp) {
+                   if ( tsp->allNextp == serverp ) {
+                       tsp->allNextp = serverp->allNextp;
+                       break;
+                   }
+               }
             }
+           free(serverp);
         }
     }
- }
+}
 
 void cm_FreeServerList(cm_serverRef_t** list)
 {