the calls in there. The next (few) commits will be the async code.
Yes, yes, I know it should be "Generic", but I'm trying to get COSS
to "user testing" state, so this is the best 'comprimise'.
For now, COSS will use the libaio routines (or the sync stuff in
disk.c - the calling API is the same so wrapping stuff in an #ifdef
will be quite easy) which are available on Solaris, FreeBSD
and possibly Linux.
#
# Makefile for the COSS storage driver for the Squid Object Cache server
#
-# $Id: Makefile.in,v 1.2 2001/08/09 21:41:53 adrian Exp $
+# $Id: Makefile.in,v 1.3 2001/08/12 10:20:41 adrian Exp $
#
FS = coss
OBJS = \
store_dir_coss.o \
- store_io_coss.o
+ store_io_coss.o \
+ async_io.o
all: $(OUT)
--- /dev/null
+/*
+ * async_io.c - some quick async IO routines for COSS
+ *
+ * Adrian Chadd <adrian@squid-cache.org>
+ *
+ * These routines are simple plugin replacements for the file_* routines
+ * in disk.c . They back-end into the POSIX AIO routines to provide
+ * a nice and simple async IO framework for COSS.
+ *
+ * AIO is suitable for COSS - the only sync operations that the standard
+ * supports are read/write, and since COSS works on a single file
+ * per storedir it should work just fine.
+ *
+ * $Id: async_io.cc,v 1.1 2001/08/12 10:20:41 adrian Exp $
+ */
+
+#include "squid.h"
+#include <time.h>
+#include <aio.h>
+
+#include "async_io.h"
+
+/*
+ * For the time being, we kinda don't need to have our own
+ * open/close. Just read/write (with the queueing), and callback
+ * with the dequeueing)
+ */
+
+void
+a_file_read(async_queue_t *q, int fd, void *buf, int req_len, off_t offset,
+ DRCB *callback, void *data)
+{
+ assert(q->aq_state == AQ_STATE_SETUP);
+
+ file_read(fd, buf, req_len, offset, callback, data);
+}
+
+
+void
+a_file_write(async_queue_t *q, int fd, off_t offset, void *buf, int len,
+ DWCB *callback, void *data, FREE *freefunc)
+{
+ assert(q->aq_state == AQ_STATE_SETUP);
+
+ file_write(fd, offset, buf, len, callback, data, freefunc);
+}
+
+
+int
+a_file_callback(async_queue_t *q)
+{
+ assert(q->aq_state == AQ_STATE_SETUP);
+
+ return 0;
+}
+
+
+void
+a_file_setupqueue(async_queue_t *q)
+{
+ int i;
+
+ /* Make sure the queue isn't setup */
+ assert(q->aq_state == AQ_STATE_NONE);
+
+ /* Loop through, blanking the queue entries */
+
+ /* Done */
+ q->aq_state = AQ_STATE_SETUP;
+
+}
+
+
+void
+a_file_syncqueue(async_queue_t *q)
+{
+ assert(q->aq_state == AQ_STATE_SETUP);
+
+}
+
+
+void
+a_file_closequeue(async_queue_t *q)
+{
+ assert(q->aq_state == AQ_STATE_SETUP);
+
+ a_file_syncqueue(q);
+ q->aq_state = AQ_STATE_NONE;
+}
+
--- /dev/null
+#ifndef __ASYNC_IO_H__
+#define __ASYNC_IO_H__
+
+#define MAX_ASYNCOP 128
+
+typedef enum {
+ AQ_STATE_NONE, /* Not active/uninitialised */
+ AQ_STATE_SETUP /* Initialised */
+} async_queue_state_t;
+
+typedef enum {
+ AQ_ENTRY_FREE,
+ AQ_ENTRY_USED
+} async_queue_entry_state_t;
+
+
+typedef struct _async_queue_entry async_queue_entry_t;
+typedef struct _async_queue async_queue_t;
+
+/* An async queue entry */
+struct _async_queue_entry {
+ async_queue_entry_state_t aq_e_state;
+ struct aiocb aq_e_queue[MAX_ASYNCOP];
+ union {
+ DRCB *read;
+ DWCB *write;
+ } callback;
+ void *callback_data;
+};
+
+/* An async queue */
+struct _async_queue {
+ async_queue_state_t aq_state;
+ async_queue_entry_t aq_queue; /* queued operations */
+ int aq_numpending; /* Num of pending ops */
+};
+
+
+/* Functions */
+extern void a_file_read(async_queue_t *q, int fd, void *buf, int req_len,
+ off_t offset, DRCB *callback, void *data);
+extern void a_file_write(async_queue_t *q, int fd, off_t offset, void *buf,
+ int len, DWCB *callback, void *data, FREE *freefunc);
+extern int a_file_callback(async_queue_t *q);
+extern void a_file_setupqueue(async_queue_t *q);
+extern void a_file_syncqueue(async_queue_t *q);
+extern void a_file_closequeue(async_queue_t *q);
+
+#endif
int numcollisions;
dlink_list index;
int count;
+ async_queue_t aq;
dlink_node *walk_current;
};
/*
- * $Id: store_dir_coss.cc,v 1.25 2001/08/10 03:20:37 adrian Exp $
+ * $Id: store_dir_coss.cc,v 1.26 2001/08/12 10:20:41 adrian Exp $
*
* DEBUG: section 81 Store COSS Directory Routines
* AUTHOR: Eric Stern
*/
#include "squid.h"
+#include <aio.h>
+#include "async_io.h"
#include "store_coss.h"
#define STORE_META_BUFSZ 4096
storeCossDirInit(SwapDir * sd)
{
CossInfo *cs = (CossInfo *) sd->fsdata;
+ a_file_setupqueue(&cs->aq);
storeCossDirOpenSwapLog(sd);
storeCossDirRebuild(sd);
cs->fd = file_open(sd->path, O_RDWR | O_CREAT);
{
CossInfo *cs = (CossInfo *) SD->fsdata;
- storeCossSync(SD);
-
+ storeCossSync(SD); /* This'll call a_file_syncqueue() */
+ a_file_closequeue(&cs->aq);
file_close(cs->fd);
cs->fd = -1;
/*
- * $Id: store_io_coss.cc,v 1.10 2001/08/09 21:41:53 adrian Exp $
+ * $Id: store_io_coss.cc,v 1.11 2001/08/12 10:20:41 adrian Exp $
*
* DEBUG: section 81 Storage Manager COSS Interface
* AUTHOR: Eric Stern
*/
#include "squid.h"
+#include <aio.h>
+#include "async_io.h"
#include "store_coss.h"
static DWCB storeCossWriteMemBufDone;
if (cstate->readbuffer == NULL) {
p = storeCossMemPointerFromDiskOffset(SD, sio->swap_filen, NULL);
/* Remember we need to translate the block offset to a disk offset! */
- file_read(cs->fd,
+ a_file_read(&cs->aq, cs->fd,
p,
sio->st_size,
cstate->reqdiskoffset,
CossMemBuf *t;
dlink_node *m;
int end;
+
+ /* First, flush pending IO ops */
+ a_file_syncqueue(&cs->aq);
+
+ /* Then, flush any in-memory partial membufs */
if (!cs->membufs.head)
return;
for (m = cs->membufs.head; m; m = m->next) {
t->diskstart, t->diskend - t->diskstart);
t->flags.writing = 1;
/* Remember that diskstart/diskend are block offsets! */
- file_write(cs->fd, t->diskstart, &t->buffer,
+ a_file_write(&cs->aq, cs->fd, t->diskstart, &t->buffer,
t->diskend - t->diskstart, storeCossWriteMemBufDone, t, NULL);
}