From: wessels <> Date: Fri, 8 May 1998 12:34:59 +0000 (+0000) Subject: URN changes -- sorting the output by RTT X-Git-Tag: SQUID_3_0_PRE1~3368 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9ce5e3e62a4c519fbc1d524ceaa170fa3bf7a634;p=thirdparty%2Fsquid.git URN changes -- sorting the output by RTT --- diff --git a/src/protos.h b/src/protos.h index be524eea45..f1b20c416d 100644 --- a/src/protos.h +++ b/src/protos.h @@ -846,6 +846,7 @@ extern int matchDomainName(const char *d, const char *h); extern int urlCheckRequest(const request_t *); extern int urlDefaultPort(protocol_t p); extern char *urlCanonicalClean(const request_t *); +extern char *urlHostname(const char *url); extern void useragentOpenLog(void); extern void useragentRotateLog(void); diff --git a/src/url.cc b/src/url.cc index 5e63db9a9e..adb10b7505 100644 --- a/src/url.cc +++ b/src/url.cc @@ -1,6 +1,6 @@ /* - * $Id: url.cc,v 1.89 1998/05/05 03:50:02 wessels Exp $ + * $Id: url.cc,v 1.90 1998/05/08 06:34:59 wessels Exp $ * * DEBUG: section 23 URL Parsing * AUTHOR: Duane Wessels @@ -443,3 +443,34 @@ urlCheckRequest(const request_t * r) } return rc; } + +/* + * Quick-n-dirty host extraction from a URL. Steps: + * Look for a colon + * Skip any '/' after the colon + * Copy the next SQUID_MAXHOSTNAMELEN bytes to host[] + * Look for an ending '/' or ':' and terminate + * Look for login info preceeded by '@' + */ +char * +urlHostname(const char *url) +{ + LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN); + char *t; + host[0] = '\0'; + if (NULL == (t = strchr(url, ':'))) + return NULL; + t++; + while (*t != '\0' && *t == '/') + t++; + xstrncpy(host, t, SQUIDHOSTNAMELEN); + if ((t = strchr(host, '/'))) + *t = '\0'; + if ((t = strchr(host, ':'))) + *t = '\0'; + if ((t = strrchr(host, '@'))) { + t++; + xmemmove(host, t, strlen(t)+1); + } + return host; +} diff --git a/src/urn.cc b/src/urn.cc index 00bfcd1729..85e156d182 100644 --- a/src/urn.cc +++ b/src/urn.cc @@ -1,7 +1,7 @@ /* * - * $Id: urn.cc,v 1.28 1998/05/01 22:13:32 wessels Exp $ + * $Id: urn.cc,v 1.29 1998/05/08 06:35:00 wessels Exp $ * * DEBUG: section 52 URN Parsing * AUTHOR: Kostas Anagnostakis @@ -32,10 +32,6 @@ #include "squid.h" -static STCB urnHandleReply; -static wordlist *urnParseReply(const char *inbuf); -static const char *const crlf = "\r\n"; - enum { URN_FORCE_MENU }; @@ -48,52 +44,52 @@ typedef struct { int flags; } UrnState; -wordlist * -urnFindMinRtt(wordlist * urls, method_t m, int *rtt_ret) +typedef struct { + char *url; + char *host; + int rtt; + struct { + int cached; + } flags; +} url_entry; + +static STCB urnHandleReply; +static url_entry *urnParseReply(const char *inbuf, method_t); +static const char *const crlf = "\r\n"; +static QS url_entry_sort; + +url_entry * +urnFindMinRtt(url_entry * urls, method_t m, int *rtt_ret) { int min_rtt = 0; - request_t *r; - int rtt; - wordlist *w; - wordlist *min_w = NULL; + url_entry *u = NULL; + url_entry *min_u = NULL; + int i; int urlcnt = 0; debug(52, 3) ("urnFindMinRtt\n"); assert(urls != NULL); - for (w = urls; w; w = w->next) + for (i = 0; NULL != (urls+i)->url; i++) urlcnt++; - if (urlcnt == 1) { - debug(52, 3) ("Only one URL - return it!\n"); - return(urls); + if (1 == urlcnt) { + debug(52, 3) ("urnFindMinRtt: Only one URL - return it!\n"); + return urls; } - for (w = urls; w; w = w->next) { - r = urlParse(m, w->key); - if (r == NULL) - continue; - debug(52, 3) ("Parsed %s\n", w->key); - rtt = netdbHostRtt(r->host); - if (rtt == 0) { - debug(52, 3) ("Pinging %s\n", r->host); - netdbPingSite(r->host); - stringClean(&r->urlpath); - memFree(MEM_REQUEST_T, r); + for (i = 0; ihost, u->rtt); + if (u->rtt == 0) continue; - } - debug(52, 3) ("%s rtt=%d\n", r->host, rtt); - if (rtt == 0) + if (u->rtt > min_rtt && min_rtt != 0) continue; - if (rtt > min_rtt && min_rtt != 0) - continue; - min_rtt = rtt; - min_w = w; - stringClean(&r->urlpath); - memFree(MEM_REQUEST_T, r); + min_rtt = u->rtt; + min_u = u; } if (rtt_ret) *rtt_ret = min_rtt; debug(52, 1) ("urnFindMinRtt: Returning '%s' RTT %d\n", - min_w ? min_w->key : "NONE", + min_u ? min_u->url : "NONE", min_rtt); - return min_w; + return min_u; } void @@ -164,6 +160,21 @@ urnStart(request_t * r, StoreEntry * e) urnState); } +static int +url_entry_sort(const void *A, const void *B) +{ + const url_entry *u1 = A; + const url_entry *u2 = B; + if (u2->rtt == u1->rtt) + return 0; + else if (0 == u1->rtt) + return 1; + else if (0 == u2->rtt) + return 1; + else + return u1->rtt - u2->rtt; +} + static void urnHandleReply(void *data, char *buf, ssize_t size) { @@ -173,13 +184,12 @@ urnHandleReply(void *data, char *buf, ssize_t size) char *s = NULL; size_t k; HttpReply *rep; - wordlist *w; - wordlist *urls; - wordlist *min_w; + url_entry *urls; + url_entry *min_u; MemBuf mb; ErrorState *err; - double tmprtt; - StoreEntry *tmpentry; + int i; + int urlcnt = 0; debug(52, 3) ("urnHandleReply: Called with size=%d.\n", size); if (urlres_e->store_status == STORE_ABORTED) { @@ -225,7 +235,9 @@ urnHandleReply(void *data, char *buf, ssize_t size) } while (isspace(*s)) s++; - urls = urnParseReply(s); + urls = urnParseReply(s, urnState->request->method); + for (i = 0; NULL != (urls+i)->url; i++) + urlcnt++; if (urls == NULL) { /* unkown URN error */ debug(52, 3) ("urnTranslateDone: unknown URN %s\n", storeUrl(e)); err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND); @@ -234,22 +246,27 @@ urnHandleReply(void *data, char *buf, ssize_t size) errorAppendEntry(e, err); return; } - min_w = urnFindMinRtt(urls, urnState->request->method, NULL); + min_u = urnFindMinRtt(urls, urnState->request->method, NULL); + qsort(urls, urlcnt, sizeof(*urls), url_entry_sort); storeBuffer(e); memBufDefInit(&mb); memBufPrintf(&mb, "Select URL for %s\n" "

Select URL for %s

\n" "\n", storeUrl(e), storeUrl(e)); - for (w = urls; w; w = w->next) { - request_t *tmpr = urlParse(urnState->request->method, w->key); - const cache_key *tmpk = storeKeyPublic(w->key, urnState->request->method); - tmpentry = storeGet(tmpk); - if (tmpr && tmpr->host && (tmprtt = netdbHostRtt(tmpr->host))) - memBufPrintf(&mb, "\n", - w->key, w->key, tmprtt, tmpentry ? " [cached]" : " "); + for (i = 0; i < urlcnt; i++) { + memBufPrintf(&mb, + "", + (urls+i)->url, (urls+i)->url); + if ((urls+i)->rtt > 0) + memBufPrintf(&mb, + "", + (urls+i)->rtt); else - memBufPrintf(&mb, "", w->key, w->key); + memBufPrintf(&mb, ""); + memBufPrintf(&mb, + "\n", + (urls+i)->flags.cached ? " [cached]" : " "); } memBufPrintf(&mb, "
%s%4.0f ms%s
%s%4d ms
%s
Unknown%s
" @@ -264,14 +281,18 @@ urnHandleReply(void *data, char *buf, ssize_t size) "text/html", mb.size, 0, squid_curtime); if (EBIT_TEST(urnState->flags, URN_FORCE_MENU)) { debug(51, 3) ("urnHandleReply: forcing menu\n"); - } else if (min_w) { - httpHeaderPutStr(&rep->header, HDR_LOCATION, min_w->key); + } else if (min_u) { + httpHeaderPutStr(&rep->header, HDR_LOCATION, min_u->url); } httpBodySet(&rep->body, mb.buf, mb.size + 1, memBufFreeFunc(&mb)); httpReplySwapOut(rep, e); storeComplete(e); memFree(MEM_4K_BUF, buf); - wordlistDestroy(&urls); + for (i = 0; i < urlcnt; i++) { + safe_free((urls+i)->url); + safe_free((urls+i)->host); + } + safe_free(urls); /* mb was frozen with memBufFreeFunc call, so we must not clean it */ storeUnregister(urlres_e, urnState); storeUnlockObject(urlres_e); @@ -281,23 +302,45 @@ urnHandleReply(void *data, char *buf, ssize_t size) cbdataFree(urnState); } -static wordlist * -urnParseReply(const char *inbuf) +static url_entry * +urnParseReply(const char *inbuf, method_t m) { char *buf = xstrdup(inbuf); char *token; - wordlist *u; - wordlist *head = NULL; - wordlist **last = &head; + char *url; + char *host; + const cache_key *key; + int rtt; + url_entry *list; + url_entry *old; + int n = 32; + int i = 0; debug(52, 3) ("urnParseReply\n"); + list = xcalloc(n + 1, sizeof(*list)); for (token = strtok(buf, crlf); token; token = strtok(NULL, crlf)) { debug(52, 3) ("urnParseReply: got '%s'\n", token); - u = xmalloc(sizeof(wordlist)); - u->key = xstrdup(token); - u->next = NULL; - *last = u; - last = &u->next; + if (i == n) { + old = list; + n <<= 2; + list = xcalloc(n + 1, sizeof(*list)); + xmemcpy(list, old, i * sizeof(*list)); + safe_free(old); + } + url = xstrdup(token); + host = urlHostname(url); + if (NULL == host) + continue; + rtt = netdbHostRtt(host); + if (0 == rtt) { + debug(52, 3) ("urnParseReply: Pinging %s\n", host); + netdbPingSite(host); + } + key = storeKeyPublic(url, m); + (list + i)->url = url; + (list + i)->host = xstrdup(host); + (list + i)->rtt = rtt; + (list + i)->flags.cached = storeGet(key) ? 1 : 0; + i++; } - safe_free(buf); - return head; + return list; }