2007-03-13 08:40:31 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
2007-06-11 21:36:57 +00:00
|
|
|
#include <stasis/io/handle.h>
|
|
|
|
#include <stasis/pageHandle.h>
|
|
|
|
#include <stasis/bufferPool.h>
|
|
|
|
#include <stasis/logger/logger2.h>
|
|
|
|
#include <stasis/truncation.h>
|
2008-03-02 23:21:39 +00:00
|
|
|
|
2008-04-13 04:02:57 +00:00
|
|
|
#include <stasis/page.h>
|
2008-03-02 23:21:39 +00:00
|
|
|
|
2007-11-11 23:22:21 +00:00
|
|
|
void (*pageWrite)(Page * dat);
|
2007-03-13 08:40:31 +00:00
|
|
|
void (*pageRead)(Page * ret);
|
|
|
|
void (*forcePageFile)();
|
2007-11-11 23:22:21 +00:00
|
|
|
void (*forceRangePageFile)();
|
2007-03-13 08:40:31 +00:00
|
|
|
void (*closePageFile)();
|
|
|
|
|
|
|
|
int printedForceWarning = 0;
|
|
|
|
|
|
|
|
static stasis_handle_t * h;
|
2007-07-18 20:09:14 +00:00
|
|
|
/**
|
2007-03-13 08:40:31 +00:00
|
|
|
@todo Make sure this doesn't need to be atomic. (It isn't!) Can
|
|
|
|
we get in trouble by setting the page clean after it's written
|
2007-07-18 20:09:14 +00:00
|
|
|
out, or forcing the log too early?
|
2007-03-13 08:40:31 +00:00
|
|
|
*/
|
2007-07-18 20:09:14 +00:00
|
|
|
static void phWrite(Page * ret) {
|
2007-03-13 08:40:31 +00:00
|
|
|
if(!ret->dirty) { return; }
|
2007-07-18 20:09:14 +00:00
|
|
|
// This lock is only held to make the page implementation happy. We should
|
|
|
|
// implicitly have exclusive access to the page before this function is called,
|
|
|
|
// or we'll deadlock.
|
|
|
|
writelock(ret->rwlatch,0);
|
2007-10-02 00:18:33 +00:00
|
|
|
stasis_page_flushed(ret);
|
2008-12-01 19:48:59 +00:00
|
|
|
LogForce(stasis_log_file, ret->LSN);
|
2007-03-13 08:40:31 +00:00
|
|
|
int err = h->write(h, PAGE_SIZE * ret->id, ret->memAddr, PAGE_SIZE);
|
|
|
|
if(err) {
|
|
|
|
printf("Couldn't write to page file: %s\n", strerror(err));
|
|
|
|
fflush(stdout);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
dirtyPages_remove(ret);
|
2007-07-18 20:09:14 +00:00
|
|
|
unlock(ret->rwlatch);
|
2007-03-13 08:40:31 +00:00
|
|
|
}
|
2007-07-18 20:09:14 +00:00
|
|
|
static void phRead(Page * ret) {
|
|
|
|
writelock(ret->rwlatch,0);
|
2007-03-13 08:40:31 +00:00
|
|
|
int err = h->read(h, PAGE_SIZE * ret->id, ret->memAddr, PAGE_SIZE);
|
|
|
|
if(err) {
|
2007-07-18 20:09:14 +00:00
|
|
|
if(err == EDOM) {
|
2007-03-13 08:40:31 +00:00
|
|
|
// tried to read off end of file...
|
|
|
|
memset(ret->memAddr, 0, PAGE_SIZE);
|
2007-07-18 20:09:14 +00:00
|
|
|
} else {
|
2007-03-13 08:40:31 +00:00
|
|
|
printf("Couldn't read from page file: %s\n", strerror(err));
|
|
|
|
fflush(stdout);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret->dirty = 0;
|
2007-10-02 00:18:33 +00:00
|
|
|
stasis_page_loaded(ret);
|
2007-07-18 20:09:14 +00:00
|
|
|
unlock(ret->rwlatch);
|
2007-03-13 08:40:31 +00:00
|
|
|
}
|
|
|
|
static void phForce() {
|
2007-10-23 01:51:03 +00:00
|
|
|
int err = h->force(h);
|
|
|
|
assert(!err);
|
2007-03-13 08:40:31 +00:00
|
|
|
}
|
2007-11-11 23:22:21 +00:00
|
|
|
static void phForceRange(lsn_t start, lsn_t stop) {
|
|
|
|
int err = h->force_range(h,start,stop);
|
|
|
|
assert(!err);
|
|
|
|
}
|
2007-03-13 08:40:31 +00:00
|
|
|
static void phClose() {
|
|
|
|
int err = h->close(h);
|
2007-06-01 21:06:18 +00:00
|
|
|
DEBUG("Closing pageHandle\n");
|
2007-03-13 08:40:31 +00:00
|
|
|
if(err) {
|
|
|
|
printf("Couldn't close page file: %s\n", strerror(err));
|
|
|
|
fflush(stdout);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void pageHandleOpen(stasis_handle_t * handle) {
|
2007-06-01 21:06:18 +00:00
|
|
|
DEBUG("Using pageHandle implementation\n");
|
2007-03-13 08:40:31 +00:00
|
|
|
pageWrite = phWrite;
|
|
|
|
pageRead = phRead;
|
|
|
|
forcePageFile = phForce;
|
2007-11-11 23:22:21 +00:00
|
|
|
forceRangePageFile = phForceRange;
|
2007-03-13 08:40:31 +00:00
|
|
|
closePageFile = phClose;
|
|
|
|
h = handle;
|
|
|
|
}
|