summaryrefslogtreecommitdiffstats
path: root/lib/cache/api.h
blob: 0abe9202ffa1a5888a7a58fe1e13b2ed793af549 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*  Copyright (C) CZ.NIC, z.s.p.o. <knot-resolver@labs.nic.cz>
 *  SPDX-License-Identifier: GPL-3.0-or-later
 */

#pragma once

#include <libknot/consts.h>
#include <libknot/rrset.h>
#include <sys/time.h>
#include "lib/cache/cdb_api.h"
#include "lib/defines.h"
#include "contrib/ucw/config.h" /*uint*/

#include "lib/module.h"
/* Prototypes for the 'cache' module implementation. */
int cache_peek(kr_layer_t *ctx, knot_pkt_t *pkt);
int cache_stash(kr_layer_t *ctx, knot_pkt_t *pkt);


/**
 * Cache structure, keeps API, instance and metadata.
 */
struct kr_cache
{
	kr_cdb_pt db;                 /**< Storage instance */
	const struct kr_cdb_api *api; /**< Storage engine */
	struct kr_cdb_stats stats;
	uint32_t ttl_min, ttl_max; /**< TTL limits; enforced primarily in iterator actually. */

	/* A pair of stamps for detection of real-time shifts during runtime. */
	struct timeval checkpoint_walltime; /**< Wall time on the last check-point. */
	uint64_t checkpoint_monotime; /**< Monotonic milliseconds on the last check-point. */

	uv_timer_t *health_timer; /**< Timer used for kr_cache_check_health() */
};
// https://datatracker.ietf.org/doc/html/rfc2181#section-8
#define TTL_MAX_MAX ((1u << 31) - 1)

/**
 * Open/create cache with provided storage options.
 * @param cache cache structure to be initialized
 * @param api   storage engine API
 * @param opts  storage-specific options (may be NULL for default)
 * @param mm    memory context.
 * @return 0 or an error code
 */
KR_EXPORT
int kr_cache_open(struct kr_cache *cache, const struct kr_cdb_api *api, struct kr_cdb_opts *opts, knot_mm_t *mm);

/**
 * Path to cache file to remove on critical out-of-space error. (do NOT modify it)
 */
KR_EXPORT extern
const char *kr_cache_emergency_file_to_remove;

/**
 * Close persistent cache.
 * @note This doesn't clear the data, just closes the connection to the database.
 * @param cache structure
 */
KR_EXPORT
void kr_cache_close(struct kr_cache *cache);

/** Run after a row of operations to release transaction/lock if needed. */
KR_EXPORT
int kr_cache_commit(struct kr_cache *cache);

/**
 * Return true if cache is open and enabled.
 */
static inline bool kr_cache_is_open(struct kr_cache *cache)
{
	return cache->db != NULL;
}

/** (Re)set the time pair to the current values. */
static inline void kr_cache_make_checkpoint(struct kr_cache *cache)
{
	cache->checkpoint_monotime = kr_now();
	gettimeofday(&cache->checkpoint_walltime, NULL);
}

/**
 * Insert RRSet into cache, replacing any existing data.
 * @param cache cache structure
 * @param rr inserted RRSet
 * @param rrsig RRSIG for inserted RRSet (optional)
 * @param rank rank of the data
 * @param timestamp current time (as-if; if the RR are older, their timestamp is appropriate)
 * @param ins_nsec_p update NSEC* parameters if applicable
 * @return 0 or an errcode
 */
KR_EXPORT
int kr_cache_insert_rr(struct kr_cache *cache,
			const knot_rrset_t *rr, const knot_rrset_t *rrsig,
			uint8_t rank, uint32_t timestamp, bool ins_nsec_p);

/**
 * Clear all items from the cache.
 * @param cache cache structure
 * @return if nonzero is returned, there's a big problem - you probably want to abort(),
 * 	perhaps except for kr_error(EAGAIN) which probably indicates transient errors.
 */
KR_EXPORT
int kr_cache_clear(struct kr_cache *cache);


/* ** This interface is temporary. ** */

struct kr_cache_p {
	uint32_t time;	/**< The time of inception. */
	uint32_t ttl;	/**< TTL at inception moment.  Assuming it fits into int32_t ATM. */
	uint8_t  rank;	/**< See enum kr_rank */
	struct {
		/* internal: pointer to eh struct */
		void *raw_data, *raw_bound;
	};
};
KR_EXPORT
int kr_cache_peek_exact(struct kr_cache *cache, const knot_dname_t *name, uint16_t type,
			struct kr_cache_p *peek);
/* Parameters (qry, name, type) are used for timestamp and stale-serving decisions. */
KR_EXPORT
int32_t kr_cache_ttl(const struct kr_cache_p *peek, const struct kr_query *qry,
		     const knot_dname_t *name, uint16_t type);

KR_EXPORT
int kr_cache_materialize(knot_rdataset_t *dst, const struct kr_cache_p *ref,
			 knot_mm_t *pool);


/**
 * Remove an entry from cache.
 * @param cache cache structure
 * @param name dname
 * @param type rr type
 * @return number of deleted records, or negative error code
 * @note only "exact hits" are considered ATM, and
 * 	some other information may be removed alongside.
 */
KR_EXPORT
int kr_cache_remove(struct kr_cache *cache, const knot_dname_t *name, uint16_t type);

/**
 * Get keys matching a dname lf prefix
 * @param cache cache structure
 * @param name dname
 * @param exact_name whether to only consider exact name matches
 * @param keyval matched key-value pairs
 * @param maxcount limit on the number of returned key-value pairs
 * @return result count or an errcode
 * @note the cache keys are matched by prefix, i.e. it very much depends
 * 	on their structure; CACHE_KEY_DEF.
 */
KR_EXPORT
int kr_cache_match(struct kr_cache *cache, const knot_dname_t *name,
		   bool exact_name, knot_db_val_t keyval[][2], int maxcount);

/**
 * Remove a subtree in cache.  It's like _match but removing them instead of returning.
 * @return number of deleted entries or an errcode
 */
KR_EXPORT
int kr_cache_remove_subtree(struct kr_cache *cache, const knot_dname_t *name,
			    bool exact_name, int maxcount);

/**
 * Find the closest cached zone apex for a name (in cache).
 * @param is_DS start searching one name higher
 * @return the number of labels to remove from the name, or negative error code
 * @note timestamp is found by a syscall, and stale-serving is not considered
 */
KR_EXPORT
int kr_cache_closest_apex(struct kr_cache *cache, const knot_dname_t *name, bool is_DS,
			  knot_dname_t **apex);

/**
 * Unpack dname and type from db key
 * @param key db key representation
 * @param buf output buffer of domain name in dname format
 * @param type output for type
 * @return length of dname or an errcode
 * @note only "exact hits" are considered ATM, moreover xNAME records
 * 	are "hidden" as NS. (see comments in struct entry_h)
 */
KR_EXPORT
int kr_unpack_cache_key(knot_db_val_t key, knot_dname_t *buf, uint16_t *type);

/** Periodic kr_cdb_api::check_health().
 * @param interval in milliseconds.  0 for one-time check, -1 to stop the checks.
 * @return see check_health() for one-time check; otherwise normal kr_error() code. */
KR_EXPORT
int kr_cache_check_health(struct kr_cache *cache, int interval);