1 | tdb - a trivial database system
|
---|
2 | tridge@linuxcare.com December 1999
|
---|
3 | ==================================
|
---|
4 |
|
---|
5 | This is a simple database API. It was inspired by the realisation that
|
---|
6 | in Samba we have several ad-hoc bits of code that essentially
|
---|
7 | implement small databases for sharing structures between parts of
|
---|
8 | Samba. As I was about to add another I realised that a generic
|
---|
9 | database module was called for to replace all the ad-hoc bits.
|
---|
10 |
|
---|
11 | I based the interface on gdbm. I couldn't use gdbm as we need to be
|
---|
12 | able to have multiple writers to the databases at one time.
|
---|
13 |
|
---|
14 | Compilation
|
---|
15 | -----------
|
---|
16 |
|
---|
17 | add HAVE_MMAP=1 to use mmap instead of read/write
|
---|
18 | add NOLOCK=1 to disable locking code
|
---|
19 |
|
---|
20 | Testing
|
---|
21 | -------
|
---|
22 |
|
---|
23 | Compile tdbtest.c and link with gdbm for testing. tdbtest will perform
|
---|
24 | identical operations via tdb and gdbm then make sure the result is the
|
---|
25 | same
|
---|
26 |
|
---|
27 | Also included is tdbtool, which allows simple database manipulation
|
---|
28 | on the commandline.
|
---|
29 |
|
---|
30 | tdbtest and tdbtool are not built as part of Samba, but are included
|
---|
31 | for completeness.
|
---|
32 |
|
---|
33 | Interface
|
---|
34 | ---------
|
---|
35 |
|
---|
36 | The interface is very similar to gdbm except for the following:
|
---|
37 |
|
---|
38 | - different open interface. The tdb_open call is more similar to a
|
---|
39 | traditional open()
|
---|
40 | - no tdbm_reorganise() function
|
---|
41 | - no tdbm_sync() function. No operations are cached in the library anyway
|
---|
42 | - added a tdb_traverse() function for traversing the whole database
|
---|
43 | - added transactions support
|
---|
44 |
|
---|
45 | A general rule for using tdb is that the caller frees any returned
|
---|
46 | TDB_DATA structures. Just call free(p.dptr) to free a TDB_DATA
|
---|
47 | return value called p. This is the same as gdbm.
|
---|
48 |
|
---|
49 | here is a full list of tdb functions with brief descriptions.
|
---|
50 |
|
---|
51 |
|
---|
52 | ----------------------------------------------------------------------
|
---|
53 | TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
|
---|
54 | int open_flags, mode_t mode)
|
---|
55 |
|
---|
56 | open the database, creating it if necessary
|
---|
57 |
|
---|
58 | The open_flags and mode are passed straight to the open call on the database
|
---|
59 | file. A flags value of O_WRONLY is invalid
|
---|
60 |
|
---|
61 | The hash size is advisory, use zero for a default value.
|
---|
62 |
|
---|
63 | return is NULL on error
|
---|
64 |
|
---|
65 | possible tdb_flags are:
|
---|
66 | TDB_CLEAR_IF_FIRST - clear database if we are the only one with it open
|
---|
67 | TDB_INTERNAL - don't use a file, instaed store the data in
|
---|
68 | memory. The filename is ignored in this case.
|
---|
69 | TDB_NOLOCK - don't do any locking
|
---|
70 | TDB_NOMMAP - don't use mmap
|
---|
71 | TDB_NOSYNC - don't synchronise transactions to disk
|
---|
72 |
|
---|
73 | ----------------------------------------------------------------------
|
---|
74 | TDB_CONTEXT *tdb_open_ex(char *name, int hash_size, int tdb_flags,
|
---|
75 | int open_flags, mode_t mode,
|
---|
76 | tdb_log_func log_fn,
|
---|
77 | tdb_hash_func hash_fn)
|
---|
78 |
|
---|
79 | This is like tdb_open(), but allows you to pass an initial logging and
|
---|
80 | hash function. Be careful when passing a hash function - all users of
|
---|
81 | the database must use the same hash function or you will get data
|
---|
82 | corruption.
|
---|
83 |
|
---|
84 |
|
---|
85 | ----------------------------------------------------------------------
|
---|
86 | char *tdb_error(TDB_CONTEXT *tdb);
|
---|
87 |
|
---|
88 | return a error string for the last tdb error
|
---|
89 |
|
---|
90 | ----------------------------------------------------------------------
|
---|
91 | int tdb_close(TDB_CONTEXT *tdb);
|
---|
92 |
|
---|
93 | close a database
|
---|
94 |
|
---|
95 | ----------------------------------------------------------------------
|
---|
96 | int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf);
|
---|
97 |
|
---|
98 | update an entry in place - this only works if the new data size
|
---|
99 | is <= the old data size and the key exists.
|
---|
100 | on failure return -1
|
---|
101 |
|
---|
102 | ----------------------------------------------------------------------
|
---|
103 | TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
|
---|
104 |
|
---|
105 | fetch an entry in the database given a key
|
---|
106 | if the return value has a null dptr then a error occurred
|
---|
107 |
|
---|
108 | caller must free the resulting data
|
---|
109 |
|
---|
110 | ----------------------------------------------------------------------
|
---|
111 | int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
|
---|
112 |
|
---|
113 | check if an entry in the database exists
|
---|
114 |
|
---|
115 | note that 1 is returned if the key is found and 0 is returned if not found
|
---|
116 | this doesn't match the conventions in the rest of this module, but is
|
---|
117 | compatible with gdbm
|
---|
118 |
|
---|
119 | ----------------------------------------------------------------------
|
---|
120 | int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb,
|
---|
121 | TDB_DATA key, TDB_DATA dbuf, void *state), void *state);
|
---|
122 |
|
---|
123 | traverse the entire database - calling fn(tdb, key, data, state) on each
|
---|
124 | element.
|
---|
125 |
|
---|
126 | return -1 on error or the record count traversed
|
---|
127 |
|
---|
128 | if fn is NULL then it is not called
|
---|
129 |
|
---|
130 | a non-zero return value from fn() indicates that the traversal
|
---|
131 | should stop. Traversal callbacks may not start transactions.
|
---|
132 |
|
---|
133 | WARNING: The data buffer given to the callback fn does NOT meet the
|
---|
134 | alignment restrictions malloc gives you.
|
---|
135 |
|
---|
136 | ----------------------------------------------------------------------
|
---|
137 | int tdb_traverse_read(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb,
|
---|
138 | TDB_DATA key, TDB_DATA dbuf, void *state), void *state);
|
---|
139 |
|
---|
140 | traverse the entire database - calling fn(tdb, key, data, state) on
|
---|
141 | each element, but marking the database read only during the
|
---|
142 | traversal, so any write operations will fail. This allows tdb to
|
---|
143 | use read locks, which increases the parallelism possible during the
|
---|
144 | traversal.
|
---|
145 |
|
---|
146 | return -1 on error or the record count traversed
|
---|
147 |
|
---|
148 | if fn is NULL then it is not called
|
---|
149 |
|
---|
150 | a non-zero return value from fn() indicates that the traversal
|
---|
151 | should stop. Traversal callbacks may not start transactions.
|
---|
152 |
|
---|
153 | ----------------------------------------------------------------------
|
---|
154 | TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
|
---|
155 |
|
---|
156 | find the first entry in the database and return its key
|
---|
157 |
|
---|
158 | the caller must free the returned data
|
---|
159 |
|
---|
160 | ----------------------------------------------------------------------
|
---|
161 | TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
|
---|
162 |
|
---|
163 | find the next entry in the database, returning its key
|
---|
164 |
|
---|
165 | the caller must free the returned data
|
---|
166 |
|
---|
167 | ----------------------------------------------------------------------
|
---|
168 | int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
|
---|
169 |
|
---|
170 | delete an entry in the database given a key
|
---|
171 |
|
---|
172 | ----------------------------------------------------------------------
|
---|
173 | int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
|
---|
174 |
|
---|
175 | store an element in the database, replacing any existing element
|
---|
176 | with the same key
|
---|
177 |
|
---|
178 | If flag==TDB_INSERT then don't overwrite an existing entry
|
---|
179 | If flag==TDB_MODIFY then don't create a new entry
|
---|
180 |
|
---|
181 | return 0 on success, -1 on failure
|
---|
182 |
|
---|
183 | ----------------------------------------------------------------------
|
---|
184 | int tdb_writelock(TDB_CONTEXT *tdb);
|
---|
185 |
|
---|
186 | lock the database. If we already have it locked then don't do anything
|
---|
187 |
|
---|
188 | ----------------------------------------------------------------------
|
---|
189 | int tdb_writeunlock(TDB_CONTEXT *tdb);
|
---|
190 | unlock the database
|
---|
191 |
|
---|
192 | ----------------------------------------------------------------------
|
---|
193 | int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key);
|
---|
194 |
|
---|
195 | lock one hash chain. This is meant to be used to reduce locking
|
---|
196 | contention - it cannot guarantee how many records will be locked
|
---|
197 |
|
---|
198 | ----------------------------------------------------------------------
|
---|
199 | int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key);
|
---|
200 |
|
---|
201 | unlock one hash chain
|
---|
202 |
|
---|
203 | ----------------------------------------------------------------------
|
---|
204 | int tdb_transaction_start(TDB_CONTEXT *tdb)
|
---|
205 |
|
---|
206 | start a transaction. All operations after the transaction start can
|
---|
207 | either be committed with tdb_transaction_commit() or cancelled with
|
---|
208 | tdb_transaction_cancel().
|
---|
209 |
|
---|
210 | If you call tdb_transaction_start() again on the same tdb context
|
---|
211 | while a transaction is in progress, then the same transaction
|
---|
212 | buffer is re-used. The number of tdb_transaction_{commit,cancel}
|
---|
213 | operations must match the number of successful
|
---|
214 | tdb_transaction_start() calls.
|
---|
215 |
|
---|
216 | Note that transactions are by default disk synchronous, and use a
|
---|
217 | recover area in the database to automatically recover the database
|
---|
218 | on the next open if the system crashes during a transaction. You
|
---|
219 | can disable the synchronous transaction recovery setup using the
|
---|
220 | TDB_NOSYNC flag, which will greatly speed up operations at the risk
|
---|
221 | of corrupting your database if the system crashes.
|
---|
222 |
|
---|
223 | Operations made within a transaction are not visible to other users
|
---|
224 | of the database until a successful commit.
|
---|
225 |
|
---|
226 | ----------------------------------------------------------------------
|
---|
227 | int tdb_transaction_cancel(TDB_CONTEXT *tdb)
|
---|
228 |
|
---|
229 | cancel a current transaction, discarding all write and lock
|
---|
230 | operations that have been made since the transaction started.
|
---|
231 |
|
---|
232 |
|
---|
233 | ----------------------------------------------------------------------
|
---|
234 | int tdb_transaction_commit(TDB_CONTEXT *tdb)
|
---|
235 |
|
---|
236 | commit a current transaction, updating the database and releasing
|
---|
237 | the transaction locks.
|
---|
238 |
|
---|