]> git.ozlabs.org Git - ccan/blob - ccan/tdb2/private.h
tdb2: now we can store a key!
[ccan] / ccan / tdb2 / private.h
1 #ifndef TDB_PRIVATE_H
2 #define TDB_PRIVATE_H
3  /* 
4    Trivial Database 2: private types and prototypes
5    Copyright (C) Rusty Russell 2010
6
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 3 of the License, or (at your option) any later version.
11
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #define _XOPEN_SOURCE 500
22 #define _FILE_OFFSET_BITS 64
23 #include <stdint.h>
24 #include <stdbool.h>
25 #include <stdlib.h>
26 #include <sys/time.h>
27 #include <sys/mman.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <utime.h>
34 #include <unistd.h>
35 #include "config.h"
36 #include <ccan/tdb2/tdb2.h>
37 #include <ccan/likely/likely.h>
38 #ifdef HAVE_BYTESWAP_H
39 #include <byteswap.h>
40 #endif
41
42 #ifndef TEST_IT
43 #define TEST_IT(cond)
44 #endif
45
46 /* #define TDB_TRACE 1 */
47
48 #ifndef __STRING
49 #define __STRING(x)    #x
50 #endif
51
52 #ifndef __STRINGSTRING
53 #define __STRINGSTRING(x) __STRING(x)
54 #endif
55
56 #ifndef __location__
57 #define __location__ __FILE__ ":" __STRINGSTRING(__LINE__)
58 #endif
59
60 typedef uint64_t tdb_len_t;
61 typedef uint64_t tdb_off_t;
62
63 #ifndef offsetof
64 #define offsetof(t,f) ((unsigned int)&((t *)0)->f)
65 #endif
66
67 #define TDB_MAGIC_FOOD "TDB file\n"
68 #define TDB_VERSION ((uint64_t)(0x26011967 + 7))
69 #define TDB_MAGIC ((uint64_t)0x1999)
70 #define TDB_FREE_MAGIC (~(uint64_t)TDB_MAGIC)
71 #define TDB_HASH_MAGIC (0xA1ABE11A01092008ULL)
72 #define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
73 #define TDB_RECOVERY_INVALID_MAGIC (0x0)
74 #define TDB_EXTRA_HASHBITS (11) /* We steal 11 bits to stash hash info. */
75 #define TDB_EXTRA_HASHBITS_NUM (3)
76
77 #define TDB_OFF_ERR ((tdb_off_t)-1)
78
79 /* Prevent others from opening the file. */
80 #define TDB_OPEN_LOCK 0
81 /* Doing a transaction. */
82 #define TDB_TRANSACTION_LOCK 1
83 /* Hash chain locks. */
84 #define TDB_HASH_LOCK_START 2
85
86 /* We start wih 256 hash buckets, 10 free buckets.  A 4k-sized zone. */
87 #define INITIAL_HASH_BITS 8
88 #define INITIAL_FREE_BUCKETS 10
89 #define INITIAL_ZONE_BITS 12
90
91 #if !HAVE_BSWAP_64
92 static inline uint64_t bswap_64(uint64_t x)
93 {
94         return (((x&0x000000FFULL)<<56)
95                 | ((x&0x0000FF00ULL)<<48)
96                 | ((x&0x00FF0000ULL)<<40)
97                 | ((x&0xFF000000ULL)<<32)
98                 | ((x>>8)&0xFF000000ULL)
99                 | ((x>>16)&0x00FF0000ULL)
100                 | ((x>>24)&0x0000FF00ULL)
101                 | ((x>>32)&0x000000FFULL));
102 }
103 #endif
104
105 struct tdb_used_record {
106         /* For on-disk compatibility, we avoid bitfields:
107            magic: 16,        (highest)
108            key_len_bits: 5,
109            hash:11,
110            extra_padding: 32 (lowest)
111         */
112         uint64_t magic_and_meta;
113         /* The bottom key_len_bits*2 are key length, rest is data length. */
114         uint64_t key_and_data_len;
115 };
116
117 static inline unsigned rec_key_bits(const struct tdb_used_record *r)
118 {
119         return ((r->magic_and_meta >> 43) & ((1 << 5)-1)) * 2;
120 }
121
122 static inline uint64_t rec_key_length(const struct tdb_used_record *r)
123 {
124         return r->key_and_data_len & ((1ULL << rec_key_bits(r)) - 1);
125 }
126
127 static inline uint64_t rec_data_length(const struct tdb_used_record *r)
128 {
129         return r->key_and_data_len >> rec_key_bits(r);
130 }
131
132 static inline uint64_t rec_extra_padding(const struct tdb_used_record *r)
133 {
134         return r->magic_and_meta & 0xFFFFFFFF;
135 }
136
137 static inline uint64_t rec_hash(const struct tdb_used_record *r)
138 {
139         return ((r->magic_and_meta >> 32) & ((1ULL << 11) - 1));
140 }
141
142 static inline uint16_t rec_magic(const struct tdb_used_record *r)
143 {
144         return (r->magic_and_meta >> 48);
145 }
146
147 struct tdb_free_record {
148         uint64_t magic;
149         uint64_t data_len; /* Not counting these two fields. */
150         /* This is why the minimum record size is 16 bytes.  */
151         uint64_t next, prev;
152 };
153
154 /* These parts can change while we have db open. */
155 struct tdb_header_volatile {
156         uint64_t generation; /* Makes sure it changes on every update. */
157         uint64_t hash_bits; /* Entries in hash table. */
158         uint64_t hash_off; /* Offset of hash table. */
159         uint64_t num_zones; /* How many zones in the file. */
160         uint64_t zone_bits; /* Size of zones. */
161         uint64_t free_buckets; /* How many buckets in each zone. */
162         uint64_t free_off; /* Arrays of free entries. */
163 };
164
165 /* this is stored at the front of every database */
166 struct tdb_header {
167         char magic_food[32]; /* for /etc/magic */
168         uint64_t version; /* version of the code */
169         uint64_t hash_test; /* result of hashing HASH_MAGIC. */
170         uint64_t hash_seed; /* "random" seed written at creation time. */
171
172         struct tdb_header_volatile v;
173
174         tdb_off_t reserved[19];
175 };
176
177 enum tdb_lock_flags {
178         /* WAIT == F_SETLKW, NOWAIT == F_SETLK */
179         TDB_LOCK_NOWAIT = 0,
180         TDB_LOCK_WAIT = 1,
181         /* If set, don't log an error on failure. */
182         TDB_LOCK_PROBE = 2,
183 };
184
185 struct tdb_lock_type {
186         uint32_t off;
187         uint32_t count;
188         uint32_t ltype;
189 };
190
191 struct tdb_context {
192         /* Filename of the database. */
193         const char *name;
194
195         /* Mmap (if any), or malloc (for TDB_INTERNAL). */
196         void *map_ptr;
197
198          /* Open file descriptor (undefined for TDB_INTERNAL). */
199         int fd;
200
201         /* How much space has been mapped (<= current file size) */
202         tdb_len_t map_size;
203
204         /* Opened read-only? */
205         bool read_only;
206
207         /* Error code for last tdb error. */
208         enum TDB_ERROR ecode; 
209
210         /* A cached copy of the header */
211         struct tdb_header header; 
212         /* (for debugging). */
213         bool header_uptodate; 
214
215         /* the flags passed to tdb_open, for tdb_reopen. */
216         uint32_t flags;
217
218         /* Logging function */
219         tdb_logfn_t log;
220         void *log_priv;
221
222         /* Hash function. */
223         tdb_hashfn_t khash;
224         void *hash_priv;
225
226         /* Set if we are in a transaction. */
227         struct tdb_transaction *transaction;
228         
229         /* What zone of the tdb to use, for spreading load. */
230         uint64_t last_zone; 
231
232         /* IO methods: changes for transactions. */
233         const struct tdb_methods *methods;
234
235         /* Lock information */
236         struct tdb_lock_type allrecord_lock;
237         uint64_t num_lockrecs;
238         struct tdb_lock_type *lockrecs;
239
240         /* Single list of all TDBs, to avoid multiple opens. */
241         struct tdb_context *next;
242         dev_t device;   
243         ino_t inode;
244 };
245
246 struct tdb_methods {
247         int (*read)(struct tdb_context *, tdb_off_t, void *, tdb_len_t);
248         int (*write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t);
249         int (*oob)(struct tdb_context *, tdb_off_t, bool);
250         int (*expand_file)(struct tdb_context *, tdb_len_t);
251 };
252
253 /*
254   internal prototypes
255 */
256 /* tdb.c: */
257 /* Returns true if header changed (and updates it). */
258 bool header_changed(struct tdb_context *tdb);
259
260 /* Commit header to disk. */
261 int write_header(struct tdb_context *tdb);
262
263 /* Hash random memory. */
264 uint64_t tdb_hash(struct tdb_context *tdb, const void *ptr, size_t len);
265
266
267 /* free.c: */
268 void tdb_zone_init(struct tdb_context *tdb);
269
270 /* If this fails, try tdb_expand. */
271 tdb_off_t alloc(struct tdb_context *tdb, size_t keylen, size_t datalen,
272                 uint64_t hash, bool growing);
273
274 /* Put this record in a free list. */
275 int add_free_record(struct tdb_context *tdb,
276                     tdb_off_t off, tdb_len_t len_with_header);
277
278 /* Set up header for a used record. */
279 int set_header(struct tdb_context *tdb,
280                struct tdb_used_record *rec,
281                uint64_t keylen, uint64_t datalen,
282                uint64_t actuallen, uint64_t hash);
283
284 /* Used by tdb_check to verify. */
285 unsigned int size_to_bucket(struct tdb_context *tdb, tdb_len_t data_len);
286 tdb_off_t zone_of(struct tdb_context *tdb, tdb_off_t off);
287
288 /* io.c: */
289 /* Initialize tdb->methods. */
290 void tdb_io_init(struct tdb_context *tdb);
291
292 /* Convert endian of the buffer if required. */
293 void *tdb_convert(const struct tdb_context *tdb, void *buf, tdb_len_t size);
294
295 /* Unmap and try to map the tdb. */
296 void tdb_munmap(struct tdb_context *tdb);
297 void tdb_mmap(struct tdb_context *tdb);
298
299 /* Hand data to a function, direct if possible */
300 int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
301                    tdb_off_t offset, tdb_len_t len,
302                    int (*parser)(TDB_DATA key, TDB_DATA data,
303                                  void *private_data),
304                    void *private_data);
305
306 /* Either make a copy into pad and return that, or return ptr into mmap.
307  * Converts endian (ie. will use pad in that case). */
308 void *tdb_get(struct tdb_context *tdb, tdb_off_t off, void *pad, size_t len);
309
310 /* Either alloc a copy, or give direct access.  Release frees or noop. */
311 const void *tdb_access_read(struct tdb_context *tdb,
312                             tdb_off_t off, tdb_len_t len);
313 void tdb_access_release(struct tdb_context *tdb, const void *p);
314
315 /* Convenience routine to get an offset. */
316 tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off);
317
318 /* Write an offset at an offset. */
319 int tdb_write_off(struct tdb_context *tdb, tdb_off_t off, tdb_off_t val);
320
321 /* Clear an ondisk area. */
322 int zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len);
323
324 /* Return a non-zero offset in this array, or num. */
325 tdb_off_t tdb_find_nonzero_off(struct tdb_context *tdb, tdb_off_t off,
326                                uint64_t num);
327
328 /* Return a zero offset in this array, or num. */
329 tdb_off_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off,
330                             uint64_t num);
331
332 /* Even on files, we can get partial writes due to signals. */
333 bool tdb_pwrite_all(int fd, const void *buf, size_t len, tdb_off_t off);
334 bool tdb_pread_all(int fd, void *buf, size_t len, tdb_off_t off);
335 bool tdb_read_all(int fd, void *buf, size_t len);
336
337 /* Allocate and make a copy of some offset. */
338 void *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
339
340 /* Munges record and writes it */
341 int tdb_write_convert(struct tdb_context *tdb, tdb_off_t off,
342                       void *rec, size_t len);
343
344 /* Reads record and converts it */
345 int tdb_read_convert(struct tdb_context *tdb, tdb_off_t off,
346                      void *rec, size_t len);
347
348 /* Hash on disk. */
349 uint64_t hash_record(struct tdb_context *tdb, tdb_off_t off);
350
351 /* lock.c: */
352 void tdb_lock_init(struct tdb_context *tdb);
353
354 /* Lock/unlock a particular hash list. */
355 tdb_off_t tdb_lock_list(struct tdb_context *tdb, uint64_t hash,
356                         int ltype, enum tdb_lock_flags waitflag);
357 int tdb_unlock_list(struct tdb_context *tdb, tdb_off_t list, int ltype);
358
359 /* Lock/unlock a particular free list. */
360 int tdb_lock_free_list(struct tdb_context *tdb, tdb_off_t flist,
361                        enum tdb_lock_flags waitflag);
362 void tdb_unlock_free_list(struct tdb_context *tdb, tdb_off_t flist);
363
364 /* Do we have any locks? */
365 bool tdb_has_locks(struct tdb_context *tdb);
366
367 /* Lock entire database. */
368 int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
369                        enum tdb_lock_flags flags, bool upgradable);
370 int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype);
371
372 /* Serialize db open. */
373 int tdb_lock_open(struct tdb_context *tdb);
374 void tdb_unlock_open(struct tdb_context *tdb);
375 /* Expand the file. */
376 int tdb_expand(struct tdb_context *tdb, tdb_len_t klen, tdb_len_t dlen,
377                bool growing);
378
379 #if 0
380 /* Low-level locking primitives. */
381 int tdb_nest_lock(struct tdb_context *tdb, tdb_off_t offset, int ltype,
382                   enum tdb_lock_flags flags);
383 int tdb_nest_unlock(struct tdb_context *tdb, tdb_off_t offset, int ltype);
384
385 int tdb_munmap(struct tdb_context *tdb);
386 void tdb_mmap(struct tdb_context *tdb);
387 int tdb_lock(struct tdb_context *tdb, int list, int ltype);
388 int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype);
389 bool tdb_have_locks(struct tdb_context *tdb);
390 int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
391 int tdb_brlock(struct tdb_context *tdb,
392                int rw_type, tdb_off_t offset, size_t len,
393                enum tdb_lock_flags flags);
394 int tdb_brunlock(struct tdb_context *tdb,
395                  int rw_type, tdb_off_t offset, size_t len);
396 bool tdb_have_extra_locks(struct tdb_context *tdb);
397 void tdb_release_extra_locks(struct tdb_context *tdb);
398 int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
399 int tdb_transaction_unlock(struct tdb_context *tdb, int ltype);
400 int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
401                        enum tdb_lock_flags flags, bool upgradable);
402 int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype);
403 int tdb_allrecord_upgrade(struct tdb_context *tdb);
404 int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
405 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
406 int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
407 int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
408 int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
409 tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec);
410 int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
411 int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
412 int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
413 int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
414 bool tdb_needs_recovery(struct tdb_context *tdb);
415 int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
416 int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
417 int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct tdb_record *rec);
418 unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
419 int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
420                    tdb_off_t offset, tdb_len_t len,
421                    int (*parser)(TDB_DATA key, TDB_DATA data,
422                                  void *private_data),
423                    void *private_data);
424 tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype,
425                            struct tdb_record *rec);
426 void tdb_io_init(struct tdb_context *tdb);
427 int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
428 int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
429                       struct tdb_record *rec);
430 #endif
431
432 #ifdef TDB_TRACE
433 void tdb_trace(struct tdb_context *tdb, const char *op);
434 void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op);
435 void tdb_trace_open(struct tdb_context *tdb, const char *op,
436                     unsigned hash_size, unsigned tdb_flags, unsigned open_flags);
437 void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret);
438 void tdb_trace_retrec(struct tdb_context *tdb, const char *op, TDB_DATA ret);
439 void tdb_trace_1rec(struct tdb_context *tdb, const char *op,
440                     TDB_DATA rec);
441 void tdb_trace_1rec_ret(struct tdb_context *tdb, const char *op,
442                         TDB_DATA rec, int ret);
443 void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op,
444                            TDB_DATA rec, TDB_DATA ret);
445 void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op,
446                              TDB_DATA rec1, TDB_DATA rec2, unsigned flag,
447                              int ret);
448 void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
449                            TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret);
450 #else
451 #define tdb_trace(tdb, op)
452 #define tdb_trace_seqnum(tdb, seqnum, op)
453 #define tdb_trace_open(tdb, op, hash_size, tdb_flags, open_flags)
454 #define tdb_trace_ret(tdb, op, ret)
455 #define tdb_trace_retrec(tdb, op, ret)
456 #define tdb_trace_1rec(tdb, op, rec)
457 #define tdb_trace_1rec_ret(tdb, op, rec, ret)
458 #define tdb_trace_1rec_retrec(tdb, op, rec, ret)
459 #define tdb_trace_2rec_flag_ret(tdb, op, rec1, rec2, flag, ret)
460 #define tdb_trace_2rec_retrec(tdb, op, rec1, rec2, ret)
461 #endif /* !TDB_TRACE */
462
463 #endif