e82ff96635a0e547acffc51bdba6bcf45ce89e0b
[openafs.git] / src / WINNT / afsd / cm_cell.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afs/param.h>
11 #include <afs/stds.h>
12
13 #ifndef DJGPP
14 #include <windows.h>
15 #include <nb30.h>
16 #include <winsock2.h>
17 #endif /* !DJGPP */
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <malloc.h>
21 #include <osi.h>
22 #include <string.h>
23
24 #include "afsd.h"
25
26 osi_rwlock_t cm_cellLock;
27
28 cm_cell_t *cm_allCellsp;
29
30 /* function called as callback proc from cm_SearchCellFile.  Return 0 to
31  * continue processing.
32  */
33 long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep)
34 {
35         cm_server_t *tsp;
36         cm_serverRef_t *tsrp;
37     cm_cell_t *cellp;
38         
39         cellp = rockp;
40
41         /* if this server was previously created by fs setserverprefs */
42         if ( tsp = cm_FindServer(addrp, CM_SERVER_VLDB))
43         {
44                 if ( !tsp->cellp )
45                         tsp->cellp = cellp;
46         }
47         else
48         tsp = cm_NewServer(addrp, CM_SERVER_VLDB, cellp);
49
50         /* Insert the vlserver into a sorted list, sorted by server rank */
51         tsrp = cm_NewServerRef(tsp);
52         cm_InsertServerList(&cellp->vlServersp, tsrp);
53     /* drop the allocation reference */
54     lock_ObtainWrite(&cm_serverLock);
55     tsrp->refCount--;
56     lock_ReleaseWrite(&cm_serverLock);
57         return 0;
58 }
59
60 /* load up a cell structure from the cell database, afsdcell.ini */
61 cm_cell_t *cm_GetCell(char *namep, long flags)
62 {
63   return cm_GetCell_Gen(namep, NULL, flags);
64 }
65
66 cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, long flags)
67 {
68         cm_cell_t *cp;
69     long code;
70     static cellCounter = 1;             /* locked by cm_cellLock */
71         int ttl;
72         char fullname[200]="";
73
74         if (!strcmp(namep,SMB_IOCTL_FILENAME_NOSLASH))
75                 return NULL;
76
77         lock_ObtainWrite(&cm_cellLock);
78         for (cp = cm_allCellsp; cp; cp=cp->nextp) {
79                 if (strcmp(namep, cp->namep) == 0) {
80             strcpy(fullname, cp->namep);
81             break;
82                 }
83     }
84
85         if ((!cp && (flags & CM_FLAG_CREATE))
86 #ifdef AFS_AFSDB_ENV
87          /* if it's from DNS, see if it has expired */
88          || (cp && (cp->flags & CM_CELLFLAG_DNS) 
89          && ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID) || (time(0) > cp->timeout)))
90 #endif
91           ) {
92         int dns_expired = 0;
93                 if (!cp) {
94             cp = malloc(sizeof(cm_cell_t));
95             memset(cp, 0, sizeof(cm_cell_t));
96         } 
97         else {
98             dns_expired = 1;
99             /* must empty cp->vlServersp */
100             lock_ObtainWrite(&cp->mx);
101             cm_FreeServerList(&cp->vlServersp);
102             cp->vlServersp = NULL;
103             lock_ReleaseWrite(&cp->mx);
104         }
105
106         code = cm_SearchCellFile(namep, fullname, cm_AddCellProc, cp);
107                 if (code) {
108             osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellFile(%s) returns code= %d fullname= %s", 
109                       namep, code, fullname);
110
111 #ifdef AFS_AFSDB_ENV
112             if (cm_dnsEnabled /*&& cm_DomainValid(namep)*/) {
113                 code = cm_SearchCellByDNS(namep, fullname, &ttl, cm_AddCellProc, cp);
114                 if ( code ) {
115                     osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s", 
116                              namep, code, fullname);
117                     if (dns_expired) {
118                         cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
119                         cp = NULL;  /* set cp to NULL to indicate error */
120                         goto done;
121                     } 
122                 }
123                 else {   /* got cell from DNS */
124                     cp->flags |= CM_CELLFLAG_DNS;
125                     cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
126                     cp->timeout = time(0) + ttl;
127                 }
128             }
129 #endif
130             if (cp && code) {     /* free newly allocated memory */
131                 free(cp);
132                 cp = NULL;
133                 goto done;
134             }
135                 }
136
137                 /* randomise among those vlservers having the same rank*/ 
138         cm_RandomizeServer(&cp->vlServersp);
139
140 #ifdef AFS_AFSDB_ENV
141         if (dns_expired) {
142             /* we want to preserve the full name and mutex.
143              * also, cp is already in the cm_allCellsp list
144              */
145             goto done;
146         }
147 #endif /* AFS_AFSDB_ENV */
148
149         /* otherwise we found the cell, and so we're nearly done */
150         lock_InitializeMutex(&cp->mx, "cm_cell_t mutex");
151
152                 /* copy in name */
153         cp->namep = malloc(strlen(fullname)+1);
154         strcpy(cp->namep, fullname);
155
156                 /* thread on global list */
157         cp->nextp = cm_allCellsp;
158         cm_allCellsp = cp;
159                 
160         cp->cellID = cellCounter++;
161     }
162
163   done:
164     /* fullname is not valid if cp == NULL */
165         if (cp && newnamep)
166         strcpy(newnamep, fullname);
167         lock_ReleaseWrite(&cm_cellLock);
168     return cp;
169 }
170
171 cm_cell_t *cm_FindCellByID(long cellID)
172 {
173         cm_cell_t *cp;
174         int ttl;
175     int code;
176
177         lock_ObtainWrite(&cm_cellLock);
178         for(cp = cm_allCellsp; cp; cp=cp->nextp) {
179                 if (cellID == cp->cellID) 
180             break;
181     }
182
183 #ifdef AFS_AFSDB_ENV
184         /* if it's from DNS, see if it has expired */
185         if (cp && cm_dnsEnabled && (cp->flags & CM_CELLFLAG_DNS) && 
186         ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID) || (time(0) > cp->timeout))) {
187         /* must empty cp->vlServersp */
188         cm_FreeServerList(&cp->vlServersp);
189         cp->vlServersp = NULL;
190
191         code = cm_SearchCellByDNS(cp->namep, NULL, &ttl, cm_AddCellProc, cp);
192         if (code == 0) {   /* got cell from DNS */
193             cp->flags |= CM_CELLFLAG_DNS;
194             cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID;
195 #ifdef DEBUG
196             fprintf(stderr, "cell %s: ttl=%d\n", cp->namep, ttl);
197 #endif
198             cp->timeout = time(0) + ttl;
199         } else {
200             cp->flags |= CM_CELLFLAG_VLSERVER_INVALID;
201             cp = NULL;      /* return NULL to indicate failure */
202         }
203         /* if we fail to find it this time, we'll just do nothing and leave the
204          * current entry alone 
205          */
206         }
207 #endif /* AFS_AFSDB_ENV */
208
209         lock_ReleaseWrite(&cm_cellLock);        
210     return cp;
211 }
212
213 void cm_InitCell(void)
214 {
215         static osi_once_t once;
216         
217     if (osi_Once(&once)) {
218                 lock_InitializeRWLock(&cm_cellLock, "cell global lock");
219         cm_allCellsp = NULL;
220                 osi_EndOnce(&once);
221     }
222 }
223 void cm_ChangeRankCellVLServer(cm_server_t *tsp)
224 {
225         cm_cell_t *cp;
226         int code;
227
228         cp = tsp->cellp;        /* cell that this vlserver belongs to */
229         osi_assert(cp);
230
231         lock_ObtainMutex(&cp->mx);
232         code = cm_ChangeRankServer(&cp->vlServersp, tsp);
233
234         if ( !code )            /* if the server list was rearranged */
235             cm_RandomizeServer(&cp->vlServersp);
236
237         lock_ReleaseMutex(&cp->mx);
238 }
239