diff options
Diffstat (limited to 'src/storage-mmap.c')
-rw-r--r-- | src/storage-mmap.c | 236 |
1 files changed, 210 insertions, 26 deletions
diff --git a/src/storage-mmap.c b/src/storage-mmap.c index 23fb720..f5e73ab 100644 --- a/src/storage-mmap.c +++ b/src/storage-mmap.c @@ -63,7 +63,7 @@ int tsnif_storage_init(struct tsnif_storage_handle *h, if (!opts->chunk_size) opts->chunk_size = sysconf(_SC_PAGESIZE); - create = (opts->flags & TSNIF_STORAGE_OPT_CREATE); + create = (opts->flags & TSNIF_STORAGE_OPT_WRITE); if (create) flags |= O_CREAT | O_TRUNC; @@ -92,13 +92,27 @@ int tsnif_storage_init(struct tsnif_storage_handle *h, return err; } + TSNIF_DEBUG("records count %d\n", h->header->cnt); + + if (opts->flags & TSNIF_STORAGE_OPT_READ) { + struct stat st; + + err = fstat(fd, &st); + if (err) + return err; + + h->file_size = st.st_size; + } + return 0; } int tsnif_storage_close(struct tsnif_storage_handle *h) { - if (h->header) + if (h->header) { + TSNIF_DEBUG("records count %d\n", h->header->cnt); munmap(h->header, sysconf(_SC_PAGESIZE)); + } unmap_chunk(h, &h->active_chunk); @@ -108,7 +122,7 @@ int tsnif_storage_close(struct tsnif_storage_handle *h) static int get_open_offset(struct tsnif_storage_handle *h) { - return 0; + return h->header->offset_start; } static int unmap_chunk(struct tsnif_storage_handle *h, @@ -123,19 +137,26 @@ static int unmap_chunk(struct tsnif_storage_handle *h, enum { STORAGE_MMAP_FIRST, STORAGE_MMAP_NEXT, + STORAGE_MMAP_PREV, }; static int file_trunc(struct tsnif_storage_handle *h, off_t new_size) { - off_t size; + off_t old_size; + + TSNIF_DEBUG("new size %d\n", new_size); - size = lseek(h->fd, 0, SEEK_END); - if (size < 0) + old_size = lseek(h->fd, 0, SEEK_END); + if (old_size < 0) return -1; - if (size >= new_size) + TSNIF_DEBUG("old size %d\n", old_size); + + if (old_size >= new_size) return 0; + TSNIF_DEBUG("truncating to %d\n", new_size); + return ftruncate(h->fd, new_size); } @@ -143,32 +164,74 @@ static int map_chunk(struct tsnif_storage_handle *h, struct tsnif_storage_chunk *chunk, int what) { void *ptr; - off_t offset; + off_t offset = 0; int err; - if (what == STORAGE_MMAP_FIRST) { - offset = sysconf(_SC_PAGESIZE); + TSNIF_DEBUG("what %d\n", what); - if (h->opts->flags & TSNIF_STORAGE_OPT_OPEN) + if (what == STORAGE_MMAP_FIRST) { + if (h->opts->flags & TSNIF_STORAGE_OPT_READ) offset = get_open_offset(h); + else { + offset = sysconf(_SC_PAGESIZE); + h->header->offset_start = offset; + } } if (what == STORAGE_MMAP_NEXT) { - offset = chunk->offset + - h->opts->chunk_size + - sysconf(_SC_PAGESIZE); + offset = chunk->offset + h->opts->chunk_size; - if (offset > h->opts->size_max) - offset = sysconf(_SC_PAGESIZE); + if (h->opts->flags & TSNIF_STORAGE_OPT_READ) { + + TSNIF_DEBUG("file size 0x%x\n", h->file_size); + TSNIF_DEBUG("offset 0x%x\n", offset); + + if (h->file_size == offset) + offset = sysconf(_SC_PAGESIZE); + + TSNIF_DEBUG("offset 0x%x\n", offset); + TSNIF_DEBUG("start offset 0x%x\n", h->header->offset_start); + + if (h->header->offset_start == offset) + return TSNIF_STORAGE_READ_EOF; + } else { + /* check the max size only in write mode */ + if (offset > h->opts->size_max) + offset = sysconf(_SC_PAGESIZE); + } + + TSNIF_DEBUG("chunk offset 0x%x\n", chunk->offset); + TSNIF_DEBUG("chunk size 0x%x\n", chunk->offset); + TSNIF_DEBUG("max size 0x%x\n", h->opts->size_max); } + if (what == STORAGE_MMAP_PREV) { + + if (h->header->offset_start == chunk->offset) + return TSNIF_STORAGE_READ_EOF; + + if (chunk->offset == sysconf(_SC_PAGESIZE)) + offset = h->file_size - h->opts->chunk_size; + else + offset = chunk->offset - h->opts->chunk_size; + + TSNIF_DEBUG("chunk offset 0x%x\n", chunk->offset); + TSNIF_DEBUG("chunk size 0x%x\n", chunk->offset); + TSNIF_DEBUG("max size 0x%x\n", h->opts->size_max); + } + + TSNIF_DEBUG("new offset 0x%x, old offset 0x%x\n", + offset, chunk->offset); + if (chunk->header) unmap_chunk(h, chunk); - err = file_trunc(h, offset); - if (err) - return err; + if (h->opts->flags & TSNIF_STORAGE_OPT_WRITE) { + err = file_trunc(h, offset + h->opts->chunk_size); + if (err) + return err; + } ptr = mmap(NULL, h->opts->chunk_size, PROT_WRITE | PROT_READ, @@ -176,7 +239,14 @@ static int map_chunk(struct tsnif_storage_handle *h, if (MAP_FAILED == ptr) return -1; + TSNIF_DEBUG("mmap-ed offset %ld, size %d\n", + offset, h->opts->chunk_size); + chunk->offset = offset; + chunk->header = ptr; + chunk->current_data = chunk->header->rec0; + chunk->current_index = (void*) (chunk->header) + h->opts->chunk_size + - sizeof(uint32_t); return 0; } @@ -190,8 +260,14 @@ static int clear_chunk(struct tsnif_storage_handle *h, sizeof(struct tsnif_storage_chunk_header); chunk->current_data = header->rec0; - chunk->current_index = (uint32_t*) (chunk->header + h->opts->chunk_size - - sizeof(uint32_t)); + chunk->current_index = (void*) (header) + h->opts->chunk_size + - sizeof(uint32_t); + + TSNIF_DEBUG("chunk header %p\n", chunk->header); + TSNIF_DEBUG("chunk data %p\n", chunk->current_data); + TSNIF_DEBUG("chunk index %p\n", chunk->current_index); + TSNIF_DEBUG("chunk size 0x%x\n", h->opts->chunk_size); + TSNIF_DEBUG("chunk free %d\n", header->free); return 0; } @@ -202,11 +278,27 @@ static int map_write_chunk(struct tsnif_storage_handle *h, clear_chunk(h, chunk)); } -static int get_chunk_rec(struct tsnif_storage_handle *h, int size) +static int map_read_chunk(struct tsnif_storage_handle *h, + struct tsnif_storage_chunk *chunk, int what) +{ + int err; + + err = map_chunk(h, chunk, what); + if ((err < 0 ) || + (err == TSNIF_STORAGE_READ_EOF)) + return err; + + chunk->read_index = -1; + return 0; +} + +static int get_chunk_write_rec(struct tsnif_storage_handle *h, int size) { struct tsnif_storage_chunk *chunk = &h->active_chunk; struct tsnif_storage_chunk_header *chunk_header = chunk->header; + TSNIF_DEBUG("chunk header %p\n", chunk_header); + /* first time */ if (!chunk_header) return map_write_chunk(h, chunk, STORAGE_MMAP_FIRST); @@ -223,6 +315,38 @@ static int get_chunk_rec(struct tsnif_storage_handle *h, int size) return map_write_chunk(h, chunk, STORAGE_MMAP_NEXT); } +static int get_chunk_read_rec(struct tsnif_storage_handle *h, int what) +{ + struct tsnif_storage_chunk *chunk = &h->active_chunk; + struct tsnif_storage_chunk_header *chunk_header = chunk->header; + int map_what = 0; + + TSNIF_DEBUG("chunk header %p\n", chunk_header); + + /* first time */ + if (!chunk_header) + return map_read_chunk(h, chunk, STORAGE_MMAP_FIRST); + + TSNIF_DEBUG("chunk cnt 0x%x\n", chunk_header->cnt); + TSNIF_DEBUG("read index 0x%x\n", chunk->read_index); + + /* we want next record and we have it */ + if (TSNIF_STORAGE_READ_NEXT == what) { + if ((chunk->read_index + 1) < chunk_header->cnt) + return 0; + map_what = STORAGE_MMAP_NEXT; + } + + /* we want previous record and we have it */ + if (TSNIF_STORAGE_READ_PREV == what) { + if (chunk->read_index) + return 0; + map_what = STORAGE_MMAP_PREV; + } + + return map_read_chunk(h, chunk, map_what); +} + static int store_rec(struct tsnif_storage_handle *h, struct tsnif_storage_rec *rec) { @@ -230,6 +354,9 @@ static int store_rec(struct tsnif_storage_handle *h, struct tsnif_storage_chunk *chunk = &h->active_chunk; struct tsnif_storage_chunk_header *header = chunk->header; + TSNIF_DEBUG("chunk data %p\n", chunk->current_data); + TSNIF_DEBUG("chunk index %p\n", chunk->current_index); + mrec = chunk->current_data; mrec->len = rec->len; mrec->flags = rec->flags; @@ -237,12 +364,59 @@ static int store_rec(struct tsnif_storage_handle *h, #define RECLEN (sizeof(struct tsnif_storage_rec_mmap) + rec->len) - *(chunk->current_index) = (void*) chunk->current_data - (void*) mrec; + *(chunk->current_index) = (void*) chunk->current_data - (void*) header; + TSNIF_DEBUG("rec offset 0x%x\n", *(chunk->current_index)); + TSNIF_DEBUG("rec size 0x%x\n", rec->len); + chunk->current_index--; chunk->current_data += RECLEN; + /* update file header */ + h->header->cnt++; + + /* update chunk header */ header->cnt++; header->free -= (sizeof(uint32_t) + RECLEN); + + TSNIF_DEBUG("chunk data %p\n", chunk->current_data); + TSNIF_DEBUG("chunk index %p\n", chunk->current_index); + TSNIF_DEBUG("chunk free %d\n", header->free); + TSNIF_DEBUG("chunk cnt %d\n", header->cnt); + return 0; +} + +static int read_rec(struct tsnif_storage_handle *h, + struct tsnif_storage_rec *rec, int what) +{ + struct tsnif_storage_rec_mmap *mrec; + struct tsnif_storage_chunk *chunk = &h->active_chunk; + struct tsnif_storage_chunk_header *header = chunk->header; + off_t offset; + + TSNIF_DEBUG("chunk data %p\n", chunk->current_data); + TSNIF_DEBUG("chunk index %p\n", chunk->current_index); + TSNIF_DEBUG("read index 0x%x\n", chunk->read_index); + + /* the chunk got loaded just now */ + if (chunk->read_index == -1) { + if (what == TSNIF_STORAGE_READ_NEXT) + chunk->read_index = 0; + else + chunk->read_index = chunk->header->cnt - 1; + /* move within the chunk */ + } else { + if (what == TSNIF_STORAGE_READ_NEXT) + chunk->read_index++; + else + chunk->read_index--; + } + + offset = *(chunk->current_index - chunk->read_index); + mrec = (void*) header + offset; + + rec->ptr = mrec->data; + rec->len = mrec->len; + rec->flags = mrec->flags; return 0; } @@ -251,15 +425,25 @@ int tsnif_storage_write(struct tsnif_storage_handle *h, { int err; - err = get_chunk_rec(h, rec->len); + TSNIF_DEBUG("entry\n"); + + err = get_chunk_write_rec(h, rec->len); if (err) return err; return store_rec(h, rec); } -int tsnif_storage_read(struct tsnif_storage_handle *h, int idx, +int tsnif_storage_read(struct tsnif_storage_handle *h, int what, struct tsnif_storage_rec *rec) { - return 0; + int err; + + TSNIF_DEBUG("entry\n"); + + err = get_chunk_read_rec(h, what); + if (err) + return err; + + return read_rec(h, rec, what); } |