#
# Makefile for the Squid Object Cache server
#
-# $Id: Makefile.in,v 1.27 1996/07/09 04:46:49 wessels Exp $
+# $Id: Makefile.in,v 1.28 1996/07/11 17:42:34 wessels Exp $
#
# Uncomment and customize the following to suit your needs:
#
fdstat.o filemap.o ftp.o gopher.o \
hash.o http.o icp.o ident.o ipcache.o \
main.o mime.o neighbors.o objcache.o \
- proto.o send-announce.o ssl.o stack.o stat.o stmem.o \
+ proto.o redirect.o send-announce.o ssl.o stack.o \
+ stat.o stmem.o \
store.o storetoString.o tools.o ttl.o \
url.o wais.o $(XTRA_OBJS)
/*
- * $Id: cache_cf.cc,v 1.57 1996/07/09 05:06:17 wessels Exp $
+ * $Id: cache_cf.cc,v 1.58 1996/07/11 17:42:36 wessels Exp $
*
* DEBUG: section 3 Configuration File Parsing
* AUTHOR: Harvest Derived
int connectTimeout;
int ageMaxDefault;
int cleanRate;
- int dnsChildren;
int maxRequestSize;
double hotVmFactor;
struct {
char *ftpget;
char *ftpget_opts;
char *dnsserver;
+ char *redirect;
} Program;
+ int dnsChildren;
+ int redirectChildren;
int sourcePing;
int quickAbort;
int commonLogFormat;
#define DefaultConnectTimeout (2 * 60) /* 2 min */
#define DefaultDefaultAgeMax (3600 * 24 * 30) /* 30 days */
#define DefaultCleanRate -1 /* disabled */
-#define DefaultDnsChildren 5 /* 3 processes */
+#define DefaultDnsChildren 5 /* 5 processes */
+#define DefaultRedirectChildren 5 /* 5 processes */
#define DefaultMaxRequestSize (100 << 10) /* 100Kb */
#define DefaultHotVmFactor 0.0 /* disabled */
#define DefaultFtpgetProgram DEFAULT_FTPGET
#define DefaultFtpgetOptions ""
#define DefaultDnsserverProgram DEFAULT_DNSSERVER
+#define DefaultRedirectProgram (char *)NULL /* default NONE */
#define DefaultEffectiveUser (char *)NULL /* default NONE */
#define DefaultEffectiveGroup (char *)NULL /* default NONE */
#define DefaultAppendDomain (char *)NULL /* default NONE */
Config.dnsChildren = i;
}
+static void parseRedirectChildrenLine()
+{
+ char *token;
+ int i;
+ GetInteger(i);
+ Config.redirectChildren = i;
+}
+
static void parseRequestSizeLine()
{
char *token;
Config.Program.dnsserver = xstrdup(token);
}
+static void parseRedirectProgramLine()
+{
+ char *token;
+ token = strtok(NULL, w_space);
+ if (token == NULL)
+ self_destruct();
+ safe_free(Config.Program.redirect);
+ Config.Program.redirect = xstrdup(token);
+}
+
static void parseEmulateLine()
{
char *token;
else if (!strcmp(token, "dns_children"))
parseDnsChildrenLine();
+ else if (!strcmp(token, "redirect_program"))
+ parseRedirectProgramLine();
+ else if (!strcmp(token, "redirect_children"))
+ parseRedirectChildrenLine();
+
/* Parse source_ping line */
else if (!strcmp(token, "source_ping"))
parseSourcePingLine();
if (getDnsChildren() < 1) {
printf("WARNING: dns_children was set to a bad value: %d\n",
getDnsChildren());
- printf("Setting it to the default (3).\n");
- Config.dnsChildren = 3;
+ Config.dnsChildren = DefaultDnsChildren;
+ printf("Setting it to the default (%d).\n", DefaultDnsChildren);
} else if (getDnsChildren() > DefaultDnsChildrenMax) {
printf("WARNING: dns_children was set to a bad value: %d\n",
getDnsChildren());
printf("Setting it to the maximum (%d).\n", DefaultDnsChildrenMax);
Config.dnsChildren = DefaultDnsChildrenMax;
}
+ if (getRedirectChildren() < 1) {
+ printf("WARNING: redirect_children was set to a bad value: %d\n",
+ getRedirectChildren());
+ Config.redirectChildren = DefaultRedirectChildren;
+ printf("Setting it to the default (%d).\n", DefaultRedirectChildren);
+ } else if (getRedirectChildren() > DefaultRedirectChildrenMax) {
+ printf("WARNING: redirect_children was set to a bad value: %d\n",
+ getRedirectChildren());
+ printf("Setting it to the maximum (%d).\n", DefaultRedirectChildrenMax);
+ Config.redirectChildren = DefaultRedirectChildrenMax;
+ }
fclose(fp);
configDoConfigure();
{
return Config.dnsChildren;
}
+int getRedirectChildren()
+{
+ return Config.redirectChildren;
+}
int getQuickAbort()
{
return Config.quickAbort;
{
return Config.Program.dnsserver;
}
+char *getRedirectProgram()
+{
+ return Config.Program.redirect;
+}
char *getFtpProgram()
{
return Config.Program.ftpget;
safe_free(Config.Program.ftpget);
safe_free(Config.Program.ftpget_opts);
safe_free(Config.Program.dnsserver);
+ safe_free(Config.Program.redirect);
safe_free(Config.Accel.host);
safe_free(Config.Accel.prefix);
safe_free(Config.appendDomain);
Config.ageMaxDefault = DefaultDefaultAgeMax;
Config.cleanRate = DefaultCleanRate;
Config.dnsChildren = DefaultDnsChildren;
+ Config.redirectChildren = DefaultRedirectChildren;
Config.hotVmFactor = DefaultHotVmFactor;
Config.sourcePing = DefaultSourcePing;
Config.quickAbort = DefaultQuickAbort;
Config.Program.ftpget = safe_xstrdup(DefaultFtpgetProgram);
Config.Program.ftpget_opts = safe_xstrdup(DefaultFtpgetOptions);
Config.Program.dnsserver = safe_xstrdup(DefaultDnsserverProgram);
+ Config.Program.redirect = safe_xstrdup(DefaultRedirectProgram);
Config.Accel.host = safe_xstrdup(DefaultAccelHost);
Config.Accel.prefix = safe_xstrdup(DefaultAccelPrefix);
Config.Accel.port = DefaultAccelPort;
DnsPositiveTtl = Config.positiveDnsTtl;
sprintf(ForwardedBy, "Forwarded: by http://%s:%d/",
getMyHostname(), getHttpPortNum());
+ do_redirect = getRedirectProgram()? 1 : 0;
#if !ALLOW_HOT_CACHE
/*
- * $Id: comm.cc,v 1.36 1996/07/09 22:58:27 wessels Exp $
+ * $Id: comm.cc,v 1.37 1996/07/11 17:42:38 wessels Exp $
*
* DEBUG: section 5 Socket Functions
* AUTHOR: Harvest Derived
serverConnectionsClose();
ftpServerClose();
ipcacheShutdownServers();
+ redirectShutdownServers();
setSocketShutdownLifetimes();
}
nfds = 0;
/*
- * $Id: main.cc,v 1.48 1996/07/09 04:46:52 wessels Exp $
+ * $Id: main.cc,v 1.49 1996/07/11 17:42:44 wessels Exp $
*
* DEBUG: section 1 Startup and Main Loop
* AUTHOR: Harvest Derived
_db_init(getCacheLogFile(), getDebugOptions());
neighbors_init();
ipcacheOpenServers();
+ redirectOpenServers();
serverConnectionsOpen();
(void) ftpInitialize();
if (theOutIcpConnection >= 0 && (!httpd_accel_mode || getAccelWithProxy()))
writePidFile(); /* write PID file */
}
ipcache_init();
+ redirectOpenServers();
neighbors_init();
(void) ftpInitialize();
/*
- * $Id: neighbors.cc,v 1.24 1996/07/09 03:41:33 wessels Exp $
+ * $Id: neighbors.cc,v 1.25 1996/07/11 17:42:45 wessels Exp $
*
* DEBUG: section 15 Neighbor Routines
* AUTHOR: Harvest Derived
}
-void hierarchy_log_append(url, code, timeout, cache_host)
- char *url;
+void hierarchy_log_append(entry, code, timeout, cache_host)
+ StoreEntry *entry;
hier_code code;
int timeout;
char *cache_host;
{
+ char *url = entry->url;
+ MemObject *mem = entry->mem_obj;
static time_t last_time = 0;
static char time_str[128];
char *s = NULL;
if (code > HIER_MAX)
code = HIER_MAX;
+ if (mem)
+ mem->hierarchy_code = code;
if (emulate_httpd_log) {
if (squid_curtime != last_time) {
inet_ntoa(e->in_addr.sin_addr));
/* log it once at the threshold */
if ((e->stats.ack_deficit == HIER_MAX_DEFICIT)) {
- if (e->type == EDGE_SIBLING) {
- hierarchy_log_append("Detect: ",
- HIER_DEAD_NEIGHBOR, 0,
- e->host);
- } else {
- hierarchy_log_append("Detect: ",
- HIER_DEAD_PARENT, 0,
- e->host);
- }
+ debug(15, 0, "neighborsUdpPing: Detected DEAD %s: %s\n",
+ e->type == EDGE_SIBLING ? "SIBLING" : "PARENT",
+ e->host);
}
}
friends->first_ping = e->next;
int n;
HttpStateData *httpState = NULL;
- debug(15, 6, "neighborsUdpAck: url=%s (%d chars), header=0x%x, from=0x%x, ent=0x%x\n",
- url, strlen(url), header, from, entry);
- debug(15, 6, " hdr: opcode=%d, ver=%d, shostid=%x, len=%d, rn=0x%x\n",
- header->opcode, header->version, header->shostid,
- header->length, header->reqnum);
- debug(15, 6, " from: fam=%d, port=%d, addr=0x%x\n",
- ntohs(from->sin_family),
- ntohs(from->sin_port),
- ntohl(from->sin_addr.s_addr));
-
- /* look up for neighbor/parent entry */
- e = whichEdge(header, from);
-
- if (e) {
- /* reset the deficit. It's alive now. */
- /* Don't care about exact count. */
- if ((e->stats.ack_deficit >= HIER_MAX_DEFICIT)) {
- if (e->type == EDGE_SIBLING) {
- hierarchy_log_append("Detect: ",
- HIER_REVIVE_NEIGHBOR, 0, e->host);
- } else {
- hierarchy_log_append("Detect: ",
- HIER_REVIVE_PARENT, 0, e->host);
- }
+ debug(15, 6, "neighborsUdpAck: opcode %d '%s'\n",
+ (int) header->opcode, url);
+ if (header->opcode > ICP_OP_END)
+ return;
+ if (mem == NULL) {
+ debug(15, 1, "Ignoring ICP reply for missing mem_obj: %s\n", url);
+ return;
+ }
+ if ((e = whichEdge(header, from))) {
+ /* Neighbor is alive, reset the ack deficit */
+ if (e->stats.ack_deficit >= HIER_MAX_DEFICIT) {
+ debug(15, 0, "neighborsUdpAck: Detected REVIVED %s: %s\n",
+ e->type == EDGE_SIBLING ? "SIBLING" : "PARENT",
+ e->host);
}
e->neighbor_up = 1;
e->stats.ack_deficit = 0;
n = ++e->stats.pings_acked;
- if (header->opcode < ICP_OP_END)
- e->stats.counts[header->opcode]++;
- if (mem) {
- if (n > RTT_AV_FACTOR)
- n = RTT_AV_FACTOR;
- rtt = tvSubMsec(mem->start_ping, current_time);
- e->stats.rtt = (e->stats.rtt * (n - 1) + rtt) / n;
- }
+ e->stats.counts[header->opcode]++;
+ if (n > RTT_AV_FACTOR)
+ n = RTT_AV_FACTOR;
+ rtt = tvSubMsec(mem->start_ping, current_time);
+ e->stats.rtt = (e->stats.rtt * (n - 1) + rtt) / n;
}
/* check if someone is already fetching it */
- if (BIT_TEST(entry->flag, ENTRY_DISPATCHED) || (entry->ping_status != PING_WAITING)) {
- if (entry->ping_status == PING_DONE) {
- debug(15, 5, "There is already a cache/source dispatched for this object\n");
- debug(15, 5, "--> <URL:%s>\n", entry->url);
- debug(15, 5, "--> entry->flag & ENTRY_DISPATCHED = %d\n",
- BIT_TEST(entry->flag, ENTRY_DISPATCHED));
- debug(15, 5, "--> entry->ping_status = %d\n", entry->ping_status);
- } else {
- debug(15, 5, "The ping already timed out.\n");
- debug(15, 5, "--> <URL:%s>\n", entry->url);
- debug(15, 5, "--> entry->flag & ENTRY_DISPATCHED = %lx\n",
- BIT_TEST(entry->flag, ENTRY_DISPATCHED));
- debug(15, 5, "--> entry->ping_status = %d\n", entry->ping_status);
- }
+ if (BIT_TEST(entry->flag, ENTRY_DISPATCHED)) {
+ debug(15, 5, "neighborsUdpAck: '%s' already being fetched.\n", url);
+ return;
+ }
+ if (entry->ping_status != PING_WAITING) {
+ debug(15, 5, "neighborsUdpAck: '%s' unexpected ICP reply.\n", url);
return;
}
- debug(15, 6, "neighborsUdpAck - url: %s to us %s \n",
- url, e ? inet_ntoa(e->in_addr.sin_addr) : "url-host");
+ debug(15, 3, "neighborsUdpAck: %s for '%s' from %s \n",
+ IcpOpcodeStr[header->opcode], url, e ? e->host : "source");
+ mem->e_pings_n_acks++;
if (header->opcode == ICP_OP_SECHO) {
- /* receive ping back from source or from non-ICP cache */
+ /* Received source-ping reply */
if (e) {
- debug(15, 6, "Got SECHO from non-ICP cache:%s\n",
- inet_ntoa(e->in_addr.sin_addr));
- debug(15, 6, "This is not supposed to happen. Ignored.\n");
+ debug(15, 1, "neighborsUdpAck: Ignoring SECHO from %s\n", e->host);
} else {
- /* if we reach here, source is the one has the fastest respond. */
- /* fetch directly from source */
+ /* if we reach here, source-ping reply is the first 'parent',
+ * so fetch directly from the source */
debug(15, 6, "Source is the first to respond.\n");
- hierarchy_log_append(entry->url,
+ hierarchy_log_append(entry,
HIER_SOURCE_FASTEST,
0,
inet_ntoa(from->sin_addr));
- if (mem)
- mem->hierarchy_code = HIER_SOURCE_FASTEST;
BIT_SET(entry->flag, ENTRY_DISPATCHED);
entry->ping_status = PING_DONE;
getFromCache(0, entry, NULL, entry->mem_obj->request);
+ return;
}
- return;
} else if (header->opcode == ICP_OP_HIT_OBJ) {
if (entry->object_len != 0) {
- debug(15, 0, "Too late UDP_HIT_OBJ '%s'?\n", entry->url);
+ debug(15, 1, "Too late UDP_HIT_OBJ '%s'?\n", entry->url);
+ } else {
+ protoCancelTimeout(0, entry);
+ entry->ping_status = PING_DONE;
+ httpState = xcalloc(1, sizeof(HttpStateData));
+ httpState->entry = entry;
+ httpProcessReplyHeader(httpState, data, data_sz);
+ storeAppend(entry, data, data_sz);
+ storeComplete(entry);
+ hierarchy_log_append(entry,
+ HIER_UDP_HIT_OBJ,
+ 0,
+ e ? e->host : inet_ntoa(from->sin_addr));
+ if (httpState->reply_hdr)
+ put_free_8k_page(httpState->reply_hdr);
+ safe_free(httpState);
return;
}
- protoCancelTimeout(0, entry);
- entry->ping_status = PING_DONE;
- httpState = xcalloc(1, sizeof(HttpStateData));
- httpState->entry = entry;
- httpProcessReplyHeader(httpState, data, data_sz);
- storeAppend(entry, data, data_sz);
- storeComplete(entry);
- hierarchy_log_append(entry->url,
- HIER_UDP_HIT_OBJ,
- 0,
- e ? e->host : inet_ntoa(from->sin_addr));
- if (mem)
- mem->hierarchy_code = HIER_UDP_HIT_OBJ;
- if (httpState->reply_hdr)
- put_free_8k_page(httpState->reply_hdr);
- safe_free(httpState);
- return;
} else if (header->opcode == ICP_OP_HIT) {
- /* If an edge is not found, count it as a MISS message. */
- if (!e) {
- /* count it as a MISS message */
- mem->e_pings_n_acks++;
+ if (e == NULL) {
+ debug(15, 1, "neighborsUdpAck: Ignoring HIT from non-neighbor\n");
+ } else {
+ hierarchy_log_append(entry,
+ e->type == EDGE_SIBLING ? HIER_NEIGHBOR_HIT : HIER_PARENT_HIT,
+ 0,
+ e->host);
+ BIT_SET(entry->flag, ENTRY_DISPATCHED);
+ entry->ping_status = PING_DONE;
+ getFromCache(0, entry, e, entry->mem_obj->request);
return;
}
- /* GOT a HIT here */
- debug(15, 6, "HIT: Getting %s from host: %s\n", entry->url, e->host);
- if (e->type == EDGE_SIBLING) {
- hierarchy_log_append(entry->url, HIER_NEIGHBOR_HIT, 0, e->host);
- if (mem)
- mem->hierarchy_code = HIER_NEIGHBOR_HIT;
+ } else if (header->opcode == ICP_OP_DECHO) {
+ if (e == NULL) {
+ debug(15, 1, "neighborsUdpAck: Ignoring DECHO from non-neighbor\n");
+ } else if (e->type == EDGE_SIBLING) {
+ fatal_dump("neighborsUdpAck: Found non-ICP cache as SIBLING\n");
} else {
- hierarchy_log_append(entry->url, HIER_PARENT_HIT, 0, e->host);
- if (mem)
- mem->hierarchy_code = HIER_PARENT_HIT;
- }
- BIT_SET(entry->flag, ENTRY_DISPATCHED);
- entry->ping_status = PING_DONE;
- getFromCache(0, entry, e, entry->mem_obj->request);
- return;
- } else if ((header->opcode == ICP_OP_MISS) || (header->opcode == ICP_OP_DECHO)) {
- /* everytime we get here, count it as a miss */
- mem->e_pings_n_acks++;
-
- if (header->opcode == ICP_OP_DECHO) {
- /* receive ping back from non-ICP cache */
-
- if (e) {
- debug(15, 6, "Got DECHO from non-ICP cache:%s\n",
- inet_ntoa(e->in_addr.sin_addr));
-
- if (e->type == EDGE_PARENT) {
- w_rtt = tvSubMsec(mem->start_ping, current_time) / e->weight;
- if (mem->w_rtt == 0 || w_rtt < mem->w_rtt) {
- debug(15, 6, "Dumb-cache has minimum weighted RTT = %d\n", w_rtt);
- mem->e_pings_first_miss = e;
- mem->w_rtt = w_rtt;
- }
- } else {
- debug(15, 6, "Dumb Cached as a neighbor does not make sense.\n");
- }
-
-
- } else {
- debug(15, 6, "Got DECHO from non-ICP cache: But the host is not in the list.\n");
- debug(15, 6, "Count it anyway.\n");
- }
-
- } else if (e && e->type == EDGE_PARENT) {
- /* ICP_OP_MISS from a cache */
w_rtt = tvSubMsec(mem->start_ping, current_time) / e->weight;
if (mem->w_rtt == 0 || w_rtt < mem->w_rtt) {
mem->e_pings_first_miss = e;
mem->w_rtt = w_rtt;
}
}
- if (mem->e_pings_n_acks == mem->e_pings_n_pings) {
- BIT_SET(entry->flag, ENTRY_DISPATCHED);
- entry->ping_status = PING_DONE;
- debug(15, 6, "Receive MISSes from all neighbors and parents\n");
- /* pass in fd=0 here so getFromCache() looks up the real FD
- * and resets the timeout handler */
- getFromDefaultSource(0, entry);
- return;
+ } else if (header->opcode == ICP_OP_MISS) {
+ if (e == NULL) {
+ debug(15, 1, "neighborsUdpAck: Ignoring MISS from non-neighbor\n");
+ } else if (e->type == EDGE_PARENT) {
+ w_rtt = tvSubMsec(mem->start_ping, current_time) / e->weight;
+ if (mem->w_rtt == 0 || w_rtt < mem->w_rtt) {
+ mem->e_pings_first_miss = e;
+ mem->w_rtt = w_rtt;
+ }
}
} else if (header->opcode == ICP_OP_DENIED) {
- debug(15, 5, "neighborsUdpAck: Access denied for '%s'\n", entry->url);
- if (e && e->stats.pings_acked > 100) {
+ if (e == NULL) {
+ debug(15, 1, "neighborsUdpAck: Ignoring DENIED from non-neighbor\n");
+ } else if (e->stats.pings_acked > 100) {
if (100 * e->stats.counts[ICP_OP_DENIED] / e->stats.pings_acked > 95) {
debug(15, 0, "95%% of replies from '%s' are UDP_DENIED\n", e->host);
debug(15, 0, "Disabling '%s', please check your configuration.\n", e->host);
}
}
} else {
- debug(15, 0, "neighborsUdpAck: WHY ARE WE HERE? header->opcode = %d\n",
- header->opcode);
+ debug(15, 0, "neighborsUdpAck: Unexpected ICP reply: %s\n",
+ IcpOpcodeStr[header->opcode]);
+ }
+ if (mem->e_pings_n_acks == mem->e_pings_n_pings) {
+ BIT_SET(entry->flag, ENTRY_DISPATCHED);
+ entry->ping_status = PING_DONE;
+ debug(15, 6, "neighborsUdpAck: All replies received.\n");
+ /* pass in fd=0 here so getFromCache() looks up the real FD
+ * and resets the timeout handler */
+ getFromDefaultSource(0, entry);
+ return;
}
}
/*
- * $Id: redirect.cc,v 1.2 1996/07/09 03:41:37 wessels Exp $
+ * $Id: redirect.cc,v 1.3 1996/07/11 17:42:50 wessels Exp $
*
* DEBUG: section 29 Redirector
* AUTHOR: Duane Wessels
#define REDIRECT_FLAG_BUSY 0x02
#define REDIRECT_FLAG_CLOSING 0x04
-typedef void (*RH) _PARAMS((int, char *));
-
-
typedef struct {
int fd;
+ void *data;
char *orig_url;
RH handler;
} redirectStateData;
char *inbuf;
unsigned int size;
unsigned int offset;
+ struct timeval dispatch_time;
redirectStateData *redirectState;
} redirector_t;
+static struct {
+ int requests;
+ int replies;
+ int errors;
+ int avg_svc_time;
+ int queue_size;
+ int use_hist[DefaultRedirectChildrenMax];
+} RedirectStats;
+
+
struct redirectQueueData {
struct redirectQueueData *next;
redirectStateData *redirectState;
};
+/* GLOBALS */
+int do_redirect = 0;
+
static redirector_t *GetFirstAvailable _PARAMS((void));
static int redirectCreateRedirector _PARAMS((char *command));
static int redirectHandleRead _PARAMS((int, redirector_t *));
static struct redirectQueueData *redirectQueueHead = NULL;
static struct redirectQueueData **redirectQueueTailP = &redirectQueueHead;
-/* TCP SOCKET VERSION */
-int redirectCreateRedirector(command)
+static int redirectCreateRedirector(command)
char *command;
{
int pid;
0,
"socket to redirector");
if (cfd == COMM_ERROR) {
- debug(14, 0, "redirect_create_redirector: Failed to create redirector\n");
+ debug(29, 0, "redirect_create_redirector: Failed to create redirector\n");
return -1;
}
len = sizeof(S);
memset(&S, '\0', len);
if (getsockname(cfd, (struct sockaddr *) &S, &len) < 0) {
- debug(14, 0, "redirect_create_redirector: getsockname: %s\n", xstrerror());
+ debug(29, 0, "redirect_create_redirector: getsockname: %s\n", xstrerror());
comm_close(cfd);
return -1;
}
port = ntohs(S.sin_port);
- debug(14, 4, "redirect_create_redirector: bind to local host.\n");
listen(cfd, 1);
if ((pid = fork()) < 0) {
- debug(14, 0, "redirect_create_redirector: fork: %s\n", xstrerror());
+ debug(29, 0, "redirect_create_redirector: fork: %s\n", xstrerror());
comm_close(cfd);
return -1;
}
return -1;
}
comm_set_fd_lifetime(sfd, -1);
- debug(14, 4, "redirect_create_redirector: FD %d connected to %s #%d.\n",
- sfd, command, n_redirector);
+ debug(29, 4, "redirect_create_redirector: FD %d connected to %s #%d.\n",
+ sfd, command, n_redirector++);
return sfd;
}
/* child */
no_suid(); /* give up extra priviliges */
- dup2(cfd, 3);
- for (fd = FD_SETSIZE; fd > 3; fd--)
+ if ((fd = accept(cfd, NULL, NULL)) < 0) {
+ debug(29, 0, "redirect_create_redirector: FD %d accept: %s\n",
+ cfd, xstrerror());
+ _exit(1);
+ }
+ dup2(fd, 0);
+ dup2(fd, 1);
+ for (fd = 3; fd < FD_SETSIZE; fd++)
close(fd);
- execlp(command, "(redirector)", "-t", NULL);
- debug(14, 0, "redirect_create_redirector: %s: %s\n", command, xstrerror());
+ execlp(command, "(redirector)", NULL);
+ debug(29, 0, "redirect_create_redirector: %s: %s\n", command, xstrerror());
_exit(1);
return 0;
}
-
-
-int redirectHandleRead(fd, redirector)
+static int redirectHandleRead(fd, redirector)
int fd;
redirector_t *redirector;
{
int len;
redirectStateData *r = redirector->redirectState;
char *t = NULL;
+ int n;
+ int svc_time;
len = read(fd,
redirector->inbuf + redirector->offset,
redirector->size - redirector->offset);
- debug(14, 5, "redirectHandleRead: Result from Redirector %d.\n",
- redirector->index + 1);
+ debug(29, 5, "redirectHandleRead: %d bytes from Redirector #%d.\n",
+ len, redirector->index + 1);
if (len <= 0) {
- debug(14, redirector->flags & REDIRECT_FLAG_CLOSING ? 5 : 1,
+ if (len < 0)
+ debug(29, 1, "redirectHandleRead: FD %d read: %s\n", fd, xstrerror());
+ debug(29, redirector->flags & REDIRECT_FLAG_CLOSING ? 5 : 1,
"FD %d: Connection from Redirector #%d is closed, disabling\n",
fd, redirector->index + 1);
redirector->flags = 0;
if ((t = strchr(redirector->inbuf, '\n'))) {
/* end of record found */
*t = '\0';
- if (t == redirector->inbuf)
- r->handler(r->fd, r->orig_url);
- else
- r->handler(r->fd, redirector->inbuf);
+ debug(29, 5, "redirectHandleRead: reply: '%s'\n", redirector->inbuf);
+ if (r->handler) {
+ r->handler(r->data,
+ t == redirector->inbuf ? NULL : redirector->inbuf);
+ }
+ safe_free(r);
redirector->redirectState = NULL;
redirector->flags &= ~REDIRECT_FLAG_BUSY;
+ redirector->offset = 0;
+ n = ++RedirectStats.replies;
+ svc_time = tvSubMsec(redirector->dispatch_time, current_time);
+ if (n > REDIRECT_AV_FACTOR)
+ n = REDIRECT_AV_FACTOR;
+ RedirectStats.avg_svc_time
+ = (RedirectStats.avg_svc_time * (n - 1) + svc_time) / n;
}
- while ((r = Dequeue()) && (redirector = GetFirstAvailable()))
+ while ((redirector = GetFirstAvailable()) && (r = Dequeue()))
redirectDispatch(redirector, r);
return 0;
}
-void redirectStart(url, fd, handler)
- char *url;
- int fd;
- RH handler;
-{
- redirectStateData *r = NULL;
- redirector_t *redirector = NULL;
-
- if (!handler)
- fatal_dump("redirectStart: NULL handler");
- r = xcalloc(1, sizeof(redirectStateData));
- r->fd = fd;
- r->orig_url = url;
- r->handler = handler;
- if ((redirector = GetFirstAvailable()))
- redirectDispatch(redirector, r);
- else
- Enqueue(r);
-}
-
static void Enqueue(r)
redirectStateData *r;
{
new->redirectState = r;
*redirectQueueTailP = new;
redirectQueueTailP = &new->next;
+ RedirectStats.queue_size++;
}
static redirectStateData *Dequeue()
if (redirectQueueHead == NULL)
redirectQueueTailP = &redirectQueueHead;
safe_free(old);
+ RedirectStats.queue_size--;
}
return r;
}
redirectStateData *r;
{
char *buf = NULL;
+ int len;
+ if (r->handler == NULL) {
+ debug(29, 1, "redirectDispatch: skipping '%s' because no handler\n",
+ r->orig_url);
+ safe_free(r);
+ return;
+ }
redirect->flags |= REDIRECT_FLAG_BUSY;
redirect->redirectState = r;
+ redirect->dispatch_time = current_time;
+ len = strlen(r->orig_url) + 1;
+ buf = xmalloc(len + 1);
+ sprintf(buf, "%s\n", r->orig_url);
comm_write(redirect->fd,
- xstrdup(buf),
- strlen(buf),
+ buf,
+ len,
0, /* timeout */
NULL, /* Handler */
NULL); /* Handler-data */
- debug(14, 5, "redirectDispatch: Request sent to Redirector #%d.\n",
- redirect->index + 1);
+ debug(29, 5, "redirectDispatch: Request sent to Redirector #%d, %d bytes\n",
+ redirect->index + 1, len);
+ RedirectStats.use_hist[redirect->index]++;
+ RedirectStats.requests++;
}
+/**** PUBLIC FUNCTIONS ****/
+
+
+void redirectStart(url, fd, handler, data)
+ char *url;
+ int fd;
+ RH handler;
+ void *data;
+{
+ redirectStateData *r = NULL;
+ redirector_t *redirector = NULL;
+ if (!handler)
+ fatal_dump("redirectStart: NULL handler");
+ if (!do_redirect) {
+ (*handler) (data, NULL);
+ return;
+ }
+ r = xcalloc(1, sizeof(redirectStateData));
+ r->fd = fd;
+ r->orig_url = url;
+ r->handler = handler;
+ r->data = data;
+ if ((redirector = GetFirstAvailable()))
+ redirectDispatch(redirector, r);
+ else
+ Enqueue(r);
+}
+
void redirectOpenServers()
{
char *prg = getRedirectProgram();
int k;
int redirectsocket;
static char fd_note_buf[FD_ASCII_NOTE_SZ];
+ static int first_time = 0;
+ if (!do_redirect)
+ return;
/* free old structures if present */
if (redirect_child_table) {
for (k = 0; k < NRedirectors; k++)
}
NRedirectors = getRedirectChildren();
redirect_child_table = xcalloc(NRedirectors, sizeof(redirector_t *));
- debug(14, 1, "redirectOpenServers: Starting %d '%s' processes\n",
+ debug(29, 1, "redirectOpenServers: Starting %d '%s' processes\n",
NRedirectors, prg);
for (k = 0; k < NRedirectors; k++) {
redirect_child_table[k] = xcalloc(1, sizeof(redirector_t));
if ((redirectsocket = redirectCreateRedirector(prg)) < 0) {
- debug(14, 1, "WARNING: Cannot run '%s' process.\n", prg);
+ debug(29, 1, "WARNING: Cannot run '%s' process.\n", prg);
redirect_child_table[k]->flags &= ~REDIRECT_FLAG_ALIVE;
} else {
redirect_child_table[k]->flags |= REDIRECT_FLAG_ALIVE;
redirect_child_table[k]->index = k;
redirect_child_table[k]->fd = redirectsocket;
+ redirect_child_table[k]->inbuf = get_free_4k_page();
+ redirect_child_table[k]->size = 4096;
+ redirect_child_table[k]->offset = 0;
sprintf(fd_note_buf, "%s #%d",
prg,
redirect_child_table[k]->index + 1);
fd_note(redirect_child_table[k]->fd, fd_note_buf);
commSetNonBlocking(redirect_child_table[k]->fd);
-
/* set handler for incoming result */
comm_set_select_handler(redirect_child_table[k]->fd,
COMM_SELECT_READ,
(PF) redirectHandleRead,
(void *) redirect_child_table[k]);
- debug(14, 3, "redirectOpenServers: 'redirect_server' %d started\n",
+ debug(29, 3, "redirectOpenServers: 'redirect_server' %d started\n",
k);
}
}
+ if (first_time == 0) {
+ first_time++;
+ memset(&RedirectStats, '\0', sizeof(RedirectStats));
+ }
+}
+
+void redirectShutdownServers()
+{
+ redirector_t *redirect = NULL;
+ int k;
+ if (!do_redirect)
+ return;
+ for (k = 0; k < NRedirectors; k++) {
+ redirect = *(redirect_child_table + k);
+ if (!(redirect->flags & REDIRECT_FLAG_ALIVE))
+ continue;
+ if (redirect->flags & REDIRECT_FLAG_BUSY)
+ continue;
+ if (redirect->flags & REDIRECT_FLAG_CLOSING)
+ continue;
+ debug(29, 3, "redirectShutdownServers: closing redirector #%d, FD %d\n",
+ redirect->index + 1, redirect->fd);
+ comm_close(redirect->fd);
+ redirect->flags |= REDIRECT_FLAG_CLOSING;
+ }
}
+
int redirectUnregister(url, fd)
char *url;
int fd;
{
- return 0;
+ redirector_t *redirect = NULL;
+ redirectStateData *r = NULL;
+ struct redirectQueueData *rq = NULL;
+ int k;
+ int n = 0;
+ if (!do_redirect)
+ return 0;
+ debug(29, 3, "redirectUnregister: FD %d '%s'\n", fd, url);
+ for (k = 0; k < NRedirectors; k++) {
+ redirect = *(redirect_child_table + k);
+ if ((r = redirect->redirectState) == NULL)
+ continue;
+ if (r->fd != fd)
+ continue;
+ if (strcmp(r->orig_url, url))
+ continue;
+ debug(29, 3, "redirectUnregister: Found match\n");
+ r->handler = NULL;
+ n++;
+ }
+ for (rq = redirectQueueHead; rq; rq = rq->next) {
+ if ((r = rq->redirectState) == NULL)
+ continue;
+ if (r->fd != fd)
+ continue;
+ if (strcmp(r->orig_url, url))
+ continue;
+ debug(29, 3, "redirectUnregister: Found match.\n");
+ r->handler = NULL;
+ n++;
+ }
+ debug(29, 3, "redirectUnregister: Unregistered %d handlers\n", n);
+ return n;
}
-void redirectShutdownServers()
+void redirectStats(sentry)
+ StoreEntry *sentry;
{
- redirector_t *redirector = NULL;
int k;
- static char *shutdown = "$shutdown\n";
-
- debug(14, 3, "redirectShutdownServers:\n");
-
- for (k = 0; k < getRedirectChildren(); k++) {
- redirector = *(redirect_child_table + k);
- debug(14, 3, "redirectShutdownServers: sending '$shutdown' to redirector #%d\n", k);
- debug(14, 3, "redirectShutdownServers: --> FD %d\n", redirector->fd);
- comm_write(redirector->fd,
- xstrdup(shutdown),
- strlen(shutdown),
- 0, /* timeout */
- NULL, /* Handler */
- NULL); /* Handler-data */
- redirector->flags |= REDIRECT_FLAG_CLOSING;
+ storeAppendPrintf(sentry, open_bracket);
+ storeAppendPrintf(sentry, "{Redirector Statistics:}\n");
+ storeAppendPrintf(sentry, "{requests: %d}\n",
+ RedirectStats.requests);
+ storeAppendPrintf(sentry, "{replies: %d}\n",
+ RedirectStats.replies);
+ storeAppendPrintf(sentry, "{queue length: %d}\n",
+ RedirectStats.queue_size);
+ storeAppendPrintf(sentry, "{avg service time: %d msec}\n",
+ RedirectStats.avg_svc_time);
+ storeAppendPrintf(sentry, "{number of redirectors: %d}\n",
+ NRedirectors);
+ storeAppendPrintf(sentry, "{use histogram:}\n");
+ for (k = 0; k < NRedirectors; k++) {
+ storeAppendPrintf(sentry, "{ redirector #%d: %d}\n",
+ k + 1,
+ RedirectStats.use_hist[k]);
}
+ storeAppendPrintf(sentry, close_bracket);
}
+
/*
- * $Id: send-announce.cc,v 1.12 1996/07/09 03:41:37 wessels Exp $
+ * $Id: send-announce.cc,v 1.13 1996/07/11 17:42:51 wessels Exp $
*
* DEBUG: section 27 Cache Announcer
* AUTHOR: Duane Wessels
/*
- * $Id: squid.h,v 1.25 1996/07/09 04:47:23 wessels Exp $
+ * $Id: squid.h,v 1.26 1996/07/11 17:42:53 wessels Exp $
*
* AUTHOR: Duane Wessels
*
#include "acl.h"
#include "util.h"
#include "background.h"
+#include "redirect.h"
#if !HAVE_TEMPNAM
#include "tempnam.h"
extern struct in_addr local_addr; /* main.c */
extern char localhost[];
extern struct in_addr any_addr; /* comm.c */
+extern int do_redirect; /* redirect.c */
/* Prototypes and definitions which don't really deserve a seaprate
/*
- * $Id: ssl.cc,v 1.4 1996/07/09 23:00:26 wessels Exp $
+ * $Id: ssl.cc,v 1.5 1996/07/11 17:42:53 wessels Exp $
*
* DEBUG: section 26 Secure Sockets Layer Proxy
* AUTHOR: Duane Wessels
COMM_SELECT_READ,
(PF) sslReadClient,
(void *) sslState);
- comm_set_select_handler_plus_timeout(sslState->server.fd,
- COMM_SELECT_TIMEOUT,
- (PF) sslReadTimeout,
- (void *) sslState,
- sslState->timeout);
+ comm_set_select_handler_plus_timeout(sslState->server.fd,
+ COMM_SELECT_TIMEOUT,
+ (PF) sslReadTimeout,
+ (void *) sslState,
+ sslState->timeout);
} else {
/* still have more to write */
comm_set_select_handler(sslState->server.fd,
/*
- * $Id: stat.cc,v 1.37 1996/07/09 23:00:55 wessels Exp $
+ * $Id: stat.cc,v 1.38 1996/07/11 17:42:54 wessels Exp $
*
* DEBUG: section 18 Cache Manager Statistics
* AUTHOR: Harvest Derived
stat_objects_get(obj, sentry, 1);
} else if (strcmp(req, "general") == 0) {
stat_ipcache_get(sentry);
- } else if (strcmp(req, "general") == 0) {
- stat_ipcache_get(sentry);
+ } else if (strcmp(req, "redirector") == 0) {
+ redirectStats(sentry);
} else if (strcmp(req, "utilization") == 0) {
stat_utilization_get(obj, sentry);
} else if (strcmp(req, "io") == 0) {
}
#endif
-static char *host_port_fmt (host, port)
- char *host;
- u_short port;
+static char *host_port_fmt(host, port)
+ char *host;
+ u_short port;
{
- static char buf[32];
- sprintf (buf, "%s.%d", host, (int) port);
- return buf;
+ static char buf[32];
+ sprintf(buf, "%s.%d", host, (int) port);
+ return buf;
}
static void statFiledescriptors(sentry)
- StoreEntry *sentry;
+ StoreEntry *sentry;
{
int i;
int j;
continue;
j = fdstatGetType(i);
storeAppendPrintf(sentry, "{%4d %-6s ",
- i,
- fdstatTypeStr[j]);
+ i,
+ fdstatTypeStr[j]);
switch (j) {
case FD_SOCKET:
if ((lft = comm_get_fd_lifetime(i)) < 0)
storeAppendPrintf(sentry, "{\tNumber of UDP connections:\t%lu}\n",
nudpconn);
- f = squid_curtime - squid_starttime;
- storeAppendPrintf(sentry, "{\tConnections per hour:\t%.1f}\n",
+ f = squid_curtime - squid_starttime;
+ storeAppendPrintf(sentry, "{\tConnections per hour:\t%.1f}\n",
f == 0.0 ? 0.0 : ((ntcpconn + nudpconn) / (f / 3600)));
storeAppendPrintf(sentry, "{Cache information for %s:}\n",
/*
- * $Id: tunnel.cc,v 1.4 1996/07/09 23:00:26 wessels Exp $
+ * $Id: tunnel.cc,v 1.5 1996/07/11 17:42:53 wessels Exp $
*
* DEBUG: section 26 Secure Sockets Layer Proxy
* AUTHOR: Duane Wessels
COMM_SELECT_READ,
(PF) sslReadClient,
(void *) sslState);
- comm_set_select_handler_plus_timeout(sslState->server.fd,
- COMM_SELECT_TIMEOUT,
- (PF) sslReadTimeout,
- (void *) sslState,
- sslState->timeout);
+ comm_set_select_handler_plus_timeout(sslState->server.fd,
+ COMM_SELECT_TIMEOUT,
+ (PF) sslReadTimeout,
+ (void *) sslState,
+ sslState->timeout);
} else {
/* still have more to write */
comm_set_select_handler(sslState->server.fd,