Skip to content

Commit 08ad89a

Browse files
authored
Merge pull request #1178 from tempesta-tech/ab-client_tdb
Temporal client accounting
2 parents 3288f6d + 1d1b901 commit 08ad89a

19 files changed

+614
-189
lines changed

etc/tempesta_fw.conf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,3 +1129,23 @@
11291129
# Default:
11301130
# Health monitor is disabled.
11311131
#
1132+
1133+
# TAG: client_db
1134+
#
1135+
# Path to a client database file used as a storage for clients info.
1136+
# The same as cache_db.
1137+
#
1138+
# Default:
1139+
# client_db /opt/tempesta/db/client.tdb;
1140+
#
1141+
1142+
# TAG: client_tbl_size
1143+
#
1144+
# Size of client drop table.
1145+
#
1146+
# Syntax:
1147+
# client_tbl_size SIZE
1148+
#
1149+
# Default:
1150+
# client_tbl_size 16777216; # 16MB
1151+
#

lib/common.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Tempesta kernel library
3+
*
4+
* Copyright (C) 2019 Tempesta Technologies, Inc.
5+
*
6+
* This program is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License,
9+
* or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE.
14+
* See the GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License along with
17+
* this program; if not, write to the Free Software Foundation, Inc., 59
18+
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19+
*/
20+
#ifndef __LIB_COMMON_H__
21+
#define __LIB_COMMON_H__
22+
23+
/* Get current timestamp in secs. */
24+
static inline time_t
25+
tfw_current_timestamp(void)
26+
{
27+
struct timespec ts;
28+
getnstimeofday(&ts);
29+
return ts.tv_sec;
30+
}
31+
32+
#endif /* __LIB_COMMON_H__ */

tempesta_db/core/htrie.c

Lines changed: 99 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,28 @@ tdb_htrie_lookup(TdbHdr *dbh, unsigned long key)
806806
return TDB_PTR(dbh, o);
807807
}
808808

809+
#define TDB_HTRIE_FOREACH_REC(dbh, b_tmp, b, r, body) \
810+
read_lock_bh(&(*b)->lock); \
811+
do { \
812+
r = TDB_HTRIE_BCKT_1ST_REC(*b); \
813+
do { \
814+
size_t rlen = sizeof(*r) + \
815+
TDB_HTRIE_RBODYLEN(dbh, r); \
816+
rlen = TDB_HTRIE_RALIGN(rlen); \
817+
if ((char *)r + rlen - (char *)*b \
818+
> TDB_HTRIE_MINDREC \
819+
&& r != TDB_HTRIE_BCKT_1ST_REC(*b)) \
820+
break; \
821+
body; \
822+
r = (TdbRec *)((char *)r + rlen); \
823+
} while ((char *)r + sizeof(*r) - (char *)*b \
824+
<= TDB_HTRIE_MINDREC); \
825+
b_tmp = TDB_HTRIE_BUCKET_NEXT(dbh, *b); \
826+
if (b_tmp) \
827+
read_lock_bh(&b_tmp->lock); \
828+
read_unlock_bh(&(*b)->lock); \
829+
*b = b_tmp; \
830+
} while (*b)
809831
/**
810832
* Iterate over all records in collision chain with locked buckets.
811833
* Buckets are inspected according to following rules:
@@ -821,29 +843,11 @@ tdb_htrie_bscan_for_rec(TdbHdr *dbh, TdbBucket **b, unsigned long key)
821843
TdbBucket *b_tmp;
822844
TdbRec *r;
823845

824-
read_lock_bh(&(*b)->lock);
825-
826-
do {
827-
r = TDB_HTRIE_BCKT_1ST_REC(*b);
828-
do {
829-
size_t rlen = sizeof(*r) + TDB_HTRIE_RBODYLEN(dbh, r);
830-
rlen = TDB_HTRIE_RALIGN(rlen);
831-
if ((char *)r + rlen - (char *)*b > TDB_HTRIE_MINDREC
832-
&& r != TDB_HTRIE_BCKT_1ST_REC(*b))
833-
break;
834-
if (tdb_live_rec(dbh, r) && r->key == key)
835-
/* Unlock the bucket by tdb_rec_put(). */
836-
return r;
837-
r = (TdbRec *)((char *)r + rlen);
838-
} while ((char *)r + sizeof(*r) - (char *)*b
839-
<= TDB_HTRIE_MINDREC);
840-
841-
b_tmp = TDB_HTRIE_BUCKET_NEXT(dbh, *b);
842-
if (b_tmp)
843-
read_lock_bh(&b_tmp->lock);
844-
read_unlock_bh(&(*b)->lock);
845-
*b = b_tmp;
846-
} while (*b);
846+
TDB_HTRIE_FOREACH_REC(dbh, b_tmp, b, r, {
847+
if (tdb_live_rec(dbh, r) && r->key == key)
848+
/* Unlock the bucket by tdb_rec_put(). */
849+
return r;
850+
});
847851

