/*
- * $Id: gopher.cc,v 1.41 1996/09/03 19:24:02 wessels Exp $
+ * $Id: gopher.cc,v 1.42 1996/09/12 16:39:53 wessels Exp $
*
* DEBUG: section 10 Gopher
* AUTHOR: Harvest Derived
int cso_recno;
int len;
char *buf; /* pts to a 4k page */
-} GopherData;
-
-GopherData *CreateGopherData();
-
-char def_gopher_bin[] = "www/unknown";
-char def_gopher_text[] = "text/plain";
+} GopherStateData;
+
+static int gopherStateFree _PARAMS((int fd, GopherStateData *));
+static void gopher_mime_content _PARAMS((char *buf, char *name, char *def));
+static void gopherMimeCreate _PARAMS((GopherStateData *));
+static int gopher_url_parser _PARAMS((char *url,
+ char *host,
+ int *port,
+ char *type_id,
+ char *request));
+static void gopherEndHTML _PARAMS((GopherStateData *));
+static void gopherToHTML _PARAMS((GopherStateData *, char *inbuf, int len));
+static int gopherReadReplyTimeout _PARAMS((int fd, GopherStateData *));
+static void gopherLifetimeExpire _PARAMS((int fd, GopherStateData *));
+static void gopherReadReply _PARAMS((int fd, GopherStateData *));
+static void gopherSendComplete _PARAMS((int fd,
+ char *buf,
+ int size,
+ int errflag,
+ void *data));
+static void gopherSendRequest _PARAMS((int fd, GopherStateData *));
+static GopherStateData *CreateGopherStateData _PARAMS((void));
+
+static char def_gopher_bin[] = "www/unknown";
+static char def_gopher_text[] = "text/plain";
static int gopherStateFree(fd, gopherState)
int fd;
- GopherData *gopherState;
+ GopherStateData *gopherState;
{
if (gopherState == NULL)
return 1;
/* create MIME Header for Gopher Data */
-void gopherMimeCreate(data)
- GopherData *data;
+static void gopherMimeCreate(data)
+ GopherStateData *data;
{
LOCAL_ARRAY(char, tempMIME, MAX_MIME);
}
/* Parse a gopher url into components. By Anawat. */
-int gopher_url_parser(url, host, port, type_id, request)
+static int gopher_url_parser(url, host, port, type_id, request)
char *url;
char *host;
int *port;
int gopherCachable(url)
char *url;
{
- GopherData *data = NULL;
+ GopherStateData *data = NULL;
int cachable = 1;
-
/* use as temp data structure to parse gopher URL */
- data = CreateGopherData();
-
+ data = CreateGopherStateData();
/* parse to see type */
- gopher_url_parser(url, data->host, &data->port, &data->type_id, data->request);
-
+ gopher_url_parser(url,
+ data->host,
+ &data->port,
+ &data->type_id,
+ data->request);
switch (data->type_id) {
case GOPHER_INDEX:
case GOPHER_CSO:
cachable = 1;
}
gopherStateFree(-1, data);
-
return cachable;
}
-void gopherEndHTML(data)
- GopherData *data;
+static void gopherEndHTML(data)
+ GopherStateData *data;
{
LOCAL_ARRAY(char, tmpbuf, TEMP_BUF_SIZE);
/* Convert Gopher to HTML */
/* Borrow part of code from libwww2 came with Mosaic distribution */
-void gopherToHTML(data, inbuf, len)
- GopherData *data;
+static void gopherToHTML(data, inbuf, len)
+ GopherStateData *data;
char *inbuf;
int len;
{
return;
}
-
-int gopherReadReplyTimeout(fd, data)
+static int gopherReadReplyTimeout(fd, data)
int fd;
- GopherData *data;
+ GopherStateData *data;
{
StoreEntry *entry = NULL;
entry = data->entry;
}
/* This will be called when socket lifetime is expired. */
-void gopherLifetimeExpire(fd, data)
+static void gopherLifetimeExpire(fd, data)
int fd;
- GopherData *data;
+ GopherStateData *data;
{
StoreEntry *entry = NULL;
entry = data->entry;
/* This will be called when data is ready to be read from fd. Read until
* error or connection closed. */
-int gopherReadReply(fd, data)
+static void gopherReadReply(fd, data)
int fd;
- GopherData *data;
+ GopherStateData *data;
{
char *buf = NULL;
int len;
int clen;
int off;
StoreEntry *entry = NULL;
+ int bin;
entry = data->entry;
- if (entry->flag & DELETE_BEHIND) {
- if (storeClientWaiting(entry)) {
- clen = entry->mem_obj->e_current_len;
- off = entry->mem_obj->e_lowest_offset;
- if ((clen - off) > GOPHER_DELETE_GAP) {
- debug(10, 3, "gopherReadReply: Read deferred for Object: %s\n",
- entry->url);
- debug(10, 3, " Current Gap: %d bytes\n",
- clen - off);
-
- /* reschedule, so it will automatically reactivated when
- * Gap is big enough. */
- comm_set_select_handler(fd,
- COMM_SELECT_READ,
- (PF) gopherReadReply,
- (void *) data);
- /* don't install read timeout until we are below the GAP */
- comm_set_select_handler_plus_timeout(fd,
- COMM_SELECT_TIMEOUT,
- (PF) NULL,
- (void *) NULL,
- (time_t) 0);
- comm_set_stall(fd, Config.stallDelay); /* dont try reading again for a while */
- return 0;
- }
- } else {
- /* we can terminate connection right now */
- squid_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL);
+ if (entry->flag & DELETE_BEHIND && !storeClientWaiting(entry)) {
+ /* we can terminate connection right now */
+ squid_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL);
+ comm_close(fd);
+ return;
+ }
+ /* check if we want to defer reading */
+ clen = entry->mem_obj->e_current_len;
+ off = storeGetLowestReaderOffset(entry);
+ if ((clen - off) > GOPHER_DELETE_GAP) {
+ if (entry->flag & CLIENT_ABORT_REQUEST) {
+ squid_error_entry(entry, ERR_CLIENT_ABORT, NULL);
comm_close(fd);
- return 0;
+ return;
+ }
+ IOStats.Gopher.reads_deferred++;
+ debug(10, 3, "gopherReadReply: Read deferred for Object: %s\n",
+ entry->url);
+ debug(10, 3, " Current Gap: %d bytes\n", clen - off);
+ /* reschedule, so it will automatically reactivated when
+ * Gap is big enough. */
+ comm_set_select_handler(fd,
+ COMM_SELECT_READ,
+ (PF) gopherReadReply,
+ (void *) data);
+ /* don't install read timeout until we are below the GAP */
+ comm_set_select_handler_plus_timeout(fd,
+ COMM_SELECT_TIMEOUT,
+ (PF) NULL,
+ (void *) NULL,
+ (time_t) 0);
+ if (!BIT_TEST(entry->flag, READ_DEFERRED)) {
+ comm_set_fd_lifetime(fd, 3600); /* limit during deferring */
+ BIT_SET(entry->flag, READ_DEFERRED);
}
+ /* dont try reading again for a while */
+ comm_set_stall(fd, Config.stallDelay);
+ return;
+ } else {
+ BIT_RESET(entry->flag, READ_DEFERRED);
}
buf = get_free_4k_page();
errno = 0;
- len = read(fd, buf, TEMP_BUF_SIZE - 1); /* leave one space for \0 in gopherToHTML */
+ /* leave one space for \0 in gopherToHTML */
+ len = read(fd, buf, TEMP_BUF_SIZE - 1);
debug(10, 5, "gopherReadReply: FD %d read len=%d\n", fd, len);
-
+ if (len > 0) {
+ IOStats.Gopher.reads++;
+ for (clen = len - 1, bin = 0; clen; bin++)
+ clen >>= 1;
+ IOStats.Gopher.read_hist[bin]++;
+ }
if (len < 0) {
debug(10, 1, "gopherReadReply: error reading: %s\n", xstrerror());
if (errno == EAGAIN || errno == EWOULDBLOCK) {
/* reinstall handlers */
/* XXX This may loop forever */
- comm_set_select_handler(fd, COMM_SELECT_READ,
- (PF) gopherReadReply, (void *) data);
- comm_set_select_handler_plus_timeout(fd, COMM_SELECT_TIMEOUT,
- (PF) gopherReadReplyTimeout, (void *) data, Config.readTimeout);
+ comm_set_select_handler(fd,
+ COMM_SELECT_READ,
+ (PF) gopherReadReply,
+ (void *) data);
+ comm_set_select_handler_plus_timeout(fd,
+ COMM_SELECT_TIMEOUT,
+ (PF) gopherReadReplyTimeout,
+ (void *) data,
+ Config.readTimeout);
} else {
BIT_RESET(entry->flag, ENTRY_CACHABLE);
storeReleaseRequest(entry);
!(entry->flag & DELETE_BEHIND)) {
/* accept data, but start to delete behind it */
storeStartDeleteBehind(entry);
-
if (data->conversion != NORMAL) {
gopherToHTML(data, buf, len);
} else {
Config.readTimeout);
}
put_free_4k_page(buf);
- return 0;
+ return;
}
/* This will be called when request write is complete. Schedule read of
* reply. */
-void gopherSendComplete(fd, buf, size, errflag, data)
+static void gopherSendComplete(fd, buf, size, errflag, data)
int fd;
char *buf;
int size;
int errflag;
void *data;
{
- GopherData *gopherState = (GopherData *) data;
+ GopherStateData *gopherState = (GopherStateData *) data;
StoreEntry *entry = NULL;
entry = gopherState->entry;
debug(10, 5, "gopherSendComplete: FD %d size: %d errflag: %d\n",
}
/* This will be called when connect completes. Write request. */
-void gopherSendRequest(fd, data)
+static void gopherSendRequest(fd, data)
int fd;
- GopherData *data;
+ GopherStateData *data;
{
int len;
LOCAL_ARRAY(char, query, MAX_URL);
{
/* Create state structure. */
int sock, status;
- GopherData *data = CreateGopherData();
+ GopherStateData *data = CreateGopherStateData();
storeLockObject(data->entry = entry, NULL, NULL);
}
-GopherData *CreateGopherData()
+static GopherStateData *CreateGopherStateData()
{
- GopherData *gd = xcalloc(1, sizeof(GopherData));
+ GopherStateData *gd = xcalloc(1, sizeof(GopherStateData));
gd->buf = get_free_4k_page();
return (gd);
}
/*
- * $Id: stat.cc,v 1.60 1996/09/05 22:16:00 wessels Exp $
+ * $Id: stat.cc,v 1.61 1996/09/12 16:39:55 wessels Exp $
*
* DEBUG: section 18 Cache Manager Statistics
* AUTHOR: Harvest Derived
percent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads));
}
+ storeAppendPrintf(sentry, "{}\n");
+ storeAppendPrintf(sentry, "{Gopher I/O}\n");
+ storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Gopher.reads);
+ storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n",
+ IOStats.Gopher.reads_deferred,
+ percent(IOStats.Gopher.reads_deferred, IOStats.Gopher.reads));
+ storeAppendPrintf(sentry, "{Read Histogram:}\n");
+ for (i = 0; i < 16; i++) {
+ storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n",
+ i ? (1 << (i - 1)) + 1 : 1,
+ 1 << i,
+ IOStats.Gopher.read_hist[i],
+ percent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads));
+ }
+
+ storeAppendPrintf(sentry, "{}\n");
+ storeAppendPrintf(sentry, "{WAIS I/O}\n");
+ storeAppendPrintf(sentry, "{number of reads: %d}\n", IOStats.Wais.reads);
+ storeAppendPrintf(sentry, "{deferred reads: %d (%d%%)}\n",
+ IOStats.Wais.reads_deferred,
+ percent(IOStats.Wais.reads_deferred, IOStats.Wais.reads));
+ storeAppendPrintf(sentry, "{Read Histogram:}\n");
+ for (i = 0; i < 16; i++) {
+ storeAppendPrintf(sentry, "{%5d-%5d: %9d %2d%%}\n",
+ i ? (1 << (i - 1)) + 1 : 1,
+ 1 << i,
+ IOStats.Wais.read_hist[i],
+ percent(IOStats.Wais.read_hist[i], IOStats.Wais.reads));
+ }
+
storeAppendPrintf(sentry, close_bracket);
}
/*
- * $Id: wais.cc,v 1.37 1996/09/03 19:24:09 wessels Exp $
+ * $Id: wais.cc,v 1.38 1996/09/12 16:39:57 wessels Exp $
*
* DEBUG: section 24 WAIS Relay
* AUTHOR: Harvest Derived
-
/* This will be called when data is ready to be read from fd. Read until
* error or connection closed. */
static void waisReadReply(fd, waisState)
LOCAL_ARRAY(char, buf, 4096);
int len;
StoreEntry *entry = NULL;
+ int clen;
+ int off;
+ int bin;
entry = waisState->entry;
- if (entry->flag & DELETE_BEHIND) {
- if (storeClientWaiting(entry)) {
- /* check if we want to defer reading */
- if ((entry->mem_obj->e_current_len -
- entry->mem_obj->e_lowest_offset) > WAIS_DELETE_GAP) {
- debug(24, 3, "waisReadReply: Read deferred for Object: %s\n",
- entry->url);
- debug(24, 3, " Current Gap: %d bytes\n",
- entry->mem_obj->e_current_len -
- entry->mem_obj->e_lowest_offset);
- /* reschedule, so it will automatically reactivated
- * when Gap is big enough. */
- comm_set_select_handler(fd,
- COMM_SELECT_READ,
- (PF) waisReadReply,
- (void *) waisState);
- /* don't install read handler while we're above the gap */
- comm_set_select_handler_plus_timeout(fd,
- COMM_SELECT_TIMEOUT,
- (PF) NULL,
- (void *) NULL,
- (time_t) 0);
- /* dont try reading again for a while */
- comm_set_stall(fd, Config.stallDelay);
- return;
- }
- } else {
- /* we can terminate connection right now */
- squid_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL);
+ if (entry->flag & DELETE_BEHIND && !storeClientWaiting(entry)) {
+ /* we can terminate connection right now */
+ squid_error_entry(entry, ERR_NO_CLIENTS_BIG_OBJ, NULL);
+ comm_close(fd);
+ return;
+ }
+ /* check if we want to defer reading */
+ clen = entry->mem_obj->e_current_len;
+ off = storeGetLowestReaderOffset(entry);
+ if ((clen - off) > WAIS_DELETE_GAP) {
+ if (entry->flag & CLIENT_ABORT_REQUEST) {
+ squid_error_entry(entry, ERR_CLIENT_ABORT, NULL);
comm_close(fd);
return;
}
+ IOStats.Wais.reads_deferred++;
+ debug(24, 3, "waisReadReply: Read deferred for Object: %s\n",
+ entry->url);
+ debug(24, 3, " Current Gap: %d bytes\n", clen - off);
+ /* reschedule, so it will automatically reactivated
+ * when Gap is big enough. */
+ comm_set_select_handler(fd,
+ COMM_SELECT_READ,
+ (PF) waisReadReply,
+ (void *) waisState);
+ /* don't install read handler while we're above the gap */
+ comm_set_select_handler_plus_timeout(fd,
+ COMM_SELECT_TIMEOUT,
+ (PF) NULL,
+ (void *) NULL,
+ (time_t) 0);
+ if (!BIT_TEST(entry->flag, READ_DEFERRED)) {
+ comm_set_fd_lifetime(fd, 3600); /* limit during deferring */
+ BIT_SET(entry->flag, READ_DEFERRED);
+ }
+ /* dont try reading again for a while */
+ comm_set_stall(fd, Config.stallDelay);
+ return;
+ } else {
+ BIT_RESET(entry->flag, READ_DEFERRED);
}
len = read(fd, buf, 4096);
- debug(24, 5, "waisReadReply - fd: %d read len:%d\n", fd, len);
-
+ debug(24, 5, "waisReadReply: FD %d read len:%d\n", fd, len);
+ if (len > 0) {
+ IOStats.Wais.reads++;
+ for (clen = len - 1, bin = 0; clen; bin++)
+ clen >>= 1;
+ IOStats.Wais.read_hist[bin]++;
+ }
if (len < 0) {
debug(24, 1, "waisReadReply: FD %d: read failure: %s.\n", xstrerror());
if (errno == EAGAIN || errno == EWOULDBLOCK) {
StoreEntry *entry = NULL;
WaisStateData *waisState = data;
entry = waisState->entry;
- debug(24, 5, "waisSendComplete - fd: %d size: %d errflag: %d\n",
+ debug(24, 5, "waisSendComplete: FD %d size: %d errflag: %d\n",
fd, size, errflag);
if (errflag) {
squid_error_entry(entry, ERR_CONNECT_FAIL, xstrerror());
char *buf = NULL;
char *Method = RequestMethodStr[waisState->method];
- debug(24, 5, "waisSendRequest - fd: %d\n", fd);
+ debug(24, 5, "waisSendRequest: FD %d\n", fd);
if (Method)
len += strlen(Method);
waisState->mime_hdr);
else
sprintf(buf, "%s %s\r\n", Method, waisState->request);
- debug(24, 6, "waisSendRequest - buf:%s\n", buf);
+ debug(24, 6, "waisSendRequest: buf: %s\n", buf);
comm_write(fd,
buf,
len,