2 Trivial Database 2: traverse function.
3 Copyright (C) Rusty Russell 2010
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 3 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include <ccan/likely/likely.h>
21 _PUBLIC_
int64_t tdb_traverse_(struct tdb_context
*tdb
,
22 int (*fn
)(struct tdb_context
*,
23 TDB_DATA
, TDB_DATA
, void *),
27 struct traverse_info tinfo
;
31 if (tdb
->flags
& TDB_VERSION1
) {
32 count
= tdb1_traverse(tdb
, fn
, p
);
34 return TDB_ERR_TO_OFF(tdb
->last_error
);
39 for (ecode
= first_in_hash(tdb
, &tinfo
, &k
, &d
.dsize
);
41 ecode
= next_in_hash(tdb
, &tinfo
, &k
, &d
.dsize
)) {
42 d
.dptr
= k
.dptr
+ k
.dsize
;
45 if (fn
&& fn(tdb
, k
, d
, p
)) {
47 tdb
->last_error
= TDB_SUCCESS
;
53 if (ecode
!= TDB_ERR_NOEXIST
) {
54 return TDB_ERR_TO_OFF(tdb
->last_error
= ecode
);
56 tdb
->last_error
= TDB_SUCCESS
;
60 _PUBLIC_
enum TDB_ERROR
tdb_firstkey(struct tdb_context
*tdb
, struct tdb_data
*key
)
62 struct traverse_info tinfo
;
64 if (tdb
->flags
& TDB_VERSION1
) {
65 tdb
->last_error
= TDB_SUCCESS
;
66 *key
= tdb1_firstkey(tdb
);
67 /* TDB1 didn't set error for last key. */
68 if (!key
->dptr
&& tdb
->last_error
== TDB_SUCCESS
) {
69 tdb
->last_error
= TDB_ERR_NOEXIST
;
71 return tdb
->last_error
;
74 return tdb
->last_error
= first_in_hash(tdb
, &tinfo
, key
, NULL
);
77 /* We lock twice, not very efficient. We could keep last key & tinfo cached. */
78 _PUBLIC_
enum TDB_ERROR
tdb_nextkey(struct tdb_context
*tdb
, struct tdb_data
*key
)
80 struct traverse_info tinfo
;
82 struct tdb_used_record rec
;
84 if (tdb
->flags
& TDB_VERSION1
) {
85 struct tdb_data last_key
= *key
;
86 tdb
->last_error
= TDB_SUCCESS
;
87 *key
= tdb1_nextkey(tdb
, last_key
);
89 /* TDB1 didn't set error for last key. */
90 if (!key
->dptr
&& tdb
->last_error
== TDB_SUCCESS
) {
91 tdb
->last_error
= TDB_ERR_NOEXIST
;
93 return tdb
->last_error
;
96 tinfo
.prev
= find_and_lock(tdb
, *key
, F_RDLCK
, &h
, &rec
, &tinfo
);
98 if (TDB_OFF_IS_ERR(tinfo
.prev
)) {
99 return tdb
->last_error
= TDB_OFF_TO_ERR(tinfo
.prev
);
101 tdb_unlock_hashes(tdb
, h
.hlock_start
, h
.hlock_range
, F_RDLCK
);
103 return tdb
->last_error
= next_in_hash(tdb
, &tinfo
, key
, NULL
);
106 static int wipe_one(struct tdb_context
*tdb
,
107 TDB_DATA key
, TDB_DATA data
, enum TDB_ERROR
*ecode
)
109 *ecode
= tdb_delete(tdb
, key
);
110 return (*ecode
!= TDB_SUCCESS
);
113 _PUBLIC_
enum TDB_ERROR
tdb_wipe_all(struct tdb_context
*tdb
)
115 enum TDB_ERROR ecode
;
118 if (tdb
->flags
& TDB_VERSION1
) {
119 if (tdb1_wipe_all(tdb
) == -1)
120 return tdb
->last_error
;
124 ecode
= tdb_allrecord_lock(tdb
, F_WRLCK
, TDB_LOCK_WAIT
, false);
125 if (ecode
!= TDB_SUCCESS
)
126 return tdb
->last_error
= ecode
;
128 /* FIXME: Be smarter. */
129 count
= tdb_traverse(tdb
, wipe_one
, &ecode
);
131 ecode
= TDB_OFF_TO_ERR(count
);
132 tdb_allrecord_unlock(tdb
, F_WRLCK
);
133 return tdb
->last_error
= ecode
;