/*
- * $Id: disk.cc,v 1.103 1998/02/09 21:17:25 wessels Exp $
+ * $Id: disk.cc,v 1.104 1998/02/10 00:55:03 wessels Exp $
*
* DEBUG: section 6 Disk I/O Routines
* AUTHOR: Harvest Derived
file_close(int fd)
{
fde *F = &fd_table[fd];
+#if USE_ASYNC_IO
if (fd < 0) {
debug(6, 0) ("file_close: FD less than zero: %d\n", fd);
return;
}
+#else
+ assert(fd >= 0);
+#endif
assert(F->open);
if (EBIT_TEST(F->flags, FD_WRITE_DAEMON)) {
EBIT_SET(F->flags, FD_CLOSE_REQUEST);
status = errno == ENOSPC ? DISK_NO_SPACE_LEFT : DISK_ERROR;
debug(50, 1) ("diskHandleWrite: FD %d: disk write error: %s\n",
fd, xstrerror());
- if (fdd->wrt_handle == NULL || status != DISK_NO_SPACE_LEFT) {
- /* FLUSH PENDING BUFFERS */
- do {
- fdd->write_q = q->next;
- if (q->free_func)
- (q->free_func) (q->buf);
- safe_free(q);
- } while ((q = fdd->write_q));
- }
+ /*
+ * If there is no write callback, then this file is
+ * most likely something important like a log file, or
+ * an interprocess pipe. Its not a swapfile. We feel
+ * that a write failure on a log file is rather important,
+ * and Squid doesn't otherwise deal with this condition.
+ * So to get the administrators attention, we exit with
+ * a fatal message.
+ */
+ if (fdd->wrt_handle == NULL)
+ fatal("Write failure -- check your disk space and cache.log");
+ /*
+ * If there is a write failure, then we notify the
+ * upper layer via the callback, at the end of this
+ * function. Meanwhile, flush all pending buffers
+ * here. Let the upper layer decide how to handle the
+ * failure. This will prevent experiencing multiple,
+ * repeated write failures for the same FD because of
+ * the queued data.
+ */
+ do {
+ fdd->write_q = q->next;
+ if (q->free_func)
+ (q->free_func) (q->buf);
+ safe_free(q);
+ } while ((q = fdd->write_q));
}
len = 0;
}
EBIT_CLR(F->flags, FD_WRITE_DAEMON);
} else {
/* another block is queued */
+ cbdataLock(fdd->wrt_handle_data);
commSetSelect(fd, COMM_SELECT_WRITE, diskHandleWrite, NULL, 0);
EBIT_SET(F->flags, FD_WRITE_DAEMON);
}
- if (fdd->wrt_handle)
- fdd->wrt_handle(fd, status, len, fdd->wrt_handle_data);
+ if (fdd->wrt_handle) {
+ if (fdd->wrt_handle_data == NULL || cbdataValid(fdd->wrt_handle_data))
+ fdd->wrt_handle(fd, status, len, fdd->wrt_handle_data);
+ if (fdd->wrt_handle_data != NULL)
+ cbdataUnlock(fdd->wrt_handle_data);
+ }
if (EBIT_TEST(F->flags, FD_CLOSE_REQUEST))
file_close(fd);
}
F->disk.write_q_tail = wq;
}
if (!EBIT_TEST(F->flags, FD_WRITE_DAEMON)) {
+ cbdataLock(F->disk.wrt_handle_data);
#if USE_ASYNC_IO
diskHandleWrite(fd, NULL);
#else
extern void storeSwapOutHandle(int fdnotused, int flag, size_t len, void *data);
extern void storeCheckSwapOut(StoreEntry * e);
extern void storeSwapOutFileClose(StoreEntry * e);
-extern void storeSwapOutFileClose(StoreEntry * e);
/*
* store_client.c
/*
- * $Id: store_dir.cc,v 1.48 1998/02/06 18:54:10 wessels Exp $
+ * $Id: store_dir.cc,v 1.49 1998/02/10 00:55:04 wessels Exp $
*
* DEBUG: section 47 Store Directory Routines
* AUTHOR: Duane Wessels
debug(50, 0) ("storeDirWriteCleanLogs: %s: %s\n", new[dirn], xstrerror());
continue;
}
+ debug(20, 3) ("storeDirWriteCleanLogs: opened %s, FD %d\n",
+ new[dirn], fd[dirn]);
#if HAVE_FCHMOD
if (stat(cur[dirn], &sb) == 0)
fchmod(fd[dirn], sb.st_mode);
/* buffered write */
if (outbufoffset[dirn] + sizeof(storeSwapData) > CLEAN_BUF_SZ) {
if (write(fd[dirn], outbuf[dirn], outbufoffset[dirn]) < 0) {
- debug(50, 0) ("storeDirWriteCleanLogs: %s: %s\n",
+ debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
new[dirn], xstrerror());
debug(20, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.\n");
file_close(fd[dirn]);
fd[dirn] = -1;
- unlink(cln[dirn]);
+ unlink(new[dirn]);
continue;
}
outbufoffset[dirn] = 0;
for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
if (outbufoffset[dirn] == 0)
continue;
+ if (fd[dirn] < 0)
+ continue;
if (write(fd[dirn], outbuf[dirn], outbufoffset[dirn]) < 0) {
- debug(50, 0) ("storeDirWriteCleanLogs: %s: %s\n", new[dirn], xstrerror());
+ debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
+ new[dirn], xstrerror());
debug(20, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.\n");
file_close(fd[dirn]);
fd[dirn] = -1;
- unlink(cln[dirn]);
+ unlink(new[dirn]);
continue;
}
safe_free(outbuf[dirn]);
}
safe_free(outbuf);
safe_free(outbufoffset);
- /* close */
+ /* rename */
for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
- file_close(fd[dirn]);
- fd[dirn] = -1;
+ if (fd[dirn] < 0)
+ continue;
if (rename(new[dirn], cur[dirn]) < 0) {
debug(50, 0) ("storeDirWriteCleanLogs: rename failed: %s, %s -> %s\n",
xstrerror(), new[dirn], cur[dirn]);
debug(20, 1) (" Took %d seconds (%6.1lf entries/sec).\n",
r > 0 ? r : 0, (double) n / (r > 0 ? r : 1));
/* touch a timestamp file if we're not still validating */
- for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
- if (!store_rebuilding)
+ if (!store_rebuilding) {
+ for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
+ if (fd[dirn] < 0)
+ continue;
file_close(file_open(cln[dirn],
- O_WRONLY | O_CREAT | O_TRUNC, NULL, NULL, NULL));
+ O_WRONLY | O_CREAT | O_TRUNC, NULL, NULL, NULL));
+ }
+ }
+ /* close */
+ for (dirn = 0; dirn < Config.cacheSwap.n_configured; dirn++) {
safe_free(cur[dirn]);
safe_free(new[dirn]);
safe_free(cln[dirn]);
+ if (fd[dirn] < 0)
+ continue;
+ file_close(fd[dirn]);
+ fd[dirn] = -1;
}
safe_free(cur);
safe_free(new);
tlv *t;
double x;
assert(d != NULL);
- debug(20, 3) ("storeRebuildFromDirectory: DIR #%s\n", d->dirn);
+ debug(20, 3) ("storeRebuildFromDirectory: DIR #%d\n", d->dirn);
for (count = 0; count < d->speed; count++) {
assert(fd == -1);
fd = storeGetNextFile(d, &sfileno, &size);
if (fd == -2) {
- debug(20, 1) ("storeRebuildFromDirectory: done!\n");
+ debug(20, 1) ("storeRebuildFromDirectory: DIR #%d done!\n", d->dirn);
+ storeDirCloseTmpSwapLog(d->dirn);
store_rebuilding = 0;
return -1;
} else if (fd < 0) {
void
storeSwapOutStart(StoreEntry * e)
{
- swapout_ctrl_t *ctrlp;
- LOCAL_ARRAY(char, swapfilename, SQUID_MAXPATHLEN);
+ swapout_ctrl_t *ctrlp = xmalloc(sizeof(swapout_ctrl_t));
+ assert(e->mem_obj);
+ cbdataAdd(ctrlp, MEM_NONE);
storeLockObject(e);
e->swap_file_number = storeDirMapAllocate();
- storeSwapFullPath(e->swap_file_number, swapfilename);
- ctrlp = xmalloc(sizeof(swapout_ctrl_t));
- ctrlp->swapfilename = xstrdup(swapfilename);
+ ctrlp->swapfilename = xstrdup(storeSwapFullPath(e->swap_file_number, NULL));
ctrlp->e = e;
ctrlp->oldswapstatus = e->swap_status;
e->swap_status = SWAPOUT_OPENING;
- file_open(swapfilename,
+ e->mem_obj->swapout.ctrl = ctrlp;
+ file_open(ctrlp->swapfilename,
O_WRONLY | O_CREAT | O_TRUNC,
storeSwapOutFileOpened,
- ctrlp, e);
+ ctrlp,
+ e);
}
void
storeSwapOutHandle(int fdnotused, int flag, size_t len, void *data)
{
- StoreEntry *e = data;
+ swapout_ctrl_t *ctrlp = data;
+ StoreEntry *e = ctrlp->e;
MemObject *mem = e->mem_obj;
debug(20, 3) ("storeSwapOutHandle: '%s', len=%d\n", storeKeyText(e->key), (int) len);
if (flag < 0) {
swap_buf,
swap_buf_len,
storeSwapOutHandle,
- e,
+ mem->swapout.ctrl,
memFreeDISK);
}
storeSwapOutFileClose(StoreEntry * e)
{
MemObject *mem = e->mem_obj;
+ swapout_ctrl_t *ctrlp;
assert(mem != NULL);
- if (mem->swapout.fd > -1) {
- file_close(mem->swapout.fd);
- mem->swapout.fd = -1;
- storeUnlockObject(e);
- }
+ if (mem->swapout.fd < 0) {
#if USE_ASYNC_IO
- else
aioCancel(-1, e); /* Make doubly certain pending ops are gone */
#endif
+ return;
+ }
+ ctrlp = mem->swapout.ctrl;
+ file_close(mem->swapout.fd);
+ mem->swapout.fd = -1;
+ xfree(ctrlp->swapfilename);
+ cbdataFree(ctrlp);
+ mem->swapout.ctrl = NULL;
+ storeUnlockObject(e);
}
static void
storeSwapOutFileOpened(void *data, int fd, int errcode)
{
swapout_ctrl_t *ctrlp = data;
- int oldswapstatus = ctrlp->oldswapstatus;
- char *swapfilename = ctrlp->swapfilename;
StoreEntry *e = ctrlp->e;
- MemObject *mem;
+ MemObject *mem = e->mem_obj;
int swap_hdr_sz = 0;
tlv *tlv_list;
char *buf;
- xfree(ctrlp);
if (fd == -2 && errcode == -2) { /* Cancelled - Clean up */
- xfree(swapfilename);
+ xfree(ctrlp->swapfilename);
+ cbdataFree(ctrlp);
+ mem->swapout.ctrl = NULL;
return;
}
assert(e->swap_status == SWAPOUT_OPENING);
if (fd < 0) {
debug(20, 0) ("storeSwapOutFileOpened: Unable to open swapfile: %s\n",
- swapfilename);
+ ctrlp->swapfilename);
storeDirMapBitReset(e->swap_file_number);
e->swap_file_number = -1;
- e->swap_status = oldswapstatus;
- xfree(swapfilename);
+ e->swap_status = ctrlp->oldswapstatus;
+ xfree(ctrlp->swapfilename);
+ cbdataFree(ctrlp);
+ mem->swapout.ctrl = NULL;
return;
}
- mem = e->mem_obj;
mem->swapout.fd = (short) fd;
e->swap_status = SWAPOUT_WRITING;
debug(20, 5) ("storeSwapOutFileOpened: Begin SwapOut '%s' to FD %d '%s'\n",
- storeUrl(e), fd, swapfilename);
- xfree(swapfilename);
+ storeUrl(e), fd, ctrlp->swapfilename);
debug(20, 5) ("swap_file_number=%08X\n", e->swap_file_number);
tlv_list = storeSwapMetaBuild(e);
buf = storeSwapMetaPack(tlv_list, &swap_hdr_sz);
buf,
mem->swap_hdr_sz,
storeSwapOutHandle,
- e,
+ ctrlp,
xfree);
}
off_t queue_offset; /* relative to in-mem data */
off_t done_offset; /* relative to swap file with meta headers! */
int fd;
+ void *ctrl;
} swapout;
struct _http_reply *reply;
request_t *request;