From: Dan Sheppard Date: Wed, 23 Apr 2025 18:18:24 +0000 (+0100) Subject: Load page. X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~dans/git?a=commitdiff_plain;h=f2b34e9f0b4e7d716eca16fb92eb98159e9defdb;p=coquet.git Load page. --- diff --git a/Makefile b/Makefile index 737216c..6a85b95 100644 --- a/Makefile +++ b/Makefile @@ -57,6 +57,7 @@ clean: -rm -f $(OBJDIR)/* -rm -f $(TESTOBJDIR)/* -rm -f $(BINDIR)/* + -rm -f tmp/* -include $(MAINDEPS) -include $(TESTDEPS) diff --git a/src/coquet.c b/src/coquet.c index 6e91682..47b382f 100644 --- a/src/coquet.c +++ b/src/coquet.c @@ -166,11 +166,9 @@ static int find_last_main_block(coquet_t *cq, struct cq_filemeta *fm) { return COQUET_RET_OK; } -static int filemeta_setup_write(coquet_t *cq, struct cq_filemeta *fm) { +static int filemeta_setup_common(coquet_t *cq, struct cq_filemeta *fm) { int r; - fm->flags = 0; - /* load superblock */ r = cq_super_load(cq,fm->which_file,&(fm->super),1); // TODO "create mode" if(r != COQUET_RET_OK) { @@ -183,15 +181,48 @@ static int filemeta_setup_write(coquet_t *cq, struct cq_filemeta *fm) { return r; } + return COQUET_RET_OK; +} + +static int filemeta_setup_write(coquet_t *cq, struct cq_filemeta *fm) { + int r; + + fm->flags = 0; + + r = filemeta_setup_common(cq,fm); + if(r != COQUET_RET_OK) { + return r; + } + fm->flags |= COQUET_FM_FLAG_WRITE; return COQUET_RET_OK; } +static int filemeta_setup_read(coquet_t *cq, struct cq_filemeta *fm) { + int r; + + fm->flags = 0; + + r = filemeta_setup_common(cq,fm); + if(r != COQUET_RET_OK) { + return r; + } + + fm->flags |= COQUET_FM_FLAG_READ; + return COQUET_RET_OK; +} + bool cq_writing(coquet_t *cq, int which_file) { return ((cq->flags & COQUET_CQ_FILE_VALID(which_file)) && (cq->filemeta[which_file].flags & COQUET_FM_FLAG_WRITE)); } +bool cq_reading(coquet_t *cq, int which_file) { + return ((cq->flags & COQUET_CQ_FILE_VALID(which_file)) && + (cq->filemeta[which_file].flags & + (COQUET_FM_FLAG_WRITE|COQUET_FM_FLAG_READ))); +} + int coquet_write_start(coquet_t *cq, int which_file, bool wait) { int r; @@ -237,3 +268,31 @@ int coquet_write_end(coquet_t *cq, int which_file) { return COQUET_RET_OK; } + +int coquet_read_start(coquet_t *cq, int which_file, bool wait) { + int r; + + if(cq_reading(cq,which_file)) { + return COQUET_RET_TRSMERROR; + } + + /* setup */ + r = filemeta_setup_read(cq,&(cq->filemeta[which_file])); + if(r != COQUET_RET_OK) { + return r; + } + cq->flags |= COQUET_CQ_FILE_VALID(which_file); + + return COQUET_RET_OK; +} + +int coquet_read_end(coquet_t *cq, int which_file) { + if(!cq_reading(cq,which_file) || cq_writing(cq,which_file)) { + return COQUET_RET_TRSMERROR; + } + + /* mark stale */ + cq->flags &=~ COQUET_CQ_FILE_VALID(which_file); + + return COQUET_RET_OK; +} diff --git a/src/coquet.h b/src/coquet.h index 38b59ae..9bb7f82 100644 --- a/src/coquet.h +++ b/src/coquet.h @@ -12,6 +12,7 @@ #define COQUET_CQ_FILE_VALID(file) (COQUET_CQ_FLAG_MAINVALID<<(file)) #define COQUET_FM_FLAG_WRITE 0x01 +#define COQUET_FM_FLAG_READ 0x02 struct cq_filemeta { int which_file; @@ -43,14 +44,19 @@ int coquet_finish(coquet_t *cq); */ char * coquet_error_string(coquet_t *cq, int error); -/* Prepare for a write transaction: locking, and general setup. +/* Prepare/finish write transaction: locking, and general setup. */ int coquet_write_start(coquet_t *cq, int which_file, bool wait); - -/* Write has fnished, tear down. */ int coquet_write_end(coquet_t *cq, int which_file); -/* test if we're open for writing */ +/* Prepare/finish read transaction: locking, and general setup. + */ +int coquet_read_start(coquet_t *cq, int which_file, bool wait); +int coquet_read_end(coquet_t *cq, int which_file); + + +/* test if we can read/write */ +bool cq_reading(coquet_t *cq, int which_file); bool cq_writing(coquet_t *cq, int which_file); #endif diff --git a/src/page.c b/src/page.c index fcfb46f..33f4fde 100644 --- a/src/page.c +++ b/src/page.c @@ -1,3 +1,4 @@ +#include #include "page.h" off_t cq_offset_main_page(coquet_t *cq, int which_file, u_int64_t pgid) { @@ -12,13 +13,39 @@ off_t cq_offset_main_page(coquet_t *cq, int which_file, u_int64_t pgid) { return header + (pgid-1) * (1<super.current.block_size); } -int cq_load_page(coquet_t *cq, int which_file, uint64_t pgid, uint64_t **buffer, int *len) { +int cq_load_page(coquet_t *cq, int which_file, uint64_t pgid, uint8_t **buffer, uint64_t *len) { + int r; + off_t offset; + struct cq_filemeta *fm; + /* TODO nursery */ + fm = &(cq->filemeta[which_file]); + + /* check we're open for reading */ + if(!cq_reading(cq,which_file)) { + return COQUET_RET_TRSMERROR; + } + + /* create buffer */ + *len = 1<super.current.block_size; + *buffer = malloc(*len); + if(*buffer == NULL) { + return COQUET_RET_HEAPERR; + } + + /* read from main (always, for now) */ + offset = cq_offset_main_page(cq,which_file,pgid); + + /* read */ + r = (cq->vfs_funcs.read)(cq->vfs_data,which_file,*buffer,offset,*len); + if(r != COQUET_RET_OK) + return r; + return COQUET_RET_OK; } -int cq_save_page(coquet_t *cq, int which_file, uint64_t *pgid, uint8_t *buffer, int len) { +int cq_save_page(coquet_t *cq, int which_file, uint64_t *pgid, uint8_t *buffer, uint64_t len) { int r; off_t offset; struct cq_filemeta *fm; @@ -60,10 +87,11 @@ int cq_save_page(coquet_t *cq, int which_file, uint64_t *pgid, uint8_t *buffer, void test_page() { uint64_t pgid,pgid2; - uint8_t buffer[4096],buffer2[4096]; + uint8_t buffer[4096],buffer2[4096],*buffer3; coquet_t cq; struct cq_super super; int r; + uint64_t len; /* write two pages, one of all 0xC3, and one of all 0x3C */ /* TODO, when we have proper end detection, this needs to become a @@ -125,6 +153,8 @@ void test_page() { * 0x00802000 - 0x00802FFF pgid = 1 value = 0xC3 * 0x00803000 - 0x00803FFF pgid = 2 value = 0x3C */ + + /* check directly */ r = (cq.vfs_funcs.read)(cq.vfs_data,COQUET_FILE_MAIN,buffer2,0x00802000,4096); test_bail(&cq,r); memset(buffer,0xC3,4096); @@ -135,6 +165,28 @@ void test_page() { memset(buffer,0x3C,4096); test_assert(!memcmp(buffer,buffer2,4096),"pgid2 data"); + /* check with "proper" reads */ + + r = coquet_read_start(&cq,COQUET_FILE_MAIN,1); + test_bail(&cq,r); + + r = cq_load_page(&cq,COQUET_FILE_MAIN,1,&buffer3,&len); + test_bail(&cq,r); + memset(buffer,0xC3,4096); + test_eq_int(len,4096,"len"); + test_assert(!memcmp(buffer,buffer3,4096),"pgid1 data (b)"); + free(buffer3); + + r = cq_load_page(&cq,COQUET_FILE_MAIN,2,&buffer3,&len); + test_bail(&cq,r); + memset(buffer,0x3C,4096); + test_eq_int(len,4096,"len"); + test_assert(!memcmp(buffer,buffer3,4096),"pgid2 data (b)"); + free(buffer3); + + r = coquet_read_end(&cq,COQUET_FILE_MAIN); + test_bail(&cq,r); + r = coquet_finish(&cq); test_bail(&cq,r); } diff --git a/src/page.h b/src/page.h index 6b2bcf3..a3a0348 100644 --- a/src/page.h +++ b/src/page.h @@ -10,8 +10,8 @@ off_t cq_offset_main_page(coquet_t *cq, int which_file, u_int64_t pgid); /* Load/Save page with given pgid. Translation to nursery addresses (if * needed) occurs immediately INSIDE these functions. */ -int cq_load_page(coquet_t *cq, int which_file, uint64_t pgid, uint64_t **buffer, int *len); -int cq_save_page(coquet_t *cq, int which_file, uint64_t *pgid, uint8_t *buffer, int len); +int cq_load_page(coquet_t *cq, int which_file, uint64_t pgid, uint8_t **buffer, uint64_t *len); +int cq_save_page(coquet_t *cq, int which_file, uint64_t *pgid, uint8_t *buffer, uint64_t len); #ifdef COQUET_TEST void test_page(); diff --git a/src/unix.c b/src/unix.c index 33bada0..e7497ff 100644 --- a/src/unix.c +++ b/src/unix.c @@ -387,7 +387,7 @@ static int unix_delete(void *vfs_data, int which_file) { r = unlink(path); free(path); - if(r == -1) { + if(r == -1 && errno!=ENOENT) { set_error(pd,"delete failed",1); return COQUET_RET_VFSERR; }