diff options
author | dormando <dormando@rydia.net> | 2018-07-16 21:58:43 -0700 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2018-08-06 15:11:04 -0700 |
commit | 89bf7ab1cfea2c24d08b9de697215ac7f61a0362 (patch) | |
tree | 25bdbe36326abb864f02caec690c4f4893d65326 /storage.c | |
parent | 954f4e044b3f1641da66910e4564cd91dfb83712 (diff) | |
download | memcached-89bf7ab1cfea2c24d08b9de697215ac7f61a0362.tar.gz |
extstore JBOD support
Just a Bunch Of Devices :P
code exists for routing specific devices to specific buckets
(lowttl/compact/etc), but enabling it requires significant fixes to
compaction algorithm. Thus it is disabled as of this writing.
code cleanups and future work:
- pedantically freeing memory and closing fd's on exit
- unify and flatten the free_bucket code
- defines for free buckets
- page eviction adjustment (force min-free per free bucket)
- fix default calculation for compact_under and drop_under
- might require forcing this value only on default bucket
Diffstat (limited to 'storage.c')
-rw-r--r-- | storage.c | 91 |
1 files changed, 89 insertions, 2 deletions
@@ -6,6 +6,7 @@ #include <stdlib.h> #include <string.h> #include <limits.h> +#include <ctype.h> #define PAGE_BUCKET_DEFAULT 0 #define PAGE_BUCKET_COMPACT 1 @@ -50,7 +51,9 @@ static int storage_write(void *storage, const int clsid, const int item_age) { // NOTE: when the item is read back in, the slab mover // may see it. Important to have refcount>=2 or ~ITEM_LINKED assert(it->refcount >= 2); - if (extstore_write_request(storage, bucket, &io) == 0) { + // NOTE: write bucket vs free page bucket will disambiguate once + // lowttl feature is better understood. + if (extstore_write_request(storage, bucket, bucket, &io) == 0) { // cuddle the hash value into the time field so we don't have // to recalculate it. item *buf_it = (item *) io.buf; @@ -365,7 +368,7 @@ static void storage_compact_readback(void *storage, logger *l, io.len = ntotal; io.mode = OBJ_IO_WRITE; for (tries = 10; tries > 0; tries--) { - if (extstore_write_request(storage, PAGE_BUCKET_COMPACT, &io) == 0) { + if (extstore_write_request(storage, PAGE_BUCKET_COMPACT, PAGE_BUCKET_COMPACT, &io) == 0) { memcpy(io.buf, it, io.len); extstore_write(storage, &io); do_update = true; @@ -561,4 +564,88 @@ int start_storage_compact_thread(void *arg) { return 0; } +/*** UTILITY ***/ +// /path/to/file:100G:bucket1 +// FIXME: Modifies argument. copy instead? +struct extstore_conf_file *storage_conf_parse(char *arg, unsigned int page_size) { + struct extstore_conf_file *cf = NULL; + char *b = NULL; + char *p = strtok_r(arg, ":", &b); + char unit = 0; + uint64_t multiplier = 0; + int base_size = 0; + if (p == NULL) + goto error; + // First arg is the filepath. + cf = calloc(1, sizeof(struct extstore_conf_file)); + cf->file = strdup(p); + + p = strtok_r(NULL, ":", &b); + if (p == NULL) { + fprintf(stderr, "must supply size to ext_path, ie: ext_path=/f/e:64m (M|G|T|P supported)\n"); + goto error; + } + unit = tolower(p[strlen(p)-1]); + p[strlen(p)-1] = '\0'; + // sigh. + switch (unit) { + case 'm': + multiplier = 1024 * 1024; + break; + case 'g': + multiplier = 1024 * 1024 * 1024; + break; + case 't': + multiplier = 1024 * 1024; + multiplier *= 1024 * 1024; + break; + case 'p': + multiplier = 1024 * 1024; + multiplier *= 1024 * 1024 * 1024; + break; + } + base_size = atoi(p); + multiplier *= base_size; + // page_count is nearest-but-not-larger-than pages * psize + cf->page_count = multiplier / page_size; + assert(page_size * cf->page_count <= multiplier); + + // final token would be a default free bucket + p = strtok_r(NULL, ",", &b); + // TODO: We reuse the original DEFINES for now, + // but if lowttl gets split up this needs to be its own set. + if (p != NULL) { + if (strcmp(p, "compact") == 0) { + cf->free_bucket = PAGE_BUCKET_COMPACT; + } else if (strcmp(p, "lowttl") == 0) { + cf->free_bucket = PAGE_BUCKET_LOWTTL; + } else if (strcmp(p, "chunked") == 0) { + cf->free_bucket = PAGE_BUCKET_CHUNKED; + } else if (strcmp(p, "default") == 0) { + cf->free_bucket = PAGE_BUCKET_DEFAULT; + } else { + fprintf(stderr, "Unknown extstore bucket: %s\n", p); + goto error; + } + } else { + // TODO: is this necessary? + cf->free_bucket = PAGE_BUCKET_DEFAULT; + } + + // TODO: disabling until compact algorithm is improved. + if (cf->free_bucket != PAGE_BUCKET_DEFAULT) { + fprintf(stderr, "ext_path only presently supports the default bucket\n"); + goto error; + } + + return cf; +error: + if (cf) { + if (cf->file) + free(cf->file); + free(cf); + } + return NULL; +} + #endif |