#include "file.h" #include "file_common.h" static void file_backing_lock(struct cch_backing *backing) { struct cch_backing_file *file = (struct cch_backing_file *)backing; nn_mutex_lock(&file->mutex); } static void file_backing_write(struct cch_backing *backing, u8 *buf, off_t index, size_t *count) { struct cch_backing_file *file = (struct cch_backing_file *)backing; off_t n = (off_t)*count; nn_mutex_lock(&file->mutex); off_t size = file->backing.size; if (size > 0 && index + n >= size) { n = MAX(size - index, (off_t)0); } if (n > 0) { al_memcpy(file->u.map + index, buf, n); cch_backing_fill_range(&file->backing, index, n); } *count = (size_t)n; nn_mutex_unlock(&file->mutex); } static u8 *file_backing_get_ptr(struct cch_backing *backing, off_t index, size_t *count) { struct cch_backing_file *file = (struct cch_backing_file *)backing; off_t n = (off_t)*count; nn_mutex_lock(&file->mutex); off_t size = file->backing.size; if (size > 0 && index + n >= size) { n = MAX(size - index, (off_t)0); } *count = (size_t)n; 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; nn_mutex_unlock(&file->mutex); } static void file_backing_set_size(struct cch_backing *backing, off_t size, bool expand_to_size) { struct cch_backing_file *file = (struct cch_backing_file *)backing; al_assert(expand_to_size || size == 0); nn_mutex_lock(&file->mutex); file->backing.size = size; if ((size_t)size > file->file.size) { nn_file_munmap(&file->file, file->u.map); nn_file_truncate(&file->file, size); file->u.map = nn_file_mmap(&file->file); file->file.size = size; } nn_mutex_unlock(&file->mutex); } static void file_backing_free(struct cch_backing **backing) { struct cch_backing_file *file = (struct cch_backing_file *)*backing; nn_file_munmap(&file->file, file->u.map); nn_file_close(&file->file); al_array_free(file->backing.available); 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 = CACHE_BACKING_MAPPED; file->backing.size = -1; file->backing.lock = file_backing_lock; file->backing.write = file_backing_write; file->backing.read = NULL; file->backing.get_ptr = file_backing_get_ptr; file->backing.unlock = file_backing_unlock; file->backing.set_size = file_backing_set_size; file->backing.get_size_if_known = file_backing_get_size_if_known; file->backing.finalize = file_backing_finalize; file->backing.free = file_backing_free; al_array_init(file->backing.available); if (!file_open_internal(file, path, size)) { goto err; } if (!(file->u.map = nn_file_mmap(&file->file))) { nn_file_close(&file->file); goto err; } nn_mutex_init(&file->mutex); return (struct cch_backing *)file; err: al_free(file); return NULL; }