848852
return NULL;
849853
}
@@ -931,3 +935,75 @@ tdb_htrie_exit(TdbHdr *dbh)
931935
{
932936
free_percpu(dbh->pcpu);
933937
}
938+
939+
static int
940+
tdb_htrie_bucket_walk(TdbHdr *dbh, TdbBucket *b, int (*fn)(void *))
941+
{
942+
TdbBucket *b_tmp;
943+
TdbRec *r;
944+
945+
TDB_HTRIE_FOREACH_REC(dbh, b_tmp, &b, r, {
946+
if (tdb_live_rec(dbh, r)) {
947+
int res = fn(r->data);
948+
if (unlikely(res)) {
949+
read_unlock_bh(&b->lock);
950+
return res;
951+
}
952+
}
953+
});
954+
955+
return 0;
956+
}
957+
958+
static int
959+
tdb_htrie_node_visit(TdbHdr *dbh, TdbHtrieNode *node, int (*fn)(void *))
960+
{
961+
int bits;
962+
int res;
963+
964+
for (bits = 0; bits < TDB_HTRIE_FANOUT; ++bits) {
965+
unsigned long o;
966+
967+
BUG_ON(TDB_HTRIE_RESOLVED(bits));
968+
969+
o = node->shifts[bits];
970+
971+
if (likely(!o))
972+
continue;
973+
974+
BUG_ON(TDB_DI2O(o & ~TDB_HTRIE_DBIT) < TDB_HDR_SZ(dbh) + sizeof(TdbExt)
975+
|| TDB_DI2O(o & ~TDB_HTRIE_DBIT) > dbh->dbsz);
976+
977+
if (o & TDB_HTRIE_DBIT) {
978+
TdbBucket *b;
979+
980+
/* We're at a data pointer - resolve it. */
981+
o ^= TDB_HTRIE_DBIT;
982+
BUG_ON(!o);
983+
984+
b = (TdbBucket *)TDB_PTR(dbh, TDB_DI2O(o));
985+
res = tdb_htrie_bucket_walk(dbh, b, fn);
986+
if (unlikely(res))
987+
return res;
988+
} else {
989+
/*
990+
* The recursion depth being hard-limited.
991+
* The function has the deepest nesting 16.
992+
*/
993+
res = tdb_htrie_node_visit(dbh, TDB_PTR(dbh,
994+
TDB_II2O(o)), fn);
995+
if (unlikely(res))
996+
return res;
997+
}
998+
}
999+
1000+
return 0;
1001+
}
1002+
1003+
int
1004+
tdb_htrie_walk(TdbHdr *dbh, int (*fn)(void *))
1005+
{
1006+
TdbHtrieNode *node = TDB_HTRIE_ROOT(dbh);
1007+
1008+
return tdb_htrie_node_visit(dbh, node, fn);
1009+
}

tempesta_db/core/htrie.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,6 @@ TdbRec *tdb_htrie_next_rec(TdbHdr *dbh, TdbRec *r, TdbBucket **b,
140140
unsigned long key);
141141
TdbHdr *tdb_htrie_init(void *p, size_t db_size, unsigned int rec_len);
142142
void tdb_htrie_exit(TdbHdr *dbh);
143+
int tdb_htrie_walk(TdbHdr *dbh, int (*fn)(void *));
143144

144145
#endif /* __HTRIE_H__ */

tempesta_db/core/main.c

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,16 @@
2828
#include "table.h"
2929
#include "tdb_if.h"
3030

31-
#define TDB_VERSION "0.1.16"
31+
#define TDB_VERSION "0.1.17"
3232

3333
MODULE_AUTHOR("Tempesta Technologies");
3434
MODULE_DESCRIPTION("Tempesta DB");
3535
MODULE_VERSION(TDB_VERSION);
3636
MODULE_LICENSE("GPL");
3737

