summaryrefslogtreecommitdiffstats
path: root/database/engine/pagecache.h
diff options
context:
space:
mode:
Diffstat (limited to 'database/engine/pagecache.h')
-rw-r--r--database/engine/pagecache.h242
1 files changed, 26 insertions, 216 deletions
diff --git a/database/engine/pagecache.h b/database/engine/pagecache.h
index 635b02123..9ab7db078 100644
--- a/database/engine/pagecache.h
+++ b/database/engine/pagecache.h
@@ -5,66 +5,34 @@
#include "rrdengine.h"
+extern struct mrg *main_mrg;
+extern struct pgc *main_cache;
+extern struct pgc *open_cache;
+extern struct pgc *extent_cache;
+
/* Forward declarations */
struct rrdengine_instance;
-struct extent_info;
-struct rrdeng_page_descr;
#define INVALID_TIME (0)
#define MAX_PAGE_CACHE_FETCH_RETRIES (3)
#define PAGE_CACHE_FETCH_WAIT_TIMEOUT (3)
-/* Page flags */
-#define RRD_PAGE_DIRTY (1LU << 0)
-#define RRD_PAGE_LOCKED (1LU << 1)
-#define RRD_PAGE_READ_PENDING (1LU << 2)
-#define RRD_PAGE_WRITE_PENDING (1LU << 3)
-#define RRD_PAGE_POPULATED (1LU << 4)
-
-struct page_cache_descr {
- struct rrdeng_page_descr *descr; /* parent descriptor */
- void *page;
- unsigned long flags;
- struct page_cache_descr *prev; /* LRU */
- struct page_cache_descr *next; /* LRU */
-
- unsigned refcnt;
- uv_mutex_t mutex; /* always take it after the page cache lock or after the commit lock */
- uv_cond_t cond;
- unsigned waiters;
-};
-
-/* Page cache descriptor flags, state = 0 means no descriptor */
-#define PG_CACHE_DESCR_ALLOCATED (1LU << 0)
-#define PG_CACHE_DESCR_DESTROY (1LU << 1)
-#define PG_CACHE_DESCR_LOCKED (1LU << 2)
-#define PG_CACHE_DESCR_SHIFT (3)
-#define PG_CACHE_DESCR_USERS_MASK (((unsigned long)-1) << PG_CACHE_DESCR_SHIFT)
-#define PG_CACHE_DESCR_FLAGS_MASK (((unsigned long)-1) >> (BITS_PER_ULONG - PG_CACHE_DESCR_SHIFT))
+extern struct rrdeng_cache_efficiency_stats rrdeng_cache_efficiency_stats;
-/*
- * Page cache descriptor state bits (works for both 32-bit and 64-bit architectures):
- *
- * 63 ... 31 ... 3 | 2 | 1 | 0|
- * -----------------------------+------------+------------+-----------|
- * number of descriptor users | DESTROY | LOCKED | ALLOCATED |
- */
-struct rrdeng_page_descr {
- uuid_t *id; /* never changes */
- struct extent_info *extent;
-
- /* points to ephemeral page cache descriptor if the page resides in the cache */
- struct page_cache_descr *pg_cache_descr;
-
- /* Compare-And-Swap target for page cache descriptor allocation algorithm */
- volatile unsigned long pg_cache_descr_state;
-
- /* page information */
+struct page_descr_with_data {
+ uuid_t *id;
+ Word_t metric_id;
usec_t start_time_ut;
usec_t end_time_ut;
- uint32_t update_every_s:24;
uint8_t type;
+ uint32_t update_every_s;
uint32_t page_length;
+ uint8_t *page;
+
+ struct {
+ struct page_descr_with_data *prev;
+ struct page_descr_with_data *next;
+ } link;
};
#define PAGE_INFO_SCRATCH_SZ (8)
@@ -76,179 +44,21 @@ struct rrdeng_page_info {
uint32_t page_length;
};
-/* returns 1 for success, 0 for failure */
-typedef int pg_cache_page_info_filter_t(struct rrdeng_page_descr *);
-
-#define PAGE_CACHE_MAX_PRELOAD_PAGES (256)
-
struct pg_alignment {
- uint32_t page_length;
+ uint32_t page_position;
uint32_t refcount;
+ uint16_t initial_slots;
};
-/* maps time ranges to pages */
-struct pg_cache_page_index {
- uuid_t id;
- /*
- * care: JudyL_array indices are converted from useconds to seconds to fit in one word in 32-bit architectures
- * TODO: examine if we want to support better granularity than seconds
- */
- Pvoid_t JudyL_array;
- Word_t page_count;
- unsigned short refcount;
- unsigned short writers;
- uv_rwlock_t lock;
-
- /*
- * Only one effective writer, data deletion workqueue.
- * It's also written during the DB loading phase.
- */
- usec_t oldest_time_ut;
-
- /*
- * Only one effective writer, data collection thread.
- * It's also written by the data deletion workqueue when data collection is disabled for this metric.
- */
- usec_t latest_time_ut;
-
- struct rrdengine_instance *ctx;
- uint32_t latest_update_every_s;
-
- struct pg_cache_page_index *prev;
-};
-
-/* maps UUIDs to page indices */
-struct pg_cache_metrics_index {
- uv_rwlock_t lock;
- Pvoid_t JudyHS_array;
- struct pg_cache_page_index *last_page_index;
-};
-
-/* gathers dirty pages to be written on disk */
-struct pg_cache_committed_page_index {
- uv_rwlock_t lock;
-
- Pvoid_t JudyL_array;
-
- /*
- * Dirty page correlation ID is a hint. Dirty pages that are correlated should have
- * a small correlation ID difference. Dirty pages in memory should never have the
- * same ID at the same time for correctness.
- */
- Word_t latest_corr_id;
-
- unsigned nr_committed_pages;
-};
-
-/*
- * Gathers populated pages to be evicted.
- * Relies on page cache descriptors being there as it uses their memory.
- */
-struct pg_cache_replaceQ {
- uv_rwlock_t lock; /* LRU lock */
-
- struct page_cache_descr *head; /* LRU */
- struct page_cache_descr *tail; /* MRU */
-};
-
-struct page_cache { /* TODO: add statistics */
- uv_rwlock_t pg_cache_rwlock; /* page cache lock */
-
- struct pg_cache_metrics_index metrics_index;
- struct pg_cache_committed_page_index committed_page_index;
- struct pg_cache_replaceQ replaceQ;
-
- unsigned page_descriptors;
- unsigned populated_pages;
-};
-
-void pg_cache_wake_up_waiters_unsafe(struct rrdeng_page_descr *descr);
-void pg_cache_wake_up_waiters(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr);
-void pg_cache_wait_event_unsafe(struct rrdeng_page_descr *descr);
-unsigned long pg_cache_wait_event(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr);
-void pg_cache_replaceQ_insert(struct rrdengine_instance *ctx,
- struct rrdeng_page_descr *descr);
-void pg_cache_replaceQ_delete(struct rrdengine_instance *ctx,
- struct rrdeng_page_descr *descr);
-void pg_cache_replaceQ_set_hot(struct rrdengine_instance *ctx,
- struct rrdeng_page_descr *descr);
-struct rrdeng_page_descr *pg_cache_create_descr(void);
-int pg_cache_try_get_unsafe(struct rrdeng_page_descr *descr, int exclusive_access);
-void pg_cache_put_unsafe(struct rrdeng_page_descr *descr);
-void pg_cache_put(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr);
-void pg_cache_insert(struct rrdengine_instance *ctx, struct pg_cache_page_index *index,
- struct rrdeng_page_descr *descr);
-uint8_t pg_cache_punch_hole(struct rrdengine_instance *ctx, struct rrdeng_page_descr *descr,
- uint8_t remove_dirty, uint8_t is_exclusive_holder, uuid_t *metric_id);
-usec_t pg_cache_oldest_time_in_range(struct rrdengine_instance *ctx, uuid_t *id,
- usec_t start_time_ut, usec_t end_time_ut);
-void pg_cache_get_filtered_info_prev(struct rrdengine_instance *ctx, struct pg_cache_page_index *page_index,
- usec_t point_in_time_ut, pg_cache_page_info_filter_t *filter,
- struct rrdeng_page_info *page_info);
-struct rrdeng_page_descr *pg_cache_lookup_unpopulated_and_lock(struct rrdengine_instance *ctx, uuid_t *id,
- usec_t start_time_ut);
-unsigned
- pg_cache_preload(struct rrdengine_instance *ctx, uuid_t *id, usec_t start_time_ut, usec_t end_time_ut,
- struct rrdeng_page_info **page_info_arrayp, struct pg_cache_page_index **ret_page_indexp);
-struct rrdeng_page_descr *
- pg_cache_lookup(struct rrdengine_instance *ctx, struct pg_cache_page_index *index, uuid_t *id,
- usec_t point_in_time_ut);
-struct rrdeng_page_descr *
- pg_cache_lookup_next(struct rrdengine_instance *ctx, struct pg_cache_page_index *index, uuid_t *id,
- usec_t start_time_ut, usec_t end_time_ut);
-struct pg_cache_page_index *create_page_index(uuid_t *id, struct rrdengine_instance *ctx);
-void init_page_cache(struct rrdengine_instance *ctx);
-void free_page_cache(struct rrdengine_instance *ctx);
-void pg_cache_add_new_metric_time(struct pg_cache_page_index *page_index, struct rrdeng_page_descr *descr);
-void pg_cache_update_metric_times(struct pg_cache_page_index *page_index);
-unsigned long pg_cache_hard_limit(struct rrdengine_instance *ctx);
-unsigned long pg_cache_soft_limit(struct rrdengine_instance *ctx);
-unsigned long pg_cache_committed_hard_limit(struct rrdengine_instance *ctx);
-
-void rrdeng_page_descr_aral_go_singlethreaded(void);
-void rrdeng_page_descr_aral_go_multithreaded(void);
-void rrdeng_page_descr_use_malloc(void);
-void rrdeng_page_descr_use_mmap(void);
-bool rrdeng_page_descr_is_mmap(void);
-struct rrdeng_page_descr *rrdeng_page_descr_mallocz(void);
-void rrdeng_page_descr_freez(struct rrdeng_page_descr *descr);
-
-static inline void
- pg_cache_atomic_get_pg_info(struct rrdeng_page_descr *descr, usec_t *end_time_ut_p, uint32_t *page_lengthp)
-{
- usec_t end_time_ut, old_end_time_ut;
- uint32_t page_length;
-
- if (NULL == descr->extent) {
- /* this page is currently being modified, get consistent info locklessly */
- do {
- end_time_ut = descr->end_time_ut;
- __sync_synchronize();
- old_end_time_ut = end_time_ut;
- page_length = descr->page_length;
- __sync_synchronize();
- end_time_ut = descr->end_time_ut;
- __sync_synchronize();
- } while ((end_time_ut != old_end_time_ut || (end_time_ut & 1) != 0));
+struct rrdeng_query_handle;
+struct page_details_control;
- *end_time_ut_p = end_time_ut;
- *page_lengthp = page_length;
- } else {
- *end_time_ut_p = descr->end_time_ut;
- *page_lengthp = descr->page_length;
- }
-}
+void rrdeng_prep_wait(struct page_details_control *pdc);
+void rrdeng_prep_query(struct page_details_control *pdc);
+void pg_cache_preload(struct rrdeng_query_handle *handle);
+struct pgc_page *pg_cache_lookup_next(struct rrdengine_instance *ctx, struct page_details_control *pdc, time_t now_s, time_t last_update_every_s, size_t *entries);
+void pgc_and_mrg_initialize(void);
-/* The caller must hold a reference to the page and must have already set the new data */
-static inline void pg_cache_atomic_set_pg_info(struct rrdeng_page_descr *descr, usec_t end_time_ut, uint32_t page_length)
-{
- fatal_assert(!(end_time_ut & 1));
- __sync_synchronize();
- descr->end_time_ut |= 1; /* mark start of uncertainty period by adding 1 microsecond */
- __sync_synchronize();
- descr->page_length = page_length;
- __sync_synchronize();
- descr->end_time_ut = end_time_ut; /* mark end of uncertainty period */
-}
+void pgc_open_add_hot_page(Word_t section, Word_t metric_id, time_t start_time_s, time_t end_time_s, time_t update_every_s, struct rrdengine_datafile *datafile, uint64_t extent_offset, unsigned extent_size, uint32_t page_length);
#endif /* NETDATA_PAGECACHE_H */