summaryrefslogtreecommitdiff
path: root/src/cache/backings
diff options
context:
space:
mode:
Diffstat (limited to 'src/cache/backings')
-rw-r--r--src/cache/backings/file.c75
-rw-r--r--src/cache/backings/file.h22
-rw-r--r--src/cache/backings/file_common.c23
-rw-r--r--src/cache/backings/file_mapped.c81
-rw-r--r--src/cache/backings/memory.c82
-rw-r--r--src/cache/backings/memory.h16
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);