diff --git a/lsm/Makefile b/lsm/Makefile new file mode 100644 index 0000000..5352623 --- /dev/null +++ b/lsm/Makefile @@ -0,0 +1,95 @@ +# https://spin.atomicobject.com/2016/08/26/makefile-c-projects/ was a great +# base for this Makefile + +-include config.mk + +LIB := $(BUILD_DIR)/$(LIB_FILENAME) + +SRCS != find '$(SRC_DIR)' -iname '*.c' +SRCS_H != find $(INC_DIRS) -iname '*.h' +SRCS_H_INTERNAL != find $(SRC_DIR) -iname '*.h' +SRCS_TEST != find '$(TEST_DIR)' -iname '*.c' + +OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) +OBJS_TEST := $(SRCS_TEST:%=$(BUILD_DIR)/%.o) +DEPS := $(SRCS:%=$(BUILD_DIR)/%.d) $(SRCS_TEST:%=$(BUILD_DIR)/%.d) + +BINS_TEST := $(OBJS_TEST:%.c.o=%) +TARGETS_TEST := $(BINS_TEST:%=test-%) +TARGETS_MEM_TEST := $(BINS_TEST:%=test-mem-%) + +_CFLAGS := $(addprefix -I,$(INC_DIRS)) $(CFLAGS) -Wall -Wextra + +.PHONY: all +all: lib + + +# =====COMPILATION===== +# Utility used by the CI to lint +.PHONY: objs +objs: $(OBJS) + +.PHONY: lib +lib: $(LIB) +$(LIB): $(OBJS) + ar -rcs $@ $(OBJS) + +$(BUILD_DIR)/$(SRC_DIR)/%.c.o: $(SRC_DIR)/%.c + mkdir -p $(dir $@) + $(CC) -c $(_CFLAGS) $< -o $@ + + +# =====TESTING===== +.PHONY: test +test: $(TARGETS_TEST) + +.PHONY: test-mem +test-mem: $(TARGETS_MEM_TEST) + +.PHONY: $(TARGETS_TEST) +$(TARGETS_TEST): test-%: % + ./$^ + +.PHONY: $(TARGETS_MEM_TEST) +$(TARGETS_MEM_TEST): test-mem-%: % + valgrind --tool=memcheck --error-exitcode=1 --track-origins=yes --leak-check=full ./$^ + +.PHONY: build-test +build-test: $(BINS_TEST) + +$(BINS_TEST): %: %.c.o $(LIB) + $(CC) \ + $^ -o $@ + +# Along with the include directory, each test includes $(TEST_DIR) (which +# contains the acutest.h header file), and the src directory of the module it's +# testing. This allows tests to access internal methods, which aren't publicly +# exposed. +$(BUILD_DIR)/$(TEST_DIR)/%.c.o: $(TEST_DIR)/%.c + mkdir -p $(dir $@) + $(CC) $(_CFLAGS) -I$(TEST_DIR) \ + -I$(dir $(@:$(BUILD_DIR)/$(TEST_DIR)/%=$(SRC_DIR)/%)) \ + -c $< -o $@ + +# =====MAINTENANCE===== +.PHONY: lint +lint: + clang-format -n --Werror $(SRCS) $(SRCS_H) $(SRCS_H_INTERNAL) + +.PHONY: fmt +fmt: + clang-format -i $(SRCS) $(SRCS_H) $(SRCS_H_INTERNAL) + +.PHONY: clean +clean: + rm -rf $(BUILD_DIR) + + +.PHONY: bear +bear: clean + bear -- make + bear --append -- make build-test + + +# Make make aware of the .d files +-include $(DEPS) diff --git a/lsm/config.mk b/lsm/config.mk new file mode 100644 index 0000000..c453c6a --- /dev/null +++ b/lsm/config.mk @@ -0,0 +1,13 @@ +LIB_FILENAME = liblsm.a + +BUILD_DIR = build +SRC_DIR = src +TEST_DIR = test +INC_DIRS = include + +# -MMD: generate a .d file for every source file. This file can be imported by +# make and makes make aware that a header file has been changed, ensuring an +# object file is also recompiled if only a header is changed. +# -MP: generate a dummy target for every header file (according to the docs it +# prevents some errors when removing header files) +CFLAGS = -MMD -MP -g diff --git a/lsm/include/lsm.h b/lsm/include/lsm.h new file mode 100644 index 0000000..838e8e9 --- /dev/null +++ b/lsm/include/lsm.h @@ -0,0 +1,47 @@ +#include + +/** + * Represents a string (or really any kind of data) with a known length. Data + * with length 8 or less is stored inside the pointer instead of needlessly + * allocating additional memory. + */ +typedef struct lsm_string { + uint64_t len; + union { + void *ptr; + char val[8]; + } str; +} lsm_string; + +typedef enum lsm_attr_type { + lsm_attr_type_entry_type = 0 +} lsm_attr_type; + +typedef struct lsm_attr { + lsm_attr_type type; + lsm_string str; +} lsm_attr; + +/** + * Represents a collection of metadata objects + */ +typedef struct lsm_attr_list { + uint64_t count; + lsm_attr *items; +} lsm_attr_list; + +/** + * An entry inside + */ +typedef struct lsm_entry { + lsm_string key; + lsm_attr_list attrs; + lsm_string data; +} lsm_entry; + +/** + * A store of entries, which manages its data both in-memory and on disk. + */ +typedef struct lsm_store { + +} lsm_store; diff --git a/src/main.c b/src/main.c index fa9d95e..f32f83f 100644 --- a/src/main.c +++ b/src/main.c @@ -27,7 +27,7 @@ int main() { int port = atoi(port_str); - if (port <= 0 || port >= 2 << 16) { + if (port <= 0 || port >= 1 << 16) { critical(1, "Invalid TCP port %s", port_str); }