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
195
196
197
198
199
200
201
|
/* Copyright (C) 2014-2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#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*/
/** When knot_pkt is passed from cache without ->wire, this is the ->size. */
static const size_t PKT_SIZE_NOWIRE = -1;
#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
{
knot_db_t *db; /**< Storage instance */
const struct kr_cdb_api *api; /**< Storage engine */
struct {
uint32_t hit; /**< Number of cache hits */
uint32_t miss; /**< Number of cache misses */
uint32_t insert; /**< Number of insertions */
uint32_t delete; /**< Number of deletions */
} stats;
uint32_t ttl_min, ttl_max; /**< TTL limits */
/* 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. */
};
/**
* 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_sync(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
* @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);
/**
* Clear all items from the cache.
* @param cache cache structure
* @return 0 or an errcode
*/
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);
|