diff options
author | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2010-04-02 18:28:35 +0200 |
---|---|---|
committer | Jiri Olsa <Jiri Olsa jolsa@redhat.com> | 2010-04-02 18:28:35 +0200 |
commit | acc5795db9fd1af91690d80ec483c745ad558f28 (patch) | |
tree | ff385c7dcfd1c7287fe56bedb8cc94c0c96c779c /src | |
parent | a9b34fd9216367d6f959f979d318b52e00d58118 (diff) | |
download | tsnif-acc5795db9fd1af91690d80ec483c745ad558f28.tar.gz tsnif-acc5795db9fd1af91690d80ec483c745ad558f28.tar.xz tsnif-acc5795db9fd1af91690d80ec483c745ad558f28.zip |
added read support for storage_mmap
Diffstat (limited to 'src')
-rw-r--r-- | src/intf.h | 4 | ||||
-rw-r--r-- | src/storage-mmap.c | 236 | ||||
-rw-r--r-- | src/storage-mmap.h | 12 | ||||
-rw-r--r-- | src/storage.h | 14 | ||||
-rw-r--r-- | src/test-storage-mmap.c | 315 | ||||
-rw-r--r-- | src/test.c | 67 | ||||
-rw-r--r-- | src/test.h | 3 | ||||
-rw-r--r-- | src/tsnif.c | 2 |
8 files changed, 605 insertions, 48 deletions
@@ -74,11 +74,11 @@ extern int tsnif_debug; do { \ if (tsnif_debug) { \ char lpbuf[256]; \ - snprintf(lpbuf, sizeof(lpbuf)-1, "USER [%3d:%s@%s:%05d] %s", \ + snprintf(lpbuf, sizeof(lpbuf)-1, "USER [%3d:%s:%05d %s] %s", \ (pid_t) syscall(SYS_gettid), \ - __FUNCTION__, \ __FILE__, \ __LINE__, \ + __FUNCTION__, \ fmt); \ printf(lpbuf, ## args); \ } \ 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); } diff --git a/src/storage-mmap.h b/src/storage-mmap.h index c05bbd0..db45cb0 100644 --- a/src/storage-mmap.h +++ b/src/storage-mmap.h @@ -4,8 +4,12 @@ struct tsnif_storage_header_mmap { struct tsnif_storage_header common; + /* max size of the file */ uint32_t size_max; + /* number of records stored */ uint32_t cnt; + /* offset of the first chunk */ + uint32_t offset_start; }; struct tsnif_storage_rec_mmap { @@ -31,10 +35,14 @@ struct tsnif_storage_chunk { off_t offset; void *current_data; uint32_t *current_index; + + /* for read interface only */ + int read_index; }; struct tsnif_storage_handle { int fd; + struct tsnif_storage_opts *opts; /* file header */ @@ -42,6 +50,10 @@ struct tsnif_storage_handle { /* active chunk */ struct tsnif_storage_chunk active_chunk; + + /* for READ mode only */ + off_t file_size; + }; #endif /* STORAGE_MMAP_H */ diff --git a/src/storage.h b/src/storage.h index 00826d8..54df8fa 100644 --- a/src/storage.h +++ b/src/storage.h @@ -19,10 +19,14 @@ struct tsnif_storage_header { }; enum { - TSNIF_STORAGE_OPT_CREATE = 0x1, - TSNIF_STORAGE_OPT_OPEN = 0x2, - TSNIF_STORAGE_OPT_READ = 0x4, - TSNIF_STORAGE_OPT_WRITE = 0x8, + TSNIF_STORAGE_OPT_READ = 0x1, + TSNIF_STORAGE_OPT_WRITE = 0x2, +}; + +enum { + TSNIF_STORAGE_READ_NEXT = 0x1, + TSNIF_STORAGE_READ_PREV = 0x2, + TSNIF_STORAGE_READ_EOF = 0x3, }; struct tsnif_storage_rec { @@ -36,7 +40,7 @@ int tsnif_storage_init(struct tsnif_storage_handle *h, int tsnif_storage_close(struct tsnif_storage_handle *h); int tsnif_storage_write(struct tsnif_storage_handle *h, struct tsnif_storage_rec *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); /* TODO make CONFIG option and ifdef this place */ diff --git a/src/test-storage-mmap.c b/src/test-storage-mmap.c index 64c9044..44f3571 100644 --- a/src/test-storage-mmap.c +++ b/src/test-storage-mmap.c @@ -1,40 +1,345 @@ +#include <unistd.h> #include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> + #include "test.h" #include "storage.h" -#define FILENAME "/tmp/tsnif-storage-mmap.tsnif" -int tsnif_debug = 0; +#define FILENAME "/tmp/tsnif-storage-mmap.tsnif" int test_storage_mmap_init(void) { int rc = 0; + struct stat st; struct tsnif_storage_handle handle; + struct tsnif_storage_header_mmap *header; struct tsnif_storage_opts opts = { - .flags = TSNIF_STORAGE_OPT_CREATE | TSNIF_STORAGE_OPT_WRITE, + .flags = TSNIF_STORAGE_OPT_WRITE | TSNIF_STORAGE_OPT_WRITE, .size_max = 1024*1024, }; TEST_ASSERT(0 == tsnif_storage_init(&handle, &opts, FILENAME), out); + + TEST_ASSERT(handle.opts == &opts, out_free); + TEST_ASSERT(handle.opts->chunk_size == sysconf(_SC_PAGESIZE), out_free); + TEST_ASSERT(handle.fd != 0, out_free); + TEST_ASSERT(handle.header != NULL, out_free); + + header = handle.header; + TEST_ASSERT(header->common.magic == TSNIF_HEADER_MAGIC, out_free); + TEST_ASSERT(header->common.type == TSNIF_STORAGE_TYPE_MMAP, out_free); + TEST_ASSERT(header->size_max == opts.size_max, out_free); + +out_free: TEST_ASSERT(0 == tsnif_storage_close(&handle), out); + TEST_ASSERT(0 == stat(FILENAME, &st), out); + TEST_ASSERT(st.st_size == sysconf(_SC_PAGESIZE), out); out: + unlink(FILENAME); return rc; } -int test_storage_mmap_write(void) +int test_storage_mmap_open(void) { int rc = 0; struct tsnif_storage_handle handle; struct tsnif_storage_opts opts = { - .flags = TSNIF_STORAGE_OPT_CREATE | TSNIF_STORAGE_OPT_WRITE, + .flags = TSNIF_STORAGE_OPT_WRITE | TSNIF_STORAGE_OPT_WRITE, + .size_max = 1024*1024, + }; + + TEST_ASSERT(0 == tsnif_storage_init(&handle, &opts, FILENAME), out); + TEST_ASSERT(0 == tsnif_storage_close(&handle), out); + + opts.flags = TSNIF_STORAGE_OPT_READ; + TEST_ASSERT(0 == tsnif_storage_init(&handle, &opts, FILENAME), out); + TEST_ASSERT(0 == tsnif_storage_close(&handle), out); + +out: + unlink(FILENAME); + return rc; +} + +static int get_rec(struct tsnif_storage_rec *rec, char *msg, int i) +{ + sprintf(msg, "krava-%i-", i); + memset(rec, 0x0, sizeof(rec)); + rec->ptr = msg; + rec->len = strlen(msg); + return 0; +} + +int test_storage_mmap_write_single_chunk(void) +{ + int rc = 0, i; + struct tsnif_storage_handle handle; + struct tsnif_storage_opts opts = { + .flags = TSNIF_STORAGE_OPT_WRITE | TSNIF_STORAGE_OPT_WRITE, + .size_max = 1024*1024, + }; + + TEST_ASSERT(0 == tsnif_storage_init(&handle, &opts, FILENAME), out); + + for(i = 0; i < 10; i++) { + struct tsnif_storage_chunk *chunk = &handle.active_chunk; + struct tsnif_storage_chunk_header *header; + struct tsnif_storage_rec_mmap *rec_mmap; + uint32_t *index; + off_t offset; + struct tsnif_storage_rec rec; + char msg[15]; + int free; + + get_rec(&rec, msg, i); + + TEST_ASSERT(0 == tsnif_storage_write(&handle, &rec), out_free); + TEST_ASSERT(chunk->header, out_free); + + /* check chunk properties */ + header = chunk->header; + free = opts.chunk_size - + /* chunk header */ + sizeof(struct tsnif_storage_chunk_header) - + (i + 1) * + ( + /* record header */ + sizeof(struct tsnif_storage_rec_mmap) + + /* record data lenght */ + rec.len + + /* index item */ + sizeof(uint32_t) + ); + + TEST_ASSERT(header->cnt == i + 1, out_free); + TEST_ASSERT(header->free == free, out_free); + + /* find current record and check it */ + index = chunk->current_index; + offset = *(++index); + rec_mmap = (void*) chunk->header + offset; + + TEST_ASSERT(rec_mmap->len == rec.len, out_free); + TEST_ASSERT(!memcmp(rec_mmap->data, rec.ptr, rec.len), out_free); + } + + TEST_ASSERT(handle.header->offset_start == sysconf(_SC_PAGESIZE), out_free); + TEST_ASSERT(handle.header->cnt == 10, out_free); + +out_free: + TEST_ASSERT(0 == tsnif_storage_close(&handle), out); + +out: + unlink(FILENAME); + return rc; +} + +int test_storage_mmap_write_multi_chunks(void) +{ + int rc = 0, i = 0; + struct tsnif_storage_handle handle; + struct tsnif_storage_chunk *chunk = &handle.active_chunk; + struct tsnif_storage_chunk_header *header; + struct tsnif_storage_opts opts = { + .flags = TSNIF_STORAGE_OPT_WRITE | TSNIF_STORAGE_OPT_WRITE, + .size_max = 1024*1024, + }; + struct tsnif_storage_rec rec; + char msg[15]; + + TEST_ASSERT(0 == tsnif_storage_init(&handle, &opts, FILENAME), out); + + get_rec(&rec, msg, i++); + + if (tsnif_storage_write(&handle, &rec)) + TEST_ASSERT(1, out_free); + + header = chunk->header; + TEST_ASSERT(header, out_free); + + do { + off_t offset_old, offset_new; + + int free_threshold = ( + /* record header */ + sizeof(struct tsnif_storage_rec_mmap) + + /* record data */ + rec.len + + /* safety overhead */ + + (4*sizeof(uint32_t))); + + get_rec(&rec, msg, i++); + + /* get to the chunk end */ + if (header->free > free_threshold) { + if (tsnif_storage_write(&handle, &rec)) + TEST_ASSERT(1, out_free); + continue; + } + + offset_old = chunk->offset; + + TEST_ASSERT(0 == tsnif_storage_write(&handle, &rec), out_free); + + offset_new = chunk->offset; + TEST_ASSERT(offset_new == (offset_old + opts.chunk_size), out_free); + break; + + } while(1); + +out_free: + TEST_ASSERT(0 == tsnif_storage_close(&handle), out); + +out: + unlink(FILENAME); + return rc; +} + +int test_storage_mmap_read_single_chunk(void) +{ + int rc = 0, i = 0; + struct tsnif_storage_handle handle; + struct tsnif_storage_opts opts = { + .flags = TSNIF_STORAGE_OPT_WRITE | TSNIF_STORAGE_OPT_WRITE, + .size_max = 1024*1024, + }; + struct tsnif_storage_rec rec; + char msg[15]; + + if (tsnif_storage_init(&handle, &opts, FILENAME)) + TEST_ASSERT(1, out); + + for(i = 0; i < 10; i++) { + get_rec(&rec, msg, i); + if (tsnif_storage_write(&handle, &rec)) + TEST_ASSERT(1, out_free); + } + + if (tsnif_storage_close(&handle)) + TEST_ASSERT(1, out); + + /* READ mode */ + opts.flags = TSNIF_STORAGE_OPT_READ | TSNIF_STORAGE_OPT_READ; + opts.size_max = 0; + + TEST_ASSERT(0 == tsnif_storage_init(&handle, &opts, FILENAME), out); + + for(i = 0; i < 10; i++) { + struct tsnif_storage_rec rec_read; + + get_rec(&rec, msg, i); + + TEST_ASSERT(0 == tsnif_storage_read(&handle, TSNIF_STORAGE_READ_NEXT, &rec_read), out_free); + + TEST_ASSERT(rec.len == rec_read.len, out_free); + TEST_ASSERT(rec.flags == rec_read.flags, out_free); + TEST_ASSERT(!memcmp(rec_read.ptr, rec.ptr, rec.len), out_free); + } + + /* there should be no other record */ + TEST_ASSERT(TSNIF_STORAGE_READ_EOF == tsnif_storage_read(&handle, TSNIF_STORAGE_READ_NEXT, &rec), out_free); + + for(i = 8; i >= 0; i--) { + struct tsnif_storage_rec rec_read; + + get_rec(&rec, msg, i); + + TEST_ASSERT(0 == tsnif_storage_read(&handle, TSNIF_STORAGE_READ_PREV, &rec_read), out_free); + +#if 0 +printf("krava:\n"); +fwrite(rec_read.ptr, rec_read.len, 1, stdout); +fflush(NULL); +#endif + TEST_ASSERT(rec.len == rec_read.len, out_free); + TEST_ASSERT(rec.flags == rec_read.flags, out_free); + TEST_ASSERT(!memcmp(rec_read.ptr, rec.ptr, rec.len), out_free); + } + + /* there should be no other record */ + TEST_ASSERT(TSNIF_STORAGE_READ_EOF == tsnif_storage_read(&handle, TSNIF_STORAGE_READ_PREV, &rec), out_free); + +out_free: + TEST_ASSERT(0 == tsnif_storage_close(&handle), out); + +out: + unlink(FILENAME); + return rc; +} + +int test_storage_mmap_read_multi_chunks(void) +{ + int rc = 0, i = 0; + struct tsnif_storage_handle handle; + struct tsnif_storage_chunk *chunk = &handle.active_chunk; + struct tsnif_storage_opts opts = { + .flags = TSNIF_STORAGE_OPT_WRITE | TSNIF_STORAGE_OPT_WRITE, .size_max = 1024*1024, }; + struct tsnif_storage_rec rec; + char msg[15]; + int offset = 0; + + if (tsnif_storage_init(&handle, &opts, FILENAME)) + TEST_ASSERT(1, out_free); + + /* write whole chunk of data + one record in 2nd chunk */ + do { + get_rec(&rec, msg, i++); + + if (tsnif_storage_write(&handle, &rec)) + TEST_ASSERT(1, out_free); + + if (!offset) + offset = chunk->offset; + + } while(chunk->offset == offset); + + get_rec(&rec, msg, i++); + if (tsnif_storage_write(&handle, &rec)) + TEST_ASSERT(1, out_free); + + if (tsnif_storage_close(&handle)) + TEST_ASSERT(1, out); + + opts.flags = TSNIF_STORAGE_OPT_READ | TSNIF_STORAGE_OPT_READ; + opts.size_max = 0; TEST_ASSERT(0 == tsnif_storage_init(&handle, &opts, FILENAME), out); + + for(i = 0; i < handle.header->cnt; i++) { + struct tsnif_storage_rec rec_read; + + get_rec(&rec, msg, i); + TEST_ASSERT(0 == tsnif_storage_read(&handle, TSNIF_STORAGE_READ_NEXT, &rec_read), out_free); + + TEST_ASSERT(rec.len == rec_read.len, out_free); + TEST_ASSERT(rec.flags == rec_read.flags, out_free); + TEST_ASSERT(!memcmp(rec_read.ptr, rec.ptr, rec.len), out_free); + } + + TEST_ASSERT(TSNIF_STORAGE_READ_EOF == tsnif_storage_read(&handle, TSNIF_STORAGE_READ_NEXT, &rec), out_free); + + for(i = handle.header->cnt - 2; i >= 0; i--) { + struct tsnif_storage_rec rec_read; + + get_rec(&rec, msg, i); + TEST_ASSERT(0 == tsnif_storage_read(&handle, TSNIF_STORAGE_READ_PREV, &rec_read), out_free); + + TEST_ASSERT(rec.len == rec_read.len, out_free); + TEST_ASSERT(rec.flags == rec_read.flags, out_free); + TEST_ASSERT(!memcmp(rec_read.ptr, rec.ptr, rec.len), out_free); + } + +out_free: TEST_ASSERT(0 == tsnif_storage_close(&handle), out); out: + unlink(FILENAME); return rc; } @@ -1,30 +1,79 @@ #include <stdio.h> +#include <unistd.h> +#include <getopt.h> #define TEST_RUN(test) \ do { \ printf("RUNNING " # test "\n"); \ if ((test())) { \ - overall_ok = 0; \ printf("FAILED test " # test "\n"); \ + goto out; \ } \ printf("\n"); \ } while(0) +int tsnif_debug = 0; + +static void usage() +{ + printf("tsnif-test [-d]\n"); + _exit(-1); +} + +static int get_args(int argc, char **argv) +{ + while (1) { + int c; + int option_index = 0; + static struct option long_options[] = { + {"debug", no_argument, 0, 'd'}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, "d", + long_options, &option_index); + + if (c == -1) + break; + + switch (c) { + case 'd': + tsnif_debug = 1; + break; + + default: + printf("unknown option '%c'", c); + } /* switch(c) */ + } /* while(1) */ + + return 0; +} + +/* storage-mmap.o */ int test_storage_mmap_init(void); -int test_storage_mmap_write(void); +int test_storage_mmap_open(void); +int test_storage_mmap_write_single_chunk(void); +int test_storage_mmap_write_multi_chunks(void); +int test_storage_mmap_read_single_chunk(void); +int test_storage_mmap_read_multi_chunks(void); int main(int argc, char **argv) { - int overall_ok = 1; + if (get_args(argc, argv)) + usage(); TEST_RUN(test_storage_mmap_init); - TEST_RUN(test_storage_mmap_write); + TEST_RUN(test_storage_mmap_open); + TEST_RUN(test_storage_mmap_write_single_chunk); + TEST_RUN(test_storage_mmap_write_multi_chunks); + TEST_RUN(test_storage_mmap_read_single_chunk); + TEST_RUN(test_storage_mmap_read_multi_chunks); - if (overall_ok) - printf("PASSED\n"); - else - printf("FAILED\n"); + printf("PASSED\n"); + return 0; - return overall_ok ? 0 : -1; +out: + printf("FAILED\n"); + return -1; } @@ -3,10 +3,13 @@ #define TEST_H #include <stdio.h> +#include "intf.h" #define TEST_ASSERT(cond, out_label) \ do { \ printf(" ASSERT '" #cond "' ... "); \ + if (tsnif_debug) \ + printf("\n"); \ if (!(cond)) { \ rc = -1; \ printf("FAILED\n"); \ diff --git a/src/tsnif.c b/src/tsnif.c index 102d2d2..0ae6d5f 100644 --- a/src/tsnif.c +++ b/src/tsnif.c @@ -17,7 +17,7 @@ static struct tsnif_handle handle; static struct tsnif_term term; static struct tsnif_storage_opts storage_opts = { - .flags = TSNIF_STORAGE_OPT_CREATE | TSNIF_STORAGE_OPT_WRITE, + .flags = TSNIF_STORAGE_OPT_WRITE | TSNIF_STORAGE_OPT_WRITE, .size_max = 1024*1024, }; static struct tsnif_storage_handle storage_handle; |