📄 net_db.c
字号:
/* * $Id: net_db.c,v 1.136.2.1 1999/03/22 03:21:54 wessels Exp $ * * DEBUG: section 38 Network Measurement Database * AUTHOR: Duane Wessels * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"#if USE_ICMPtypedef struct { peer *p; StoreEntry *e; request_t *r; off_t seen; off_t used; size_t buf_sz; char *buf;} netdbExchangeState;static hash_table *addr_table = NULL;static hash_table *host_table = NULL;static struct in_addr networkFromInaddr(struct in_addr a);static void netdbRelease(netdbEntry * n);static void netdbHashInsert(netdbEntry * n, struct in_addr addr);static void netdbHashDelete(const char *key);static void netdbHostInsert(netdbEntry * n, const char *hostname);static void netdbHostDelete(const net_db_name * x);static void netdbPurgeLRU(void);static netdbEntry *netdbLookupHost(const char *key);static net_db_peer *netdbPeerByName(const netdbEntry * n, const char *);static net_db_peer *netdbPeerAdd(netdbEntry * n, peer * e);static char *netdbPeerName(const char *name);static IPH netdbSendPing;static QS sortPeerByRtt;static QS sortByRtt;static QS netdbLRU;static FREE netdbFreeNameEntry;static FREE netdbFreeNetdbEntry;static STCB netdbExchangeHandleReply;static void netdbExchangeDone(void *);/* We have to keep a local list of peer names. The Peers structure * gets freed during a reconfigure. We want this database to * remain persisitent, so _net_db_peer->peername points into this * linked list */static wordlist *peer_names = NULL;static voidnetdbHashInsert(netdbEntry * n, struct in_addr addr){ xstrncpy(n->network, inet_ntoa(networkFromInaddr(addr)), 16); n->key = n->network; assert(hash_lookup(addr_table, n->network) == NULL); hash_join(addr_table, (hash_link *) n);}static voidnetdbHashDelete(const char *key){ hash_link *hptr = hash_lookup(addr_table, key); if (hptr == NULL) { debug_trap("netdbHashDelete: key not found"); return; } hash_remove_link(addr_table, hptr);}static voidnetdbHostInsert(netdbEntry * n, const char *hostname){ net_db_name *x = memAllocate(MEM_NET_DB_NAME); x->name = xstrdup(hostname); x->next = n->hosts; n->hosts = x; x->net_db_entry = n; assert(hash_lookup(host_table, hostname) == NULL); hash_join(host_table, (hash_link *) x); n->link_count++;}static voidnetdbHostDelete(const net_db_name * x){ netdbEntry *n; net_db_name **X; assert(x != NULL); assert(x->net_db_entry != NULL); n = x->net_db_entry; n->link_count--; for (X = &n->hosts; *X; X = &(*X)->next) { if (*X == x) { *X = x->next; break; } } hash_remove_link(host_table, (hash_link *) x); xfree(x->name); memFree((void *) x, MEM_NET_DB_NAME);}static netdbEntry *netdbLookupHost(const char *key){ net_db_name *x = (net_db_name *) hash_lookup(host_table, key); return x ? x->net_db_entry : NULL;}static voidnetdbRelease(netdbEntry * n){ net_db_name *x; net_db_name *next; for (x = n->hosts; x; x = next) { next = x->next; netdbHostDelete(x); } n->hosts = NULL; safe_free(n->peers); n->peers = NULL; n->n_peers = 0; n->n_peers_alloc = 0; if (n->link_count == 0) { netdbHashDelete(n->network); memFree(n, MEM_NETDBENTRY); }}static intnetdbLRU(const void *A, const void *B){ const netdbEntry *const *n1 = A; const netdbEntry *const *n2 = B; if ((*n1)->last_use_time > (*n2)->last_use_time) return (1); if ((*n1)->last_use_time < (*n2)->last_use_time) return (-1); return (0);}static voidnetdbPurgeLRU(void){ netdbEntry *n; netdbEntry **list; int k = 0; int list_count = 0; int removed = 0; list = xcalloc(memInUse(MEM_NETDBENTRY), sizeof(netdbEntry *)); hash_first(addr_table); while ((n = (netdbEntry *) hash_next(addr_table))) { assert(list_count < memInUse(MEM_NETDBENTRY)); *(list + list_count) = n; list_count++; } qsort((char *) list, list_count, sizeof(netdbEntry *), netdbLRU); for (k = 0; k < list_count; k++) { if (memInUse(MEM_NETDBENTRY) < Config.Netdb.low) break; netdbRelease(*(list + k)); removed++; } xfree(list);}static netdbEntry *netdbLookupAddr(struct in_addr addr){ netdbEntry *n; char *key = inet_ntoa(networkFromInaddr(addr)); n = (netdbEntry *) hash_lookup(addr_table, key); return n;}static netdbEntry *netdbAdd(struct in_addr addr){ netdbEntry *n; if (memInUse(MEM_NETDBENTRY) > Config.Netdb.high) netdbPurgeLRU(); if ((n = netdbLookupAddr(addr)) == NULL) { n = memAllocate(MEM_NETDBENTRY); netdbHashInsert(n, addr); } return n;}static voidnetdbSendPing(const ipcache_addrs * ia, void *data){ struct in_addr addr; char *hostname = data; netdbEntry *n; netdbEntry *na; net_db_name *x; net_db_name **X; cbdataUnlock(hostname); if (ia == NULL) { cbdataFree(hostname); return; } addr = ia->in_addrs[ia->cur]; if ((n = netdbLookupHost(hostname)) == NULL) { n = netdbAdd(addr); netdbHostInsert(n, hostname); } else if ((na = netdbLookupAddr(addr)) != n) { /* *hostname moved from 'network n' to 'network na'! */ if (na == NULL) na = netdbAdd(addr); debug(38, 3) ("netdbSendPing: %s moved from %s to %s\n", hostname, n->network, na->network); x = (net_db_name *) hash_lookup(host_table, hostname); if (x == NULL) { debug(38, 1) ("netdbSendPing: net_db_name list bug: %s not found", hostname); cbdataFree(hostname); return; } /* remove net_db_name from 'network n' linked list */ for (X = &n->hosts; *X; X = &(*X)->next) { if (*X == x) { *X = x->next; break; } } n->link_count--; /* point to 'network na' from host entry */ x->net_db_entry = na; /* link net_db_name to 'network na' */ x->next = na->hosts; na->hosts = x; na->link_count++; n = na; } if (n->next_ping_time <= squid_curtime) { debug(38, 3) ("netdbSendPing: pinging %s\n", hostname); icmpDomainPing(addr, hostname); n->pings_sent++; n->next_ping_time = squid_curtime + Config.Netdb.period; n->last_use_time = squid_curtime; } cbdataFree(hostname);}static struct in_addrnetworkFromInaddr(struct in_addr a){ struct in_addr b; b.s_addr = ntohl(a.s_addr);#if USE_CLASSFUL if (IN_CLASSC(b.s_addr)) b.s_addr &= IN_CLASSC_NET; else if (IN_CLASSB(b.s_addr)) b.s_addr &= IN_CLASSB_NET; else if (IN_CLASSA(b.s_addr)) b.s_addr &= IN_CLASSA_NET;#else /* use /24 for everything */ b.s_addr &= IN_CLASSC_NET;#endif b.s_addr = htonl(b.s_addr); return b;}static intsortByRtt(const void *A, const void *B){ const netdbEntry *const *n1 = A; const netdbEntry *const *n2 = B; if ((*n1)->rtt > (*n2)->rtt) return 1; else if ((*n1)->rtt < (*n2)->rtt) return -1; else return 0;}static net_db_peer *netdbPeerByName(const netdbEntry * n, const char *peername){ int i; net_db_peer *p = n->peers; for (i = 0; i < n->n_peers; i++, p++) { if (!strcmp(p->peername, peername)) return p; } return NULL;}static net_db_peer *netdbPeerAdd(netdbEntry * n, peer * e){ net_db_peer *p; net_db_peer *o; int osize; int i; if (n->n_peers == n->n_peers_alloc) { o = n->peers; osize = n->n_peers_alloc; if (n->n_peers_alloc == 0) n->n_peers_alloc = 2; else n->n_peers_alloc <<= 1; debug(38, 3) ("netdbPeerAdd: Growing peer list for '%s' to %d\n", n->network, n->n_peers_alloc); n->peers = xcalloc(n->n_peers_alloc, sizeof(net_db_peer)); for (i = 0; i < osize; i++) *(n->peers + i) = *(o + i); if (osize) { safe_free(o); } } p = n->peers + n->n_peers; p->peername = netdbPeerName(e->host); n->n_peers++; return p;}static intsortPeerByRtt(const void *A, const void *B){ const net_db_peer *p1 = A; const net_db_peer *p2 = B; if (p1->rtt > p2->rtt) return 1; else if (p1->rtt < p2->rtt) return -1; else return 0;}static voidnetdbSaveState(void *foo){ LOCAL_ARRAY(char, path, SQUID_MAXPATHLEN); FILE *fp; netdbEntry *n; net_db_name *x; struct timeval start = current_time; int count = 0; snprintf(path, SQUID_MAXPATHLEN, "%s/netdb_state", storeSwapDir(0)); fp = fopen(path, "w"); if (fp == NULL) { debug(50, 1) ("netdbSaveState: %s: %s\n", path, xstrerror()); return; } hash_first(addr_table); while ((n = (netdbEntry *) hash_next(addr_table))) { if (n->pings_recv == 0) continue; fprintf(fp, "%s %d %d %10.5f %10.5f %d %d", n->network, n->pings_sent, n->pings_recv, n->hops, n->rtt, (int) n->next_ping_time, (int) n->last_use_time); for (x = n->hosts; x; x = x->next) fprintf(fp, " %s", x->name); fprintf(fp, "\n"); count++; } fclose(fp); getCurrentTime(); debug(38, 1) ("NETDB state saved; %d entries, %d msec\n", count, tvSubMsec(start, current_time)); eventAddIsh("netdbSaveState", netdbSaveState, NULL, 3600.0, 1);}static voidnetdbReloadState(void){ LOCAL_ARRAY(char, path, SQUID_MAXPATHLEN); char *buf; char *t; FILE *fp; netdbEntry *n; netdbEntry N; struct in_addr addr; int count = 0; struct timeval start = current_time; snprintf(path, SQUID_MAXPATHLEN, "%s/netdb_state", storeSwapDir(0)); fp = fopen(path, "r"); if (fp == NULL) return; buf = memAllocate(MEM_4K_BUF); while (fgets(buf, 4095, fp)) { memset(&N, '\0', sizeof(netdbEntry)); if ((t = strtok(buf, w_space)) == NULL) continue; if (!safe_inet_addr(t, &addr)) continue; if (netdbLookupAddr(addr) != NULL) /* no dups! */ continue; if ((t = strtok(NULL, w_space)) == NULL) continue; N.pings_sent = atoi(t); if ((t = strtok(NULL, w_space)) == NULL) continue; N.pings_recv = atoi(t); if (N.pings_recv == 0) continue; /* give this measurement low weight */ N.pings_sent = 1; N.pings_recv = 1; if ((t = strtok(NULL, w_space)) == NULL) continue; N.hops = atof(t); if ((t = strtok(NULL, w_space)) == NULL) continue; N.rtt = atof(t); if ((t = strtok(NULL, w_space)) == NULL) continue; N.next_ping_time = (time_t) atoi(t); if ((t = strtok(NULL, w_space)) == NULL) continue; N.last_use_time = (time_t) atoi(t); n = memAllocate(MEM_NETDBENTRY); xmemcpy(n, &N, sizeof(netdbEntry)); netdbHashInsert(n, addr); while ((t = strtok(NULL, w_space)) != NULL) { if (netdbLookupHost(t) != NULL) /* no dups! */ continue; netdbHostInsert(n, t); } count++; } memFree(buf, MEM_4K_BUF); fclose(fp); getCurrentTime(); debug(38, 1) ("NETDB state reloaded; %d entries, %d msec\n", count, tvSubMsec(start, current_time));}static char *netdbPeerName(const char *name){ wordlist *w; for (w = peer_names; w; w = w->next) { if (!strcmp(w->key, name)) return w->key; } w = wordlistAdd(&peer_names, name); return w->key;}static voidnetdbFreeNetdbEntry(void *data){ netdbEntry *n = data; safe_free(n->peers); memFree(n, MEM_NETDBENTRY);}static voidnetdbFreeNameEntry(void *data){ net_db_name *x = data; xfree(x->name); memFree(x, MEM_NET_DB_NAME);}static voidnetdbExchangeHandleReply(void *data, char *buf, ssize_t size){ netdbExchangeState *ex = data; int rec_sz = 0; off_t o; struct in_addr addr; double rtt; double hops; char *p; int j; HttpReply *rep; size_t hdr_sz; int nused = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -