smb-notify-callback-expire-20040817
[openafs.git] / src / WINNT / afsd / cm_server.c
index ffb2b7a..ebe9eb2 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
 #include <winsock2.h>
+#include <nb30.h>
+#else
+#include <sys/socket.h>
+#endif /* !DJGPP */
 #include <stdlib.h>
 #include <malloc.h>
 #include <string.h>
 
 #include <osi.h>
 #include <rx/rx.h>
-#include <nb30.h>
 #include "afsd.h"
 
 osi_rwlock_t cm_serverLock;
@@ -49,7 +53,7 @@ void cm_CheckServers(long flags, cm_cell_t *cellp)
 
         lock_ObtainWrite(&cm_serverLock);
        for(tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
-               tsp->refCount++;
+        cm_GetServerNoLock(tsp);
                 lock_ReleaseWrite(&cm_serverLock);
 
                /* now process the server */
@@ -94,7 +98,7 @@ void cm_CheckServers(long flags, cm_cell_t *cellp)
                                        code = RXAFS_GetTime(connp->callp, &secs, &usecs);
                                }
                                if (wasDown)
-                                       rx_SetConnDeadTime(connp->callp, CM_CONN_CONNDEADTIME);
+                                       rx_SetConnDeadTime(connp->callp, ConnDeadtimeout);
                                cm_PutConn(connp);
                        }       /* got an unauthenticated connection to this server */
 
@@ -116,7 +120,7 @@ void cm_CheckServers(long flags, cm_cell_t *cellp)
                cm_GCConnections(tsp);
 
                 lock_ObtainWrite(&cm_serverLock);
-                osi_assert(tsp->refCount-- > 0);
+        cm_PutServerNoLock(tsp);
         }
         lock_ReleaseWrite(&cm_serverLock);
 }
@@ -131,6 +135,18 @@ void cm_InitServer(void)
         }
 }
 
+void cm_GetServer(cm_server_t *serverp)
+{
+    lock_ObtainWrite(&cm_serverLock);
+    serverp->refCount++;
+    lock_ReleaseWrite(&cm_serverLock);
+}
+
+void cm_GetServerNoLock(cm_server_t *serverp)
+{
+    serverp->refCount++;
+}
+
 void cm_PutServer(cm_server_t *serverp)
 {
        lock_ObtainWrite(&cm_serverLock);
@@ -138,6 +154,11 @@ void cm_PutServer(cm_server_t *serverp)
        lock_ReleaseWrite(&cm_serverLock);
 }
 
+void cm_PutServerNoLock(cm_server_t *serverp)
+{
+       osi_assert(serverp->refCount-- > 0);
+}
+
 void cm_SetServerPrefs(cm_server_t * serverp)
 {
        unsigned long   serverAddr;     /* in host byte order */
@@ -186,7 +207,8 @@ void cm_SetServerPrefs(cm_server_t * serverp)
                serverp->ipRank += min(serverp->ipRank, rand() % 0x000f);
            } /* and of for loop */
        }
-       else    serverp->ipRank = 10000 + (rand() % 0x00ff); /* VL server */
+    else 
+        serverp->ipRank = 10000 + (rand() % 0x00ff); /* VL server */
 }
 
 cm_server_t *cm_NewServer(struct sockaddr_in *socketp, int type, cm_cell_t *cellp) {
@@ -195,17 +217,21 @@ cm_server_t *cm_NewServer(struct sockaddr_in *socketp, int type, cm_cell_t *cell
        osi_assert(socketp->sin_family == AF_INET);
 
        tsp = malloc(sizeof(*tsp));
-        memset(tsp, 0, sizeof(*tsp));
+    memset(tsp, 0, sizeof(*tsp));
        tsp->type = type;
-        tsp->cellp = cellp;
-        tsp->refCount = 1;
-       tsp->allNextp = cm_allServersp;
-        cm_allServersp = tsp;
+    tsp->cellp = cellp;
+    tsp->refCount = 1;
        lock_InitializeMutex(&tsp->mx, "cm_server_t mutex");
        tsp->addr = *socketp;
 
        cm_SetServerPrefs(tsp); 
-        return tsp;
+
+    lock_ObtainWrite(&cm_serverLock); /* get server lock */
+       tsp->allNextp = cm_allServersp;
+    cm_allServersp = tsp;
+    lock_ReleaseWrite(&cm_serverLock); /* release server lock */
+
+    return tsp;
 }
 
 /* find a server based on its properties */
@@ -222,7 +248,8 @@ cm_server_t *cm_FindServer(struct sockaddr_in *addrp, int type)
         }
 
        /* bump ref count if we found the server */
-       if (tsp) tsp->refCount++;
+    if (tsp) 
+        cm_GetServerNoLock(tsp);
 
        /* drop big table lock */
         lock_ReleaseWrite(&cm_serverLock);
@@ -235,13 +262,12 @@ cm_serverRef_t *cm_NewServerRef(cm_server_t *serverp)
 {
        cm_serverRef_t *tsrp;
 
-        lock_ObtainWrite(&cm_serverLock);
-       serverp->refCount++;
-        lock_ReleaseWrite(&cm_serverLock);
+    cm_GetServer(serverp);
        tsrp = malloc(sizeof(*tsrp));
        tsrp->server = serverp;
        tsrp->status = not_busy;
        tsrp->next = NULL;
+    tsrp->refCount = 1;
 
        return tsrp;
 }
