static struct ropa_ccpair * add_client (struct ropa_cb *cb, struct ropa_client *c) { struct timeval tv; struct ropa_ccpair cckey, *cc; assert (cb && c); cckey.client = c; cckey.cb = cb; cc = hashtabsearch (ht_ccpairs, &cckey); if (cc) { listdel (lru_ccpair, cc->li); cc->li = listaddhead (lru_ccpair, cc); return cc; } /* The reverse of these are in break_ccpair */ callback_ref (cb); client_ref (c); cc = listdeltail (lru_ccpair); DIAGNOSTIC_CHECK_CCPAIR(cc); cc->li = NULL; if (ccpairs_inuse_p (cc)) break_ccpair (cc, TRUE); /* XXX do it for real */ gettimeofday(&tv, NULL); cc->expire = tv.tv_sec + 3600; heap_insert (heap_ccpairs, cc, &cc->heap); LWP_NoYieldSignal (heap_ccpairs); cc->cb_li = listaddtail (cb->ccpairs, cc); cc->client = c; cc->cb = cb; cc->li = listaddhead (lru_ccpair, cc); hashtabadd (ht_ccpairs, cc); mlog_log (MDEBROPA, "add_client: added %x to callback %x.%x.%x", c->addr[0].addr_in, cb->fid.Volume, cb->fid.Vnode, cb->fid.Unique); return cc; }
static void break_callback (struct ropa_cb *cb, struct ropa_client *caller, Bool break_own) { struct ropa_ccpair *cc; struct ropa_ccpair *own_cc = NULL; assert (cb); assert (cb->ccpairs); mlog_log (MDEBROPA, "break_callback: breaking callback %x.%x.%x (%d)", cb->fid.Volume, cb->fid.Vnode, cb->fid.Unique, break_own); callback_ref (cb); if (caller) client_ref (caller); while ((cc = listdelhead (cb->ccpairs)) != 0) { assert (cc->cb == cb); cc->cb_li = NULL; if (break_own) break_ccpair (cc, cc->client != caller); else if (cc->client == caller) own_cc = cc; else break_ccpair (cc, TRUE); } if (own_cc) own_cc->cb_li = listaddhead (cb->ccpairs, own_cc); callback_deref (cb); if (caller) client_deref (caller); }
void mnode_free (struct mnode *node, Bool bad) { if (node->li) listdel (mnode_lru, node->li); /* bad -> reread 0 -> close */ if (bad) { if (node->flags.fdp) close (node->fd); memset (&node->flags, 0, sizeof (node->flags)); } if (--node->ref == 0) { if (node->flags.fdp) { close (node->fd); node->flags.fdp = FALSE; } if (node->flags.removedp == TRUE) { hashtabdel (mnode_htab, node); node->flags.removedp = FALSE; } mnode_numfree++; node->li = listaddtail (mnode_lru, node); } else node->li = listaddhead (mnode_lru, node); }
void mnode_init (unsigned num) { struct mnode *nodes = calloc (sizeof(struct mnode), num); int i; mnode_numfree = mnode_nodes = num; if (nodes == NULL) errx (1, "mnode_init: calloc failed"); mnode_lru = listnew(); if (mnode_lru == NULL) errx (1, "mnode_init: listnew returned NULL"); for (i = 0; i < num ;i++) { nodes[i].li = listaddhead (mnode_lru, &nodes[i]); assert(nodes[i].li); } mnode_htab = hashtabnew (num * 2, /* XXX */ mnode_cmp, mnode_hash); if (mnode_htab == NULL) errx (1, "mnode_init: hashtabnew returned NULL"); }
static void client_ref (struct ropa_client *c) { assert (c->ref >= 0); if (c->li) listdel (lru_clients, c->li); c->ref++; if (c->li) c->li = listaddhead (lru_clients, c); }
int mnode_find (const AFSFid *fid, struct mnode **node) { struct mnode ptr, *res = NULL; ptr.fid = *fid; while (res == NULL) { res = hashtabsearch (mnode_htab, &ptr); if (res) { if (res->flags.removedp == TRUE) return ENOENT; if (res->li) listdel (mnode_lru, res->li); if (res->ref == 0) mnode_numfree--; res->ref++; } else if (mnode_numfree != 0) { res = listdeltail (mnode_lru); assert (res); assert (res->ref == 0); hashtabdel (mnode_htab, res); reset_node (res, fid); hashtabadd (mnode_htab, res); res->ref++; } else { /* XXX */ mlog_log (MDEBWARN, "mnode_find: no free nodes, had to malloc()"); res = malloc(sizeof(struct mnode)); if (res == NULL) { mlog_log (MDEBWARN, "mnode_find: malloc() failed"); LWP_DispatchProcess(); /* Yield */ continue; } reset_node (res, fid); hashtabadd (mnode_htab, res); res->ref++; } } assert(res->flags.removedp == FALSE); *node = res; res->li = listaddhead (mnode_lru, *node); return 0; }
static void callback_ref (struct ropa_cb *cb) { assert (cb->ref >= 0); if (cb->li) listdel (lru_callback, cb->li); cb->ref++; mlog_log (MDEBROPA, "cb_ref: %x.%x.%x (%d)", cb->fid.Volume, cb->fid.Vnode, cb->fid.Unique, cb->ref); if (cb->li) cb->li = listaddhead (lru_callback, cb); }
static void create_new_connections (unsigned n) { unsigned i; ConnCacheEntry *entries; entries = (ConnCacheEntry*)calloc (n, sizeof (ConnCacheEntry)); if (entries == NULL) arla_errx (1, ADEBERROR, "conncache: calloc failed"); for (i = 0; i < n; ++i) { entries[i].connection = NULL; entries[i].refcount = 0; entries[i].parent = NULL; entries[i].probe_le = NULL; listaddhead (connfreelist, &entries[i]); } nconnections += n; }
void mnode_remove (const AFSFid *fid) { struct mnode ptr, *res; ptr.fid = *fid; res = hashtabsearch (mnode_htab, &ptr); if (res) { if (res->ref == 0 && res->flags.fdp) { close (res->fd); res->flags.fdp = FALSE; } if (res->li) listdel (mnode_lru, res->li); res->li = listaddhead (mnode_lru, res); res->flags.removedp = TRUE; } }
static void recycle_conn (ConnCacheEntry *e) { assert (e->refcount == 0); if (e->parent != NULL) { conn_free (e->parent); e->parent = NULL; } if (e->probe_le != NULL) { listdel (connprobelist, e->probe_le); e->probe_le = NULL; } if (!e->flags.killme) hashtabdel (connhtab, e); rx_DestroyConnection (e->connection); memset (e, 0, sizeof(*e)); listaddhead (connfreelist, e); --nactive_connections; }
int vld_init (void) { struct dp_part *dp; int ret, partnum, i; db_lru = listnew(); if (db_lru == NULL) errx (1, "vld_init: db_lru == NULL"); for (i = 0; i < 100 /* XXX */ ; i++) listaddhead (db_lru, NULL); vol_list = listnew(); if (vol_list == NULL) errx (1, "vld_init: vol_list == NULL"); volume_htab = hashtabnew(volume_htab_sz, volume_cmp, volume_hash); if (volume_htab == NULL) errx (1, "vld_init: volume_htab == NULL"); for (partnum = 0; partnum < 'z'-'a'; partnum++) { ret = dp_create (partnum , &dp); if (ret) { warnx ("vld_init: dp_create(%d) returned %d", partnum, ret); continue; } ret = dp_findvol (dp, register_vols_cb, dp); if (ret) warnx ("vld_init: dp_findvol returned: %d", ret); dp_free (dp); } return 0; }
int ropa_getcallback (uint32_t host, uint16_t port, const struct AFSFid *fid, AFSCallBack *callback, int32_t voltype) { struct ropa_client *c; struct ropa_cb cbkey, *cb; struct ropa_ccpair *cc ; struct AFSFid callback_fid; debug_print_callbacks(); c = client_query (host, port); if (c == NULL) { mlog_log (MDEBROPA, "ropa_getcallback: didn't find client %x/%d", host, port); update_callback_time (DEFAULT_TIMEOUT, callback, CBSHARED); return 0; } /* * At this point the client should be firmly set * in the ropa client database. */ #if 0 if (c->have_outstanding_callbacks) break_outstanding_callbacks (c); #endif if (voltype == RWVOL) { callback_fid = *fid; } else { callback_fid.Volume = fid->Volume; callback_fid.Vnode = 0; callback_fid.Unique = 0; } cbkey.fid = callback_fid; cb = hashtabsearch (ht_callbacks, &cbkey); if (cb == NULL) { cb = listdeltail (lru_callback); DIAGNOSTIC_CHECK_CALLBACK(cb); cb->li = NULL; if (callback_inuse_p (cb)) { break_callback (cb, NULL, FALSE); callback_ref(cb); } else { callback_ref(cb); cb->li = listaddhead (lru_callback, cb); } cb->fid = callback_fid; hashtabadd (ht_callbacks, cb); mlog_log (MDEBROPA, "ropa_getcallback: added callback %x.%x.%x:%x", callback_fid.Volume, callback_fid.Vnode, callback_fid.Unique, host); } else { mlog_log (MDEBROPA, "ropa_getcallback: found callback %x.%x.%x:%x", callback_fid.Volume, callback_fid.Vnode, callback_fid.Unique, host); callback_ref(cb); } cc = add_client (cb, c); callback_deref (cb); update_callback (cc, callback, CBSHARED); debug_print_callbacks(); return 0; }
static struct ropa_client * client_query (uint32_t host, uint16_t port) { struct ropa_client *c, *c_new; int ret; c = client_query_notalkback(host, port); if (c == NULL) { interfaceAddr remote; struct rx_connection *conn = NULL; c = obtain_client(); assert (c->state == ROPAC_FREE && c->li == NULL); c->state = ROPAC_LOOKUP_U; c->flags |= ROPAF_LOOKUP; client_init (c, host, port, NULL, NULL); conn = rx_NewConnection (host, port, CM_SERVICE_ID, rxnull_NewClientSecurityObject(), 0); if (conn == NULL) { free(c); return NULL; } retry: switch (c->state) { case ROPAC_DEAD: c->li = listaddtail (lru_clients, c); ret = ENETDOWN; break; case ROPAC_LOOKUP_U: ret = RXAFSCB_WhoAreYou (conn, &remote); if (ret == RXGEN_OPCODE) { c->state = ROPAC_LOOKUP; goto retry; } else if (ret == RX_CALL_DEAD) { c->state = ROPAC_DEAD; goto retry; } else { struct ropa_client ckey; ckey.uuid = remote.uuid; c_new = hashtabsearch (ht_clients_uuid, &ckey); if (c_new == NULL) { client_init (c, host, port, &remote.uuid, NULL); ret = RXAFSCB_InitCallBackState3(conn, &server_uuid); } else { client_update_interfaces (c_new, host, port, &remote); disconnect_client (c); c = c_new; listdel(lru_clients, c->li); c->li = NULL; } } break; case ROPAC_LOOKUP: { afsUUID uuid; ret = RXAFSCB_InitCallBackState(conn); if (ret == RX_CALL_DEAD) { c->state = ROPAC_DEAD; goto retry; } uuid_init_simple (&uuid, host); client_init (c, host, port, &uuid, NULL); break; } default: exit(-1); } rx_DestroyConnection (conn); if ((c->flags & ROPAF_WAITING) != 0) LWP_NoYieldSignal (c); c->flags &= ~(ROPAF_LOOKUP|ROPAF_WAITING); if (ret) { assert (c->li != NULL); return NULL; } assert (c->li == NULL); c->li = listaddhead (lru_clients, c); } else { /* c != NULL */ if ((c->flags & ROPAF_LOOKUP) != 0) { c->flags |= ROPAF_WAITING; LWP_WaitProcess (c); } assert (c->li != NULL); } return c; }