4
extern Store *store_new();
5
extern void store_destroy(Store *store);
6
extern OutStream *os_new();
7
extern InStream *is_new();
8
extern int file_is_lock(char *filename);
10
static RAMFile *rf_new(const char *name)
12
RAMFile *rf = ALLOC(RAMFile);
13
rf->buffers = ALLOC(uchar *);
14
rf->buffers[0] = ALLOC_N(uchar, BUFFER_SIZE);
15
rf->name = estrdup(name);
22
static void rf_extend_if_necessary(RAMFile *rf, int buf_num)
24
while (rf->bufcnt <= buf_num) {
25
REALLOC_N(rf->buffers, uchar *, (rf->bufcnt + 1));
26
rf->buffers[rf->bufcnt++] = ALLOC_N(uchar, BUFFER_SIZE);
30
static void rf_close(void *p)
33
RAMFile *rf = (RAMFile *)p;
34
if (rf->ref_cnt > 0) {
38
for (i = 0; i < rf->bufcnt; i++) {
45
static void ram_touch(Store *store, char *filename)
47
if (h_get(store->dir.ht, filename) == NULL) {
48
h_set(store->dir.ht, filename, rf_new(filename));
52
static int ram_exists(Store *store, char *filename)
54
if (h_get(store->dir.ht, filename) != NULL) {
62
static int ram_remove(Store *store, char *filename)
64
RAMFile *rf = h_rem(store->dir.ht, filename, false);
75
static void ram_rename(Store *store, char *from, char *to)
77
RAMFile *rf = (RAMFile *)h_rem(store->dir.ht, from, false);
81
RAISE(IO_ERROR, "couldn't rename \"%s\" to \"%s\". \"%s\""
82
" doesn't exist", from, to, from);
87
rf->name = estrdup(to);
89
/* clean up the file we are overwriting */
90
tmp = (RAMFile *)h_get(store->dir.ht, to);
95
h_set(store->dir.ht, rf->name, rf);
98
static int ram_count(Store *store)
100
return store->dir.ht->size;
103
static void ram_each(Store *store,
104
void (*func)(char *fname, void *arg), void *arg)
106
HashTable *ht = store->dir.ht;
108
for (i = 0; i <= ht->mask; i++) {
109
RAMFile *rf = (RAMFile *)ht->table[i].value;
111
if (strncmp(rf->name, LOCK_PREFIX, strlen(LOCK_PREFIX)) == 0) {
119
static void ram_close_i(Store *store)
121
HashTable *ht = store->dir.ht;
123
for (i = 0; i <= ht->mask; i++) {
124
RAMFile *rf = (RAMFile *)ht->table[i].value;
129
h_destroy(store->dir.ht);
130
store_destroy(store);
134
* Be sure to keep the locks
136
static void ram_clear(Store *store)
139
HashTable *ht = store->dir.ht;
140
for (i = 0; i <= ht->mask; i++) {
141
RAMFile *rf = (RAMFile *)ht->table[i].value;
142
if (rf && !file_is_lock(rf->name)) {
149
static void ram_clear_locks(Store *store)
152
HashTable *ht = store->dir.ht;
153
for (i = 0; i <= ht->mask; i++) {
154
RAMFile *rf = (RAMFile *)ht->table[i].value;
155
if (rf && file_is_lock(rf->name)) {
162
static void ram_clear_all(Store *store)
165
HashTable *ht = store->dir.ht;
166
for (i = 0; i <= ht->mask; i++) {
167
RAMFile *rf = (RAMFile *)ht->table[i].value;
175
static off_t ram_length(Store *store, char *filename)
177
RAMFile *rf = (RAMFile *)h_get(store->dir.ht, filename);
186
off_t ramo_length(OutStream *os)
188
return os->file.rf->len;
191
static void ramo_flush_i(OutStream *os, uchar *src, int len)
194
RAMFile *rf = os->file.rf;
195
int buffer_number, buffer_offset, bytes_in_buffer, bytes_to_copy;
197
off_t pointer = os->pointer;
199
buffer_number = (int)(pointer / BUFFER_SIZE);
200
buffer_offset = pointer % BUFFER_SIZE;
201
bytes_in_buffer = BUFFER_SIZE - buffer_offset;
202
bytes_to_copy = bytes_in_buffer < len ? bytes_in_buffer : len;
204
rf_extend_if_necessary(rf, buffer_number);
206
buffer = rf->buffers[buffer_number];
207
memcpy(buffer + buffer_offset, src, bytes_to_copy);
209
if (bytes_to_copy < len) {
210
src_offset = bytes_to_copy;
211
bytes_to_copy = len - bytes_to_copy;
213
rf_extend_if_necessary(rf, buffer_number);
214
buffer = rf->buffers[buffer_number];
216
memcpy(buffer, src + src_offset, bytes_to_copy);
220
if (os->pointer > rf->len) {
221
rf->len = os->pointer;
225
static void ramo_seek_i(OutStream *os, off_t pos)
230
void ramo_reset(OutStream *os)
233
os->file.rf->len = 0;
236
static void ramo_close_i(OutStream *os)
238
RAMFile *rf = os->file.rf;
243
void ramo_write_to(OutStream *os, OutStream *other_o)
246
RAMFile *rf = os->file.rf;
247
int last_buffer_number;
248
int last_buffer_offset;
251
last_buffer_number = (int) (rf->len / BUFFER_SIZE);
252
last_buffer_offset = rf->len % BUFFER_SIZE;
253
for (i = 0; i <= last_buffer_number; i++) {
254
len = (i == last_buffer_number ? last_buffer_offset : BUFFER_SIZE);
255
os_write_bytes(other_o, rf->buffers[i], len);
259
const struct OutStreamMethods RAM_OUT_STREAM_METHODS = {
265
OutStream *ram_new_buffer()
267
RAMFile *rf = rf_new("");
268
OutStream *os = os_new();
273
os->m = &RAM_OUT_STREAM_METHODS;
277
void ram_destroy_buffer(OutStream *os)
279
rf_close(os->file.rf);
283
static OutStream *ram_new_output(Store *store, const char *filename)
285
RAMFile *rf = (RAMFile *)h_get(store->dir.ht, filename);
286
OutStream *os = os_new();
289
rf = rf_new(filename);
290
h_set(store->dir.ht, rf->name, rf);
295
os->m = &RAM_OUT_STREAM_METHODS;
299
static void rami_read_i(InStream *is, uchar *b, int len)
301
RAMFile *rf = is->file.rf;
304
int buffer_number, buffer_offset, bytes_in_buffer, bytes_to_copy;
306
off_t start = is->d.pointer;
309
while (remainder > 0) {
310
buffer_number = (int) (start / BUFFER_SIZE);
311
buffer_offset = start % BUFFER_SIZE;
312
bytes_in_buffer = BUFFER_SIZE - buffer_offset;
314
if (bytes_in_buffer >= remainder) {
315
bytes_to_copy = remainder;
318
bytes_to_copy = bytes_in_buffer;
320
buffer = rf->buffers[buffer_number];
321
memcpy(b + offset, buffer + buffer_offset, bytes_to_copy);
322
offset += bytes_to_copy;
323
start += bytes_to_copy;
324
remainder -= bytes_to_copy;
327
is->d.pointer += len;
330
static off_t rami_length_i(InStream *is)
332
return is->file.rf->len;
335
static void rami_seek_i(InStream *is, off_t pos)
340
static void rami_close_i(InStream *is)
342
RAMFile *rf = is->file.rf;
347
static const struct InStreamMethods RAM_IN_STREAM_METHODS = {
354
static InStream *ram_open_input(Store *store, const char *filename)
356
RAMFile *rf = (RAMFile *)h_get(store->dir.ht, filename);
360
RAISE(FILE_NOT_FOUND_ERROR,
361
"tried to open \"%s\" but it doesn't exist", filename);
367
is->m = &RAM_IN_STREAM_METHODS;
372
#define LOCK_OBTAIN_TIMEOUT 5
374
static int ram_lock_obtain(Lock *lock)
377
if (ram_exists(lock->store, lock->name))
379
ram_touch(lock->store, lock->name);
383
static int ram_lock_is_locked(Lock *lock)
385
return ram_exists(lock->store, lock->name);
388
static void ram_lock_release(Lock *lock)
390
ram_remove(lock->store, lock->name);
393
static Lock *ram_open_lock_i(Store *store, char *lockname)
395
Lock *lock = ALLOC(Lock);
397
snprintf(lname, 100, "%s%s.lck", LOCK_PREFIX, lockname);
398
lock->name = estrdup(lname);
400
lock->obtain = &ram_lock_obtain;
401
lock->release = &ram_lock_release;
402
lock->is_locked = &ram_lock_is_locked;
406
static void ram_close_lock_i(Lock *lock)
413
Store *open_ram_store()
415
Store *new_store = store_new();
417
new_store->dir.ht = h_new_str(NULL, rf_close);
418
new_store->touch = &ram_touch;
419
new_store->exists = &ram_exists;
420
new_store->remove = &ram_remove;
421
new_store->rename = &ram_rename;
422
new_store->count = &ram_count;
423
new_store->clear = &ram_clear;
424
new_store->clear_all = &ram_clear_all;
425
new_store->clear_locks = &ram_clear_locks;
426
new_store->length = &ram_length;
427
new_store->each = &ram_each;
428
new_store->new_output = &ram_new_output;
429
new_store->open_input = &ram_open_input;
430
new_store->open_lock_i = &ram_open_lock_i;
431
new_store->close_lock_i = &ram_close_lock_i;
432
new_store->close_i = &ram_close_i;
438
Store *to_store, *from_store;
441
static void copy_files(char *fname, void *arg)
443
struct CopyFileArg *cfa = (struct CopyFileArg *)arg;
444
OutStream *os = cfa->to_store->new_output(cfa->to_store, fname);
445
InStream *is = cfa->from_store->open_input(cfa->from_store, fname);
446
int len = (int)is_length(is);
447
uchar *buffer = ALLOC_N(uchar, len + 1);
449
is_read_bytes(is, buffer, len);
450
os_write_bytes(os, buffer, len);
457
Store *open_ram_store_and_copy(Store *from_store, bool close_dir)
459
Store *store = open_ram_store();
460
struct CopyFileArg cfa;
461
cfa.to_store = store;
462
cfa.from_store = from_store;
464
from_store->each(from_store, ©_files, &cfa);
467
store_deref(from_store);