new_off = alloc(tdb, key.dsize, dbuf.dsize, h->h, TDB_USED_MAGIC,
growing);
if (TDB_OFF_IS_ERR(new_off)) {
- return new_off;
+ return TDB_OFF_TO_ERR(new_off);
}
/* We didn't like the existing one: remove it. */
off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) {
- return tdb->last_error = off;
+ return tdb->last_error = TDB_OFF_TO_ERR(off);
}
/* Now we have lock on this hash bucket. */
off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) {
- return tdb->last_error = off;
+ return tdb->last_error = TDB_OFF_TO_ERR(off);
}
if (off) {
off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) {
- return tdb->last_error = off;
+ return tdb->last_error = TDB_OFF_TO_ERR(off);
}
if (!off) {
struct tdb_used_record rec;
struct hash_info h;
+ if (tdb->flags & TDB_VERSION1) {
+ return tdb1_exists(tdb, key);
+ }
+
off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) {
- tdb->last_error = off;
+ tdb->last_error = TDB_OFF_TO_ERR(off);
return false;
}
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_RDLCK);
off = find_and_lock(tdb, key, F_WRLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) {
- return tdb->last_error = off;
+ return tdb->last_error = TDB_OFF_TO_ERR(off);
}
if (!off) {
caller);
return false;
}
-
- if (tdb->file->allrecord_lock.count != 0
- || tdb->file->num_lockrecs != 0) {
- tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
- TDB_LOG_USE_ERROR,
- "%s: can't change"
- " TDB_RDONLY holding locks",
- caller);
- return false;
- }
return true;
}
const char *tdb_errorstr(enum TDB_ERROR ecode)
{
/* Gcc warns if you miss a case in the switch, so use that. */
- switch (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_EINVAL: return "Invalid parameter";
- case TDB_ERR_NOEXIST: return "Record does not exist";
- case TDB_ERR_RDONLY: return "write not permitted";
+ switch (TDB_ERR_TO_OFF(ecode)) {
+ case TDB_ERR_TO_OFF(TDB_SUCCESS): return "Success";
+ case TDB_ERR_TO_OFF(TDB_ERR_CORRUPT): return "Corrupt database";
+ case TDB_ERR_TO_OFF(TDB_ERR_IO): return "IO Error";
+ case TDB_ERR_TO_OFF(TDB_ERR_LOCK): return "Locking error";
+ case TDB_ERR_TO_OFF(TDB_ERR_OOM): return "Out of memory";
+ case TDB_ERR_TO_OFF(TDB_ERR_EXISTS): return "Record exists";
+ case TDB_ERR_TO_OFF(TDB_ERR_EINVAL): return "Invalid parameter";
+ case TDB_ERR_TO_OFF(TDB_ERR_NOEXIST): return "Record does not exist";
+ case TDB_ERR_TO_OFF(TDB_ERR_RDONLY): return "write not permitted";
}
return "Invalid error code";
}
struct hash_info h;
enum TDB_ERROR ecode;
+ if (tdb->flags & TDB_VERSION1) {
+ return tdb->last_error = tdb1_parse_record(tdb, key, parse,
+ data);
+ }
+
off = find_and_lock(tdb, key, F_RDLCK, &h, &rec, NULL);
if (TDB_OFF_IS_ERR(off)) {
- return tdb->last_error = off;
+ return tdb->last_error = TDB_OFF_TO_ERR(off);
}
if (!off) {
int64_t tdb_get_seqnum(struct tdb_context *tdb)
{
- tdb_off_t off = tdb_read_off(tdb, offsetof(struct tdb_header, seqnum));
+ tdb_off_t off;
+
+ if (tdb->flags & TDB_VERSION1) {
+ tdb1_off_t val;
+ tdb->last_error = TDB_SUCCESS;
+ val = tdb1_get_seqnum(tdb);
+
+ if (tdb->last_error != TDB_SUCCESS)
+ return TDB_ERR_TO_OFF(tdb->last_error);
+ else
+ return val;
+ }
+
+ off = tdb_read_off(tdb, offsetof(struct tdb_header, seqnum));
if (TDB_OFF_IS_ERR(off))
- tdb->last_error = off;
+ tdb->last_error = TDB_OFF_TO_ERR(off);
else
tdb->last_error = TDB_SUCCESS;
return off;
{
return tdb->file->fd;
}
+
+struct traverse_state {
+ enum TDB_ERROR error;
+ struct tdb_context *dest_db;
+};
+
+/*
+ traverse function for repacking
+ */
+static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
+ struct traverse_state *state)
+{
+ state->error = tdb_store(state->dest_db, key, data, TDB_INSERT);
+ if (state->error != TDB_SUCCESS) {
+ return -1;
+ }
+ return 0;
+}
+
+enum TDB_ERROR tdb_repack(struct tdb_context *tdb)
+{
+ struct tdb_context *tmp_db;
+ struct traverse_state state;
+
+ state.error = tdb_transaction_start(tdb);
+ if (state.error != TDB_SUCCESS) {
+ return state.error;
+ }
+
+ tmp_db = tdb_open("tmpdb", TDB_INTERNAL, O_RDWR|O_CREAT, 0, NULL);
+ if (tmp_db == NULL) {
+ state.error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
+ __location__
+ " Failed to create tmp_db");
+ tdb_transaction_cancel(tdb);
+ return tdb->last_error = state.error;
+ }
+
+ state.dest_db = tmp_db;
+ if (tdb_traverse(tdb, repack_traverse, &state) < 0) {
+ goto fail;
+ }
+
+ state.error = tdb_wipe_all(tdb);
+ if (state.error != TDB_SUCCESS) {
+ goto fail;
+ }
+
+ state.dest_db = tdb;
+ if (tdb_traverse(tmp_db, repack_traverse, &state) < 0) {
+ goto fail;
+ }
+
+ tdb_close(tmp_db);
+ return tdb_transaction_commit(tdb);
+
+fail:
+ tdb_transaction_cancel(tdb);
+ tdb_close(tmp_db);
+ return state.error;
+}