Skip to content
Snippets Groups Projects
Verified Commit f9a6781c authored by Petr Špaček's avatar Petr Špaček
Browse files

gc: reformat source code to conform to Linux codestyle

Main motivation is getting rid of tab-space mix.
parent 7956fe75
Branches
Tags
1 merge request!817cache garbage collector
Pipeline #50218 canceled with stages
in 1 minute and 23 seconds
......@@ -25,7 +25,7 @@ static int get_random(int to)
}
// TODO this is just an example, make this more clever
category_t kr_gc_categorize(gc_record_info_t *info)
category_t kr_gc_categorize(gc_record_info_t * info)
{
category_t res;
......@@ -33,13 +33,13 @@ category_t kr_gc_categorize(gc_record_info_t *info)
return CATEGORIES - 1;
switch (info->no_labels) {
case 0: /* root zone */
case 0: /* root zone */
res = 5;
break;
case 1: /* TLD */
case 1: /* TLD */
res = 10;
break;
default: /* SLD and below */
default: /* SLD and below */
res = (rrtype_is_infrastructure(info->rrtype) ? 15 : 20);
if (info->entry_size > 300)
/* Penalty for big answers */
......@@ -53,4 +53,3 @@ category_t kr_gc_categorize(gc_record_info_t *info)
return res + get_random(5);
}
......@@ -4,7 +4,6 @@
typedef uint8_t category_t;
#define CATEGORIES 100 // number of categories
category_t kr_gc_categorize(gc_record_info_t *info);
#define CATEGORIES 100 // number of categories
category_t kr_gc_categorize(gc_record_info_t * info);
......@@ -5,29 +5,27 @@
#include <lib/cache/impl.h>
//#include <lib/defines.h>
#include <ctype.h> //DEBUG
#include <ctype.h> //DEBUG
#include <time.h>
#include <sys/stat.h>
struct libknot_lmdb_env
{
struct libknot_lmdb_env {
bool shared;
unsigned dbi;
void *env;
knot_mm_t *pool;
};
struct kres_lmdb_env
{
struct kres_lmdb_env {
size_t mapsize;
unsigned dbi;
void *env;
// sub-struct txn ommited
};
static knot_db_t *knot_db_t_kres2libknot(const knot_db_t *db)
static knot_db_t *knot_db_t_kres2libknot(const knot_db_t * db)
{
const struct kres_lmdb_env *kres_db = db; // this is struct lmdb_env as in resolver/cdb_lmdb.c
const struct kres_lmdb_env *kres_db = db; // this is struct lmdb_env as in resolver/cdb_lmdb.c
struct libknot_lmdb_env *libknot_db = malloc(sizeof(*libknot_db));
if (libknot_db != NULL) {
libknot_db->shared = false;
......@@ -38,7 +36,8 @@ static knot_db_t *knot_db_t_kres2libknot(const knot_db_t *db)
return libknot_db;
}
int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db, knot_db_t **libknot_db)
int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db,
knot_db_t ** libknot_db)
{
char cache_data[strlen(cache_path) + 10];
snprintf(cache_data, sizeof(cache_data), "%s/data.mdb", cache_path);
......@@ -68,7 +67,7 @@ int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db, knot_db_t
return 0;
}
void kr_gc_cache_close(struct kr_cache *kres_db, knot_db_t *knot_db)
void kr_gc_cache_close(struct kr_cache *kres_db, knot_db_t * knot_db)
{
free(knot_db);
kr_cache_close(kres_db);
......@@ -82,15 +81,15 @@ const uint16_t *kr_gc_key_consistent(knot_db_val_t key)
ssize_t i;
/* CACHE_KEY_DEF */
if (key.len >= 2 && kd[0] == '\0') {
/* Beware: root zone is special and starts with
/* Beware: root zone is special and starts with
* a single \0 followed by type sign */
i = 1;
i = 1;
} else {
/* find the first double zero in the key */
for (i = 2; kd[i - 1] || kd[i - 2]; ++i) {
if (i >= key.len)
return NULL;
}
for (i = 2; kd[i - 1] || kd[i - 2]; ++i) {
if (i >= key.len)
return NULL;
}
}
// the next character can be used for classification
switch (kd[i]) {
......@@ -99,7 +98,7 @@ const uint16_t *kr_gc_key_consistent(knot_db_val_t key)
assert(!EINVAL);
return NULL;
}
return (uint16_t *)&kd[i + 1];
return (uint16_t *) & kd[i + 1];
case '1':
return &NSEC1;
case '3':
......@@ -110,12 +109,12 @@ const uint16_t *kr_gc_key_consistent(knot_db_val_t key)
}
/// expects that key is consistent! CACHE_KEY_DEF
static uint8_t entry_labels(knot_db_val_t *key, uint16_t rrtype)
static uint8_t entry_labels(knot_db_val_t * key, uint16_t rrtype)
{
uint8_t lab = 0, *p = key->data;
while (*p != 0) {
while (*p++ != 0) {
if (p - (uint8_t *)key->data >= key->len) {
if (p - (uint8_t *) key->data >= key->len) {
return 0;
}
}
......@@ -131,7 +130,8 @@ static uint8_t entry_labels(knot_db_val_t *key, uint16_t rrtype)
}
#ifdef DEBUG
void debug_printbin(const char *str, unsigned int len) {
void debug_printbin(const char *str, unsigned int len)
{
putchar('"');
for (int idx = 0; idx < len; idx++) {
char c = str[idx];
......@@ -145,7 +145,7 @@ void debug_printbin(const char *str, unsigned int len) {
#endif
/** Return one entry_h reference from a cache DB value. NULL if not consistent/suitable. */
static const struct entry_h * val2entry(const knot_db_val_t val, uint16_t ktype)
static const struct entry_h *val2entry(const knot_db_val_t val, uint16_t ktype)
{
if (ktype != KNOT_RRTYPE_NS)
return entry_h_consistent(val, ktype);
......@@ -163,7 +163,7 @@ static const struct entry_h * val2entry(const knot_db_val_t val, uint16_t ktype)
return NULL;
}
int kr_gc_cache_iter(knot_db_t *knot_db, kr_gc_iter_callback callback, void *ctx)
int kr_gc_cache_iter(knot_db_t * knot_db, kr_gc_iter_callback callback, void *ctx)
{
#ifdef DEBUG
unsigned int counter_iter = 0;
......@@ -206,7 +206,8 @@ int kr_gc_cache_iter(knot_db_t *knot_db, kr_gc_iter_callback callback, void *ctx
info.entry_size = key.len + val.len;
info.valid = false;
const uint16_t *entry_type = ret == KNOT_EOK ? kr_gc_key_consistent(key) : NULL;
const uint16_t *entry_type =
ret == KNOT_EOK ? kr_gc_key_consistent(key) : NULL;
const struct entry_h *entry = NULL;
if (entry_type != NULL) {
#ifdef DEBUG
......@@ -228,7 +229,8 @@ int kr_gc_cache_iter(knot_db_t *knot_db, kr_gc_iter_callback callback, void *ctx
#ifdef DEBUG
counter_kr_consistent += info.valid;
printf("GC %sconsistent, KR %sconsistent, size %zu, key len %zu: ",
entry_type ? "" : "in", entry ? "" : "IN", (key.len + val.len), key.len);
entry_type ? "" : "in", entry ? "" : "IN", (key.len + val.len),
key.len);
debug_printbin(key.data, key.len);
printf("\n");
#endif
......@@ -247,7 +249,8 @@ int kr_gc_cache_iter(knot_db_t *knot_db, kr_gc_iter_callback callback, void *ctx
api->txn_abort(&txn);
#ifdef DEBUG
printf("DEBUG: iterated %u items, gc consistent %u, kr consistent %u\n", counter_iter, counter_gc_consistent, counter_kr_consistent);
printf("DEBUG: iterated %u items, gc consistent %u, kr consistent %u\n",
counter_iter, counter_gc_consistent, counter_kr_consistent);
#endif
return KNOT_EOK;
}
......@@ -5,12 +5,14 @@
#include "kr_cache_gc.h"
int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db, knot_db_t **libknot_db);
int kr_gc_cache_open(const char *cache_path, struct kr_cache *kres_db,
knot_db_t ** libknot_db);
void kr_gc_cache_close(struct kr_cache *kres_db, knot_db_t *knot_db);
void kr_gc_cache_close(struct kr_cache *kres_db, knot_db_t * knot_db);
typedef int (*kr_gc_iter_callback)(const knot_db_val_t *key, gc_record_info_t *info, void *ctx);
typedef int (*kr_gc_iter_callback)(const knot_db_val_t * key, gc_record_info_t * info,
void *ctx);
int kr_gc_cache_iter(knot_db_t *knot_db, kr_gc_iter_callback callback, void *ctx);
int kr_gc_cache_iter(knot_db_t * knot_db, kr_gc_iter_callback callback, void *ctx);
const uint16_t *kr_gc_key_consistent(knot_db_val_t key);
......@@ -24,35 +24,37 @@
typedef struct timespec gc_timer_t;
static gc_timer_t gc_timer_internal = { 0 };
static void gc_timer_start(gc_timer_t *t)
static void gc_timer_start(gc_timer_t * t)
{
(void)clock_gettime(CLOCK_MONOTONIC, t == NULL ? &gc_timer_internal : t);
}
static double gc_timer_end(gc_timer_t *t)
static double gc_timer_end(gc_timer_t * t)
{
gc_timer_t *start = t == NULL ? &gc_timer_internal : t;
gc_timer_t end = { 0 };
(void)clock_gettime(CLOCK_MONOTONIC, &end);
return (((double)end.tv_sec - (double)start->tv_sec) + ((double)end.tv_nsec - (double)start->tv_nsec) / 1e9);
return (((double)end.tv_sec - (double)start->tv_sec) +
((double)end.tv_nsec - (double)start->tv_nsec) / 1e9);
}
static unsigned long gc_timer_usecs(gc_timer_t *t)
static unsigned long gc_timer_usecs(gc_timer_t * t)
{
gc_timer_t *start = t == NULL ? &gc_timer_internal : t;
gc_timer_t end = { 0 };
(void)clock_gettime(CLOCK_MONOTONIC, &end);
return ((end.tv_sec - start->tv_sec) * 1000000UL + (end.tv_nsec - start->tv_nsec) / 1000UL);
return ((end.tv_sec - start->tv_sec) * 1000000UL +
(end.tv_nsec - start->tv_nsec) / 1000UL);
}
// section: dbval_copy
static knot_db_val_t *dbval_copy(const knot_db_val_t *from)
static knot_db_val_t *dbval_copy(const knot_db_val_t * from)
{
knot_db_val_t *to = malloc(sizeof(knot_db_val_t) + from->len);
if (to != NULL) {
memcpy(to, from, sizeof(knot_db_val_t));
to->data = to + 1; // == ((uit8_t *)to) + sizeof(knot_db_val_t)
to->data = to + 1; // == ((uit8_t *)to) + sizeof(knot_db_val_t)
memcpy(to->data, from->data, from->len);
}
return to;
......@@ -61,9 +63,8 @@ static knot_db_val_t *dbval_copy(const knot_db_val_t *from)
// section: rrtype list
dynarray_declare(rrtype, uint16_t, DYNARRAY_VISIBILITY_STATIC, 64)
dynarray_define(rrtype, uint16_t, DYNARRAY_VISIBILITY_STATIC)
static void rrtypelist_add(rrtype_dynarray_t *arr, uint16_t add_type)
dynarray_define(rrtype, uint16_t, DYNARRAY_VISIBILITY_STATIC)
static void rrtypelist_add(rrtype_dynarray_t * arr, uint16_t add_type)
{
bool already_present = false;
dynarray_foreach(rrtype, uint16_t, i, *arr) {
......@@ -77,7 +78,7 @@ static void rrtypelist_add(rrtype_dynarray_t *arr, uint16_t add_type)
}
}
static void rrtypelist_print(rrtype_dynarray_t *arr)
static void rrtypelist_print(rrtype_dynarray_t * arr)
{
char type_s[32] = { 0 };
dynarray_foreach(rrtype, uint16_t, i, *arr) {
......@@ -87,11 +88,11 @@ static void rrtypelist_print(rrtype_dynarray_t *arr)
printf("\n");
}
dynarray_declare(entry, knot_db_val_t*, DYNARRAY_VISIBILITY_STATIC, 256)
dynarray_define(entry, knot_db_val_t*, DYNARRAY_VISIBILITY_STATIC)
static void entry_dynarray_deep_free(entry_dynarray_t *d)
dynarray_declare(entry, knot_db_val_t *, DYNARRAY_VISIBILITY_STATIC, 256)
dynarray_define(entry, knot_db_val_t *, DYNARRAY_VISIBILITY_STATIC)
static void entry_dynarray_deep_free(entry_dynarray_t * d)
{
dynarray_foreach(entry, knot_db_val_t*, i, *d) {
dynarray_foreach(entry, knot_db_val_t *, i, *d) {
free(*i);
}
entry_dynarray_free(d);
......@@ -102,7 +103,7 @@ typedef struct {
size_t records;
} ctx_compute_categories_t;
int cb_compute_categories(const knot_db_val_t *key, gc_record_info_t *info, void *vctx)
int cb_compute_categories(const knot_db_val_t * key, gc_record_info_t * info, void *vctx)
{
ctx_compute_categories_t *ctx = vctx;
category_t cat = kr_gc_categorize(info);
......@@ -120,7 +121,7 @@ typedef struct {
size_t oversize_records;
} ctx_delete_categories_t;
int cb_delete_categories(const knot_db_val_t *key, gc_record_info_t *info, void *vctx)
int cb_delete_categories(const knot_db_val_t * key, gc_record_info_t * info, void *vctx)
{
ctx_delete_categories_t *ctx = vctx;
category_t cat = kr_gc_categorize(info);
......@@ -128,8 +129,7 @@ int cb_delete_categories(const knot_db_val_t *key, gc_record_info_t *info, void
knot_db_val_t *todelete = dbval_copy(key);
size_t used = ctx->used_space + key->len + sizeof(*key);
if ((ctx->cfg_temp_keys_space > 0 &&
used > ctx->cfg_temp_keys_space) ||
todelete == NULL) {
used > ctx->cfg_temp_keys_space) || todelete == NULL) {
ctx->oversize_records++;
} else {
entry_dynarray_add(&ctx->to_delete, &todelete);
......@@ -139,7 +139,7 @@ int cb_delete_categories(const knot_db_val_t *key, gc_record_info_t *info, void
return KNOT_EOK;
}
int kr_cache_gc(kr_cache_gc_cfg_t *cfg)
int kr_cache_gc(kr_cache_gc_cfg_t * cfg)
{
struct kr_cache kres_db = { 0 };
knot_db_t *db = NULL;
......@@ -152,7 +152,7 @@ int kr_cache_gc(kr_cache_gc_cfg_t *cfg)
const size_t db_size = knot_db_lmdb_get_mapsize(db);
const size_t db_usage_abs = knot_db_lmdb_get_usage(db);
const double db_usage = (double)db_usage_abs / db_size * 100.0;
#if 0 // Probably not worth it, better reduce the risk by checking more often.
#if 0 // Probably not worth it, better reduce the risk by checking more often.
if (db_usage > 90.0) {
free(*libknot_db);
kr_cache_close(kres_db);
......@@ -160,9 +160,9 @@ int kr_cache_gc(kr_cache_gc_cfg_t *cfg)
opts.maxsize = cache_size;
goto open_kr_cache;
}
# endif
#endif
const bool large_usage = db_usage >= cfg->cache_max_usage;
if (cfg->dry_run || large_usage) { // don't print this on every size check
if (cfg->dry_run || large_usage) { // don't print this on every size check
printf("Usage: %.2lf%% (%zu / %zu)\n", db_usage, db_usage_abs, db_size);
}
if (cfg->dry_run || !large_usage) {
......@@ -170,32 +170,36 @@ int kr_cache_gc(kr_cache_gc_cfg_t *cfg)
return KNOT_EOK;
}
gc_timer_t timer_analyze = { 0 }, timer_choose = { 0 }, timer_delete = { 0 }, timer_rw_txn = { 0 };
gc_timer_t timer_analyze = { 0 }, timer_choose = { 0 }, timer_delete =
{ 0 }, timer_rw_txn = { 0 };
gc_timer_start(&timer_analyze);
ctx_compute_categories_t cats = {{ 0 }};
ctx_compute_categories_t cats = { { 0 }
};
ret = kr_gc_cache_iter(db, cb_compute_categories, &cats);
if (ret != KNOT_EOK) {
kr_gc_cache_close(&kres_db, db);
return ret;
}
ssize_t amount_tofree = knot_db_lmdb_get_mapsize(db) * cfg->cache_to_be_freed / 100;
ssize_t amount_tofree =
knot_db_lmdb_get_mapsize(db) * cfg->cache_to_be_freed / 100;
// debug
/*printf("tofree: %zd\n", amount_tofree);
for (int i = 0; i < CATEGORIES; i++) {
if (cats.categories_sizes[i] > 0) {
printf("category %d size %zu\n", i, cats.categories_sizes[i]);
}
}*/
for (int i = 0; i < CATEGORIES; i++) {
if (cats.categories_sizes[i] > 0) {
printf("category %d size %zu\n", i, cats.categories_sizes[i]);
}
} */
category_t limit_category = CATEGORIES;
while (limit_category > 0 && amount_tofree > 0) {
amount_tofree -= cats.categories_sizes[--limit_category];
}
printf("Cache analyzed in %.2lf secs, %zu records, limit category is %d.\n", gc_timer_end(&timer_analyze), cats.records, limit_category);
printf("Cache analyzed in %.2lf secs, %zu records, limit category is %d.\n",
gc_timer_end(&timer_analyze), cats.records, limit_category);
gc_timer_start(&timer_choose);
ctx_delete_categories_t to_del = { 0 };
......@@ -207,8 +211,10 @@ int kr_cache_gc(kr_cache_gc_cfg_t *cfg)
kr_gc_cache_close(&kres_db, db);
return ret;
}
printf("%zu records to be deleted using %.2lf MBytes of temporary memory, %zu records skipped due to memory limit.\n",
to_del.to_delete.size, ((double)to_del.used_space / 1048576.0), to_del.oversize_records);
printf
("%zu records to be deleted using %.2lf MBytes of temporary memory, %zu records skipped due to memory limit.\n",
to_del.to_delete.size, ((double)to_del.used_space / 1048576.0),
to_del.oversize_records);
const knot_db_api_t *api = knot_db_lmdb_api();
knot_db_txn_t txn = { 0 };
......@@ -226,7 +232,7 @@ int kr_cache_gc(kr_cache_gc_cfg_t *cfg)
return ret;
}
dynarray_foreach(entry, knot_db_val_t*, i, to_del.to_delete) {
dynarray_foreach(entry, knot_db_val_t *, i, to_del.to_delete) {
ret = api->del(&txn, *i);
switch (ret) {
case KNOT_EOK:
......@@ -239,7 +245,8 @@ int kr_cache_gc(kr_cache_gc_cfg_t *cfg)
already_gone++;
break;
default:
printf("Warning: skipping deleting because of error (%s)\n", knot_strerror(ret));
printf("Warning: skipping deleting because of error (%s)\n",
knot_strerror(ret));
api->txn_abort(&txn);
ret = api->txn_begin(db, &txn, 0);
if (ret != KNOT_EOK) {
......@@ -264,9 +271,11 @@ int kr_cache_gc(kr_cache_gc_cfg_t *cfg)
}
}
printf("Deleted %zu records (%zu already gone) types", deleted_records, already_gone);
printf("Deleted %zu records (%zu already gone) types", deleted_records,
already_gone);
rrtypelist_print(&deleted_rrtypes);
printf("It took %.2lf secs, %zu transactions (%s)\n", gc_timer_end(&timer_delete), rw_txn_count, knot_strerror(ret));
printf("It took %.2lf secs, %zu transactions (%s)\n", gc_timer_end(&timer_delete),
rw_txn_count, knot_strerror(ret));
ret = api->txn_commit(&txn);
......
......@@ -5,31 +5,30 @@
#include <stdint.h>
typedef struct {
size_t entry_size; // amount of bytes occupied in cache by this record
bool valid; // fields further down are valid (ignore them if false)
int64_t expires_in; // < 0 => already expired
uint16_t rrtype;
uint8_t no_labels; // 0 == ., 1 == root zone member, 2 == TLD member ...
uint8_t rank;
size_t entry_size; // amount of bytes occupied in cache by this record
bool valid; // fields further down are valid (ignore them if false)
int64_t expires_in; // < 0 => already expired
uint16_t rrtype;
uint8_t no_labels; // 0 == ., 1 == root zone member, 2 == TLD member ...
uint8_t rank;
} gc_record_info_t;
typedef struct {
const char *cache_path; // path to the LMDB with resolver cache
unsigned long gc_interval; // waiting time between two whole garbage collections in usecs (0 = just one-time cleanup)
const char *cache_path; // path to the LMDB with resolver cache
unsigned long gc_interval; // waiting time between two whole garbage collections in usecs (0 = just one-time cleanup)
size_t temp_keys_space; // maximum amount of temporary memory for copied keys in bytes (0 = unlimited)
size_t temp_keys_space; // maximum amount of temporary memory for copied keys in bytes (0 = unlimited)
size_t rw_txn_items; // maximum number of deleted records per RW transaction (0 = unlimited)
unsigned long rw_txn_duration; // maximum duration of RW transaction in usecs (0 = unlimited)
unsigned long rw_txn_delay; // waiting time between two RW transactions in usecs
size_t rw_txn_items; // maximum number of deleted records per RW transaction (0 = unlimited)
unsigned long rw_txn_duration; // maximum duration of RW transaction in usecs (0 = unlimited)
unsigned long rw_txn_delay; // waiting time between two RW transactions in usecs
uint8_t cache_max_usage; // maximum cache usage before triggering GC (percent)
uint8_t cache_to_be_freed; // percent of cache to be freed during GC
uint8_t cache_max_usage; // maximum cache usage before triggering GC (percent)
uint8_t cache_to_be_freed; // percent of cache to be freed during GC
bool dry_run;
bool dry_run;
} kr_cache_gc_cfg_t;
int kr_cache_gc(kr_cache_gc_cfg_t *cfg);
int kr_cache_gc(kr_cache_gc_cfg_t * cfg);
#define KR_CACHE_GC_VERSION "0.2"
......@@ -127,4 +127,3 @@ int main(int argc, char *argv[])
return 0;
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment