-rm -f $(OBJDIR)/*
-rm -f $(TESTOBJDIR)/*
-rm -f $(BINDIR)/*
+ -rm -f tmp/*
-include $(MAINDEPS)
-include $(TESTDEPS)
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) {
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;
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;
+}
#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;
*/
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
+#include <stdlib.h>
#include "page.h"
off_t cq_offset_main_page(coquet_t *cq, int which_file, u_int64_t pgid) {
return header + (pgid-1) * (1<<fm->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<<fm->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;
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
* 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);
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);
}
/* 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();
r = unlink(path);
free(path);
- if(r == -1) {
+ if(r == -1 && errno!=ENOENT) {
set_error(pd,"delete failed",1);
return COQUET_RET_VFSERR;
}