1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
#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;
}
|