diff --git a/applications/Makefile b/applications/Makefile index a461aa2..ba0ec94 100644 --- a/applications/Makefile +++ b/applications/Makefile @@ -22,11 +22,16 @@ all: \ gocr.install \ gps_ekf.install \ license_plate_detection.install \ - resize_image.install + resize_image.install \ + scratch_storage_get.install \ + scratch_storage_set.install \ + scratch_storage_delete.install \ + scratch_storage_upsert.install \ .PHONY: clean clean: @make -C wasm_apps clean + @make -C scratch_storage clean @rm -rf dist @rm -rf ../runtime/bin/*.so @@ -39,6 +44,23 @@ wasm_apps/dist/%.wasm: ../libsledge/dist/libsledge.a: ../libsledge/dist/ 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 ${AWSMCC} ${AWSMFLAGS} $< -o $@ @@ -88,3 +110,15 @@ stack_overflow.install: ../runtime/bin/stack_overflow.wasm.so .PHONY: html.install html.install: ../runtime/bin/html.wasm.so + +.PHONY: scratch_storage_get.install +scratch_storage_get.install: ../runtime/bin/scratch_storage_get.wasm.so + +.PHONY: scratch_storage_set.install +scratch_storage_set.install: ../runtime/bin/scratch_storage_set.wasm.so + +.PHONY: scratch_storage_delete.install +scratch_storage_delete.install: ../runtime/bin/scratch_storage_delete.wasm.so + +.PHONY: scratch_storage_upsert.install +scratch_storage_upsert.install: ../runtime/bin/scratch_storage_upsert.wasm.so diff --git a/applications/scratch_storage/.gitignore b/applications/scratch_storage/.gitignore new file mode 100644 index 0000000..19e1bce --- /dev/null +++ b/applications/scratch_storage/.gitignore @@ -0,0 +1 @@ +*.wasm diff --git a/applications/scratch_storage/Makefile b/applications/scratch_storage/Makefile new file mode 100644 index 0000000..1a751d8 --- /dev/null +++ b/applications/scratch_storage/Makefile @@ -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 $@ diff --git a/applications/scratch_storage/scratch_storage_delete.c b/applications/scratch_storage/scratch_storage_delete.c new file mode 100644 index 0000000..5111107 --- /dev/null +++ b/applications/scratch_storage/scratch_storage_delete.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include + +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 ", argv[0]); + return 0; + } + + char *key = argv[1]; + + if (key == NULL || strlen(key) < 0) { + fprintf(stderr, "%s ", 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); + } +}; diff --git a/applications/scratch_storage/scratch_storage_get.c b/applications/scratch_storage/scratch_storage_get.c new file mode 100644 index 0000000..ba863e5 --- /dev/null +++ b/applications/scratch_storage/scratch_storage_get.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include + +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 ", argv[0]); + return 0; + } + + char *key = argv[1]; + + if (key == NULL || strlen(key) < 0) { + fprintf(stderr, "%s ", 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); + } +}; diff --git a/applications/scratch_storage/scratch_storage_set.c b/applications/scratch_storage/scratch_storage_set.c new file mode 100644 index 0000000..232dc17 --- /dev/null +++ b/applications/scratch_storage/scratch_storage_set.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include + +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 ", 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 ", 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; +}; diff --git a/applications/scratch_storage/scratch_storage_upsert.c b/applications/scratch_storage/scratch_storage_upsert.c new file mode 100644 index 0000000..6e05a96 --- /dev/null +++ b/applications/scratch_storage/scratch_storage_upsert.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include + +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 ", 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 ", argv[0]); + return 0; + } + + scratch_storage_upsert(key, strlen(key), value, strlen(value)); + printf("Key %s set to value %s\n", key, value); +}; diff --git a/applications/wasm_apps b/applications/wasm_apps index 456edf5..20a7c88 160000 --- a/applications/wasm_apps +++ b/applications/wasm_apps @@ -1 +1 @@ -Subproject commit 456edf5cecd7edc36314ba87e2d76ebf8cf1b5db +Subproject commit 20a7c88816c8f8882e03d42c76ff8c1e72bfeaec diff --git a/libsledge/Makefile b/libsledge/Makefile index f0dd19c..37679f1 100644 --- a/libsledge/Makefile +++ b/libsledge/Makefile @@ -26,7 +26,7 @@ dist: dist/%.o: src/%.c dist clang ${CFLAGS} -c ${INCLUDES} -o $@ $< -dist/libsledge.a: dist/control_instructions.o dist/memory_instructions.o dist/numeric_instructions.o dist/table_instructions.o dist/variable_instructions.o dist/instantiation.o dist/wasi_snapshot_preview1.o +dist/libsledge.a: dist/control_instructions.o dist/memory_instructions.o dist/numeric_instructions.o dist/table_instructions.o dist/variable_instructions.o dist/instantiation.o dist/wasi_snapshot_preview1.o dist/sledge_extensions.o ar rcs dist/libsledge.a $^ clean: diff --git a/libsledge/include/sledge_abi.h b/libsledge/include/sledge_abi.h index a26e959..2b47f86 100644 --- a/libsledge/include/sledge_abi.h +++ b/libsledge/include/sledge_abi.h @@ -249,3 +249,10 @@ uint32_t sledge_abi__wasi_snapshot_preview1_sock_send(__wasi_fd_t fd, __wasi_siz __wasi_size_t nbytes_retoffset); uint32_t sledge_abi__wasi_snapshot_preview1_sock_shutdown(__wasi_fd_t fd, uint32_t how); + +uint32_t sledge_abi__scratch_storage_get_size(uint32_t key_offset, uint32_t key_len); +int sledge_abi__scratch_storage_get(uint32_t key_offset, uint32_t key_size, uint32_t buf_offset, uint32_t buf_len); +int sledge_abi__scratch_storage_set(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len); +int sledge_abi__scratch_storage_delete(uint32_t key_offset, uint32_t key_len); +void +sledge_abi__scratch_storage_upsert(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len); diff --git a/libsledge/src/sledge_extensions.c b/libsledge/src/sledge_extensions.c new file mode 100644 index 0000000..3687a4f --- /dev/null +++ b/libsledge/src/sledge_extensions.c @@ -0,0 +1,65 @@ +#include +#include "sledge_abi.h" + +#define INLINE __attribute__((always_inline)) + +/** + * @param key + * @param key_len + * @returns value_size at key or 0 if key not present + */ +INLINE uint32_t +scratch_storage_get_size(uint32_t key_offset, uint32_t key_len) +{ + return sledge_abi__scratch_storage_get_size(key_offset, key_len); +} + +/** + * @param key_offset + * @param key_len + * @param buf_offset linear memory offset to buffer where value should be copied. + * @param buf_len Size of buffer. Assumed to be size returned by sledge_kv_get_value_size. + * @returns 0 on success, 1 if key missing, 2 if buffer too small + */ +INLINE int +scratch_storage_get(uint32_t key_offset, uint32_t key_len, uint32_t buf_offset, uint32_t buf_len) +{ + return sledge_abi__scratch_storage_get(key_offset, key_len, buf_offset, buf_len); +}; + +/** + * @param key_offset + * @param key_len + * @param value_offset + * @param value_len + * @returns 0 on success, 1 if already present, + */ +INLINE int +scratch_storage_set(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len) +{ + return sledge_abi__scratch_storage_set(key_offset, key_len, value_offset, value_len); +} + +/** + * @param key_offset + * @param key_len + * @returns 0 on success, 1 if not present + */ +INLINE int +scratch_storage_delete(uint32_t key_offset, uint32_t key_len) +{ + return sledge_abi__scratch_storage_delete(key_offset, key_len); +} + +/** + * @param key_offset + * @param key_len + * @param value_offset + * @param value_len + * @returns 0 on success, 1 if already present, + */ +INLINE void +scratch_storage_upsert(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len) +{ + sledge_abi__scratch_storage_upsert(key_offset, key_len, value_offset, value_len); +} diff --git a/runtime/include/lock.h b/runtime/include/lock.h index 5f15d1b..81a7681 100644 --- a/runtime/include/lock.h +++ b/runtime/include/lock.h @@ -5,6 +5,7 @@ #include "arch/getcycles.h" #include "runtime.h" +#include "generic_thread.h" typedef ck_spinlock_mcs_t lock_t; diff --git a/runtime/include/map.h b/runtime/include/map.h new file mode 100644 index 0000000..b923af8 --- /dev/null +++ b/runtime/include/map.h @@ -0,0 +1,191 @@ +#pragma once + +#include +#include +#include +#include + +#include "lock.h" +#include "xmalloc.h" + +/* 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) */ +#define MAP_BUCKET_COUNT 7907 +#define MAP_HASH jenkins_hash + +struct map_node { + struct map_node *next; + uint8_t *key; + uint8_t *value; + uint32_t key_len; + uint32_t value_len; + uint32_t hash; +}; + +struct map_bucket { + lock_t lock; + struct map_node *head; +}; + +struct map { + struct map_bucket buckets[MAP_BUCKET_COUNT]; +}; + +static inline void +map_init(struct map *restrict map) +{ + for (int i = 0; i < MAP_BUCKET_COUNT; i++) { + map->buckets[i].head = NULL; + LOCK_INIT(&map->buckets[i].lock); + } +}; + +/* See https://en.wikipedia.org/wiki/Jenkins_hash_function */ +static inline uint32_t +jenkins_hash(uint8_t *key, uint32_t key_len) +{ + uint32_t i = 0; + uint32_t hash = 0; + while (i != key_len) { + hash += key[i++]; + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return hash; +} + +static inline uint8_t * +map_get(struct map *map, uint8_t *key, uint32_t key_len, uint32_t *ret_value_len) +{ + uint8_t *value = NULL; + + uint32_t hash = MAP_HASH(key, key_len); + + 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) { + value = node->value; + *ret_value_len = node->value_len; + goto DONE; + } + } + + if (value == NULL) *ret_value_len = 0; + +DONE: + LOCK_UNLOCK(&bucket->lock); + return value; +} + +static inline bool +map_set(struct map *map, uint8_t *key, uint32_t key_len, uint8_t *value, uint32_t value_len) +{ + bool did_set = false; + + uint32_t hash = MAP_HASH(key, key_len); + 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) goto DONE; + } + + struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node)); + *(new_node) = (struct map_node){ .hash = hash, + .key = xmalloc(key_len), + .key_len = key_len, + .value = xmalloc(value_len), + .value_len = value_len, + .next = bucket->head }; + + // Copy Key and Value + memcpy(new_node->key, key, key_len); + memcpy(new_node->value, value, value_len); + + bucket->head = new_node; + did_set = true; + +DONE: + LOCK_UNLOCK(&bucket->lock); + return did_set; +} + +/** + * @returns boolean if node was deleted or not + */ +static inline bool +map_delete(struct map *map, uint8_t *key, uint32_t key_len) +{ + bool did_delete = false; + + uint32_t hash = MAP_HASH(key, key_len); + struct map_bucket *bucket = &map->buckets[hash % MAP_BUCKET_COUNT]; + LOCK_LOCK(&bucket->lock); + + struct map_node *prev = bucket->head; + if (prev != NULL && prev->hash == hash) { + bucket->head = prev->next; + free(prev->key); + free(prev->value); + free(prev); + did_delete = true; + goto DONE; + } + + for (struct map_node *node = prev->next; node != NULL; prev = node, node = node->next) { + prev->next = node->next; + free(node->key); + free(node->value); + free(node); + did_delete = true; + goto DONE; + } + +DONE: + LOCK_UNLOCK(&bucket->lock); + return did_delete; +} + +static inline void +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); + 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) { + node->value_len = value_len; + node->value = realloc(node->value, value_len); + assert(node->value); + memcpy(node->value, value, value_len); + goto DONE; + } + } + + struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node)); + + *(new_node) = (struct map_node){ .hash = hash, + .key = xmalloc(key_len), + .key_len = key_len, + .value = xmalloc(value_len), + .value_len = value_len, + .next = bucket->head }; + + assert(new_node->key); + assert(new_node->value); + + // Copy Key and Value + memcpy(new_node->key, key, key_len); + memcpy(new_node->value, value, value_len); + + bucket->head = new_node; + +DONE: + LOCK_UNLOCK(&bucket->lock); +} diff --git a/runtime/include/route_config.h b/runtime/include/route_config.h index 3a2dc6b..aeb214e 100644 --- a/runtime/include/route_config.h +++ b/runtime/include/route_config.h @@ -73,7 +73,6 @@ route_config_validate(struct route_config *config, bool *did_set) if (did_set[route_config_member_http_resp_content_type] == false) { debuglog("http_resp_content_type not set, defaulting to text/plain\n"); config->http_resp_content_type = "text/plain"; - return -1; } if (scheduler == SCHEDULER_EDF) { diff --git a/runtime/include/tenant.h b/runtime/include/tenant.h index 01977fc..06fa730 100644 --- a/runtime/include/tenant.h +++ b/runtime/include/tenant.h @@ -1,6 +1,7 @@ #pragma once #include "http_router.h" +#include "map.h" #include "module_database.h" #include "tcp_server.h" @@ -9,4 +10,5 @@ struct tenant { struct tcp_server tcp_server; http_router_t router; struct module_database module_db; + struct map scratch_storage; }; diff --git a/runtime/include/tenant_functions.h b/runtime/include/tenant_functions.h index cdf446c..89bb6f8 100644 --- a/runtime/include/tenant_functions.h +++ b/runtime/include/tenant_functions.h @@ -37,6 +37,7 @@ tenant_alloc(struct tenant_config *config) tcp_server_init(&tenant->tcp_server, config->port); http_router_init(&tenant->router, config->routes_len); module_database_init(&tenant->module_db); + map_init(&tenant->scratch_storage); for (int i = 0; i < config->routes_len; i++) { struct module *module = module_database_find_by_path(&tenant->module_db, config->routes[i].path); diff --git a/runtime/include/xmalloc.h b/runtime/include/xmalloc.h new file mode 100644 index 0000000..8449da0 --- /dev/null +++ b/runtime/include/xmalloc.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#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; +} diff --git a/runtime/src/sledge_abi.c b/runtime/src/sledge_abi.c index 5cdf918..6d1424a 100644 --- a/runtime/src/sledge_abi.c +++ b/runtime/src/sledge_abi.c @@ -1,4 +1,5 @@ #include "current_sandbox.h" +#include "map.h" #include "sandbox_set_as_running_sys.h" #include "sandbox_set_as_running_user.h" #include "sledge_abi.h" @@ -1039,3 +1040,126 @@ sledge_abi__wasi_snapshot_preview1_sock_shutdown(__wasi_fd_t fd, uint32_t how) { return wasi_unsupported_syscall(__func__); } + +/** + * @param key + * @param key_len + * @returns value_len at key or 0 if key not present + */ +EXPORT uint32_t +sledge_abi__scratch_storage_get_size(uint32_t key_offset, uint32_t key_len) +{ + struct sandbox *sandbox = current_sandbox_get(); + + sandbox_syscall(sandbox); + + uint8_t *key = (uint8_t *)get_memory_ptr_for_runtime(key_offset, key_len); + + uint32_t value_len; + map_get(&sandbox->tenant->scratch_storage, key, key_len, &value_len); + + sandbox_return(sandbox); + + return value_len; +} + +EXPORT int +sledge_abi__scratch_storage_get(uint32_t key_offset, uint32_t key_len, uint32_t buf_offset, uint32_t buf_len) +{ + int rc = 0; + + struct sandbox *sandbox = current_sandbox_get(); + + sandbox_syscall(sandbox); + + uint8_t *key = (uint8_t *)get_memory_ptr_for_runtime(key_offset, key_len); + uint8_t *buf = (uint8_t *)get_memory_ptr_for_runtime(buf_offset, buf_len); + + uint32_t value_len; + uint8_t *value = map_get(&sandbox->tenant->scratch_storage, key, key_len, &value_len); + + if (value == NULL) { + rc = 1; + goto DONE; + } else if (value_len > buf_len) { + rc = 2; + goto DONE; + } else { + memcpy(buf, value, value_len); + rc = 0; + } + +DONE: + sandbox_return(sandbox); + return rc; +} + +/** + * @param key_offset + * @param key_len + * @param value_offset + * @param value_len + * @returns 0 on success, 1 if already present, + */ +EXPORT int +sledge_abi__scratch_storage_set(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len) +{ + int rc = 0; + + struct sandbox *sandbox = current_sandbox_get(); + + sandbox_syscall(sandbox); + + uint8_t *key = (uint8_t *)get_memory_ptr_for_runtime(key_offset, key_len); + uint8_t *value = (uint8_t *)get_memory_ptr_for_runtime(value_offset, value_len); + + bool did_set = map_set(&sandbox->tenant->scratch_storage, key, key_len, value, value_len); + +DONE: + sandbox_return(sandbox); + return did_set ? 0 : 1; +} + +/** + * @param key_offset + * @param key_len + * @returns 0 on success, 1 if not present + */ +EXPORT int +sledge_abi__scratch_storage_delete(uint32_t key_offset, uint32_t key_len) +{ + int rc = 0; + + struct sandbox *sandbox = current_sandbox_get(); + + sandbox_syscall(sandbox); + + uint8_t *key = (uint8_t *)get_memory_ptr_for_runtime(key_offset, key_len); + + bool did_delete = map_delete(&sandbox->tenant->scratch_storage, key, key_len); + +DONE: + sandbox_return(sandbox); + return did_delete ? 0 : 1; +} + +/** + * @param key_offset + * @param key_len + * @param value_offset + * @param value_len + */ +EXPORT void +sledge_abi__scratch_storage_upsert(uint32_t key_offset, uint32_t key_len, uint32_t value_offset, uint32_t value_len) +{ + struct sandbox *sandbox = current_sandbox_get(); + + sandbox_syscall(sandbox); + + uint8_t *key = (uint8_t *)get_memory_ptr_for_runtime(key_offset, key_len); + uint8_t *value = (uint8_t *)get_memory_ptr_for_runtime(value_offset, value_len); + + map_upsert(&sandbox->tenant->scratch_storage, key, key_len, value, value_len); + + sandbox_return(sandbox); +} diff --git a/tests/scratch_storage/.gitignore b/tests/scratch_storage/.gitignore new file mode 100644 index 0000000..26cdcd9 --- /dev/null +++ b/tests/scratch_storage/.gitignore @@ -0,0 +1,3 @@ +res +perf.data +perf.data.old diff --git a/tests/scratch_storage/Makefile b/tests/scratch_storage/Makefile new file mode 100644 index 0000000..c4f42c2 --- /dev/null +++ b/tests/scratch_storage/Makefile @@ -0,0 +1,46 @@ +RUNTIME_DIR=../../runtime/ +SLEDGE_BINARY_DIR=${RUNTIME_DIR}/bin +SLEDGE_TESTS_DIR=${RUNTIME_DIR}/tests +HOSTNAME=localhost + +all: run + +clean: + make -C ${RUNTIME_DIR} clean + make -C ${SLEDGE_TESTS_DIR} clean + rm -f ${SLEDGE_BINARY_DIR}/html.wasm.so + +${SLEDGE_BINARY_DIR}/sledgert: + make -C ${RUNTIME_DIR} runtime + +.PHONY: sledgert +sledgert: ${SLEDGE_BINARY_DIR}/sledgert + +${SLEDGE_BINARY_DIR}/scratch_storage.wasm.so: + make -C ../../applications scratch_storage.install + +.PHONY: scratch_storage_get +scratch_storage_get: ${SLEDGE_BINARY_DIR}/scratch_storage_get.wasm.so + +.PHONY: scratch_storage_set +scratch_storage_set: ${SLEDGE_BINARY_DIR}/scratch_storage_set.wasm.so + +run: sledgert scratch_storage_get scratch_storage_set + LD_LIBRARY_PATH=${SLEDGE_BINARY_DIR} ${SLEDGE_BINARY_DIR}/sledgert spec.json + +debug: sledgert scratch_storage_get scratch_storage_set + SLEDGE_DISABLE_PREEMPTION=true SLEDGE_NWORKERS=1 \ + LD_LIBRARY_PATH=${SLEDGE_BINARY_DIR} gdb ${SLEDGE_BINARY_DIR}/sledgert \ + --eval-command="handle SIGUSR1 noprint nostop" \ + --eval-command="handle SIGPIPE noprint nostop" \ + --eval-command="set pagination off" \ + --eval-command="run spec.json" + +client-upsert-multi: + hey -z 6s -cpus 4 -c 100 -t 0 -o csv -m GET "http://${HOSTNAME}:1337/upsert?test&wakka2" + +client-get-multi: + hey -z 6s -cpus 4 -c 100 -t 0 -o csv -m GET "http://${HOSTNAME}:1337/get?test" + +client: + http :1337/scratch_storage diff --git a/tests/scratch_storage/edf_nopreemption.env b/tests/scratch_storage/edf_nopreemption.env new file mode 100644 index 0000000..eeba531 --- /dev/null +++ b/tests/scratch_storage/edf_nopreemption.env @@ -0,0 +1,2 @@ +SLEDGE_SCHEDULER=EDF +SLEDGE_DISABLE_PREEMPTION=true diff --git a/tests/scratch_storage/edf_preemption.env b/tests/scratch_storage/edf_preemption.env new file mode 100644 index 0000000..302a324 --- /dev/null +++ b/tests/scratch_storage/edf_preemption.env @@ -0,0 +1,3 @@ +SLEDGE_SCHEDULER=EDF +SLEDGE_DISABLE_PREEMPTION=false +SLEDGE_SIGALRM_HANDLER=TRIAGED diff --git a/tests/scratch_storage/fifo_nopreemption.env b/tests/scratch_storage/fifo_nopreemption.env new file mode 100644 index 0000000..a572a70 --- /dev/null +++ b/tests/scratch_storage/fifo_nopreemption.env @@ -0,0 +1,2 @@ +SLEDGE_SCHEDULER=FIFO +SLEDGE_DISABLE_PREEMPTION=true diff --git a/tests/scratch_storage/fifo_preemption.env b/tests/scratch_storage/fifo_preemption.env new file mode 100644 index 0000000..eb1298f --- /dev/null +++ b/tests/scratch_storage/fifo_preemption.env @@ -0,0 +1,2 @@ +SLEDGE_SCHEDULER=FIFO +SLEDGE_DISABLE_PREEMPTION=false diff --git a/tests/scratch_storage/install.sh b/tests/scratch_storage/install.sh new file mode 100755 index 0000000..0cbcfe8 --- /dev/null +++ b/tests/scratch_storage/install.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if ! command -v hey > /dev/null; then + HEY_URL=https://hey-release.s3.us-east-2.amazonaws.com/hey_linux_amd64 + wget $HEY_URL -O hey + chmod +x hey + + if [[ $(whoami) == "root" ]]; then + mv hey /usr/bin/hey + else + sudo mv hey /usr/bin/hey + fi +fi diff --git a/tests/scratch_storage/spec.json b/tests/scratch_storage/spec.json new file mode 100644 index 0000000..79ee5d1 --- /dev/null +++ b/tests/scratch_storage/spec.json @@ -0,0 +1,44 @@ +[ + { + "name": "gwu", + "port": 1337, + "routes": [ + { + "route": "/set", + "path": "scratch_storage_set.wasm.so", + "expected-execution-us": 10000000, + "admissions-percentile": 70, + "relative-deadline-us": 20000000, + "http-resp-content-type": "text/plain", + "http-resp-size": 1024 + }, + { + "route": "/get", + "path": "scratch_storage_get.wasm.so", + "expected-execution-us": 10000000, + "admissions-percentile": 70, + "relative-deadline-us": 20000000, + "http-resp-content-type": "text/plain", + "http-resp-size": 1024 + }, + { + "route": "/delete", + "path": "scratch_storage_delete.wasm.so", + "expected-execution-us": 10000000, + "admissions-percentile": 70, + "relative-deadline-us": 20000000, + "http-resp-content-type": "text/plain", + "http-resp-size": 1024 + }, + { + "route": "/upsert", + "path": "scratch_storage_upsert.wasm.so", + "expected-execution-us": 10000000, + "admissions-percentile": 70, + "relative-deadline-us": 20000000, + "http-resp-content-type": "text/plain", + "http-resp-size": 1024 + } + ] + } +]