38+
/* Lock for atomic execution of lookup and create a record TDB */
39+
static DEFINE_SPINLOCK(get_alloc_lock);
40+
3841
/**
3942
* Create TDB entry and copy @len contiguous bytes from @data to the entry.
4043
*/
@@ -52,6 +55,7 @@ EXPORT_SYMBOL(tdb_entry_create);
5255

5356
/**
5457
* Create TDB entry to store @len bytes.
58+
* TODO #515 function must holds a lock upon return.
5559
*/
5660
TdbRec *
5761
tdb_entry_alloc(TDB *db, unsigned long key, size_t *len)
@@ -222,6 +226,63 @@ tdb_get_db(const char *path, int node)
222226
return tdb_get(db);
223227
}
224228

229+
/**
230+
* Lookup and get a record if the record is found or create TDB entry to store
231+
* @len bytes. If record exist then since we don't copy returned records,
232+
* we have to lock the memory location where the record is placed and
233+
* the user must call tdb_rec_put() when finish with the record.
234+
*
235+
* The caller must not call sleeping functions during work with the record.
236+
* Typically there is only one large record per bucket, so the bucket lock
237+
* is exactly the same as to lock the record. While there could be many
238+
* small records in a bucket, so the caller should not perform long jobs
239+
* with small records.
240+
*
241+
* @return pointer to record with acquired bucket lock if the record is
242+
* found and create TDB entry without acquired locks otherwise.
243+
*
244+
* TODO #515 rework the function in lock-free way.
245+
* TODO #515 TDB must be extended to support small records with constant memory
246+
* address.
247+
*/
248+
TdbRec *
249+
tdb_rec_get_alloc(TDB *db, unsigned long key, size_t *len,
250+
bool (*predicate)(TdbRec *, void (*)(void *), void *),
251+
void (*init)(TdbRec *, void (*)(void *), void *),
252+
void (*cb)(void *), void *data, bool *is_new)
253+
{
254+
TdbIter iter;
255+
TdbRec *r;
256+
257+
spin_lock(&get_alloc_lock);
258+
259+
*is_new = false;
260+
iter = tdb_rec_get(db, key);
261+
while (!TDB_ITER_BAD(iter)) {
262+
if ((*predicate)(iter.rec, cb, data)) {
263+
spin_unlock(&get_alloc_lock);
264+
return iter.rec;
265+
}
266+
tdb_rec_next(db, &iter);
267+
}
268+
269+
*is_new = true;
270+
r = tdb_entry_alloc(db, key, len);
271+
init(r, cb, data);
272+
273+
spin_unlock(&get_alloc_lock);
274+
275+
return r;
276+
}
277+
EXPORT_SYMBOL(tdb_rec_get_alloc);
278+
279+
int
280+
tdb_entry_walk(TDB *db, int (*fn)(void *))
281+
{
282+
return tdb_htrie_walk(db->hdr, fn);
283+
}
284+
EXPORT_SYMBOL(tdb_entry_walk);
285+
225286
/**
226287
* Open database file and @return its descriptor.
227288
* If the database is already opened, then returns the handler.

tempesta_db/core/tdb.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@ TdbIter tdb_rec_get(TDB *db, unsigned long key);
173173
void tdb_rec_next(TDB *db, TdbIter *iter);
174174
void tdb_rec_put(void *rec);
175175
int tdb_info(char *buf, size_t len);
176+
TdbRec * tdb_rec_get_alloc(TDB *db, unsigned long key, size_t *len,
177+
bool (*predicate)(TdbRec *, void (*)(void *), void *),
178+
void (*init)(TdbRec *, void (*)(void *), void *),
179+
void (*cb)(void *), void *data, bool *is_new);
180+
int tdb_entry_walk(TDB *db, int (*fn)(void *));
181+
void tdb_rec_get_lock(void *rec);
176182

177183
/* Open/close database handler. */
178184
TDB *tdb_open(const char *path, size_t fsize, unsigned int rec_size, int node);

tempesta_fw/cache.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "procfs.h"
3838
#include "sync_socket.h"
3939
#include "work_queue.h"
40+
#include "lib/common.h"
4041

4142
#if MAX_NUMNODES > ((1 << 16) - 1)
4243
#warning "Please set CONFIG_NODES_SHIFT to less than 16"

0 commit comments

Comments
 (0)