-/* $Id: http.cc,v 1.32 1996/04/08 18:28:57 wessels Exp $ */
+/* $Id: http.cc,v 1.33 1996/04/09 23:27:56 wessels Exp $ */
/*
* DEBUG: Section 11 http: HTTP
* icpReadWriteData */
char *reply_hdr;
int reply_hdr_state;
- int content_length;
- int http_code;
- char content_type[128];
} HttpData;
char *RequestMethodStr[] =
char *t2 = NULL;
StoreEntry *entry = data->entry;
char *headers = NULL;
- int hdr_sz = 0;
int room;
int hdr_len;
+ struct _http_reply *reply = NULL;
debug(11, 3, "httpProcessReplyHeader: key '%s'\n", entry->key);
t = t2 < t1 ? t2 : t1;
else
t = t2 ? t2 : t1;
- if (t) {
- data->reply_hdr_state++;
- t += (t == t1 ? 4 : 2);
- *t = '\0';
- hdr_sz = t - data->reply_hdr;
- }
- debug(11, 7, "httpProcessReplyHeader: hdr_sz = %d\n", hdr_sz);
+ if (!t)
+ return; /* headers not complete */
+ t += (t == t1 ? 4 : 2);
+ *t = '\0';
+ reply = entry->mem_obj->reply;
+ reply->hdr_sz = t - data->reply_hdr;
+ debug(11, 7, "httpProcessReplyHeader: hdr_sz = %d\n", reply->hdr_sz);
+ data->reply_hdr_state++;
}
if (data->reply_hdr_state == 1) {
headers = xstrdup(data->reply_hdr);
while (*s == '\r')
*s-- = '\0';
if (!strncasecmp(t, "HTTP", 4)) {
+ sscanf (t+1, "%lf", &reply->version);
if ((t = strchr(t, ' '))) {
t++;
- data->http_code = atoi(t);
+ reply->code = atoi(t);
}
} else if (!strncasecmp(t, "Content-type:", 13)) {
if ((t = strchr(t, ' '))) {
t++;
- strncpy(data->content_type, t, 127);
+ strncpy(reply->content_type, t, HTTP_REPLY_FIELD_SZ-1);
}
} else if (!strncasecmp(t, "Content-length:", 15)) {
if ((t = strchr(t, ' '))) {
t++;
- data->content_length = atoi(t);
+ reply->content_length = atoi(t);
+ }
+ } else if (!strncasecmp(t, "Date:", 5)) {
+ if ((t = strchr(t, ' '))) {
+ t++;
+ strncpy(reply->date, t, HTTP_REPLY_FIELD_SZ-1);
+ }
+ } else if (!strncasecmp(t, "Expires:", 8)) {
+ if ((t = strchr(t, ' '))) {
+ t++;
+ strncpy(reply->expires, t, HTTP_REPLY_FIELD_SZ-1);
+ }
+ } else if (!strncasecmp(t, "Last-Modified:", 14)) {
+ if ((t = strchr(t, ' '))) {
+ t++;
+ strncpy(reply->last_modified, t, HTTP_REPLY_FIELD_SZ-1);
}
}
t = strtok(NULL, "\n");
}
- if (data->http_code)
- debug(11, 3, "httpReadReply: HTTP CODE: %d\n", data->http_code);
- if (data->content_length)
- debug(11, 3, "httpReadReply: Content Length: %d\n", data->content_length);
- switch (data->http_code) {
+ if (reply->code)
+ debug(11, 3, "httpReadReply: HTTP CODE: %d\n", reply->code);
+ switch (reply->code) {
case 200: /* OK */
case 203: /* Non-Authoritative Information */
case 300: /* Multiple Choices */
storeSetPrivateKey(entry);
storeExpireNow(entry);
BIT_RESET(entry->flag, CACHABLE);
- BIT_SET(entry->flag, RELEASE_REQUEST);
+ storeReleaseRequest(entry, __FILE__,__LINE__);
break;
default:
/* These can be negative cached, make key public */
storeSetPublicKey(entry);
break;
}
- entry->mem_obj->http_code = data->http_code;
- entry->mem_obj->content_length = data->content_length;
- entry->mem_obj->hdr_sz = hdr_sz;
}
}
(PF) httpReadReplyTimeout, (void *) data, getReadTimeout());
} else {
BIT_RESET(entry->flag, CACHABLE);
- BIT_SET(entry->flag, RELEASE_REQUEST);
+ storeReleaseRequest(entry, __FILE__,__LINE__);
cached_error_entry(entry, ERR_READ_ERROR, xstrerror());
httpCloseAndFree(fd, data);
}
-/* $Id: store.cc,v 1.34 1996/04/09 18:37:15 wessels Exp $ */
-#ident "$Id: store.cc,v 1.34 1996/04/09 18:37:15 wessels Exp $"
+/* $Id: store.cc,v 1.35 1996/04/09 23:27:59 wessels Exp $ */
+#ident "$Id: store.cc,v 1.35 1996/04/09 23:27:59 wessels Exp $"
/*
* DEBUG: Section 20 store
#define STORE_BUCKETS (7921)
#define STORE_IN_MEM_BUCKETS (143)
+#define STORE_LOG_CREATE 0
+#define STORE_LOG_SWAPIN 1
+#define STORE_LOG_SWAPOUT 2
+#define STORE_LOG_RELEASE 3
+
+static char *storeLogTags[] = {
+ "CREATE",
+ "SWAPIN",
+ "SWAPOUT",
+ "RELEASE"
+};
+
/* Now, this table is inaccessible to outsider. They have to use a method
* to access a value in internal storage data structure. */
HashID table = 0;
static int store_swap_size = 0; /* kilobytes !! */
static unsigned long store_swap_high = 0;
static unsigned long store_swap_low = 0;
-static int swaplog_fd = 0;
-static int swaplog_lock;
+static int swaplog_fd = -1;
+static int swaplog_lock = 0;
FILE *swaplog_stream = NULL;
+static int storelog_fd = -1;
/* counter for uncachable objects */
static int key_counter = 0;
static MemObject *new_MemObject()
{
MemObject *m = NULL;
- m = xcalloc(1, sizeof(MemObject));
+ m = (MemObject *) xcalloc(1, sizeof(MemObject));
+ m->reply = (struct _http_reply *) xcalloc (1, sizeof(struct _http_reply));
meta_data.store_in_mem_objects++;
debug(20, 3, "new_MemObject: returning %p\n", m);
return m;
MemObject *m;
{
debug(20, 3, "destroy_MemObject: destroying %p\n", m);
+ safe_free(m->mime_hdr);
+ safe_free(m->reply);
xfree(m);
- if (m->mime_hdr)
- xfree(m->mime_hdr);
meta_data.store_in_mem_objects--;
}
if (!e)
fatal_dump("storeFreeEntry: NULL Entry");
- debug(20, 3, "storeFreeEntry: Freeing %s\n", e->url);
+ debug(20, 3, "storeFreeEntry: Freeing %s\n", e->key);
if (has_mem_obj(e)) {
destroy_MemObjectData(e->mem_obj);
destroy_StoreEntry(e);
}
+static char *time_describe (t)
+ time_t t;
+{
+ static char buf[128];
+
+ if (t < 60) {
+ sprintf (buf, "%ds", (int) t);
+ } else if (t < 3600) {
+ sprintf(buf, "%dm", (int) t/60);
+ } else if (t < 86400) {
+ sprintf(buf, "%dh", (int) t/3600);
+ } else if (t < 604800) {
+ sprintf(buf, "%dD", (int) t/86400);
+ } else if (t < 2592000) {
+ sprintf(buf, "%dW", (int) t/604800);
+ } else if (t < 31536000) {
+ sprintf(buf, "%dM", (int) t/2592000);
+ } else {
+ sprintf(buf, "%dY", (int) t/31536000);
+ }
+ return buf;
+}
+
+static void storeLog(tag, e)
+ int tag;
+ StoreEntry *e;
+{
+ time_t t;
+ int expect_len = 0;
+ int actual_len = 0;
+ int code = 0;
+ static char logmsg[MAX_URL + 300];
+ if (storelog_fd < 0)
+ return;
+ t = e->expires - cached_curtime;
+ if (e->mem_obj) {
+ code = e->mem_obj->reply->code;
+ expect_len = (int) e->mem_obj->reply->content_length;
+ actual_len = (int) e->mem_obj->e_current_len - e->mem_obj->reply->hdr_sz;
+ }
+ sprintf(logmsg, "%9d.%03d %-7s %4d %9d [%3s] %d/%d %s\n",
+ (int) current_time.tv_sec,
+ (int) current_time.tv_usec / 1000,
+ storeLogTags[tag],
+ code,
+ (int) t,
+ time_describe(t),
+ expect_len,
+ actual_len,
+ e->key);
+ file_write(storelog_fd,
+ xstrdup(logmsg),
+ strlen(logmsg),
+ 0,
+ NULL,
+ NULL);
+}
+
/* get rid of memory copy of the object */
void storePurgeMem(e)
StoreEntry *e;
{
- debug(20, 3, "storePurgeMem: Freeing memory-copy of %s\n", e->url);
+ debug(20, 3, "storePurgeMem: Freeing memory-copy of %s\n", e->key);
if (!has_mem_obj(e))
return;
int status = 0;
e->lock_count++;
- debug(20, 3, "storeLockObject: locks %d: <URL:%s>\n", e->lock_count, e->url);
+ debug(20, 3, "storeLockObject: locks %d: '%s'\n", e->lock_count, e->key);
if ((e->mem_status == NOT_IN_MEMORY) && /* Not in memory */
(e->swap_status != SWAP_OK) && /* Not on disk */
return status;
}
+void storeReleaseRequest (e, file, line)
+ StoreEntry *e;
+ char *file;
+ int line;
+{
+ debug(20,1,"storeReleaseRequest: FROM %s:%d FOR '%s'\n",
+ file, line, e->key ? e->key : e->url);
+ BIT_SET(e->flag, RELEASE_REQUEST);
+}
+
/* unlock object, return -1 if object get released after unlock
* otherwise lock_count */
debug(20, 0, "storeSetPublicKey: Making old '%s' private.\n", newkey);
e2 = (StoreEntry *) table_entry;
storeSetPrivateKey(e2);
- BIT_SET(e2->flag, RELEASE_REQUEST);
+ storeReleaseRequest(e2, __FILE__,__LINE__);
}
if (e->key)
storeHashDelete(e);
BIT_RESET(e->flag, ENTRY_PRIVATE);
} else {
BIT_RESET(e->flag, CACHABLE);
- BIT_SET(e->flag, RELEASE_REQUEST);
+ storeReleaseRequest(e, __FILE__,__LINE__);
BIT_SET(e->flag, ENTRY_PRIVATE);
}
if (neighbors_do_private_keys || !BIT_TEST(flags, REQ_PUBLIC))
m->client_list_size = MIN_CLIENT;
m->client_list = (ClientStatusEntry **)
xcalloc(m->client_list_size, sizeof(ClientStatusEntry *));
+ /* storeLog(STORE_LOG_CREATE, e); */
return e;
}
PendingEntry *pe = (PendingEntry *) xmalloc(sizeof(PendingEntry));
int old_size, i, j;
- debug(20, 3, "storeRegister: FD %d <URL:%s>\n", fd, e->url);
+ debug(20, 3, "storeRegister: FD %d '%s'\n", fd, e->key);
memset(pe, '\0', sizeof(PendingEntry));
pe->fd = fd;
int i;
int freed = 0;
- debug(20, 10, "storeUnregister: called for FD %d <URL:%s>\n", fd, e->url);
+ debug(20, 10, "storeUnregister: called for FD %d '%s'\n", fd, e->key);
/* look for entry in client_list */
if (e->mem_obj->client_list) {
void storeExpireNow(e)
StoreEntry *e;
{
- debug(20, 3, "storeExpireNow: Object %s\n", e->url);
+ debug(20, 3, "storeExpireNow: '%s'\n", e->key);
e->expires = cached_curtime;
}
/* change its key, so it couldn't be found by other client */
storeSetPrivateKey(e);
BIT_SET(e->flag, DELETE_BEHIND);
- BIT_SET(e->flag, RELEASE_REQUEST);
+ storeReleaseRequest(e, __FILE__,__LINE__);
BIT_RESET(e->flag, CACHABLE);
storeExpireNow(e);
}
fatal_dump(NULL);
}
if (len) {
- debug(20, 5, "storeAppend: appending %d bytes for %s\n", len, e->url);
+ debug(20, 5, "storeAppend: appending %d bytes for '%s'\n", len, e->key);
/* get some extra storage if needed */
(void) storeGetMemSpace(len, 0);
StoreEntry *e;
int offset_notused;
{
- debug(20, 2, "storeSwapInHandle: <URL:%s>\n", e->url);
+ debug(20, 2, "storeSwapInHandle: '%s'\n", e->key);
if ((flag < 0) && (flag != DISK_EOF)) {
debug(20, 0, "storeSwapInHandle: SwapIn failure (err code = %d).\n", flag);
storeSetMemStatus(e, IN_MEMORY);
put_free_8k_page(e->mem_obj->e_swap_buf, __FILE__, __LINE__);
file_close(e->mem_obj->swap_fd);
+ storeLog(STORE_LOG_SWAPIN, e);
debug(20, 5, "storeSwapInHandle: SwapIn complete: <URL:%s> from %s.\n",
e->url, storeSwapFullPath(e->swap_file_number, NULL));
if (e->mem_obj->e_current_len != e->object_len) {
static char logmsg[6000];
char *page_ptr = NULL;
- debug(20, 3, "storeSwapOutHandle: <URL:%s>\n", e->url);
+ debug(20, 3, "storeSwapOutHandle: '%s'\n", e->key);
e->timestamp = cached_curtime;
storeSwapFullPath(e->swap_file_number, filename);
e->swap_status = NO_SWAP;
put_free_8k_page(page_ptr, __FILE__, __LINE__);
file_close(fd);
- BIT_SET(e->flag, RELEASE_REQUEST);
+ storeReleaseRequest(e, __FILE__,__LINE__);
if (e->swap_file_number != -1) {
file_map_bit_reset(e->swap_file_number);
safeunlink(filename, 0); /* remove it */
/* swapping complete */
e->swap_status = SWAP_OK;
file_close(e->mem_obj->swap_fd);
+ storeLog(STORE_LOG_SWAPOUT, e);
debug(20, 5, "storeSwapOutHandle: SwapOut complete: <URL:%s> to %s.\n",
e->url, storeSwapFullPath(e->swap_file_number, NULL));
put_free_8k_page(page_ptr, __FILE__, __LINE__);
{
if (BIT_TEST(e->flag, ENTRY_PRIVATE)) {
- debug(20, 3, "storeCheckSwapable: NO: private entry\n");
+ debug(20, 2, "storeCheckSwapable: NO: private entry\n");
} else if (e->expires <= cached_curtime) {
- debug(20, 3, "storeCheckSwapable: NO: already expired\n");
+ debug(20, 2, "storeCheckSwapable: NO: already expired\n");
} else if (e->type_id != METHOD_GET) {
- debug(20, 3, "storeCheckSwapable: NO: non-GET method\n");
+ debug(20, 2, "storeCheckSwapable: NO: non-GET method\n");
} else if (!BIT_TEST(e->flag, CACHABLE)) {
- debug(20, 3, "storeCheckSwapable: NO: not cachable\n");
+ debug(20, 2, "storeCheckSwapable: NO: not cachable\n");
} else if (BIT_TEST(e->flag, RELEASE_REQUEST)) {
- debug(20, 3, "storeCheckSwapable: NO: release requested\n");
+ debug(20, 2, "storeCheckSwapable: NO: release requested\n");
} else if (!storeEntryValidLength(e)) {
- debug(20, 3, "storeCheckSwapable: NO: wrong content-length\n");
+ debug(20, 2, "storeCheckSwapable: NO: wrong content-length\n");
} else
return 1;
- BIT_SET(e->flag, RELEASE_REQUEST);
+ storeReleaseRequest(e, __FILE__,__LINE__);
BIT_RESET(e->flag, CACHABLE);
return 0;
}
void storeComplete(e)
StoreEntry *e;
{
- debug(20, 3, "storeComplete: <URL:%s>\n", e->url);
+ debug(20, 3, "storeComplete: '%s'\n", e->key);
e->object_len = e->mem_obj->e_current_len;
InvokeHandlers(e);
static char mime_hdr[300];
static char abort_msg[2000];
- debug(20, 6, "storeAbort: <URL:%s>\n", e->url);
+ debug(20, 6, "storeAbort: '%s'\n", e->key);
e->expires = cached_curtime + getNegativeTTL();
e->status = STORE_ABORTED;
storeSetMemStatus(e, IN_MEMORY);
(e->lock_count == 0) && /* Be overly cautious */
(e->mem_status != SWAPPING_IN)) { /* Not if it's being faulted into memory */
if (cached_curtime > e->expires) {
- debug(20, 2, "storeRemoveExpiredObj: Expired: <URL:%s>\n", e->url);
+ debug(20, 2, "storeGetSwapSpace: Expired: <URL:%s>\n", e->url);
/* just call release. don't have to check for lock status.
* storeRelease will take care of that and set a pending flag
* if it's still locked. */
if (storeEntryLocked(e)) {
storeExpireNow(e);
debug(20, 3, "storeRelease: Only setting RELEASE_REQUEST bit\n");
- BIT_SET(e->flag, RELEASE_REQUEST);
+ if (!BIT_TEST(e->flag, RELEASE_REQUEST))
+ storeReleaseRequest(e, __FILE__,__LINE__);
return -1;
}
if (e->key != NULL) {
if ((hptr = hash_lookup(table, e->key)) == NULL) {
- debug(20, 0, "storeRelease: Not Found: %s\n", e->url);
+ debug(20, 0, "storeRelease: Not Found: '%s'\n", e->key);
debug(20, 0, "Dump of Entry 'e':\n %s\n", storeToString(e));
fatal_dump(NULL);
}
e->object_len);
if (hptr)
storeHashDelete(hptr);
+ storeLog(STORE_LOG_RELEASE,e);
storeFreeEntry(e);
return 0;
}
return *size;
}
+#ifdef UNUSED_CODE
/*
* Go through the first 300 bytes of MIME header of a cached object, returning
* fields that match.
}
return (buf);
}
+#endif
int storeGrep(e, string, nbytes)
StoreEntry *e;
return 0;
}
-#ifdef HENRIK_VERSION
int storeEntryValidLength(e)
StoreEntry *e;
{
- int headerlength;
- int length;
- static char buf[BUFSIZ];
- char *header = NULL;
-
- header = storeMatchMime(e, "content-length: ", buf, BUFSIZ);
- if (!header) {
- debug(20, 1, "storeEntryValidLength: no content-length: %s\n", e->key);
- return 0;
- }
- length = atoi(header);
- if (!length) {
- debug(20, 1, "storeEntryValidLength: can't parse content-length: %s\n", e->key);
- debug(20, 1, "--> header = '%s'\n", header);
- return 0;
- }
- headerlength = storeGrep(e, "\r\n\r\n", 300);
- if (!headerlength) {
- debug(20, 1, "storeEntryValidLength: can't get headersize: %s\n", e->key);
- return 0;
- }
- if (length + headerlength != e->object_len) {
- debug(20, 1, "storeEntryValidLength: invalid content-length for '%s'\n", e->key);
- debug(20, 1, "--> %d + %d != %d\n", headerlength, length, e->object_len);
- return 0;
- }
- return 1;
-}
-#else
-int storeEntryValidLength(e)
- StoreEntry *e;
-{
- MemObject *mem = e->mem_obj;
int diff;
+ int hdr_sz;
+ int content_length;
- if (mem == NULL)
+ if (e->mem_obj == NULL)
fatal_dump("storeEntryValidLength: NULL mem_obj");
+ hdr_sz = e->mem_obj->reply->hdr_sz;
+ content_length = e->mem_obj->reply->content_length;
+
debug(20, 3, "storeEntryValidLength: Checking '%s'\n", e->key);
debug(20, 5, "storeEntryValidLength: object_len = %d\n", e->object_len);
- debug(20, 5, "storeEntryValidLength: hdr_sz = %d\n", mem->hdr_sz);
- debug(20, 5, "storeEntryValidLength: content_length = %d\n", mem->content_length);
+ debug(20, 5, "storeEntryValidLength: hdr_sz = %d\n", hdr_sz);
+ debug(20, 5, "storeEntryValidLength: content_length = %d\n", content_length);
- if (mem->content_length == 0) {
+ if (content_length == 0) {
debug(20, 5, "storeEntryValidLength: Zero content length; assume valid; '%s'\n",
e->key);
return 1;
}
- if (mem->hdr_sz == 0) {
+ if (hdr_sz == 0) {
debug(20, 5, "storeEntryValidLength: Zero header size; assume valid; '%s'\n",
e->key);
return 1;
}
- diff = mem->hdr_sz + mem->content_length - e->object_len;
+ diff = hdr_sz + content_length - e->object_len;
if (diff != 0) {
debug(20, 3, "storeEntryValidLength: %d bytes too %s; '%s'\n",
diff < 0 ? -diff : diff,
}
return 1;
}
-#endif
static int storeVerifySwapDirs(clean)
int clean;
{
int dir_created;
+ storelog_fd = file_open("store.log", NULL, O_WRONLY|O_APPEND|O_CREAT);
+
storeSanityCheck();
file_map_create(MAX_SWAP_FILE);
dir_created = storeVerifySwapDirs(zap_disk_store);
sprintf(swaplog_file, "%s/log", swappath(0));
-
if (!zap_disk_store) {
ok_write_clean_log = 0;
storeRebuildFromDisk();