diff options
Diffstat (limited to 'src/cache/backings')
| -rw-r--r-- | src/cache/backings/file.c | 75 | ||||
| -rw-r--r-- | src/cache/backings/file.h | 22 | ||||
| -rw-r--r-- | src/cache/backings/file_common.c | 23 | ||||
| -rw-r--r-- | src/cache/backings/file_mapped.c | 81 | ||||
| -rw-r--r-- | src/cache/backings/memory.c | 82 | ||||
| -rw-r--r-- | src/cache/backings/memory.h | 16 |
6 files changed, 299 insertions, 0 deletions
diff --git a/src/cache/backings/file.c b/src/cache/backings/file.c new file mode 100644 index 0000000..4c5f344 --- /dev/null +++ b/src/cache/backings/file.c @@ -0,0 +1,75 @@ +#include "file.h" +#include "file_common.c" + +static void file_backing_write(struct cch_backing *backing, u8 *buf, off_t index, size_t *size) +{ + struct cch_backing_file *file = (struct cch_backing_file *)backing; + aki_mutex_lock(&file->mutex); + if (file->u.pointer != index) { + file->u.pointer = aki_file_seek(&file->file, index, SEEK_SET); + al_assert(file->u.pointer == index); + } + if (file->size >= 0 && index + ((off_t)*size) >= file->size) { + *size = file->size - index; + } + aki_file_write(&file->file, buf, *size); + file->u.pointer += *size; + aki_mutex_unlock(&file->mutex); +} + +static void file_backing_read(struct cch_backing *backing, u8 *buf, off_t index, size_t *size) +{ + struct cch_backing_file *file = (struct cch_backing_file *)backing; + aki_mutex_lock(&file->mutex); + if (file->u.pointer != index) { + file->u.pointer = aki_file_seek(&file->file, index, SEEK_SET); + al_assert(file->u.pointer == index); + } + if (file->size >= 0 && index + ((off_t)*size) >= file->size) { + *size = file->size - index; + } + aki_file_read(&file->file, buf, *size); + file->u.pointer += *size; + aki_mutex_unlock(&file->mutex); +} + +static void file_backing_resize(struct cch_backing *backing, size_t size) +{ + struct cch_backing_file *file = (struct cch_backing_file *)backing; + aki_mutex_lock(&file->mutex); + file->size = size; + if ((off_t)size > file->filesize) { + aki_file_truncate(&file->file, size); + file->filesize = size; + } + aki_mutex_unlock(&file->mutex); +} + +static void file_backing_free(struct cch_backing **backing) +{ + struct cch_backing_file *file = (struct cch_backing_file *)*backing; + aki_file_close(&file->file); + al_free(file); + *backing = NULL; +} + +struct cch_backing *cch_backing_file_create(str *path, size_t size) +{ + struct cch_backing_file *file = al_alloc_object(struct cch_backing_file); + file->backing.mode = CCH_BACKING_READ; + file->backing.write = file_backing_write; + file->backing.read = file_backing_read; + file->backing.get_ptr = NULL; + file->backing.unlock = NULL; + file->backing.get_mmap = NULL; + file->backing.get_size_estimate = file_backing_get_size_estimate; + file->backing.resize = file_backing_resize; + file->backing.free = file_backing_free; + if (!file_open_internal(file, path, size)) { + al_free(file); + return NULL; + } + file->u.pointer = 0; + aki_mutex_init(&file->mutex); + return (struct cch_backing *)file; +} diff --git a/src/cache/backings/file.h b/src/cache/backings/file.h new file mode 100644 index 0000000..9794bbb --- /dev/null +++ b/src/cache/backings/file.h @@ -0,0 +1,22 @@ +#pragma once + +#include <al/str.h> +#include <aki/thread.h> +#include <aki/common.h> +#include <aki/file.h> + +#include "../backing.h" + +struct cch_backing_file { + struct cch_backing backing; + struct aki_file file; + off_t size; + off_t filesize; + union { + void *map; // CCH_BACKING_MAPPED + off_t pointer; // CCH_BACKING_READ + } u; + struct aki_mutex mutex; +}; + +struct cch_backing *cch_backing_file_create(str *path, size_t filesize); diff --git a/src/cache/backings/file_common.c b/src/cache/backings/file_common.c new file mode 100644 index 0000000..c0b54c0 --- /dev/null +++ b/src/cache/backings/file_common.c @@ -0,0 +1,23 @@ +static off_t file_backing_get_size_estimate(struct cch_backing *backing) +{ + struct cch_backing_file *file = (struct cch_backing_file *)backing; + aki_mutex_lock(&file->mutex); + off_t size = file->size; + aki_mutex_unlock(&file->mutex); + return size; +} + +static bool file_open_internal(struct cch_backing_file *file, str *path, size_t size) +{ + if (!aki_file_open(&file->file, path, size != 0)) return false; + file->filesize = aki_file_get_filesize(&file->file); + if (!size) { + file->size = file->filesize; + } else { + file->size = -1; + if (file->filesize < (off_t)size) { + aki_file_truncate(&file->file, size); + } + } + return true; +} diff --git a/src/cache/backings/file_mapped.c b/src/cache/backings/file_mapped.c new file mode 100644 index 0000000..1b06ad2 --- /dev/null +++ b/src/cache/backings/file_mapped.c @@ -0,0 +1,81 @@ +#include "file.h" +#include "file_common.c" + +static void file_backing_write(struct cch_backing *backing, u8 *buf, off_t index, size_t *size) +{ + struct cch_backing_file *file = (struct cch_backing_file *)backing; + aki_mutex_lock(&file->mutex); + if (file->size >= 0 && index + ((off_t)*size) >= file->size) { + *size = file->size - index; + } + al_memcpy(file->u.map + index, buf, *size); + aki_mutex_unlock(&file->mutex); +} + +static u8 *file_backing_get_ptr(struct cch_backing *backing, off_t index, size_t *size) +{ + struct cch_backing_file *file = (struct cch_backing_file *)backing; + aki_mutex_lock(&file->mutex); + if (file->size >= 0 && index + ((off_t)*size) >= file->size) { + *size = file->size - index; + } + return (u8 *)(file->u.map + index); +} + +static void file_backing_unlock(struct cch_backing *backing) +{ + struct cch_backing_file *file = (struct cch_backing_file *)backing; + aki_mutex_unlock(&file->mutex); +} + +static void *file_backing_get_mmap(struct cch_backing *backing) +{ + struct cch_backing_file *file = (struct cch_backing_file *)backing; + aki_mutex_lock(&file->mutex); + void *map = file->u.map; + aki_mutex_unlock(&file->mutex); + return map; +} + +static void file_backing_resize(struct cch_backing *backing, size_t size) +{ + struct cch_backing_file *file = (struct cch_backing_file *)backing; + aki_mutex_lock(&file->mutex); + file->size = size; + if ((off_t)size > file->filesize) { + file->u.map = aki_file_mremap(&file->file, size, file->u.map); + aki_file_truncate(&file->file, size); + file->filesize = size; + } + aki_mutex_unlock(&file->mutex); +} + +static void file_backing_free(struct cch_backing **backing) +{ + struct cch_backing_file *file = (struct cch_backing_file *)*backing; + aki_file_munmap(&file->file, file->u.map); + aki_file_close(&file->file); + al_free(file); + *backing = NULL; +} + +struct cch_backing *cch_backing_file_create(str *path, size_t size) +{ + struct cch_backing_file *file = al_alloc_object(struct cch_backing_file); + file->backing.mode = CCH_BACKING_MAPPED; + file->backing.write = file_backing_write; + file->backing.read = NULL; + file->backing.get_mmap = file_backing_get_mmap; + file->backing.get_ptr = file_backing_get_ptr; + file->backing.unlock = file_backing_unlock; + file->backing.get_size_estimate = file_backing_get_size_estimate; + file->backing.resize = file_backing_resize; + file->backing.free = file_backing_free; + if (!file_open_internal(file, path, size)) { + al_free(file); + return NULL; + } + file->u.map = aki_file_mmap(&file->file); + aki_mutex_init(&file->mutex); + return (struct cch_backing *)file; +} diff --git a/src/cache/backings/memory.c b/src/cache/backings/memory.c new file mode 100644 index 0000000..194d66c --- /dev/null +++ b/src/cache/backings/memory.c @@ -0,0 +1,82 @@ +#include "memory.h" + +static void ensure_alloced(struct cch_backing_memory *mem, size_t size) +{ + if (size > mem->alloc) { + mem->data = al_realloc(mem->data, size); + mem->alloc = size; + } +} + +static void memory_backing_write(struct cch_backing *backing, u8 *buf, off_t index, size_t *size) +{ + struct cch_backing_memory *mem = (struct cch_backing_memory *)backing; + aki_mutex_lock(&mem->mutex); + if (mem->size >= 0 && index + ((off_t)*size) >= mem->size) { + *size = mem->size - index; + } + ensure_alloced(mem, index + *size); + al_memcpy(mem->data + index, buf, *size); + aki_mutex_unlock(&mem->mutex); +} + +static u8 *memory_backing_get_ptr(struct cch_backing *backing, off_t index, size_t *size) +{ + struct cch_backing_memory *mem = (struct cch_backing_memory *)backing; + aki_mutex_lock(&mem->mutex); + if (mem->size >= 0 && index + ((off_t)*size) >= mem->size) { + *size = mem->size - index; + } + return (u8 *)(mem->data + index); +} + +static void memory_backing_unlock(struct cch_backing *backing) +{ + struct cch_backing_memory *mem = (struct cch_backing_memory *)backing; + aki_mutex_unlock(&mem->mutex); +} + +static off_t memory_backing_get_size_estimate(struct cch_backing *backing) +{ + struct cch_backing_memory *mem = (struct cch_backing_memory *)backing; + aki_mutex_lock(&mem->mutex); + off_t size = mem->size; + aki_mutex_unlock(&mem->mutex); + return size; +} + +static void memory_backing_resize(struct cch_backing *backing, size_t size) +{ + struct cch_backing_memory *mem = (struct cch_backing_memory *)backing; + aki_mutex_lock(&mem->mutex); + ensure_alloced(mem, size); + mem->size = size; + aki_mutex_unlock(&mem->mutex); +} + +static void memory_backing_free(struct cch_backing **backing) +{ + struct cch_backing_memory *mem = (struct cch_backing_memory *)*backing; + al_free(mem->data); + aki_mutex_destroy(&mem->mutex); + al_free(mem); + *backing = NULL; +} + +struct cch_backing *cch_backing_memory_create(size_t size) +{ + struct cch_backing_memory *mem = al_alloc_object(struct cch_backing_memory); + mem->backing.mode = CCH_BACKING_MAPPED; + mem->backing.write = memory_backing_write; + mem->backing.get_mmap = NULL; + mem->backing.get_ptr = memory_backing_get_ptr; + mem->backing.unlock = memory_backing_unlock; + mem->backing.get_size_estimate = memory_backing_get_size_estimate; + mem->backing.resize = memory_backing_resize; + mem->backing.free = memory_backing_free; + mem->data = al_malloc(size); + mem->alloc = size; + mem->size = -1; + aki_mutex_init(&mem->mutex); + return (struct cch_backing *)mem; +} diff --git a/src/cache/backings/memory.h b/src/cache/backings/memory.h new file mode 100644 index 0000000..107ae4b --- /dev/null +++ b/src/cache/backings/memory.h @@ -0,0 +1,16 @@ +#pragma once + +#include <al/lib.h> +#include <aki/thread.h> + +#include "../backing.h" + +struct cch_backing_memory { + struct cch_backing backing; + u8 *data; + size_t alloc; + off_t size; + struct aki_mutex mutex; +}; + +struct cch_backing *cch_backing_memory_create(size_t size); |