// SPDX-License-Identifier: GPL-3.0-or-later
#include "page.h"
#include "daemon/global_statistics.h"
#include "libnetdata/libnetdata.h"
typedef enum __attribute__((packed)) {
PAGE_OPTION_ALL_VALUES_EMPTY = (1 << 0),
} PAGE_OPTIONS;
typedef enum __attribute__((packed)) {
PGD_STATE_CREATED_FROM_COLLECTOR = (1 << 0),
PGD_STATE_CREATED_FROM_DISK = (1 << 1),
PGD_STATE_SCHEDULED_FOR_FLUSHING = (1 << 2),
PGD_STATE_FLUSHED_TO_DISK = (1 << 3),
} PGD_STATES;
typedef struct {
uint8_t *data;
uint32_t size;
} page_raw_t;
typedef struct {
storage_number v;
uint32_t n;
} page_constant_t;
typedef struct {
size_t num_buffers;
gorilla_writer_t *writer;
int aral_index;
} page_gorilla_t;
struct pgd {
// the page type
uint8_t type;
// options related to the page
PAGE_OPTIONS options;
PGD_STATES states;
// the uses number of slots in the page
uint32_t used;
// the total number of slots available in the page
uint32_t slots;
union {
page_raw_t raw;
page_gorilla_t gorilla;
page_constant_t constant;
};
};
// ----------------------------------------------------------------------------
// memory management
struct {
ARAL *aral_pgd;
ARAL *aral_data[RRD_STORAGE_TIERS];
ARAL *aral_gorilla_buffer[4];
ARAL *aral_gorilla_writer[4];
} pgd_alloc_globals = {};
static ARAL *pgd_aral_data_lookup(size_t size)
{
for (size_t tier = 0; tier < storage_tiers; tier++)
if (size == tier_page_size[tier])
return pgd_alloc_globals.aral_data[tier];
return NULL;
}
void pgd_init_arals(void)
{
// pgd aral
{
char buf[20 + 1];
snprintfz(buf, sizeof(buf) - 1, "pgd");
// FIXME: add stats
pgd_alloc_globals.aral_pgd = aral_create(
buf,
sizeof(struct pgd),
64,
512 * (sizeof(struct pgd)),
pgc_aral_statistics(),
NULL, NULL, false, false);
}
// tier page aral
{
for (size_t i = storage_tiers; i > 0 ;i--)
{
size_t tier = storage_tiers - i;
char buf[20 + 1];
snprintfz(buf, sizeof(buf) - 1, "tier%zu-pages", tier);
pgd_alloc_globals.aral_data[tier] = aral_create(
buf,
tier_page_size[tier],
64,
512 * (tier_page_size[tier]),
pgc_aral_statistics(),
NULL, NULL, false, false);
}
}
// gorilla buffers aral
for (size_t i = 0; i != 4; i++) {
char buf[20 + 1];
snprintfz(buf, sizeof(buf) - 1, "gbuffer-%zu", i);
// FIXME: add stats
pgd_alloc_globals.aral_gorilla_buffer[i] = aral_create(
buf,
GORILLA_BUFFER_SIZE,
64,
512 * GORILLA_BUFFER_SIZE,
pgc_aral_statistics(),
NULL, NULL, false, false);
}
// gorilla writers aral
for (size_t i = 0; i != 4; i++) {
char buf[20 + 1];
snprintfz(buf, sizeof(buf) - 1, "gwriter-%zu", i);
// FIXME: add stats
pgd_alloc_globals.aral_gorilla_writer[i] = aral_create(
buf,
sizeof(gorilla_writer_t),
64,
512 * sizeof(gorilla_writer_t),
pgc_aral_statistics(),
NULL, NULL, false, false);
}
}
static void *pgd_data_aral_alloc(size_t size)
{
ARAL *ar = pgd_aral_data_lookup(size);
if (!ar)
return mallocz(size);
else
return aral_mallocz(ar);
}
static void pgd_data_aral_free(void *page, size_t size)
{
ARAL *ar = pgd_aral_data_lookup(size);
if (!ar)
freez(page);
else
aral_freez(ar, page);
}
// ----------------------------------------------------------------------------
// management api
PGD *pgd_create(uint8_t type, uint32_t slots)
{
PGD *pg = aral_mallocz(pgd_alloc_globals.aral_pgd);
pg->type = type;
pg->used = 0;
pg->slots = slots;
pg->options = PAGE_OPTION_ALL_VALUES_EMPTY;
pg->states = PGD_STATE_CREATED_FROM_COLLECTOR;
switch (type) {
case PAGE_RAW_METRICS:
global_statistic_raw_page_new();
// intentional fall-through
case PAGE_TIER: {
uint32_t size = slots * page_type_size[type];
internal_fatal(!size || slots == 1,
"DBENGINE: invalid number of slots (%u) or page type (%