cache.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #ifndef DBENGINE_CACHE_H
  3. #define DBENGINE_CACHE_H
  4. #include "../rrd.h"
  5. // CACHE COMPILE TIME CONFIGURATION
  6. // #define PGC_COUNT_POINTS_COLLECTED 1
  7. typedef struct pgc PGC;
  8. typedef struct pgc_page PGC_PAGE;
  9. #define PGC_NAME_MAX 23
  10. typedef enum __attribute__ ((__packed__)) {
  11. PGC_OPTIONS_NONE = 0,
  12. PGC_OPTIONS_EVICT_PAGES_INLINE = (1 << 0),
  13. PGC_OPTIONS_FLUSH_PAGES_INLINE = (1 << 1),
  14. PGC_OPTIONS_AUTOSCALE = (1 << 2),
  15. } PGC_OPTIONS;
  16. #define PGC_OPTIONS_DEFAULT (PGC_OPTIONS_EVICT_PAGES_INLINE | PGC_OPTIONS_FLUSH_PAGES_INLINE | PGC_OPTIONS_AUTOSCALE)
  17. typedef struct pgc_entry {
  18. Word_t section; // the section this belongs to
  19. Word_t metric_id; // the metric this belongs to
  20. time_t start_time_s; // the start time of the page
  21. time_t end_time_s; // the end time of the page
  22. size_t size; // the size in bytes of the allocation, outside the cache
  23. void *data; // a pointer to data outside the cache
  24. uint32_t update_every_s; // the update every of the page
  25. bool hot; // true if this entry is currently being collected
  26. uint8_t *custom_data;
  27. } PGC_ENTRY;
  28. #define PGC_CACHE_LINE_PADDING(x) uint8_t padding##x[64]
  29. struct pgc_queue_statistics {
  30. size_t entries;
  31. size_t size;
  32. PGC_CACHE_LINE_PADDING(1);
  33. size_t max_entries;
  34. size_t max_size;
  35. PGC_CACHE_LINE_PADDING(2);
  36. size_t added_entries;
  37. size_t added_size;
  38. PGC_CACHE_LINE_PADDING(3);
  39. size_t removed_entries;
  40. size_t removed_size;
  41. PGC_CACHE_LINE_PADDING(4);
  42. };
  43. struct pgc_statistics {
  44. size_t wanted_cache_size;
  45. size_t current_cache_size;
  46. PGC_CACHE_LINE_PADDING(1);
  47. size_t added_entries;
  48. size_t added_size;
  49. PGC_CACHE_LINE_PADDING(2);
  50. size_t removed_entries;
  51. size_t removed_size;
  52. PGC_CACHE_LINE_PADDING(3);
  53. size_t entries; // all the entries (includes clean, dirty, hot)
  54. size_t size; // all the entries (includes clean, dirty, hot)
  55. size_t evicting_entries;
  56. size_t evicting_size;
  57. size_t flushing_entries;
  58. size_t flushing_size;
  59. size_t hot2dirty_entries;
  60. size_t hot2dirty_size;
  61. PGC_CACHE_LINE_PADDING(4);
  62. size_t acquires;
  63. PGC_CACHE_LINE_PADDING(4a);
  64. size_t releases;
  65. PGC_CACHE_LINE_PADDING(4b);
  66. size_t acquires_for_deletion;
  67. PGC_CACHE_LINE_PADDING(4c);
  68. size_t referenced_entries; // all the entries currently referenced
  69. size_t referenced_size; // all the entries currently referenced
  70. PGC_CACHE_LINE_PADDING(5);
  71. size_t searches_exact;
  72. size_t searches_exact_hits;
  73. size_t searches_exact_misses;
  74. PGC_CACHE_LINE_PADDING(6);
  75. size_t searches_closest;
  76. size_t searches_closest_hits;
  77. size_t searches_closest_misses;
  78. PGC_CACHE_LINE_PADDING(7);
  79. size_t flushes_completed;
  80. size_t flushes_completed_size;
  81. size_t flushes_cancelled;
  82. size_t flushes_cancelled_size;
  83. #ifdef PGC_COUNT_POINTS_COLLECTED
  84. PGC_CACHE_LINE_PADDING(8);
  85. size_t points_collected;
  86. #endif
  87. PGC_CACHE_LINE_PADDING(9);
  88. size_t insert_spins;
  89. size_t evict_spins;
  90. size_t release_spins;
  91. size_t acquire_spins;
  92. size_t delete_spins;
  93. size_t flush_spins;
  94. PGC_CACHE_LINE_PADDING(10);
  95. size_t workers_search;
  96. size_t workers_add;
  97. size_t workers_evict;
  98. size_t workers_flush;
  99. size_t workers_jv2_flush;
  100. size_t workers_hot2dirty;
  101. size_t evict_skipped;
  102. size_t hot_empty_pages_evicted_immediately;
  103. size_t hot_empty_pages_evicted_later;
  104. PGC_CACHE_LINE_PADDING(11);
  105. // events
  106. size_t events_cache_under_severe_pressure;
  107. size_t events_cache_needs_space_aggressively;
  108. size_t events_flush_critical;
  109. PGC_CACHE_LINE_PADDING(12);
  110. struct {
  111. PGC_CACHE_LINE_PADDING(0);
  112. struct pgc_queue_statistics hot;
  113. PGC_CACHE_LINE_PADDING(1);
  114. struct pgc_queue_statistics dirty;
  115. PGC_CACHE_LINE_PADDING(2);
  116. struct pgc_queue_statistics clean;
  117. PGC_CACHE_LINE_PADDING(3);
  118. } queues;
  119. };
  120. typedef void (*free_clean_page_callback)(PGC *cache, PGC_ENTRY entry);
  121. typedef void (*save_dirty_page_callback)(PGC *cache, PGC_ENTRY *entries_array, PGC_PAGE **pages_array, size_t entries);
  122. typedef void (*save_dirty_init_callback)(PGC *cache, Word_t section);
  123. // create a cache
  124. PGC *pgc_create(const char *name,
  125. size_t clean_size_bytes, free_clean_page_callback pgc_free_clean_cb,
  126. size_t max_dirty_pages_per_flush, save_dirty_init_callback pgc_save_init_cb, save_dirty_page_callback pgc_save_dirty_cb,
  127. size_t max_pages_per_inline_eviction, size_t max_inline_evictors,
  128. size_t max_skip_pages_per_inline_eviction,
  129. size_t max_flushes_inline,
  130. PGC_OPTIONS options, size_t partitions, size_t additional_bytes_per_page);
  131. // destroy the cache
  132. void pgc_destroy(PGC *cache);
  133. #define PGC_SECTION_ALL ((Word_t)0)
  134. void pgc_flush_all_hot_and_dirty_pages(PGC *cache, Word_t section);
  135. // add a page to the cache and return a pointer to it
  136. PGC_PAGE *pgc_page_add_and_acquire(PGC *cache, PGC_ENTRY entry, bool *added);
  137. // get another reference counter on an already referenced page
  138. PGC_PAGE *pgc_page_dup(PGC *cache, PGC_PAGE *page);
  139. // release a page (all pointers to it are now invalid)
  140. void pgc_page_release(PGC *cache, PGC_PAGE *page);
  141. // mark a hot page dirty, and release it
  142. void pgc_page_hot_to_dirty_and_release(PGC *cache, PGC_PAGE *page);
  143. // find a page from the cache
  144. typedef enum {
  145. PGC_SEARCH_EXACT,
  146. PGC_SEARCH_CLOSEST,
  147. PGC_SEARCH_FIRST,
  148. PGC_SEARCH_NEXT,
  149. PGC_SEARCH_LAST,
  150. PGC_SEARCH_PREV,
  151. } PGC_SEARCH;
  152. PGC_PAGE *pgc_page_get_and_acquire(PGC *cache, Word_t section, Word_t metric_id, time_t start_time_s, PGC_SEARCH method);
  153. // get information from an acquired page
  154. Word_t pgc_page_section(PGC_PAGE *page);
  155. Word_t pgc_page_metric(PGC_PAGE *page);
  156. time_t pgc_page_start_time_s(PGC_PAGE *page);
  157. time_t pgc_page_end_time_s(PGC_PAGE *page);
  158. time_t pgc_page_update_every_s(PGC_PAGE *page);
  159. time_t pgc_page_fix_update_every(PGC_PAGE *page, time_t update_every_s);
  160. time_t pgc_page_fix_end_time_s(PGC_PAGE *page, time_t end_time_s);
  161. void *pgc_page_data(PGC_PAGE *page);
  162. void *pgc_page_custom_data(PGC *cache, PGC_PAGE *page);
  163. size_t pgc_page_data_size(PGC *cache, PGC_PAGE *page);
  164. bool pgc_is_page_hot(PGC_PAGE *page);
  165. bool pgc_is_page_dirty(PGC_PAGE *page);
  166. bool pgc_is_page_clean(PGC_PAGE *page);
  167. void pgc_reset_hot_max(PGC *cache);
  168. size_t pgc_get_current_cache_size(PGC *cache);
  169. size_t pgc_get_wanted_cache_size(PGC *cache);
  170. // resetting the end time of a hot page
  171. void pgc_page_hot_set_end_time_s(PGC *cache, PGC_PAGE *page, time_t end_time_s);
  172. bool pgc_page_to_clean_evict_or_release(PGC *cache, PGC_PAGE *page);
  173. typedef void (*migrate_to_v2_callback)(Word_t section, unsigned datafile_fileno, uint8_t type, Pvoid_t JudyL_metrics, Pvoid_t JudyL_extents_pos, size_t count_of_unique_extents, size_t count_of_unique_metrics, size_t count_of_unique_pages, void *data);
  174. void pgc_open_cache_to_journal_v2(PGC *cache, Word_t section, unsigned datafile_fileno, uint8_t type, migrate_to_v2_callback cb, void *data);
  175. void pgc_open_evict_clean_pages_of_datafile(PGC *cache, struct rrdengine_datafile *datafile);
  176. size_t pgc_count_clean_pages_having_data_ptr(PGC *cache, Word_t section, void *ptr);
  177. size_t pgc_count_hot_pages_having_data_ptr(PGC *cache, Word_t section, void *ptr);
  178. typedef size_t (*dynamic_target_cache_size_callback)(void);
  179. void pgc_set_dynamic_target_cache_size_callback(PGC *cache, dynamic_target_cache_size_callback callback);
  180. // return true when there is more work to do
  181. bool pgc_evict_pages(PGC *cache, size_t max_skip, size_t max_evict);
  182. bool pgc_flush_pages(PGC *cache, size_t max_flushes);
  183. struct pgc_statistics pgc_get_statistics(PGC *cache);
  184. size_t pgc_hot_and_dirty_entries(PGC *cache);
  185. struct aral_statistics *pgc_aral_statistics(void);
  186. size_t pgc_aral_structures(void);
  187. size_t pgc_aral_overhead(void);
  188. #endif // DBENGINE_CACHE_H