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
)
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
);
43 return ((ctx
->positive
!= NULL
) && (ctx
->negative
!= NULL
));
46 static NTSTATUS
dbwrap_cache_parse_record(
47 struct db_context
*db
, TDB_DATA key
,
48 void (*parser
)(TDB_DATA key
, TDB_DATA data
, void *private_data
),
51 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
52 db
->private_data
, struct db_cache_ctx
);
56 if (!dbwrap_cache_validate(ctx
)) {
57 return NT_STATUS_NO_MEMORY
;
60 status
= dbwrap_parse_record(ctx
->positive
, key
, parser
, private_data
);
61 if (NT_STATUS_IS_OK(status
)) {
64 if (dbwrap_exists(ctx
->negative
, key
)) {
65 return NT_STATUS_NOT_FOUND
;
68 status
= dbwrap_fetch(ctx
->backing
, talloc_tos(), key
, &value
);
70 if (NT_STATUS_IS_OK(status
)) {
71 dbwrap_store(ctx
->positive
, key
, value
, 0);
72 parser(key
, value
, private_data
);
73 TALLOC_FREE(value
.dptr
);
77 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
79 value
.dptr
= (uint8_t *)&c
;
80 value
.dsize
= sizeof(c
);
81 dbwrap_store(ctx
->negative
, key
, value
, 0);
82 return NT_STATUS_NOT_FOUND
;
87 static struct db_record
*dbwrap_cache_fetch_locked(
88 struct db_context
*db
, TALLOC_CTX
*mem_ctx
, TDB_DATA key
)
90 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
91 db
->private_data
, struct db_cache_ctx
);
92 return dbwrap_fetch_locked(ctx
->backing
, mem_ctx
, key
);
95 static int dbwrap_cache_traverse(struct db_context
*db
,
96 int (*f
)(struct db_record
*rec
,
100 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
101 db
->private_data
, struct db_cache_ctx
);
104 status
= dbwrap_traverse(ctx
->backing
, f
, private_data
, &ret
);
105 if (!NT_STATUS_IS_OK(status
)) {
111 static int dbwrap_cache_traverse_read(struct db_context
*db
,
112 int (*f
)(struct db_record
*rec
,
116 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
117 db
->private_data
, struct db_cache_ctx
);
120 status
= dbwrap_traverse_read(ctx
->backing
, f
, private_data
, &ret
);
121 if (!NT_STATUS_IS_OK(status
)) {
127 static int dbwrap_cache_get_seqnum(struct db_context
*db
)
129 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
130 db
->private_data
, struct db_cache_ctx
);
131 return dbwrap_get_seqnum(ctx
->backing
);
134 static int dbwrap_cache_transaction_start(struct db_context
*db
)
136 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
137 db
->private_data
, struct db_cache_ctx
);
138 return dbwrap_transaction_start(ctx
->backing
);
141 static int dbwrap_cache_transaction_commit(struct db_context
*db
)
143 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
144 db
->private_data
, struct db_cache_ctx
);
145 return dbwrap_transaction_commit(ctx
->backing
);
148 static int dbwrap_cache_transaction_cancel(struct db_context
*db
)
150 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
151 db
->private_data
, struct db_cache_ctx
);
152 return dbwrap_transaction_cancel(ctx
->backing
);
155 static int dbwrap_cache_exists(struct db_context
*db
, TDB_DATA key
)
157 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
158 db
->private_data
, struct db_cache_ctx
);
160 if (ctx
->positive
&& dbwrap_exists(ctx
->positive
, key
)) {
163 if (ctx
->negative
&& dbwrap_exists(ctx
->negative
, key
)) {
166 return dbwrap_exists(ctx
->backing
, key
);
169 static void dbwrap_cache_id(struct db_context
*db
, const uint8_t **id
,
172 struct db_cache_ctx
*ctx
= talloc_get_type_abort(
173 db
->private_data
, struct db_cache_ctx
);
174 dbwrap_db_id(ctx
->backing
, id
, idlen
);
177 struct db_context
*db_open_cache(TALLOC_CTX
*mem_ctx
,
178 struct db_context
*backing
)
180 struct db_context
*db
;
181 struct db_cache_ctx
*ctx
;
183 db
= talloc(mem_ctx
, struct db_context
);
187 ctx
= talloc_zero(db
, struct db_cache_ctx
);
194 ctx
->backing
= talloc_move(ctx
, &backing
);
195 db
->private_data
= ctx
;
196 if (!dbwrap_cache_validate(ctx
)) {
201 db
->fetch_locked
= dbwrap_cache_fetch_locked
;
202 db
->try_fetch_locked
= NULL
;
203 db
->traverse
= dbwrap_cache_traverse
;
204 db
->traverse_read
= dbwrap_cache_traverse_read
;
205 db
->get_seqnum
= dbwrap_cache_get_seqnum
;
206 db
->transaction_start
= dbwrap_cache_transaction_start
;
207 db
->transaction_commit
= dbwrap_cache_transaction_commit
;
208 db
->transaction_cancel
= dbwrap_cache_transaction_cancel
;
209 db
->parse_record
= dbwrap_cache_parse_record
;
210 db
->exists
= dbwrap_cache_exists
;
211 db
->id
= dbwrap_cache_id
;
212 db
->name
= dbwrap_name(ctx
->backing
);
213 db
->hash_size
= dbwrap_hash_size(ctx
->backing
);
214 db
->stored_callback
= NULL
;
217 db
->persistent
= false;