Remove the RCSID macro
[openafs.git] / src / ubik / ubikclient.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 <afsconfig.h>
11 #if defined(UKERNEL)
12 #include "afs/param.h"
13 #else
14 #include <afs/param.h>
15 #endif
16
17
18 #if defined(UKERNEL)
19 #include "afs/sysincludes.h"
20 #include "afsincludes.h"
21 #include "afs/stds.h"
22 #include "rx/xdr.h"
23 #include "rx/rx.h"
24 #include "afs/lock.h"
25 #include "afs/rxgen_consts.h"
26 #define UBIK_LEGACY_CALLITER 1
27 #include "ubik.h"
28 #include "afs/pthread_glock.h"
29 #include <netdb.h>
30 #else /* defined(UKERNEL) */
31 #include <afs/stds.h>
32 #include <afs/pthread_glock.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <rx/xdr.h>
36 #include <rx/rx.h>
37 #include <lock.h>
38 #ifdef AFS_NT40_ENV
39 #include <winsock2.h>
40 #else
41 #include <unistd.h>
42 #include <netdb.h>
43 #include <netinet/in.h>
44 #endif
45 #include <afs/rxgen_consts.h>
46 #include "ubik.h"
47 #endif /* defined(UKERNEL) */
48
49
50 short ubik_initializationState; /*!< initial state is zero */
51
52
53 /*!
54  * \brief Parse list for clients.
55  */
56 int
57 ubik_ParseClientList(int argc, char **argv, afs_int32 * aothers)
58 {
59     register afs_int32 i;
60     register char *tp;
61     register struct hostent *th;
62     afs_int32 temp, counter;
63     int inServer;
64
65     inServer = 0;               /* haven't seen -servers yet */
66     counter = 0;
67     for (i = 1; i < argc; i++) {
68         /* look for -servers argument */
69         tp = argv[i];
70
71         if (inServer) {
72             if (*tp == '-')
73                 break;          /* done */
74             /* otherwise this is a new host name */
75             LOCK_GLOBAL_MUTEX;
76             th = gethostbyname(tp);
77             if (!th) {
78                 UNLOCK_GLOBAL_MUTEX;
79                 return UBADHOST;
80             }
81             memmove((void *)&temp, (const void *)th->h_addr,
82                     sizeof(afs_int32));
83             UNLOCK_GLOBAL_MUTEX;
84             if (counter++ >= MAXSERVERS)
85                 return UNHOSTS;
86             *aothers++ = temp;
87         } else {
88             /* haven't seen a -server yet */
89             if (!strcmp(tp, "-servers")) {
90                 inServer = 1;
91             }
92         }
93     }
94     if (!inServer) {
95         /* never saw a -server */
96         return UNOENT;
97     }
98     if (counter < MAXSERVERS)
99         *aothers++ = 0;         /* null terminate if room */
100     return 0;
101 }
102
103 #ifdef AFS_PTHREAD_ENV
104 #include <pthread.h>
105 #include <assert.h>
106
107 static pthread_once_t random_once = PTHREAD_ONCE_INIT;
108 static int called_afs_random_once;
109 static pthread_key_t random_number_key;
110
111 static void
112 afs_random_once(void)
113 {
114     assert(pthread_key_create(&random_number_key, NULL) == 0);
115     called_afs_random_once = 1;
116 }
117
118 #endif
119
120 #if !defined(UKERNEL)
121 /*! 
122  * \brief use time and pid to try to get some initial randomness.
123  */
124 #define ranstage(x)     (x)= (afs_uint32) (3141592621U*((afs_uint32)x)+1)
125
126 /*! 
127  * \brief Random number generator and constants from KnuthV2 2d ed, p170
128  *
129  * Rules: \n
130  * X = (aX + c) % m \n
131  * m is a power of two \n
132  * a % 8 is 5 \n
133  * a is 0.73m  should be 0.01m .. 0.99m \n
134  * c is more or less immaterial.  1 or a is suggested. \n
135  *
136  * NB:  LOW ORDER BITS are not very random.  To get small random numbers,
137  *      treat result as <1, with implied binary point, and multiply by 
138  *      desired modulus.
139  *
140  * NB:  Has to be unsigned, since shifts on signed quantities may preserve
141  *      the sign bit.
142  * 
143  * In this case, m == 2^32, the mod operation is implicit. a == pi, which
144  * is used because it has some interesting characteristics (lacks any
145  * interesting bit-patterns).   
146  */
147 unsigned int
148 afs_random(void)
149 {
150 #ifdef AFS_PTHREAD_ENV
151     afs_uint32 state;
152
153     (called_afs_random_once || pthread_once(&random_once, afs_random_once));
154     state = (afs_uint32) pthread_getspecific(random_number_key);
155 #else
156     static afs_uint32 state = 0;
157 #endif
158
159     if (!state) {
160         int i;
161         state = time(0) + getpid();
162         for (i = 0; i < 15; i++) {
163             ranstage(state);
164         }
165     }
166
167     ranstage(state);
168 #ifdef AFS_PTHREAD_ENV
169     pthread_setspecific(random_number_key, (const void *)state);
170 #endif
171     return (state);
172
173 }
174
175 /*!
176  * \brief Returns int 0..14 using the high bits of a pseudo-random number instead of
177  * the low bits, as the low bits are "less random" than the high ones...
178  * 
179  * \todo Slight roundoff error exists, an excercise for the reader.
180  *
181  * Need to multiply by something with lots of ones in it, so multiply by 
182  * 8 or 16 is right out.
183  */
184 static unsigned int
185 afs_randomMod15(void)
186 {
187     afs_uint32 temp;
188
189     temp = afs_random() >> 4;
190     temp = (temp * 15) >> 28;
191
192     return temp;
193 }
194 #endif /* !defined(UKERNEL) */
195
196 #ifdef abs
197 #undef abs
198 #endif /* abs */
199 #define abs(a) ((a) < 0 ? -1*(a) : (a))
200 int
201 ubik_ClientInit(register struct rx_connection **serverconns,
202                 struct ubik_client **aclient)
203 {
204     int i, j;
205     int count;
206     int offset;
207     register struct ubik_client *tc;
208
209     initialize_U_error_table();
210
211     if (*aclient) {             /* the application is doing a re-initialization */
212         LOCK_UBIK_CLIENT((*aclient));
213         /* this is an important defensive check */
214         if (!((*aclient)->initializationState)) {
215             UNLOCK_UBIK_CLIENT((*aclient));
216             return UREINITIALIZE;
217         }
218
219         /* release all existing connections */
220         for (tc = *aclient, i = 0; i < MAXSERVERS; i++) {
221             struct rx_connection *rxConn = ubik_GetRPCConn(tc, i);
222             if (rxConn == 0)
223                 break;
224 #ifdef AFS_PTHREAD_ENV
225             rx_ReleaseCachedConnection(rxConn);
226 #else
227             rx_DestroyConnection(rxConn);
228 #endif
229         }
230         UNLOCK_UBIK_CLIENT((*aclient));
231 #ifdef AFS_PTHREAD_ENV
232         if (pthread_mutex_destroy(&((*aclient)->cm)))
233             return UMUTEXDESTROY;
234 #endif
235     } else {
236         tc = (struct ubik_client *)malloc(sizeof(struct ubik_client));
237     }
238     if (tc == NULL)
239         return UNOMEM;
240     memset((void *)tc, 0, sizeof(*tc));
241 #ifdef AFS_PTHREAD_ENV
242     if (pthread_mutex_init(&(tc->cm), (const pthread_mutexattr_t *)0)) {
243         return UMUTEXINIT;
244     }
245 #endif
246     tc->initializationState = ++ubik_initializationState;
247
248     /* first count the # of server conns so we can randomize properly */
249     count = 0;
250     for (i = 0; i < MAXSERVERS; i++) {
251         if (serverconns[i] == (struct rx_connection *)0)
252             break;
253         count++;
254     }
255
256     /* here count is the # of servers we're actually passed in.  Compute
257      * offset, a number between 0..count-1, where we'll start copying from the
258      * client-provided array. */
259     for (i = 0; i < count; i++) {
260         offset = afs_randomMod15() % count;
261         for (j = abs(offset); j < 2 * count; j++) {
262             if (!tc->conns[abs(j % count)]) {
263                 tc->conns[abs(j % count)] = serverconns[i];
264                 break;
265             }
266         }
267     }
268
269     *aclient = tc;
270     return 0;
271 }
272
273 /*! 
274  * \brief Destroy an ubik connection.
275  *
276  * It calls rx to destroy the component rx connections, then frees the ubik
277  * connection structure.
278  */
279 afs_int32
280 ubik_ClientDestroy(struct ubik_client * aclient)
281 {
282     register int c;
283
284     if (aclient == 0)
285         return 0;
286     LOCK_UBIK_CLIENT(aclient);
287     for (c = 0; c < MAXSERVERS; c++) {
288         struct rx_connection *rxConn = ubik_GetRPCConn(aclient, c);
289         if (rxConn == 0)
290             break;
291 #ifdef AFS_PTHREAD_ENV
292         rx_ReleaseCachedConnection(rxConn);
293 #else
294         rx_DestroyConnection(rxConn);
295 #endif
296     }
297     aclient->initializationState = 0;   /* client in not initialized */
298     UNLOCK_UBIK_CLIENT(aclient);
299 #ifdef AFS_PTHREAD_ENV
300     pthread_mutex_destroy(&(aclient->cm));      /* ignore failure */
301 #endif
302     free(aclient);
303     return 0;
304 }
305
306 /*!
307  * \brief So that intermittent failures that cause connections to die
308  *     don't kill whole ubik connection, refresh them when the connection is in
309  *     error.
310  */
311 struct rx_connection *
312 ubik_RefreshConn(struct rx_connection *tc)
313 {
314     afs_uint32 host;
315     u_short port;
316     u_short service;
317     struct rx_securityClass *sc;
318     int si;
319     struct rx_connection *newTc;
320
321     host = rx_HostOf(rx_PeerOf(tc));
322     port = rx_PortOf(rx_PeerOf(tc));
323     service = rx_ServiceIdOf(tc);
324     sc = rx_SecurityObjectOf(tc);
325     si = rx_SecurityClassOf(tc);
326
327     /*
328      * destroy old one after creating new one so that refCount on security
329      * object cannot reach zero.
330      */
331     newTc = rx_NewConnection(host, port, service, sc, si);
332     rx_DestroyConnection(tc);
333     return newTc;
334 }
335
336 #ifdef AFS_PTHREAD_ENV
337
338 pthread_once_t ubik_client_once = PTHREAD_ONCE_INIT;
339 pthread_mutex_t ubik_client_mutex;
340 #define LOCK_UCLNT_CACHE \
341     assert(pthread_once(&ubik_client_once, ubik_client_init_mutex) == 0 && \
342            pthread_mutex_lock(&ubik_client_mutex)==0)
343 #define UNLOCK_UCLNT_CACHE assert(pthread_mutex_unlock(&ubik_client_mutex)==0)
344
345 void
346 ubik_client_init_mutex(void)
347 {
348     assert(pthread_mutex_init(&ubik_client_mutex, NULL) == 0);
349 }
350
351 #else
352
353 #define LOCK_UCLNT_CACHE
354 #define UNLOCK_UCLNT_CACHE
355
356 #endif
357
358 #define SYNCCOUNT 10
359 static int *calls_needsync[SYNCCOUNT];  /* proc calls that need the sync site */
360 static int synccount = 0;
361
362 /*!
363  * call this instead of stub and we'll guarantee to find a host that's up.
364  * 
365  * \todo In the future, we should also put in a protocol to find the sync site.
366  */
367 afs_int32
368 ubik_Call(int (*aproc) (), register struct ubik_client *aclient, 
369           afs_int32 aflags, long p1, long p2, long p3, long p4, 
370           long p5, long p6, long p7, long p8, long p9, long p10,
371           long p11, long p12, long p13, long p14, long p15, long p16)
372 {
373     afs_int32 rcode, code, newHost, thisHost, i, count;
374     int chaseCount, pass, needsync, inlist, j;
375     struct rx_connection *tc;
376     struct rx_peer *rxp;
377     short origLevel;
378
379     if (!aclient)
380         return UNOENT;
381     LOCK_UBIK_CLIENT(aclient);
382
383   restart:
384     origLevel = aclient->initializationState;
385     rcode = UNOSERVERS;
386     chaseCount = inlist = needsync = 0;
387
388     LOCK_UCLNT_CACHE;
389     for (j = 0; ((j < SYNCCOUNT) && calls_needsync[j]); j++) {
390         if (calls_needsync[j] == (int *)aproc) {
391             inlist = needsync = 1;
392             break;
393         }
394     }
395     UNLOCK_UCLNT_CACHE;
396     /* 
397      * First  pass, we try all servers that are up.
398      * Second pass, we try all servers.
399      */
400     for (pass = 0; pass < 2; pass++) {  /*p */
401         /* For each entry in our servers list */
402         for (count = 0;; count++) {     /*s */
403
404             if (needsync) {
405                 /* Need a sync site. Lets try to quickly find it */
406                 if (aclient->syncSite) {
407                     newHost = aclient->syncSite;        /* already in network order */
408                     aclient->syncSite = 0;      /* Will reset if it works */
409                 } else if (aclient->conns[3]) {
410                     /* If there are fewer than four db servers in a cell,
411                      * there's no point in making the GetSyncSite call.
412                      * At best, it's a wash. At worst, it results in more
413                      * RPCs than you would otherwise make.
414                      */
415                     tc = aclient->conns[count];
416                     if (tc && rx_ConnError(tc)) {
417                         aclient->conns[count] = tc = ubik_RefreshConn(tc);
418                     }
419                     if (!tc)
420                         break;
421                     code = VOTE_GetSyncSite(tc, &newHost);
422                     if (aclient->initializationState != origLevel)
423                         goto restart;   /* somebody did a ubik_ClientInit */
424                     if (code)
425                         newHost = 0;
426                     newHost = htonl(newHost);   /* convert to network order */
427                 } else {
428                     newHost = 0;
429                 }
430                 if (newHost) {
431                     /* position count at the appropriate slot in the client
432                      * structure and retry. If we can't find in slot, we'll
433                      * just continue through the whole list 
434                      */
435                     for (i = 0; i < MAXSERVERS && aclient->conns[i]; i++) {
436                         rxp = rx_PeerOf(aclient->conns[i]);
437                         thisHost = rx_HostOf(rxp);
438                         if (!thisHost)
439                             break;
440                         if (thisHost == newHost) {
441                             if (chaseCount++ > 2)
442                                 break;  /* avoid loop asking */
443                             count = i;  /* this index is the sync site */
444                             break;
445                         }
446                     }
447                 }
448             }
449             /*needsync */
450             tc = aclient->conns[count];
451             if (tc && rx_ConnError(tc)) {
452                 aclient->conns[count] = tc = ubik_RefreshConn(tc);
453             }
454             if (!tc)
455                 break;
456
457             if ((pass == 0) && (aclient->states[count] & CFLastFailed)) {
458                 continue;       /* this guy's down */
459             }
460
461             rcode =
462                 (*aproc) (tc, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,
463                           p12, p13, p14, p15, p16);
464             if (aclient->initializationState != origLevel) {
465                 /* somebody did a ubik_ClientInit */
466                 if (rcode)
467                     goto restart;       /* call failed */
468                 else
469                     goto done;  /* call suceeded */
470             }
471             if (rcode < 0) {    /* network errors */
472                 aclient->states[count] |= CFLastFailed; /* Mark serer down */
473             } else if (rcode == UNOTSYNC) {
474                 needsync = 1;
475             } else if (rcode != UNOQUORUM) {
476                 /* either misc ubik code, or misc appl code, or success. */
477                 aclient->states[count] &= ~CFLastFailed;        /* mark server up */
478                 goto done;      /* all done */
479             }
480         }                       /*s */
481     }                           /*p */
482
483   done:
484     if (needsync) {
485         if (!inlist) {          /* Remember proc call that needs sync site */
486             LOCK_UCLNT_CACHE;
487             calls_needsync[synccount % SYNCCOUNT] = (int *)aproc;
488             synccount++;
489             UNLOCK_UCLNT_CACHE;
490             inlist = 1;
491         }
492         if (!rcode) {           /* Remember the sync site - cmd successful */
493             rxp = rx_PeerOf(aclient->conns[count]);
494             aclient->syncSite = rx_HostOf(rxp);
495         }
496     }
497     UNLOCK_UBIK_CLIENT(aclient);
498     return rcode;
499 }
500
501
502
503 /*!
504  * \brief Call this after getting back a #UNOTSYNC.
505  *
506  * \note Getting a #UNOTSYNC error code back does \b not guarantee
507  * that there is a sync site yet elected.  However, if there is a sync
508  * site out there somewhere, and you're trying an operation that
509  * requires a sync site, ubik will return #UNOTSYNC, indicating the
510  * operation won't work until you find a sync site
511  */
512 static int
513 try_GetSyncSite(register struct ubik_client *aclient, afs_int32 apos)
514 {
515     struct rx_peer *rxp;
516     afs_int32 code;
517     int i;
518     afs_int32 thisHost, newHost;
519     struct rx_connection *tc;
520     short origLevel;
521
522     origLevel = aclient->initializationState;
523
524     /* get this conn */
525     tc = aclient->conns[apos];
526     if (tc && rx_ConnError(tc)) {
527         aclient->conns[apos] = (tc = ubik_RefreshConn(tc));
528     }
529     if (!tc) {
530         return -1;
531     }
532
533     /* now see if we can find the sync site host */
534     code = VOTE_GetSyncSite(tc, &newHost);
535     if (aclient->initializationState != origLevel) {
536         return -1;              /* somebody did a ubik_ClientInit */
537     }
538
539     if (!code && newHost) {
540         newHost = htonl(newHost);       /* convert back to network order */
541
542         /*
543          * position count at the appropriate slot in the client
544          * structure and retry. If we can't find in slot, we'll just
545          * continue through the whole list
546          */
547         for (i = 0; i < MAXSERVERS; i++) {
548             rxp = rx_PeerOf(aclient->conns[i]);
549             thisHost = rx_HostOf(rxp);
550             if (!thisHost) {
551                 return -1;
552             } else if (thisHost == newHost) {
553                 return i;       /* we were told to use this one */
554             }
555         }
556     }
557     return -1;
558 }
559
560 #define NEED_LOCK 1
561 #define NO_LOCK 0
562
563 /*! 
564  * \brief Create an internal version of ubik_CallIter that takes an additional
565  * parameter - to indicate whether the ubik client handle has already
566  * been locked.
567  */
568 static afs_int32
569 CallIter(int (*aproc) (), register struct ubik_client *aclient, 
570          afs_int32 aflags, int *apos, long p1, long p2, long p3, long p4, 
571          long p5, long p6, long p7, long p8, long p9, long p10, long p11, 
572          long p12, long p13, long p14, long p15, long p16, int needlock)
573 {
574     register afs_int32 code;
575     struct rx_connection *tc;
576     short origLevel;
577
578     if (needlock) {
579         LOCK_UBIK_CLIENT(aclient);
580     }
581     origLevel = aclient->initializationState;
582
583     code = UNOSERVERS;
584
585     while (*apos < MAXSERVERS) {
586         /* tc is the next conn to try */
587         tc = aclient->conns[*apos];
588         if (!tc) {
589             if (needlock) {
590                 UNLOCK_UBIK_CLIENT(aclient);
591             }
592             return UNOSERVERS;
593         }
594
595         if (rx_ConnError(tc)) {
596             tc = ubik_RefreshConn(tc);
597             aclient->conns[*apos] = tc;
598         }
599
600         if ((aflags & UPUBIKONLY) && (aclient->states[*apos] & CFLastFailed)) {
601             (*apos)++;          /* try another one if this server is down */
602         } else {
603             break;              /* this is the desired path */
604         }
605     }
606     if (*apos >= MAXSERVERS) {
607         if (needlock) {
608             UNLOCK_UBIK_CLIENT(aclient);
609         }
610         return UNOSERVERS;
611     }
612
613     code =
614         (*aproc) (tc, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13,
615                   p14, p15, p16);
616     if (aclient->initializationState != origLevel) {
617         if (needlock) {
618             UNLOCK_UBIK_CLIENT(aclient);
619         }
620         return code;            /* somebody did a ubik_ClientInit */
621     }
622
623     /* what should I do in case of UNOQUORUM ? */
624     if (code < 0) {
625         aclient->states[*apos] |= CFLastFailed; /* network errors */
626     } else {
627         /* either misc ubik code, or misc application code or success. */
628         aclient->states[*apos] &= ~CFLastFailed;        /* operation worked */
629     }
630
631     (*apos)++;
632     if (needlock) {
633         UNLOCK_UBIK_CLIENT(aclient);
634     }
635     return code;
636 }
637
638 /*! 
639  * \brief Call this instead of stub and we'll guarantee to find a host that's up.
640  *
641  * \todo In the future, we should also put in a protocol to find the sync site.
642  */
643 afs_int32
644 ubik_Call_New(int (*aproc) (), register struct ubik_client *aclient, 
645               afs_int32 aflags, long p1, long p2, long p3, long p4, long p5, 
646               long p6, long p7, long p8, long p9, long p10, long p11, 
647               long p12, long p13, long p14, long p15, long p16)
648 {
649     afs_int32 code, rcode;
650     afs_int32 count;
651     afs_int32 temp;
652     int pass;
653     int stepBack;
654     short origLevel;
655
656     LOCK_UBIK_CLIENT(aclient);
657   restart:
658     rcode = UNOSERVERS;
659     origLevel = aclient->initializationState;
660
661     /* Do two passes. First pass only checks servers known running */
662     for (aflags |= UPUBIKONLY, pass = 0; pass < 2;
663          pass++, aflags &= ~UPUBIKONLY) {
664         stepBack = 0;
665         count = 0;
666         while (1) {
667             code =
668                 CallIter(aproc, aclient, aflags, &count, p1, p2, p3, p4, p5,
669                          p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16,
670                          NO_LOCK);
671             if (code && (aclient->initializationState != origLevel)) {
672                 goto restart;
673             }
674             if (code == UNOSERVERS) {
675                 break;
676             }
677             rcode = code;       /* remember code from last good call */
678
679             if (code == UNOTSYNC) {     /* means this requires a sync site */
680                 if (aclient->conns[3]) {        /* don't bother unless 4 or more srv */
681                     temp = try_GetSyncSite(aclient, count);
682                     if (aclient->initializationState != origLevel) {
683                         goto restart;   /* somebody did a ubik_ClientInit */
684                     }
685                     if ((temp >= 0) && ((temp > count) || (stepBack++ <= 2))) {
686                         count = temp;   /* generally try to make progress */
687                     }
688                 }
689             } else if ((code >= 0) && (code != UNOQUORUM)) {
690                 UNLOCK_UBIK_CLIENT(aclient);
691                 return code;    /* success or global error condition */
692             }
693         }
694     }
695     UNLOCK_UBIK_CLIENT(aclient);
696     return rcode;
697 }
698
699 /*!
700  * \brief This is part of an iterator.  It doesn't handle finding sync sites.
701  */
702 afs_int32
703 ubik_CallIter(int (*aproc) (), struct ubik_client *aclient,
704                                afs_int32 aflags, int *apos, long p1, long p2,
705                                long p3, long p4, long p5, long p6, long p7,
706                                long p8, long p9, long p10, long p11, long p12,
707                                long p13, long p14, long p15, long p16)
708 {
709     return CallIter(aproc, aclient, aflags, apos, p1, p2, p3, p4, p5, p6, p7,
710                     p8, p9, p10, p11, p12, p13, p14, p15, p16, NEED_LOCK);
711 }