summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Olsa <Jiri Olsa jolsa@redhat.com>2010-04-02 18:28:35 +0200
committerJiri Olsa <Jiri Olsa jolsa@redhat.com>2010-04-02 18:28:35 +0200
commitacc5795db9fd1af91690d80ec483c745ad558f28 (patch)
treeff385c7dcfd1c7287fe56bedb8cc94c0c96c779c
parenta9b34fd9216367d6f959f979d318b52e00d58118 (diff)
downloadtsnif-acc5795db9fd1af91690d80ec483c745ad558f28.tar.gz
tsnif-acc5795db9fd1af91690d80ec483c745ad558f28.tar.xz
tsnif-acc5795db9fd1af91690d80ec483c745ad558f28.zip
added read support for storage_mmap
-rw-r--r--src/intf.h4
-rw-r--r--src/storage-mmap.c236
-rw-r--r--src/storage-mmap.h12
-rw-r--r--src/storage.h14
-rw-r--r--src/test-storage-mmap.c315
-rw-r--r--src/test.c67
-rw-r--r--src/test.h3
-rw-r--r--src/tsnif.c2
8 files changed, 605 insertions, 48 deletions
diff --git a/src/intf.h b/src/intf.h
index a6b6577..6cabfde 100644
--- a/src/intf.h
+++ b/src/intf.h
@@ -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;
}
diff --git a/src/test.c b/src/test.c
index 0bd2f10..c1b0a7f 100644
--- a/src/test.c
+++ b/src/test.c
@@ -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;
}
diff --git a/src/test.h b/src/test.h
index a1f89ce..3aba06f 100644
--- a/src/test.h
+++ b/src/test.h
@@ -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;