author | Tero Marttila <terom@fixme.fi> |
Sat, 30 Aug 2008 19:13:15 +0300 | |
changeset 49 | 10c7dce1a043 |
parent 37 | f0188b445c84 |
permissions | -rw-r--r-- |
31 | 1 |
#define _GNU_SOURCE |
2 |
#include <sys/types.h> |
|
3 |
#include <unistd.h> |
|
4 |
#include <sys/mman.h> |
|
5 |
#include <sys/stat.h> |
|
6 |
#include <stdlib.h> |
|
7 |
#include <sys/param.h> |
|
8 |
#include <stdio.h> |
|
9 |
#include <fcntl.h> |
|
10 |
#include <errno.h> |
|
11 |
#include <assert.h> |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
12 |
|
31 | 13 |
#include "../../cache.h" |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
14 |
#include "../cache.h" |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
15 |
#include "../engine.h" |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
16 |
#include "../op.h" |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
17 |
#include "../../common.h" |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
18 |
|
31 | 19 |
#define FS_PAGE_SIZE (4096) |
20 |
#define FS_INITIAL_SIZE (1 * FS_PAGE_SIZE) |
|
21 |
#define FS_PAGE_GROW_FACTOR (2) |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
22 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
23 |
struct cache_engine_fs { |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
24 |
struct cache_engine base; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
25 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
26 |
// custom stuff |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
27 |
const char *cache_dir; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
28 |
}; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
29 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
30 |
struct cache_fs { |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
31 |
struct cache base; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
32 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
33 |
// custom stuff? |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
34 |
}; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
35 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
36 |
struct cache_op_fs { |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
37 |
struct cache_op base; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
38 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
39 |
// custom |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
40 |
int fd; |
33 | 41 |
|
37 | 42 |
// what kind of access... PROT_READ | PROT_WRITE or PROT_READ |
43 |
int mmap_prot; |
|
44 |
||
33 | 45 |
/* |
46 |
* Either contains the final size of the cache entry, or zero. |
|
47 |
*/ |
|
48 |
off_t size; |
|
37 | 49 |
|
50 |
/* |
|
51 |
* Contains the size of the underlying file. Usually this is the same as mmap_size. |
|
52 |
*/ |
|
53 |
off_t file_size; |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
54 |
|
33 | 55 |
/* |
56 |
* Contains the size of the currently mmap'd region |
|
57 |
*/ |
|
58 |
off_t mmap_size; |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
59 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
60 |
void *mmap; |
31 | 61 |
|
62 |
off_t write_offset; |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
63 |
}; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
64 |
|
37 | 65 |
#define FS_OP_DATA_SIZE(op) (op->size ? op->size : op->write_offset) |
66 |
||
31 | 67 |
/* |
33 | 68 |
* if new_size is equal to op->mmap_size, nothing will be changed |
31 | 69 |
*/ |
70 |
static int _fs_mmap (struct cache_op_fs *op, size_t new_size) { |
|
71 |
assert(new_size > 0); |
|
37 | 72 |
|
73 |
// resize file? |
|
74 |
if (new_size != op->file_size) { |
|
75 |
// new size |
|
76 |
op->file_size = new_size; |
|
31 | 77 |
|
78 |
// and ftruncate |
|
37 | 79 |
if (ftruncate(op->fd, op->file_size)) |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
80 |
PERROR("ftruncate"); |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
81 |
} |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
82 |
|
37 | 83 |
// create mmap, or resize? |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
84 |
if (op->mmap) { |
37 | 85 |
assert(op->mmap_size > 0); |
86 |
||
87 |
// resize mmap? |
|
88 |
if (op->mmap_size != new_size) { |
|
89 |
if ((op->mmap = mremap(op->mmap, new_size, op->mmap_size, MREMAP_MAYMOVE)) == MAP_FAILED) |
|
90 |
PERROR("mremap"); |
|
91 |
||
92 |
op->mmap_size = new_size; |
|
93 |
} |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
94 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
95 |
} else { |
37 | 96 |
// do new mmap |
97 |
op->mmap_size = new_size; |
|
98 |
||
99 |
if ((op->mmap = mmap(NULL, op->mmap_size, op->mmap_prot, MAP_SHARED | MAP_POPULATE, op->fd, 0)) == MAP_FAILED) |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
100 |
PERROR("mmap"); |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
101 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
102 |
} |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
103 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
104 |
return 0; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
105 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
106 |
error: |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
107 |
return -1; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
108 |
} |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
109 |
|
31 | 110 |
/* |
111 |
* reuturn a pointer to a static buf containing the path to the key in the given op |
|
112 |
*/ |
|
113 |
static const char *_fs_path (struct cache_engine_fs *engine, struct cache_op_fs *op) { |
|
114 |
static char path[PATH_MAX]; |
|
115 |
||
116 |
struct cache_key *key = op->base.key; |
|
117 |
||
118 |
// construct the path to the appropriate file |
|
119 |
if (snprintf(path, PATH_MAX, "%s/%*s", engine->cache_dir, (int) key->length - 1, key->buf) >= PATH_MAX) |
|
120 |
ERROR("path too long: %s/%*s", engine->cache_dir, (int) key->length - 1, key->buf); |
|
121 |
||
122 |
return path; |
|
123 |
||
124 |
error: |
|
125 |
return NULL; |
|
126 |
} |
|
127 |
||
128 |
/* |
|
129 |
* Grow the file if needed so that it fits the given amount of bytes |
|
130 |
*/ |
|
131 |
static int _fs_grow (struct cache_op_fs *op, size_t new_size_hint) { |
|
33 | 132 |
if (op->mmap_size >= new_size_hint) |
31 | 133 |
return 0; |
134 |
||
135 |
// XXX: need some math.ceil |
|
33 | 136 |
size_t new_size = ((op->mmap_size / FS_PAGE_SIZE) + 1) * FS_PAGE_SIZE; |
31 | 137 |
|
138 |
while (new_size < new_size_hint) { |
|
139 |
new_size *= FS_PAGE_GROW_FACTOR; |
|
140 |
} |
|
141 |
||
142 |
return _fs_mmap(op, new_size); |
|
143 |
} |
|
144 |
||
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
145 |
static int _fs_do_init (struct cache_engine *engine, struct cache **cache_ptr) { |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
146 |
struct cache_engine_fs *ctx = (struct cache_engine_fs *) engine; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
147 |
struct cache_fs *cache = NULL; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
148 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
149 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
150 |
if ((cache = calloc(1, sizeof(*cache))) == NULL) |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
151 |
ERROR("calloc"); |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
152 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
153 |
if (cache_init(&cache->base, &ctx->base)) |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
154 |
goto error; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
155 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
156 |
*cache_ptr = &cache->base; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
157 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
158 |
return 0; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
159 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
160 |
error: |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
161 |
free(cache); |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
162 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
163 |
return -1; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
164 |
} |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
165 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
166 |
static int _fs_do_op_start (struct cache *cache, struct cache_op **op_ptr, struct cache_key *key) { |
31 | 167 |
struct cache_engine_fs *engine = (struct cache_engine_fs *) cache->engine; |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
168 |
struct cache_op_fs *op = NULL; |
31 | 169 |
struct stat stat_info; |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
170 |
int found = 0; |
31 | 171 |
const char *path; |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
172 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
173 |
// allocate it |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
174 |
if ((op = calloc(1, sizeof(*op))) == NULL) |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
175 |
ERROR("calloc"); |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
176 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
177 |
// init it |
36
b4023990811e
rename/clean up states slightly and add lots of documentation
Tero Marttila <terom@fixme.fi>
parents:
33
diff
changeset
|
178 |
if (_cache_op_init(&op->base, cache, key)) |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
179 |
goto error; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
180 |
|
31 | 181 |
// mark it as being in the lookup state... |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
182 |
op->base.state = OP_STATE_LOOKUP; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
183 |
|
31 | 184 |
// fetch the path |
185 |
if ((path = _fs_path(engine, op)) == NULL) |
|
186 |
goto error; |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
187 |
|
31 | 188 |
// stat |
189 |
if (stat(path, &stat_info)) { |
|
33 | 190 |
if (errno == ENOENT) { |
31 | 191 |
found = 0; |
33 | 192 |
// op->size remains 0 |
193 |
} else |
|
31 | 194 |
PERROR("stat: %s", path); |
33 | 195 |
} else { |
31 | 196 |
found = 1; |
37 | 197 |
op->file_size = stat_info.st_size; |
33 | 198 |
} |
31 | 199 |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
200 |
// indicate that the key was found/not found |
36
b4023990811e
rename/clean up states slightly and add lots of documentation
Tero Marttila <terom@fixme.fi>
parents:
33
diff
changeset
|
201 |
if (_cache_op_lookup_done(&op->base, found)) |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
202 |
goto error; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
203 |
|
31 | 204 |
*op_ptr = &op->base; |
205 |
||
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
206 |
// done! |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
207 |
return 0; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
208 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
209 |
error: |
31 | 210 |
free(op); |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
211 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
212 |
return -1; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
213 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
214 |
} |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
215 |
|
33 | 216 |
int _fs_do_op_available (struct cache_op *op_base, size_t *size, size_t *offset) { |
217 |
struct cache_op_fs *op = (struct cache_op_fs *) op_base; |
|
218 |
||
219 |
// this is easy, it's only known if a HIT, or after op_done, so it's the same as... |
|
220 |
*size = op->size; |
|
221 |
||
222 |
// op->size if nonzero, write_offset otherwise |
|
223 |
*offset = op->size ? op->size : op->write_offset; |
|
224 |
||
225 |
return 0; |
|
226 |
} |
|
227 |
||
37 | 228 |
int _fs_do_op_begin_read (struct cache_op *op_base) { |
229 |
struct cache_op_fs *op = (struct cache_op_fs *) op_base; |
|
230 |
struct cache_engine_fs *engine = (struct cache_engine_fs *) op->base.cache->engine; |
|
231 |
||
232 |
const char *path; |
|
233 |
||
234 |
// should be known (nonzero) for HITs that we read from |
|
235 |
assert(op->file_size > 0); |
|
236 |
||
237 |
// fetch the path |
|
238 |
if ((path = _fs_path(engine, op)) == NULL) |
|
239 |
goto error; |
|
240 |
||
241 |
// create the appropriate file for read-write, exclusively |
|
242 |
if ((op->fd = open(path, O_RDONLY)) == -1) |
|
243 |
PERROR("open: %s", path); |
|
244 |
||
245 |
{ |
|
246 |
struct stat stat_info; |
|
247 |
||
248 |
// assert size hasn't changed |
|
249 |
if (fstat(op->fd, &stat_info)) |
|
250 |
PERROR("fstat"); |
|
251 |
||
252 |
assert(stat_info.st_size == op->file_size); |
|
253 |
} |
|
254 |
||
255 |
// assign exact size |
|
256 |
op->size = op->file_size; |
|
257 |
||
258 |
// read-only access |
|
259 |
op->mmap_prot = PROT_READ; |
|
260 |
||
261 |
// doesn't ftruncate, just mmap's |
|
262 |
if (_fs_mmap(op, op->size)) |
|
263 |
goto error; |
|
264 |
||
265 |
// great |
|
266 |
if (_cache_op_read_ready(&op->base)) |
|
267 |
goto error; |
|
268 |
||
269 |
// done |
|
270 |
return 0; |
|
271 |
||
272 |
error: |
|
273 |
return -1; |
|
274 |
} |
|
275 |
||
31 | 276 |
int _fs_do_op_begin_write (struct cache_op *op_base, size_t size_hint) { |
277 |
struct cache_op_fs *op = (struct cache_op_fs *) op_base; |
|
278 |
struct cache_engine_fs *engine = (struct cache_engine_fs *) op->base.cache->engine; |
|
279 |
||
280 |
const char *path; |
|
281 |
||
282 |
assert(size_hint >= 0); |
|
283 |
||
37 | 284 |
// should be unknown (0) for MISS's that we then write to |
33 | 285 |
assert(op->size == 0); |
31 | 286 |
|
287 |
// fetch the path |
|
288 |
if ((path = _fs_path(engine, op)) == NULL) |
|
289 |
goto error; |
|
290 |
||
291 |
// create the appropriate file for read-write, exclusively |
|
292 |
if ((op->fd = open(path, O_CREAT | O_RDWR | O_EXCL, 0644)) == -1) |
|
293 |
PERROR("open: %s", path); |
|
294 |
||
37 | 295 |
// read/write access |
296 |
op->mmap_prot = PROT_READ | PROT_WRITE; |
|
297 |
||
31 | 298 |
// ftruncate, and then mmap |
299 |
if (_fs_mmap(op, size_hint ? size_hint : FS_INITIAL_SIZE)) |
|
300 |
goto error; |
|
301 |
||
302 |
// great |
|
36
b4023990811e
rename/clean up states slightly and add lots of documentation
Tero Marttila <terom@fixme.fi>
parents:
33
diff
changeset
|
303 |
if (_cache_op_write_ready(&op->base)) |
31 | 304 |
goto error; |
305 |
||
306 |
// done |
|
307 |
return 0; |
|
308 |
||
309 |
error: |
|
310 |
return -1; |
|
311 |
} |
|
312 |
||
313 |
int _fs_do_op_push (struct cache_op *op_base, int fd, size_t *size_ptr) { |
|
314 |
struct cache_op_fs *op = (struct cache_op_fs *) op_base; |
|
315 |
struct cache_engine_fs *engine = (struct cache_engine_fs *) op->base.cache->engine; |
|
316 |
||
317 |
size_t ret, size; |
|
318 |
||
319 |
assert(op->fd > 0); |
|
33 | 320 |
|
321 |
// must have called begin_write first... |
|
322 |
assert(op->mmap_size > 0); |
|
31 | 323 |
assert(op->mmap != NULL); |
33 | 324 |
assert(op->write_offset <= op->mmap_size); |
31 | 325 |
|
326 |
// default size if none specified |
|
327 |
if (*size_ptr == 0) |
|
328 |
size = FS_INITIAL_SIZE; |
|
329 |
else |
|
330 |
size = *size_ptr; |
|
331 |
||
332 |
// grow the file if needed |
|
333 |
if (_fs_grow(op, op->write_offset + size)) |
|
334 |
goto error; |
|
335 |
||
336 |
// read the data into the mmap'd region |
|
337 |
if ((ret = read(fd, op->mmap + op->write_offset, size)) == -1) |
|
338 |
// XXX: EAGAIN |
|
339 |
PERROR("read"); |
|
340 |
||
341 |
// move the write offset along |
|
342 |
op->write_offset += ret; |
|
343 |
||
344 |
// return something |
|
345 |
*size_ptr = ret; |
|
346 |
||
347 |
// notify newly available data |
|
36
b4023990811e
rename/clean up states slightly and add lots of documentation
Tero Marttila <terom@fixme.fi>
parents:
33
diff
changeset
|
348 |
if (_cache_op_data_available(&op->base)) |
31 | 349 |
goto error; |
350 |
||
351 |
// great |
|
352 |
return 0; |
|
353 |
||
354 |
error: |
|
355 |
return -1; |
|
356 |
} |
|
357 |
||
37 | 358 |
int _fs_do_op_pull (struct cache_op *op_base, int fd, size_t *offset, size_t *size) { |
359 |
struct cache_op_fs *op = (struct cache_op_fs *) op_base; |
|
360 |
struct cache_engine_fs *engine = (struct cache_engine_fs *) op->base.cache->engine; |
|
361 |
||
362 |
size_t ret; |
|
363 |
||
364 |
// must have called begin_read first... |
|
365 |
assert(op->fd > 0); |
|
366 |
assert(op->mmap_size > 0); |
|
367 |
assert(op->mmap != NULL); |
|
368 |
// op->size may be zero |
|
369 |
||
370 |
// default size if none specified |
|
371 |
if (*size == 0) { |
|
372 |
*size = FS_OP_DATA_SIZE(op) - *offset; |
|
373 |
||
374 |
if (*size == 0) { |
|
375 |
ERROR("no more data available"); |
|
376 |
} |
|
377 |
||
378 |
} else if (*size + *offset > FS_OP_DATA_SIZE(op)) { |
|
379 |
ERROR("more data requested is available"); |
|
380 |
||
381 |
} else if (*size == 0) { |
|
382 |
ERROR("size may not be zero"); |
|
383 |
} |
|
384 |
||
385 |
// write the data from the mmap'd region |
|
386 |
if ((ret = write(fd, op->mmap + *offset, *size)) == -1) |
|
387 |
// XXX: EAGAIN? |
|
388 |
PERROR("write"); |
|
389 |
||
390 |
// move the offset along |
|
391 |
*offset += ret; |
|
392 |
||
393 |
// great |
|
394 |
return 0; |
|
395 |
||
396 |
error: |
|
397 |
return -1; |
|
398 |
} |
|
399 |
||
31 | 400 |
int _fs_do_op_done (struct cache_op *op_base) { |
401 |
struct cache_op_fs *op = (struct cache_op_fs *) op_base; |
|
402 |
struct cache_engine_fs *engine = (struct cache_engine_fs *) op->base.cache->engine; |
|
403 |
||
404 |
assert(op->fd > 0); |
|
405 |
assert(op->mmap != NULL); |
|
33 | 406 |
assert(op->write_offset <= op->mmap_size); |
407 |
||
408 |
// empty cache entries are illegal |
|
409 |
assert(op->write_offset > 0); |
|
410 |
||
411 |
// final size is now known |
|
412 |
op->size = op->write_offset; |
|
31 | 413 |
|
414 |
// truncate to match data length |
|
33 | 415 |
if (_fs_mmap(op, op->size)) |
31 | 416 |
goto error; |
417 |
||
418 |
// notify that data is complete |
|
36
b4023990811e
rename/clean up states slightly and add lots of documentation
Tero Marttila <terom@fixme.fi>
parents:
33
diff
changeset
|
419 |
if (_cache_op_write_done(&op->base)) |
31 | 420 |
goto error; |
421 |
||
422 |
// great |
|
423 |
return 0; |
|
424 |
||
425 |
error: |
|
426 |
return -1; |
|
427 |
||
428 |
} |
|
429 |
||
33 | 430 |
int _fs_do_op_close (struct cache_op *op_base) { |
431 |
struct cache_op_fs *op = (struct cache_op_fs *) op_base; |
|
432 |
||
433 |
// unmap |
|
434 |
if (op->mmap) |
|
435 |
if (munmap(op->mmap, op->mmap_size)) |
|
436 |
PWARNING("munmap"); |
|
437 |
||
438 |
// close |
|
439 |
if (op->fd > 0) |
|
440 |
if (close(op->fd)) |
|
441 |
PWARNING("close"); |
|
442 |
||
443 |
// XXX: delete if op->write_offset == 0? |
|
444 |
||
445 |
// free |
|
446 |
free(op); |
|
447 |
||
448 |
return 0; |
|
449 |
} |
|
31 | 450 |
struct cache_engine *cache_engine_fs (const char *cache_dir) { |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
451 |
struct cache_engine_fs *ctx = NULL; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
452 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
453 |
if ((ctx = calloc(1, sizeof(*ctx))) == NULL) |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
454 |
ERROR("calloc"); |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
455 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
456 |
ctx->cache_dir = cache_dir; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
457 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
458 |
// set up the fn table |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
459 |
ctx->base.fn_init = &_fs_do_init; |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
460 |
ctx->base.fn_op_start = &_fs_do_op_start; |
33 | 461 |
ctx->base.fn_op_available = &_fs_do_op_available; |
37 | 462 |
ctx->base.fn_op_begin_read = &_fs_do_op_begin_read; |
31 | 463 |
ctx->base.fn_op_begin_write = &_fs_do_op_begin_write; |
464 |
ctx->base.fn_op_push = &_fs_do_op_push; |
|
37 | 465 |
ctx->base.fn_op_pull = &_fs_do_op_pull; |
33 | 466 |
ctx->base.fn_op_done = &_fs_do_op_done; |
467 |
ctx->base.fn_op_close = &_fs_do_op_close; |
|
31 | 468 |
|
469 |
return &ctx->base; |
|
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
470 |
|
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
471 |
error: |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
472 |
free(ctx); |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
473 |
|
31 | 474 |
return NULL; |
30
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
475 |
} |
33e464fd6773
my hg working dir managed to break itself somehow... my attempt to fix that, and add some cache code :)
terom@cl-543.hel-01.fi.sixxs.net
parents:
diff
changeset
|
476 |