@@ -252,6 +278,7 @@ long cm_ChecksumServerList(cm_serverRef_t *serversp)
        int first = 1;
        cm_serverRef_t *tsrp;
 
+    lock_ObtainWrite(&cm_serverLock);
        for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
                if (first)
                        first = 0;
@@ -260,23 +287,30 @@ long cm_ChecksumServerList(cm_serverRef_t *serversp)
                sum ^= (long) tsrp->server;
        }
 
+    lock_ReleaseWrite(&cm_serverLock);
        return sum;
 }
 
 /*
 ** Insert a server into the server list keeping the list sorted in 
 ** asending order of ipRank. 
+** 
+** The refCount of the cm_serverRef_t is increased
 */
 void cm_InsertServerList(cm_serverRef_t** list, cm_serverRef_t* element)
 {
        cm_serverRef_t  *current=*list;
        unsigned short ipRank = element->server->ipRank;
 
-       /* insertion into empty list  or at the beginning of the list */
+    lock_ObtainWrite(&cm_serverLock);
+    element->refCount++;                /* increase refCount */
+
+    /* insertion into empty list  or at the beginning of the list */
        if ( !current || (current->server->ipRank > ipRank) )
        {
                element->next = *list;
                *list = element;
+        lock_ReleaseWrite(&cm_serverLock);
                return ;        
        }
        
@@ -288,6 +322,7 @@ void cm_InsertServerList(cm_serverRef_t** list, cm_serverRef_t* element)
        }
        element->next = current->next;
        current->next = element;
+    lock_ReleaseWrite(&cm_serverLock);
 }
 /*
 ** Re-sort the server list with the modified rank
@@ -303,6 +338,7 @@ long cm_ChangeRankServer(cm_serverRef_t** list, cm_server_t*        server)
        if ( (!*current) || !((*current)->next)  )
                return 1;               /* list unchanged: return success */
 
+    lock_ObtainWrite(&cm_serverLock);
        /* if the server is on the list, delete it from list */
        while ( *current )
        {
@@ -314,12 +350,19 @@ long cm_ChangeRankServer(cm_serverRef_t** list, cm_server_t*      server)
                }
                current = & ( (*current)->next);        
        }
-       /* if this volume is not replicated on this server  */
-       if ( !element)
+    lock_ReleaseWrite(&cm_serverLock);
+
+    /* if this volume is not replicated on this server  */
+       if (!element)
                return 1;       /* server is not on list */
 
        /* re-insert deleted element into the list with modified rank*/
        cm_InsertServerList(list, element);
+
+    /* reduce refCount which was increased by cm_InsertServerList */
+    lock_ObtainWrite(&cm_serverLock);
+    element->refCount--;
+    lock_ReleaseWrite(&cm_serverLock);
        return 0;
 }
 /*
@@ -336,6 +379,8 @@ void cm_RandomizeServer(cm_serverRef_t** list)
        if ( !tsrp || ! tsrp->next )
                return ; 
 
+    lock_ObtainWrite(&cm_serverLock);
+
        /* count the number of servers with the lowest rank */
        lowestRank = tsrp->server->ipRank;
        for ( count=1, tsrp=tsrp->next; tsrp; tsrp=tsrp->next)
@@ -347,12 +392,17 @@ void cm_RandomizeServer(cm_serverRef_t** list)
        }       
 
        /* if there is only one server with the lowest rank, we are done */
-       if ( count <= 1 )               
+       if ( count <= 1 ) {
+        lock_ReleaseWrite(&cm_serverLock);
                return ;
+    }
 
        picked = rand() % count;
-       if ( !picked )
+       if ( !picked ) {
+        lock_ReleaseWrite(&cm_serverLock);
                return ;
+    }
+
        tsrp = *list;
        while (--picked >= 0)
        {
@@ -362,4 +412,58 @@ void cm_RandomizeServer(cm_serverRef_t** list)
        lastTsrp->next = tsrp->next;  /* delete random element from list*/
        tsrp->next     = *list; /* insert element at the beginning of list */
        *list          = tsrp;
+    lock_ReleaseWrite(&cm_serverLock);
+}
+
+/* call cm_FreeServer while holding a write lock on cm_serverLock */
+void cm_FreeServer(cm_server_t* serverp)
+{
+    cm_PutServerNoLock(serverp);
+    if (serverp->refCount == 0)
+    {
+        /* we need to check to ensure that all of the connections
+         * for this server have a 0 refCount; otherwise, they will
+         * not be garbage collected 
+         */
+        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;
+                }
+            }
+        }
+    }
+ }
+
+void cm_FreeServerList(cm_serverRef_t** list)
+{
+    cm_serverRef_t  **current = list;
+    cm_serverRef_t  **nextp = 0;
+       cm_serverRef_t  * next = 0;
+
+    lock_ObtainWrite(&cm_serverLock);
+
+    while (*current)
+    {
+        nextp = &(*current)->next;
+        if (--((*current)->refCount) == 0) {
+                       next = *nextp;
+            cm_FreeServer((*current)->server);
+            free(*current);
+            *current = next;
+        } else {
+           current = nextp;
+        }
+    }
+  
+    lock_ReleaseWrite(&cm_serverLock);
 }
+