cache.h 8.0 KB

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