2 Unix SMB/CIFS implementation.
3 Cache db contents for parse_record based on seqnum
4 Copyright (C) Volker Lendecke 2012
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "lib/dbwrap/dbwrap.h"
22 #include "lib/dbwrap/dbwrap_private.h"
23 #include "lib/dbwrap/dbwrap_rbt.h"
24 #include "lib/dbwrap/dbwrap_cache.h"
28 struct db_context
*backing
;
29 struct db_context
*positive
;
30 struct db_context
*negative
;
33 static void dbwrap_cache_validate(struct db_cache_ctx
*ctx
)
35 if (ctx
->seqnum
== dbwrap_get_seqnum(ctx
->backing
)) {
38 TALLOC_FREE(ctx
->positive
);
39 ctx
->positive
= db_open_rbt(ctx
);
40 TALLOC_FREE(ctx
->negative
);
41 ctx
->negative
= db_open_rbt(ctx
);
44 static NTSTATUS
dbwrap_cache_parse_record(
45 struct db_context
*db
, TDB_DATA key
,
46 void (*parser
)(TDB_DATA key
, TDB_DATA data
, void *private_data
),
49 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
50 db
->private_data
, struct db_cache_ctx
);
54 dbwrap_cache_validate(ctx
);
56 if (ctx
->positive
!= NULL
) {
57 status
= dbwrap_parse_record(
58 ctx
->positive
, key
, parser
, private_data
);
59 if (NT_STATUS_IS_OK(status
)) {
63 if ((ctx
->negative
!= NULL
) && dbwrap_exists(ctx
->negative
, key
)) {
64 return NT_STATUS_NOT_FOUND
;
67 status
= dbwrap_fetch(ctx
->backing
, talloc_tos(), key
, &value
);
69 if (NT_STATUS_IS_OK(status
)) {
70 dbwrap_store(ctx
->positive
, key
, value
, 0);
71 parser(key
, value
, private_data
);
72 TALLOC_FREE(value
.dptr
);
76 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
78 value
.dptr
= (uint8_t *)&c
;
79 value
.dsize
= sizeof(c
);
80 dbwrap_store(ctx
->negative
, key
, value
, 0);
81 return NT_STATUS_NOT_FOUND
;
86 static struct db_record
*dbwrap_cache_fetch_locked(
87 struct db_context
*db
, TALLOC_CTX
*mem_ctx
, TDB_DATA key
)
89 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
90 db
->private_data
, struct db_cache_ctx
);
91 return dbwrap_fetch_locked(ctx
->backing
, mem_ctx
, key
);
94 static int dbwrap_cache_traverse(struct db_context
*db
,
95 int (*f
)(struct db_record
*rec
,
99 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
100 db
->private_data
, struct db_cache_ctx
);
103 status
= dbwrap_traverse(ctx
->backing
, f
, private_data
, &ret
);
104 if (!NT_STATUS_IS_OK(status
)) {
110 static int dbwrap_cache_traverse_read(struct db_context
*db
,
111 int (*f
)(struct db_record
*rec
,
115 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
116 db
->private_data
, struct db_cache_ctx
);
119 status
= dbwrap_traverse_read(ctx
->backing
, f
, private_data
, &ret
);
120 if (!NT_STATUS_IS_OK(status
)) {
126 static int dbwrap_cache_get_seqnum(struct db_context
*db
)
128 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
129 db
->private_data
, struct db_cache_ctx
);
130 return dbwrap_get_seqnum(ctx
->backing
);
133 static int dbwrap_cache_get_flags(struct db_context
*db
)
135 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
136 db
->private_data
, struct db_cache_ctx
);
137 return dbwrap_get_flags(ctx
->backing
);
140 static int dbwrap_cache_transaction_start(struct db_context
*db
)
142 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
143 db
->private_data
, struct db_cache_ctx
);
144 return dbwrap_transaction_start(ctx
->backing
);
147 static int dbwrap_cache_transaction_commit(struct db_context
*db
)
149 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
150 db
->private_data
, struct db_cache_ctx
);
151 return dbwrap_transaction_commit(ctx
->backing
);
154 static int dbwrap_cache_transaction_cancel(struct db_context
*db
)
156 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
157 db
->private_data
, struct db_cache_ctx
);
158 return dbwrap_transaction_cancel(ctx
->backing
);
161 static int dbwrap_cache_exists(struct db_context
*db
, TDB_DATA key
)
163 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
164 db
->private_data
, struct db_cache_ctx
);
166 if (ctx
->positive
&& dbwrap_exists(ctx
->positive
, key
)) {
169 if (ctx
->negative
&& dbwrap_exists(ctx
->negative
, key
)) {
172 return dbwrap_exists(ctx
->backing
, key
);
175 struct db_context
*db_open_cache(TALLOC_CTX
*mem_ctx
,
176 struct db_context
*backing
)
178 struct db_context
*db
;
179 struct db_cache_ctx
*ctx
;
181 db
= talloc(mem_ctx
, struct db_context
);
185 ctx
= talloc_zero(db
, struct db_cache_ctx
);
192 ctx
->backing
= talloc_move(ctx
, &backing
);
193 db
->private_data
= ctx
;
194 dbwrap_cache_validate(ctx
);
196 db
->fetch_locked
= dbwrap_cache_fetch_locked
;
197 db
->traverse
= dbwrap_cache_traverse
;
198 db
->traverse_read
= dbwrap_cache_traverse_read
;
199 db
->get_seqnum
= dbwrap_cache_get_seqnum
;
200 db
->get_flags
= dbwrap_cache_get_flags
;
201 db
->transaction_start
= dbwrap_cache_transaction_start
;
202 db
->transaction_commit
= dbwrap_cache_transaction_commit
;
203 db
->transaction_cancel
= dbwrap_cache_transaction_cancel
;
204 db
->parse_record
= dbwrap_cache_parse_record
;
205 db
->exists
= dbwrap_cache_exists
;
208 db
->persistent
= false;