30#define ex_mkdir(p) _mkdir(p)
34#define ex_mkdir(p) mkdir(p, 0700)
38#define EX_DIR "ex_disk_cache.dir"
57 while ((opt = getopt(argc, argv,
"V:")) != -1) {
71 return stat(path, &st) == 0;
79 snprintf(path,
sizeof(path),
"%s/%s",
EX_DIR, name);
80 f = fopen(path,
"wb");
82 fputs(
"not the cache's", f);
93 memset(data,
key[0],
sizeof(data));
96 when.actime = time(NULL) - ago;
97 when.modtime = when.actime;
108int main(
int argc,
char** argv) {
110 unsigned char* data = NULL;
113 char p1[512], p2[512], p3[512];
114 const char* upper =
"0123456789ABCDEF0123456789ABCDEF.bin";
118 fprintf(stderr,
"Usage: %s [-V LOG_LEVEL]\n", argv[0]);
126 expect_true(
"an existing directory opens", cache != NULL);
127 if (!cache)
return 1;
134 expect_true(
"the same key has the same path", strcmp(p1, p2) == 0);
135 expect_true(
"another extension, another file", strcmp(p1, p3) != 0);
136 expect_true(
"the path is the directory, 32 digits and the extension",
143 expect_true(
"get finds it",
n_disk_cache_get(cache,
"hello", 5, NULL, 1024, &data, &len) && len == 5 && memcmp(data,
"world", 5) == 0 && data[5] ==
'\0');
146 expect_true(
"an entry over the limit is a miss",
n_disk_cache_get(cache,
"hello", 5, NULL, 4, &data, &len) == FALSE && data == NULL);
152 expect_true(
"remove removes",
n_disk_cache_remove(cache,
"hello", 5, NULL) && !
n_disk_cache_get(cache,
"hello", 5, NULL, 1024, &data, &len));
176 snprintf(p1,
sizeof(p1),
"%s/notes.txt",
EX_DIR);
177 snprintf(p2,
sizeof(p2),
"%s/%s",
EX_DIR, upper);
190 expect_true(
"a second cache opens", other != NULL);
199 expect_true(
"the two oldest, one from each", !
has(cache,
"f") && !
has(other,
"g") &&
has(cache,
"h") &&
has(other,
"i"));
206 expect_true(
"the second scratch directory is empty again", rmdir(
EX_DIR "/other") == 0);
210 expect_true(
"close sets the handle to NULL", cache == NULL);
216 fprintf(stderr,
"ex_disk_cache: %d failure(s)\n",
failures);
219 printf(
"ex_disk_cache: ok\n");
void process_args(int argc, char **argv)
static void expect_true(const char *label, int cond)
static int exists(const char *path)
does a file exist
#define ex_mkdir(p)
owner only elsewhere
static void write_foreign(const char *name)
write a small file that is not an entry
#define EX_DIR
the scratch directory, made and removed by this example
static int has(const N_DISK_CACHE *cache, const char *key)
is the entry for key there
static void put_aged(const N_DISK_CACHE *cache, const char *key, long ago)
store 100 bytes under key and say it was last used ago seconds ago
volatile char key[227]
TRUE while the key is held.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
#define LOG_INFO
informational
const char * n_disk_cache_dir(const N_DISK_CACHE *cache)
The cache's directory, as it was opened.
#define N_DISK_CACHE_NAME_LEN
length of an entry's name before its extension: 128 bits in hexadecimal
int n_disk_cache_get(const N_DISK_CACHE *cache, const void *key, size_t key_len, const char *ext, size_t max_len, unsigned char **data, size_t *len)
Read an entry.
int n_disk_cache_path(const N_DISK_CACHE *cache, const void *key, size_t key_len, const char *ext, char *out, size_t out_len)
The file an entry lives in, whether or not it exists.
void n_disk_cache_close(N_DISK_CACHE **cache)
Forget a cache.
int n_disk_cache_put(const N_DISK_CACHE *cache, const void *key, size_t key_len, const char *ext, const void *data, size_t len)
Store an entry, replacing any under the same key and extension.
int n_disk_cache_prune_group(const N_DISK_CACHE *const *caches, int count, uint64_t max_bytes)
n_disk_cache_prune() over several caches that share one budget.
int n_disk_cache_prune(const N_DISK_CACHE *cache, uint64_t max_bytes)
Remove least recently used entries until the rest fit a budget.
int n_disk_cache_remove(const N_DISK_CACHE *cache, const void *key, size_t key_len, const char *ext)
Remove one entry, for a caller that found it unreadable.
int n_disk_cache_expire(const N_DISK_CACHE *cache, int64_t max_age_seconds)
Remove every entry unused for longer than an age.
int n_disk_cache_size(const N_DISK_CACHE *cache, uint64_t *total)
How many bytes the cache's entries take.
N_DISK_CACHE * n_disk_cache_open(const char *dir)
Use a directory as a cache.
Common headers and low-level functions & define.
a cache: only where it is
A bounded cache of files in one directory, keyed by content.