#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;
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 */
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 */
cm_GCConnections(tsp);
lock_ObtainWrite(&cm_serverLock);
- osi_assert(tsp->refCount-- > 0);
+ cm_PutServerNoLock(tsp);
}
lock_ReleaseWrite(&cm_serverLock);
}
}
}
+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);
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 */
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) {
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 */
}
/* 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);
{
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;
}
int first = 1;
cm_serverRef_t *tsrp;
+ lock_ObtainWrite(&cm_serverLock);
for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
if (first)
first = 0;
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 ;
}
}
element->next = current->next;
current->next = element;
+ lock_ReleaseWrite(&cm_serverLock);
}
/*
** Re-sort the server list with the modified rank
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 )
{
}
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;
}
/*
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)
}
/* 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)
{
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);
}
+