initial import of sources
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
*.elf
|
||||||
|
*.bin
|
||||||
|
*.map
|
||||||
|
*.geany
|
||||||
|
*.o
|
||||||
|
*~
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||||
|
#
|
||||||
|
|
||||||
|
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
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <hwmemory.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HWMEMORY_H_QWERTY
|
||||||
|
#define HWMEMORY_H_QWERTY
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
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
|
||||||
@@ -0,0 +1,375 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <hwmemory.h>
|
||||||
|
#include <hwstore.h>
|
||||||
|
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HWSTORE_H_QWERTY
|
||||||
|
#define HWSTORE_H_QWERTY
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#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
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <hwmemory.h>
|
||||||
|
#include <hwstore.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,354 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,500 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
+183
@@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 Oleg Borodin <borodin@unix7.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user