]> git.ozlabs.org Git - ccan/blob - ccan/tdb2/private.h
tdb2: tdb_expand on empty database now tested.
[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)) << (64 - 11);
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. */
258 bool update_header(struct tdb_context *tdb);
259
260 /* Hash random memory. */
261 uint64_t tdb_hash(struct tdb_context *tdb, const void *ptr, size_t len);
262
263
264 /* free.c: */
265 void tdb_zone_init(struct tdb_context *tdb);
266
267 /* If this fails, try tdb_expand. */
268 tdb_off_t alloc(struct tdb_context *tdb, size_t keylen, size_t datalen,
269                 uint64_t hash, bool growing);
270
271 /* Put this record in a free list. */
272 int add_free_record(struct tdb_context *tdb,
273                     tdb_off_t off, tdb_len_t len_with_header);
274
275 /* Set up header for a used record. */
276 int set_header(struct tdb_context *tdb,
277                struct tdb_used_record *rec,
278                uint64_t keylen, uint64_t datalen,
279                uint64_t actuallen, uint64_t hash);
280
281 /* Used by tdb_check to verify. */
282 unsigned int size_to_bucket(struct tdb_context *tdb, tdb_len_t data_len);
283 tdb_off_t zone_of(struct tdb_context *tdb, tdb_off_t off);
284
285 /* io.c: */
286 /* Initialize tdb->methods. */
287 void tdb_io_init(struct tdb_context *tdb);
288
289 /* Convert endian of the buffer if required. */
290 void *tdb_convert(const struct tdb_context *tdb, void *buf, tdb_len_t size);
291
292 /* Unmap and try to map the tdb. */
293 void tdb_munmap(struct tdb_context *tdb);
294 void tdb_mmap(struct tdb_context *tdb);
295
296 /* Hand data to a function, direct if possible */
297 int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
298                    tdb_off_t offset, tdb_len_t len,
299                    int (*parser)(TDB_DATA key, TDB_DATA data,
300                                  void *private_data),
301                    void *private_data);
302
303 /* Either make a copy into pad and return that, or return ptr into mmap.
304  * Converts endian (ie. will use pad in that case). */
305 void *tdb_get(struct tdb_context *tdb, tdb_off_t off, void *pad, size_t len);
306
307 /* Either alloc a copy, or give direct access.  Release frees or noop. */
308 const void *tdb_access_read(struct tdb_context *tdb,
309                             tdb_off_t off, tdb_len_t len);
310 void tdb_access_release(struct tdb_context *tdb, const void *p);
311
312 /* Convenience routine to get an offset. */
313 tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off);
314
315 /* Write an offset at an offset. */
316 int tdb_write_off(struct tdb_context *tdb, tdb_off_t off, tdb_off_t val);
317
318 /* Clear an ondisk area. */
319 int zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len);
320
321 /* Return a non-zero offset in this array, or num. */
322 tdb_off_t tdb_find_nonzero_off(struct tdb_context *tdb, tdb_off_t off,
323                                uint64_t num);
324
325 /* Return a zero offset in this array, or num. */
326 tdb_off_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off,
327                             uint64_t num);
328
329 /* Even on files, we can get partial writes due to signals. */
330 bool tdb_pwrite_all(int fd, const void *buf, size_t len, tdb_off_t off);
331 bool tdb_pread_all(int fd, void *buf, size_t len, tdb_off_t off);
332 bool tdb_read_all(int fd, void *buf, size_t len);
333
334 /* Allocate and make a copy of some offset. */
335 void *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
336
337 /* Munges record and writes it */
338 int tdb_write_convert(struct tdb_context *tdb, tdb_off_t off,
339                       void *rec, size_t len);
340
341 /* Reads record and converts it */
342 int tdb_read_convert(struct tdb_context *tdb, tdb_off_t off,
343                      void *rec, size_t len);
344
345 /* Hash on disk. */
346 uint64_t hash_record(struct tdb_context *tdb, tdb_off_t off);
347
348 /* lock.c: */
349 void tdb_lock_init(struct tdb_context *tdb);
350
351 /* Lock/unlock a particular hash list. */
352 int tdb_lock_list(struct tdb_context *tdb, tdb_off_t list,
353                   int ltype, enum tdb_lock_flags waitflag);
354 int tdb_unlock_list(struct tdb_context *tdb, tdb_off_t list, int ltype);
355
356 /* Lock/unlock a particular free list. */
357 int tdb_lock_free_list(struct tdb_context *tdb, tdb_off_t flist,
358                        enum tdb_lock_flags waitflag);
359 void tdb_unlock_free_list(struct tdb_context *tdb, tdb_off_t flist);
360
361 /* Do we have any locks? */
362 bool tdb_has_locks(struct tdb_context *tdb);
363
364 /* Lock entire database. */
365 int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
366                        enum tdb_lock_flags flags, bool upgradable);
367 int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype);
368
369 /* Serialize db open. */
370 int tdb_lock_open(struct tdb_context *tdb);
371 void tdb_unlock_open(struct tdb_context *tdb);
372 /* Expand the file. */
373 int tdb_expand(struct tdb_context *tdb, tdb_len_t klen, tdb_len_t dlen,
374                bool growing);
375
376 #if 0
377 /* Low-level locking primitives. */
378 int tdb_nest_lock(struct tdb_context *tdb, tdb_off_t offset, int ltype,
379                   enum tdb_lock_flags flags);
380 int tdb_nest_unlock(struct tdb_context *tdb, tdb_off_t offset, int ltype);
381
382 int tdb_munmap(struct tdb_context *tdb);
383 void tdb_mmap(struct tdb_context *tdb);
384 int tdb_lock(struct tdb_context *tdb, int list, int ltype);
385 int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype);
386 bool tdb_have_locks(struct tdb_context *tdb);
387 int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
388 int tdb_brlock(struct tdb_context *tdb,
389                int rw_type, tdb_off_t offset, size_t len,
390                enum tdb_lock_flags flags);
391 int tdb_brunlock(struct tdb_context *tdb,
392                  int rw_type, tdb_off_t offset, size_t len);
393 bool tdb_have_extra_locks(struct tdb_context *tdb);
394 void tdb_release_extra_locks(struct tdb_context *tdb);
395 int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
396 int tdb_transaction_unlock(struct tdb_context *tdb, int ltype);
397 int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
398                        enum tdb_lock_flags flags, bool upgradable);
399 int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype);
400 int tdb_allrecord_upgrade(struct tdb_context *tdb);
401 int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
402 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
403 int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
404 int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
405 int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
406 tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec);
407 int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
408 int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d);
409 int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
410 int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
411 bool tdb_needs_recovery(struct tdb_context *tdb);
412 int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
413 int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
414 int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct tdb_record *rec);
415 unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len);
416 int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key,
417                    tdb_off_t offset, tdb_len_t len,
418                    int (*parser)(TDB_DATA key, TDB_DATA data,
419                                  void *private_data),
420                    void *private_data);
421 tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype,
422                            struct tdb_record *rec);
423 void tdb_io_init(struct tdb_context *tdb);
424 int tdb_expand(struct tdb_context *tdb, tdb_off_t size);
425 int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
426                       struct tdb_record *rec);
427 #endif
428
429 #ifdef TDB_TRACE
430 void tdb_trace(struct tdb_context *tdb, const char *op);
431 void tdb_trace_seqnum(struct tdb_context *tdb, uint32_t seqnum, const char *op);
432 void tdb_trace_open(struct tdb_context *tdb, const char *op,
433                     unsigned hash_size, unsigned tdb_flags, unsigned open_flags);
434 void tdb_trace_ret(struct tdb_context *tdb, const char *op, int ret);
435 void tdb_trace_retrec(struct tdb_context *tdb, const char *op, TDB_DATA ret);
436 void tdb_trace_1rec(struct tdb_context *tdb, const char *op,
437                     TDB_DATA rec);
438 void tdb_trace_1rec_ret(struct tdb_context *tdb, const char *op,
439                         TDB_DATA rec, int ret);
440 void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op,
441                            TDB_DATA rec, TDB_DATA ret);
442 void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op,
443                              TDB_DATA rec1, TDB_DATA rec2, unsigned flag,
444                              int ret);
445 void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
446                            TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret);
447 #else
448 #define tdb_trace(tdb, op)
449 #define tdb_trace_seqnum(tdb, seqnum, op)
450 #define tdb_trace_open(tdb, op, hash_size, tdb_flags, open_flags)
451 #define tdb_trace_ret(tdb, op, ret)
452 #define tdb_trace_retrec(tdb, op, ret)
453 #define tdb_trace_1rec(tdb, op, rec)
454 #define tdb_trace_1rec_ret(tdb, op, rec, ret)
455 #define tdb_trace_1rec_retrec(tdb, op, rec, ret)
456 #define tdb_trace_2rec_flag_ret(tdb, op, rec1, rec2, flag, ret)
457 #define tdb_trace_2rec_retrec(tdb, op, rec1, rec2, ret)
458 #endif /* !TDB_TRACE */
459
460 #endif