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/param/loadparm.h"
22 #include "lib/dbwrap/dbwrap_cache.h"
23 #include "lib/dbwrap/dbwrap_private.h"
24 #include "lib/dbwrap/dbwrap_rbt.h"
25 #include "lib/util/talloc_stack.h"
29 struct db_context
*backing
;
30 struct db_context
*positive
;
31 struct db_context
*negative
;
34 static bool dbwrap_cache_validate(struct db_cache_ctx
*ctx
)
38 backing_seqnum
= dbwrap_get_seqnum(ctx
->backing
);
39 if (backing_seqnum
== ctx
->seqnum
) {
43 TALLOC_FREE(ctx
->positive
);
44 ctx
->positive
= db_open_rbt(ctx
);
45 if (ctx
->positive
== NULL
) {
49 TALLOC_FREE(ctx
->negative
);
50 ctx
->negative
= db_open_rbt(ctx
);
51 if (ctx
->negative
== NULL
) {
55 ctx
->seqnum
= backing_seqnum
;
59 static NTSTATUS
dbwrap_cache_parse_record(
60 struct db_context
*db
, TDB_DATA key
,
61 void (*parser
)(TDB_DATA key
, TDB_DATA data
, void *private_data
),
64 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
65 db
->private_data
, struct db_cache_ctx
);
69 if (!dbwrap_cache_validate(ctx
)) {
70 return NT_STATUS_NO_MEMORY
;
73 if (dbwrap_exists(ctx
->negative
, key
)) {
74 return NT_STATUS_NOT_FOUND
;
76 status
= dbwrap_parse_record(ctx
->positive
, key
, parser
, private_data
);
77 if (NT_STATUS_IS_OK(status
)) {
81 status
= dbwrap_fetch(ctx
->backing
, talloc_tos(), key
, &value
);
83 if (NT_STATUS_IS_OK(status
)) {
84 dbwrap_store(ctx
->positive
, key
, value
, 0);
85 parser(key
, value
, private_data
);
86 TALLOC_FREE(value
.dptr
);
90 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
92 value
.dptr
= (uint8_t *)&c
;
93 value
.dsize
= sizeof(c
);
94 dbwrap_store(ctx
->negative
, key
, value
, 0);
95 return NT_STATUS_NOT_FOUND
;
100 static struct db_record
*dbwrap_cache_fetch_locked(
101 struct db_context
*db
, TALLOC_CTX
*mem_ctx
, TDB_DATA key
)
103 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
104 db
->private_data
, struct db_cache_ctx
);
105 return dbwrap_fetch_locked(ctx
->backing
, mem_ctx
, key
);
108 static int dbwrap_cache_traverse(struct db_context
*db
,
109 int (*f
)(struct db_record
*rec
,
113 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
114 db
->private_data
, struct db_cache_ctx
);
117 status
= dbwrap_traverse(ctx
->backing
, f
, private_data
, &ret
);
118 if (!NT_STATUS_IS_OK(status
)) {
124 static int dbwrap_cache_traverse_read(struct db_context
*db
,
125 int (*f
)(struct db_record
*rec
,
129 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
130 db
->private_data
, struct db_cache_ctx
);
133 status
= dbwrap_traverse_read(ctx
->backing
, f
, private_data
, &ret
);
134 if (!NT_STATUS_IS_OK(status
)) {
140 static int dbwrap_cache_get_seqnum(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_get_seqnum(ctx
->backing
);
147 static int dbwrap_cache_transaction_start(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_start(ctx
->backing
);
154 static int dbwrap_cache_transaction_commit(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_commit(ctx
->backing
);
161 static int dbwrap_cache_transaction_cancel(struct db_context
*db
)
163 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
164 db
->private_data
, struct db_cache_ctx
);
165 return dbwrap_transaction_cancel(ctx
->backing
);
168 static int dbwrap_cache_exists(struct db_context
*db
, TDB_DATA key
)
170 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
171 db
->private_data
, struct db_cache_ctx
);
173 if (ctx
->positive
&& dbwrap_exists(ctx
->positive
, key
)) {
176 if (ctx
->negative
&& dbwrap_exists(ctx
->negative
, key
)) {
179 return dbwrap_exists(ctx
->backing
, key
);
182 static void dbwrap_cache_id(struct db_context
*db
, const uint8_t **id
,
185 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
186 db
->private_data
, struct db_cache_ctx
);
187 dbwrap_db_id(ctx
->backing
, id
, idlen
);
190 struct db_context
*db_open_cache(TALLOC_CTX
*mem_ctx
,
191 struct db_context
*backing
)
193 struct db_context
*db
;
194 struct db_cache_ctx
*ctx
;
196 db
= talloc_zero(mem_ctx
, struct db_context
);
200 ctx
= talloc_zero(db
, struct db_cache_ctx
);
207 ctx
->backing
= talloc_move(ctx
, &backing
);
208 db
->private_data
= ctx
;
209 if (!dbwrap_cache_validate(ctx
)) {
214 db
->fetch_locked
= dbwrap_cache_fetch_locked
;
215 db
->traverse
= dbwrap_cache_traverse
;
216 db
->traverse_read
= dbwrap_cache_traverse_read
;
217 db
->get_seqnum
= dbwrap_cache_get_seqnum
;
218 db
->transaction_start
= dbwrap_cache_transaction_start
;
219 db
->transaction_commit
= dbwrap_cache_transaction_commit
;
220 db
->transaction_cancel
= dbwrap_cache_transaction_cancel
;
221 db
->parse_record
= dbwrap_cache_parse_record
;
222 db
->exists
= dbwrap_cache_exists
;
223 db
->id
= dbwrap_cache_id
;
224 db
->name
= dbwrap_name(ctx
->backing
);
225 db
->hash_size
= dbwrap_hash_size(ctx
->backing
);