X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftdb2%2Ftdb.c;h=b5e5457691257cbc8034a393f9d2bdeaf091a3cf;hb=9d9a9897b608af3a6acd623cc09557f9985b03e6;hp=ce431208bf4cb4fa28d09f9158c7fb02c93d7d37;hpb=95c98eb3ee9fcb3913ecb6c2618fcdaf3c8ce60a;p=ccan diff --git a/ccan/tdb2/tdb.c b/ccan/tdb2/tdb.c index ce431208..b5e54576 100644 --- a/ccan/tdb2/tdb.c +++ b/ccan/tdb2/tdb.c @@ -112,6 +112,7 @@ static enum TDB_ERROR tdb_new_database(struct tdb_context *tdb, newdb.hdr.hash_seed, tdb->hash_priv); newdb.hdr.recovery = 0; + newdb.hdr.features_used = newdb.hdr.features_offered = TDB_FEATURE_MASK; memset(newdb.hdr.reserved, 0, sizeof(newdb.hdr.reserved)); /* Initial hashes are empty. */ memset(newdb.hdr.hashtable, 0, sizeof(newdb.hdr.hashtable)); @@ -361,6 +362,16 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, goto fail; } + /* Clear any features we don't understand. */ + if ((open_flags & O_ACCMODE) != O_RDONLY) { + hdr.features_used &= TDB_FEATURE_MASK; + if (tdb_write_convert(tdb, offsetof(struct tdb_header, + features_used), + &hdr.features_used, + sizeof(hdr.features_used)) == -1) + goto fail; + } + tdb->device = st.st_dev; tdb->inode = st.st_ino; tdb_unlock_open(tdb); @@ -499,6 +510,21 @@ static enum TDB_ERROR replace_data(struct tdb_context *tdb, return TDB_SUCCESS; } +static enum TDB_ERROR update_data(struct tdb_context *tdb, + tdb_off_t off, + struct tdb_data dbuf, + tdb_len_t extra) +{ + enum TDB_ERROR ecode; + + ecode = tdb->methods->twrite(tdb, off, dbuf.dptr, dbuf.dsize); + if (ecode == TDB_SUCCESS && extra) { + /* Put a zero in; future versions may append other data. */ + ecode = tdb->methods->twrite(tdb, off + dbuf.dsize, "", 1); + } + return ecode; +} + enum TDB_ERROR tdb_store(struct tdb_context *tdb, struct tdb_data key, struct tdb_data dbuf, int flag) { @@ -531,11 +557,10 @@ enum TDB_ERROR tdb_store(struct tdb_context *tdb, if (ecode != TDB_SUCCESS) { goto out; } - ecode = tdb->methods->twrite(tdb, - off + sizeof(rec) - + key.dsize, - dbuf.dptr, - dbuf.dsize); + ecode = update_data(tdb, + off + sizeof(rec) + + key.dsize, dbuf, + old_room - dbuf.dsize); if (ecode != TDB_SUCCESS) { goto out; } @@ -591,8 +616,8 @@ enum TDB_ERROR tdb_append(struct tdb_context *tdb, } off += sizeof(rec) + key.dsize + old_dlen; - ecode = tdb->methods->twrite(tdb, off, dbuf.dptr, - dbuf.dsize); + ecode = update_data(tdb, off, dbuf, + rec_extra_padding(&rec)); goto out; } @@ -733,6 +758,59 @@ int tdb_close(struct tdb_context *tdb) return ret; } +unsigned int tdb_get_flags(struct tdb_context *tdb) +{ + return tdb->flags; +} + +void tdb_add_flag(struct tdb_context *tdb, unsigned flag) +{ + if (tdb->flags & TDB_INTERNAL) { + tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, + "tdb_add_flag: internal db"); + return; + } + switch (flag) { + case TDB_NOLOCK: + tdb->flags |= TDB_NOLOCK; + break; + case TDB_NOMMAP: + tdb->flags |= TDB_NOMMAP; + tdb_munmap(tdb); + break; + case TDB_NOSYNC: + tdb->flags |= TDB_NOSYNC; + break; + default: + tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, + "tdb_add_flag: Unknown flag %u", flag); + } +} + +void tdb_remove_flag(struct tdb_context *tdb, unsigned flag) +{ + if (tdb->flags & TDB_INTERNAL) { + tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, + "tdb_remove_flag: internal db"); + return; + } + switch (flag) { + case TDB_NOLOCK: + tdb->flags &= ~TDB_NOLOCK; + break; + case TDB_NOMMAP: + tdb->flags &= ~TDB_NOMMAP; + tdb_mmap(tdb); + break; + case TDB_NOSYNC: + tdb->flags &= ~TDB_NOSYNC; + break; + default: + tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR, + "tdb_remove_flag: Unknown flag %u", flag); + } +} + const char *tdb_errorstr(enum TDB_ERROR ecode) { /* Gcc warns if you miss a case in the switch, so use that. */