commit 5ae5004e2032458daa894e3feebb07249f73917a Author: Oleg Borodin Date: Thu Jan 5 16:18:18 2023 +0200 initial import of sources diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..195d686 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.elf +*.bin +*.map +*.geany +*.o +*~ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..41158b8 --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ +# +# Copyright 2023 Oleg Borodin +# + +all: test + +CC = cc +CFLAGS = -O -Wall -I. -std=c99 -pthread +LDFLAGS = -pthread + +.c.o: + $(CC) -c $(CFLAGS) -o $@ $< + +hwmemory.c: hwmemory.h +hwmemory.o: hwmemory.c + +hwstore.c: hwstore.h +hwstore.o: hwstore.c + +hwstore_test.c: hwstore.h +hwstore_test.o: hwstore_test.c + +OBJS += hwstore.o +OBJS += hwmemory.o + +hwstore_test: hwstore_test.o $(OBJS) + $(CC) $(LDFLAGS) -o $@ hwstore_test.o $(OBJS) + +test: hwstore_test + ./hwstore_test + +clean: + rm -f *_test + rm -f *.o *~ + +#EOF diff --git a/hwmemory.c b/hwmemory.c new file mode 100644 index 0000000..952d026 --- /dev/null +++ b/hwmemory.c @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Oleg Borodin + */ + +#include +#include +#include +#include +#include + +#include + +int msleep(int tms) { + return usleep(tms * 1000); +} + +#define BYTERATE (8 + 2) + + +void hwmemory_init(hwmemory_t* hwmemory, int size) { + hwmemory->data = malloc(size); + memset(hwmemory->data, 0, size); + hwmemory->size = size; +} + +int hwmemory_write(hwmemory_t* hwmemory, int pos, void* data, int size) { + if ((pos + size) > hwmemory->size) return -1; + memcpy(&(hwmemory->data[pos]), data, size); + usleep(BYTERATE * size); + return size; +} + +int hwmemory_read(hwmemory_t* hwmemory, int pos, void* data, int size) { + if ((pos + size) > hwmemory->size) { + size = hwmemory->size - pos; + } + memcpy(&(*data), &(hwmemory->data[pos]), size); + usleep(BYTERATE * size); + return size; +} + +int hwmemory_size(hwmemory_t* hwmemory) { + return hwmemory->size; +} + +void hwmemory_destroy(hwmemory_t* hwmemory) { + free(hwmemory->data); +} diff --git a/hwmemory.h b/hwmemory.h new file mode 100644 index 0000000..94f8bdf --- /dev/null +++ b/hwmemory.h @@ -0,0 +1,25 @@ +/* + * Copyright 2023 Oleg Borodin + */ + +#ifndef HWMEMORY_H_QWERTY +#define HWMEMORY_H_QWERTY + +#include +#include +#include +#include +#include + +typedef struct { + char* data; + int size; +} hwmemory_t; + +void hwmemory_init(hwmemory_t* hwmemory, int size); +int hwmemory_write(hwmemory_t* hwmemory, int pos, void* data, int size); +int hwmemory_read(hwmemory_t* hwmemory, int pos, void* data, int size); +int hwmemory_size(hwmemory_t* hwmemory); +void hwmemory_destroy(hwmemory_t* hwmemory); + +#endif diff --git a/hwstore.c b/hwstore.c new file mode 100644 index 0000000..7edfa92 --- /dev/null +++ b/hwstore.c @@ -0,0 +1,375 @@ +/* + * Copyright 2023 Oleg Borodin + */ + +#include +#include +#include +#include +#include + +#include +#include + + +#define STOREHEAD_SIZE ((int)sizeof(hwstore_t)) +#define CELLHEAD_SIZE ((int)sizeof(hwcell_t)) + + +static void hwcell_init(hwcell_t* hwcell, int keysize, int valsize); + +static void hwstore_read_chead(hwstore_t* hwstore, int pos, hwcell_t *cell); +static void hwstore_read_cell(hwstore_t* hwstore, int pos, hwcell_t *cell, char** key, char** val); +static void hwstore_read_ckey(hwstore_t* hwstore, int pos, hwcell_t *cell, char** key); +static void hwstore_read_cval(hwstore_t* hwstore, int pos, hwcell_t *cell, char** val); + +static void hwstore_write_cell(hwstore_t* hwstore, int pos, hwcell_t *cell, char* key, char* val); +static void hwstore_write_chead(hwstore_t* hwstore, int pos, hwcell_t *cell); +static void hwstore_write_shead(hwstore_t* hwstore); + + +static int hwstore_trywrite_tofree(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize); +static int hwstore_trywrite_tohead(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize); +static int hwstore_trywrite_totail(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize); +static int hwstore_alloc(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize); +static void hwstore_free(hwstore_t* hwstore, int addr); + +static int hwstore_find(hwstore_t* hwstore, char* key, int keysize, hwcell_t* currcell); + +static void hwcell_init(hwcell_t* hwcell, int keysize, int valsize) { + hwcell->keysize = keysize; + hwcell->valsize = valsize; + hwcell->capa = keysize + valsize; + hwcell->next = HWNULL; +} + +void hwstore_init(hwstore_t* hwstore, hwmemory_t* hwmemory) { + hwstore->hwmemory = hwmemory; + hwstore->size = hwmemory_size(hwmemory); + hwstore->head = HWNULL; + hwstore->tail = HWNULL; + hwstore->freehead = HWNULL; +} + +static void hwstore_read_chead(hwstore_t* hwstore, int pos, hwcell_t *cell) { + hwmemory_read(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); +} + +static void hwstore_read_cell(hwstore_t* hwstore, int pos, hwcell_t *cell, char** key, char** val) { + hwmemory_read(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); + pos += CELLHEAD_SIZE; + *key = malloc(cell->keysize); + *val = malloc(cell->valsize); + hwmemory_read(hwstore->hwmemory, pos, *key, cell->keysize); + pos += cell->keysize; + hwmemory_read(hwstore->hwmemory, pos, *val, cell->valsize); +} + +static void hwstore_read_ckey(hwstore_t* hwstore, int pos, hwcell_t *cell, char** key) { + //hwmemory_read(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); + pos += CELLHEAD_SIZE; + *key = malloc(cell->keysize); + hwmemory_read(hwstore->hwmemory, pos, *key, cell->keysize); +} + +static void hwstore_read_cval(hwstore_t* hwstore, int pos, hwcell_t *cell, char** val) { + //hwmemory_read(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); + pos += CELLHEAD_SIZE; + pos += cell->keysize; + *val = malloc(cell->valsize); + hwmemory_read(hwstore->hwmemory, pos, *val, cell->valsize); +} + + +static void hwstore_write_cell(hwstore_t* hwstore, int pos, hwcell_t *cell, char* key, char* val) { + hwmemory_write(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); + pos += CELLHEAD_SIZE; + hwmemory_write(hwstore->hwmemory, pos, key, cell->keysize); + pos += cell->keysize; + hwmemory_write(hwstore->hwmemory, pos, val, cell->valsize); +} + +static void hwstore_write_chead(hwstore_t* hwstore, int pos, hwcell_t *cell) { + hwmemory_write(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); +} + +static void hwstore_write_shead(hwstore_t* hwstore) { + hwstore_t chwstore = *hwstore; + chwstore.magic = STORE_MAGIC; + hwmemory_write(hwstore->hwmemory, 0, &chwstore, STOREHEAD_SIZE); +} + +static int hwstore_trywrite_tofree(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + /* Check free chain */ + if (hwstore->freehead == HWNULL) return -1; + + int datasize = keysize + valsize; + + hwcell_t freecell; + int freepos = hwstore->freehead; + hwstore_read_chead(hwstore, freepos, &freecell); + + if (freecell.capa >= datasize) { + /* Delete cell from free chain */ + hwstore->freehead = freecell.next; + /* Insert cell to chain */ + freecell.next = hwstore->head; + hwstore->head = freepos; + + hwstore_write_cell(hwstore, freepos, &freecell, key, val); + hwstore_write_shead(hwstore); + + return freepos; + } + + while (freecell.next != HWNULL) { + /* Read next cell */ + hwcell_t nextcell; + int nextpos = freecell.next; + hwstore_read_chead(hwstore, nextpos, &nextcell); + + if (nextcell.capa >= datasize) { + /* Delete free cell from chain */ + freecell.next = nextcell.next; + hwstore_write_chead(hwstore, freepos, &freecell); + + /* Insert next cell to used chain */ + nextcell.next = hwstore->head; + hwstore_write_cell(hwstore, nextpos, &nextcell, key, val); + + hwstore->head = nextpos; + hwstore_write_shead(hwstore); + + return freepos; + } + + hwstore_read_chead(hwstore, freepos, &freecell); + freepos = freecell.next; + } + return -1; + +} + +static int hwstore_trywrite_tohead(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + + /* Check null store head */ + if (hwstore->head == HWNULL) { + hwcell_t headcell; + hwcell_init(&headcell, keysize, valsize); + + /* Write new cell */ + int headpos = 0 + STOREHEAD_SIZE; + hwstore_write_cell(hwstore, headpos, &headcell, key, val); + + /* Update store descriptor */ + hwstore->head = headpos; + hwstore->tail = headpos; + hwstore->freehead = HWNULL; + hwstore_write_shead(hwstore); + return headpos; + } + return -1; +} + +static int hwstore_trywrite_totail(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + /* Check tail space */ + int datasize = keysize + valsize; + + /* Read tail call from device */ + hwcell_t tailcell; + int tailpos = hwstore->tail; + hwstore_read_chead(hwstore, tailpos, &tailcell); + + /* Calculate exists and future bound of cells */ + int tailend = hwstore->tail + CELLHEAD_SIZE + tailcell.capa; + int nextend = tailend + CELLHEAD_SIZE + datasize; + + /* Compare future bound and size of device */ + if (nextend < hwstore->size) { + hwcell_t nextcell; + hwcell_init(&nextcell, keysize, valsize); + + /* Write new tail cell */ + int nextpos = tailend + 1; + hwstore_write_cell(hwstore, nextpos, &nextcell, key, val); + + /* Update old tail cell */ + tailcell.next = nextpos; + hwstore_write_chead(hwstore, tailpos, &tailcell); + + /* Update store descriptor */ + hwstore->tail = nextpos; + hwstore_write_shead(hwstore); + return nextpos; + } + + return -1; +} + +static int hwstore_alloc(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + int addr = -1; + + if ((addr = hwstore_trywrite_tohead(hwstore, key, keysize, val, valsize)) > 0) { + return addr; + } + + if ((addr = hwstore_trywrite_tofree(hwstore, key, keysize, val, valsize)) > 0) { + return addr; + } + + if ((addr = hwstore_trywrite_totail(hwstore, key, keysize, val, valsize)) > 0) { + return addr; + } + + return addr; +} + +static void hwstore_free(hwstore_t* hwstore, int addr) { + + if (hwstore->head == HWNULL) return; + + /* Check head for address */ + int headpos = hwstore->head; + if (headpos == addr) { + hwcell_t headcell; + hwstore_read_chead(hwstore, headpos, &headcell); + + /* Delete cell from used head */ + hwstore->head = headcell.next; + + /* Insert cell to free head */ + headcell.next = hwstore->freehead; + hwstore->freehead = headpos; + + hwstore_write_chead(hwstore, headpos, &headcell); + hwstore_write_shead(hwstore); + return; + } + + /* Check cell chain after head cell */ + int currpos = hwstore->head; + hwcell_t currcell; + hwstore_read_chead(hwstore, currpos, &currcell); + + while (currcell.next != HWNULL) { + if (currcell.next == addr) { + + printf("del addr = %d\n", currcell.next); + + /* Read next cell */ + hwcell_t nextcell; + int nextpos = currcell.next; + hwstore_read_chead(hwstore, nextpos, &nextcell); + + /* Delete next used cell from chain */ + currcell.next = nextcell.next; + hwstore_write_chead(hwstore, currpos, &currcell); + + /* Insert next cell to free head */ + nextcell.next = hwstore->freehead; + + hwstore->freehead = nextpos; + hwstore_write_chead(hwstore, nextpos, &nextcell); + hwstore_write_shead(hwstore); + return; + } + currpos = currcell.next; + hwstore_read_chead(hwstore, currpos, &currcell); + } + return; +} + +void hwstore_print(hwstore_t* hwstore) { + int currpos = hwstore->head; + while (currpos != HWNULL) { + hwcell_t currcell; + char* key = NULL; + char* val = NULL; + hwstore_read_cell(hwstore, currpos, &currcell, &key, &val); + printf("## used cell addr = %3d, key = %s, val=%s\n", currpos, key, val); + free(key); + free(val); + currpos = currcell.next; + } + + currpos = hwstore->freehead; + while (currpos != HWNULL) { + hwcell_t currcell; + hwstore_read_chead(hwstore, currpos, &currcell); + printf("# free cell addr = %3d\n", currpos); + currpos = currcell.next; + } + return; +} + +int hwstore_get(hwstore_t* hwstore, char* key, int keysize, char** val) { + int currpos = hwstore->head; + while (currpos != HWNULL) { + hwcell_t currcell; + hwstore_read_chead(hwstore, currpos, &currcell); + if (currcell.keysize == keysize) { + char* hwkey = NULL; + hwstore_read_ckey(hwstore, currpos, &currcell, &hwkey); + + if (memcmp(key, hwkey, keysize) == 0) { + hwstore_read_cval(hwstore, currpos, &currcell, val); + + free(hwkey); + return currpos; + } + + free(hwkey); + } + currpos = currcell.next; + } + return -1; +} + +static int hwstore_find(hwstore_t* hwstore, char* key, int keysize, hwcell_t* currcell) { + int currpos = hwstore->head; + while (currpos != HWNULL) { + hwstore_read_chead(hwstore, currpos, currcell); + if (currcell->keysize == keysize) { + char* hwkey = NULL; + hwstore_read_ckey(hwstore, currpos, currcell, &hwkey); + + if (memcmp(key, hwkey, keysize) == 0) { + free(hwkey); + return currpos; + } + free(hwkey); + } + currpos = currcell->next; + } + return -1; +} + +int hwstore_del(hwstore_t* hwstore, char* key, int keysize) { + int addr = -1; + hwcell_t currcell; + if ((addr = hwstore_find(hwstore, key, keysize, &currcell)) > 0) { + hwstore_free(hwstore, addr); + } + return addr; +} + +int hwstore_set(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + int addr = -1; + hwcell_t currcell; + + if ((addr = hwstore_find(hwstore, key, keysize, &currcell)) > 0) { + int datasize = keysize + valsize; + if (datasize > currcell.capa) { + hwstore_free(hwstore, addr); + int newaddr = hwstore_alloc(hwstore, key, keysize, val, valsize); + return newaddr; + } + + currcell.keysize = keysize; + currcell.valsize = valsize; + hwstore_write_cell(hwstore, addr, &currcell, key, val); + return addr; + } + addr = hwstore_alloc(hwstore, key, keysize, val, valsize); + return addr; +} diff --git a/hwstore.h b/hwstore.h new file mode 100644 index 0000000..dab8da6 --- /dev/null +++ b/hwstore.h @@ -0,0 +1,44 @@ +/* + * Copyright 2023 Oleg Borodin + */ + +#ifndef HWSTORE_H_QWERTY +#define HWSTORE_H_QWERTY + +#include +#include +#include +#include +#include + +#define HWNULL 0 +#define STORE_MAGIC 0xABBAABBA + +typedef struct __attribute__((packed)) { + int keysize; + int valsize; + int capa; + int next; +} hwcell_t; + +typedef struct __attribute__((packed)) { + union { + hwmemory_t* hwmemory; + int magic; + }; + int size; + int head; + int tail; + int freehead; +} hwstore_t; + + +void hwstore_init(hwstore_t* hwstore, hwmemory_t* hwmemory); + +int hwstore_set(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize); +int hwstore_get(hwstore_t* hwstore, char* key, int keysize, char** val); +int hwstore_del(hwstore_t* hwstore, char* key, int keysize); + +void hwstore_print(hwstore_t* hwstore); + +#endif diff --git a/hwstore_test.c b/hwstore_test.c new file mode 100644 index 0000000..b9e897b --- /dev/null +++ b/hwstore_test.c @@ -0,0 +1,79 @@ +/* + * Copyright 2023 Oleg Borodin + */ + +#include +#include +#include +#include +#include + +#include +#include + +int main(int argc, char **argv) { + + hwmemory_t hwmemory; + hwmemory_init(&hwmemory, 1024 * 16); + + hwstore_t hwstore; + hwstore_init(&hwstore, &hwmemory); + + + int count = 12; + for (int i = 0; i < count; i++) { + + char* key = NULL; + char* val = NULL; + asprintf(&key, "key%04d", i); + asprintf(&val, "val%04d", i); + int keysize = strlen(key) + 1; + int valsize = strlen(val) + 1; + + int address = hwstore_set(&hwstore, key, keysize, val, valsize); + + printf("i = %3d, addr = %3d\n", i, address); + free(key); + free(val); + } + + for (int i = 0; i < count; i++) { + + char* key = NULL; + char* val = NULL; + asprintf(&key, "key%04d", i); + asprintf(&val, "VAR%04d", i); + int keysize = strlen(key) + 1; + int valsize = strlen(val) + 1; + + int address = hwstore_set(&hwstore, key, keysize, val, valsize); + + printf("i = %3d, addr = %3d\n", i, address); + free(key); + free(val); + } + + for (int i = 0; i < count; i++) { + + char* key = NULL; + char* val = NULL; + + asprintf(&key, "key%04d", i); + asprintf(&val, "val%04d", i); + int keysize = strlen(key) + 1; + + char* rval = NULL; + int addr = HWNULL; + if ((addr = hwstore_get(&hwstore, key, keysize, &rval)) > 0) { + printf("i = %3d, get addr = %3d, key = %s, val = %s\n", i, addr, key, rval); + } + + free(rval); + free(key); + free(val); + } + + hwstore_print(&hwstore); + + return 0; +} diff --git a/works/hwstore00.c b/works/hwstore00.c new file mode 100644 index 0000000..6106a19 --- /dev/null +++ b/works/hwstore00.c @@ -0,0 +1,354 @@ +/* + * Copyright 2023 Oleg Borodin + */ + + +#include +#include +#include +#include +#include + +int msleep(int tms) { + return usleep(tms * 1000); +} + +#define BYTERATE (8 + 2) + +typedef struct { + char* data; + int size; +} hwpage_t; + +void hwpage_init(hwpage_t* hwpage, int size) { + hwpage->data = malloc(size); + memset(hwpage->data, 0, size); + hwpage->size = size; +} + +int hwpage_write(hwpage_t* hwpage, int pos, void* data, int size) { + if ((pos + size) > hwpage->size) return -1; + memcpy(&(hwpage->data[pos]), data, size); + usleep(BYTERATE * size); + return size; +} + +int hwpage_read(hwpage_t* hwpage, int pos, void* data, int size) { + if ((pos + size) > hwpage->size) { + size = hwpage->size - pos; + } + memcpy(&(*data), &(hwpage->data[pos]), size); + usleep(BYTERATE * size); + return size; +} + +int hwpage_size(hwpage_t* hwpage) { + return hwpage->size; +} + +void hwpage_destroy(hwpage_t* hwpage) { + free(hwpage->data); +} + +typedef struct __attribute__((packed)) { + int size; + int capa; + int next; +} hwcell_t; + +typedef struct __attribute__((packed)) { + union { + hwpage_t* hwpage; + int magic; + }; + int size; + int head; + int tail; + int freehead; + //int freetail; +} hwstore_t; + +#define STOREHEAD_SIZE ((int)sizeof(hwstore_t)) +#define CELLHEAD_SIZE ((int)sizeof(hwcell_t)) +#define HWNULL 0 +#define STORE_MAGIC 0xABBAABBA + +void hwcell_init(hwcell_t* hwcell, int size) { + hwcell->size = size; + hwcell->capa = size; + hwcell->next = HWNULL; +} + +void hwcell_destroy(hwcell_t* hwcell) { + // nop +} + +void hwcell_print(hwcell_t* hwcell) { + printf("cell size = %d, capa = %d, next = %d\n", hwcell->size, hwcell->capa, hwcell->next); +} + + +void hwstore_init(hwstore_t* hwstore, hwpage_t* hwpage) { + hwstore->hwpage = hwpage; + hwstore->size = hwpage_size(hwpage); + hwstore->head = HWNULL; + hwstore->tail = HWNULL; + hwstore->freehead = HWNULL; +} + +void hwstore_readcell(hwstore_t* hwstore, int pos, hwcell_t *cell) { + hwpage_read(hwstore->hwpage, pos, cell, CELLHEAD_SIZE); +} + +void hwstore_writecell(hwstore_t* hwstore, int pos, hwcell_t *cell) { + hwpage_write(hwstore->hwpage, pos, cell, CELLHEAD_SIZE); +} + +void hwstore_writehead(hwstore_t* hwstore) { + hwstore_t chwstore = *hwstore; + chwstore.magic = STORE_MAGIC; + hwpage_write(hwstore->hwpage, 0, &chwstore, STOREHEAD_SIZE); +} + +int hwstore_allocfree(hwstore_t* hwstore, int size) { + /* Check free chain */ + if (hwstore->freehead == HWNULL) return -1; + + hwcell_t freecell; + int freepos = hwstore->freehead; + hwstore_readcell(hwstore, freepos, &freecell); + + if (freecell.capa >= size) { + /* Delete cell from free chain */ + hwstore->freehead = freecell.next; + /* Insert cell to chain */ + freecell.next = hwstore->head; + hwstore->head = freepos; + + hwstore_writecell(hwstore, freepos, &freecell); + hwstore_writehead(hwstore); + + hwcell_destroy(&freecell); + return freepos + CELLHEAD_SIZE; + } + + while (freecell.next != HWNULL) { + /* Read next cell */ + hwcell_t nextcell; + int nextpos = freecell.next; + hwstore_readcell(hwstore, nextpos, &nextcell); + + if (nextcell.capa >= size) { + /* Delete free cell from chain */ + freecell.next = nextcell.next; + hwstore_writecell(hwstore, freepos, &freecell); + + /* Insert next cell to used chain */ + nextcell.next = hwstore->head; + hwstore_writecell(hwstore, nextpos, &nextcell); + + hwstore->head = nextpos; + hwstore_writehead(hwstore); + + hwcell_destroy(&freecell); + return freepos + CELLHEAD_SIZE; + } + hwcell_destroy(&nextcell); + + hwstore_readcell(hwstore, freepos, &freecell); + freepos = freecell.next; + } + hwcell_destroy(&freecell); + return -1; + +} + +int hwstore_allochead(hwstore_t* hwstore, int size) { + + /* Check null store head */ + if (hwstore->head == HWNULL) { + hwcell_t headcell; + hwcell_init(&headcell, size); + + /* Write new cell */ + int headpos = 0 + STOREHEAD_SIZE; + hwstore_writecell(hwstore, headpos, &headcell); + + /* Update store descriptor */ + hwstore->head = headpos; + hwstore->tail = headpos; + hwstore_writehead(hwstore); + + hwcell_destroy(&headcell); + return headpos + CELLHEAD_SIZE; + } + return -1; +} + +int hwstore_alloctail(hwstore_t* hwstore, int size) { + + /* Check tail space */ + /* Read tail call from device */ + hwcell_t tailcell; + int tailpos = hwstore->tail; + hwstore_readcell(hwstore, tailpos, &tailcell); + + /* Calculate exists and future bound of cells */ + int tailend = hwstore->tail + CELLHEAD_SIZE + tailcell.capa; + int nextend = tailend + CELLHEAD_SIZE + size; + + /* Compare future bound and size of device */ + if (nextend < hwstore->size) { + hwcell_t nextcell; + hwcell_init(&nextcell, size); + + /* Write new tail cell */ + int nextpos = tailend + 1; + hwstore_writecell(hwstore, nextpos, &nextcell); + + /* Update old tail cell */ + tailcell.next = nextpos; + hwstore_writecell(hwstore, tailpos, &tailcell); + + /* Update store descriptor */ + hwstore->tail = nextpos; + hwstore_writehead(hwstore); + + hwcell_destroy(&nextcell); + hwcell_destroy(&tailcell); + return nextpos + CELLHEAD_SIZE; + } + + hwcell_destroy(&tailcell); + return -1; +} + +int hwstore_alloc(hwstore_t* hwstore, int size) { + + int addr = -1; + if ((addr = hwstore_allocfree(hwstore, size)) > 0) { + return addr; + } + + if ((addr = hwstore_allochead(hwstore, size)) > 0) { + return addr; + } + + if ((addr = hwstore_alloctail(hwstore, size)) > 0) { + return addr; + } + + return -1; +} + +void hwstore_free(hwstore_t* hwstore, int addr) { + + if (hwstore->head == HWNULL) return; + + /* Check head for address */ + int headpos = hwstore->head; + if ((headpos + CELLHEAD_SIZE) == addr) { + hwcell_t headcell; + hwstore_readcell(hwstore, headpos, &headcell); + + /* Delete cell from used head */ + hwstore->head = headcell.next; + + /* Insert cell to free head */ + headcell.next = hwstore->freehead; + hwstore->freehead = headpos; + + hwstore_writecell(hwstore, headpos, &headcell); + hwstore_writehead(hwstore); + return; + } + + /* Check cell chain after head cell */ + int currpos = hwstore->head; + hwcell_t currcell; + hwstore_readcell(hwstore, currpos, &currcell); + + while (currcell.next != HWNULL) { + if ((currcell.next + CELLHEAD_SIZE) == addr) { + + printf("del pos = %d, addr = %d\n", currcell.next, currcell.next + CELLHEAD_SIZE); + + /* Read next cell */ + hwcell_t nextcell; + int nextpos = currcell.next; + hwstore_readcell(hwstore, nextpos, &nextcell); + + /* Delete next used cell from chain */ + currcell.next = nextcell.next; + hwstore_writecell(hwstore, currpos, &currcell); + + /* Insert next cell to free head */ + nextcell.next = hwstore->freehead; + + hwstore->freehead = nextpos; + hwstore_writecell(hwstore, nextpos, &nextcell); + hwstore_writehead(hwstore); + return; + } + currpos = currcell.next; + hwstore_readcell(hwstore, currpos, &currcell); + } + return; +} + +void hwstore_print(hwstore_t* hwstore) { + int currpos = hwstore->head; + while (currpos != HWNULL) { + hwcell_t currcell; + hwstore_readcell(hwstore, currpos, &currcell); + printf("## used cell pos = %3d, addr = %3d\n", currpos, currpos + CELLHEAD_SIZE); + currpos = currcell.next; + } + + currpos = hwstore->freehead; + while (currpos != HWNULL) { + hwcell_t currcell; + hwstore_readcell(hwstore, currpos, &currcell); + printf("# free cell pos = %3d, addr = %3d\n", currpos, currpos + CELLHEAD_SIZE); + currpos = currcell.next; + } + return; +} + + +int main(int argc, char **argv) { + + hwpage_t hwpage; + hwpage_init(&hwpage, 256); + + hwstore_t hwstore; + hwstore_init(&hwstore, &hwpage); + + int size = 5; + + int count = 7; + for (int i = 0; i < count; i++) { + int address = hwstore_alloc(&hwstore, size); + printf("i - %d, cell = %3d, addr = %3d\n", i, address - CELLHEAD_SIZE, address); + } + + for (int i = 0; i < 100; i++) { + hwstore_free(&hwstore, i); + } + + hwstore_free(&hwstore, 90); + + //int address = hwstore_alloc(&hwstore, size); + //printf("new addr = %d\n", address); + //printf("freehead = %d, data addr = %d\n", hwstore.freehead, hwstore.freehead + CELLHEAD_SIZE); + + + //hwstore_t* hhwstore = ((hwstore_t*)(hwpage.data)); + //printf("hhw magic = %X\n", hhwstore->magic); + //printf("freehead = %d, data addr = %d\n", hhwstore->freehead, hwstore.freehead + CELLHEAD_SIZE); + + hwstore_print(&hwstore); + + + return 0; +} diff --git a/works/hwstore01.c b/works/hwstore01.c new file mode 100644 index 0000000..e162a04 --- /dev/null +++ b/works/hwstore01.c @@ -0,0 +1,500 @@ +/* + * Copyright 2023 Oleg Borodin + */ + +#include +#include +#include +#include +#include + +int msleep(int tms) { + return usleep(tms * 1000); +} + +#define BYTERATE (8 + 2) + +typedef struct { + char* data; + int size; +} hwmemory_t; + +void hwmemory_init(hwmemory_t* hwmemory, int size) { + hwmemory->data = malloc(size); + memset(hwmemory->data, 0, size); + hwmemory->size = size; +} + +int hwmemory_write(hwmemory_t* hwmemory, int pos, void* data, int size) { + if ((pos + size) > hwmemory->size) return -1; + memcpy(&(hwmemory->data[pos]), data, size); + usleep(BYTERATE * size); + return size; +} + +int hwmemory_read(hwmemory_t* hwmemory, int pos, void* data, int size) { + if ((pos + size) > hwmemory->size) { + size = hwmemory->size - pos; + } + memcpy(&(*data), &(hwmemory->data[pos]), size); + usleep(BYTERATE * size); + return size; +} + +int hwmemory_size(hwmemory_t* hwmemory) { + return hwmemory->size; +} + +void hwmemory_destroy(hwmemory_t* hwmemory) { + free(hwmemory->data); +} + +typedef struct __attribute__((packed)) { + int keysize; + int valsize; + int capa; + int next; +} hwcell_t; + +typedef struct __attribute__((packed)) { + union { + hwmemory_t* hwmemory; + int magic; + }; + int size; + int head; + int tail; + int freehead; +} hwstore_t; + +#define STOREHEAD_SIZE ((int)sizeof(hwstore_t)) +#define CELLHEAD_SIZE ((int)sizeof(hwcell_t)) +#define HWNULL 0 +#define STORE_MAGIC 0xABBAABBA + +void hwcell_init(hwcell_t* hwcell, int keysize, int valsize) { + hwcell->keysize = keysize; + hwcell->valsize = valsize; + hwcell->capa = keysize + valsize; + hwcell->next = HWNULL; +} + +void hwcell_destroy(hwcell_t* hwcell) { + // nop +} + +void hwcell_print(hwcell_t* hwcell) { + printf("cell size = %d, capa = %d, next = %d\n", hwcell->keysize + hwcell->valsize, hwcell->capa, hwcell->next); +} + + +void hwstore_init(hwstore_t* hwstore, hwmemory_t* hwmemory) { + hwstore->hwmemory = hwmemory; + hwstore->size = hwmemory_size(hwmemory); + hwstore->head = HWNULL; + hwstore->tail = HWNULL; + hwstore->freehead = HWNULL; +} + +void hwstore_read_chead(hwstore_t* hwstore, int pos, hwcell_t *cell) { + hwmemory_read(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); + +} + +void hwstore_read_cell(hwstore_t* hwstore, int pos, hwcell_t *cell, char** key, char** val) { + hwmemory_read(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); + pos += CELLHEAD_SIZE; + *key = malloc(cell->keysize); + *val = malloc(cell->valsize); + hwmemory_read(hwstore->hwmemory, pos, *key, cell->keysize); + pos += cell->keysize; + hwmemory_read(hwstore->hwmemory, pos, *val, cell->valsize); +} + +void hwstore_read_ckey(hwstore_t* hwstore, int pos, hwcell_t *cell, char** key) { + //hwmemory_read(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); + pos += CELLHEAD_SIZE; + *key = malloc(cell->keysize); + hwmemory_read(hwstore->hwmemory, pos, *key, cell->keysize); +} + +void hwstore_read_cval(hwstore_t* hwstore, int pos, hwcell_t *cell, char** val) { + //hwmemory_read(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); + pos += CELLHEAD_SIZE; + pos += cell->keysize; + *val = malloc(cell->valsize); + hwmemory_read(hwstore->hwmemory, pos, *val, cell->valsize); +} + + +void hwstore_write_cell(hwstore_t* hwstore, int pos, hwcell_t *cell, char* key, char* val) { + hwmemory_write(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); + pos += CELLHEAD_SIZE; + hwmemory_write(hwstore->hwmemory, pos, key, cell->keysize); + pos += cell->keysize; + hwmemory_write(hwstore->hwmemory, pos, val, cell->valsize); +} + +void hwstore_write_chead(hwstore_t* hwstore, int pos, hwcell_t *cell) { + hwmemory_write(hwstore->hwmemory, pos, cell, CELLHEAD_SIZE); +} + + +void hwstore_write_shead(hwstore_t* hwstore) { + hwstore_t chwstore = *hwstore; + chwstore.magic = STORE_MAGIC; + hwmemory_write(hwstore->hwmemory, 0, &chwstore, STOREHEAD_SIZE); +} + +int hwstore_trywrite_tofree(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + /* Check free chain */ + if (hwstore->freehead == HWNULL) return -1; + + int datasize = keysize + valsize; + + hwcell_t freecell; + int freepos = hwstore->freehead; + hwstore_read_chead(hwstore, freepos, &freecell); + + if (freecell.capa >= datasize) { + /* Delete cell from free chain */ + hwstore->freehead = freecell.next; + /* Insert cell to chain */ + freecell.next = hwstore->head; + hwstore->head = freepos; + + hwstore_write_cell(hwstore, freepos, &freecell, key, val); + hwstore_write_shead(hwstore); + + hwcell_destroy(&freecell); + return freepos; + } + + while (freecell.next != HWNULL) { + /* Read next cell */ + hwcell_t nextcell; + int nextpos = freecell.next; + hwstore_read_chead(hwstore, nextpos, &nextcell); + + if (nextcell.capa >= datasize) { + /* Delete free cell from chain */ + freecell.next = nextcell.next; + hwstore_write_chead(hwstore, freepos, &freecell); + + /* Insert next cell to used chain */ + nextcell.next = hwstore->head; + hwstore_write_cell(hwstore, nextpos, &nextcell, key, val); + + hwstore->head = nextpos; + hwstore_write_shead(hwstore); + + hwcell_destroy(&freecell); + return freepos; + } + hwcell_destroy(&nextcell); + + hwstore_read_chead(hwstore, freepos, &freecell); + freepos = freecell.next; + } + hwcell_destroy(&freecell); + return -1; + +} + +int hwstore_trywrite_tohead(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + + /* Check null store head */ + if (hwstore->head == HWNULL) { + hwcell_t headcell; + hwcell_init(&headcell, keysize, valsize); + + /* Write new cell */ + int headpos = 0 + STOREHEAD_SIZE; + hwstore_write_cell(hwstore, headpos, &headcell, key, val); + + /* Update store descriptor */ + hwstore->head = headpos; + hwstore->tail = headpos; + hwstore->freehead = HWNULL; + hwstore_write_shead(hwstore); + + hwcell_destroy(&headcell); + return headpos; + } + return -1; +} + +int hwstore_trywrite_totail(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + /* Check tail space */ + int datasize = keysize + valsize; + + /* Read tail call from device */ + hwcell_t tailcell; + int tailpos = hwstore->tail; + hwstore_read_chead(hwstore, tailpos, &tailcell); + + /* Calculate exists and future bound of cells */ + int tailend = hwstore->tail + CELLHEAD_SIZE + tailcell.capa; + int nextend = tailend + CELLHEAD_SIZE + datasize; + + /* Compare future bound and size of device */ + if (nextend < hwstore->size) { + hwcell_t nextcell; + hwcell_init(&nextcell, keysize, valsize); + + /* Write new tail cell */ + int nextpos = tailend + 1; + hwstore_write_cell(hwstore, nextpos, &nextcell, key, val); + + /* Update old tail cell */ + tailcell.next = nextpos; + hwstore_write_chead(hwstore, tailpos, &tailcell); + + /* Update store descriptor */ + hwstore->tail = nextpos; + hwstore_write_shead(hwstore); + + hwcell_destroy(&nextcell); + hwcell_destroy(&tailcell); + return nextpos; + } + + hwcell_destroy(&tailcell); + return -1; +} + +int hwstore_alloc(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + + int addr = -1; + + if ((addr = hwstore_trywrite_tohead(hwstore, key, keysize, val, valsize)) > 0) { + return addr; + } + + if ((addr = hwstore_trywrite_tofree(hwstore, key, keysize, val, valsize)) > 0) { + return addr; + } + + if ((addr = hwstore_trywrite_totail(hwstore, key, keysize, val, valsize)) > 0) { + return addr; + } + + return addr; +} + +void hwstore_free(hwstore_t* hwstore, int addr) { + + if (hwstore->head == HWNULL) return; + + /* Check head for address */ + int headpos = hwstore->head; + if (headpos == addr) { + hwcell_t headcell; + hwstore_read_chead(hwstore, headpos, &headcell); + + /* Delete cell from used head */ + hwstore->head = headcell.next; + + /* Insert cell to free head */ + headcell.next = hwstore->freehead; + hwstore->freehead = headpos; + + hwstore_write_chead(hwstore, headpos, &headcell); + hwstore_write_shead(hwstore); + return; + } + + /* Check cell chain after head cell */ + int currpos = hwstore->head; + hwcell_t currcell; + hwstore_read_chead(hwstore, currpos, &currcell); + + while (currcell.next != HWNULL) { + if (currcell.next == addr) { + + printf("del addr = %d\n", currcell.next); + + /* Read next cell */ + hwcell_t nextcell; + int nextpos = currcell.next; + hwstore_read_chead(hwstore, nextpos, &nextcell); + + /* Delete next used cell from chain */ + currcell.next = nextcell.next; + hwstore_write_chead(hwstore, currpos, &currcell); + + /* Insert next cell to free head */ + nextcell.next = hwstore->freehead; + + hwstore->freehead = nextpos; + hwstore_write_chead(hwstore, nextpos, &nextcell); + hwstore_write_shead(hwstore); + return; + } + currpos = currcell.next; + hwstore_read_chead(hwstore, currpos, &currcell); + } + return; +} + +void hwstore_print(hwstore_t* hwstore) { + int currpos = hwstore->head; + while (currpos != HWNULL) { + hwcell_t currcell; + char* key = NULL; + char* val = NULL; + hwstore_read_cell(hwstore, currpos, &currcell, &key, &val); + printf("## used cell addr = %3d, key = %s, val=%s\n", currpos, key, val); + free(key); + free(val); + currpos = currcell.next; + } + + currpos = hwstore->freehead; + while (currpos != HWNULL) { + hwcell_t currcell; + hwstore_read_chead(hwstore, currpos, &currcell); + printf("# free cell addr = %3d\n", currpos); + currpos = currcell.next; + } + return; +} + +int hwstore_get(hwstore_t* hwstore, char* key, int keysize, char** val) { + int currpos = hwstore->head; + while (currpos != HWNULL) { + hwcell_t currcell; + hwstore_read_chead(hwstore, currpos, &currcell); + if (currcell.keysize == keysize) { + char* hwkey = NULL; + hwstore_read_ckey(hwstore, currpos, &currcell, &hwkey); + + if (memcmp(key, hwkey, keysize) == 0) { + hwstore_read_cval(hwstore, currpos, &currcell, val); + + free(hwkey); + return currpos; + } + + free(hwkey); + } + currpos = currcell.next; + } + return -1; +} + +int hwstore_find(hwstore_t* hwstore, char* key, int keysize, hwcell_t* currcell) { + int currpos = hwstore->head; + while (currpos != HWNULL) { + hwstore_read_chead(hwstore, currpos, currcell); + if (currcell->keysize == keysize) { + char* hwkey = NULL; + hwstore_read_ckey(hwstore, currpos, currcell, &hwkey); + + if (memcmp(key, hwkey, keysize) == 0) { + free(hwkey); + return currpos; + } + free(hwkey); + } + currpos = currcell->next; + } + return -1; +} + +int hwstore_del(hwstore_t* hwstore, char* key, int keysize) { + int addr = -1; + hwcell_t currcell; + if ((addr = hwstore_find(hwstore, key, keysize, &currcell)) > 0) { + hwstore_free(hwstore, addr); + } + return addr; +} + +int hwstore_set(hwstore_t* hwstore, char* key, int keysize, char* val, int valsize) { + int addr = -1; + hwcell_t currcell; + + if ((addr = hwstore_find(hwstore, key, keysize, &currcell)) > 0) { + int datasize = keysize + valsize; + if (datasize > currcell.capa) { + hwstore_free(hwstore, addr); + int newaddr = hwstore_alloc(hwstore, key, keysize, val, valsize); + return newaddr; + } + + currcell.keysize = keysize; + currcell.valsize = valsize; + hwstore_write_cell(hwstore, addr, &currcell, key, val); + return addr; + } + addr = hwstore_alloc(hwstore, key, keysize, val, valsize); + return addr; +} + +int main(int argc, char **argv) { + + hwmemory_t hwmemory; + hwmemory_init(&hwmemory, 1024 * 16); + + hwstore_t hwstore; + hwstore_init(&hwstore, &hwmemory); + + + int count = 12; + for (int i = 0; i < count; i++) { + + char* key = NULL; + char* val = NULL; + asprintf(&key, "key%04d", i); + asprintf(&val, "val%04d", i); + int keysize = strlen(key) + 1; + int valsize = strlen(val) + 1; + + int address = hwstore_set(&hwstore, key, keysize, val, valsize); + + printf("i = %3d, addr = %3d\n", i, address); + free(key); + free(val); + } + + for (int i = 0; i < count; i++) { + + char* key = NULL; + char* val = NULL; + asprintf(&key, "key%04d", i); + asprintf(&val, "VAR%04d", i); + int keysize = strlen(key) + 1; + int valsize = strlen(val) + 1; + + int address = hwstore_set(&hwstore, key, keysize, val, valsize); + + printf("i = %3d, addr = %3d\n", i, address); + free(key); + free(val); + } + + for (int i = 0; i < count; i++) { + + char* key = NULL; + char* val = NULL; + + asprintf(&key, "key%04d", i); + asprintf(&val, "val%04d", i); + int keysize = strlen(key) + 1; + + char* rval = NULL; + int addr = HWNULL; + if ((addr = hwstore_get(&hwstore, key, keysize, &rval)) > 0) { + printf("i = %3d, get addr = %3d, key = %s, val = %s\n", i, addr, key, rval); + } + + free(rval); + free(key); + free(val); + } + + hwstore_print(&hwstore); + + return 0; +} diff --git a/works/kvstore.c b/works/kvstore.c new file mode 100644 index 0000000..3396ee0 --- /dev/null +++ b/works/kvstore.c @@ -0,0 +1,183 @@ +/* + * Copyright 2022 Oleg Borodin + */ + +#include +#include +#include +#include +#include + +#include +#include + +typedef struct cell cell_t; +struct cell { + cell_t* next; + char* key; + char* val; + int hwnext; + int hwfree; +}; + +char* new_string(char* orig) { + if (orig == NULL) return NULL; + int strsize = strlen(orig) + 1; + char* copy = malloc(strsize); + memset(copy, '\0', strsize); + strcpy(copy, orig); + return copy; +} + + +cell_t* new_cell(char* key, char* val) { + cell_t* cell = malloc(sizeof(cell_t)); + cell->key = new_string(key); + cell->val = new_string(val); + cell->next = NULL; + return cell; +} + +void cell_free(cell_t* cell) { + if (cell == NULL) return; + free(cell->key); + free(cell->val); + free(cell); +} + +typedef struct store store_t; +struct store { + int count; + cell_t* head; + cell_t* tail; +}; + +typedef struct { + int hwsize; + int hwfree; + int hwhead; + int hwtail; +} hwstore_t; + +typedef struct { + int keysize; + int valsize; + int hwnext; +} hwcell_t; + +void store_init(store_t* store) { + store->head = NULL; + store->tail = NULL; + store->count = 0; + return; +} + +int store_hwsize(store_t* store, char* key, char* val) { + int hwsize = sizeof(hwcell_t); + hwsize += strlen(key); + hwsize += strlen(val); + return hwsize; +} + +int store_set(store_t* store, char* key, char* val) { + + cell_t* currcell = store->head; + while (currcell != NULL) { + if (strcmp(currcell->key, key) == 0) { + free(currcell->val); + currcell->val = new_string(val); + return 1; + } + currcell = currcell->next; + } + + cell_t* newcell = new_cell(key, val); + if (store->head == NULL) { + store->head = newcell; + store->tail = newcell; + store->count++; + return 1; + } + + store->tail->next = newcell; + store->tail = newcell; + store->count++; + return 1; +} + +char* store_get(store_t* store, char* key) { + cell_t* currcell = store->head; + while (currcell != NULL) { + if (strcmp(currcell->key, key) == 0) { + return currcell->val; + } + currcell = currcell->next; + } + return NULL; +} + + +void store_del(store_t* store, char* key) { + if (store->head == NULL) return; + + if (strcmp(store->head->key, key) == 0) { + cell_t* delcell = store->head; + store->head = store->head->next; + store->count--; + cell_free(delcell); + return; + } + + cell_t* currcell = store->head->next; + while (currcell->next != NULL) { + if (strcmp(currcell->next->key, key) == 0) { + cell_t* delcell = currcell->next; + currcell->next = currcell->next->next; + store->count--; + cell_free(delcell); + return; + } + currcell = currcell->next; + } +} + +void store_iprint(store_t* store) { + cell_t* currcell = store->head; + while (currcell != NULL) { + printf("key = %s, val = %s\n", currcell->key, currcell->val); + currcell = currcell->next; + } +} + +long getnanotime() { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + long time = ts.tv_nsec; + time += ts.tv_sec * 1000 * 1000 * 1000; + return time; +} + + +int main(int argc, char **argv) { + + store_t store; + store_init(&store); + + int count = 1000; + long start = getnanotime(); + for (int i = 0; i < count; i++) { + char *key = malloc(16); + char *val = malloc(16); + sprintf(key, "k%03d", i); + sprintf(val, "v%03d", i); + store_set(&store, key, val); + free(key); + free(val); + } + long stop = getnanotime(); + printf("time per set %ld\n", (stop - start) / count); + + //store_iprint(&store); + + return 0; +}