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 bool dbwrap_cache_validate(struct db_cache_ctx
*ctx
)
37 backing_seqnum
= dbwrap_get_seqnum(ctx
->backing
);
38 if (backing_seqnum
== ctx
->seqnum
) {
42 TALLOC_FREE(ctx
->positive
);
43 ctx
->positive
= db_open_rbt(ctx
);
44 if (ctx
->positive
== NULL
) {
48 TALLOC_FREE(ctx
->negative
);
49 ctx
->negative
= db_open_rbt(ctx
);
50 if (ctx
->negative
== NULL
) {
54 ctx
->seqnum
= backing_seqnum
;
58 static NTSTATUS
dbwrap_cache_parse_record(
59 struct db_context
*db
, TDB_DATA key
,
60 void (*parser
)(TDB_DATA key
, TDB_DATA data
, void *private_data
),
63 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
64 db
->private_data
, struct db_cache_ctx
);
68 if (!dbwrap_cache_validate(ctx
)) {
69 return NT_STATUS_NO_MEMORY
;
72 if (dbwrap_exists(ctx
->negative
, key
)) {
73 return NT_STATUS_NOT_FOUND
;
75 status
= dbwrap_parse_record(ctx
->positive
, key
, parser
, private_data
);
76 if (NT_STATUS_IS_OK(status
)) {
80 status
= dbwrap_fetch(ctx
->backing
, talloc_tos(), key
, &value
);
82 if (NT_STATUS_IS_OK(status
)) {
83 dbwrap_store(ctx
->positive
, key
, value
, 0);
84 parser(key
, value
, private_data
);
85 TALLOC_FREE(value
.dptr
);
89 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
91 value
.dptr
= (uint8_t *)&c
;
92 value
.dsize
= sizeof(c
);
93 dbwrap_store(ctx
->negative
, key
, value
, 0);
94 return NT_STATUS_NOT_FOUND
;
99 static struct db_record
*dbwrap_cache_fetch_locked(
100 struct db_context
*db
, TALLOC_CTX
*mem_ctx
, TDB_DATA key
)
102 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
103 db
->private_data
, struct db_cache_ctx
);
104 return dbwrap_fetch_locked(ctx
->backing
, mem_ctx
, key
);
107 static int dbwrap_cache_traverse(struct db_context
*db
,
108 int (*f
)(struct db_record
*rec
,
112 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
113 db
->private_data
, struct db_cache_ctx
);
116 status
= dbwrap_traverse(ctx
->backing
, f
, private_data
, &ret
);
117 if (!NT_STATUS_IS_OK(status
)) {
123 static int dbwrap_cache_traverse_read(struct db_context
*db
,
124 int (*f
)(struct db_record
*rec
,
128 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
129 db
->private_data
, struct db_cache_ctx
);
132 status
= dbwrap_traverse_read(ctx
->backing
, f
, private_data
, &ret
);
133 if (!NT_STATUS_IS_OK(status
)) {
139 static int dbwrap_cache_get_seqnum(struct db_context
*db
)
141 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
142 db
->private_data
, struct db_cache_ctx
);
143 return dbwrap_get_seqnum(ctx
->backing
);
146 static int dbwrap_cache_transaction_start(struct db_context
*db
)
148 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
149 db
->private_data
, struct db_cache_ctx
);
150 return dbwrap_transaction_start(ctx
->backing
);
153 static int dbwrap_cache_transaction_commit(struct db_context
*db
)
155 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
156 db
->private_data
, struct db_cache_ctx
);
157 return dbwrap_transaction_commit(ctx
->backing
);
160 static int dbwrap_cache_transaction_cancel(struct db_context
*db
)
162 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
163 db
->private_data
, struct db_cache_ctx
);
164 return dbwrap_transaction_cancel(ctx
->backing
);
167 static int dbwrap_cache_exists(struct db_context
*db
, TDB_DATA key
)
169 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
170 db
->private_data
, struct db_cache_ctx
);
172 if (ctx
->positive
&& dbwrap_exists(ctx
->positive
, key
)) {
175 if (ctx
->negative
&& dbwrap_exists(ctx
->negative
, key
)) {
178 return dbwrap_exists(ctx
->backing
, key
);
181 static void dbwrap_cache_id(struct db_context
*db
, const uint8_t **id
,
184 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
185 db
->private_data
, struct db_cache_ctx
);
186 dbwrap_db_id(ctx
->backing
, id
, idlen
);
189 struct db_context
*db_open_cache(TALLOC_CTX
*mem_ctx
,
190 struct db_context
*backing
)
192 struct db_context
*db
;
193 struct db_cache_ctx
*ctx
;
195 db
= talloc_zero(mem_ctx
, struct db_context
);
199 ctx
= talloc_zero(db
, struct db_cache_ctx
);
206 ctx
->backing
= talloc_move(ctx
, &backing
);
207 db
->private_data
= ctx
;
208 if (!dbwrap_cache_validate(ctx
)) {
213 db
->fetch_locked
= dbwrap_cache_fetch_locked
;
214 db
->traverse
= dbwrap_cache_traverse
;
215 db
->traverse_read
= dbwrap_cache_traverse_read
;
216 db
->get_seqnum
= dbwrap_cache_get_seqnum
;
217 db
->transaction_start
= dbwrap_cache_transaction_start
;
218 db
->transaction_commit
= dbwrap_cache_transaction_commit
;
219 db
->transaction_cancel
= dbwrap_cache_transaction_cancel
;
220 db
->parse_record
= dbwrap_cache_parse_record
;
221 db
->exists
= dbwrap_cache_exists
;
222 db
->id
= dbwrap_cache_id
;
223 db
->name
= dbwrap_name(ctx
->backing
);
224 db
->hash_size
= dbwrap_hash_size(ctx
->backing
);