X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftdb2%2Ftdb.c;h=e3b3c2303f282ae387eec8171a3327f4d8864a29;hp=1a229dc2b94c1538e5093a8df55d74b8dd8d74f8;hb=8afb9681b3be7149cf8913a5aefe915194fd20f7;hpb=6804501c350181dea8f531142b28c620b70edbd9 diff --git a/ccan/tdb2/tdb.c b/ccan/tdb2/tdb.c index 1a229dc2..e3b3c230 100644 --- a/ccan/tdb2/tdb.c +++ b/ccan/tdb2/tdb.c @@ -10,7 +10,7 @@ struct tdb_data tdb_null = { .dptr = NULL, .dsize = 0 }; /* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ static struct tdb_context *tdbs = NULL; -PRINTF_ATTRIBUTE(4, 5) static void +PRINTF_FMT(4, 5) static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, void *priv, const char *fmt, ...) @@ -94,7 +94,9 @@ struct new_database { }; /* initialise a new database */ -static int tdb_new_database(struct tdb_context *tdb, struct tdb_header *hdr) +static int tdb_new_database(struct tdb_context *tdb, + struct tdb_attribute_seed *seed, + struct tdb_header *hdr) { /* We make it up in memory, then write it out if not internal */ struct new_database newdb; @@ -105,7 +107,10 @@ static int tdb_new_database(struct tdb_context *tdb, struct tdb_header *hdr) /* Fill in the header */ newdb.hdr.version = TDB_VERSION; - newdb.hdr.hash_seed = random_number(tdb); + if (seed) + newdb.hdr.hash_seed = seed->seed; + else + newdb.hdr.hash_seed = random_number(tdb); newdb.hdr.hash_test = TDB_HASH_MAGIC; newdb.hdr.hash_test = tdb->khash(&newdb.hdr.hash_test, sizeof(newdb.hdr.hash_test), @@ -181,6 +186,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, uint64_t hash_test; unsigned v; struct tdb_header hdr; + struct tdb_attribute_seed *seed = NULL; tdb = malloc(sizeof(*tdb)); if (!tdb) { @@ -213,6 +219,9 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, tdb->khash = attr->hash.hash_fn; tdb->hash_priv = attr->hash.hash_private; break; + case TDB_ATTRIBUTE_SEED: + seed = &attr->seed; + break; default: tdb->log(tdb, TDB_DEBUG_ERROR, tdb->log_priv, "tdb_open: unknown attribute type %u\n", @@ -234,13 +243,16 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, tdb->read_only = true; /* read only databases don't do locking */ tdb->flags |= TDB_NOLOCK; - } else + tdb->mmap_flags = PROT_READ; + } else { tdb->read_only = false; + tdb->mmap_flags = PROT_READ | PROT_WRITE; + } /* internal databases don't need any of the rest. */ if (tdb->flags & TDB_INTERNAL) { tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); - if (tdb_new_database(tdb, &hdr) != 0) { + if (tdb_new_database(tdb, seed, &hdr) != 0) { tdb->log(tdb, TDB_DEBUG_ERROR, tdb->log_priv, "tdb_open: tdb_new_database failed!"); goto fail; @@ -272,7 +284,8 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, if (!tdb_pread_all(tdb->fd, &hdr, sizeof(hdr), 0) || strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0) { - if (!(open_flags & O_CREAT) || tdb_new_database(tdb, &hdr) == -1) { + if (!(open_flags & O_CREAT) + || tdb_new_database(tdb, seed, &hdr) == -1) { if (errno == 0) { errno = EIO; /* ie bad format or something */ } @@ -429,7 +442,7 @@ int tdb_store(struct tdb_context *tdb, struct tdb_used_record rec; int ret; - off = find_and_lock(tdb, key, F_WRLCK, &h, &rec); + off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL); if (unlikely(off == TDB_OFF_ERR)) return -1; @@ -491,7 +504,7 @@ int tdb_append(struct tdb_context *tdb, struct tdb_data new_dbuf; int ret; - off = find_and_lock(tdb, key, F_WRLCK, &h, &rec); + off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL); if (unlikely(off == TDB_OFF_ERR)) return -1; @@ -559,7 +572,7 @@ struct tdb_data tdb_fetch(struct tdb_context *tdb, struct tdb_data key) struct hash_info h; struct tdb_data ret; - off = find_and_lock(tdb, key, F_RDLCK, &h, &rec); + off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL); if (unlikely(off == TDB_OFF_ERR)) return tdb_null; @@ -582,7 +595,7 @@ int tdb_delete(struct tdb_context *tdb, struct tdb_data key) struct tdb_used_record rec; struct hash_info h; - off = find_and_lock(tdb, key, F_WRLCK, &h, &rec); + off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL); if (unlikely(off == TDB_OFF_ERR)) return -1; @@ -656,3 +669,21 @@ enum TDB_ERROR tdb_error(struct tdb_context *tdb) { return tdb->ecode; } + +const char *tdb_errorstr(struct tdb_context *tdb) +{ + /* Gcc warns if you miss a case in the switch, so use that. */ + switch (tdb->ecode) { + case TDB_SUCCESS: return "Success"; + case TDB_ERR_CORRUPT: return "Corrupt database"; + case TDB_ERR_IO: return "IO Error"; + case TDB_ERR_LOCK: return "Locking error"; + case TDB_ERR_OOM: return "Out of memory"; + case TDB_ERR_EXISTS: return "Record exists"; + case TDB_ERR_NESTING: return "Transaction already started"; + case TDB_ERR_EINVAL: return "Invalid parameter"; + case TDB_ERR_NOEXIST: return "Record does not exist"; + case TDB_ERR_RDONLY: return "write not permitted"; + } + return "Invalid error code"; +}