dns-and-server-ref-counts-20040530
[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
54         return 0;
55 }
56
57 /* load up a cell structure from the cell database, afsdcell.ini */
58 cm_cell_t *cm_GetCell(char *namep, long flags)
59 {
60   return cm_GetCell_Gen(namep, NULL, flags);
61 }
62
63 cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, long flags)
64 {
65         cm_cell_t *cp;
66     long code;
67     static cellCounter = 1;             /* locked by cm_cellLock */
68         int ttl;
69         char fullname[200]="";
70
71         lock_ObtainWrite(&cm_cellLock);
72         for(cp = cm_allCellsp; cp; cp=cp->nextp) {
73                 if (strcmp(namep, cp->namep) == 0) {
74             strcpy(fullname, cp->namep);
75             break;
76                 }
77     }
78
79         if ((!cp && (flags & CM_FLAG_CREATE))
80 #ifdef AFS_AFSDB_ENV
81          /* if it's from DNS, see if it has expired */
82          || (cp && (cp->flags & CM_CELLFLAG_DNS) && (time(0) > cp->timeout))
83 #endif
84           ) {
85         int dns_expired = 0;
86                 if (!cp) {
87             cp = malloc(sizeof(*cp));
88             memset(cp, 0, sizeof(*cp));
89         } 
90         else {
91             dns_expired = 1;
92             /* must empty cp->vlServersp */
93             cm_FreeServerList(&cp->vlServersp);
94             cp->vlServersp = NULL;
95         }
96
97         code = cm_SearchCellFile(namep, fullname, cm_AddCellProc, cp);
98                 if (code) {
99             afsi_log("in cm_GetCell_gen cm_SearchCellFile(%s) returns code= %d fullname= %s", 
100                       namep, code, fullname);
101
102 #ifdef AFS_AFSDB_ENV
103             if (cm_dnsEnabled /*&& cm_DomainValid(namep)*/) {
104                 code = cm_SearchCellByDNS(namep, fullname, &ttl, cm_AddCellProc, cp);
105                 if ( code ) {
106                     afsi_log("in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s", 
107                              namep, code, fullname);
108                     if (dns_expired) {
109                         if ( cm_allCellsp == cp )
110                             cm_allCellsp = cp->nextp;
111                         else {
112                             cm_cell_t *tcp;
113
114                             for(tcp = cm_allCellsp; tcp->nextp; tcp=tcp->nextp) {
115                                 if ( tcp->nextp == cp ) {
116                                     tcp->nextp = cp->nextp;
117                                     break;
118                                 }
119                             }
120                         }
121                     
122                         lock_FinalizeMutex(&cp->mx);
123                         free(cp->namep);
124                     }
125                 }
126                 else {   /* got cell from DNS */
127                     cp->flags |= CM_CELLFLAG_DNS;
128                     cp->timeout = time(0) + ttl;
129                 }
130             }
131 #endif
132             if (code) {
133                 free(cp);
134                 cp = NULL;
135                 goto done;
136             }
137                 }
138
139                 /* randomise among those vlservers having the same rank*/ 
140                 cm_RandomizeServer(&cp->vlServersp);
141
142 #ifdef AFS_AFSDB_ENV
143         if (dns_expired) {
144             /* we want to preserve the full name and mutex.
145              * also, cp is already in the cm_allCellsp list
146              */
147             goto done;
148         }
149 #endif /* AFS_AFSDB_ENV */
150
151         /* otherwise we found the cell, and so we're nearly done */
152         lock_InitializeMutex(&cp->mx, "cm_cell_t mutex");
153
154                 /* copy in name */
155         cp->namep = malloc(strlen(fullname)+1);
156         strcpy(cp->namep, fullname);
157
158                 /* thread on global list */
159         cp->nextp = cm_allCellsp;
160         cm_allCellsp = cp;
161                 
162         cp->cellID = cellCounter++;
163     }
164
165   done:
166     /* fullname is not valid if cp == NULL */
167         if (cp && newnamep)
168         strcpy(newnamep, fullname);
169         lock_ReleaseWrite(&cm_cellLock);
170     return cp;
171 }
172
173 cm_cell_t *cm_FindCellByID(long cellID)
174 {
175         cm_cell_t *cp;
176         int ttl;
177      int code;
178
179         lock_ObtainWrite(&cm_cellLock);
180         for(cp = cm_allCellsp; cp; cp=cp->nextp) {
181                 if (cellID == cp->cellID) 
182             break;
183     }
184
185 #ifdef AFS_AFSDB_ENV
186         /* if it's from DNS, see if it has expired */
187         if (cp && cm_dnsEnabled && (cp->flags & CM_CELLFLAG_DNS) && (time(0) > cp->timeout)) {
188           code = cm_SearchCellByDNS(cp->namep, NULL, &ttl, cm_AddCellProc, cp);
189           if (code == 0) {   /* got cell from DNS */
190             cp->flags |= CM_CELLFLAG_DNS;
191 #ifdef DEBUG
192             fprintf(stderr, "cell %s: ttl=%d\n", cp->namep, ttl);
193 #endif
194             cp->timeout = time(0) + ttl;
195           }
196           /* if we fail to find it this time, we'll just do nothing and leave the
197              current entry alone */
198         }
199 #endif /* AFS_AFSDB_ENV */
200
201         lock_ReleaseWrite(&cm_cellLock);        
202     return cp;
203 }
204
205 void cm_InitCell(void)
206 {
207         static osi_once_t once;
208         
209         if (osi_Once(&once)) {
210                 lock_InitializeRWLock(&cm_cellLock, "cell global lock");
211                 cm_allCellsp = NULL;
212                 osi_EndOnce(&once);
213         }
214 }
215 void cm_ChangeRankCellVLServer(cm_server_t *tsp)
216 {
217         cm_cell_t *cp;
218         int code;
219
220         cp = tsp->cellp;        /* cell that this vlserver belongs to */
221         osi_assert(cp);
222
223         lock_ObtainMutex(&cp->mx);
224         code = cm_ChangeRankServer(&cp->vlServersp, tsp);
225
226         if ( !code )            /* if the server list was rearranged */
227             cm_RandomizeServer(&cp->vlServersp);
228
229         lock_ReleaseMutex(&cp->mx);
230 }
231