fix: Address Gabe feedback

master
Sean McBride 3 years ago
parent 443f6c2c43
commit c1df8e2fc3

@ -31,6 +31,7 @@ all: \
.PHONY: clean .PHONY: clean
clean: clean:
@make -C wasm_apps clean @make -C wasm_apps clean
@make -C scratch_storage clean
@rm -rf dist @rm -rf dist
@rm -rf ../runtime/bin/*.so @rm -rf ../runtime/bin/*.so
@ -43,6 +44,23 @@ wasm_apps/dist/%.wasm:
../libsledge/dist/libsledge.a: ../libsledge/dist/ ../libsledge/dist/libsledge.a: ../libsledge/dist/
make -C .. libsledge make -C .. libsledge
PHONY: scratch_storage
scratch_storage:
make -C scratch_storage all
PHONY: scratch_storage.install
scratch_storage.install: \
scratch_storage_get.install \
scratch_storage_set.install \
scratch_storage_delete.install \
scratch_storage_upsert.install
scratch_storage/scratch_storage_%.wasm:
make -C scratch_storage all
dist/scratch_storage_%.bc: scratch_storage/scratch_storage_%.wasm dist
${AWSMCC} ${AWSMFLAGS} $< -o $@
dist/%.bc: ./wasm_apps/dist/%.wasm dist dist/%.bc: ./wasm_apps/dist/%.wasm dist
${AWSMCC} ${AWSMFLAGS} $< -o $@ ${AWSMCC} ${AWSMFLAGS} $< -o $@

@ -0,0 +1,24 @@
include ../wasm_apps/common.mk
.PHONY: all
all: \
scratch_storage_get.wasm \
scratch_storage_set.wasm \
scratch_storage_delete.wasm \
scratch_storage_upsert.wasm \
.PHONY: clean
clean:
@rm -f scratch_storage_set.wa* scratch_storage_get.wa* scratch_storage_delete.wa* scratch_storage_upsert.wa*
scratch_storage_set.wasm: scratch_storage_set.c
@${WASMCC} ${WASMCFLAGS} ${WASMLDFLAGS} $^ -o $@
scratch_storage_get.wasm: scratch_storage_get.c
@${WASMCC} ${WASMCFLAGS} ${WASMLDFLAGS} $^ -o $@
scratch_storage_delete.wasm: scratch_storage_delete.c
@${WASMCC} ${WASMCFLAGS} ${WASMLDFLAGS} $^ -o $@
scratch_storage_upsert.wasm: scratch_storage_upsert.c
@${WASMCC} ${WASMCFLAGS} ${WASMLDFLAGS} $^ -o $@

@ -0,0 +1,32 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int scratch_storage_delete(void *key, uint32_t key_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("delete")));
int
main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "%s <key>", argv[0]);
return 0;
}
char *key = argv[1];
if (key == NULL || strlen(key) < 0) {
fprintf(stderr, "%s <key>", argv[0]);
return 0;
}
int rc = scratch_storage_delete(key, strlen(key));
if (rc == 1) {
printf("Key '%s' not found\n", key);
return 0;
} else {
printf("Key %s deleted\n", key);
}
};

@ -0,0 +1,38 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int scratch_storage_get(void *key, uint32_t key_len, void *buf, uint32_t buf_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("get")));
extern uint32_t scratch_storage_get_size(void *key, uint32_t key_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("get_size")));
int
main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "%s <key>", argv[0]);
return 0;
}
char *key = argv[1];
if (key == NULL || strlen(key) < 0) {
fprintf(stderr, "%s <key>", argv[0]);
return 0;
}
uint32_t val_size = scratch_storage_get_size(key, strlen(key));
char *buf = calloc(val_size + 1, sizeof(char));
int rc = scratch_storage_get(key, strlen(key), buf, val_size);
assert(rc != 2);
if (rc == 1) {
printf("Key '%s' not found\n", key);
return 0;
} else {
printf("Key %s resolved to value of size %u with contents %s\n", key, val_size, buf);
}
};

@ -0,0 +1,35 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int scratch_storage_set(void *key, uint32_t key_len, void *value, uint32_t value_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("set")));
int
main(int argc, char **argv)
{
if (argc < 3) {
fprintf(stderr, "%s <key> <value>", argv[0]);
return 0;
}
char *key = argv[1];
char *value = argv[2];
if (key == NULL || strlen(key) < 0 || value == NULL || strlen(value) < 0) {
fprintf(stderr, "%s <key> <value>", argv[0]);
return 0;
}
int rc = scratch_storage_set(key, strlen(key), value, strlen(value));
if (rc == 1) {
printf("Key %s was already present\n", key);
return 0;
}
assert(rc == 0);
printf("Key %s set to value %s\n", key, value);
return rc;
};

@ -0,0 +1,28 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int scratch_storage_upsert(void *key, uint32_t key_len, void *value, uint32_t value_len)
__attribute__((__import_module__("scratch_storage"), __import_name__("upsert")));
int
main(int argc, char **argv)
{
if (argc < 3) {
fprintf(stderr, "%s <key> <value>", argv[0]);
return 0;
}
char *key = argv[1];
char *value = argv[2];
if (key == NULL || strlen(key) < 0 || value == NULL || strlen(value) < 0) {
fprintf(stderr, "%s <key> <value>", argv[0]);
return 0;
}
scratch_storage_upsert(key, strlen(key), value, strlen(value));
printf("Key %s set to value %s\n", key, value);
};

@ -1 +1 @@
Subproject commit cf8a8bafb10c37f207ccba1405cac07cd70bae8f Subproject commit 20a7c88816c8f8882e03d42c76ff8c1e72bfeaec

@ -6,13 +6,12 @@
#include <stdlib.h> #include <stdlib.h>
#include "lock.h" #include "lock.h"
#include "xmalloc.h"
/* Simple K-V store based on The Practice of Programming by Kernighan and Pike */ /* Simple K-V store based on The Practice of Programming by Kernighan and Pike */
/* Bucket count is sized to be a prime that is approximately 20% larger than the desired capacity (6k keys) */ /* Bucket count is sized to be a prime that is approximately 20% larger than the desired capacity (6k keys) */
#define MAP_BUCKET_COUNT 7907 #define MAP_BUCKET_COUNT 7907
#define MAP_LOCK_STRIPES 17
#define MAP_HASH jenkins_hash #define MAP_HASH jenkins_hash
struct map_node { struct map_node {
@ -24,16 +23,22 @@ struct map_node {
uint32_t hash; uint32_t hash;
}; };
struct map_bucket {
lock_t lock;
struct map_node *head;
};
struct map { struct map {
struct map_node *buckets[MAP_BUCKET_COUNT]; struct map_bucket buckets[MAP_BUCKET_COUNT];
lock_t locks[MAP_LOCK_STRIPES];
}; };
static inline void static inline void
map_init(struct map *restrict map) map_init(struct map *restrict map)
{ {
for (int i = 0; i < MAP_BUCKET_COUNT; i++) { map->buckets[i] = NULL; } for (int i = 0; i < MAP_BUCKET_COUNT; i++) {
for (int i = 0; i < MAP_LOCK_STRIPES; i++) { LOCK_INIT(&map->locks[i]); } map->buckets[i].head = NULL;
LOCK_INIT(&map->buckets[i].lock);
}
}; };
/* See https://en.wikipedia.org/wiki/Jenkins_hash_function */ /* See https://en.wikipedia.org/wiki/Jenkins_hash_function */
@ -59,8 +64,11 @@ map_get(struct map *map, uint8_t *key, uint32_t key_len, uint32_t *ret_value_len
uint8_t *value = NULL; uint8_t *value = NULL;
uint32_t hash = MAP_HASH(key, key_len); uint32_t hash = MAP_HASH(key, key_len);
LOCK_LOCK(&map->locks[hash % MAP_LOCK_STRIPES]);
for (struct map_node *node = map->buckets[hash % MAP_BUCKET_COUNT]; node != NULL; node = node->next) { struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT];
LOCK_LOCK(&bucket->lock);
for (struct map_node *node = bucket->head; node != NULL; node = node->next) {
if (node->hash == hash) { if (node->hash == hash) {
value = node->value; value = node->value;
*ret_value_len = node->value_len; *ret_value_len = node->value_len;
@ -71,7 +79,7 @@ map_get(struct map *map, uint8_t *key, uint32_t key_len, uint32_t *ret_value_len
if (value == NULL) *ret_value_len = 0; if (value == NULL) *ret_value_len = 0;
DONE: DONE:
LOCK_UNLOCK(&map->locks[hash % MAP_LOCK_STRIPES]); LOCK_UNLOCK(&bucket->lock);
return value; return value;
} }
@ -80,33 +88,30 @@ map_set(struct map *map, uint8_t *key, uint32_t key_len, uint8_t *value, uint32_
{ {
bool did_set = false; bool did_set = false;
uint32_t hash = MAP_HASH(key, key_len); uint32_t hash = MAP_HASH(key, key_len);
LOCK_LOCK(&map->locks[hash % MAP_LOCK_STRIPES]); struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT];
for (struct map_node *node = map->buckets[hash % MAP_BUCKET_COUNT]; node != NULL; node = node->next) { LOCK_LOCK(&bucket->lock);
for (struct map_node *node = bucket->head; node != NULL; node = node->next) {
if (node->hash == hash) goto DONE; if (node->hash == hash) goto DONE;
} }
struct map_node *new_node = (struct map_node *)malloc(sizeof(struct map_node)); struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node));
*(new_node) = (struct map_node){ .hash = hash,
*(new_node) = (struct map_node){ .hash = hash, .key = xmalloc(key_len),
.key = malloc(key_len), .key_len = key_len,
.key_len = key_len, .value = xmalloc(value_len),
.value = malloc(value_len), .value_len = value_len,
.value_len = value_len, .next = bucket->head };
.next = map->buckets[hash % MAP_BUCKET_COUNT] };
assert(new_node->key);
assert(new_node->value);
// Copy Key and Value // Copy Key and Value
memcpy(new_node->key, key, key_len); memcpy(new_node->key, key, key_len);
memcpy(new_node->value, value, value_len); memcpy(new_node->value, value, value_len);
map->buckets[hash % MAP_BUCKET_COUNT] = new_node; bucket->head = new_node;
did_set = true; did_set = true;
DONE: DONE:
LOCK_UNLOCK(&map->locks[hash % MAP_LOCK_STRIPES]); LOCK_UNLOCK(&bucket->lock);
return did_set; return did_set;
} }
@ -118,12 +123,13 @@ map_delete(struct map *map, uint8_t *key, uint32_t key_len)
{ {
bool did_delete = false; bool did_delete = false;
uint32_t hash = MAP_HASH(key, key_len); uint32_t hash = MAP_HASH(key, key_len);
LOCK_LOCK(&map->locks[hash % MAP_LOCK_STRIPES]); struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT];
LOCK_LOCK(&bucket->lock);
struct map_node *prev = map->buckets[hash % MAP_BUCKET_COUNT]; struct map_node *prev = bucket->head;
if (prev->hash == hash) { if (prev != NULL && prev->hash == hash) {
map->buckets[hash % MAP_BUCKET_COUNT] = prev->next; bucket->head = prev->next;
free(prev->key); free(prev->key);
free(prev->value); free(prev->value);
free(prev); free(prev);
@ -141,33 +147,35 @@ map_delete(struct map *map, uint8_t *key, uint32_t key_len)
} }
DONE: DONE:
LOCK_UNLOCK(&map->locks[hash % MAP_LOCK_STRIPES]); LOCK_UNLOCK(&bucket->lock);
return did_delete; return did_delete;
} }
static inline void static inline void
map_upsert(struct map *map, uint8_t *key, uint32_t key_len, uint8_t *value, uint32_t value_len) map_upsert(struct map *map, uint8_t *key, uint32_t key_len, uint8_t *value, uint32_t value_len)
{ {
uint32_t hash = MAP_HASH(key, key_len); uint32_t hash = MAP_HASH(key, key_len);
LOCK_LOCK(&map->locks[hash % MAP_LOCK_STRIPES]); struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT];
for (struct map_node *node = map->buckets[hash % MAP_BUCKET_COUNT]; node != NULL; node = node->next) { LOCK_LOCK(&bucket->lock);
for (struct map_node *node = bucket->head; node != NULL; node = node->next) {
if (node->hash == hash) { if (node->hash == hash) {
node->value_len = value_len; node->value_len = value_len;
node->value = realloc(node->value, value_len); node->value = realloc(node->value, value_len);
assert(node->value); assert(node->value);
memcpy(node->value, value, value_len); memcpy(node->value, value, value_len);
goto DONE;
} }
goto DONE;
} }
struct map_node *new_node = (struct map_node *)malloc(sizeof(struct map_node)); struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node));
*(new_node) = (struct map_node){ .hash = hash, *(new_node) = (struct map_node){ .hash = hash,
.key = malloc(key_len), .key = xmalloc(key_len),
.key_len = key_len, .key_len = key_len,
.value = malloc(value_len), .value = xmalloc(value_len),
.value_len = value_len, .value_len = value_len,
.next = map->buckets[hash % MAP_BUCKET_COUNT] }; .next = bucket->head };
assert(new_node->key); assert(new_node->key);
assert(new_node->value); assert(new_node->value);
@ -176,8 +184,8 @@ map_upsert(struct map *map, uint8_t *key, uint32_t key_len, uint8_t *value, uint
memcpy(new_node->key, key, key_len); memcpy(new_node->key, key, key_len);
memcpy(new_node->value, value, value_len); memcpy(new_node->value, value, value_len);
map->buckets[hash % MAP_BUCKET_COUNT] = new_node; bucket->head = new_node;
DONE: DONE:
LOCK_UNLOCK(&map->locks[hash % MAP_LOCK_STRIPES]); LOCK_UNLOCK(&bucket->lock);
} }

@ -0,0 +1,14 @@
#pragma once
#include <stdlib.h>
#include "likely.h"
#include "panic.h"
static inline void *
xmalloc(size_t size)
{
void *allocation = malloc(size);
if (unlikely(allocation == NULL)) panic("xmalloc failed!\n");
return allocation;
}
Loading…
Cancel
Save