1 #ifndef EXTSTORE_H 2 #define EXTSTORE_H 3 4 /* A safe-to-read dataset for determining compaction. 5 * id is the array index. 6 */ 7 struct extstore_page_data { 8 uint64_t version; 9 uint64_t bytes_used; 10 unsigned int bucket; 11 unsigned int free_bucket; 12 bool active; // page is actively being written to; ignore it except for tallying. 13 }; 14 15 /* Pages can have objects deleted from them at any time. This creates holes 16 * that can't be reused until the page is either evicted or all objects are 17 * deleted. 18 * bytes_fragmented is the total bytes for all of these holes. 19 * It is the size of all used pages minus each page's bytes_used value. 20 */ 21 struct extstore_stats { 22 uint64_t page_allocs; 23 uint64_t page_count; /* total page count */ 24 uint64_t page_evictions; 25 uint64_t page_reclaims; 26 uint64_t page_size; /* size in bytes per page (supplied by caller) */ 27 uint64_t pages_free; /* currently unallocated/unused pages */ 28 uint64_t pages_used; 29 uint64_t objects_evicted; 30 uint64_t objects_read; 31 uint64_t objects_written; 32 uint64_t objects_used; /* total number of objects stored */ 33 uint64_t bytes_evicted; 34 uint64_t bytes_written; 35 uint64_t bytes_read; /* wbuf - read -> bytes read from storage */ 36 uint64_t bytes_used; /* total number of bytes stored */ 37 uint64_t bytes_fragmented; /* see above comment */ 38 uint64_t io_queue; 39 struct extstore_page_data *page_data; 40 }; 41 42 // TODO: Temporary configuration structure. A "real" library should have an 43 // extstore_set(enum, void *ptr) which hides the implementation. 44 // this is plenty for quick development. 45 struct extstore_conf { 46 unsigned int page_size; // ideally 64-256M in size 47 unsigned int page_count; 48 unsigned int page_buckets; // number of different writeable pages 49 unsigned int free_page_buckets; // buckets of dedicated pages (see code) 50 unsigned int wbuf_size; // must divide cleanly into page_size 51 unsigned int wbuf_count; // this might get locked to "2 per active page" 52 unsigned int io_threadcount; 53 unsigned int io_depth; // with normal I/O, hits locks less. req'd for AIO 54 }; 55 56 struct extstore_conf_file { 57 unsigned int page_count; 58 char *file; 59 int fd; // internal usage 60 uint64_t offset; // internal usage 61 unsigned int bucket; // free page bucket 62 unsigned int free_bucket; // specialized free bucket 63 struct extstore_conf_file *next; 64 }; 65 66 enum obj_io_mode { 67 OBJ_IO_READ = 0, 68 OBJ_IO_WRITE, 69 }; 70 71 typedef struct _obj_io obj_io; 72 typedef void (*obj_io_cb)(void *e, obj_io *io, int ret); 73 74 /* An object for both reads and writes to the storage engine. 75 * Once an IO is submitted, ->next may be changed by the IO thread. It is not 76 * safe to further modify the IO stack until the entire request is completed. 77 */ 78 struct _obj_io { 79 void *data; /* user supplied data pointer */ 80 struct _obj_io *next; 81 char *buf; /* buffer of data to read or write to */ 82 struct iovec *iov; /* alternatively, use this iovec */ 83 unsigned int iovcnt; /* number of IOV's */ 84 unsigned int page_version; /* page version for read mode */ 85 unsigned int len; /* for both modes */ 86 unsigned int offset; /* for read mode */ 87 unsigned short page_id; /* for read mode */ 88 enum obj_io_mode mode; 89 /* callback pointers? */ 90 obj_io_cb cb; 91 }; 92 93 enum extstore_res { 94 EXTSTORE_INIT_BAD_WBUF_SIZE = 1, 95 EXTSTORE_INIT_NEED_MORE_WBUF, 96 EXTSTORE_INIT_NEED_MORE_BUCKETS, 97 EXTSTORE_INIT_PAGE_WBUF_ALIGNMENT, 98 EXTSTORE_INIT_TOO_MANY_PAGES, 99 EXTSTORE_INIT_OOM, 100 EXTSTORE_INIT_OPEN_FAIL, 101 EXTSTORE_INIT_THREAD_FAIL 102 }; 103 104 const char *extstore_err(enum extstore_res res); 105 void *extstore_init(struct extstore_conf_file *fh, struct extstore_conf *cf, enum extstore_res *res); 106 int extstore_write_request(void *ptr, unsigned int bucket, unsigned int free_bucket, obj_io *io); 107 void extstore_write(void *ptr, obj_io *io); 108 int extstore_submit(void *ptr, obj_io *io); 109 int extstore_submit_bg(void *ptr, obj_io *io); 110 /* count are the number of objects being removed, bytes are the original 111 * length of those objects. Bytes is optional but you can't track 112 * fragmentation without it. 113 */ 114 int extstore_check(void *ptr, unsigned int page_id, uint64_t page_version); 115 int extstore_delete(void *ptr, unsigned int page_id, uint64_t page_version, unsigned int count, unsigned int bytes); 116 void extstore_get_stats(void *ptr, struct extstore_stats *st); 117 /* add page data array to a stats structure. 118 * caller must allocate its stats.page_data memory first. 119 */ 120 void extstore_get_page_data(void *ptr, struct extstore_stats *st); 121 void extstore_close_page(void *ptr, unsigned int page_id, uint64_t page_version); 122 void extstore_evict_page(void *ptr, unsigned int page_id, uint64_t page_version); 123 124 #endif 125