mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
tdb2: merge tdb1_context into tdb_context.
Finally, we split out the tdb2-specific parts of tdb_context, and put them into a "tdb2" sub-struct; the tdb1 parts go into a "tdb1" sub-struct. We get rido of tdb1_context and use tdb_context everywhere. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (Imported from CCAN commit bbeb528e74c0e234e1f724ac8d54be404cfc6f9a)
This commit is contained in:
parent
997592431f
commit
c16184f83b
@ -478,7 +478,7 @@ static enum TDB_ERROR check_free(struct tdb_context *tdb,
|
||||
|
||||
}
|
||||
|
||||
ecode = tdb->methods->oob(tdb, off
|
||||
ecode = tdb->tdb2.io->oob(tdb, off
|
||||
+ frec_len(frec)
|
||||
+ sizeof(struct tdb_used_record),
|
||||
false);
|
||||
@ -587,7 +587,7 @@ tdb_off_t dead_space(struct tdb_context *tdb, tdb_off_t off)
|
||||
|
||||
for (len = 0; off + len < tdb->file->map_size; len++) {
|
||||
char c;
|
||||
ecode = tdb->methods->tread(tdb, off, &c, 1);
|
||||
ecode = tdb->tdb2.io->tread(tdb, off, &c, 1);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return ecode;
|
||||
}
|
||||
|
@ -65,8 +65,8 @@ enum TDB_ERROR tdb_ftable_init(struct tdb_context *tdb)
|
||||
unsigned int rnd, max = 0, count = 0;
|
||||
tdb_off_t off;
|
||||
|
||||
tdb->ftable_off = off = first_ftable(tdb);
|
||||
tdb->ftable = 0;
|
||||
tdb->tdb2.ftable_off = off = first_ftable(tdb);
|
||||
tdb->tdb2.ftable = 0;
|
||||
|
||||
while (off) {
|
||||
if (TDB_OFF_IS_ERR(off)) {
|
||||
@ -75,8 +75,8 @@ enum TDB_ERROR tdb_ftable_init(struct tdb_context *tdb)
|
||||
|
||||
rnd = random();
|
||||
if (rnd >= max) {
|
||||
tdb->ftable_off = off;
|
||||
tdb->ftable = count;
|
||||
tdb->tdb2.ftable_off = off;
|
||||
tdb->tdb2.ftable = count;
|
||||
max = rnd;
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ static enum TDB_ERROR enqueue_in_free(struct tdb_context *tdb,
|
||||
return head;
|
||||
|
||||
/* We only need to set ftable_and_len; rest is set in enqueue_in_free */
|
||||
new.ftable_and_len = ((uint64_t)tdb->ftable << (64 - TDB_OFF_UPPER_STEAL))
|
||||
new.ftable_and_len = ((uint64_t)tdb->tdb2.ftable << (64 - TDB_OFF_UPPER_STEAL))
|
||||
| len;
|
||||
|
||||
/* new->next = head. */
|
||||
@ -287,8 +287,8 @@ static tdb_off_t ftable_offset(struct tdb_context *tdb, unsigned int ftable)
|
||||
tdb_off_t off;
|
||||
unsigned int i;
|
||||
|
||||
if (likely(tdb->ftable == ftable))
|
||||
return tdb->ftable_off;
|
||||
if (likely(tdb->tdb2.ftable == ftable))
|
||||
return tdb->tdb2.ftable_off;
|
||||
|
||||
off = first_ftable(tdb);
|
||||
for (i = 0; i < ftable; i++) {
|
||||
@ -595,7 +595,7 @@ enum TDB_ERROR add_free_record(struct tdb_context *tdb,
|
||||
|
||||
len = len_with_header - sizeof(struct tdb_used_record);
|
||||
|
||||
b_off = bucket_off(tdb->ftable_off, size_to_bucket(len));
|
||||
b_off = bucket_off(tdb->tdb2.ftable_off, size_to_bucket(len));
|
||||
ecode = tdb_lock_free_bucket(tdb, b_off, waitflag);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return ecode;
|
||||
@ -606,7 +606,7 @@ enum TDB_ERROR add_free_record(struct tdb_context *tdb,
|
||||
|
||||
/* Coalescing unlocks free list. */
|
||||
if (!ecode && coalesce)
|
||||
ecode = coalesce_list(tdb, tdb->ftable_off, b_off, 2);
|
||||
ecode = coalesce_list(tdb, tdb->tdb2.ftable_off, b_off, 2);
|
||||
else
|
||||
tdb_unlock_free_bucket(tdb, b_off);
|
||||
return ecode;
|
||||
@ -752,7 +752,7 @@ static tdb_off_t lock_and_alloc(struct tdb_context *tdb,
|
||||
|
||||
/* For futureproofing, we put a 0 in any unused space. */
|
||||
if (rec_extra_padding(&rec)) {
|
||||
ecode = tdb->methods->twrite(tdb, best_off + sizeof(rec)
|
||||
ecode = tdb->tdb2.io->twrite(tdb, best_off + sizeof(rec)
|
||||
+ keylen + datalen, "", 1);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
goto unlock_err;
|
||||
@ -800,9 +800,9 @@ static tdb_off_t get_free(struct tdb_context *tdb,
|
||||
else
|
||||
start_b = size_to_bucket(adjust_size(keylen, datalen));
|
||||
|
||||
ftable_off = tdb->ftable_off;
|
||||
ftable = tdb->ftable;
|
||||
while (!wrapped || ftable_off != tdb->ftable_off) {
|
||||
ftable_off = tdb->tdb2.ftable_off;
|
||||
ftable = tdb->tdb2.ftable;
|
||||
while (!wrapped || ftable_off != tdb->tdb2.ftable_off) {
|
||||
/* Start at exact size bucket, and search up... */
|
||||
for (b = find_free_head(tdb, ftable_off, start_b);
|
||||
b < TDB_FREE_BUCKETS;
|
||||
@ -819,8 +819,8 @@ static tdb_off_t get_free(struct tdb_context *tdb,
|
||||
if (b == TDB_FREE_BUCKETS - 1)
|
||||
tdb->stats.alloc_bucket_max++;
|
||||
/* Worked? Stay using this list. */
|
||||
tdb->ftable_off = ftable_off;
|
||||
tdb->ftable = ftable;
|
||||
tdb->tdb2.ftable_off = ftable_off;
|
||||
tdb->tdb2.ftable = ftable;
|
||||
return off;
|
||||
}
|
||||
/* Didn't work. Try next bucket. */
|
||||
@ -898,7 +898,7 @@ static enum TDB_ERROR tdb_expand(struct tdb_context *tdb, tdb_len_t size)
|
||||
|
||||
/* Someone else may have expanded the file, so retry. */
|
||||
old_size = tdb->file->map_size;
|
||||
tdb->methods->oob(tdb, tdb->file->map_size + 1, true);
|
||||
tdb->tdb2.io->oob(tdb, tdb->file->map_size + 1, true);
|
||||
if (tdb->file->map_size != old_size) {
|
||||
tdb_unlock_expand(tdb, F_WRLCK);
|
||||
return TDB_SUCCESS;
|
||||
@ -930,7 +930,7 @@ static enum TDB_ERROR tdb_expand(struct tdb_context *tdb, tdb_len_t size)
|
||||
/* We need room for the record header too. */
|
||||
wanted = adjust_size(0, sizeof(struct tdb_used_record) + wanted);
|
||||
|
||||
ecode = tdb->methods->expand_file(tdb, wanted);
|
||||
ecode = tdb->tdb2.io->expand_file(tdb, wanted);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
tdb_unlock_expand(tdb, F_WRLCK);
|
||||
return ecode;
|
||||
@ -950,7 +950,7 @@ tdb_off_t alloc(struct tdb_context *tdb, size_t keylen, size_t datalen,
|
||||
tdb_off_t off;
|
||||
|
||||
/* We can't hold pointers during this: we could unmap! */
|
||||
assert(!tdb->direct_access);
|
||||
assert(!tdb->tdb2.direct_access);
|
||||
|
||||
for (;;) {
|
||||
enum TDB_ERROR ecode;
|
||||
|
@ -88,7 +88,7 @@ static enum TDB_ERROR tdb_oob(struct tdb_context *tdb, tdb_off_t len,
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
/* We can't hold pointers during this: we could unmap! */
|
||||
assert(!tdb->direct_access
|
||||
assert(!tdb->tdb2.direct_access
|
||||
|| (tdb->flags & TDB_NOLOCK)
|
||||
|| tdb_has_expansion_lock(tdb));
|
||||
|
||||
@ -197,7 +197,7 @@ uint64_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off,
|
||||
enum TDB_ERROR zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len)
|
||||
{
|
||||
char buf[8192] = { 0 };
|
||||
void *p = tdb->methods->direct(tdb, off, len, true);
|
||||
void *p = tdb->tdb2.io->direct(tdb, off, len, true);
|
||||
enum TDB_ERROR ecode = TDB_SUCCESS;
|
||||
|
||||
assert(!(tdb->flags & TDB_RDONLY));
|
||||
@ -210,7 +210,7 @@ enum TDB_ERROR zero_out(struct tdb_context *tdb, tdb_off_t off, tdb_len_t len)
|
||||
}
|
||||
while (len) {
|
||||
unsigned todo = len < sizeof(buf) ? len : sizeof(buf);
|
||||
ecode = tdb->methods->twrite(tdb, off, buf, todo);
|
||||
ecode = tdb->tdb2.io->twrite(tdb, off, buf, todo);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
@ -226,7 +226,7 @@ tdb_off_t tdb_read_off(struct tdb_context *tdb, tdb_off_t off)
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
if (likely(!(tdb->flags & TDB_CONVERT))) {
|
||||
tdb_off_t *p = tdb->methods->direct(tdb, off, sizeof(*p),
|
||||
tdb_off_t *p = tdb->tdb2.io->direct(tdb, off, sizeof(*p),
|
||||
false);
|
||||
if (TDB_PTR_IS_ERR(p)) {
|
||||
return TDB_PTR_ERR(p);
|
||||
@ -253,7 +253,7 @@ static enum TDB_ERROR tdb_write(struct tdb_context *tdb, tdb_off_t off,
|
||||
"Write to read-only database");
|
||||
}
|
||||
|
||||
ecode = tdb->methods->oob(tdb, off + len, false);
|
||||
ecode = tdb->tdb2.io->oob(tdb, off + len, false);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return ecode;
|
||||
}
|
||||
@ -283,7 +283,7 @@ static enum TDB_ERROR tdb_read(struct tdb_context *tdb, tdb_off_t off,
|
||||
{
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
ecode = tdb->methods->oob(tdb, off + len, false);
|
||||
ecode = tdb->tdb2.io->oob(tdb, off + len, false);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return ecode;
|
||||
}
|
||||
@ -317,11 +317,11 @@ enum TDB_ERROR tdb_write_convert(struct tdb_context *tdb, tdb_off_t off,
|
||||
" %zu bytes", len);
|
||||
}
|
||||
memcpy(conv, rec, len);
|
||||
ecode = tdb->methods->twrite(tdb, off,
|
||||
ecode = tdb->tdb2.io->twrite(tdb, off,
|
||||
tdb_convert(tdb, conv, len), len);
|
||||
free(conv);
|
||||
} else {
|
||||
ecode = tdb->methods->twrite(tdb, off, rec, len);
|
||||
ecode = tdb->tdb2.io->twrite(tdb, off, rec, len);
|
||||
}
|
||||
return ecode;
|
||||
}
|
||||
@ -329,7 +329,7 @@ enum TDB_ERROR tdb_write_convert(struct tdb_context *tdb, tdb_off_t off,
|
||||
enum TDB_ERROR tdb_read_convert(struct tdb_context *tdb, tdb_off_t off,
|
||||
void *rec, size_t len)
|
||||
{
|
||||
enum TDB_ERROR ecode = tdb->methods->tread(tdb, off, rec, len);
|
||||
enum TDB_ERROR ecode = tdb->tdb2.io->tread(tdb, off, rec, len);
|
||||
tdb_convert(tdb, rec, len);
|
||||
return ecode;
|
||||
}
|
||||
@ -343,7 +343,7 @@ enum TDB_ERROR tdb_write_off(struct tdb_context *tdb,
|
||||
}
|
||||
|
||||
if (likely(!(tdb->flags & TDB_CONVERT))) {
|
||||
tdb_off_t *p = tdb->methods->direct(tdb, off, sizeof(*p),
|
||||
tdb_off_t *p = tdb->tdb2.io->direct(tdb, off, sizeof(*p),
|
||||
true);
|
||||
if (TDB_PTR_IS_ERR(p)) {
|
||||
return TDB_PTR_ERR(p);
|
||||
@ -370,7 +370,7 @@ static void *_tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset,
|
||||
(size_t)(prefix + len));
|
||||
return TDB_ERR_PTR(TDB_ERR_OOM);
|
||||
} else {
|
||||
ecode = tdb->methods->tread(tdb, offset, buf+prefix, len);
|
||||
ecode = tdb->tdb2.io->tread(tdb, offset, buf+prefix, len);
|
||||
if (unlikely(ecode != TDB_SUCCESS)) {
|
||||
free(buf);
|
||||
return TDB_ERR_PTR(ecode);
|
||||
@ -459,7 +459,7 @@ const void *tdb_access_read(struct tdb_context *tdb,
|
||||
void *ret = NULL;
|
||||
|
||||
if (likely(!(tdb->flags & TDB_CONVERT))) {
|
||||
ret = tdb->methods->direct(tdb, off, len, false);
|
||||
ret = tdb->tdb2.io->direct(tdb, off, len, false);
|
||||
|
||||
if (TDB_PTR_IS_ERR(ret)) {
|
||||
return ret;
|
||||
@ -471,14 +471,14 @@ const void *tdb_access_read(struct tdb_context *tdb,
|
||||
if (TDB_PTR_IS_ERR(hdr)) {
|
||||
return hdr;
|
||||
}
|
||||
hdr->next = tdb->access;
|
||||
tdb->access = hdr;
|
||||
hdr->next = tdb->tdb2.access;
|
||||
tdb->tdb2.access = hdr;
|
||||
ret = hdr + 1;
|
||||
if (convert) {
|
||||
tdb_convert(tdb, (void *)ret, len);
|
||||
}
|
||||
} else
|
||||
tdb->direct_access++;
|
||||
tdb->tdb2.direct_access++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -495,7 +495,7 @@ void *tdb_access_write(struct tdb_context *tdb,
|
||||
}
|
||||
|
||||
if (likely(!(tdb->flags & TDB_CONVERT))) {
|
||||
ret = tdb->methods->direct(tdb, off, len, true);
|
||||
ret = tdb->tdb2.io->direct(tdb, off, len, true);
|
||||
|
||||
if (TDB_PTR_IS_ERR(ret)) {
|
||||
return ret;
|
||||
@ -508,8 +508,8 @@ void *tdb_access_write(struct tdb_context *tdb,
|
||||
if (TDB_PTR_IS_ERR(hdr)) {
|
||||
return hdr;
|
||||
}
|
||||
hdr->next = tdb->access;
|
||||
tdb->access = hdr;
|
||||
hdr->next = tdb->tdb2.access;
|
||||
tdb->tdb2.access = hdr;
|
||||
hdr->off = off;
|
||||
hdr->len = len;
|
||||
hdr->convert = convert;
|
||||
@ -517,7 +517,7 @@ void *tdb_access_write(struct tdb_context *tdb,
|
||||
if (convert)
|
||||
tdb_convert(tdb, (void *)ret, len);
|
||||
} else
|
||||
tdb->direct_access++;
|
||||
tdb->tdb2.direct_access++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -526,7 +526,7 @@ static struct tdb_access_hdr **find_hdr(struct tdb_context *tdb, const void *p)
|
||||
{
|
||||
struct tdb_access_hdr **hp;
|
||||
|
||||
for (hp = &tdb->access; *hp; hp = &(*hp)->next) {
|
||||
for (hp = &tdb->tdb2.access; *hp; hp = &(*hp)->next) {
|
||||
if (*hp + 1 == p)
|
||||
return hp;
|
||||
}
|
||||
@ -542,7 +542,7 @@ void tdb_access_release(struct tdb_context *tdb, const void *p)
|
||||
*hp = hdr->next;
|
||||
free(hdr);
|
||||
} else
|
||||
tdb->direct_access--;
|
||||
tdb->tdb2.direct_access--;
|
||||
}
|
||||
|
||||
enum TDB_ERROR tdb_access_commit(struct tdb_context *tdb, void *p)
|
||||
@ -559,7 +559,7 @@ enum TDB_ERROR tdb_access_commit(struct tdb_context *tdb, void *p)
|
||||
*hp = hdr->next;
|
||||
free(hdr);
|
||||
} else {
|
||||
tdb->direct_access--;
|
||||
tdb->tdb2.direct_access--;
|
||||
ecode = TDB_SUCCESS;
|
||||
}
|
||||
|
||||
@ -587,7 +587,7 @@ void tdb_inc_seqnum(struct tdb_context *tdb)
|
||||
if (likely(!(tdb->flags & TDB_CONVERT))) {
|
||||
int64_t *direct;
|
||||
|
||||
direct = tdb->methods->direct(tdb,
|
||||
direct = tdb->tdb2.io->direct(tdb,
|
||||
offsetof(struct tdb_header,
|
||||
seqnum),
|
||||
sizeof(*direct), true);
|
||||
@ -622,5 +622,5 @@ static const struct tdb_methods io_methods = {
|
||||
*/
|
||||
void tdb_io_init(struct tdb_context *tdb)
|
||||
{
|
||||
tdb->methods = &io_methods;
|
||||
tdb->tdb2.io = &io_methods;
|
||||
}
|
||||
|
@ -363,11 +363,8 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
|
||||
} else {
|
||||
tdb->name = NULL;
|
||||
}
|
||||
tdb->direct_access = 0;
|
||||
tdb->flags = tdb_flags;
|
||||
tdb->log_fn = NULL;
|
||||
tdb->transaction = NULL;
|
||||
tdb->access = NULL;
|
||||
tdb->open_flags = open_flags;
|
||||
tdb->last_error = TDB_SUCCESS;
|
||||
tdb->file = NULL;
|
||||
@ -379,6 +376,9 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
|
||||
tdb->stats.base.attr = TDB_ATTRIBUTE_STATS;
|
||||
tdb->stats.size = sizeof(tdb->stats);
|
||||
tdb_io_init(tdb);
|
||||
tdb->tdb2.direct_access = 0;
|
||||
tdb->tdb2.transaction = NULL;
|
||||
tdb->tdb2.access = NULL;
|
||||
|
||||
while (attr) {
|
||||
switch (attr->base.attr) {
|
||||
@ -573,7 +573,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
|
||||
tdb_unlock_open(tdb, openlock);
|
||||
|
||||
/* This make sure we have current map_size and mmap. */
|
||||
ecode = tdb->methods->oob(tdb, tdb->file->map_size + 1, true);
|
||||
ecode = tdb->tdb2.io->oob(tdb, tdb->file->map_size + 1, true);
|
||||
if (unlikely(ecode != TDB_SUCCESS))
|
||||
goto fail;
|
||||
|
||||
@ -655,7 +655,7 @@ int tdb_close(struct tdb_context *tdb)
|
||||
|
||||
tdb_trace(tdb, "tdb_close");
|
||||
|
||||
if (tdb->transaction) {
|
||||
if (tdb->tdb2.transaction) {
|
||||
tdb_transaction_cancel(tdb);
|
||||
}
|
||||
|
||||
|
@ -283,6 +283,9 @@ struct traverse_info {
|
||||
tdb_off_t prev;
|
||||
};
|
||||
|
||||
typedef uint32_t tdb1_len_t;
|
||||
typedef uint32_t tdb1_off_t;
|
||||
|
||||
enum tdb_lock_flags {
|
||||
/* WAIT == F_SETLKW, NOWAIT == F_SETLK */
|
||||
TDB_LOCK_NOWAIT = 0,
|
||||
@ -333,68 +336,6 @@ struct tdb_file {
|
||||
ino_t inode;
|
||||
};
|
||||
|
||||
struct tdb_context {
|
||||
/* Single list of all TDBs, to detect multiple opens. */
|
||||
struct tdb_context *next;
|
||||
|
||||
/* Filename of the database. */
|
||||
const char *name;
|
||||
|
||||
/* Logging function */
|
||||
void (*log_fn)(struct tdb_context *tdb,
|
||||
enum tdb_log_level level,
|
||||
enum TDB_ERROR ecode,
|
||||
const char *message,
|
||||
void *data);
|
||||
void *log_data;
|
||||
|
||||
/* Last error we returned. */
|
||||
enum TDB_ERROR last_error;
|
||||
|
||||
/* The actual file information */
|
||||
struct tdb_file *file;
|
||||
|
||||
/* Open flags passed to tdb_open. */
|
||||
int open_flags;
|
||||
|
||||
/* low level (fnctl) lock functions. */
|
||||
int (*lock_fn)(int fd, int rw, off_t off, off_t len, bool w, void *);
|
||||
int (*unlock_fn)(int fd, int rw, off_t off, off_t len, void *);
|
||||
void *lock_data;
|
||||
|
||||
/* the flags passed to tdb_open. */
|
||||
uint32_t flags;
|
||||
|
||||
/* Our statistics. */
|
||||
struct tdb_attribute_stats stats;
|
||||
|
||||
/* Hash function. */
|
||||
uint64_t (*hash_fn)(const void *key, size_t len, uint64_t seed, void *);
|
||||
void *hash_data;
|
||||
uint64_t hash_seed;
|
||||
|
||||
/* Are we accessing directly? (debugging check). */
|
||||
int direct_access;
|
||||
|
||||
/* Set if we are in a transaction. */
|
||||
struct tdb_transaction *transaction;
|
||||
|
||||
/* What free table are we using? */
|
||||
tdb_off_t ftable_off;
|
||||
unsigned int ftable;
|
||||
|
||||
/* Our open hook, if any. */
|
||||
enum TDB_ERROR (*openhook)(int fd, void *data);
|
||||
void *openhook_data;
|
||||
|
||||
/* IO methods: changes for transactions. */
|
||||
const struct tdb_methods *methods;
|
||||
|
||||
/* Direct access information */
|
||||
struct tdb_access_hdr *access;
|
||||
|
||||
};
|
||||
|
||||
struct tdb_methods {
|
||||
enum TDB_ERROR (*tread)(struct tdb_context *, tdb_off_t, void *,
|
||||
tdb_len_t);
|
||||
@ -600,6 +541,102 @@ int tdb_fcntl_unlock(int fd, int rw, off_t off, off_t len, void *);
|
||||
enum TDB_ERROR tdb_transaction_recover(struct tdb_context *tdb);
|
||||
tdb_bool_err tdb_needs_recovery(struct tdb_context *tdb);
|
||||
|
||||
/* this is stored at the front of every database */
|
||||
struct tdb1_header {
|
||||
char magic_food[32]; /* for /etc/magic */
|
||||
uint32_t version; /* version of the code */
|
||||
uint32_t hash_size; /* number of hash entries */
|
||||
tdb1_off_t rwlocks; /* obsolete - kept to detect old formats */
|
||||
tdb1_off_t recovery_start; /* offset of transaction recovery region */
|
||||
tdb1_off_t sequence_number; /* used when TDB1_SEQNUM is set */
|
||||
uint32_t magic1_hash; /* hash of TDB_MAGIC_FOOD. */
|
||||
uint32_t magic2_hash; /* hash of TDB1_MAGIC. */
|
||||
tdb1_off_t reserved[27];
|
||||
};
|
||||
|
||||
struct tdb1_traverse_lock {
|
||||
struct tdb1_traverse_lock *next;
|
||||
uint32_t off;
|
||||
uint32_t hash;
|
||||
int lock_rw;
|
||||
};
|
||||
|
||||
struct tdb_context {
|
||||
/* Single list of all TDBs, to detect multiple opens. */
|
||||
struct tdb_context *next;
|
||||
|
||||
/* Filename of the database. */
|
||||
const char *name;
|
||||
|
||||
/* Logging function */
|
||||
void (*log_fn)(struct tdb_context *tdb,
|
||||
enum tdb_log_level level,
|
||||
enum TDB_ERROR ecode,
|
||||
const char *message,
|
||||
void *data);
|
||||
void *log_data;
|
||||
|
||||
/* Open flags passed to tdb_open. */
|
||||
int open_flags;
|
||||
|
||||
/* low level (fnctl) lock functions. */
|
||||
int (*lock_fn)(int fd, int rw, off_t off, off_t len, bool w, void *);
|
||||
int (*unlock_fn)(int fd, int rw, off_t off, off_t len, void *);
|
||||
void *lock_data;
|
||||
|
||||
/* the tdb flags passed to tdb_open. */
|
||||
uint32_t flags;
|
||||
|
||||
/* Our statistics. */
|
||||
struct tdb_attribute_stats stats;
|
||||
|
||||
/* The actual file information */
|
||||
struct tdb_file *file;
|
||||
|
||||
/* Hash function. */
|
||||
uint64_t (*hash_fn)(const void *key, size_t len, uint64_t seed, void *);
|
||||
void *hash_data;
|
||||
uint64_t hash_seed;
|
||||
|
||||
/* Our open hook, if any. */
|
||||
enum TDB_ERROR (*openhook)(int fd, void *data);
|
||||
void *openhook_data;
|
||||
|
||||
/* Last error we returned. */
|
||||
enum TDB_ERROR last_error;
|
||||
|
||||
struct {
|
||||
|
||||
/* Are we accessing directly? (debugging check). */
|
||||
int direct_access;
|
||||
|
||||
/* Set if we are in a transaction. */
|
||||
struct tdb_transaction *transaction;
|
||||
|
||||
/* What free table are we using? */
|
||||
tdb_off_t ftable_off;
|
||||
unsigned int ftable;
|
||||
|
||||
/* IO methods: changes for transactions. */
|
||||
const struct tdb_methods *io;
|
||||
|
||||
/* Direct access information */
|
||||
struct tdb_access_hdr *access;
|
||||
} tdb2;
|
||||
|
||||
struct {
|
||||
int traverse_read; /* read-only traversal */
|
||||
int traverse_write; /* read-write traversal */
|
||||
|
||||
struct tdb1_header header; /* a cached copy of the header */
|
||||
struct tdb1_traverse_lock travlocks; /* current traversal locks */
|
||||
const struct tdb1_methods *io;
|
||||
struct tdb1_transaction *transaction;
|
||||
int page_size;
|
||||
int max_dead_records;
|
||||
} tdb1;
|
||||
};
|
||||
|
||||
/* tdb.c: */
|
||||
enum TDB_ERROR COLD tdb_logerr(struct tdb_context *tdb,
|
||||
enum TDB_ERROR ecode,
|
||||
|
@ -72,13 +72,13 @@ static enum TDB_ERROR replace_data(struct tdb_context *tdb,
|
||||
}
|
||||
|
||||
new_off += sizeof(struct tdb_used_record);
|
||||
ecode = tdb->methods->twrite(tdb, new_off, key.dptr, key.dsize);
|
||||
ecode = tdb->tdb2.io->twrite(tdb, new_off, key.dptr, key.dsize);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return ecode;
|
||||
}
|
||||
|
||||
new_off += key.dsize;
|
||||
ecode = tdb->methods->twrite(tdb, new_off, dbuf.dptr, dbuf.dsize);
|
||||
ecode = tdb->tdb2.io->twrite(tdb, new_off, dbuf.dptr, dbuf.dsize);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return ecode;
|
||||
}
|
||||
@ -96,10 +96,10 @@ static enum TDB_ERROR update_data(struct tdb_context *tdb,
|
||||
{
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
ecode = tdb->methods->twrite(tdb, off, dbuf.dptr, dbuf.dsize);
|
||||
ecode = tdb->tdb2.io->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);
|
||||
ecode = tdb->tdb2.io->twrite(tdb, off + dbuf.dsize, "", 1);
|
||||
}
|
||||
if (tdb->flags & TDB_SEQNUM)
|
||||
tdb_inc_seqnum(tdb);
|
||||
@ -213,7 +213,7 @@ enum TDB_ERROR tdb_append(struct tdb_context *tdb,
|
||||
+ dbuf.dsize));
|
||||
goto out;
|
||||
}
|
||||
ecode = tdb->methods->tread(tdb, off + sizeof(rec) + key.dsize,
|
||||
ecode = tdb->tdb2.io->tread(tdb, off + sizeof(rec) + key.dsize,
|
||||
newdata, old_dlen);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
goto out_free_newdata;
|
||||
@ -326,9 +326,17 @@ unsigned int tdb_get_flags(struct tdb_context *tdb)
|
||||
return tdb->flags;
|
||||
}
|
||||
|
||||
static bool inside_transaction(const struct tdb_context *tdb)
|
||||
{
|
||||
if (tdb->flags & TDB_VERSION1)
|
||||
return tdb->tdb1.transaction != NULL;
|
||||
else
|
||||
return tdb->tdb2.transaction != NULL;
|
||||
}
|
||||
|
||||
static bool readonly_changable(struct tdb_context *tdb, const char *caller)
|
||||
{
|
||||
if (tdb->transaction) {
|
||||
if (inside_transaction(tdb)) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
|
||||
TDB_LOG_USE_ERROR,
|
||||
"%s: can't change"
|
||||
|
@ -36,11 +36,8 @@
|
||||
#endif
|
||||
|
||||
|
||||
/** This is the context structure that is returned from a db open. */
|
||||
typedef struct tdb1_context TDB1_CONTEXT;
|
||||
|
||||
typedef int (*tdb1_traverse_func)(struct tdb1_context *, TDB_DATA, TDB_DATA, void *);
|
||||
typedef void (*tdb1_log_func)(struct tdb1_context *, enum tdb_log_level, enum TDB_ERROR,
|
||||
typedef int (*tdb1_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *);
|
||||
typedef void (*tdb1_log_func)(struct tdb_context *, enum tdb_log_level, enum TDB_ERROR,
|
||||
const char *, void *);
|
||||
typedef uint64_t (*tdb1_hash_func)(const void *key, size_t len, uint64_t seed,
|
||||
void *data);
|
||||
@ -50,84 +47,84 @@ struct tdb1_logging_context {
|
||||
void *log_private;
|
||||
};
|
||||
|
||||
struct tdb1_context *tdb1_open(const char *name, int hash_size, int tdb1_flags,
|
||||
struct tdb_context *tdb1_open(const char *name, int hash_size, int tdb1_flags,
|
||||
int open_flags, mode_t mode);
|
||||
|
||||
struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flags,
|
||||
struct tdb_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flags,
|
||||
int open_flags, mode_t mode,
|
||||
const struct tdb1_logging_context *log_ctx,
|
||||
tdb1_hash_func hash_fn);
|
||||
|
||||
void tdb1_set_max_dead(struct tdb1_context *tdb, int max_dead);
|
||||
void tdb1_set_max_dead(struct tdb_context *tdb, int max_dead);
|
||||
|
||||
TDB_DATA tdb1_fetch(struct tdb1_context *tdb, TDB_DATA key);
|
||||
TDB_DATA tdb1_fetch(struct tdb_context *tdb, TDB_DATA key);
|
||||
|
||||
int tdb1_parse_record(struct tdb1_context *tdb, TDB_DATA key,
|
||||
int tdb1_parse_record(struct tdb_context *tdb, TDB_DATA key,
|
||||
int (*parser)(TDB_DATA key, TDB_DATA data,
|
||||
void *private_data),
|
||||
void *private_data);
|
||||
|
||||
int tdb1_delete(struct tdb1_context *tdb, TDB_DATA key);
|
||||
int tdb1_delete(struct tdb_context *tdb, TDB_DATA key);
|
||||
|
||||
int tdb1_store(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
|
||||
int tdb1_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
|
||||
|
||||
int tdb1_append(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA new_dbuf);
|
||||
int tdb1_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf);
|
||||
|
||||
int tdb1_close(struct tdb1_context *tdb);
|
||||
int tdb1_close(struct tdb_context *tdb);
|
||||
|
||||
TDB_DATA tdb1_firstkey(struct tdb1_context *tdb);
|
||||
TDB_DATA tdb1_firstkey(struct tdb_context *tdb);
|
||||
|
||||
TDB_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB_DATA key);
|
||||
TDB_DATA tdb1_nextkey(struct tdb_context *tdb, TDB_DATA key);
|
||||
|
||||
int tdb1_traverse(struct tdb1_context *tdb, tdb1_traverse_func fn, void *private_data);
|
||||
int tdb1_traverse(struct tdb_context *tdb, tdb1_traverse_func fn, void *private_data);
|
||||
|
||||
int tdb1_traverse_read(struct tdb1_context *tdb, tdb1_traverse_func fn, void *private_data);
|
||||
int tdb1_traverse_read(struct tdb_context *tdb, tdb1_traverse_func fn, void *private_data);
|
||||
|
||||
int tdb1_exists(struct tdb1_context *tdb, TDB_DATA key);
|
||||
int tdb1_exists(struct tdb_context *tdb, TDB_DATA key);
|
||||
|
||||
int tdb1_lockall(struct tdb1_context *tdb);
|
||||
int tdb1_lockall(struct tdb_context *tdb);
|
||||
|
||||
int tdb1_unlockall(struct tdb1_context *tdb);
|
||||
int tdb1_unlockall(struct tdb_context *tdb);
|
||||
|
||||
int tdb1_lockall_read(struct tdb1_context *tdb);
|
||||
int tdb1_lockall_read(struct tdb_context *tdb);
|
||||
|
||||
int tdb1_unlockall_read(struct tdb1_context *tdb);
|
||||
int tdb1_unlockall_read(struct tdb_context *tdb);
|
||||
|
||||
int tdb1_transaction_start(struct tdb1_context *tdb);
|
||||
int tdb1_transaction_start(struct tdb_context *tdb);
|
||||
|
||||
int tdb1_transaction_prepare_commit(struct tdb1_context *tdb);
|
||||
int tdb1_transaction_prepare_commit(struct tdb_context *tdb);
|
||||
|
||||
int tdb1_transaction_commit(struct tdb1_context *tdb);
|
||||
int tdb1_transaction_commit(struct tdb_context *tdb);
|
||||
|
||||
int tdb1_transaction_cancel(struct tdb1_context *tdb);
|
||||
int tdb1_transaction_cancel(struct tdb_context *tdb);
|
||||
|
||||
int tdb1_get_seqnum(struct tdb1_context *tdb);
|
||||
int tdb1_get_seqnum(struct tdb_context *tdb);
|
||||
|
||||
int tdb1_hash_size(struct tdb1_context *tdb);
|
||||
int tdb1_hash_size(struct tdb_context *tdb);
|
||||
|
||||
void tdb1_increment_seqnum_nonblock(struct tdb1_context *tdb);
|
||||
void tdb1_increment_seqnum_nonblock(struct tdb_context *tdb);
|
||||
|
||||
uint64_t tdb1_incompatible_hash(const void *key, size_t len, uint64_t seed, void *);
|
||||
|
||||
int tdb1_check(struct tdb1_context *tdb,
|
||||
int tdb1_check(struct tdb_context *tdb,
|
||||
int (*check) (TDB_DATA key, TDB_DATA data, void *private_data),
|
||||
void *private_data);
|
||||
|
||||
/* @} ******************************************************************/
|
||||
|
||||
/* Low level locking functions: use with care */
|
||||
int tdb1_chainlock(struct tdb1_context *tdb, TDB_DATA key);
|
||||
int tdb1_chainunlock(struct tdb1_context *tdb, TDB_DATA key);
|
||||
int tdb1_chainlock_read(struct tdb1_context *tdb, TDB_DATA key);
|
||||
int tdb1_chainunlock_read(struct tdb1_context *tdb, TDB_DATA key);
|
||||
int tdb1_chainlock(struct tdb_context *tdb, TDB_DATA key);
|
||||
int tdb1_chainunlock(struct tdb_context *tdb, TDB_DATA key);
|
||||
int tdb1_chainlock_read(struct tdb_context *tdb, TDB_DATA key);
|
||||
int tdb1_chainunlock_read(struct tdb_context *tdb, TDB_DATA key);
|
||||
|
||||
|
||||
/* wipe and repack */
|
||||
int tdb1_wipe_all(struct tdb1_context *tdb);
|
||||
int tdb1_repack(struct tdb1_context *tdb);
|
||||
int tdb1_wipe_all(struct tdb_context *tdb);
|
||||
int tdb1_repack(struct tdb_context *tdb);
|
||||
|
||||
/* Debug functions. Not used in production. */
|
||||
char *tdb1_summary(struct tdb1_context *tdb);
|
||||
char *tdb1_summary(struct tdb_context *tdb);
|
||||
|
||||
extern TDB_DATA tdb1_null;
|
||||
|
||||
|
@ -25,12 +25,12 @@
|
||||
#include "tdb1_private.h"
|
||||
|
||||
/* Since we opened it, these shouldn't fail unless it's recent corruption. */
|
||||
static bool tdb1_check_header(struct tdb1_context *tdb, tdb1_off_t *recovery)
|
||||
static bool tdb1_check_header(struct tdb_context *tdb, tdb1_off_t *recovery)
|
||||
{
|
||||
struct tdb1_header hdr;
|
||||
uint32_t h1, h2;
|
||||
|
||||
if (tdb->methods->tdb1_read(tdb, 0, &hdr, sizeof(hdr), 0) == -1)
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, 0, &hdr, sizeof(hdr), 0) == -1)
|
||||
return false;
|
||||
if (strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0)
|
||||
goto corrupt;
|
||||
@ -50,11 +50,11 @@ static bool tdb1_check_header(struct tdb1_context *tdb, tdb1_off_t *recovery)
|
||||
if (hdr.hash_size == 0)
|
||||
goto corrupt;
|
||||
|
||||
if (hdr.hash_size != tdb->header.hash_size)
|
||||
if (hdr.hash_size != tdb->tdb1.header.hash_size)
|
||||
goto corrupt;
|
||||
|
||||
if (hdr.recovery_start != 0 &&
|
||||
hdr.recovery_start < TDB1_DATA_START(tdb->header.hash_size))
|
||||
hdr.recovery_start < TDB1_DATA_START(tdb->tdb1.header.hash_size))
|
||||
goto corrupt;
|
||||
|
||||
*recovery = hdr.recovery_start;
|
||||
@ -67,14 +67,14 @@ corrupt:
|
||||
}
|
||||
|
||||
/* Generic record header check. */
|
||||
static bool tdb1_check_record(struct tdb1_context *tdb,
|
||||
static bool tdb1_check_record(struct tdb_context *tdb,
|
||||
tdb1_off_t off,
|
||||
const struct tdb1_record *rec)
|
||||
{
|
||||
tdb1_off_t tailer;
|
||||
|
||||
/* Check rec->next: 0 or points to record offset, aligned. */
|
||||
if (rec->next > 0 && rec->next < TDB1_DATA_START(tdb->header.hash_size)){
|
||||
if (rec->next > 0 && rec->next < TDB1_DATA_START(tdb->tdb1.header.hash_size)){
|
||||
tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
|
||||
"Record offset %d too small next %d\n",
|
||||
off, rec->next);
|
||||
@ -92,7 +92,7 @@ static bool tdb1_check_record(struct tdb1_context *tdb,
|
||||
off, rec->next);
|
||||
goto corrupt;
|
||||
}
|
||||
if (tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0))
|
||||
if (tdb->tdb1.io->tdb1_oob(tdb, rec->next+sizeof(*rec), 0))
|
||||
goto corrupt;
|
||||
|
||||
/* Check rec_len: similar to rec->next, implies next record. */
|
||||
@ -110,7 +110,7 @@ static bool tdb1_check_record(struct tdb1_context *tdb,
|
||||
goto corrupt;
|
||||
}
|
||||
/* OOB allows "right at the end" access, so this works for last rec. */
|
||||
if (tdb->methods->tdb1_oob(tdb, off+sizeof(*rec)+rec->rec_len, 0))
|
||||
if (tdb->tdb1.io->tdb1_oob(tdb, off+sizeof(*rec)+rec->rec_len, 0))
|
||||
goto corrupt;
|
||||
|
||||
/* Check tailer. */
|
||||
@ -132,14 +132,14 @@ corrupt:
|
||||
|
||||
/* Grab some bytes: may copy if can't use mmap.
|
||||
Caller has already done bounds check. */
|
||||
static TDB_DATA get_bytes(struct tdb1_context *tdb,
|
||||
static TDB_DATA get_bytes(struct tdb_context *tdb,
|
||||
tdb1_off_t off, tdb1_len_t len)
|
||||
{
|
||||
TDB_DATA d;
|
||||
|
||||
d.dsize = len;
|
||||
|
||||
if (tdb->transaction == NULL && tdb->file->map_ptr != NULL)
|
||||
if (tdb->tdb1.transaction == NULL && tdb->file->map_ptr != NULL)
|
||||
d.dptr = (unsigned char *)tdb->file->map_ptr + off;
|
||||
else
|
||||
d.dptr = tdb1_alloc_read(tdb, off, d.dsize);
|
||||
@ -147,9 +147,9 @@ static TDB_DATA get_bytes(struct tdb1_context *tdb,
|
||||
}
|
||||
|
||||
/* Frees data if we're not able to simply use mmap. */
|
||||
static void put_bytes(struct tdb1_context *tdb, TDB_DATA d)
|
||||
static void put_bytes(struct tdb_context *tdb, TDB_DATA d)
|
||||
{
|
||||
if (tdb->transaction == NULL && tdb->file->map_ptr != NULL)
|
||||
if (tdb->tdb1.transaction == NULL && tdb->file->map_ptr != NULL)
|
||||
return;
|
||||
free(d.dptr);
|
||||
}
|
||||
@ -232,7 +232,7 @@ static void record_offset(unsigned char bits[], tdb1_off_t off)
|
||||
}
|
||||
|
||||
/* Check that an in-use record is valid. */
|
||||
static bool tdb1_check_used_record(struct tdb1_context *tdb,
|
||||
static bool tdb1_check_used_record(struct tdb_context *tdb,
|
||||
tdb1_off_t off,
|
||||
const struct tdb1_record *rec,
|
||||
unsigned char **hashes,
|
||||
@ -291,7 +291,7 @@ fail_put_key:
|
||||
}
|
||||
|
||||
/* Check that an unused record is valid. */
|
||||
static bool tdb1_check_free_record(struct tdb1_context *tdb,
|
||||
static bool tdb1_check_free_record(struct tdb_context *tdb,
|
||||
tdb1_off_t off,
|
||||
const struct tdb1_record *rec,
|
||||
unsigned char **hashes)
|
||||
@ -308,13 +308,13 @@ static bool tdb1_check_free_record(struct tdb1_context *tdb,
|
||||
}
|
||||
|
||||
/* Slow, but should be very rare. */
|
||||
size_t tdb1_dead_space(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
size_t tdb1_dead_space(struct tdb_context *tdb, tdb1_off_t off)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
for (len = 0; off + len < tdb->file->map_size; len++) {
|
||||
char c;
|
||||
if (tdb->methods->tdb1_read(tdb, off, &c, 1, 0))
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, off, &c, 1, 0))
|
||||
return 0;
|
||||
if (c != 0 && c != 0x42)
|
||||
break;
|
||||
@ -322,7 +322,7 @@ size_t tdb1_dead_space(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
return len;
|
||||
}
|
||||
|
||||
int tdb1_check(struct tdb1_context *tdb,
|
||||
int tdb1_check(struct tdb_context *tdb,
|
||||
int (*check)(TDB_DATA key, TDB_DATA data, void *private_data),
|
||||
void *private_data)
|
||||
{
|
||||
@ -344,14 +344,14 @@ int tdb1_check(struct tdb1_context *tdb,
|
||||
}
|
||||
|
||||
/* Make sure we know true size of the underlying file. */
|
||||
tdb->methods->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
|
||||
tdb->tdb1.io->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
|
||||
|
||||
/* Header must be OK: also gets us the recovery ptr, if any. */
|
||||
if (!tdb1_check_header(tdb, &recovery_start))
|
||||
goto unlock;
|
||||
|
||||
/* We should have the whole header, too. */
|
||||
if (tdb->file->map_size < TDB1_DATA_START(tdb->header.hash_size)) {
|
||||
if (tdb->file->map_size < TDB1_DATA_START(tdb->tdb1.header.hash_size)) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
|
||||
"File too short for hashes\n");
|
||||
goto unlock;
|
||||
@ -359,20 +359,20 @@ int tdb1_check(struct tdb1_context *tdb,
|
||||
|
||||
/* One big malloc: pointers then bit arrays. */
|
||||
hashes = (unsigned char **)calloc(
|
||||
1, sizeof(hashes[0]) * (1+tdb->header.hash_size)
|
||||
+ BITMAP_BITS / CHAR_BIT * (1+tdb->header.hash_size));
|
||||
1, sizeof(hashes[0]) * (1+tdb->tdb1.header.hash_size)
|
||||
+ BITMAP_BITS / CHAR_BIT * (1+tdb->tdb1.header.hash_size));
|
||||
if (!hashes) {
|
||||
tdb->last_error = TDB_ERR_OOM;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* Initialize pointers */
|
||||
hashes[0] = (unsigned char *)(&hashes[1+tdb->header.hash_size]);
|
||||
for (h = 1; h < 1+tdb->header.hash_size; h++)
|
||||
hashes[0] = (unsigned char *)(&hashes[1+tdb->tdb1.header.hash_size]);
|
||||
for (h = 1; h < 1+tdb->tdb1.header.hash_size; h++)
|
||||
hashes[h] = hashes[h-1] + BITMAP_BITS / CHAR_BIT;
|
||||
|
||||
/* Freelist and hash headers are all in a row: read them. */
|
||||
for (h = 0; h < 1+tdb->header.hash_size; h++) {
|
||||
for (h = 0; h < 1+tdb->tdb1.header.hash_size; h++) {
|
||||
if (tdb1_ofs_read(tdb, TDB1_FREELIST_TOP + h*sizeof(tdb1_off_t),
|
||||
&off) == -1)
|
||||
goto free;
|
||||
@ -381,10 +381,10 @@ int tdb1_check(struct tdb1_context *tdb,
|
||||
}
|
||||
|
||||
/* For each record, read it in and check it's ok. */
|
||||
for (off = TDB1_DATA_START(tdb->header.hash_size);
|
||||
for (off = TDB1_DATA_START(tdb->tdb1.header.hash_size);
|
||||
off < tdb->file->map_size;
|
||||
off += sizeof(rec) + rec.rec_len) {
|
||||
if (tdb->methods->tdb1_read(tdb, off, &rec, sizeof(rec),
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, off, &rec, sizeof(rec),
|
||||
TDB1_DOCONV()) == -1)
|
||||
goto free;
|
||||
switch (rec.magic) {
|
||||
@ -434,7 +434,7 @@ int tdb1_check(struct tdb1_context *tdb,
|
||||
|
||||
/* Now, hashes should all be empty: each record exists and is referred
|
||||
* to by one other. */
|
||||
for (h = 0; h < 1+tdb->header.hash_size; h++) {
|
||||
for (h = 0; h < 1+tdb->tdb1.header.hash_size; h++) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < BITMAP_BITS / CHAR_BIT; i++) {
|
||||
if (hashes[h][i] != 0) {
|
||||
|
@ -28,9 +28,9 @@
|
||||
#include "tdb1_private.h"
|
||||
|
||||
/* read a freelist record and check for simple errors */
|
||||
int tdb1_rec_free_read(struct tdb1_context *tdb, tdb1_off_t off, struct tdb1_record *rec)
|
||||
int tdb1_rec_free_read(struct tdb_context *tdb, tdb1_off_t off, struct tdb1_record *rec)
|
||||
{
|
||||
if (tdb->methods->tdb1_read(tdb, off, rec, sizeof(*rec),TDB1_DOCONV()) == -1)
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, off, rec, sizeof(*rec),TDB1_DOCONV()) == -1)
|
||||
return -1;
|
||||
|
||||
if (rec->magic == TDB1_MAGIC) {
|
||||
@ -40,7 +40,7 @@ int tdb1_rec_free_read(struct tdb1_context *tdb, tdb1_off_t off, struct tdb1_rec
|
||||
"tdb1_rec_free_read non-free magic 0x%x at offset=%d - fixing\n",
|
||||
rec->magic, off);
|
||||
rec->magic = TDB1_FREE_MAGIC;
|
||||
if (tdb->methods->tdb1_write(tdb, off, rec, sizeof(*rec)) == -1)
|
||||
if (tdb->tdb1.io->tdb1_write(tdb, off, rec, sizeof(*rec)) == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -50,14 +50,14 @@ int tdb1_rec_free_read(struct tdb1_context *tdb, tdb1_off_t off, struct tdb1_rec
|
||||
rec->magic, off);
|
||||
return -1;
|
||||
}
|
||||
if (tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
|
||||
if (tdb->tdb1.io->tdb1_oob(tdb, rec->next+sizeof(*rec), 0) != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* update a record tailer (must hold allocation lock) */
|
||||
static int update_tailer(struct tdb1_context *tdb, tdb1_off_t offset,
|
||||
static int update_tailer(struct tdb_context *tdb, tdb1_off_t offset,
|
||||
const struct tdb1_record *rec)
|
||||
{
|
||||
tdb1_off_t totalsize;
|
||||
@ -70,7 +70,7 @@ static int update_tailer(struct tdb1_context *tdb, tdb1_off_t offset,
|
||||
|
||||
/* Add an element into the freelist. Merge adjacent records if
|
||||
necessary. */
|
||||
int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *rec)
|
||||
int tdb1_free(struct tdb_context *tdb, tdb1_off_t offset, struct tdb1_record *rec)
|
||||
{
|
||||
/* Allocation and tailer lock */
|
||||
if (tdb1_lock(tdb, -1, F_WRLCK) != 0)
|
||||
@ -84,7 +84,7 @@ int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *r
|
||||
}
|
||||
|
||||
/* Look left */
|
||||
if (offset - sizeof(tdb1_off_t) > TDB1_DATA_START(tdb->header.hash_size)) {
|
||||
if (offset - sizeof(tdb1_off_t) > TDB1_DATA_START(tdb->tdb1.header.hash_size)) {
|
||||
tdb1_off_t left = offset - sizeof(tdb1_off_t);
|
||||
struct tdb1_record l;
|
||||
tdb1_off_t leftsize;
|
||||
@ -104,12 +104,12 @@ int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *r
|
||||
left = offset - leftsize;
|
||||
|
||||
if (leftsize > offset ||
|
||||
left < TDB1_DATA_START(tdb->header.hash_size)) {
|
||||
left < TDB1_DATA_START(tdb->tdb1.header.hash_size)) {
|
||||
goto update;
|
||||
}
|
||||
|
||||
/* Now read in the left record */
|
||||
if (tdb->methods->tdb1_read(tdb, left, &l, sizeof(l), TDB1_DOCONV()) == -1) {
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, left, &l, sizeof(l), TDB1_DOCONV()) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_free: left read failed at %u (%u)", left, leftsize);
|
||||
goto update;
|
||||
@ -169,7 +169,7 @@ update:
|
||||
not the beginning. This is so the left merge in a free is more likely to be
|
||||
able to free up the record without fragmentation
|
||||
*/
|
||||
static tdb1_off_t tdb1_allocate_ofs(struct tdb1_context *tdb,
|
||||
static tdb1_off_t tdb1_allocate_ofs(struct tdb_context *tdb,
|
||||
tdb1_len_t length, tdb1_off_t rec_ptr,
|
||||
struct tdb1_record *rec, tdb1_off_t last_ptr)
|
||||
{
|
||||
@ -224,7 +224,7 @@ static tdb1_off_t tdb1_allocate_ofs(struct tdb1_context *tdb,
|
||||
|
||||
0 is returned if the space could not be allocated
|
||||
*/
|
||||
tdb1_off_t tdb1_allocate(struct tdb1_context *tdb, tdb1_len_t length, struct tdb1_record *rec)
|
||||
tdb1_off_t tdb1_allocate(struct tdb_context *tdb, tdb1_len_t length, struct tdb1_record *rec)
|
||||
{
|
||||
tdb1_off_t rec_ptr, last_ptr, newrec_ptr;
|
||||
struct {
|
||||
|
@ -36,7 +36,7 @@
|
||||
if necessary
|
||||
note that "len" is the minimum length needed for the db
|
||||
*/
|
||||
static int tdb1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
|
||||
static int tdb1_oob(struct tdb_context *tdb, tdb1_off_t len, int probe)
|
||||
{
|
||||
struct stat st;
|
||||
if (len <= tdb->file->map_size)
|
||||
@ -75,19 +75,19 @@ static int tdb1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
|
||||
}
|
||||
|
||||
/* write a lump of data at a specified offset */
|
||||
static int tdb1_write(struct tdb1_context *tdb, tdb1_off_t off,
|
||||
static int tdb1_write(struct tdb_context *tdb, tdb1_off_t off,
|
||||
const void *buf, tdb1_len_t len)
|
||||
{
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->traverse_read) {
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->tdb1.traverse_read) {
|
||||
tdb->last_error = TDB_ERR_RDONLY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tdb->methods->tdb1_oob(tdb, off + len, 0) != 0)
|
||||
if (tdb->tdb1.io->tdb1_oob(tdb, off + len, 0) != 0)
|
||||
return -1;
|
||||
|
||||
if (tdb->file->map_ptr) {
|
||||
@ -133,10 +133,10 @@ void *tdb1_convert(void *buf, uint32_t size)
|
||||
|
||||
|
||||
/* read a lump of data at a specified offset, maybe convert */
|
||||
static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf,
|
||||
static int tdb1_read(struct tdb_context *tdb, tdb1_off_t off, void *buf,
|
||||
tdb1_len_t len, int cv)
|
||||
{
|
||||
if (tdb->methods->tdb1_oob(tdb, off + len, 0) != 0) {
|
||||
if (tdb->tdb1.io->tdb1_oob(tdb, off + len, 0) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -167,18 +167,18 @@ static int tdb1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf,
|
||||
do an unlocked scan of the hash table heads to find the next non-zero head. The value
|
||||
will then be confirmed with the lock held
|
||||
*/
|
||||
static void tdb1_next_hash_chain(struct tdb1_context *tdb, uint32_t *chain)
|
||||
static void tdb1_next_hash_chain(struct tdb_context *tdb, uint32_t *chain)
|
||||
{
|
||||
uint32_t h = *chain;
|
||||
if (tdb->file->map_ptr) {
|
||||
for (;h < tdb->header.hash_size;h++) {
|
||||
for (;h < tdb->tdb1.header.hash_size;h++) {
|
||||
if (0 != *(uint32_t *)(TDB1_HASH_TOP(h) + (unsigned char *)tdb->file->map_ptr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32_t off=0;
|
||||
for (;h < tdb->header.hash_size;h++) {
|
||||
for (;h < tdb->tdb1.header.hash_size;h++) {
|
||||
if (tdb1_ofs_read(tdb, TDB1_HASH_TOP(h), &off) != 0 || off != 0) {
|
||||
break;
|
||||
}
|
||||
@ -188,7 +188,7 @@ static void tdb1_next_hash_chain(struct tdb1_context *tdb, uint32_t *chain)
|
||||
}
|
||||
|
||||
|
||||
int tdb1_munmap(struct tdb1_context *tdb)
|
||||
int tdb1_munmap(struct tdb_context *tdb)
|
||||
{
|
||||
if (tdb->flags & TDB_INTERNAL)
|
||||
return 0;
|
||||
@ -206,7 +206,7 @@ int tdb1_munmap(struct tdb1_context *tdb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tdb1_mmap(struct tdb1_context *tdb)
|
||||
void tdb1_mmap(struct tdb_context *tdb)
|
||||
{
|
||||
if (tdb->flags & TDB_INTERNAL)
|
||||
return;
|
||||
@ -243,11 +243,11 @@ void tdb1_mmap(struct tdb1_context *tdb)
|
||||
|
||||
/* expand a file. we prefer to use ftruncate, as that is what posix
|
||||
says to use for mmap expansion */
|
||||
static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_t addition)
|
||||
static int tdb1_expand_file(struct tdb_context *tdb, tdb1_off_t size, tdb1_off_t addition)
|
||||
{
|
||||
char buf[8192];
|
||||
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->traverse_read) {
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->tdb1.traverse_read) {
|
||||
tdb->last_error = TDB_ERR_RDONLY;
|
||||
return -1;
|
||||
}
|
||||
@ -313,7 +313,7 @@ static int tdb1_expand_file(struct tdb1_context *tdb, tdb1_off_t size, tdb1_off_
|
||||
|
||||
/* expand the database at least size bytes by expanding the underlying
|
||||
file and doing the mmap again if necessary */
|
||||
int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size)
|
||||
int tdb1_expand(struct tdb_context *tdb, tdb1_off_t size)
|
||||
{
|
||||
struct tdb1_record rec;
|
||||
tdb1_off_t offset, new_size, top_size, map_size;
|
||||
@ -325,7 +325,7 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size)
|
||||
}
|
||||
|
||||
/* must know about any previous expansions by another process */
|
||||
tdb->methods->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
|
||||
tdb->tdb1.io->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
|
||||
|
||||
/* limit size in order to avoid using up huge amounts of memory for
|
||||
* in memory tdbs if an oddball huge record creeps in */
|
||||
@ -346,7 +346,7 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size)
|
||||
|
||||
/* Round the database up to a multiple of the page size */
|
||||
new_size = MAX(top_size, map_size);
|
||||
size = TDB1_ALIGN(new_size, tdb->page_size) - tdb->file->map_size;
|
||||
size = TDB1_ALIGN(new_size, tdb->tdb1.page_size) - tdb->file->map_size;
|
||||
|
||||
if (!(tdb->flags & TDB_INTERNAL))
|
||||
tdb1_munmap(tdb);
|
||||
@ -359,7 +359,7 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size)
|
||||
|
||||
/* expand the file itself */
|
||||
if (!(tdb->flags & TDB_INTERNAL)) {
|
||||
if (tdb->methods->tdb1_expand_file(tdb, tdb->file->map_size, size) != 0)
|
||||
if (tdb->tdb1.io->tdb1_expand_file(tdb, tdb->file->map_size, size) != 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -401,20 +401,20 @@ int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size)
|
||||
}
|
||||
|
||||
/* read/write a tdb1_off_t */
|
||||
int tdb1_ofs_read(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_off_t *d)
|
||||
int tdb1_ofs_read(struct tdb_context *tdb, tdb1_off_t offset, tdb1_off_t *d)
|
||||
{
|
||||
return tdb->methods->tdb1_read(tdb, offset, (char*)d, sizeof(*d), TDB1_DOCONV());
|
||||
return tdb->tdb1.io->tdb1_read(tdb, offset, (char*)d, sizeof(*d), TDB1_DOCONV());
|
||||
}
|
||||
|
||||
int tdb1_ofs_write(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_off_t *d)
|
||||
int tdb1_ofs_write(struct tdb_context *tdb, tdb1_off_t offset, tdb1_off_t *d)
|
||||
{
|
||||
tdb1_off_t off = *d;
|
||||
return tdb->methods->tdb1_write(tdb, offset, TDB1_CONV(off), sizeof(*d));
|
||||
return tdb->tdb1.io->tdb1_write(tdb, offset, TDB1_CONV(off), sizeof(*d));
|
||||
}
|
||||
|
||||
|
||||
/* read a lump of data, allocating the space for it */
|
||||
unsigned char *tdb1_alloc_read(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_len_t len)
|
||||
unsigned char *tdb1_alloc_read(struct tdb_context *tdb, tdb1_off_t offset, tdb1_len_t len)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
@ -427,7 +427,7 @@ unsigned char *tdb1_alloc_read(struct tdb1_context *tdb, tdb1_off_t offset, tdb1
|
||||
len, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if (tdb->methods->tdb1_read(tdb, offset, buf, len, 0) == -1) {
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, offset, buf, len, 0) == -1) {
|
||||
SAFE_FREE(buf);
|
||||
return NULL;
|
||||
}
|
||||
@ -436,7 +436,7 @@ unsigned char *tdb1_alloc_read(struct tdb1_context *tdb, tdb1_off_t offset, tdb1
|
||||
|
||||
/* Give a piece of tdb data to a parser */
|
||||
|
||||
int tdb1_parse_data(struct tdb1_context *tdb, TDB_DATA key,
|
||||
int tdb1_parse_data(struct tdb_context *tdb, TDB_DATA key,
|
||||
tdb1_off_t offset, tdb1_len_t len,
|
||||
int (*parser)(TDB_DATA key, TDB_DATA data,
|
||||
void *private_data),
|
||||
@ -447,12 +447,12 @@ int tdb1_parse_data(struct tdb1_context *tdb, TDB_DATA key,
|
||||
|
||||
data.dsize = len;
|
||||
|
||||
if ((tdb->transaction == NULL) && (tdb->file->map_ptr != NULL)) {
|
||||
if ((tdb->tdb1.transaction == NULL) && (tdb->file->map_ptr != NULL)) {
|
||||
/*
|
||||
* Optimize by avoiding the malloc/memcpy/free, point the
|
||||
* parser directly at the mmap area.
|
||||
*/
|
||||
if (tdb->methods->tdb1_oob(tdb, offset+len, 0) != 0) {
|
||||
if (tdb->tdb1.io->tdb1_oob(tdb, offset+len, 0) != 0) {
|
||||
return -1;
|
||||
}
|
||||
data.dptr = offset + (unsigned char *)tdb->file->map_ptr;
|
||||
@ -469,9 +469,9 @@ int tdb1_parse_data(struct tdb1_context *tdb, TDB_DATA key,
|
||||
}
|
||||
|
||||
/* read/write a record */
|
||||
int tdb1_rec_read(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *rec)
|
||||
int tdb1_rec_read(struct tdb_context *tdb, tdb1_off_t offset, struct tdb1_record *rec)
|
||||
{
|
||||
if (tdb->methods->tdb1_read(tdb, offset, rec, sizeof(*rec),TDB1_DOCONV()) == -1)
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, offset, rec, sizeof(*rec),TDB1_DOCONV()) == -1)
|
||||
return -1;
|
||||
if (TDB1_BAD_MAGIC(rec)) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
|
||||
@ -479,13 +479,13 @@ int tdb1_rec_read(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_recor
|
||||
rec->magic, offset);
|
||||
return -1;
|
||||
}
|
||||
return tdb->methods->tdb1_oob(tdb, rec->next+sizeof(*rec), 0);
|
||||
return tdb->tdb1.io->tdb1_oob(tdb, rec->next+sizeof(*rec), 0);
|
||||
}
|
||||
|
||||
int tdb1_rec_write(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *rec)
|
||||
int tdb1_rec_write(struct tdb_context *tdb, tdb1_off_t offset, struct tdb1_record *rec)
|
||||
{
|
||||
struct tdb1_record r = *rec;
|
||||
return tdb->methods->tdb1_write(tdb, offset, TDB1_CONV(r), sizeof(r));
|
||||
return tdb->tdb1.io->tdb1_write(tdb, offset, TDB1_CONV(r), sizeof(r));
|
||||
}
|
||||
|
||||
static const struct tdb1_methods io1_methods = {
|
||||
@ -499,7 +499,7 @@ static const struct tdb1_methods io1_methods = {
|
||||
/*
|
||||
initialise the default methods table
|
||||
*/
|
||||
void tdb1_io_init(struct tdb1_context *tdb)
|
||||
void tdb1_io_init(struct tdb_context *tdb)
|
||||
{
|
||||
tdb->methods = &io1_methods;
|
||||
tdb->tdb1.io = &io1_methods;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ static tdb1_off_t lock_offset(int list)
|
||||
|
||||
note that a len of zero means lock to end of file
|
||||
*/
|
||||
int tdb1_brlock(struct tdb1_context *tdb,
|
||||
int tdb1_brlock(struct tdb_context *tdb,
|
||||
int rw_type, tdb1_off_t offset, size_t len,
|
||||
enum tdb_lock_flags flags)
|
||||
{
|
||||
@ -53,7 +53,7 @@ int tdb1_brlock(struct tdb1_context *tdb,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tdb1_brunlock(struct tdb1_context *tdb,
|
||||
int tdb1_brunlock(struct tdb_context *tdb,
|
||||
int rw_type, tdb1_off_t offset, size_t len)
|
||||
{
|
||||
enum TDB_ERROR ecode = tdb_brunlock(tdb, rw_type, offset, len);
|
||||
@ -63,7 +63,7 @@ int tdb1_brunlock(struct tdb1_context *tdb,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tdb1_allrecord_upgrade(struct tdb1_context *tdb)
|
||||
int tdb1_allrecord_upgrade(struct tdb_context *tdb)
|
||||
{
|
||||
enum TDB_ERROR ecode = tdb_allrecord_upgrade(tdb, TDB1_FREELIST_TOP);
|
||||
if (ecode == TDB_SUCCESS)
|
||||
@ -72,7 +72,7 @@ int tdb1_allrecord_upgrade(struct tdb1_context *tdb)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct tdb_lock *tdb1_find_nestlock(struct tdb1_context *tdb,
|
||||
static struct tdb_lock *tdb1_find_nestlock(struct tdb_context *tdb,
|
||||
tdb1_off_t offset)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -86,12 +86,12 @@ static struct tdb_lock *tdb1_find_nestlock(struct tdb1_context *tdb,
|
||||
}
|
||||
|
||||
/* lock an offset in the database. */
|
||||
int tdb1_nest_lock(struct tdb1_context *tdb, uint32_t offset, int ltype,
|
||||
int tdb1_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
|
||||
enum tdb_lock_flags flags)
|
||||
{
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
if (offset >= lock_offset(tdb->header.hash_size)) {
|
||||
if (offset >= lock_offset(tdb->tdb1.header.hash_size)) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
|
||||
"tdb1_lock: invalid offset %u for"
|
||||
" ltype=%d",
|
||||
@ -107,7 +107,7 @@ int tdb1_nest_lock(struct tdb1_context *tdb, uint32_t offset, int ltype,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tdb1_lock_and_recover(struct tdb1_context *tdb)
|
||||
static int tdb1_lock_and_recover(struct tdb_context *tdb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -131,7 +131,7 @@ static int tdb1_lock_and_recover(struct tdb1_context *tdb)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool have_data_locks(const struct tdb1_context *tdb)
|
||||
static bool have_data_locks(const struct tdb_context *tdb)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@ -142,7 +142,7 @@ static bool have_data_locks(const struct tdb1_context *tdb)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int tdb1_lock_list(struct tdb1_context *tdb, int list, int ltype,
|
||||
static int tdb1_lock_list(struct tdb_context *tdb, int list, int ltype,
|
||||
enum tdb_lock_flags waitflag)
|
||||
{
|
||||
int ret;
|
||||
@ -175,7 +175,7 @@ static int tdb1_lock_list(struct tdb1_context *tdb, int list, int ltype,
|
||||
}
|
||||
|
||||
/* lock a list in the database. list -1 is the alloc list */
|
||||
int tdb1_lock(struct tdb1_context *tdb, int list, int ltype)
|
||||
int tdb1_lock(struct tdb_context *tdb, int list, int ltype)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -189,15 +189,15 @@ int tdb1_lock(struct tdb1_context *tdb, int list, int ltype)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tdb1_nest_unlock(struct tdb1_context *tdb, uint32_t offset, int ltype)
|
||||
int tdb1_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype)
|
||||
{
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
/* Sanity checks */
|
||||
if (offset >= lock_offset(tdb->header.hash_size)) {
|
||||
if (offset >= lock_offset(tdb->tdb1.header.hash_size)) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK, TDB_LOG_ERROR,
|
||||
"tdb1_unlock: offset %u invalid (%d)",
|
||||
offset, tdb->header.hash_size);
|
||||
offset, tdb->tdb1.header.hash_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -209,7 +209,7 @@ int tdb1_nest_unlock(struct tdb1_context *tdb, uint32_t offset, int ltype)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tdb1_unlock(struct tdb1_context *tdb, int list, int ltype)
|
||||
int tdb1_unlock(struct tdb_context *tdb, int list, int ltype)
|
||||
{
|
||||
/* a global lock allows us to avoid per chain locks */
|
||||
if (tdb->file->allrecord_lock.count &&
|
||||
@ -228,7 +228,7 @@ int tdb1_unlock(struct tdb1_context *tdb, int list, int ltype)
|
||||
/*
|
||||
get the transaction lock
|
||||
*/
|
||||
int tdb1_transaction_lock(struct tdb1_context *tdb, int ltype,
|
||||
int tdb1_transaction_lock(struct tdb_context *tdb, int ltype,
|
||||
enum tdb_lock_flags lockflags)
|
||||
{
|
||||
return tdb1_nest_lock(tdb, TDB1_TRANSACTION_LOCK, ltype, lockflags);
|
||||
@ -237,7 +237,7 @@ int tdb1_transaction_lock(struct tdb1_context *tdb, int ltype,
|
||||
/*
|
||||
release the transaction lock
|
||||
*/
|
||||
int tdb1_transaction_unlock(struct tdb1_context *tdb, int ltype)
|
||||
int tdb1_transaction_unlock(struct tdb_context *tdb, int ltype)
|
||||
{
|
||||
return tdb1_nest_unlock(tdb, TDB1_TRANSACTION_LOCK, ltype);
|
||||
}
|
||||
@ -245,13 +245,13 @@ int tdb1_transaction_unlock(struct tdb1_context *tdb, int ltype)
|
||||
/* lock/unlock entire database. It can only be upgradable if you have some
|
||||
* other way of guaranteeing exclusivity (ie. transaction write lock).
|
||||
* We do the locking gradually to avoid being starved by smaller locks. */
|
||||
int tdb1_allrecord_lock(struct tdb1_context *tdb, int ltype,
|
||||
int tdb1_allrecord_lock(struct tdb_context *tdb, int ltype,
|
||||
enum tdb_lock_flags flags, bool upgradable)
|
||||
{
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
/* tdb_lock_gradual() doesn't know about tdb->traverse_read. */
|
||||
if (tdb->traverse_read && !(tdb->flags & TDB_NOLOCK)) {
|
||||
/* tdb_lock_gradual() doesn't know about tdb->tdb1.traverse_read. */
|
||||
if (tdb->tdb1.traverse_read && !(tdb->flags & TDB_NOLOCK)) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_LOCK,
|
||||
TDB_LOG_USE_ERROR,
|
||||
"tdb1_allrecord_lock during"
|
||||
@ -291,17 +291,17 @@ int tdb1_allrecord_lock(struct tdb1_context *tdb, int ltype,
|
||||
* It is (1) which cause the starvation problem, so we're only
|
||||
* gradual for that. */
|
||||
ecode = tdb_lock_gradual(tdb, ltype, flags | TDB_LOCK_NOCHECK,
|
||||
TDB1_FREELIST_TOP, tdb->header.hash_size * 4);
|
||||
TDB1_FREELIST_TOP, tdb->tdb1.header.hash_size * 4);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
tdb->last_error = ecode;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Grab individual record locks. */
|
||||
if (tdb1_brlock(tdb, ltype, lock_offset(tdb->header.hash_size), 0,
|
||||
if (tdb1_brlock(tdb, ltype, lock_offset(tdb->tdb1.header.hash_size), 0,
|
||||
flags) == -1) {
|
||||
tdb1_brunlock(tdb, ltype, TDB1_FREELIST_TOP,
|
||||
tdb->header.hash_size * 4);
|
||||
tdb->tdb1.header.hash_size * 4);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -327,10 +327,10 @@ int tdb1_allrecord_lock(struct tdb1_context *tdb, int ltype,
|
||||
|
||||
|
||||
/* unlock entire db */
|
||||
int tdb1_allrecord_unlock(struct tdb1_context *tdb, int ltype)
|
||||
int tdb1_allrecord_unlock(struct tdb_context *tdb, int ltype)
|
||||
{
|
||||
/* Don't try this during r/o traversal! */
|
||||
if (tdb->traverse_read) {
|
||||
if (tdb->tdb1.traverse_read) {
|
||||
tdb->last_error = TDB_ERR_LOCK;
|
||||
return -1;
|
||||
}
|
||||
@ -365,32 +365,32 @@ int tdb1_allrecord_unlock(struct tdb1_context *tdb, int ltype)
|
||||
}
|
||||
|
||||
/* lock entire database with write lock */
|
||||
int tdb1_lockall(struct tdb1_context *tdb)
|
||||
int tdb1_lockall(struct tdb_context *tdb)
|
||||
{
|
||||
return tdb1_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false);
|
||||
}
|
||||
|
||||
/* unlock entire database with write lock */
|
||||
int tdb1_unlockall(struct tdb1_context *tdb)
|
||||
int tdb1_unlockall(struct tdb_context *tdb)
|
||||
{
|
||||
return tdb1_allrecord_unlock(tdb, F_WRLCK);
|
||||
}
|
||||
|
||||
/* lock entire database with read lock */
|
||||
int tdb1_lockall_read(struct tdb1_context *tdb)
|
||||
int tdb1_lockall_read(struct tdb_context *tdb)
|
||||
{
|
||||
return tdb1_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false);
|
||||
}
|
||||
|
||||
/* unlock entire database with read lock */
|
||||
int tdb1_unlockall_read(struct tdb1_context *tdb)
|
||||
int tdb1_unlockall_read(struct tdb_context *tdb)
|
||||
{
|
||||
return tdb1_allrecord_unlock(tdb, F_RDLCK);
|
||||
}
|
||||
|
||||
/* lock/unlock one hash chain. This is meant to be used to reduce
|
||||
contention - it cannot guarantee how many records will be locked */
|
||||
int tdb1_chainlock(struct tdb1_context *tdb, TDB_DATA key)
|
||||
int tdb1_chainlock(struct tdb_context *tdb, TDB_DATA key)
|
||||
{
|
||||
int ret = tdb1_lock(tdb,
|
||||
TDB1_BUCKET(tdb_hash(tdb, key.dptr, key.dsize)),
|
||||
@ -398,13 +398,13 @@ int tdb1_chainlock(struct tdb1_context *tdb, TDB_DATA key)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tdb1_chainunlock(struct tdb1_context *tdb, TDB_DATA key)
|
||||
int tdb1_chainunlock(struct tdb_context *tdb, TDB_DATA key)
|
||||
{
|
||||
return tdb1_unlock(tdb, TDB1_BUCKET(tdb_hash(tdb, key.dptr, key.dsize)),
|
||||
F_WRLCK);
|
||||
}
|
||||
|
||||
int tdb1_chainlock_read(struct tdb1_context *tdb, TDB_DATA key)
|
||||
int tdb1_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
|
||||
{
|
||||
int ret;
|
||||
ret = tdb1_lock(tdb, TDB1_BUCKET(tdb_hash(tdb, key.dptr, key.dsize)),
|
||||
@ -412,14 +412,14 @@ int tdb1_chainlock_read(struct tdb1_context *tdb, TDB_DATA key)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tdb1_chainunlock_read(struct tdb1_context *tdb, TDB_DATA key)
|
||||
int tdb1_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
|
||||
{
|
||||
return tdb1_unlock(tdb, TDB1_BUCKET(tdb_hash(tdb, key.dptr, key.dsize)),
|
||||
F_RDLCK);
|
||||
}
|
||||
|
||||
/* record lock stops delete underneath */
|
||||
int tdb1_lock_record(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
int tdb1_lock_record(struct tdb_context *tdb, tdb1_off_t off)
|
||||
{
|
||||
if (tdb->file->allrecord_lock.count) {
|
||||
return 0;
|
||||
@ -432,10 +432,10 @@ int tdb1_lock_record(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
|
||||
an error to fail to get the lock here.
|
||||
*/
|
||||
int tdb1_write_lock_record(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
int tdb1_write_lock_record(struct tdb_context *tdb, tdb1_off_t off)
|
||||
{
|
||||
struct tdb1_traverse_lock *i;
|
||||
for (i = &tdb->travlocks; i; i = i->next)
|
||||
for (i = &tdb->tdb1.travlocks; i; i = i->next)
|
||||
if (i->off == off)
|
||||
return -1;
|
||||
if (tdb->file->allrecord_lock.count) {
|
||||
@ -447,7 +447,7 @@ int tdb1_write_lock_record(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
return tdb1_brlock(tdb, F_WRLCK, off, 1, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
|
||||
}
|
||||
|
||||
int tdb1_write_unlock_record(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
int tdb1_write_unlock_record(struct tdb_context *tdb, tdb1_off_t off)
|
||||
{
|
||||
if (tdb->file->allrecord_lock.count) {
|
||||
return 0;
|
||||
@ -456,7 +456,7 @@ int tdb1_write_unlock_record(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
}
|
||||
|
||||
/* fcntl locks don't stack: avoid unlocking someone else's */
|
||||
int tdb1_unlock_record(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
int tdb1_unlock_record(struct tdb_context *tdb, tdb1_off_t off)
|
||||
{
|
||||
struct tdb1_traverse_lock *i;
|
||||
uint32_t count = 0;
|
||||
@ -467,18 +467,18 @@ int tdb1_unlock_record(struct tdb1_context *tdb, tdb1_off_t off)
|
||||
|
||||
if (off == 0)
|
||||
return 0;
|
||||
for (i = &tdb->travlocks; i; i = i->next)
|
||||
for (i = &tdb->tdb1.travlocks; i; i = i->next)
|
||||
if (i->off == off)
|
||||
count++;
|
||||
return (count == 1 ? tdb1_brunlock(tdb, F_RDLCK, off, 1) : 0);
|
||||
}
|
||||
|
||||
bool tdb1_have_extra_locks(struct tdb1_context *tdb)
|
||||
bool tdb1_have_extra_locks(struct tdb_context *tdb)
|
||||
{
|
||||
unsigned int extra = tdb->file->num_lockrecs;
|
||||
|
||||
/* A transaction holds the lock for all records. */
|
||||
if (!tdb->transaction && tdb->file->allrecord_lock.count) {
|
||||
if (!tdb->tdb1.transaction && tdb->file->allrecord_lock.count) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -488,7 +488,7 @@ bool tdb1_have_extra_locks(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* In a transaction, we expect to hold the transaction lock */
|
||||
if (tdb->transaction
|
||||
if (tdb->tdb1.transaction
|
||||
&& tdb1_find_nestlock(tdb, TDB1_TRANSACTION_LOCK)) {
|
||||
extra--;
|
||||
}
|
||||
@ -497,7 +497,7 @@ bool tdb1_have_extra_locks(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* The transaction code uses this to remove all locks. */
|
||||
void tdb1_release_transaction_locks(struct tdb1_context *tdb)
|
||||
void tdb1_release_transaction_locks(struct tdb_context *tdb)
|
||||
{
|
||||
unsigned int i, active = 0;
|
||||
|
||||
|
@ -28,10 +28,10 @@
|
||||
#include "tdb1_private.h"
|
||||
|
||||
/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */
|
||||
static struct tdb1_context *tdb1s = NULL;
|
||||
static struct tdb_context *tdb1s = NULL;
|
||||
|
||||
/* We use two hashes to double-check they're using the right hash function. */
|
||||
void tdb1_header_hash(struct tdb1_context *tdb,
|
||||
void tdb1_header_hash(struct tdb_context *tdb,
|
||||
uint32_t *magic1_hash, uint32_t *magic2_hash)
|
||||
{
|
||||
uint32_t tdb1_magic = TDB1_MAGIC;
|
||||
@ -45,7 +45,7 @@ void tdb1_header_hash(struct tdb1_context *tdb,
|
||||
}
|
||||
|
||||
/* initialise a new database with a specified hash size */
|
||||
static int tdb1_new_database(struct tdb1_context *tdb, int hash_size)
|
||||
static int tdb1_new_database(struct tdb_context *tdb, int hash_size)
|
||||
{
|
||||
struct tdb1_header *newdb;
|
||||
size_t size;
|
||||
@ -73,7 +73,7 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size)
|
||||
tdb->file->fd = -1;
|
||||
tdb->file->map_size = size;
|
||||
tdb->file->map_ptr = (char *)newdb;
|
||||
memcpy(&tdb->header, newdb, sizeof(tdb->header));
|
||||
memcpy(&tdb->tdb1.header, newdb, sizeof(tdb->tdb1.header));
|
||||
/* Convert the `ondisk' version if asked. */
|
||||
TDB1_CONV(*newdb);
|
||||
return 0;
|
||||
@ -86,7 +86,7 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size)
|
||||
|
||||
/* This creates an endian-converted header, as if read from disk */
|
||||
TDB1_CONV(*newdb);
|
||||
memcpy(&tdb->header, newdb, sizeof(tdb->header));
|
||||
memcpy(&tdb->tdb1.header, newdb, sizeof(tdb->tdb1.header));
|
||||
/* Don't endian-convert the magic food! */
|
||||
memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
|
||||
/* we still have "ret == -1" here */
|
||||
@ -103,7 +103,7 @@ static int tdb1_new_database(struct tdb1_context *tdb, int hash_size)
|
||||
static int tdb1_already_open(dev_t device,
|
||||
ino_t ino)
|
||||
{
|
||||
struct tdb1_context *i;
|
||||
struct tdb_context *i;
|
||||
|
||||
for (i = tdb1s; i; i = i->next) {
|
||||
if (i->file->device == device && i->file->inode == ino) {
|
||||
@ -124,21 +124,21 @@ static int tdb1_already_open(dev_t device,
|
||||
try to call tdb1_error or tdb1_errname, just do strerror(errno).
|
||||
|
||||
@param name may be NULL for internal databases. */
|
||||
struct tdb1_context *tdb1_open(const char *name, int hash_size, int tdb1_flags,
|
||||
struct tdb_context *tdb1_open(const char *name, int hash_size, int tdb1_flags,
|
||||
int open_flags, mode_t mode)
|
||||
{
|
||||
return tdb1_open_ex(name, hash_size, tdb1_flags, open_flags, mode, NULL, NULL);
|
||||
}
|
||||
|
||||
static bool hash_correct(struct tdb1_context *tdb,
|
||||
static bool hash_correct(struct tdb_context *tdb,
|
||||
uint32_t *m1, uint32_t *m2)
|
||||
{
|
||||
tdb1_header_hash(tdb, m1, m2);
|
||||
return (tdb->header.magic1_hash == *m1 &&
|
||||
tdb->header.magic2_hash == *m2);
|
||||
return (tdb->tdb1.header.magic1_hash == *m1 &&
|
||||
tdb->tdb1.header.magic2_hash == *m2);
|
||||
}
|
||||
|
||||
static bool check_header_hash(struct tdb1_context *tdb,
|
||||
static bool check_header_hash(struct tdb_context *tdb,
|
||||
uint32_t *m1, uint32_t *m2)
|
||||
{
|
||||
if (hash_correct(tdb, m1, m2))
|
||||
@ -154,19 +154,19 @@ static bool check_header_hash(struct tdb1_context *tdb,
|
||||
return hash_correct(tdb, m1, m2);
|
||||
}
|
||||
|
||||
struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flags,
|
||||
struct tdb_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flags,
|
||||
int open_flags, mode_t mode,
|
||||
const struct tdb1_logging_context *log_ctx,
|
||||
tdb1_hash_func hash_fn)
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
struct stat st;
|
||||
int rev = 0;
|
||||
unsigned v;
|
||||
const char *hash_alg;
|
||||
uint32_t magic1, magic2;
|
||||
|
||||
if (!(tdb = (struct tdb1_context *)calloc(1, sizeof *tdb))) {
|
||||
if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
|
||||
/* Can't log this */
|
||||
errno = ENOMEM;
|
||||
goto fail;
|
||||
@ -231,13 +231,13 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
|
||||
}
|
||||
|
||||
/* cache the page size */
|
||||
tdb->page_size = getpagesize();
|
||||
if (tdb->page_size <= 0) {
|
||||
tdb->page_size = 0x2000;
|
||||
tdb->tdb1.page_size = getpagesize();
|
||||
if (tdb->tdb1.page_size <= 0) {
|
||||
tdb->tdb1.page_size = 0x2000;
|
||||
}
|
||||
|
||||
/* FIXME: Used to be 5 for TDB_VOLATILE. */
|
||||
tdb->max_dead_records = 0;
|
||||
tdb->tdb1.max_dead_records = 0;
|
||||
|
||||
if ((open_flags & O_ACCMODE) == O_WRONLY) {
|
||||
tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
@ -286,8 +286,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (read(tdb->file->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header)
|
||||
|| strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0) {
|
||||
if (read(tdb->file->fd, &tdb->tdb1.header, sizeof(tdb->tdb1.header)) != sizeof(tdb->tdb1.header)
|
||||
|| strcmp(tdb->tdb1.header.magic_food, TDB_MAGIC_FOOD) != 0) {
|
||||
if (!(open_flags & O_CREAT) || tdb1_new_database(tdb, hash_size) == -1) {
|
||||
if (errno == 0) {
|
||||
errno = EIO; /* ie bad format or something */
|
||||
@ -295,8 +295,8 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
|
||||
goto fail;
|
||||
}
|
||||
rev = (tdb->flags & TDB_CONVERT);
|
||||
} else if (tdb->header.version != TDB1_VERSION
|
||||
&& !(rev = (tdb->header.version==TDB1_BYTEREV(TDB1_VERSION)))) {
|
||||
} else if (tdb->tdb1.header.version != TDB1_VERSION
|
||||
&& !(rev = (tdb->tdb1.header.version==TDB1_BYTEREV(TDB1_VERSION)))) {
|
||||
/* wrong version */
|
||||
errno = EIO;
|
||||
goto fail;
|
||||
@ -305,19 +305,19 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
|
||||
tdb->flags &= ~TDB_CONVERT;
|
||||
else {
|
||||
tdb->flags |= TDB_CONVERT;
|
||||
tdb1_convert(&tdb->header, sizeof(tdb->header));
|
||||
tdb1_convert(&tdb->tdb1.header, sizeof(tdb->tdb1.header));
|
||||
}
|
||||
if (fstat(tdb->file->fd, &st) == -1)
|
||||
goto fail;
|
||||
|
||||
if (tdb->header.rwlocks != 0 &&
|
||||
tdb->header.rwlocks != TDB1_HASH_RWLOCK_MAGIC) {
|
||||
if (tdb->tdb1.header.rwlocks != 0 &&
|
||||
tdb->tdb1.header.rwlocks != TDB1_HASH_RWLOCK_MAGIC) {
|
||||
tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
|
||||
"tdb1_open_ex: spinlocks no longer supported");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((tdb->header.magic1_hash == 0) && (tdb->header.magic2_hash == 0)) {
|
||||
if ((tdb->tdb1.header.magic1_hash == 0) && (tdb->tdb1.header.magic2_hash == 0)) {
|
||||
/* older TDB without magic hash references */
|
||||
tdb->hash_fn = tdb1_old_hash;
|
||||
} else if (!check_header_hash(tdb, &magic1, &magic2)) {
|
||||
@ -327,11 +327,11 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
|
||||
"magic1_hash[0x%08X %s 0x%08X] "
|
||||
"magic2_hash[0x%08X %s 0x%08X]",
|
||||
name, hash_alg,
|
||||
tdb->header.magic1_hash,
|
||||
(tdb->header.magic1_hash == magic1) ? "==" : "!=",
|
||||
tdb->tdb1.header.magic1_hash,
|
||||
(tdb->tdb1.header.magic1_hash == magic1) ? "==" : "!=",
|
||||
magic1,
|
||||
tdb->header.magic2_hash,
|
||||
(tdb->header.magic2_hash == magic2) ? "==" : "!=",
|
||||
tdb->tdb1.header.magic2_hash,
|
||||
(tdb->tdb1.header.magic2_hash == magic2) ? "==" : "!=",
|
||||
magic2);
|
||||
errno = EINVAL;
|
||||
goto fail;
|
||||
@ -399,9 +399,9 @@ struct tdb1_context *tdb1_open_ex(const char *name, int hash_size, int tdb1_flag
|
||||
* Set the maximum number of dead records per hash chain
|
||||
*/
|
||||
|
||||
void tdb1_set_max_dead(struct tdb1_context *tdb, int max_dead)
|
||||
void tdb1_set_max_dead(struct tdb_context *tdb, int max_dead)
|
||||
{
|
||||
tdb->max_dead_records = max_dead;
|
||||
tdb->tdb1.max_dead_records = max_dead;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -409,12 +409,12 @@ void tdb1_set_max_dead(struct tdb1_context *tdb, int max_dead)
|
||||
*
|
||||
* @returns -1 for error; 0 for success.
|
||||
**/
|
||||
int tdb1_close(struct tdb1_context *tdb)
|
||||
int tdb1_close(struct tdb_context *tdb)
|
||||
{
|
||||
struct tdb1_context **i;
|
||||
struct tdb_context **i;
|
||||
int ret = 0;
|
||||
|
||||
if (tdb->transaction) {
|
||||
if (tdb->tdb1.transaction) {
|
||||
tdb1_transaction_cancel(tdb);
|
||||
}
|
||||
|
||||
|
@ -28,44 +28,6 @@
|
||||
#include "private.h"
|
||||
#include "tdb1.h"
|
||||
|
||||
/**** FIXME: Type overrides for tdb2, for transition! */
|
||||
#define tdb_logerr(tdb, ecode, level, ...) \
|
||||
tdb_logerr((struct tdb_context *)(tdb), (ecode), (level), __VA_ARGS__)
|
||||
|
||||
#define tdb_error(tdb) \
|
||||
tdb_error((struct tdb_context *)(tdb))
|
||||
|
||||
#define tdb_brlock(tdb1, rw_type, offset, len, flags) \
|
||||
tdb_brlock((struct tdb_context *)(tdb1), \
|
||||
(rw_type), (offset), (len), (flags))
|
||||
|
||||
#define tdb_brunlock(tdb1, rw_type, offset, len) \
|
||||
tdb_brunlock((struct tdb_context *)(tdb1), (rw_type), (offset), (len))
|
||||
|
||||
#define tdb_nest_lock(tdb1, offset, ltype, flags) \
|
||||
tdb_nest_lock((struct tdb_context *)(tdb1), (offset), (ltype), (flags))
|
||||
|
||||
#define tdb_nest_unlock(tdb1, offset, ltype) \
|
||||
tdb_nest_unlock((struct tdb_context *)(tdb1), (offset), (ltype))
|
||||
|
||||
#define tdb_allrecord_lock(tdb1, offset, flags, upgradable) \
|
||||
tdb_allrecord_lock((struct tdb_context *)(tdb1), \
|
||||
(offset), (flags), (upgradable))
|
||||
|
||||
#define tdb_allrecord_unlock(tdb1, ltype) \
|
||||
tdb_allrecord_unlock((struct tdb_context *)(tdb1), (ltype))
|
||||
|
||||
#define tdb_allrecord_upgrade(tdb1, start) \
|
||||
tdb_allrecord_upgrade((struct tdb_context *)(tdb1), (start))
|
||||
|
||||
#define tdb_hash(tdb1, ptr, len) \
|
||||
tdb_hash((struct tdb_context *)(tdb1), (ptr), (len))
|
||||
|
||||
#define tdb_lock_gradual(tdb1, ltype, flags, off, len) \
|
||||
tdb_lock_gradual((struct tdb_context *)(tdb1), \
|
||||
(ltype), (flags), (off), (len))
|
||||
/***** END FIXME ***/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* #define TDB_TRACE 1 */
|
||||
@ -85,9 +47,6 @@
|
||||
#define __location__ __FILE__ ":" __STRINGSTRING(__LINE__)
|
||||
#endif
|
||||
|
||||
typedef uint32_t tdb1_len_t;
|
||||
typedef uint32_t tdb1_off_t;
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(t,f) ((unsigned int)&((t *)0)->f)
|
||||
#endif
|
||||
@ -107,7 +66,7 @@ typedef uint32_t tdb1_off_t;
|
||||
#define TDB1_DEAD(r) ((r)->magic == TDB1_DEAD_MAGIC)
|
||||
#define TDB1_BAD_MAGIC(r) ((r)->magic != TDB1_MAGIC && !TDB1_DEAD(r))
|
||||
#define TDB1_HASH_TOP(hash) (TDB1_FREELIST_TOP + (TDB1_BUCKET(hash)+1)*sizeof(tdb1_off_t))
|
||||
#define TDB1_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb1_off_t))
|
||||
#define TDB1_HASHTABLE_SIZE(tdb) ((tdb->tdb1.header.hash_size+1)*sizeof(tdb1_off_t))
|
||||
#define TDB1_DATA_START(hash_size) (TDB1_HASH_TOP(hash_size-1) + sizeof(tdb1_off_t))
|
||||
#define TDB1_RECOVERY_HEAD offsetof(struct tdb1_header, recovery_start)
|
||||
#define TDB1_SEQNUM_OFS offsetof(struct tdb1_header, sequence_number)
|
||||
@ -121,10 +80,10 @@ typedef uint32_t tdb1_off_t;
|
||||
|
||||
/* free memory if the pointer is valid and zero the pointer */
|
||||
#ifndef SAFE_FREE
|
||||
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
|
||||
#define SAFE_FREE(x) do { if ((x) != NULL) {free((void *)x); (x)=NULL;} } while(0)
|
||||
#endif
|
||||
|
||||
#define TDB1_BUCKET(hash) ((hash) % tdb->header.hash_size)
|
||||
#define TDB1_BUCKET(hash) ((hash) % tdb->tdb1.header.hash_size)
|
||||
|
||||
#define TDB1_DOCONV() (tdb->flags & TDB_CONVERT)
|
||||
#define TDB1_CONV(x) (TDB1_DOCONV() ? tdb1_convert(&x, sizeof(x)) : &x)
|
||||
@ -151,141 +110,74 @@ struct tdb1_record {
|
||||
};
|
||||
|
||||
|
||||
/* this is stored at the front of every database */
|
||||
struct tdb1_header {
|
||||
char magic_food[32]; /* for /etc/magic */
|
||||
uint32_t version; /* version of the code */
|
||||
uint32_t hash_size; /* number of hash entries */
|
||||
tdb1_off_t rwlocks; /* obsolete - kept to detect old formats */
|
||||
tdb1_off_t recovery_start; /* offset of transaction recovery region */
|
||||
tdb1_off_t sequence_number; /* used when TDB1_SEQNUM is set */
|
||||
uint32_t magic1_hash; /* hash of TDB_MAGIC_FOOD. */
|
||||
uint32_t magic2_hash; /* hash of TDB1_MAGIC. */
|
||||
tdb1_off_t reserved[27];
|
||||
};
|
||||
|
||||
struct tdb1_traverse_lock {
|
||||
struct tdb1_traverse_lock *next;
|
||||
uint32_t off;
|
||||
uint32_t hash;
|
||||
int lock_rw;
|
||||
};
|
||||
|
||||
struct tdb1_context;
|
||||
|
||||
struct tdb1_methods {
|
||||
int (*tdb1_read)(struct tdb1_context *, tdb1_off_t , void *, tdb1_len_t , int );
|
||||
int (*tdb1_write)(struct tdb1_context *, tdb1_off_t, const void *, tdb1_len_t);
|
||||
void (*next_hash_chain)(struct tdb1_context *, uint32_t *);
|
||||
int (*tdb1_oob)(struct tdb1_context *, tdb1_off_t , int );
|
||||
int (*tdb1_expand_file)(struct tdb1_context *, tdb1_off_t , tdb1_off_t );
|
||||
int (*tdb1_read)(struct tdb_context *, tdb1_off_t , void *, tdb1_len_t , int );
|
||||
int (*tdb1_write)(struct tdb_context *, tdb1_off_t, const void *, tdb1_len_t);
|
||||
void (*next_hash_chain)(struct tdb_context *, uint32_t *);
|
||||
int (*tdb1_oob)(struct tdb_context *, tdb1_off_t , int );
|
||||
int (*tdb1_expand_file)(struct tdb_context *, tdb1_off_t , tdb1_off_t );
|
||||
};
|
||||
|
||||
struct tdb1_context {
|
||||
struct tdb1_context *next;
|
||||
|
||||
char *name; /* the name of the database */
|
||||
|
||||
/* Logging function */
|
||||
void (*log_fn)(struct tdb1_context *tdb,
|
||||
enum tdb_log_level level,
|
||||
enum TDB_ERROR ecode,
|
||||
const char *message,
|
||||
void *data);
|
||||
void *log_data;
|
||||
|
||||
/* Last error we returned. */
|
||||
enum TDB_ERROR last_error; /* error code for last tdb error */
|
||||
|
||||
/* The actual file information */
|
||||
struct tdb_file *file;
|
||||
|
||||
int open_flags; /* flags used in the open - needed by reopen */
|
||||
|
||||
/* low level (fnctl) lock functions. */
|
||||
int (*lock_fn)(int fd, int rw, off_t off, off_t len, bool w, void *);
|
||||
int (*unlock_fn)(int fd, int rw, off_t off, off_t len, void *);
|
||||
void *lock_data;
|
||||
|
||||
uint32_t flags; /* the flags passed to tdb1_open */
|
||||
|
||||
/* Our statistics. */
|
||||
struct tdb_attribute_stats stats;
|
||||
|
||||
/* Hash function. */
|
||||
uint64_t (*hash_fn)(const void *key, size_t len, uint64_t seed, void *);
|
||||
void *hash_data;
|
||||
uint64_t hash_seed;
|
||||
|
||||
int traverse_read; /* read-only traversal */
|
||||
int traverse_write; /* read-write traversal */
|
||||
struct tdb1_header header; /* a cached copy of the header */
|
||||
struct tdb1_traverse_lock travlocks; /* current traversal locks */
|
||||
const struct tdb1_methods *methods;
|
||||
struct tdb1_transaction *transaction;
|
||||
int page_size;
|
||||
int max_dead_records;
|
||||
};
|
||||
|
||||
/*
|
||||
internal prototypes
|
||||
*/
|
||||
int tdb1_munmap(struct tdb1_context *tdb);
|
||||
void tdb1_mmap(struct tdb1_context *tdb);
|
||||
int tdb1_lock(struct tdb1_context *tdb, int list, int ltype);
|
||||
int tdb1_nest_lock(struct tdb1_context *tdb, uint32_t offset, int ltype,
|
||||
int tdb1_munmap(struct tdb_context *tdb);
|
||||
void tdb1_mmap(struct tdb_context *tdb);
|
||||
int tdb1_lock(struct tdb_context *tdb, int list, int ltype);
|
||||
int tdb1_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
|
||||
enum tdb_lock_flags flags);
|
||||
int tdb1_nest_unlock(struct tdb1_context *tdb, uint32_t offset, int ltype);
|
||||
int tdb1_unlock(struct tdb1_context *tdb, int list, int ltype);
|
||||
int tdb1_brlock(struct tdb1_context *tdb,
|
||||
int tdb1_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype);
|
||||
int tdb1_unlock(struct tdb_context *tdb, int list, int ltype);
|
||||
int tdb1_brlock(struct tdb_context *tdb,
|
||||
int rw_type, tdb1_off_t offset, size_t len,
|
||||
enum tdb_lock_flags flags);
|
||||
int tdb1_brunlock(struct tdb1_context *tdb,
|
||||
int tdb1_brunlock(struct tdb_context *tdb,
|
||||
int rw_type, tdb1_off_t offset, size_t len);
|
||||
bool tdb1_have_extra_locks(struct tdb1_context *tdb);
|
||||
void tdb1_release_transaction_locks(struct tdb1_context *tdb);
|
||||
int tdb1_transaction_lock(struct tdb1_context *tdb, int ltype,
|
||||
bool tdb1_have_extra_locks(struct tdb_context *tdb);
|
||||
void tdb1_release_transaction_locks(struct tdb_context *tdb);
|
||||
int tdb1_transaction_lock(struct tdb_context *tdb, int ltype,
|
||||
enum tdb_lock_flags lockflags);
|
||||
int tdb1_transaction_unlock(struct tdb1_context *tdb, int ltype);
|
||||
int tdb1_recovery_area(struct tdb1_context *tdb,
|
||||
int tdb1_transaction_unlock(struct tdb_context *tdb, int ltype);
|
||||
int tdb1_recovery_area(struct tdb_context *tdb,
|
||||
const struct tdb1_methods *methods,
|
||||
tdb1_off_t *recovery_offset,
|
||||
struct tdb1_record *rec);
|
||||
int tdb1_allrecord_lock(struct tdb1_context *tdb, int ltype,
|
||||
int tdb1_allrecord_lock(struct tdb_context *tdb, int ltype,
|
||||
enum tdb_lock_flags flags, bool upgradable);
|
||||
int tdb1_allrecord_unlock(struct tdb1_context *tdb, int ltype);
|
||||
int tdb1_allrecord_upgrade(struct tdb1_context *tdb);
|
||||
int tdb1_write_lock_record(struct tdb1_context *tdb, tdb1_off_t off);
|
||||
int tdb1_write_unlock_record(struct tdb1_context *tdb, tdb1_off_t off);
|
||||
int tdb1_ofs_read(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_off_t *d);
|
||||
int tdb1_ofs_write(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_off_t *d);
|
||||
int tdb1_allrecord_unlock(struct tdb_context *tdb, int ltype);
|
||||
int tdb1_allrecord_upgrade(struct tdb_context *tdb);
|
||||
int tdb1_write_lock_record(struct tdb_context *tdb, tdb1_off_t off);
|
||||
int tdb1_write_unlock_record(struct tdb_context *tdb, tdb1_off_t off);
|
||||
int tdb1_ofs_read(struct tdb_context *tdb, tdb1_off_t offset, tdb1_off_t *d);
|
||||
int tdb1_ofs_write(struct tdb_context *tdb, tdb1_off_t offset, tdb1_off_t *d);
|
||||
void *tdb1_convert(void *buf, uint32_t size);
|
||||
int tdb1_free(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *rec);
|
||||
tdb1_off_t tdb1_allocate(struct tdb1_context *tdb, tdb1_len_t length, struct tdb1_record *rec);
|
||||
int tdb1_ofs_read(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_off_t *d);
|
||||
int tdb1_ofs_write(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_off_t *d);
|
||||
int tdb1_lock_record(struct tdb1_context *tdb, tdb1_off_t off);
|
||||
int tdb1_unlock_record(struct tdb1_context *tdb, tdb1_off_t off);
|
||||
bool tdb1_needs_recovery(struct tdb1_context *tdb);
|
||||
int tdb1_rec_read(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *rec);
|
||||
int tdb1_rec_write(struct tdb1_context *tdb, tdb1_off_t offset, struct tdb1_record *rec);
|
||||
int tdb1_do_delete(struct tdb1_context *tdb, tdb1_off_t rec_ptr, struct tdb1_record *rec);
|
||||
unsigned char *tdb1_alloc_read(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_len_t len);
|
||||
int tdb1_parse_data(struct tdb1_context *tdb, TDB_DATA key,
|
||||
int tdb1_free(struct tdb_context *tdb, tdb1_off_t offset, struct tdb1_record *rec);
|
||||
tdb1_off_t tdb1_allocate(struct tdb_context *tdb, tdb1_len_t length, struct tdb1_record *rec);
|
||||
int tdb1_ofs_read(struct tdb_context *tdb, tdb1_off_t offset, tdb1_off_t *d);
|
||||
int tdb1_ofs_write(struct tdb_context *tdb, tdb1_off_t offset, tdb1_off_t *d);
|
||||
int tdb1_lock_record(struct tdb_context *tdb, tdb1_off_t off);
|
||||
int tdb1_unlock_record(struct tdb_context *tdb, tdb1_off_t off);
|
||||
bool tdb1_needs_recovery(struct tdb_context *tdb);
|
||||
int tdb1_rec_read(struct tdb_context *tdb, tdb1_off_t offset, struct tdb1_record *rec);
|
||||
int tdb1_rec_write(struct tdb_context *tdb, tdb1_off_t offset, struct tdb1_record *rec);
|
||||
int tdb1_do_delete(struct tdb_context *tdb, tdb1_off_t rec_ptr, struct tdb1_record *rec);
|
||||
unsigned char *tdb1_alloc_read(struct tdb_context *tdb, tdb1_off_t offset, tdb1_len_t len);
|
||||
int tdb1_parse_data(struct tdb_context *tdb, TDB_DATA key,
|
||||
tdb1_off_t offset, tdb1_len_t len,
|
||||
int (*parser)(TDB_DATA key, TDB_DATA data,
|
||||
void *private_data),
|
||||
void *private_data);
|
||||
tdb1_off_t tdb1_find_lock_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t hash, int locktype,
|
||||
tdb1_off_t tdb1_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype,
|
||||
struct tdb1_record *rec);
|
||||
void tdb1_io_init(struct tdb1_context *tdb);
|
||||
int tdb1_expand(struct tdb1_context *tdb, tdb1_off_t size);
|
||||
int tdb1_rec_free_read(struct tdb1_context *tdb, tdb1_off_t off,
|
||||
void tdb1_io_init(struct tdb_context *tdb);
|
||||
int tdb1_expand(struct tdb_context *tdb, tdb1_off_t size);
|
||||
int tdb1_rec_free_read(struct tdb_context *tdb, tdb1_off_t off,
|
||||
struct tdb1_record *rec);
|
||||
bool tdb1_write_all(int fd, const void *buf, size_t count);
|
||||
int tdb1_transaction_recover(struct tdb1_context *tdb);
|
||||
void tdb1_header_hash(struct tdb1_context *tdb,
|
||||
int tdb1_transaction_recover(struct tdb_context *tdb);
|
||||
void tdb1_header_hash(struct tdb_context *tdb,
|
||||
uint32_t *magic1_hash, uint32_t *magic2_hash);
|
||||
uint64_t tdb1_old_hash(const void *key, size_t len, uint64_t seed, void *);
|
||||
size_t tdb1_dead_space(struct tdb1_context *tdb, tdb1_off_t off);
|
||||
size_t tdb1_dead_space(struct tdb_context *tdb, tdb1_off_t off);
|
||||
#endif /* CCAN_TDB2_TDB1_PRIVATE_H */
|
||||
|
@ -65,7 +65,7 @@ static size_t tally1_mean(const struct tally *tally)
|
||||
return tally->total / tally->num;
|
||||
}
|
||||
|
||||
static size_t get_hash_length(struct tdb1_context *tdb, unsigned int i)
|
||||
static size_t get_hash_length(struct tdb_context *tdb, unsigned int i)
|
||||
{
|
||||
tdb1_off_t rec_ptr;
|
||||
size_t count = 0;
|
||||
@ -84,7 +84,7 @@ static size_t get_hash_length(struct tdb1_context *tdb, unsigned int i)
|
||||
return count;
|
||||
}
|
||||
|
||||
char *tdb1_summary(struct tdb1_context *tdb)
|
||||
char *tdb1_summary(struct tdb_context *tdb)
|
||||
{
|
||||
tdb1_off_t off, rec_off;
|
||||
struct tally freet, keys, data, dead, extra, hash, uncoal;
|
||||
@ -103,7 +103,7 @@ char *tdb1_summary(struct tdb1_context *tdb)
|
||||
locked = true;
|
||||
}
|
||||
|
||||
if (tdb1_recovery_area(tdb, tdb->methods, &rec_off, &recovery) != 0) {
|
||||
if (tdb1_recovery_area(tdb, tdb->tdb1.io, &rec_off, &recovery) != 0) {
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
@ -115,10 +115,10 @@ char *tdb1_summary(struct tdb1_context *tdb)
|
||||
tally1_init(&hash);
|
||||
tally1_init(&uncoal);
|
||||
|
||||
for (off = TDB1_DATA_START(tdb->header.hash_size);
|
||||
for (off = TDB1_DATA_START(tdb->tdb1.header.hash_size);
|
||||
off < tdb->file->map_size - 1;
|
||||
off += sizeof(rec) + rec.rec_len) {
|
||||
if (tdb->methods->tdb1_read(tdb, off, &rec, sizeof(rec),
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, off, &rec, sizeof(rec),
|
||||
TDB1_DOCONV()) == -1)
|
||||
goto unlock;
|
||||
switch (rec.magic) {
|
||||
@ -160,7 +160,7 @@ char *tdb1_summary(struct tdb1_context *tdb)
|
||||
if (unc > 1)
|
||||
tally1_add(&uncoal, unc - 1);
|
||||
|
||||
for (off = 0; off < tdb->header.hash_size; off++)
|
||||
for (off = 0; off < tdb->tdb1.header.hash_size; off++)
|
||||
tally1_add(&hash, get_hash_length(tdb, off));
|
||||
|
||||
/* 20 is max length of a %zu. */
|
||||
@ -191,7 +191,7 @@ char *tdb1_summary(struct tdb1_context *tdb)
|
||||
(keys.num + freet.num + dead.num)
|
||||
* (sizeof(struct tdb1_record) + sizeof(uint32_t))
|
||||
* 100.0 / tdb->file->map_size,
|
||||
tdb->header.hash_size * sizeof(tdb1_off_t)
|
||||
tdb->tdb1.header.hash_size * sizeof(tdb1_off_t)
|
||||
* 100.0 / (tdb1_len_t)tdb->file->map_size);
|
||||
|
||||
unlock:
|
||||
|
@ -33,7 +33,7 @@ TDB_DATA tdb1_null;
|
||||
non-blocking increment of the tdb sequence number if the tdb has been opened using
|
||||
the TDB_SEQNUM flag
|
||||
*/
|
||||
void tdb1_increment_seqnum_nonblock(struct tdb1_context *tdb)
|
||||
void tdb1_increment_seqnum_nonblock(struct tdb_context *tdb)
|
||||
{
|
||||
tdb1_off_t seqnum=0;
|
||||
|
||||
@ -53,7 +53,7 @@ void tdb1_increment_seqnum_nonblock(struct tdb1_context *tdb)
|
||||
increment the tdb sequence number if the tdb has been opened using
|
||||
the TDB_SEQNUM flag
|
||||
*/
|
||||
static void tdb1_increment_seqnum(struct tdb1_context *tdb)
|
||||
static void tdb1_increment_seqnum(struct tdb_context *tdb)
|
||||
{
|
||||
if (!(tdb->flags & TDB_SEQNUM)) {
|
||||
return;
|
||||
@ -76,7 +76,7 @@ static int tdb1_key_compare(TDB_DATA key, TDB_DATA data, void *private_data)
|
||||
|
||||
/* Returns 0 on fail. On success, return offset of record, and fills
|
||||
in rec */
|
||||
static tdb1_off_t tdb1_find(struct tdb1_context *tdb, TDB_DATA key, uint32_t hash,
|
||||
static tdb1_off_t tdb1_find(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
|
||||
struct tdb1_record *r)
|
||||
{
|
||||
tdb1_off_t rec_ptr;
|
||||
@ -111,7 +111,7 @@ static tdb1_off_t tdb1_find(struct tdb1_context *tdb, TDB_DATA key, uint32_t has
|
||||
}
|
||||
|
||||
/* As tdb1_find, but if you succeed, keep the lock */
|
||||
tdb1_off_t tdb1_find_lock_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t hash, int locktype,
|
||||
tdb1_off_t tdb1_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, int locktype,
|
||||
struct tdb1_record *rec)
|
||||
{
|
||||
uint32_t rec_ptr;
|
||||
@ -123,13 +123,13 @@ tdb1_off_t tdb1_find_lock_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t
|
||||
return rec_ptr;
|
||||
}
|
||||
|
||||
static TDB_DATA _tdb1_fetch(struct tdb1_context *tdb, TDB_DATA key);
|
||||
static TDB_DATA _tdb1_fetch(struct tdb_context *tdb, TDB_DATA key);
|
||||
|
||||
/* update an entry in place - this only works if the new data size
|
||||
is <= the old data size and the key exists.
|
||||
on failure return -1.
|
||||
*/
|
||||
static int tdb1_update_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t hash, TDB_DATA dbuf)
|
||||
static int tdb1_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, TDB_DATA dbuf)
|
||||
{
|
||||
struct tdb1_record rec;
|
||||
tdb1_off_t rec_ptr;
|
||||
@ -162,7 +162,7 @@ static int tdb1_update_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t has
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tdb->methods->tdb1_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
|
||||
if (tdb->tdb1.io->tdb1_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
|
||||
dbuf.dptr, dbuf.dsize) == -1)
|
||||
return -1;
|
||||
|
||||
@ -181,7 +181,7 @@ static int tdb1_update_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t has
|
||||
* then the TDB_DATA will have zero length but
|
||||
* a non-zero pointer
|
||||
*/
|
||||
static TDB_DATA _tdb1_fetch(struct tdb1_context *tdb, TDB_DATA key)
|
||||
static TDB_DATA _tdb1_fetch(struct tdb_context *tdb, TDB_DATA key)
|
||||
{
|
||||
tdb1_off_t rec_ptr;
|
||||
struct tdb1_record rec;
|
||||
@ -200,7 +200,7 @@ static TDB_DATA _tdb1_fetch(struct tdb1_context *tdb, TDB_DATA key)
|
||||
return ret;
|
||||
}
|
||||
|
||||
TDB_DATA tdb1_fetch(struct tdb1_context *tdb, TDB_DATA key)
|
||||
TDB_DATA tdb1_fetch(struct tdb_context *tdb, TDB_DATA key)
|
||||
{
|
||||
TDB_DATA ret = _tdb1_fetch(tdb, key);
|
||||
|
||||
@ -225,7 +225,7 @@ TDB_DATA tdb1_fetch(struct tdb1_context *tdb, TDB_DATA key)
|
||||
* Return -1 if the record was not found.
|
||||
*/
|
||||
|
||||
int tdb1_parse_record(struct tdb1_context *tdb, TDB_DATA key,
|
||||
int tdb1_parse_record(struct tdb_context *tdb, TDB_DATA key,
|
||||
int (*parser)(TDB_DATA key, TDB_DATA data,
|
||||
void *private_data),
|
||||
void *private_data)
|
||||
@ -258,7 +258,7 @@ int tdb1_parse_record(struct tdb1_context *tdb, TDB_DATA key,
|
||||
this doesn't match the conventions in the rest of this module, but is
|
||||
compatible with gdbm
|
||||
*/
|
||||
static int tdb1_exists_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t hash)
|
||||
static int tdb1_exists_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash)
|
||||
{
|
||||
struct tdb1_record rec;
|
||||
|
||||
@ -268,7 +268,7 @@ static int tdb1_exists_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t has
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tdb1_exists(struct tdb1_context *tdb, TDB_DATA key)
|
||||
int tdb1_exists(struct tdb_context *tdb, TDB_DATA key)
|
||||
{
|
||||
uint32_t hash = tdb_hash(tdb, key.dptr, key.dsize);
|
||||
int ret;
|
||||
@ -278,14 +278,14 @@ int tdb1_exists(struct tdb1_context *tdb, TDB_DATA key)
|
||||
}
|
||||
|
||||
/* actually delete an entry in the database given the offset */
|
||||
int tdb1_do_delete(struct tdb1_context *tdb, tdb1_off_t rec_ptr, struct tdb1_record *rec)
|
||||
int tdb1_do_delete(struct tdb_context *tdb, tdb1_off_t rec_ptr, struct tdb1_record *rec)
|
||||
{
|
||||
tdb1_off_t last_ptr, i;
|
||||
struct tdb1_record lastrec;
|
||||
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->traverse_read) return -1;
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->tdb1.traverse_read) return -1;
|
||||
|
||||
if (((tdb->traverse_write != 0) && (!TDB1_DEAD(rec))) ||
|
||||
if (((tdb->tdb1.traverse_write != 0) && (!TDB1_DEAD(rec))) ||
|
||||
tdb1_write_lock_record(tdb, rec_ptr) == -1) {
|
||||
/* Someone traversing here: mark it as dead */
|
||||
rec->magic = TDB1_DEAD_MAGIC;
|
||||
@ -313,7 +313,7 @@ int tdb1_do_delete(struct tdb1_context *tdb, tdb1_off_t rec_ptr, struct tdb1_rec
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tdb1_count_dead(struct tdb1_context *tdb, uint32_t hash)
|
||||
static int tdb1_count_dead(struct tdb_context *tdb, uint32_t hash)
|
||||
{
|
||||
int res = 0;
|
||||
tdb1_off_t rec_ptr;
|
||||
@ -338,7 +338,7 @@ static int tdb1_count_dead(struct tdb1_context *tdb, uint32_t hash)
|
||||
/*
|
||||
* Purge all DEAD records from a hash chain
|
||||
*/
|
||||
static int tdb1_purge_dead(struct tdb1_context *tdb, uint32_t hash)
|
||||
static int tdb1_purge_dead(struct tdb_context *tdb, uint32_t hash)
|
||||
{
|
||||
int res = -1;
|
||||
struct tdb1_record rec;
|
||||
@ -374,13 +374,13 @@ static int tdb1_purge_dead(struct tdb1_context *tdb, uint32_t hash)
|
||||
}
|
||||
|
||||
/* delete an entry in the database given a key */
|
||||
static int tdb1_delete_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t hash)
|
||||
static int tdb1_delete_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash)
|
||||
{
|
||||
tdb1_off_t rec_ptr;
|
||||
struct tdb1_record rec;
|
||||
int ret;
|
||||
|
||||
if (tdb->max_dead_records != 0) {
|
||||
if (tdb->tdb1.max_dead_records != 0) {
|
||||
|
||||
/*
|
||||
* Allow for some dead records per hash chain, mainly for
|
||||
@ -390,7 +390,7 @@ static int tdb1_delete_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t has
|
||||
if (tdb1_lock(tdb, TDB1_BUCKET(hash), F_WRLCK) == -1)
|
||||
return -1;
|
||||
|
||||
if (tdb1_count_dead(tdb, hash) >= tdb->max_dead_records) {
|
||||
if (tdb1_count_dead(tdb, hash) >= tdb->tdb1.max_dead_records) {
|
||||
/*
|
||||
* Don't let the per-chain freelist grow too large,
|
||||
* delete all existing dead records
|
||||
@ -427,7 +427,7 @@ static int tdb1_delete_hash(struct tdb1_context *tdb, TDB_DATA key, uint32_t has
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tdb1_delete(struct tdb1_context *tdb, TDB_DATA key)
|
||||
int tdb1_delete(struct tdb_context *tdb, TDB_DATA key)
|
||||
{
|
||||
uint32_t hash = tdb_hash(tdb, key.dptr, key.dsize);
|
||||
int ret;
|
||||
@ -439,7 +439,7 @@ int tdb1_delete(struct tdb1_context *tdb, TDB_DATA key)
|
||||
/*
|
||||
* See if we have a dead record around with enough space
|
||||
*/
|
||||
static tdb1_off_t tdb1_find_dead(struct tdb1_context *tdb, uint32_t hash,
|
||||
static tdb1_off_t tdb1_find_dead(struct tdb_context *tdb, uint32_t hash,
|
||||
struct tdb1_record *r, tdb1_len_t length)
|
||||
{
|
||||
tdb1_off_t rec_ptr;
|
||||
@ -465,7 +465,7 @@ static tdb1_off_t tdb1_find_dead(struct tdb1_context *tdb, uint32_t hash,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _tdb1_store(struct tdb1_context *tdb, TDB_DATA key,
|
||||
static int _tdb1_store(struct tdb_context *tdb, TDB_DATA key,
|
||||
TDB_DATA dbuf, int flag, uint32_t hash)
|
||||
{
|
||||
struct tdb1_record rec;
|
||||
@ -512,7 +512,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB_DATA key,
|
||||
if (dbuf.dsize)
|
||||
memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize);
|
||||
|
||||
if (tdb->max_dead_records != 0) {
|
||||
if (tdb->tdb1.max_dead_records != 0) {
|
||||
/*
|
||||
* Allow for some dead records per hash chain, look if we can
|
||||
* find one that can hold the new record. We need enough space
|
||||
@ -529,7 +529,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB_DATA key,
|
||||
rec.full_hash = hash;
|
||||
rec.magic = TDB1_MAGIC;
|
||||
if (tdb1_rec_write(tdb, rec_ptr, &rec) == -1
|
||||
|| tdb->methods->tdb1_write(
|
||||
|| tdb->tdb1.io->tdb1_write(
|
||||
tdb, rec_ptr + sizeof(rec),
|
||||
p, key.dsize + dbuf.dsize) == -1) {
|
||||
goto fail;
|
||||
@ -548,7 +548,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB_DATA key,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((tdb->max_dead_records != 0)
|
||||
if ((tdb->tdb1.max_dead_records != 0)
|
||||
&& (tdb1_purge_dead(tdb, hash) == -1)) {
|
||||
tdb1_unlock(tdb, -1, F_WRLCK);
|
||||
goto fail;
|
||||
@ -574,7 +574,7 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB_DATA key,
|
||||
|
||||
/* write out and point the top of the hash chain at it */
|
||||
if (tdb1_rec_write(tdb, rec_ptr, &rec) == -1
|
||||
|| tdb->methods->tdb1_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
|
||||
|| tdb->tdb1.io->tdb1_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1
|
||||
|| tdb1_ofs_write(tdb, TDB1_HASH_TOP(hash), &rec_ptr) == -1) {
|
||||
/* Need to tdb1_unallocate() here */
|
||||
goto fail;
|
||||
@ -596,12 +596,12 @@ static int _tdb1_store(struct tdb1_context *tdb, TDB_DATA key,
|
||||
|
||||
return 0 on success, -1 on failure
|
||||
*/
|
||||
int tdb1_store(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
|
||||
int tdb1_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
|
||||
{
|
||||
uint32_t hash;
|
||||
int ret;
|
||||
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->traverse_read) {
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->tdb1.traverse_read) {
|
||||
tdb->last_error = TDB_ERR_RDONLY;
|
||||
return -1;
|
||||
}
|
||||
@ -617,7 +617,7 @@ int tdb1_store(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
|
||||
}
|
||||
|
||||
/* Append to an entry. Create if not exist. */
|
||||
int tdb1_append(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
|
||||
int tdb1_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
|
||||
{
|
||||
uint32_t hash;
|
||||
TDB_DATA dbuf;
|
||||
@ -673,7 +673,7 @@ failed:
|
||||
The aim of this sequence number is to allow for a very lightweight
|
||||
test of a possible tdb change.
|
||||
*/
|
||||
int tdb1_get_seqnum(struct tdb1_context *tdb)
|
||||
int tdb1_get_seqnum(struct tdb_context *tdb)
|
||||
{
|
||||
tdb1_off_t seqnum=0;
|
||||
|
||||
@ -681,9 +681,9 @@ int tdb1_get_seqnum(struct tdb1_context *tdb)
|
||||
return seqnum;
|
||||
}
|
||||
|
||||
int tdb1_hash_size(struct tdb1_context *tdb)
|
||||
int tdb1_hash_size(struct tdb_context *tdb)
|
||||
{
|
||||
return tdb->header.hash_size;
|
||||
return tdb->tdb1.header.hash_size;
|
||||
}
|
||||
|
||||
|
||||
@ -691,7 +691,7 @@ int tdb1_hash_size(struct tdb1_context *tdb)
|
||||
add a region of the file to the freelist. Length is the size of the region in bytes,
|
||||
which includes the free list header that needs to be added
|
||||
*/
|
||||
static int tdb1_free_region(struct tdb1_context *tdb, tdb1_off_t offset, ssize_t length)
|
||||
static int tdb1_free_region(struct tdb_context *tdb, tdb1_off_t offset, ssize_t length)
|
||||
{
|
||||
struct tdb1_record rec;
|
||||
if (length <= sizeof(rec)) {
|
||||
@ -721,7 +721,7 @@ static int tdb1_free_region(struct tdb1_context *tdb, tdb1_off_t offset, ssize_t
|
||||
|
||||
This code carefully steps around the recovery area, leaving it alone
|
||||
*/
|
||||
int tdb1_wipe_all(struct tdb1_context *tdb)
|
||||
int tdb1_wipe_all(struct tdb_context *tdb)
|
||||
{
|
||||
int i;
|
||||
tdb1_off_t offset = 0;
|
||||
@ -746,7 +746,7 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
|
||||
|
||||
if (recovery_head != 0) {
|
||||
struct tdb1_record rec;
|
||||
if (tdb->methods->tdb1_read(tdb, recovery_head, &rec, sizeof(rec), TDB1_DOCONV()) == -1) {
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, recovery_head, &rec, sizeof(rec), TDB1_DOCONV()) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_wipe_all: failed to read recovery record");
|
||||
return -1;
|
||||
@ -755,7 +755,7 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* wipe the hashes */
|
||||
for (i=0;i<tdb->header.hash_size;i++) {
|
||||
for (i=0;i<tdb->tdb1.header.hash_size;i++) {
|
||||
if (tdb1_ofs_write(tdb, TDB1_HASH_TOP(i), &offset) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_wipe_all: failed to write hash %d", i);
|
||||
@ -774,8 +774,8 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
|
||||
for the recovery area */
|
||||
if (recovery_size == 0) {
|
||||
/* the simple case - the whole file can be used as a freelist */
|
||||
data_len = (tdb->file->map_size - TDB1_DATA_START(tdb->header.hash_size));
|
||||
if (tdb1_free_region(tdb, TDB1_DATA_START(tdb->header.hash_size), data_len) != 0) {
|
||||
data_len = (tdb->file->map_size - TDB1_DATA_START(tdb->tdb1.header.hash_size));
|
||||
if (tdb1_free_region(tdb, TDB1_DATA_START(tdb->tdb1.header.hash_size), data_len) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
} else {
|
||||
@ -787,8 +787,8 @@ int tdb1_wipe_all(struct tdb1_context *tdb)
|
||||
move the recovery area or we risk subtle data
|
||||
corruption
|
||||
*/
|
||||
data_len = (recovery_head - TDB1_DATA_START(tdb->header.hash_size));
|
||||
if (tdb1_free_region(tdb, TDB1_DATA_START(tdb->header.hash_size), data_len) != 0) {
|
||||
data_len = (recovery_head - TDB1_DATA_START(tdb->tdb1.header.hash_size));
|
||||
if (tdb1_free_region(tdb, TDB1_DATA_START(tdb->tdb1.header.hash_size), data_len) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
/* and the 2nd free list entry after the recovery area - if any */
|
||||
@ -813,13 +813,13 @@ failed:
|
||||
|
||||
struct traverse_state {
|
||||
enum TDB_ERROR error;
|
||||
struct tdb1_context *dest_db;
|
||||
struct tdb_context *dest_db;
|
||||
};
|
||||
|
||||
/*
|
||||
traverse function for repacking
|
||||
*/
|
||||
static int repack_traverse(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data, void *private_data)
|
||||
static int repack_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private_data)
|
||||
{
|
||||
struct traverse_state *state = (struct traverse_state *)private_data;
|
||||
if (tdb1_store(state->dest_db, key, data, TDB_INSERT) != 0) {
|
||||
@ -832,9 +832,9 @@ static int repack_traverse(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data
|
||||
/*
|
||||
repack a tdb
|
||||
*/
|
||||
int tdb1_repack(struct tdb1_context *tdb)
|
||||
int tdb1_repack(struct tdb_context *tdb)
|
||||
{
|
||||
struct tdb1_context *tmp_db;
|
||||
struct tdb_context *tmp_db;
|
||||
struct traverse_state state;
|
||||
|
||||
if (tdb1_transaction_start(tdb) != 0) {
|
||||
|
@ -138,14 +138,14 @@ struct tdb1_transaction {
|
||||
read while in a transaction. We need to check first if the data is in our list
|
||||
of transaction elements, then if not do a real read
|
||||
*/
|
||||
static int transaction1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf,
|
||||
static int transaction1_read(struct tdb_context *tdb, tdb1_off_t off, void *buf,
|
||||
tdb1_len_t len, int cv)
|
||||
{
|
||||
uint32_t blk;
|
||||
|
||||
/* break it down into block sized ops */
|
||||
while (len + (off % tdb->transaction->block_size) > tdb->transaction->block_size) {
|
||||
tdb1_len_t len2 = tdb->transaction->block_size - (off % tdb->transaction->block_size);
|
||||
while (len + (off % tdb->tdb1.transaction->block_size) > tdb->tdb1.transaction->block_size) {
|
||||
tdb1_len_t len2 = tdb->tdb1.transaction->block_size - (off % tdb->tdb1.transaction->block_size);
|
||||
if (transaction1_read(tdb, off, buf, len2, cv) != 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -158,27 +158,27 @@ static int transaction1_read(struct tdb1_context *tdb, tdb1_off_t off, void *buf
|
||||
return 0;
|
||||
}
|
||||
|
||||
blk = off / tdb->transaction->block_size;
|
||||
blk = off / tdb->tdb1.transaction->block_size;
|
||||
|
||||
/* see if we have it in the block list */
|
||||
if (tdb->transaction->num_blocks <= blk ||
|
||||
tdb->transaction->blocks[blk] == NULL) {
|
||||
if (tdb->tdb1.transaction->num_blocks <= blk ||
|
||||
tdb->tdb1.transaction->blocks[blk] == NULL) {
|
||||
/* nope, do a real read */
|
||||
if (tdb->transaction->io_methods->tdb1_read(tdb, off, buf, len, cv) != 0) {
|
||||
if (tdb->tdb1.transaction->io_methods->tdb1_read(tdb, off, buf, len, cv) != 0) {
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* it is in the block list. Now check for the last block */
|
||||
if (blk == tdb->transaction->num_blocks-1) {
|
||||
if (len > tdb->transaction->last_block_size) {
|
||||
if (blk == tdb->tdb1.transaction->num_blocks-1) {
|
||||
if (len > tdb->tdb1.transaction->last_block_size) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* now copy it out of this block */
|
||||
memcpy(buf, tdb->transaction->blocks[blk] + (off % tdb->transaction->block_size), len);
|
||||
memcpy(buf, tdb->tdb1.transaction->blocks[blk] + (off % tdb->tdb1.transaction->block_size), len);
|
||||
if (cv) {
|
||||
tdb1_convert(buf, len);
|
||||
}
|
||||
@ -188,7 +188,7 @@ fail:
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
|
||||
"transaction_read: failed at off=%d len=%d",
|
||||
off, len);
|
||||
tdb->transaction->transaction_error = 1;
|
||||
tdb->tdb1.transaction->transaction_error = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -196,17 +196,17 @@ fail:
|
||||
/*
|
||||
write while in a transaction
|
||||
*/
|
||||
static int transaction1_write(struct tdb1_context *tdb, tdb1_off_t off,
|
||||
static int transaction1_write(struct tdb_context *tdb, tdb1_off_t off,
|
||||
const void *buf, tdb1_len_t len)
|
||||
{
|
||||
uint32_t blk;
|
||||
|
||||
/* Only a commit is allowed on a prepared transaction */
|
||||
if (tdb->transaction->prepared) {
|
||||
if (tdb->tdb1.transaction->prepared) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
"transaction_write: transaction already"
|
||||
" prepared, write not allowed");
|
||||
tdb->transaction->transaction_error = 1;
|
||||
tdb->tdb1.transaction->transaction_error = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -215,12 +215,12 @@ static int transaction1_write(struct tdb1_context *tdb, tdb1_off_t off,
|
||||
if (len == sizeof(tdb1_off_t) && off >= TDB1_FREELIST_TOP &&
|
||||
off < TDB1_FREELIST_TOP+TDB1_HASHTABLE_SIZE(tdb)) {
|
||||
uint32_t chain = (off-TDB1_FREELIST_TOP) / sizeof(tdb1_off_t);
|
||||
memcpy(&tdb->transaction->hash_heads[chain], buf, len);
|
||||
memcpy(&tdb->tdb1.transaction->hash_heads[chain], buf, len);
|
||||
}
|
||||
|
||||
/* break it up into block sized chunks */
|
||||
while (len + (off % tdb->transaction->block_size) > tdb->transaction->block_size) {
|
||||
tdb1_len_t len2 = tdb->transaction->block_size - (off % tdb->transaction->block_size);
|
||||
while (len + (off % tdb->tdb1.transaction->block_size) > tdb->tdb1.transaction->block_size) {
|
||||
tdb1_len_t len2 = tdb->tdb1.transaction->block_size - (off % tdb->tdb1.transaction->block_size);
|
||||
if (transaction1_write(tdb, off, buf, len2) != 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -235,66 +235,66 @@ static int transaction1_write(struct tdb1_context *tdb, tdb1_off_t off,
|
||||
return 0;
|
||||
}
|
||||
|
||||
blk = off / tdb->transaction->block_size;
|
||||
off = off % tdb->transaction->block_size;
|
||||
blk = off / tdb->tdb1.transaction->block_size;
|
||||
off = off % tdb->tdb1.transaction->block_size;
|
||||
|
||||
if (tdb->transaction->num_blocks <= blk) {
|
||||
if (tdb->tdb1.transaction->num_blocks <= blk) {
|
||||
uint8_t **new_blocks;
|
||||
/* expand the blocks array */
|
||||
if (tdb->transaction->blocks == NULL) {
|
||||
if (tdb->tdb1.transaction->blocks == NULL) {
|
||||
new_blocks = (uint8_t **)malloc(
|
||||
(blk+1)*sizeof(uint8_t *));
|
||||
} else {
|
||||
new_blocks = (uint8_t **)realloc(
|
||||
tdb->transaction->blocks,
|
||||
tdb->tdb1.transaction->blocks,
|
||||
(blk+1)*sizeof(uint8_t *));
|
||||
}
|
||||
if (new_blocks == NULL) {
|
||||
tdb->last_error = TDB_ERR_OOM;
|
||||
goto fail;
|
||||
}
|
||||
memset(&new_blocks[tdb->transaction->num_blocks], 0,
|
||||
(1+(blk - tdb->transaction->num_blocks))*sizeof(uint8_t *));
|
||||
tdb->transaction->blocks = new_blocks;
|
||||
tdb->transaction->num_blocks = blk+1;
|
||||
tdb->transaction->last_block_size = 0;
|
||||
memset(&new_blocks[tdb->tdb1.transaction->num_blocks], 0,
|
||||
(1+(blk - tdb->tdb1.transaction->num_blocks))*sizeof(uint8_t *));
|
||||
tdb->tdb1.transaction->blocks = new_blocks;
|
||||
tdb->tdb1.transaction->num_blocks = blk+1;
|
||||
tdb->tdb1.transaction->last_block_size = 0;
|
||||
}
|
||||
|
||||
/* allocate and fill a block? */
|
||||
if (tdb->transaction->blocks[blk] == NULL) {
|
||||
tdb->transaction->blocks[blk] = (uint8_t *)calloc(tdb->transaction->block_size, 1);
|
||||
if (tdb->transaction->blocks[blk] == NULL) {
|
||||
if (tdb->tdb1.transaction->blocks[blk] == NULL) {
|
||||
tdb->tdb1.transaction->blocks[blk] = (uint8_t *)calloc(tdb->tdb1.transaction->block_size, 1);
|
||||
if (tdb->tdb1.transaction->blocks[blk] == NULL) {
|
||||
tdb->last_error = TDB_ERR_OOM;
|
||||
tdb->transaction->transaction_error = 1;
|
||||
tdb->tdb1.transaction->transaction_error = 1;
|
||||
return -1;
|
||||
}
|
||||
if (tdb->transaction->old_map_size > blk * tdb->transaction->block_size) {
|
||||
tdb1_len_t len2 = tdb->transaction->block_size;
|
||||
if (len2 + (blk * tdb->transaction->block_size) > tdb->transaction->old_map_size) {
|
||||
len2 = tdb->transaction->old_map_size - (blk * tdb->transaction->block_size);
|
||||
if (tdb->tdb1.transaction->old_map_size > blk * tdb->tdb1.transaction->block_size) {
|
||||
tdb1_len_t len2 = tdb->tdb1.transaction->block_size;
|
||||
if (len2 + (blk * tdb->tdb1.transaction->block_size) > tdb->tdb1.transaction->old_map_size) {
|
||||
len2 = tdb->tdb1.transaction->old_map_size - (blk * tdb->tdb1.transaction->block_size);
|
||||
}
|
||||
if (tdb->transaction->io_methods->tdb1_read(tdb, blk * tdb->transaction->block_size,
|
||||
tdb->transaction->blocks[blk],
|
||||
if (tdb->tdb1.transaction->io_methods->tdb1_read(tdb, blk * tdb->tdb1.transaction->block_size,
|
||||
tdb->tdb1.transaction->blocks[blk],
|
||||
len2, 0) != 0) {
|
||||
SAFE_FREE(tdb->transaction->blocks[blk]);
|
||||
SAFE_FREE(tdb->tdb1.transaction->blocks[blk]);
|
||||
tdb->last_error = TDB_ERR_IO;
|
||||
goto fail;
|
||||
}
|
||||
if (blk == tdb->transaction->num_blocks-1) {
|
||||
tdb->transaction->last_block_size = len2;
|
||||
if (blk == tdb->tdb1.transaction->num_blocks-1) {
|
||||
tdb->tdb1.transaction->last_block_size = len2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* overwrite part of an existing block */
|
||||
if (buf == NULL) {
|
||||
memset(tdb->transaction->blocks[blk] + off, 0, len);
|
||||
memset(tdb->tdb1.transaction->blocks[blk] + off, 0, len);
|
||||
} else {
|
||||
memcpy(tdb->transaction->blocks[blk] + off, buf, len);
|
||||
memcpy(tdb->tdb1.transaction->blocks[blk] + off, buf, len);
|
||||
}
|
||||
if (blk == tdb->transaction->num_blocks-1) {
|
||||
if (len + off > tdb->transaction->last_block_size) {
|
||||
tdb->transaction->last_block_size = len + off;
|
||||
if (blk == tdb->tdb1.transaction->num_blocks-1) {
|
||||
if (len + off > tdb->tdb1.transaction->last_block_size) {
|
||||
tdb->tdb1.transaction->last_block_size = len + off;
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,8 +303,8 @@ static int transaction1_write(struct tdb1_context *tdb, tdb1_off_t off,
|
||||
fail:
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"transaction_write: failed at off=%d len=%d",
|
||||
(blk*tdb->transaction->block_size) + off, len);
|
||||
tdb->transaction->transaction_error = 1;
|
||||
(blk*tdb->tdb1.transaction->block_size) + off, len);
|
||||
tdb->tdb1.transaction->transaction_error = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -313,14 +313,14 @@ fail:
|
||||
write while in a transaction - this varient never expands the transaction blocks, it only
|
||||
updates existing blocks. This means it cannot change the recovery size
|
||||
*/
|
||||
static int transaction1_write_existing(struct tdb1_context *tdb, tdb1_off_t off,
|
||||
static int transaction1_write_existing(struct tdb_context *tdb, tdb1_off_t off,
|
||||
const void *buf, tdb1_len_t len)
|
||||
{
|
||||
uint32_t blk;
|
||||
|
||||
/* break it up into block sized chunks */
|
||||
while (len + (off % tdb->transaction->block_size) > tdb->transaction->block_size) {
|
||||
tdb1_len_t len2 = tdb->transaction->block_size - (off % tdb->transaction->block_size);
|
||||
while (len + (off % tdb->tdb1.transaction->block_size) > tdb->tdb1.transaction->block_size) {
|
||||
tdb1_len_t len2 = tdb->tdb1.transaction->block_size - (off % tdb->tdb1.transaction->block_size);
|
||||
if (transaction1_write_existing(tdb, off, buf, len2) != 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -335,24 +335,24 @@ static int transaction1_write_existing(struct tdb1_context *tdb, tdb1_off_t off,
|
||||
return 0;
|
||||
}
|
||||
|
||||
blk = off / tdb->transaction->block_size;
|
||||
off = off % tdb->transaction->block_size;
|
||||
blk = off / tdb->tdb1.transaction->block_size;
|
||||
off = off % tdb->tdb1.transaction->block_size;
|
||||
|
||||
if (tdb->transaction->num_blocks <= blk ||
|
||||
tdb->transaction->blocks[blk] == NULL) {
|
||||
if (tdb->tdb1.transaction->num_blocks <= blk ||
|
||||
tdb->tdb1.transaction->blocks[blk] == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (blk == tdb->transaction->num_blocks-1 &&
|
||||
off + len > tdb->transaction->last_block_size) {
|
||||
if (off >= tdb->transaction->last_block_size) {
|
||||
if (blk == tdb->tdb1.transaction->num_blocks-1 &&
|
||||
off + len > tdb->tdb1.transaction->last_block_size) {
|
||||
if (off >= tdb->tdb1.transaction->last_block_size) {
|
||||
return 0;
|
||||
}
|
||||
len = tdb->transaction->last_block_size - off;
|
||||
len = tdb->tdb1.transaction->last_block_size - off;
|
||||
}
|
||||
|
||||
/* overwrite part of an existing block */
|
||||
memcpy(tdb->transaction->blocks[blk] + off, buf, len);
|
||||
memcpy(tdb->tdb1.transaction->blocks[blk] + off, buf, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -361,12 +361,12 @@ static int transaction1_write_existing(struct tdb1_context *tdb, tdb1_off_t off,
|
||||
/*
|
||||
accelerated hash chain head search, using the cached hash heads
|
||||
*/
|
||||
static void transaction1_next_hash_chain(struct tdb1_context *tdb, uint32_t *chain)
|
||||
static void transaction1_next_hash_chain(struct tdb_context *tdb, uint32_t *chain)
|
||||
{
|
||||
uint32_t h = *chain;
|
||||
for (;h < tdb->header.hash_size;h++) {
|
||||
for (;h < tdb->tdb1.header.hash_size;h++) {
|
||||
/* the +1 takes account of the freelist */
|
||||
if (0 != tdb->transaction->hash_heads[h+1]) {
|
||||
if (0 != tdb->tdb1.transaction->hash_heads[h+1]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -376,7 +376,7 @@ static void transaction1_next_hash_chain(struct tdb1_context *tdb, uint32_t *cha
|
||||
/*
|
||||
out of bounds check during a transaction
|
||||
*/
|
||||
static int transaction1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
|
||||
static int transaction1_oob(struct tdb_context *tdb, tdb1_off_t len, int probe)
|
||||
{
|
||||
if (len <= tdb->file->map_size) {
|
||||
return 0;
|
||||
@ -388,7 +388,7 @@ static int transaction1_oob(struct tdb1_context *tdb, tdb1_off_t len, int probe)
|
||||
/*
|
||||
transaction version of tdb1_expand().
|
||||
*/
|
||||
static int transaction1_expand_file(struct tdb1_context *tdb, tdb1_off_t size,
|
||||
static int transaction1_expand_file(struct tdb_context *tdb, tdb1_off_t size,
|
||||
tdb1_off_t addition)
|
||||
{
|
||||
/* add a write to the transaction elements, so subsequent
|
||||
@ -397,7 +397,7 @@ static int transaction1_expand_file(struct tdb1_context *tdb, tdb1_off_t size,
|
||||
return -1;
|
||||
}
|
||||
|
||||
tdb->transaction->expanded = true;
|
||||
tdb->tdb1.transaction->expanded = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -413,12 +413,12 @@ static const struct tdb1_methods transaction1_methods = {
|
||||
|
||||
/*
|
||||
start a tdb transaction. No token is returned, as only a single
|
||||
transaction is allowed to be pending per tdb1_context
|
||||
transaction is allowed to be pending per tdb_context
|
||||
*/
|
||||
static int _tdb1_transaction_start(struct tdb1_context *tdb)
|
||||
static int _tdb1_transaction_start(struct tdb_context *tdb)
|
||||
{
|
||||
/* some sanity checks */
|
||||
if ((tdb->flags & TDB_RDONLY) || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) {
|
||||
if ((tdb->flags & TDB_RDONLY) || (tdb->flags & TDB_INTERNAL) || tdb->tdb1.traverse_read) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
"tdb1_transaction_start: cannot start a"
|
||||
" transaction on a read-only or"
|
||||
@ -427,12 +427,12 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* cope with nested tdb1_transaction_start() calls */
|
||||
if (tdb->transaction != NULL) {
|
||||
if (tdb->tdb1.transaction != NULL) {
|
||||
if (!(tdb->flags & TDB_ALLOW_NESTING)) {
|
||||
tdb->last_error = TDB_ERR_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
tdb->transaction->nesting++;
|
||||
tdb->tdb1.transaction->nesting++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -446,7 +446,7 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tdb->travlocks.next != NULL) {
|
||||
if (tdb->tdb1.travlocks.next != NULL) {
|
||||
/* you cannot use transactions inside a traverse (although you can use
|
||||
traverse inside a transaction) as otherwise you can end up with
|
||||
deadlock */
|
||||
@ -456,22 +456,22 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
|
||||
return -1;
|
||||
}
|
||||
|
||||
tdb->transaction = (struct tdb1_transaction *)
|
||||
tdb->tdb1.transaction = (struct tdb1_transaction *)
|
||||
calloc(sizeof(struct tdb1_transaction), 1);
|
||||
if (tdb->transaction == NULL) {
|
||||
if (tdb->tdb1.transaction == NULL) {
|
||||
tdb->last_error = TDB_ERR_OOM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* a page at a time seems like a reasonable compromise between compactness and efficiency */
|
||||
tdb->transaction->block_size = tdb->page_size;
|
||||
tdb->tdb1.transaction->block_size = tdb->tdb1.page_size;
|
||||
|
||||
/* get the transaction write lock. This is a blocking lock. As
|
||||
discussed with Volker, there are a number of ways we could
|
||||
make this async, which we will probably do in the future */
|
||||
if (tdb1_transaction_lock(tdb, F_WRLCK, TDB_LOCK_WAIT) == -1) {
|
||||
SAFE_FREE(tdb->transaction->blocks);
|
||||
SAFE_FREE(tdb->transaction);
|
||||
SAFE_FREE(tdb->tdb1.transaction->blocks);
|
||||
SAFE_FREE(tdb->tdb1.transaction);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -488,13 +488,13 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
|
||||
|
||||
/* setup a copy of the hash table heads so the hash scan in
|
||||
traverse can be fast */
|
||||
tdb->transaction->hash_heads = (uint32_t *)
|
||||
calloc(tdb->header.hash_size+1, sizeof(uint32_t));
|
||||
if (tdb->transaction->hash_heads == NULL) {
|
||||
tdb->tdb1.transaction->hash_heads = (uint32_t *)
|
||||
calloc(tdb->tdb1.header.hash_size+1, sizeof(uint32_t));
|
||||
if (tdb->tdb1.transaction->hash_heads == NULL) {
|
||||
tdb->last_error = TDB_ERR_OOM;
|
||||
goto fail;
|
||||
}
|
||||
if (tdb->methods->tdb1_read(tdb, TDB1_FREELIST_TOP, tdb->transaction->hash_heads,
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, TDB1_FREELIST_TOP, tdb->tdb1.transaction->hash_heads,
|
||||
TDB1_HASHTABLE_SIZE(tdb), 0) != 0) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_start: failed to read hash heads");
|
||||
@ -503,13 +503,13 @@ static int _tdb1_transaction_start(struct tdb1_context *tdb)
|
||||
|
||||
/* make sure we know about any file expansions already done by
|
||||
anyone else */
|
||||
tdb->methods->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
|
||||
tdb->transaction->old_map_size = tdb->file->map_size;
|
||||
tdb->tdb1.io->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
|
||||
tdb->tdb1.transaction->old_map_size = tdb->file->map_size;
|
||||
|
||||
/* finally hook the io methods, replacing them with
|
||||
transaction specific methods */
|
||||
tdb->transaction->io_methods = tdb->methods;
|
||||
tdb->methods = &transaction1_methods;
|
||||
tdb->tdb1.transaction->io_methods = tdb->tdb1.io;
|
||||
tdb->tdb1.io = &transaction1_methods;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -517,13 +517,13 @@ fail:
|
||||
tdb1_allrecord_unlock(tdb, F_RDLCK);
|
||||
fail_allrecord_lock:
|
||||
tdb1_transaction_unlock(tdb, F_WRLCK);
|
||||
SAFE_FREE(tdb->transaction->blocks);
|
||||
SAFE_FREE(tdb->transaction->hash_heads);
|
||||
SAFE_FREE(tdb->transaction);
|
||||
SAFE_FREE(tdb->tdb1.transaction->blocks);
|
||||
SAFE_FREE(tdb->tdb1.transaction->hash_heads);
|
||||
SAFE_FREE(tdb->tdb1.transaction);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tdb1_transaction_start(struct tdb1_context *tdb)
|
||||
int tdb1_transaction_start(struct tdb_context *tdb)
|
||||
{
|
||||
return _tdb1_transaction_start(tdb);
|
||||
}
|
||||
@ -531,7 +531,7 @@ int tdb1_transaction_start(struct tdb1_context *tdb)
|
||||
/*
|
||||
sync to disk
|
||||
*/
|
||||
static int transaction1_sync(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_len_t length)
|
||||
static int transaction1_sync(struct tdb_context *tdb, tdb1_off_t offset, tdb1_len_t length)
|
||||
{
|
||||
if (tdb->flags & TDB_NOSYNC) {
|
||||
return 0;
|
||||
@ -548,7 +548,7 @@ static int transaction1_sync(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_l
|
||||
}
|
||||
#if HAVE_MMAP
|
||||
if (tdb->file->map_ptr) {
|
||||
tdb1_off_t moffset = offset & ~(tdb->page_size-1);
|
||||
tdb1_off_t moffset = offset & ~(tdb->tdb1.page_size-1);
|
||||
if (msync(moffset + (char *)tdb->file->map_ptr,
|
||||
length + (offset - moffset), MS_SYNC) != 0) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
|
||||
@ -563,40 +563,40 @@ static int transaction1_sync(struct tdb1_context *tdb, tdb1_off_t offset, tdb1_l
|
||||
}
|
||||
|
||||
|
||||
static int _tdb1_transaction_cancel(struct tdb1_context *tdb)
|
||||
static int _tdb1_transaction_cancel(struct tdb_context *tdb)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
if (tdb->transaction == NULL) {
|
||||
if (tdb->tdb1.transaction == NULL) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
"tdb1_transaction_cancel:"
|
||||
" no transaction");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tdb->transaction->nesting != 0) {
|
||||
tdb->transaction->transaction_error = 1;
|
||||
tdb->transaction->nesting--;
|
||||
if (tdb->tdb1.transaction->nesting != 0) {
|
||||
tdb->tdb1.transaction->transaction_error = 1;
|
||||
tdb->tdb1.transaction->nesting--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
tdb->file->map_size = tdb->transaction->old_map_size;
|
||||
tdb->file->map_size = tdb->tdb1.transaction->old_map_size;
|
||||
|
||||
/* free all the transaction blocks */
|
||||
for (i=0;i<tdb->transaction->num_blocks;i++) {
|
||||
if (tdb->transaction->blocks[i] != NULL) {
|
||||
free(tdb->transaction->blocks[i]);
|
||||
for (i=0;i<tdb->tdb1.transaction->num_blocks;i++) {
|
||||
if (tdb->tdb1.transaction->blocks[i] != NULL) {
|
||||
free(tdb->tdb1.transaction->blocks[i]);
|
||||
}
|
||||
}
|
||||
SAFE_FREE(tdb->transaction->blocks);
|
||||
SAFE_FREE(tdb->tdb1.transaction->blocks);
|
||||
|
||||
if (tdb->transaction->magic_offset) {
|
||||
const struct tdb1_methods *methods = tdb->transaction->io_methods;
|
||||
if (tdb->tdb1.transaction->magic_offset) {
|
||||
const struct tdb1_methods *methods = tdb->tdb1.transaction->io_methods;
|
||||
const uint32_t invalid = TDB1_RECOVERY_INVALID_MAGIC;
|
||||
|
||||
/* remove the recovery marker */
|
||||
if (methods->tdb1_write(tdb, tdb->transaction->magic_offset, &invalid, 4) == -1 ||
|
||||
transaction1_sync(tdb, tdb->transaction->magic_offset, 4) == -1) {
|
||||
if (methods->tdb1_write(tdb, tdb->tdb1.transaction->magic_offset, &invalid, 4) == -1 ||
|
||||
transaction1_sync(tdb, tdb->tdb1.transaction->magic_offset, 4) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_cancel: failed to"
|
||||
" remove recovery magic");
|
||||
@ -608,10 +608,10 @@ static int _tdb1_transaction_cancel(struct tdb1_context *tdb)
|
||||
tdb1_release_transaction_locks(tdb);
|
||||
|
||||
/* restore the normal io methods */
|
||||
tdb->methods = tdb->transaction->io_methods;
|
||||
tdb->tdb1.io = tdb->tdb1.transaction->io_methods;
|
||||
|
||||
SAFE_FREE(tdb->transaction->hash_heads);
|
||||
SAFE_FREE(tdb->transaction);
|
||||
SAFE_FREE(tdb->tdb1.transaction->hash_heads);
|
||||
SAFE_FREE(tdb->tdb1.transaction);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -619,7 +619,7 @@ static int _tdb1_transaction_cancel(struct tdb1_context *tdb)
|
||||
/*
|
||||
cancel the current transaction
|
||||
*/
|
||||
int tdb1_transaction_cancel(struct tdb1_context *tdb)
|
||||
int tdb1_transaction_cancel(struct tdb_context *tdb)
|
||||
{
|
||||
return _tdb1_transaction_cancel(tdb);
|
||||
}
|
||||
@ -627,31 +627,31 @@ int tdb1_transaction_cancel(struct tdb1_context *tdb)
|
||||
/*
|
||||
work out how much space the linearised recovery data will consume
|
||||
*/
|
||||
static tdb1_len_t tdb1_recovery_size(struct tdb1_context *tdb)
|
||||
static tdb1_len_t tdb1_recovery_size(struct tdb_context *tdb)
|
||||
{
|
||||
tdb1_len_t recovery_size = 0;
|
||||
int i;
|
||||
|
||||
recovery_size = sizeof(uint32_t);
|
||||
for (i=0;i<tdb->transaction->num_blocks;i++) {
|
||||
if (i * tdb->transaction->block_size >= tdb->transaction->old_map_size) {
|
||||
for (i=0;i<tdb->tdb1.transaction->num_blocks;i++) {
|
||||
if (i * tdb->tdb1.transaction->block_size >= tdb->tdb1.transaction->old_map_size) {
|
||||
break;
|
||||
}
|
||||
if (tdb->transaction->blocks[i] == NULL) {
|
||||
if (tdb->tdb1.transaction->blocks[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
recovery_size += 2*sizeof(tdb1_off_t);
|
||||
if (i == tdb->transaction->num_blocks-1) {
|
||||
recovery_size += tdb->transaction->last_block_size;
|
||||
if (i == tdb->tdb1.transaction->num_blocks-1) {
|
||||
recovery_size += tdb->tdb1.transaction->last_block_size;
|
||||
} else {
|
||||
recovery_size += tdb->transaction->block_size;
|
||||
recovery_size += tdb->tdb1.transaction->block_size;
|
||||
}
|
||||
}
|
||||
|
||||
return recovery_size;
|
||||
}
|
||||
|
||||
int tdb1_recovery_area(struct tdb1_context *tdb,
|
||||
int tdb1_recovery_area(struct tdb_context *tdb,
|
||||
const struct tdb1_methods *methods,
|
||||
tdb1_off_t *recovery_offset,
|
||||
struct tdb1_record *rec)
|
||||
@ -683,13 +683,13 @@ int tdb1_recovery_area(struct tdb1_context *tdb,
|
||||
allocate the recovery area, or use an existing recovery area if it is
|
||||
large enough
|
||||
*/
|
||||
static int tdb1_recovery_allocate(struct tdb1_context *tdb,
|
||||
static int tdb1_recovery_allocate(struct tdb_context *tdb,
|
||||
tdb1_len_t *recovery_size,
|
||||
tdb1_off_t *recovery_offset,
|
||||
tdb1_len_t *recovery_max_size)
|
||||
{
|
||||
struct tdb1_record rec;
|
||||
const struct tdb1_methods *methods = tdb->transaction->io_methods;
|
||||
const struct tdb1_methods *methods = tdb->tdb1.transaction->io_methods;
|
||||
tdb1_off_t recovery_head;
|
||||
|
||||
if (tdb1_recovery_area(tdb, methods, &recovery_head, &rec) == -1) {
|
||||
@ -726,12 +726,13 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb,
|
||||
*recovery_size = tdb1_recovery_size(tdb);
|
||||
|
||||
/* round up to a multiple of page size */
|
||||
*recovery_max_size = TDB1_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec);
|
||||
*recovery_max_size = TDB1_ALIGN(sizeof(rec) + *recovery_size,
|
||||
tdb->tdb1.page_size) - sizeof(rec);
|
||||
*recovery_offset = tdb->file->map_size;
|
||||
recovery_head = *recovery_offset;
|
||||
|
||||
if (methods->tdb1_expand_file(tdb, tdb->transaction->old_map_size,
|
||||
(tdb->file->map_size - tdb->transaction->old_map_size) +
|
||||
if (methods->tdb1_expand_file(tdb, tdb->tdb1.transaction->old_map_size,
|
||||
(tdb->file->map_size - tdb->tdb1.transaction->old_map_size) +
|
||||
sizeof(rec) + *recovery_max_size) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_recovery_allocate:"
|
||||
@ -744,7 +745,7 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb,
|
||||
|
||||
/* we have to reset the old map size so that we don't try to expand the file
|
||||
again in the transaction commit, which would destroy the recovery area */
|
||||
tdb->transaction->old_map_size = tdb->file->map_size;
|
||||
tdb->tdb1.transaction->old_map_size = tdb->file->map_size;
|
||||
|
||||
/* write the recovery header offset and sync - we can sync without a race here
|
||||
as the magic ptr in the recovery record has not been set */
|
||||
@ -770,15 +771,15 @@ static int tdb1_recovery_allocate(struct tdb1_context *tdb,
|
||||
/*
|
||||
setup the recovery data that will be used on a crash during commit
|
||||
*/
|
||||
static int transaction1_setup_recovery(struct tdb1_context *tdb,
|
||||
static int transaction1_setup_recovery(struct tdb_context *tdb,
|
||||
tdb1_off_t *magic_offset)
|
||||
{
|
||||
tdb1_len_t recovery_size;
|
||||
unsigned char *data, *p;
|
||||
const struct tdb1_methods *methods = tdb->transaction->io_methods;
|
||||
const struct tdb1_methods *methods = tdb->tdb1.transaction->io_methods;
|
||||
struct tdb1_record *rec;
|
||||
tdb1_off_t recovery_offset, recovery_max_size;
|
||||
tdb1_off_t old_map_size = tdb->transaction->old_map_size;
|
||||
tdb1_off_t old_map_size = tdb->tdb1.transaction->old_map_size;
|
||||
uint32_t magic, tailer;
|
||||
int i;
|
||||
|
||||
@ -808,24 +809,24 @@ static int transaction1_setup_recovery(struct tdb1_context *tdb,
|
||||
/* build the recovery data into a single blob to allow us to do a single
|
||||
large write, which should be more efficient */
|
||||
p = data + sizeof(*rec);
|
||||
for (i=0;i<tdb->transaction->num_blocks;i++) {
|
||||
for (i=0;i<tdb->tdb1.transaction->num_blocks;i++) {
|
||||
tdb1_off_t offset;
|
||||
tdb1_len_t length;
|
||||
|
||||
if (tdb->transaction->blocks[i] == NULL) {
|
||||
if (tdb->tdb1.transaction->blocks[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = i * tdb->transaction->block_size;
|
||||
length = tdb->transaction->block_size;
|
||||
if (i == tdb->transaction->num_blocks-1) {
|
||||
length = tdb->transaction->last_block_size;
|
||||
offset = i * tdb->tdb1.transaction->block_size;
|
||||
length = tdb->tdb1.transaction->block_size;
|
||||
if (i == tdb->tdb1.transaction->num_blocks-1) {
|
||||
length = tdb->tdb1.transaction->last_block_size;
|
||||
}
|
||||
|
||||
if (offset >= old_map_size) {
|
||||
continue;
|
||||
}
|
||||
if (offset + length > tdb->transaction->old_map_size) {
|
||||
if (offset + length > tdb->tdb1.transaction->old_map_size) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
|
||||
TDB_LOG_ERROR,
|
||||
"tdb1_transaction_setup_recovery: transaction data over new region boundary");
|
||||
@ -907,18 +908,18 @@ static int transaction1_setup_recovery(struct tdb1_context *tdb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
|
||||
static int _tdb1_transaction_prepare_commit(struct tdb_context *tdb)
|
||||
{
|
||||
const struct tdb1_methods *methods;
|
||||
|
||||
if (tdb->transaction == NULL) {
|
||||
if (tdb->tdb1.transaction == NULL) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
"tdb1_transaction_prepare_commit:"
|
||||
" no transaction");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tdb->transaction->prepared) {
|
||||
if (tdb->tdb1.transaction->prepared) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
"tdb1_transaction_prepare_commit:"
|
||||
" transaction already prepared");
|
||||
@ -926,7 +927,7 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tdb->transaction->transaction_error) {
|
||||
if (tdb->tdb1.transaction->transaction_error) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_prepare_commit:"
|
||||
" transaction error pending");
|
||||
@ -935,16 +936,16 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
|
||||
if (tdb->transaction->nesting != 0) {
|
||||
if (tdb->tdb1.transaction->nesting != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for a null transaction */
|
||||
if (tdb->transaction->blocks == NULL) {
|
||||
if (tdb->tdb1.transaction->blocks == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
methods = tdb->transaction->io_methods;
|
||||
methods = tdb->tdb1.transaction->io_methods;
|
||||
|
||||
/* if there are any locks pending then the caller has not
|
||||
nested their locks properly, so fail the transaction */
|
||||
@ -979,7 +980,7 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
|
||||
|
||||
if (!(tdb->flags & TDB_NOSYNC)) {
|
||||
/* write the recovery data to the end of the file */
|
||||
if (transaction1_setup_recovery(tdb, &tdb->transaction->magic_offset) == -1) {
|
||||
if (transaction1_setup_recovery(tdb, &tdb->tdb1.transaction->magic_offset) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_prepare_commit:"
|
||||
" failed to setup recovery data");
|
||||
@ -987,19 +988,19 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
|
||||
}
|
||||
}
|
||||
|
||||
tdb->transaction->prepared = true;
|
||||
tdb->tdb1.transaction->prepared = true;
|
||||
|
||||
/* expand the file to the new size if needed */
|
||||
if (tdb->file->map_size != tdb->transaction->old_map_size) {
|
||||
if (methods->tdb1_expand_file(tdb, tdb->transaction->old_map_size,
|
||||
if (tdb->file->map_size != tdb->tdb1.transaction->old_map_size) {
|
||||
if (methods->tdb1_expand_file(tdb, tdb->tdb1.transaction->old_map_size,
|
||||
tdb->file->map_size -
|
||||
tdb->transaction->old_map_size) == -1) {
|
||||
tdb->tdb1.transaction->old_map_size) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_prepare_commit:"
|
||||
" expansion failed");
|
||||
return -1;
|
||||
}
|
||||
tdb->file->map_size = tdb->transaction->old_map_size;
|
||||
tdb->file->map_size = tdb->tdb1.transaction->old_map_size;
|
||||
methods->tdb1_oob(tdb, tdb->file->map_size + 1, 1);
|
||||
}
|
||||
|
||||
@ -1011,13 +1012,13 @@ static int _tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
|
||||
/*
|
||||
prepare to commit the current transaction
|
||||
*/
|
||||
int tdb1_transaction_prepare_commit(struct tdb1_context *tdb)
|
||||
int tdb1_transaction_prepare_commit(struct tdb_context *tdb)
|
||||
{
|
||||
return _tdb1_transaction_prepare_commit(tdb);
|
||||
}
|
||||
|
||||
/* A repack is worthwhile if the largest is less than half total free. */
|
||||
static bool repack_worthwhile(struct tdb1_context *tdb)
|
||||
static bool repack_worthwhile(struct tdb_context *tdb)
|
||||
{
|
||||
tdb1_off_t ptr;
|
||||
struct tdb1_record rec;
|
||||
@ -1041,20 +1042,20 @@ static bool repack_worthwhile(struct tdb1_context *tdb)
|
||||
/*
|
||||
commit the current transaction
|
||||
*/
|
||||
int tdb1_transaction_commit(struct tdb1_context *tdb)
|
||||
int tdb1_transaction_commit(struct tdb_context *tdb)
|
||||
{
|
||||
const struct tdb1_methods *methods;
|
||||
int i;
|
||||
bool need_repack = false;
|
||||
|
||||
if (tdb->transaction == NULL) {
|
||||
if (tdb->tdb1.transaction == NULL) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
"tdb1_transaction_commit:"
|
||||
" no transaction");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tdb->transaction->transaction_error) {
|
||||
if (tdb->tdb1.transaction->transaction_error) {
|
||||
tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_commit:"
|
||||
" transaction error pending");
|
||||
@ -1063,18 +1064,18 @@ int tdb1_transaction_commit(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
|
||||
if (tdb->transaction->nesting != 0) {
|
||||
tdb->transaction->nesting--;
|
||||
if (tdb->tdb1.transaction->nesting != 0) {
|
||||
tdb->tdb1.transaction->nesting--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for a null transaction */
|
||||
if (tdb->transaction->blocks == NULL) {
|
||||
if (tdb->tdb1.transaction->blocks == NULL) {
|
||||
_tdb1_transaction_cancel(tdb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!tdb->transaction->prepared) {
|
||||
if (!tdb->tdb1.transaction->prepared) {
|
||||
int ret = _tdb1_transaction_prepare_commit(tdb);
|
||||
if (ret) {
|
||||
_tdb1_transaction_cancel(tdb);
|
||||
@ -1082,24 +1083,24 @@ int tdb1_transaction_commit(struct tdb1_context *tdb)
|
||||
}
|
||||
}
|
||||
|
||||
methods = tdb->transaction->io_methods;
|
||||
methods = tdb->tdb1.transaction->io_methods;
|
||||
|
||||
/* perform all the writes */
|
||||
for (i=0;i<tdb->transaction->num_blocks;i++) {
|
||||
for (i=0;i<tdb->tdb1.transaction->num_blocks;i++) {
|
||||
tdb1_off_t offset;
|
||||
tdb1_len_t length;
|
||||
|
||||
if (tdb->transaction->blocks[i] == NULL) {
|
||||
if (tdb->tdb1.transaction->blocks[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = i * tdb->transaction->block_size;
|
||||
length = tdb->transaction->block_size;
|
||||
if (i == tdb->transaction->num_blocks-1) {
|
||||
length = tdb->transaction->last_block_size;
|
||||
offset = i * tdb->tdb1.transaction->block_size;
|
||||
length = tdb->tdb1.transaction->block_size;
|
||||
if (i == tdb->tdb1.transaction->num_blocks-1) {
|
||||
length = tdb->tdb1.transaction->last_block_size;
|
||||
}
|
||||
|
||||
if (methods->tdb1_write(tdb, offset, tdb->transaction->blocks[i], length) == -1) {
|
||||
if (methods->tdb1_write(tdb, offset, tdb->tdb1.transaction->blocks[i], length) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_commit:"
|
||||
" write failed during commit");
|
||||
@ -1107,7 +1108,7 @@ int tdb1_transaction_commit(struct tdb1_context *tdb)
|
||||
/* we've overwritten part of the data and
|
||||
possibly expanded the file, so we need to
|
||||
run the crash recovery code */
|
||||
tdb->methods = methods;
|
||||
tdb->tdb1.io = methods;
|
||||
tdb1_transaction_recover(tdb);
|
||||
|
||||
_tdb1_transaction_cancel(tdb);
|
||||
@ -1116,16 +1117,16 @@ int tdb1_transaction_commit(struct tdb1_context *tdb)
|
||||
"tdb1_transaction_commit: write failed");
|
||||
return -1;
|
||||
}
|
||||
SAFE_FREE(tdb->transaction->blocks[i]);
|
||||
SAFE_FREE(tdb->tdb1.transaction->blocks[i]);
|
||||
}
|
||||
|
||||
/* Do this before we drop lock or blocks. */
|
||||
if (tdb->transaction->expanded) {
|
||||
if (tdb->tdb1.transaction->expanded) {
|
||||
need_repack = repack_worthwhile(tdb);
|
||||
}
|
||||
|
||||
SAFE_FREE(tdb->transaction->blocks);
|
||||
tdb->transaction->num_blocks = 0;
|
||||
SAFE_FREE(tdb->tdb1.transaction->blocks);
|
||||
tdb->tdb1.transaction->num_blocks = 0;
|
||||
|
||||
/* ensure the new data is on disk */
|
||||
if (transaction1_sync(tdb, 0, tdb->file->map_size) == -1) {
|
||||
@ -1164,7 +1165,7 @@ int tdb1_transaction_commit(struct tdb1_context *tdb)
|
||||
database write access already established (including the open
|
||||
lock to prevent new processes attaching)
|
||||
*/
|
||||
int tdb1_transaction_recover(struct tdb1_context *tdb)
|
||||
int tdb1_transaction_recover(struct tdb_context *tdb)
|
||||
{
|
||||
tdb1_off_t recovery_head, recovery_eof;
|
||||
unsigned char *data, *p;
|
||||
@ -1185,7 +1186,7 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* read the recovery record */
|
||||
if (tdb->methods->tdb1_read(tdb, recovery_head, &rec,
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, recovery_head, &rec,
|
||||
sizeof(rec), TDB1_DOCONV()) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_recover:"
|
||||
@ -1217,7 +1218,7 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* read the full recovery data */
|
||||
if (tdb->methods->tdb1_read(tdb, recovery_head + sizeof(rec), data,
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, recovery_head + sizeof(rec), data,
|
||||
rec.data_len, 0) == -1) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_recover:"
|
||||
@ -1235,7 +1236,7 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
|
||||
memcpy(&ofs, p, 4);
|
||||
memcpy(&len, p+4, 4);
|
||||
|
||||
if (tdb->methods->tdb1_write(tdb, ofs, p+8, len) == -1) {
|
||||
if (tdb->tdb1.io->tdb1_write(tdb, ofs, p+8, len) == -1) {
|
||||
free(data);
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_transaction_recover: failed to recover"
|
||||
@ -1288,7 +1289,7 @@ int tdb1_transaction_recover(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* Any I/O failures we say "needs recovery". */
|
||||
bool tdb1_needs_recovery(struct tdb1_context *tdb)
|
||||
bool tdb1_needs_recovery(struct tdb_context *tdb)
|
||||
{
|
||||
tdb1_off_t recovery_head;
|
||||
struct tdb1_record rec;
|
||||
@ -1304,7 +1305,7 @@ bool tdb1_needs_recovery(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* read the recovery record */
|
||||
if (tdb->methods->tdb1_read(tdb, recovery_head, &rec,
|
||||
if (tdb->tdb1.io->tdb1_read(tdb, recovery_head, &rec,
|
||||
sizeof(rec), TDB1_DOCONV()) == -1) {
|
||||
return true;
|
||||
}
|
||||
|
@ -31,13 +31,13 @@
|
||||
|
||||
/* Uses traverse lock: 0 = finish, TDB1_NEXT_LOCK_ERR = error,
|
||||
other = record offset */
|
||||
static tdb1_off_t tdb1_next_lock(struct tdb1_context *tdb, struct tdb1_traverse_lock *tlock,
|
||||
static tdb1_off_t tdb1_next_lock(struct tdb_context *tdb, struct tdb1_traverse_lock *tlock,
|
||||
struct tdb1_record *rec)
|
||||
{
|
||||
int want_next = (tlock->off != 0);
|
||||
|
||||
/* Lock each chain from the start one. */
|
||||
for (; tlock->hash < tdb->header.hash_size; tlock->hash++) {
|
||||
for (; tlock->hash < tdb->tdb1.header.hash_size; tlock->hash++) {
|
||||
if (!tlock->off && tlock->hash != 0) {
|
||||
/* this is an optimisation for the common case where
|
||||
the hash chain is empty, which is particularly
|
||||
@ -67,8 +67,8 @@ static tdb1_off_t tdb1_next_lock(struct tdb1_context *tdb, struct tdb1_traverse_
|
||||
factor of around 80 in speed on a linux 2.6.x
|
||||
system (testing using ldbtest).
|
||||
*/
|
||||
tdb->methods->next_hash_chain(tdb, &tlock->hash);
|
||||
if (tlock->hash == tdb->header.hash_size) {
|
||||
tdb->tdb1.io->next_hash_chain(tdb, &tlock->hash);
|
||||
if (tlock->hash == tdb->tdb1.header.hash_size) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -119,7 +119,7 @@ static tdb1_off_t tdb1_next_lock(struct tdb1_context *tdb, struct tdb1_traverse_
|
||||
/* Try to clean dead ones from old traverses */
|
||||
current = tlock->off;
|
||||
tlock->off = rec->next;
|
||||
if (!((tdb->flags & TDB_RDONLY) || tdb->traverse_read) &&
|
||||
if (!((tdb->flags & TDB_RDONLY) || tdb->tdb1.traverse_read) &&
|
||||
tdb1_do_delete(tdb, current, rec) != 0)
|
||||
goto fail;
|
||||
}
|
||||
@ -143,7 +143,7 @@ static tdb1_off_t tdb1_next_lock(struct tdb1_context *tdb, struct tdb1_traverse_
|
||||
if fn is NULL then it is not called
|
||||
a non-zero return value from fn() indicates that the traversal should stop
|
||||
*/
|
||||
static int tdb1_traverse_internal(struct tdb1_context *tdb,
|
||||
static int tdb1_traverse_internal(struct tdb_context *tdb,
|
||||
tdb1_traverse_func fn, void *private_data,
|
||||
struct tdb1_traverse_lock *tl)
|
||||
{
|
||||
@ -155,10 +155,10 @@ static int tdb1_traverse_internal(struct tdb1_context *tdb,
|
||||
/* This was in the initializaton, above, but the IRIX compiler
|
||||
* did not like it. crh
|
||||
*/
|
||||
tl->next = tdb->travlocks.next;
|
||||
tl->next = tdb->tdb1.travlocks.next;
|
||||
|
||||
/* fcntl locks don't stack: beware traverse inside traverse */
|
||||
tdb->travlocks.next = tl;
|
||||
tdb->tdb1.travlocks.next = tl;
|
||||
|
||||
/* tdb1_next_lock places locks on the record returned, and its chain */
|
||||
while ((off = tdb1_next_lock(tdb, tl, &rec)) != 0) {
|
||||
@ -204,7 +204,7 @@ static int tdb1_traverse_internal(struct tdb1_context *tdb,
|
||||
SAFE_FREE(key.dptr);
|
||||
}
|
||||
out:
|
||||
tdb->travlocks.next = tl->next;
|
||||
tdb->tdb1.travlocks.next = tl->next;
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
else
|
||||
@ -215,7 +215,7 @@ out:
|
||||
/*
|
||||
a write style traverse - temporarily marks the db read only
|
||||
*/
|
||||
int tdb1_traverse_read(struct tdb1_context *tdb,
|
||||
int tdb1_traverse_read(struct tdb_context *tdb,
|
||||
tdb1_traverse_func fn, void *private_data)
|
||||
{
|
||||
struct tdb1_traverse_lock tl = { NULL, 0, 0, F_RDLCK };
|
||||
@ -227,9 +227,9 @@ int tdb1_traverse_read(struct tdb1_context *tdb,
|
||||
return -1;
|
||||
}
|
||||
|
||||
tdb->traverse_read++;
|
||||
tdb->tdb1.traverse_read++;
|
||||
ret = tdb1_traverse_internal(tdb, fn, private_data, &tl);
|
||||
tdb->traverse_read--;
|
||||
tdb->tdb1.traverse_read--;
|
||||
|
||||
tdb1_transaction_unlock(tdb, F_RDLCK);
|
||||
|
||||
@ -243,13 +243,13 @@ int tdb1_traverse_read(struct tdb1_context *tdb,
|
||||
WARNING: The data buffer given to the callback fn does NOT meet the
|
||||
alignment restrictions malloc gives you.
|
||||
*/
|
||||
int tdb1_traverse(struct tdb1_context *tdb,
|
||||
int tdb1_traverse(struct tdb_context *tdb,
|
||||
tdb1_traverse_func fn, void *private_data)
|
||||
{
|
||||
struct tdb1_traverse_lock tl = { NULL, 0, 0, F_WRLCK };
|
||||
int ret;
|
||||
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->traverse_read) {
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->tdb1.traverse_read) {
|
||||
return tdb1_traverse_read(tdb, fn, private_data);
|
||||
}
|
||||
|
||||
@ -257,9 +257,9 @@ int tdb1_traverse(struct tdb1_context *tdb,
|
||||
return -1;
|
||||
}
|
||||
|
||||
tdb->traverse_write++;
|
||||
tdb->tdb1.traverse_write++;
|
||||
ret = tdb1_traverse_internal(tdb, fn, private_data, &tl);
|
||||
tdb->traverse_write--;
|
||||
tdb->tdb1.traverse_write--;
|
||||
|
||||
tdb1_transaction_unlock(tdb, F_WRLCK);
|
||||
|
||||
@ -268,29 +268,29 @@ int tdb1_traverse(struct tdb1_context *tdb,
|
||||
|
||||
|
||||
/* find the first entry in the database and return its key */
|
||||
TDB_DATA tdb1_firstkey(struct tdb1_context *tdb)
|
||||
TDB_DATA tdb1_firstkey(struct tdb_context *tdb)
|
||||
{
|
||||
TDB_DATA key;
|
||||
struct tdb1_record rec;
|
||||
tdb1_off_t off;
|
||||
|
||||
/* release any old lock */
|
||||
if (tdb1_unlock_record(tdb, tdb->travlocks.off) != 0)
|
||||
if (tdb1_unlock_record(tdb, tdb->tdb1.travlocks.off) != 0)
|
||||
return tdb1_null;
|
||||
tdb->travlocks.off = tdb->travlocks.hash = 0;
|
||||
tdb->travlocks.lock_rw = F_RDLCK;
|
||||
tdb->tdb1.travlocks.off = tdb->tdb1.travlocks.hash = 0;
|
||||
tdb->tdb1.travlocks.lock_rw = F_RDLCK;
|
||||
|
||||
/* Grab first record: locks chain and returned record. */
|
||||
off = tdb1_next_lock(tdb, &tdb->travlocks, &rec);
|
||||
off = tdb1_next_lock(tdb, &tdb->tdb1.travlocks, &rec);
|
||||
if (off == 0 || off == TDB1_NEXT_LOCK_ERR) {
|
||||
return tdb1_null;
|
||||
}
|
||||
/* now read the key */
|
||||
key.dsize = rec.key_len;
|
||||
key.dptr =tdb1_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize);
|
||||
key.dptr =tdb1_alloc_read(tdb,tdb->tdb1.travlocks.off+sizeof(rec),key.dsize);
|
||||
|
||||
/* Unlock the hash chain of the record we just read. */
|
||||
if (tdb1_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
|
||||
if (tdb1_unlock(tdb, tdb->tdb1.travlocks.hash, tdb->tdb1.travlocks.lock_rw) != 0)
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_firstkey:"
|
||||
" error occurred while tdb1_unlocking!");
|
||||
@ -298,7 +298,7 @@ TDB_DATA tdb1_firstkey(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* find the next entry in the database, returning its key */
|
||||
TDB_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB_DATA oldkey)
|
||||
TDB_DATA tdb1_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
|
||||
{
|
||||
uint32_t oldhash;
|
||||
TDB_DATA key = tdb1_null;
|
||||
@ -307,58 +307,58 @@ TDB_DATA tdb1_nextkey(struct tdb1_context *tdb, TDB_DATA oldkey)
|
||||
tdb1_off_t off;
|
||||
|
||||
/* Is locked key the old key? If so, traverse will be reliable. */
|
||||
if (tdb->travlocks.off) {
|
||||
if (tdb1_lock(tdb,tdb->travlocks.hash,tdb->travlocks.lock_rw))
|
||||
if (tdb->tdb1.travlocks.off) {
|
||||
if (tdb1_lock(tdb,tdb->tdb1.travlocks.hash,tdb->tdb1.travlocks.lock_rw))
|
||||
return tdb1_null;
|
||||
if (tdb1_rec_read(tdb, tdb->travlocks.off, &rec) == -1
|
||||
|| !(k = tdb1_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),
|
||||
if (tdb1_rec_read(tdb, tdb->tdb1.travlocks.off, &rec) == -1
|
||||
|| !(k = tdb1_alloc_read(tdb,tdb->tdb1.travlocks.off+sizeof(rec),
|
||||
rec.key_len))
|
||||
|| memcmp(k, oldkey.dptr, oldkey.dsize) != 0) {
|
||||
/* No, it wasn't: unlock it and start from scratch */
|
||||
if (tdb1_unlock_record(tdb, tdb->travlocks.off) != 0) {
|
||||
if (tdb1_unlock_record(tdb, tdb->tdb1.travlocks.off) != 0) {
|
||||
SAFE_FREE(k);
|
||||
return tdb1_null;
|
||||
}
|
||||
if (tdb1_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) {
|
||||
if (tdb1_unlock(tdb, tdb->tdb1.travlocks.hash, tdb->tdb1.travlocks.lock_rw) != 0) {
|
||||
SAFE_FREE(k);
|
||||
return tdb1_null;
|
||||
}
|
||||
tdb->travlocks.off = 0;
|
||||
tdb->tdb1.travlocks.off = 0;
|
||||
}
|
||||
|
||||
SAFE_FREE(k);
|
||||
}
|
||||
|
||||
if (!tdb->travlocks.off) {
|
||||
if (!tdb->tdb1.travlocks.off) {
|
||||
/* No previous element: do normal find, and lock record */
|
||||
tdb->travlocks.off = tdb1_find_lock_hash(tdb, oldkey, tdb_hash(tdb, oldkey.dptr, oldkey.dsize), tdb->travlocks.lock_rw, &rec);
|
||||
if (!tdb->travlocks.off) {
|
||||
tdb->tdb1.travlocks.off = tdb1_find_lock_hash(tdb, oldkey, tdb_hash(tdb, oldkey.dptr, oldkey.dsize), tdb->tdb1.travlocks.lock_rw, &rec);
|
||||
if (!tdb->tdb1.travlocks.off) {
|
||||
return tdb1_null;
|
||||
}
|
||||
tdb->travlocks.hash = TDB1_BUCKET(rec.full_hash);
|
||||
if (tdb1_lock_record(tdb, tdb->travlocks.off) != 0) {
|
||||
tdb->tdb1.travlocks.hash = TDB1_BUCKET(rec.full_hash);
|
||||
if (tdb1_lock_record(tdb, tdb->tdb1.travlocks.off) != 0) {
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_nextkey: lock_record failed (%s)!",
|
||||
strerror(errno));
|
||||
return tdb1_null;
|
||||
}
|
||||
}
|
||||
oldhash = tdb->travlocks.hash;
|
||||
oldhash = tdb->tdb1.travlocks.hash;
|
||||
|
||||
/* Grab next record: locks chain and returned record,
|
||||
unlocks old record */
|
||||
off = tdb1_next_lock(tdb, &tdb->travlocks, &rec);
|
||||
off = tdb1_next_lock(tdb, &tdb->tdb1.travlocks, &rec);
|
||||
if (off != TDB1_NEXT_LOCK_ERR && off != 0) {
|
||||
key.dsize = rec.key_len;
|
||||
key.dptr = tdb1_alloc_read(tdb, tdb->travlocks.off+sizeof(rec),
|
||||
key.dptr = tdb1_alloc_read(tdb, tdb->tdb1.travlocks.off+sizeof(rec),
|
||||
key.dsize);
|
||||
/* Unlock the chain of this new record */
|
||||
if (tdb1_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0)
|
||||
if (tdb1_unlock(tdb, tdb->tdb1.travlocks.hash, tdb->tdb1.travlocks.lock_rw) != 0)
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_nextkey: WARNING tdb1_unlock failed!");
|
||||
}
|
||||
/* Unlock the chain of old record */
|
||||
if (tdb1_unlock(tdb, TDB1_BUCKET(oldhash), tdb->travlocks.lock_rw) != 0)
|
||||
if (tdb1_unlock(tdb, TDB1_BUCKET(oldhash), tdb->tdb1.travlocks.lock_rw) != 0)
|
||||
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
|
||||
"tdb1_nextkey: WARNING tdb1_unlock failed!");
|
||||
return key;
|
||||
|
@ -147,8 +147,8 @@ static void add_to_freetable(struct tdb_context *tdb,
|
||||
unsigned ftable,
|
||||
struct tle_freetable *freetable)
|
||||
{
|
||||
tdb->ftable_off = freetable->base.off;
|
||||
tdb->ftable = ftable;
|
||||
tdb->tdb2.ftable_off = freetable->base.off;
|
||||
tdb->tdb2.ftable = ftable;
|
||||
add_free_record(tdb, eoff, sizeof(struct tdb_used_record) + elen,
|
||||
TDB_LOCK_WAIT, false);
|
||||
}
|
||||
@ -312,7 +312,7 @@ struct tdb_context *tdb_layout_get(struct tdb_layout *layout)
|
||||
}
|
||||
}
|
||||
|
||||
tdb->ftable_off = find_ftable(layout, 0)->base.off;
|
||||
tdb->tdb2.ftable_off = find_ftable(layout, 0)->base.off;
|
||||
|
||||
/* Get physical if they asked for it. */
|
||||
if (layout->filename) {
|
||||
|
@ -41,7 +41,7 @@ int main(int argc, char *argv[])
|
||||
ok1(free_record_length(tdb, layout->elem[1].base.off) == len);
|
||||
|
||||
/* Figure out which bucket free entry is. */
|
||||
b_off = bucket_off(tdb->ftable_off, size_to_bucket(len));
|
||||
b_off = bucket_off(tdb->tdb2.ftable_off, size_to_bucket(len));
|
||||
/* Lock and fail to coalesce. */
|
||||
ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
|
||||
test = layout->elem[1].base.off;
|
||||
@ -64,7 +64,7 @@ int main(int argc, char *argv[])
|
||||
ok1(tdb_check(tdb, NULL, NULL) == 0);
|
||||
|
||||
/* Figure out which bucket free entry is. */
|
||||
b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024));
|
||||
b_off = bucket_off(tdb->tdb2.ftable_off, size_to_bucket(1024));
|
||||
/* Lock and fail to coalesce. */
|
||||
ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
|
||||
test = layout->elem[1].base.off;
|
||||
@ -88,7 +88,7 @@ int main(int argc, char *argv[])
|
||||
ok1(tdb_check(tdb, NULL, NULL) == 0);
|
||||
|
||||
/* Figure out which bucket (first) free entry is. */
|
||||
b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024));
|
||||
b_off = bucket_off(tdb->tdb2.ftable_off, size_to_bucket(1024));
|
||||
/* Lock and coalesce. */
|
||||
ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
|
||||
test = layout->elem[2].base.off;
|
||||
@ -115,7 +115,7 @@ int main(int argc, char *argv[])
|
||||
ok1(tdb_check(tdb, NULL, NULL) == 0);
|
||||
|
||||
/* Figure out which bucket free entry is. */
|
||||
b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024));
|
||||
b_off = bucket_off(tdb->tdb2.ftable_off, size_to_bucket(1024));
|
||||
/* Lock and coalesce. */
|
||||
ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
|
||||
test = layout->elem[2].base.off;
|
||||
@ -142,7 +142,7 @@ int main(int argc, char *argv[])
|
||||
ok1(tdb_check(tdb, NULL, NULL) == 0);
|
||||
|
||||
/* Figure out which bucket free entry is. */
|
||||
b_off = bucket_off(tdb->ftable_off, size_to_bucket(1024));
|
||||
b_off = bucket_off(tdb->tdb2.ftable_off, size_to_bucket(1024));
|
||||
/* Lock and coalesce. */
|
||||
ok1(tdb_lock_free_bucket(tdb, b_off, TDB_LOCK_WAIT) == 0);
|
||||
test = layout->elem[2].base.off;
|
||||
|
@ -68,9 +68,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Make sure we fill it in for later finding. */
|
||||
off = new_off + sizeof(struct tdb_used_record);
|
||||
ok1(!tdb->methods->twrite(tdb, off, key.dptr, key.dsize));
|
||||
ok1(!tdb->tdb2.io->twrite(tdb, off, key.dptr, key.dsize));
|
||||
off += key.dsize;
|
||||
ok1(!tdb->methods->twrite(tdb, off, dbuf.dptr, dbuf.dsize));
|
||||
ok1(!tdb->tdb2.io->twrite(tdb, off, dbuf.dptr, dbuf.dsize));
|
||||
|
||||
/* We should be able to unlock that OK. */
|
||||
ok1(tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range,
|
||||
@ -228,9 +228,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* Make sure we fill it in for later finding. */
|
||||
off = new_off + sizeof(struct tdb_used_record);
|
||||
ok1(!tdb->methods->twrite(tdb, off, key.dptr, key.dsize));
|
||||
ok1(!tdb->tdb2.io->twrite(tdb, off, key.dptr, key.dsize));
|
||||
off += key.dsize;
|
||||
ok1(!tdb->methods->twrite(tdb, off, dbuf.dptr, dbuf.dsize));
|
||||
ok1(!tdb->tdb2.io->twrite(tdb, off, dbuf.dptr, dbuf.dsize));
|
||||
|
||||
/* We should be able to unlock that OK. */
|
||||
ok1(tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range,
|
||||
|
@ -9,7 +9,7 @@ static bool empty_freetable(struct tdb_context *tdb)
|
||||
unsigned int i;
|
||||
|
||||
/* Now, free table should be completely exhausted in zone 0 */
|
||||
if (tdb_read_convert(tdb, tdb->ftable_off, &ftab, sizeof(ftab)) != 0)
|
||||
if (tdb_read_convert(tdb, tdb->tdb2.ftable_off, &ftab, sizeof(ftab)) != 0)
|
||||
abort();
|
||||
|
||||
for (i = 0; i < sizeof(ftab.buckets)/sizeof(ftab.buckets[0]); i++) {
|
||||
|
@ -35,22 +35,22 @@ int main(int argc, char *argv[])
|
||||
off = get_free(tdb, 0, 80 - sizeof(struct tdb_used_record), 0,
|
||||
TDB_USED_MAGIC, 0);
|
||||
ok1(off == layout->elem[3].base.off);
|
||||
ok1(tdb->ftable_off == layout->elem[0].base.off);
|
||||
ok1(tdb->tdb2.ftable_off == layout->elem[0].base.off);
|
||||
|
||||
off = get_free(tdb, 0, 160 - sizeof(struct tdb_used_record), 0,
|
||||
TDB_USED_MAGIC, 0);
|
||||
ok1(off == layout->elem[5].base.off);
|
||||
ok1(tdb->ftable_off == layout->elem[1].base.off);
|
||||
ok1(tdb->tdb2.ftable_off == layout->elem[1].base.off);
|
||||
|
||||
off = get_free(tdb, 0, 320 - sizeof(struct tdb_used_record), 0,
|
||||
TDB_USED_MAGIC, 0);
|
||||
ok1(off == layout->elem[7].base.off);
|
||||
ok1(tdb->ftable_off == layout->elem[2].base.off);
|
||||
ok1(tdb->tdb2.ftable_off == layout->elem[2].base.off);
|
||||
|
||||
off = get_free(tdb, 0, 40 - sizeof(struct tdb_used_record), 0,
|
||||
TDB_USED_MAGIC, 0);
|
||||
ok1(off == layout->elem[9].base.off);
|
||||
ok1(tdb->ftable_off == layout->elem[0].base.off);
|
||||
ok1(tdb->tdb2.ftable_off == layout->elem[0].base.off);
|
||||
|
||||
/* Now we fail. */
|
||||
off = get_free(tdb, 0, 0, 1, TDB_USED_MAGIC, 0);
|
||||
|
@ -6,11 +6,11 @@
|
||||
#include <err.h>
|
||||
#include "tdb1-logging.h"
|
||||
|
||||
static int tdb1_expand_file_sparse(struct tdb1_context *tdb,
|
||||
static int tdb1_expand_file_sparse(struct tdb_context *tdb,
|
||||
tdb1_off_t size,
|
||||
tdb1_off_t addition)
|
||||
{
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->traverse_read) {
|
||||
if ((tdb->flags & TDB_RDONLY) || tdb->tdb1.traverse_read) {
|
||||
tdb->last_error = TDB_ERR_RDONLY;
|
||||
return -1;
|
||||
}
|
||||
@ -46,7 +46,7 @@ static const struct tdb1_methods large_io_methods = {
|
||||
tdb1_expand_file_sparse
|
||||
};
|
||||
|
||||
static int test_traverse(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
static int test_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
void *_data)
|
||||
{
|
||||
TDB_DATA *expect = _data;
|
||||
@ -59,7 +59,7 @@ static int test_traverse(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, orig_data, data;
|
||||
uint32_t hash;
|
||||
tdb1_off_t rec_ptr;
|
||||
@ -70,7 +70,7 @@ int main(int argc, char *argv[])
|
||||
O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);
|
||||
|
||||
ok1(tdb);
|
||||
tdb->methods = &large_io_methods;
|
||||
tdb->tdb1.io = &large_io_methods;
|
||||
|
||||
/* Enlarge the file (internally multiplies by 2). */
|
||||
ok1(tdb1_expand(tdb, 1500000000) == 0);
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
struct tdb1_header hdr;
|
||||
int fd;
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, data;
|
||||
|
||||
plan_tests(13);
|
||||
|
@ -23,7 +23,7 @@ static int check(TDB_DATA key, TDB_DATA data, void *private)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tdb1_flip_bit(struct tdb1_context *tdb, unsigned int bit)
|
||||
static void tdb1_flip_bit(struct tdb_context *tdb, unsigned int bit)
|
||||
{
|
||||
unsigned int off = bit / CHAR_BIT;
|
||||
unsigned char mask = (1 << (bit % CHAR_BIT));
|
||||
@ -40,7 +40,7 @@ static void tdb1_flip_bit(struct tdb1_context *tdb, unsigned int bit)
|
||||
}
|
||||
}
|
||||
|
||||
static void check_test(struct tdb1_context *tdb)
|
||||
static void check_test(struct tdb_context *tdb)
|
||||
{
|
||||
TDB_DATA key, data;
|
||||
unsigned int i, verifiable, corrupt, sizes[2], dsize, ksize;
|
||||
@ -93,7 +93,7 @@ static void check_test(struct tdb1_context *tdb)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
|
||||
plan_tests(4);
|
||||
/* This should use mmap. */
|
||||
|
@ -81,7 +81,7 @@ static int ftruncate_check(int fd, off_t length)
|
||||
|
||||
static bool test_death(enum operation op, struct agent *agent)
|
||||
{
|
||||
struct tdb1_context *tdb = NULL;
|
||||
struct tdb_context *tdb = NULL;
|
||||
TDB_DATA key;
|
||||
enum agent_return ret;
|
||||
int needed_recovery = 0;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, data;
|
||||
|
||||
plan_tests(13);
|
||||
|
@ -9,7 +9,7 @@ static uint64_t tdb1_dumb_hash(const void *key, size_t len, uint64_t seed,
|
||||
return len;
|
||||
}
|
||||
|
||||
static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level,
|
||||
static void log_fn(struct tdb_context *tdb, enum tdb_log_level level,
|
||||
enum TDB_ERROR ecode, const char *message, void *priv)
|
||||
{
|
||||
unsigned int *count = priv;
|
||||
@ -46,7 +46,7 @@ static uint64_t old_hash(const void *key, size_t len, uint64_t seed,
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
unsigned int log_count, flags;
|
||||
TDB_DATA d;
|
||||
struct tdb1_logging_context log_ctx = { log_fn, &log_count };
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, data;
|
||||
|
||||
plan_tests(27);
|
||||
|
@ -23,7 +23,7 @@ static bool correct_data(TDB_DATA data)
|
||||
&& memcmp(data.dptr, "world", data.dsize) == 0;
|
||||
}
|
||||
|
||||
static int traverse2(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
static int traverse2(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
void *p)
|
||||
{
|
||||
ok1(correct_key(key));
|
||||
@ -31,7 +31,7 @@ static int traverse2(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int traverse1(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
static int traverse1(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
void *p)
|
||||
{
|
||||
ok1(correct_key(key));
|
||||
@ -48,7 +48,7 @@ static int traverse1(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, data;
|
||||
|
||||
plan_tests(17);
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
#define NUM_ENTRIES 10
|
||||
|
||||
static bool prepare_entries(struct tdb1_context *tdb)
|
||||
static bool prepare_entries(struct tdb_context *tdb)
|
||||
{
|
||||
unsigned int i;
|
||||
TDB_DATA key, data;
|
||||
@ -31,7 +31,7 @@ static bool prepare_entries(struct tdb1_context *tdb)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void delete_entries(struct tdb1_context *tdb)
|
||||
static void delete_entries(struct tdb_context *tdb)
|
||||
{
|
||||
unsigned int i;
|
||||
TDB_DATA key;
|
||||
@ -45,7 +45,7 @@ static void delete_entries(struct tdb1_context *tdb)
|
||||
}
|
||||
|
||||
/* We don't know how many times this will run. */
|
||||
static int delete_other(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
static int delete_other(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
void *private_data)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -57,7 +57,7 @@ static int delete_other(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int delete_self(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
static int delete_self(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
void *private_data)
|
||||
{
|
||||
ok1(tdb1_delete(tdb, key) == 0);
|
||||
@ -66,7 +66,7 @@ static int delete_self(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
int errors = 0;
|
||||
|
||||
plan_tests(41);
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
|
||||
plan_tests(8);
|
||||
|
||||
|
@ -131,7 +131,7 @@ int main(int argc, char *argv[])
|
||||
const int flags[] = { TDB_DEFAULT,
|
||||
TDB_NOMMAP };
|
||||
int i;
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, data;
|
||||
|
||||
plan_tests(10);
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, data;
|
||||
|
||||
plan_tests(11);
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <err.h>
|
||||
|
||||
static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level,
|
||||
static void log_fn(struct tdb_context *tdb, enum tdb_log_level level,
|
||||
enum TDB_ERROR ecode, const char *message, void *priv)
|
||||
{
|
||||
unsigned int *count = priv;
|
||||
@ -14,7 +14,7 @@ static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level,
|
||||
/* The code should barf on TDBs created with rwlocks. */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
unsigned int log_count;
|
||||
struct tdb1_logging_context log_ctx = { log_fn, &log_count };
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned int i, j;
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
int flags[] = { TDB_INTERNAL, TDB_DEFAULT, TDB_NOMMAP,
|
||||
TDB_INTERNAL|TDB_CONVERT, TDB_CONVERT,
|
||||
TDB_NOMMAP|TDB_CONVERT };
|
||||
|
@ -24,7 +24,7 @@ static bool correct_data(TDB_DATA data)
|
||||
&& memcmp(data.dptr, "world", data.dsize) == 0;
|
||||
}
|
||||
|
||||
static int traverse(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
static int traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
void *p)
|
||||
{
|
||||
ok1(correct_key(key));
|
||||
@ -34,7 +34,7 @@ static int traverse(struct tdb1_context *tdb, TDB_DATA key, TDB_DATA data,
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, data;
|
||||
|
||||
plan_tests(13);
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <err.h>
|
||||
|
||||
static void log_fn(struct tdb1_context *tdb, enum tdb_log_level level,
|
||||
static void log_fn(struct tdb_context *tdb, enum tdb_log_level level,
|
||||
enum TDB_ERROR ecode, const char *message, void *priv)
|
||||
{
|
||||
unsigned int *count = priv;
|
||||
@ -27,7 +27,7 @@ static uint64_t old_hash(const void *key, size_t len, uint64_t seed,
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
unsigned int log_count;
|
||||
TDB_DATA d;
|
||||
struct tdb1_logging_context log_ctx = { log_fn, &log_count };
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, data;
|
||||
|
||||
plan_tests(4);
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct tdb1_context *tdb;
|
||||
struct tdb_context *tdb;
|
||||
TDB_DATA key, data;
|
||||
|
||||
plan_tests(10);
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static struct tdb1_context *tdb;
|
||||
static struct tdb_context *tdb;
|
||||
|
||||
static enum agent_return do_operation(enum operation op, const char *name)
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* Turn log messages into tap diag messages. */
|
||||
static void taplog(struct tdb1_context *tdb,
|
||||
static void taplog(struct tdb_context *tdb,
|
||||
enum tdb_log_level level,
|
||||
enum TDB_ERROR ecode,
|
||||
const char *message,
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
|
||||
#define SAFE_FREE(x) do { if ((x) != NULL) {free((void *)x); (x)=NULL;} } while(0)
|
||||
|
||||
/*
|
||||
transaction design:
|
||||
@ -151,10 +151,10 @@ static enum TDB_ERROR transaction_read(struct tdb_context *tdb, tdb_off_t off,
|
||||
blk = off / PAGESIZE;
|
||||
|
||||
/* see if we have it in the block list */
|
||||
if (tdb->transaction->num_blocks <= blk ||
|
||||
tdb->transaction->blocks[blk] == NULL) {
|
||||
if (tdb->tdb2.transaction->num_blocks <= blk ||
|
||||
tdb->tdb2.transaction->blocks[blk] == NULL) {
|
||||
/* nope, do a real read */
|
||||
ecode = tdb->transaction->io_methods->tread(tdb, off, buf, len);
|
||||
ecode = tdb->tdb2.transaction->io_methods->tread(tdb, off, buf, len);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
goto fail;
|
||||
}
|
||||
@ -162,19 +162,19 @@ static enum TDB_ERROR transaction_read(struct tdb_context *tdb, tdb_off_t off,
|
||||
}
|
||||
|
||||
/* it is in the block list. Now check for the last block */
|
||||
if (blk == tdb->transaction->num_blocks-1) {
|
||||
if (len > tdb->transaction->last_block_size) {
|
||||
if (blk == tdb->tdb2.transaction->num_blocks-1) {
|
||||
if (len > tdb->tdb2.transaction->last_block_size) {
|
||||
ecode = TDB_ERR_IO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* now copy it out of this block */
|
||||
memcpy(buf, tdb->transaction->blocks[blk] + (off % PAGESIZE), len);
|
||||
memcpy(buf, tdb->tdb2.transaction->blocks[blk] + (off % PAGESIZE), len);
|
||||
return TDB_SUCCESS;
|
||||
|
||||
fail:
|
||||
tdb->transaction->transaction_error = 1;
|
||||
tdb->tdb2.transaction->transaction_error = 1;
|
||||
return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
|
||||
"transaction_read: failed at off=%zu len=%zu",
|
||||
(size_t)off, (size_t)len);
|
||||
@ -191,7 +191,7 @@ static enum TDB_ERROR transaction_write(struct tdb_context *tdb, tdb_off_t off,
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
/* Only a commit is allowed on a prepared transaction */
|
||||
if (tdb->transaction->prepared) {
|
||||
if (tdb->tdb2.transaction->prepared) {
|
||||
ecode = tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_ERROR,
|
||||
"transaction_write: transaction already"
|
||||
" prepared, write not allowed");
|
||||
@ -219,15 +219,15 @@ static enum TDB_ERROR transaction_write(struct tdb_context *tdb, tdb_off_t off,
|
||||
blk = off / PAGESIZE;
|
||||
off = off % PAGESIZE;
|
||||
|
||||
if (tdb->transaction->num_blocks <= blk) {
|
||||
if (tdb->tdb2.transaction->num_blocks <= blk) {
|
||||
uint8_t **new_blocks;
|
||||
/* expand the blocks array */
|
||||
if (tdb->transaction->blocks == NULL) {
|
||||
if (tdb->tdb2.transaction->blocks == NULL) {
|
||||
new_blocks = (uint8_t **)malloc(
|
||||
(blk+1)*sizeof(uint8_t *));
|
||||
} else {
|
||||
new_blocks = (uint8_t **)realloc(
|
||||
tdb->transaction->blocks,
|
||||
tdb->tdb2.transaction->blocks,
|
||||
(blk+1)*sizeof(uint8_t *));
|
||||
}
|
||||
if (new_blocks == NULL) {
|
||||
@ -236,30 +236,30 @@ static enum TDB_ERROR transaction_write(struct tdb_context *tdb, tdb_off_t off,
|
||||
" failed to allocate");
|
||||
goto fail;
|
||||
}
|
||||
memset(&new_blocks[tdb->transaction->num_blocks], 0,
|
||||
(1+(blk - tdb->transaction->num_blocks))*sizeof(uint8_t *));
|
||||
tdb->transaction->blocks = new_blocks;
|
||||
tdb->transaction->num_blocks = blk+1;
|
||||
tdb->transaction->last_block_size = 0;
|
||||
memset(&new_blocks[tdb->tdb2.transaction->num_blocks], 0,
|
||||
(1+(blk - tdb->tdb2.transaction->num_blocks))*sizeof(uint8_t *));
|
||||
tdb->tdb2.transaction->blocks = new_blocks;
|
||||
tdb->tdb2.transaction->num_blocks = blk+1;
|
||||
tdb->tdb2.transaction->last_block_size = 0;
|
||||
}
|
||||
|
||||
/* allocate and fill a block? */
|
||||
if (tdb->transaction->blocks[blk] == NULL) {
|
||||
tdb->transaction->blocks[blk] = (uint8_t *)calloc(PAGESIZE, 1);
|
||||
if (tdb->transaction->blocks[blk] == NULL) {
|
||||
if (tdb->tdb2.transaction->blocks[blk] == NULL) {
|
||||
tdb->tdb2.transaction->blocks[blk] = (uint8_t *)calloc(PAGESIZE, 1);
|
||||
if (tdb->tdb2.transaction->blocks[blk] == NULL) {
|
||||
ecode = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
|
||||
"transaction_write:"
|
||||
" failed to allocate");
|
||||
goto fail;
|
||||
}
|
||||
if (tdb->transaction->old_map_size > blk * PAGESIZE) {
|
||||
if (tdb->tdb2.transaction->old_map_size > blk * PAGESIZE) {
|
||||
tdb_len_t len2 = PAGESIZE;
|
||||
if (len2 + (blk * PAGESIZE) > tdb->transaction->old_map_size) {
|
||||
len2 = tdb->transaction->old_map_size - (blk * PAGESIZE);
|
||||
if (len2 + (blk * PAGESIZE) > tdb->tdb2.transaction->old_map_size) {
|
||||
len2 = tdb->tdb2.transaction->old_map_size - (blk * PAGESIZE);
|
||||
}
|
||||
ecode = tdb->transaction->io_methods->tread(tdb,
|
||||
ecode = tdb->tdb2.transaction->io_methods->tread(tdb,
|
||||
blk * PAGESIZE,
|
||||
tdb->transaction->blocks[blk],
|
||||
tdb->tdb2.transaction->blocks[blk],
|
||||
len2);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
ecode = tdb_logerr(tdb, ecode,
|
||||
@ -268,31 +268,31 @@ static enum TDB_ERROR transaction_write(struct tdb_context *tdb, tdb_off_t off,
|
||||
" failed to"
|
||||
" read old block: %s",
|
||||
strerror(errno));
|
||||
SAFE_FREE(tdb->transaction->blocks[blk]);
|
||||
SAFE_FREE(tdb->tdb2.transaction->blocks[blk]);
|
||||
goto fail;
|
||||
}
|
||||
if (blk == tdb->transaction->num_blocks-1) {
|
||||
tdb->transaction->last_block_size = len2;
|
||||
if (blk == tdb->tdb2.transaction->num_blocks-1) {
|
||||
tdb->tdb2.transaction->last_block_size = len2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* overwrite part of an existing block */
|
||||
if (buf == NULL) {
|
||||
memset(tdb->transaction->blocks[blk] + off, 0, len);
|
||||
memset(tdb->tdb2.transaction->blocks[blk] + off, 0, len);
|
||||
} else {
|
||||
memcpy(tdb->transaction->blocks[blk] + off, buf, len);
|
||||
memcpy(tdb->tdb2.transaction->blocks[blk] + off, buf, len);
|
||||
}
|
||||
if (blk == tdb->transaction->num_blocks-1) {
|
||||
if (len + off > tdb->transaction->last_block_size) {
|
||||
tdb->transaction->last_block_size = len + off;
|
||||
if (blk == tdb->tdb2.transaction->num_blocks-1) {
|
||||
if (len + off > tdb->tdb2.transaction->last_block_size) {
|
||||
tdb->tdb2.transaction->last_block_size = len + off;
|
||||
}
|
||||
}
|
||||
|
||||
return TDB_SUCCESS;
|
||||
|
||||
fail:
|
||||
tdb->transaction->transaction_error = 1;
|
||||
tdb->tdb2.transaction->transaction_error = 1;
|
||||
return ecode;
|
||||
}
|
||||
|
||||
@ -324,21 +324,21 @@ static void transaction_write_existing(struct tdb_context *tdb, tdb_off_t off,
|
||||
blk = off / PAGESIZE;
|
||||
off = off % PAGESIZE;
|
||||
|
||||
if (tdb->transaction->num_blocks <= blk ||
|
||||
tdb->transaction->blocks[blk] == NULL) {
|
||||
if (tdb->tdb2.transaction->num_blocks <= blk ||
|
||||
tdb->tdb2.transaction->blocks[blk] == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (blk == tdb->transaction->num_blocks-1 &&
|
||||
off + len > tdb->transaction->last_block_size) {
|
||||
if (off >= tdb->transaction->last_block_size) {
|
||||
if (blk == tdb->tdb2.transaction->num_blocks-1 &&
|
||||
off + len > tdb->tdb2.transaction->last_block_size) {
|
||||
if (off >= tdb->tdb2.transaction->last_block_size) {
|
||||
return;
|
||||
}
|
||||
len = tdb->transaction->last_block_size - off;
|
||||
len = tdb->tdb2.transaction->last_block_size - off;
|
||||
}
|
||||
|
||||
/* overwrite part of an existing block */
|
||||
memcpy(tdb->transaction->blocks[blk] + off, buf, len);
|
||||
memcpy(tdb->tdb2.transaction->blocks[blk] + off, buf, len);
|
||||
}
|
||||
|
||||
|
||||
@ -388,32 +388,32 @@ static void *transaction_direct(struct tdb_context *tdb, tdb_off_t off,
|
||||
if (write_mode) {
|
||||
tdb->stats.transaction_write_direct++;
|
||||
if (blk != end_blk
|
||||
|| blk >= tdb->transaction->num_blocks
|
||||
|| tdb->transaction->blocks[blk] == NULL) {
|
||||
|| blk >= tdb->tdb2.transaction->num_blocks
|
||||
|| tdb->tdb2.transaction->blocks[blk] == NULL) {
|
||||
tdb->stats.transaction_write_direct_fail++;
|
||||
return NULL;
|
||||
}
|
||||
return tdb->transaction->blocks[blk] + off % PAGESIZE;
|
||||
return tdb->tdb2.transaction->blocks[blk] + off % PAGESIZE;
|
||||
}
|
||||
|
||||
tdb->stats.transaction_read_direct++;
|
||||
/* Single which we have copied? */
|
||||
if (blk == end_blk
|
||||
&& blk < tdb->transaction->num_blocks
|
||||
&& tdb->transaction->blocks[blk])
|
||||
return tdb->transaction->blocks[blk] + off % PAGESIZE;
|
||||
&& blk < tdb->tdb2.transaction->num_blocks
|
||||
&& tdb->tdb2.transaction->blocks[blk])
|
||||
return tdb->tdb2.transaction->blocks[blk] + off % PAGESIZE;
|
||||
|
||||
/* Otherwise must be all not copied. */
|
||||
while (blk <= end_blk) {
|
||||
if (blk >= tdb->transaction->num_blocks)
|
||||
if (blk >= tdb->tdb2.transaction->num_blocks)
|
||||
break;
|
||||
if (tdb->transaction->blocks[blk]) {
|
||||
if (tdb->tdb2.transaction->blocks[blk]) {
|
||||
tdb->stats.transaction_read_direct_fail++;
|
||||
return NULL;
|
||||
}
|
||||
blk++;
|
||||
}
|
||||
return tdb->transaction->io_methods->direct(tdb, off, len, false);
|
||||
return tdb->tdb2.transaction->io_methods->direct(tdb, off, len, false);
|
||||
}
|
||||
|
||||
static const struct tdb_methods transaction_methods = {
|
||||
@ -459,38 +459,38 @@ static void _tdb_transaction_cancel(struct tdb_context *tdb)
|
||||
int i;
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
if (tdb->transaction == NULL) {
|
||||
if (tdb->tdb2.transaction == NULL) {
|
||||
tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
"tdb_transaction_cancel: no transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tdb->transaction->nesting != 0) {
|
||||
tdb->transaction->transaction_error = 1;
|
||||
tdb->transaction->nesting--;
|
||||
if (tdb->tdb2.transaction->nesting != 0) {
|
||||
tdb->tdb2.transaction->transaction_error = 1;
|
||||
tdb->tdb2.transaction->nesting--;
|
||||
return;
|
||||
}
|
||||
|
||||
tdb->file->map_size = tdb->transaction->old_map_size;
|
||||
tdb->file->map_size = tdb->tdb2.transaction->old_map_size;
|
||||
|
||||
/* free all the transaction blocks */
|
||||
for (i=0;i<tdb->transaction->num_blocks;i++) {
|
||||
if (tdb->transaction->blocks[i] != NULL) {
|
||||
free(tdb->transaction->blocks[i]);
|
||||
for (i=0;i<tdb->tdb2.transaction->num_blocks;i++) {
|
||||
if (tdb->tdb2.transaction->blocks[i] != NULL) {
|
||||
free(tdb->tdb2.transaction->blocks[i]);
|
||||
}
|
||||
}
|
||||
SAFE_FREE(tdb->transaction->blocks);
|
||||
SAFE_FREE(tdb->tdb2.transaction->blocks);
|
||||
|
||||
if (tdb->transaction->magic_offset) {
|
||||
const struct tdb_methods *methods = tdb->transaction->io_methods;
|
||||
if (tdb->tdb2.transaction->magic_offset) {
|
||||
const struct tdb_methods *methods = tdb->tdb2.transaction->io_methods;
|
||||
uint64_t invalid = TDB_RECOVERY_INVALID_MAGIC;
|
||||
|
||||
/* remove the recovery marker */
|
||||
ecode = methods->twrite(tdb, tdb->transaction->magic_offset,
|
||||
ecode = methods->twrite(tdb, tdb->tdb2.transaction->magic_offset,
|
||||
&invalid, sizeof(invalid));
|
||||
if (ecode == TDB_SUCCESS)
|
||||
ecode = transaction_sync(tdb,
|
||||
tdb->transaction->magic_offset,
|
||||
tdb->tdb2.transaction->magic_offset,
|
||||
sizeof(invalid));
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
|
||||
@ -503,14 +503,14 @@ static void _tdb_transaction_cancel(struct tdb_context *tdb)
|
||||
tdb_allrecord_unlock(tdb, tdb->file->allrecord_lock.ltype);
|
||||
|
||||
/* restore the normal io methods */
|
||||
tdb->methods = tdb->transaction->io_methods;
|
||||
tdb->tdb2.io = tdb->tdb2.transaction->io_methods;
|
||||
|
||||
tdb_transaction_unlock(tdb, F_WRLCK);
|
||||
|
||||
if (tdb_has_open_lock(tdb))
|
||||
tdb_unlock_open(tdb, F_WRLCK);
|
||||
|
||||
SAFE_FREE(tdb->transaction);
|
||||
SAFE_FREE(tdb->tdb2.transaction);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -542,7 +542,7 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
|
||||
}
|
||||
|
||||
/* cope with nested tdb_transaction_start() calls */
|
||||
if (tdb->transaction != NULL) {
|
||||
if (tdb->tdb2.transaction != NULL) {
|
||||
if (!(tdb->flags & TDB_ALLOW_NESTING)) {
|
||||
return tdb->last_error
|
||||
= tdb_logerr(tdb, TDB_ERR_IO,
|
||||
@ -550,7 +550,7 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
|
||||
"tdb_transaction_start:"
|
||||
" already inside transaction");
|
||||
}
|
||||
tdb->transaction->nesting++;
|
||||
tdb->tdb2.transaction->nesting++;
|
||||
tdb->stats.transaction_nest++;
|
||||
return 0;
|
||||
}
|
||||
@ -567,9 +567,9 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
|
||||
" held");
|
||||
}
|
||||
|
||||
tdb->transaction = (struct tdb_transaction *)
|
||||
tdb->tdb2.transaction = (struct tdb_transaction *)
|
||||
calloc(sizeof(struct tdb_transaction), 1);
|
||||
if (tdb->transaction == NULL) {
|
||||
if (tdb->tdb2.transaction == NULL) {
|
||||
return tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM,
|
||||
TDB_LOG_ERROR,
|
||||
"tdb_transaction_start:"
|
||||
@ -581,8 +581,8 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
|
||||
make this async, which we will probably do in the future */
|
||||
ecode = tdb_transaction_lock(tdb, F_WRLCK);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
SAFE_FREE(tdb->transaction->blocks);
|
||||
SAFE_FREE(tdb->transaction);
|
||||
SAFE_FREE(tdb->tdb2.transaction->blocks);
|
||||
SAFE_FREE(tdb->tdb2.transaction);
|
||||
return tdb->last_error = ecode;
|
||||
}
|
||||
|
||||
@ -595,19 +595,19 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
|
||||
|
||||
/* make sure we know about any file expansions already done by
|
||||
anyone else */
|
||||
tdb->methods->oob(tdb, tdb->file->map_size + 1, true);
|
||||
tdb->transaction->old_map_size = tdb->file->map_size;
|
||||
tdb->tdb2.io->oob(tdb, tdb->file->map_size + 1, true);
|
||||
tdb->tdb2.transaction->old_map_size = tdb->file->map_size;
|
||||
|
||||
/* finally hook the io methods, replacing them with
|
||||
transaction specific methods */
|
||||
tdb->transaction->io_methods = tdb->methods;
|
||||
tdb->methods = &transaction_methods;
|
||||
tdb->tdb2.transaction->io_methods = tdb->tdb2.io;
|
||||
tdb->tdb2.io = &transaction_methods;
|
||||
return tdb->last_error = TDB_SUCCESS;
|
||||
|
||||
fail_allrecord_lock:
|
||||
tdb_transaction_unlock(tdb, F_WRLCK);
|
||||
SAFE_FREE(tdb->transaction->blocks);
|
||||
SAFE_FREE(tdb->transaction);
|
||||
SAFE_FREE(tdb->tdb2.transaction->blocks);
|
||||
SAFE_FREE(tdb->tdb2.transaction);
|
||||
return tdb->last_error = ecode;
|
||||
}
|
||||
|
||||
@ -630,16 +630,16 @@ static tdb_len_t tdb_recovery_size(struct tdb_context *tdb)
|
||||
int i;
|
||||
|
||||
recovery_size = 0;
|
||||
for (i=0;i<tdb->transaction->num_blocks;i++) {
|
||||
if (i * PAGESIZE >= tdb->transaction->old_map_size) {
|
||||
for (i=0;i<tdb->tdb2.transaction->num_blocks;i++) {
|
||||
if (i * PAGESIZE >= tdb->tdb2.transaction->old_map_size) {
|
||||
break;
|
||||
}
|
||||
if (tdb->transaction->blocks[i] == NULL) {
|
||||
if (tdb->tdb2.transaction->blocks[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
recovery_size += 2*sizeof(tdb_off_t);
|
||||
if (i == tdb->transaction->num_blocks-1) {
|
||||
recovery_size += tdb->transaction->last_block_size;
|
||||
if (i == tdb->tdb2.transaction->num_blocks-1) {
|
||||
recovery_size += tdb->tdb2.transaction->last_block_size;
|
||||
} else {
|
||||
recovery_size += PAGESIZE;
|
||||
}
|
||||
@ -726,7 +726,7 @@ static struct tdb_recovery_record *alloc_recovery(struct tdb_context *tdb,
|
||||
size_t i;
|
||||
enum TDB_ERROR ecode;
|
||||
unsigned char *p;
|
||||
const struct tdb_methods *old_methods = tdb->methods;
|
||||
const struct tdb_methods *old_methods = tdb->tdb2.io;
|
||||
|
||||
rec = malloc(sizeof(*rec) + tdb_recovery_size(tdb));
|
||||
if (!rec) {
|
||||
@ -738,28 +738,28 @@ static struct tdb_recovery_record *alloc_recovery(struct tdb_context *tdb,
|
||||
|
||||
/* We temporarily revert to the old I/O methods, so we can use
|
||||
* tdb_access_read */
|
||||
tdb->methods = tdb->transaction->io_methods;
|
||||
tdb->tdb2.io = tdb->tdb2.transaction->io_methods;
|
||||
|
||||
/* build the recovery data into a single blob to allow us to do a single
|
||||
large write, which should be more efficient */
|
||||
p = (unsigned char *)(rec + 1);
|
||||
for (i=0;i<tdb->transaction->num_blocks;i++) {
|
||||
for (i=0;i<tdb->tdb2.transaction->num_blocks;i++) {
|
||||
tdb_off_t offset;
|
||||
tdb_len_t length;
|
||||
unsigned int off;
|
||||
const unsigned char *buffer;
|
||||
|
||||
if (tdb->transaction->blocks[i] == NULL) {
|
||||
if (tdb->tdb2.transaction->blocks[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = i * PAGESIZE;
|
||||
length = PAGESIZE;
|
||||
if (i == tdb->transaction->num_blocks-1) {
|
||||
length = tdb->transaction->last_block_size;
|
||||
if (i == tdb->tdb2.transaction->num_blocks-1) {
|
||||
length = tdb->tdb2.transaction->last_block_size;
|
||||
}
|
||||
|
||||
if (offset >= tdb->transaction->old_map_size) {
|
||||
if (offset >= tdb->tdb2.transaction->old_map_size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -770,9 +770,9 @@ static struct tdb_recovery_record *alloc_recovery(struct tdb_context *tdb,
|
||||
" boundary");
|
||||
goto fail;
|
||||
}
|
||||
if (offset + length > tdb->transaction->old_map_size) {
|
||||
if (offset + length > tdb->tdb2.transaction->old_map_size) {
|
||||
/* Short read at EOF. */
|
||||
length = tdb->transaction->old_map_size - offset;
|
||||
length = tdb->tdb2.transaction->old_map_size - offset;
|
||||
}
|
||||
buffer = tdb_access_read(tdb, offset, length, false);
|
||||
if (TDB_PTR_IS_ERR(buffer)) {
|
||||
@ -781,14 +781,14 @@ static struct tdb_recovery_record *alloc_recovery(struct tdb_context *tdb,
|
||||
}
|
||||
|
||||
/* Skip over anything the same at the start. */
|
||||
off = same(tdb->transaction->blocks[i], buffer, length);
|
||||
off = same(tdb->tdb2.transaction->blocks[i], buffer, length);
|
||||
offset += off;
|
||||
|
||||
while (off < length) {
|
||||
tdb_len_t len;
|
||||
unsigned int samelen;
|
||||
|
||||
len = different(tdb->transaction->blocks[i] + off,
|
||||
len = different(tdb->tdb2.transaction->blocks[i] + off,
|
||||
buffer + off, length - off,
|
||||
sizeof(offset) + sizeof(len) + 1,
|
||||
&samelen);
|
||||
@ -806,12 +806,12 @@ static struct tdb_recovery_record *alloc_recovery(struct tdb_context *tdb,
|
||||
}
|
||||
|
||||
*len = p - (unsigned char *)(rec + 1);
|
||||
tdb->methods = old_methods;
|
||||
tdb->tdb2.io = old_methods;
|
||||
return rec;
|
||||
|
||||
fail:
|
||||
free(rec);
|
||||
tdb->methods = old_methods;
|
||||
tdb->tdb2.io = old_methods;
|
||||
return TDB_ERR_PTR(ecode);
|
||||
}
|
||||
|
||||
@ -822,7 +822,7 @@ static tdb_off_t create_recovery_area(struct tdb_context *tdb,
|
||||
tdb_off_t off, recovery_off;
|
||||
tdb_len_t addition;
|
||||
enum TDB_ERROR ecode;
|
||||
const struct tdb_methods *methods = tdb->transaction->io_methods;
|
||||
const struct tdb_methods *methods = tdb->tdb2.transaction->io_methods;
|
||||
|
||||
/* round up to a multiple of page size. Overallocate, since each
|
||||
* such allocation forces us to expand the file. */
|
||||
@ -836,9 +836,9 @@ static tdb_off_t create_recovery_area(struct tdb_context *tdb,
|
||||
Also so that we don't try to expand the file again in the
|
||||
transaction commit, which would destroy the recovery
|
||||
area */
|
||||
addition = (tdb->file->map_size - tdb->transaction->old_map_size) +
|
||||
addition = (tdb->file->map_size - tdb->tdb2.transaction->old_map_size) +
|
||||
sizeof(*rec) + rec->max_len;
|
||||
tdb->file->map_size = tdb->transaction->old_map_size;
|
||||
tdb->file->map_size = tdb->tdb2.transaction->old_map_size;
|
||||
tdb->stats.transaction_expand_file++;
|
||||
ecode = methods->expand_file(tdb, addition);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
@ -850,7 +850,7 @@ static tdb_off_t create_recovery_area(struct tdb_context *tdb,
|
||||
/* we have to reset the old map size so that we don't try to
|
||||
expand the file again in the transaction commit, which
|
||||
would destroy the recovery area */
|
||||
tdb->transaction->old_map_size = tdb->file->map_size;
|
||||
tdb->tdb2.transaction->old_map_size = tdb->file->map_size;
|
||||
|
||||
/* write the recovery header offset and sync - we can sync without a race here
|
||||
as the magic ptr in the recovery record has not been set */
|
||||
@ -876,9 +876,9 @@ static enum TDB_ERROR transaction_setup_recovery(struct tdb_context *tdb)
|
||||
{
|
||||
tdb_len_t recovery_size = 0;
|
||||
tdb_off_t recovery_off = 0;
|
||||
tdb_off_t old_map_size = tdb->transaction->old_map_size;
|
||||
tdb_off_t old_map_size = tdb->tdb2.transaction->old_map_size;
|
||||
struct tdb_recovery_record *recovery;
|
||||
const struct tdb_methods *methods = tdb->transaction->io_methods;
|
||||
const struct tdb_methods *methods = tdb->tdb2.transaction->io_methods;
|
||||
uint64_t magic;
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
@ -950,21 +950,21 @@ static enum TDB_ERROR transaction_setup_recovery(struct tdb_context *tdb)
|
||||
magic = TDB_RECOVERY_MAGIC;
|
||||
tdb_convert(tdb, &magic, sizeof(magic));
|
||||
|
||||
tdb->transaction->magic_offset
|
||||
tdb->tdb2.transaction->magic_offset
|
||||
= recovery_off + offsetof(struct tdb_recovery_record, magic);
|
||||
|
||||
ecode = methods->twrite(tdb, tdb->transaction->magic_offset,
|
||||
ecode = methods->twrite(tdb, tdb->tdb2.transaction->magic_offset,
|
||||
&magic, sizeof(magic));
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
|
||||
"tdb_transaction_setup_recovery:"
|
||||
" failed to write recovery magic");
|
||||
}
|
||||
transaction_write_existing(tdb, tdb->transaction->magic_offset,
|
||||
transaction_write_existing(tdb, tdb->tdb2.transaction->magic_offset,
|
||||
&magic, sizeof(magic));
|
||||
|
||||
/* ensure the recovery magic marker is on disk */
|
||||
return transaction_sync(tdb, tdb->transaction->magic_offset,
|
||||
return transaction_sync(tdb, tdb->tdb2.transaction->magic_offset,
|
||||
sizeof(magic));
|
||||
}
|
||||
|
||||
@ -973,20 +973,20 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb)
|
||||
const struct tdb_methods *methods;
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
if (tdb->transaction == NULL) {
|
||||
if (tdb->tdb2.transaction == NULL) {
|
||||
return tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
"tdb_transaction_prepare_commit:"
|
||||
" no transaction");
|
||||
}
|
||||
|
||||
if (tdb->transaction->prepared) {
|
||||
if (tdb->tdb2.transaction->prepared) {
|
||||
_tdb_transaction_cancel(tdb);
|
||||
return tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_USE_ERROR,
|
||||
"tdb_transaction_prepare_commit:"
|
||||
" transaction already prepared");
|
||||
}
|
||||
|
||||
if (tdb->transaction->transaction_error) {
|
||||
if (tdb->tdb2.transaction->transaction_error) {
|
||||
_tdb_transaction_cancel(tdb);
|
||||
return tdb_logerr(tdb, TDB_ERR_EINVAL, TDB_LOG_ERROR,
|
||||
"tdb_transaction_prepare_commit:"
|
||||
@ -994,16 +994,16 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb)
|
||||
}
|
||||
|
||||
|
||||
if (tdb->transaction->nesting != 0) {
|
||||
if (tdb->tdb2.transaction->nesting != 0) {
|
||||
return TDB_SUCCESS;
|
||||
}
|
||||
|
||||
/* check for a null transaction */
|
||||
if (tdb->transaction->blocks == NULL) {
|
||||
if (tdb->tdb2.transaction->blocks == NULL) {
|
||||
return TDB_SUCCESS;
|
||||
}
|
||||
|
||||
methods = tdb->transaction->io_methods;
|
||||
methods = tdb->tdb2.transaction->io_methods;
|
||||
|
||||
/* upgrade the main transaction lock region to a write lock */
|
||||
ecode = tdb_allrecord_upgrade(tdb, TDB_HASH_LOCK_START);
|
||||
@ -1020,23 +1020,23 @@ static enum TDB_ERROR _tdb_transaction_prepare_commit(struct tdb_context *tdb)
|
||||
|
||||
/* Since we have whole db locked, we don't need the expansion lock. */
|
||||
if (!(tdb->flags & TDB_NOSYNC)) {
|
||||
/* Sets up tdb->transaction->recovery and
|
||||
* tdb->transaction->magic_offset. */
|
||||
/* Sets up tdb->tdb2.transaction->recovery and
|
||||
* tdb->tdb2.transaction->magic_offset. */
|
||||
ecode = transaction_setup_recovery(tdb);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return ecode;
|
||||
}
|
||||
}
|
||||
|
||||
tdb->transaction->prepared = true;
|
||||
tdb->tdb2.transaction->prepared = true;
|
||||
|
||||
/* expand the file to the new size if needed */
|
||||
if (tdb->file->map_size != tdb->transaction->old_map_size) {
|
||||
if (tdb->file->map_size != tdb->tdb2.transaction->old_map_size) {
|
||||
tdb_len_t add;
|
||||
|
||||
add = tdb->file->map_size - tdb->transaction->old_map_size;
|
||||
add = tdb->file->map_size - tdb->tdb2.transaction->old_map_size;
|
||||
/* Restore original map size for tdb_expand_file */
|
||||
tdb->file->map_size = tdb->transaction->old_map_size;
|
||||
tdb->file->map_size = tdb->tdb2.transaction->old_map_size;
|
||||
ecode = methods->expand_file(tdb, add);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return ecode;
|
||||
@ -1064,7 +1064,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
|
||||
int i;
|
||||
enum TDB_ERROR ecode;
|
||||
|
||||
if (tdb->transaction == NULL) {
|
||||
if (tdb->tdb2.transaction == NULL) {
|
||||
return tdb->last_error = tdb_logerr(tdb, TDB_ERR_EINVAL,
|
||||
TDB_LOG_USE_ERROR,
|
||||
"tdb_transaction_commit:"
|
||||
@ -1073,18 +1073,18 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
|
||||
|
||||
tdb_trace(tdb, "tdb_transaction_commit");
|
||||
|
||||
if (tdb->transaction->nesting != 0) {
|
||||
tdb->transaction->nesting--;
|
||||
if (tdb->tdb2.transaction->nesting != 0) {
|
||||
tdb->tdb2.transaction->nesting--;
|
||||
return tdb->last_error = TDB_SUCCESS;
|
||||
}
|
||||
|
||||
/* check for a null transaction */
|
||||
if (tdb->transaction->blocks == NULL) {
|
||||
if (tdb->tdb2.transaction->blocks == NULL) {
|
||||
_tdb_transaction_cancel(tdb);
|
||||
return tdb->last_error = TDB_SUCCESS;
|
||||
}
|
||||
|
||||
if (!tdb->transaction->prepared) {
|
||||
if (!tdb->tdb2.transaction->prepared) {
|
||||
ecode = _tdb_transaction_prepare_commit(tdb);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
_tdb_transaction_cancel(tdb);
|
||||
@ -1092,41 +1092,41 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
|
||||
}
|
||||
}
|
||||
|
||||
methods = tdb->transaction->io_methods;
|
||||
methods = tdb->tdb2.transaction->io_methods;
|
||||
|
||||
/* perform all the writes */
|
||||
for (i=0;i<tdb->transaction->num_blocks;i++) {
|
||||
for (i=0;i<tdb->tdb2.transaction->num_blocks;i++) {
|
||||
tdb_off_t offset;
|
||||
tdb_len_t length;
|
||||
|
||||
if (tdb->transaction->blocks[i] == NULL) {
|
||||
if (tdb->tdb2.transaction->blocks[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
offset = i * PAGESIZE;
|
||||
length = PAGESIZE;
|
||||
if (i == tdb->transaction->num_blocks-1) {
|
||||
length = tdb->transaction->last_block_size;
|
||||
if (i == tdb->tdb2.transaction->num_blocks-1) {
|
||||
length = tdb->tdb2.transaction->last_block_size;
|
||||
}
|
||||
|
||||
ecode = methods->twrite(tdb, offset,
|
||||
tdb->transaction->blocks[i], length);
|
||||
tdb->tdb2.transaction->blocks[i], length);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
/* we've overwritten part of the data and
|
||||
possibly expanded the file, so we need to
|
||||
run the crash recovery code */
|
||||
tdb->methods = methods;
|
||||
tdb->tdb2.io = methods;
|
||||
tdb_transaction_recover(tdb);
|
||||
|
||||
_tdb_transaction_cancel(tdb);
|
||||
|
||||
return tdb->last_error = ecode;
|
||||
}
|
||||
SAFE_FREE(tdb->transaction->blocks[i]);
|
||||
SAFE_FREE(tdb->tdb2.transaction->blocks[i]);
|
||||
}
|
||||
|
||||
SAFE_FREE(tdb->transaction->blocks);
|
||||
tdb->transaction->num_blocks = 0;
|
||||
SAFE_FREE(tdb->tdb2.transaction->blocks);
|
||||
tdb->tdb2.transaction->num_blocks = 0;
|
||||
|
||||
/* ensure the new data is on disk */
|
||||
ecode = transaction_sync(tdb, 0, tdb->file->map_size);
|
||||
@ -1151,7 +1151,7 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
|
||||
|
||||
/* use a transaction cancel to free memory and remove the
|
||||
transaction locks: it "restores" map_size, too. */
|
||||
tdb->transaction->old_map_size = tdb->file->map_size;
|
||||
tdb->tdb2.transaction->old_map_size = tdb->file->map_size;
|
||||
_tdb_transaction_cancel(tdb);
|
||||
|
||||
return tdb->last_error = TDB_SUCCESS;
|
||||
@ -1212,7 +1212,7 @@ enum TDB_ERROR tdb_transaction_recover(struct tdb_context *tdb)
|
||||
}
|
||||
|
||||
/* read the full recovery data */
|
||||
ecode = tdb->methods->tread(tdb, recovery_head + sizeof(rec), data,
|
||||
ecode = tdb->tdb2.io->tread(tdb, recovery_head + sizeof(rec), data,
|
||||
rec.len);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
|
||||
@ -1230,7 +1230,7 @@ enum TDB_ERROR tdb_transaction_recover(struct tdb_context *tdb)
|
||||
memcpy(&len, p + sizeof(ofs), sizeof(len));
|
||||
p += sizeof(ofs) + sizeof(len);
|
||||
|
||||
ecode = tdb->methods->twrite(tdb, ofs, p, len);
|
||||
ecode = tdb->tdb2.io->twrite(tdb, ofs, p, len);
|
||||
if (ecode != TDB_SUCCESS) {
|
||||
free(data);
|
||||
return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
|
||||
|
Loading…
Reference in New Issue
Block a user