| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #ifndef NETDATA_DATAFILE_H |
| 4 | #define NETDATA_DATAFILE_H |
| 5 | |
| 6 | #include "rrdengine.h" |
| 7 | |
| 8 | /* Forward declarations */ |
| 9 | struct rrdengine_datafile; |
| 10 | struct rrdengine_journalfile; |
| 11 | struct rrdengine_instance; |
| 12 | |
| 13 | #define DATAFILE_PREFIX "datafile-" |
| 14 | #define DATAFILE_EXTENSION ".ndf" |
| 15 | |
| 16 | #define MIN_DATAFILE_SIZE (512LU * 1024LU) |
| 17 | #ifndef MAX_DATAFILE_SIZE |
| 18 | #define MAX_DATAFILE_SIZE (1LLU * 1024LLU * 1024LLU * 1024LLU) |
| 19 | #endif |
| 20 | #if MIN_DATAFILE_SIZE > MAX_DATAFILE_SIZE |
| 21 | #error MIN_DATAFILE_SIZE > MAX_DATAFILE_SIZE |
| 22 | #endif |
| 23 | |
| 24 | #define MAX_DATAFILES (65536 * 4) /* Supports up to 64TiB for now */ |
| 25 | #define TARGET_DATAFILES (100) |
| 26 | |
| 27 | // When trying to acquire a datafile for deletion and an attempt to evict pages is completed |
| 28 | // the acquire for deletion will return true after this timeout |
| 29 | #define DATAFILE_DELETE_TIMEOUT_SHORT (1) |
| 30 | #define DATAFILE_DELETE_TIMEOUT_LONG (120) |
| 31 | |
| 32 | typedef enum __attribute__ ((__packed__)) { |
| 33 | DATAFILE_ACQUIRE_OPEN_CACHE = 0, |
| 34 | DATAFILE_ACQUIRE_PAGE_DETAILS, |
| 35 | DATAFILE_ACQUIRE_RETENTION, |
| 36 | DATAFILE_ACQUIRE_INDEXING, |
| 37 | |
| 38 | // terminator |
| 39 | DATAFILE_ACQUIRE_MAX, |
| 40 | } DATAFILE_ACQUIRE_REASONS; |
| 41 | |
| 42 | struct extent_page_details_list; |
| 43 | typedef struct { |
| 44 | SPINLOCK spinlock; |
| 45 | struct extent_page_details_list *base; |
| 46 | } EPDL_EXTENT; |
| 47 | void epdl_extent_release(EPDL_EXTENT *e); |
| 48 | |
| 49 | #define DATAFILE_MAGIC 0xDA7AF11E |
| 50 | |
| 51 | /* only one event loop is supported for now */ |
| 52 | struct rrdengine_datafile { |
| 53 | uint32_t magic1; |
| 54 | |
| 55 | unsigned tier; |
| 56 | unsigned fileno; |
| 57 | uv_file file; |
| 58 | uint64_t pos; |
| 59 | netdata_rwlock_t extent_rwlock; |
| 60 | struct rrdengine_instance *ctx; |
| 61 | struct rrdengine_journalfile *journalfile; |
| 62 | |
| 63 | struct { |
| 64 | SPINLOCK spinlock; |
| 65 | bool populated; |
| 66 | } populate_mrg; |
| 67 | |
| 68 | struct { |
| 69 | SPINLOCK spinlock; |
| 70 | size_t running; |
| 71 | size_t flushed_to_open_running; |
| 72 | #ifdef OS_WINDOWS |
| 73 | time_t last_sync_time; |
| 74 | #endif |
| 75 | } writers; |
| 76 | |
| 77 | struct { |
| 78 | SPINLOCK spinlock; |
| 79 | unsigned lockers; |
| 80 | unsigned lockers_by_reason[DATAFILE_ACQUIRE_MAX]; |
| 81 | bool available; |
| 82 | bool pending_deletion; |
| 83 | time_t time_to_evict; |
| 84 | } users; |
| 85 | |
| 86 | struct { |
| 87 | RW_SPINLOCK spinlock; |
| 88 | Pvoid_t epdl_per_extent; |
| 89 | } extent_epdl; |
| 90 | |
| 91 | uint32_t magic2; |
| 92 | }; |
| 93 | |
| 94 | bool datafile_acquire(struct rrdengine_datafile *df, DATAFILE_ACQUIRE_REASONS reason); |
| 95 | void datafile_release_with_trace(struct rrdengine_datafile *df, DATAFILE_ACQUIRE_REASONS reason, const char *func); |
| 96 | #define datafile_release(df, reason) datafile_release_with_trace(df, reason, __FUNCTION__) |
| 97 | bool datafile_acquire_for_deletion(struct rrdengine_datafile *df, bool is_shutdown); |
| 98 | |
| 99 | void datafile_list_insert(struct rrdengine_instance *ctx, struct rrdengine_datafile *datafile); |
| 100 | void datafile_list_delete_unsafe(struct rrdengine_instance *ctx, struct rrdengine_datafile *datafile); |
| 101 | void generate_datafilepath(struct rrdengine_datafile *datafile, char *str, size_t maxlen); |
| 102 | int close_data_file(struct rrdengine_datafile *datafile); |
| 103 | int unlink_data_file(struct rrdengine_datafile *datafile); |
| 104 | int destroy_data_file_unsafe(struct rrdengine_datafile *datafile); |
| 105 | int create_data_file(struct rrdengine_datafile *datafile); |
| 106 | int create_new_datafile_pair(struct rrdengine_instance *ctx); |
| 107 | int init_data_files(struct rrdengine_instance *ctx); |
| 108 | void finalize_data_files(struct rrdengine_instance *ctx); |
| 109 | void cleanup_datafile_epdl_structures(struct rrdengine_datafile *datafile); |
| 110 | |
| 111 | NEVERNULL ALWAYS_INLINE |
| 112 | static struct rrdengine_instance *datafile_ctx(struct rrdengine_datafile *datafile) { |
| 113 | if(unlikely(!datafile->ctx)) |
| 114 | fatal("DBENGINE: datafile %u of tier %u has no ctx", datafile->fileno, datafile->tier); |
| 115 | |
| 116 | if(unlikely(datafile->magic1 != DATAFILE_MAGIC || datafile->magic2 != DATAFILE_MAGIC)) |
| 117 | fatal("DBENGINE: datafile %u of tier %u has invalid magic", datafile->fileno, datafile->tier); |
| 118 | |
| 119 | return datafile->ctx; |
| 120 | } |
| 121 | |
| 122 | #ifdef OS_WINDOWS |
| 123 | void sync_uv_file_data(uv_file file); |
| 124 | #endif |
| 125 | |
| 126 | #endif /* NETDATA_DATAFILE_H */ |