*** empty log message ***
[arla.git] / arlad / poller.c
blob6b1c9efc0c734a97a1ca73b8f87b39b7d7accafd
1 /*
2 * Copyright (c) 2002, Stockholms universitet
3 * (Stockholm University, Stockholm Sweden)
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the university nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
35 * Poller of fileserver
37 * Its part of the afs protocol that you need to talk the server now
38 * and then to make sure you don't have any droped callbacks.
40 * It is in its own module since mixing it with connection makes the
41 * connection code ever harder to read and understand the it is today,
42 * and there is enough of strange dependencies between clear conns and
43 * auth/crypto conns today and when they are allowed to be gc-ed, etc.
47 #include "arla_local.h"
48 #ifdef RCSID
49 RCSID("$Id$") ;
50 #endif
52 #define POLLERCACHESIZE 101
54 #define POLLERHEAPSIZE 101
56 /* Hashtable of connections */
57 static Hashtab *pollerhtab;
59 /* Heap for poller */
60 Heap *pollerheap;
63 int poller_timeout = 300; /* 5 min */
64 int poller_downhost_timeout = 60; /* 1 min */
66 static PROCESS poller_pid;
68 enum { POLLER_RUNNING, POLLER_SLEEPING, POLLER_WAITING } poller_status;
71 * Functions for handling entries into the poller cache.
74 static int
75 pollercmp (void *a, void *b)
77 PollerEntry *c1 = (PollerEntry*)a;
78 PollerEntry *c2 = (PollerEntry*)b;
80 return c1->server != c2->server;
83 static unsigned int
84 pollerhash (void *a)
86 PollerEntry *c = (PollerEntry*)a;
88 return c->server;
91 static int
92 poller_time_cmp (const void *a, const void *b)
94 PollerEntry *c1 = (PollerEntry*)a;
95 PollerEntry *c2 = (PollerEntry*)b;
97 return c1->server - c2->server;
102 * Add it to heap, use the minium of cell's timeout value and
103 * poller_{,downhost_}timeout.
106 static void
107 poller_add(PollerEntry *e, int host_dead, cell_entry *c)
109 time_t timeout = 0;
111 if (c)
112 timeout = cell_get_poller_time(c);
114 if (timeout == 0)
115 timeout = max(poller_timeout, poller_downhost_timeout);
117 if (host_dead == 0)
118 timeout = min(poller_timeout, timeout);
119 else
120 timeout = min(poller_downhost_timeout, timeout);
122 e->timeout = timeout + time(NULL);
124 heap_insert(pollerheap, e, &e->heapptr);
126 switch(poller_status) {
127 case POLLER_SLEEPING:
128 /* we can only insert before first entry if its the short
129 * timeout, that is host_dead -> poller_downhost_timeout */
130 if (host_dead)
131 IOMGR_Cancel(poller_pid);
132 break;
133 case POLLER_WAITING:
134 LWP_NoYieldSignal(poller_add);
135 break;
136 case POLLER_RUNNING:
137 break;
138 default:
139 abort();
145 * Add a poller event for this conn, there is really a fcache entry
146 * that will need to be refreshed.
149 PollerEntry *
150 poller_add_conn(ConnCacheEntry *conn)
152 PollerEntry *e, key;
153 cell_entry *cell;
155 key.server = rx_HostOf(rx_PeerOf(conn->connection));
157 cell = cell_get_by_id(conn->cell);
159 e = hashtabsearch(pollerhtab, &key);
160 if (e == NULL) {
161 e = malloc(sizeof(*e));
162 if (e == NULL)
163 return NULL;
165 e->server = rx_HostOf(rx_PeerOf(conn->connection));
166 e->cell = conn->cell;
167 e->refcount = 0;
168 hashtabadd(pollerhtab, e);
169 } else
170 heap_remove(pollerheap, e->heapptr);
172 e->refcount++;
173 poller_add(e, 0, cell);
175 return e;
178 void
179 poller_remove(PollerEntry *e)
181 assert(e->refcount > 0);
183 e->refcount--;
184 if (e->refcount == 0) {
185 hashtabdel(pollerhtab, e);
186 heap_remove(pollerheap, e->heapptr);
187 free(e);
191 struct poller_intr_arg {
192 poller_iter_func func;
193 void *arg;
196 static Bool
197 poller_foreach_func(void *ptr, void *arg)
199 PollerEntry *e = ptr;
200 struct poller_intr_arg *a = arg;
201 e->refcount++;
202 (*a->func)(e->cell, e->server, a->arg);
203 poller_remove(e);
204 return FALSE;
208 poller_foreach(poller_iter_func iter_func, void *arg)
210 struct poller_intr_arg a;
212 a.arg = arg;
213 a.func = iter_func;
214 hashtabforeach(pollerhtab, poller_foreach_func, &a);
216 return 0;
224 * Loop waiting for things servers to probe.
227 static void
228 poller (char *arg)
230 cell_entry *cell;
231 PollerEntry *e;
232 time_t now;
233 int host_dead_p;
235 for (;;) {
236 poller_status = POLLER_RUNNING;
238 arla_warnx(ADEBCONN, "poller waiting");
240 now = time(NULL);
242 e = (PollerEntry *)heap_head(pollerheap);
243 if (e == NULL) {
244 poller_status = POLLER_WAITING;
245 LWP_WaitProcess(poller_add);
246 continue;
247 } else if (e->timeout > now) {
248 poller_status = POLLER_SLEEPING;
249 IOMGR_Sleep (e->timeout - now);
250 continue;
253 arla_warnx(ADEBCONN, "running poller");
255 e->refcount++;
257 /* XXX should a dead host break callbacks ? */
259 host_dead_p = 0;
261 if (connected_mode != DISCONNECTED) {
262 ConnCacheEntry *conn;
263 CredCacheEntry *ce;
265 ce = cred_get (e->cell, 0, CRED_NONE);
266 assert (ce != NULL);
268 conn = conn_get (e->cell, e->server, afsport,
269 FS_SERVICE_ID, fs_probe, ce);
270 cred_free (ce);
272 if (conn) {
273 if (!conn_isalivep (conn))
274 host_dead_p = 1;
275 else if (fs_probe(conn->connection) != 0)
276 host_dead_p = 1;
277 conn_free(conn);
278 } else
279 host_dead_p = 1;
282 cell = cell_get_by_id(e->cell);
284 e->refcount--;
286 heap_remove(pollerheap, e->heapptr);
287 poller_add(e, host_dead_p, cell);
289 arla_warnx(ADEBCONN, "poller done");
294 * Find and return the cell for given `server', if the cell can't be
295 * found, return -1.
298 int32_t
299 poller_host2cell(uint32_t server)
301 PollerEntry *e, key;
303 key.server = server;
305 e = hashtabsearch(pollerhtab, &key);
306 if (e == NULL)
307 return -1;
308 return e->cell;
312 * Initialize the poller.
315 void
316 poller_init (void)
318 arla_warnx (ADEBCONN, "initpoller");
320 pollerhtab = hashtabnew (POLLERCACHESIZE, pollercmp, pollerhash);
321 if (pollerhtab == NULL)
322 arla_errx (1, ADEBERROR, "poller_init: hashtabnew failed");
324 pollerheap = heap_new(POLLERHEAPSIZE, poller_time_cmp);
325 if (pollerheap == NULL)
326 arla_errx (1, ADEBERROR, "poller_init: heap_new failed");
328 poller_status = POLLER_RUNNING;
330 if (LWP_CreateProcess (poller, 0, 1, NULL, "poller", &poller_pid))
331 arla_errx (1, ADEBERROR,
332 "conn: cannot create poller thread");