summaryrefslogtreecommitdiffstats
path: root/src/storage-mmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/storage-mmap.c')
-rw-r--r--src/storage-mmap.c236
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);
}