tdb and ldb
Rusty Russell
rusty at rustcorp.com.au
Fri Feb 3 13:31:47 MST 2012
On Thu, 2 Feb 2012 13:32:31 +0100, Volker Lendecke <Volker.Lendecke at SerNet.DE> wrote:
> On Thu, Feb 02, 2012 at 12:32:27PM +1030, Rusty Russell wrote:
> > On Wed, 01 Feb 2012 16:49:48 +1100, Andrew Bartlett <abartlet at samba.org> wrote:
> > > Rusty,
> > >
> > > It would seem that the next logical step would be to have ldb move to
> > > directly using only the TDB2 API and library. It isn't shared with the
> > > autoconf build, so this restriction won't cause any issues. The
> > > unshared code in source4 and the waf build in general could then move
> > > next.
> >
> > There's one really compelling reason to do that: the (yet-unexistsing)
> > allocator attribute. That will make tdb2 use the given allocator
> > (ie. talloc), so we can get have tallocated tdb_contexts and TDB_DATAs.
>
> Given we have tdb_parse_record now I'm not sure we need a
> custom allocator for tdb_fetch or equivalents.
I hadn't thought of using tdb_parse_record() that way. Clever!
Note that tdb_parse_record() does a copy if you're inside a transaction.
TDB2 does better, but there are still some cases where it's necessary.
> tdb_contexts are being taken care of by tdb_wrap, so I'm not sure that
> we need to extend the API with a custom allocator.
But TDB2 handles multiple opens correctly internally, so tdb_wrap is
only useful to provide a nice talloc handle.
The most compelling reason is that it's simple; API extension is really
easy for TDB2, and this gives us not just support for talloc, but for
any allocator.
Cheers,
Rusty.
tdb2: TDB_ATTRIBUTE_ALLOCATOR
This allows replacement of malloc/realloc/free, in particular, talloc
can use these hooks to make a tdb a genuine talloc object.
Note the "expand" rather than a complete realloc; some code paths have
to change to accomodate this, but it's clearer than a generic realloc
hook.
diff --git a/lib/tdb2/tdb2.h b/lib/tdb2/tdb2.h
index 44e7897..a183233 100644
--- a/lib/tdb2/tdb2.h
+++ b/lib/tdb2/tdb2.h
@@ -638,6 +638,7 @@ enum tdb_attribute_type {
TDB_ATTRIBUTE_STATS = 3,
TDB_ATTRIBUTE_OPENHOOK = 4,
TDB_ATTRIBUTE_FLOCK = 5,
+ TDB_ATTRIBUTE_ALLOCATOR = 6,
TDB_ATTRIBUTE_TDB1_HASHSIZE = 128,
TDB_ATTRIBUTE_TDB1_MAX_DEAD = 129,
};
@@ -872,6 +873,29 @@ struct tdb_attribute_flock {
};
/**
+ * struct tdb_attribute_allocator - allocator for tdb to use.
+ *
+ * You can replace malloc/free with your own allocation functions.
+ * The allocator takes an "owner" pointer, which is either NULL (for
+ * the initial struct tdb_context and struct tdb_file), or a
+ * previously allocated pointer. This is useful for relationship
+ * tracking, such as the talloc library.
+ *
+ * The expand function is realloc, but only ever used to expand an
+ * existing allocation.
+ *
+ * Be careful mixing allocators: two tdb_contexts which have the same file
+ * open will share the same struct tdb_file. This may be allocated by one
+ * tdb's allocator, and freed by the other.
+ */
+struct tdb_attribute_allocator {
+ struct tdb_attribute_base base; /* .attr = TDB_ATTRIBUTE_ALLOCATOR */
+ void *(*alloc)(const void *owner, size_t len);
+ void *(*expand)(void *old, size_t newlen);
+ void (*free)(void *old);
+};
+
+/**
* struct tdb_attribute_tdb1_hashsize - tdb1 hashsize
*
* This attribute allows setting the TDB1 hashsize; it only makes sense with
@@ -915,6 +939,7 @@ union tdb_attribute {
struct tdb_attribute_stats stats;
struct tdb_attribute_openhook openhook;
struct tdb_attribute_flock flock;
+ struct tdb_attribute_allocator alloc;
struct tdb_attribute_tdb1_hashsize tdb1_hashsize;
struct tdb_attribute_tdb1_max_dead tdb1_max_dead;
};
diff --git a/lib/tdb2/check.c b/lib/tdb2/check.c
index ecd6c13..b91818d 100644
--- a/lib/tdb2/check.c
+++ b/lib/tdb2/check.c
@@ -20,9 +20,16 @@
#include <ccan/asearch/asearch.h>
/* We keep an ordered array of offsets. */
-static bool append(tdb_off_t **arr, size_t *num, tdb_off_t off)
+static bool append(struct tdb_context *tdb,
+ tdb_off_t **arr, size_t *num, tdb_off_t off)
{
- tdb_off_t *new = realloc(*arr, (*num + 1) * sizeof(tdb_off_t));
+ tdb_off_t *new;
+
+ if (*num == 0) {
+ new = tdb->alloc(tdb, sizeof(tdb_off_t));
+ } else {
+ new = tdb->expand(*arr, (*num + 1) * sizeof(tdb_off_t));
+ }
if (!new)
return false;
new[(*num)++] = off;
@@ -708,7 +715,7 @@ static enum TDB_ERROR check_linear(struct tdb_context *tdb,
}
/* This record should be in free lists. */
if (frec_ftable(&rec.f) != TDB_FTABLE_NONE
- && !append(fr, num_free, off)) {
+ && !append(tdb, fr, num_free, off)) {
return tdb_logerr(tdb, TDB_ERR_OOM,
TDB_LOG_ERROR,
"tdb_check: tracking %zu'th"
@@ -722,7 +729,7 @@ static enum TDB_ERROR check_linear(struct tdb_context *tdb,
uint64_t klen, dlen, extra;
/* This record is used! */
- if (!append(used, num_used, off)) {
+ if (!append(tdb, used, num_used, off)) {
return tdb_logerr(tdb, TDB_ERR_OOM,
TDB_LOG_ERROR,
"tdb_check: tracking %zu'th"
@@ -864,7 +871,7 @@ enum TDB_ERROR tdb_check_(struct tdb_context *tdb,
out:
tdb_allrecord_unlock(tdb, F_RDLCK);
tdb_unlock_expand(tdb, F_RDLCK);
- free(fr);
- free(used);
+ tdb->free(fr);
+ tdb->free(used);
return tdb->last_error = ecode;
}
diff --git a/lib/tdb2/io.c b/lib/tdb2/io.c
index b4a6f0b..85a5062 100644
--- a/lib/tdb2/io.c
+++ b/lib/tdb2/io.c
@@ -109,7 +109,7 @@ static enum TDB_ERROR tdb_oob(struct tdb_context *tdb,
tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"tdb_oob len %lld beyond internal"
- " malloc size %lld",
+ " alloc size %lld",
(long long)(off + len),
(long long)tdb->file->map_size);
return TDB_ERR_IO;
@@ -319,7 +319,7 @@ enum TDB_ERROR tdb_write_convert(struct tdb_context *tdb, tdb_off_t off,
enum TDB_ERROR ecode;
if (unlikely((tdb->flags & TDB_CONVERT))) {
- void *conv = malloc(len);
+ void *conv = tdb->alloc(tdb, len);
if (!conv) {
return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"tdb_write: no memory converting"
@@ -328,7 +328,7 @@ enum TDB_ERROR tdb_write_convert(struct tdb_context *tdb, tdb_off_t off,
memcpy(conv, rec, len);
ecode = tdb->tdb2.io->twrite(tdb, off,
tdb_convert(tdb, conv, len), len);
- free(conv);
+ tdb->free(conv);
} else {
ecode = tdb->tdb2.io->twrite(tdb, off, rec, len);
}
@@ -372,16 +372,16 @@ static void *_tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset,
enum TDB_ERROR ecode;
/* some systems don't like zero length malloc */
- buf = malloc(prefix + len ? prefix + len : 1);
+ buf = tdb->alloc(tdb, prefix + len ? prefix + len : 1);
if (!buf) {
tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_USE_ERROR,
- "tdb_alloc_read malloc failed len=%zu",
+ "tdb_alloc_read alloc failed len=%zu",
(size_t)(prefix + len));
return TDB_ERR_PTR(TDB_ERR_OOM);
} else {
ecode = tdb->tdb2.io->tread(tdb, offset, buf+prefix, len);
if (unlikely(ecode != TDB_SUCCESS)) {
- free(buf);
+ tdb->free(buf);
return TDB_ERR_PTR(ecode);
}
}
@@ -431,8 +431,8 @@ static enum TDB_ERROR tdb_expand_file(struct tdb_context *tdb,
}
if (tdb->flags & TDB_INTERNAL) {
- char *new = realloc(tdb->file->map_ptr,
- tdb->file->map_size + addition);
+ char *new = tdb->expand(tdb->file->map_ptr,
+ tdb->file->map_size + addition);
if (!new) {
return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"No memory to expand database");
@@ -549,7 +549,7 @@ void tdb_access_release(struct tdb_context *tdb, const void *p)
if (hp) {
hdr = *hp;
*hp = hdr->next;
- free(hdr);
+ tdb->free(hdr);
} else
tdb->tdb2.direct_access--;
}
@@ -566,7 +566,7 @@ enum TDB_ERROR tdb_access_commit(struct tdb_context *tdb, void *p)
else
ecode = tdb_write(tdb, hdr->off, p, hdr->len);
*hp = hdr->next;
- free(hdr);
+ tdb->free(hdr);
} else {
tdb->tdb2.direct_access--;
ecode = TDB_SUCCESS;
diff --git a/lib/tdb2/lock.c b/lib/tdb2/lock.c
index a71c95f..fe25a2b 100644
--- a/lib/tdb2/lock.c
+++ b/lib/tdb2/lock.c
@@ -388,10 +388,13 @@ enum TDB_ERROR tdb_nest_lock(struct tdb_context *tdb,
"tdb_nest_lock: already have a hash lock?");
}
#endif
-
- new_lck = (struct tdb_lock *)realloc(
- tdb->file->lockrecs,
- sizeof(*tdb->file->lockrecs) * (tdb->file->num_lockrecs+1));
+ if (tdb->file->num_lockrecs == 0) {
+ new_lck = tdb->alloc(tdb->file, sizeof(*tdb->file->lockrecs));
+ } else {
+ new_lck = (struct tdb_lock *)tdb->expand(
+ tdb->file->lockrecs,
+ sizeof(*tdb->file->lockrecs) * (tdb->file->num_lockrecs+1));
+ }
if (new_lck == NULL) {
return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"tdb_nest_lock:"
diff --git a/lib/tdb2/open.c b/lib/tdb2/open.c
index 2730f21..8ecc494 100644
--- a/lib/tdb2/open.c
+++ b/lib/tdb2/open.c
@@ -164,7 +164,7 @@ static enum TDB_ERROR tdb_new_database(struct tdb_context *tdb,
if (tdb->flags & TDB_INTERNAL) {
tdb->file->map_size = sizeof(newdb);
- tdb->file->map_ptr = malloc(tdb->file->map_size);
+ tdb->file->map_ptr = tdb->alloc(tdb, tdb->file->map_size);
if (!tdb->file->map_ptr) {
return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"tdb_new_database:"
@@ -198,7 +198,7 @@ static enum TDB_ERROR tdb_new_database(struct tdb_context *tdb,
static enum TDB_ERROR tdb_new_file(struct tdb_context *tdb)
{
- tdb->file = malloc(sizeof(*tdb->file));
+ tdb->file = tdb->alloc(NULL, sizeof(*tdb->file));
if (!tdb->file)
return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"tdb_open: cannot alloc tdb_file structure");
@@ -245,6 +245,11 @@ enum TDB_ERROR tdb_set_attribute(struct tdb_context *tdb,
tdb->unlock_fn = attr->flock.unlock;
tdb->lock_data = attr->flock.data;
break;
+ case TDB_ATTRIBUTE_ALLOCATOR:
+ tdb->alloc = attr->alloc.alloc;
+ tdb->expand = attr->alloc.expand;
+ tdb->free = attr->alloc.free;
+ break;
default:
return tdb->last_error
= tdb_logerr(tdb, TDB_ERR_EINVAL,
@@ -298,6 +303,11 @@ enum TDB_ERROR tdb_get_attribute(struct tdb_context *tdb,
attr->flock.unlock = tdb->unlock_fn;
attr->flock.data = tdb->lock_data;
break;
+ case TDB_ATTRIBUTE_ALLOCATOR:
+ attr->alloc.alloc = tdb->alloc;;
+ attr->alloc.expand = tdb->expand;
+ attr->alloc.free = tdb->free;
+ break;
case TDB_ATTRIBUTE_TDB1_HASHSIZE:
if (!(tdb->flags & TDB_VERSION1))
return tdb->last_error
@@ -424,6 +434,26 @@ static enum TDB_ERROR capabilities_ok(struct tdb_context *tdb,
return ecode;
}
+static void *default_alloc(const void *owner, size_t len)
+{
+ return malloc(len);
+}
+
+/* First allocation needs manual search of attributes. */
+static struct tdb_context *alloc_tdb(const union tdb_attribute *attr,
+ const char *name)
+{
+ size_t len = sizeof(struct tdb_context) + (name ? strlen(name) + 1 : 0);
+
+ while (attr) {
+ if (attr->base.attr == TDB_ATTRIBUTE_ALLOCATOR) {
+ return attr->alloc.alloc(NULL, len);
+ }
+ attr = attr->base.next;
+ }
+ return default_alloc(NULL, len);
+}
+
struct tdb_context *tdb_open(const char *name, int tdb_flags,
int open_flags, mode_t mode,
union tdb_attribute *attr)
@@ -442,7 +472,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
enum TDB_ERROR ecode;
int openlock;
- tdb = malloc(sizeof(*tdb) + (name ? strlen(name) + 1 : 0));
+ tdb = alloc_tdb(attr, name);
if (!tdb) {
/* Can't log this */
errno = ENOMEM;
@@ -466,6 +496,9 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags,
memset(&tdb->stats, 0, sizeof(tdb->stats));
tdb->stats.base.attr = TDB_ATTRIBUTE_STATS;
tdb->stats.size = sizeof(tdb->stats);
+ tdb->alloc = default_alloc;
+ tdb->expand = realloc;
+ tdb->free = free;
while (attr) {
switch (attr->base.attr) {
@@ -807,7 +840,7 @@ fail_errno:
assert(tdb->file->num_lockrecs == 0);
if (tdb->file->map_ptr) {
if (tdb->flags & TDB_INTERNAL) {
- free(tdb->file->map_ptr);
+ tdb->free(tdb->file->map_ptr);
} else
tdb_munmap(tdb->file);
}
@@ -815,12 +848,12 @@ fail_errno:
tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
"tdb_open: failed to close tdb fd"
" on error: %s", strerror(errno));
- free(tdb->file->lockrecs);
- free(tdb->file);
+ tdb->free(tdb->file->lockrecs);
+ tdb->free(tdb->file);
}
}
- free(tdb);
+ tdb->free(tdb);
errno = saved_errno;
return NULL;
}
@@ -844,7 +877,7 @@ int tdb_close(struct tdb_context *tdb)
if (tdb->file->map_ptr) {
if (tdb->flags & TDB_INTERNAL)
- free(tdb->file->map_ptr);
+ tdb->free(tdb->file->map_ptr);
else
tdb_munmap(tdb->file);
}
@@ -852,8 +885,8 @@ int tdb_close(struct tdb_context *tdb)
tdb_lock_cleanup(tdb);
if (--tdb->file->refcnt == 0) {
ret = close(tdb->file->fd);
- free(tdb->file->lockrecs);
- free(tdb->file);
+ tdb->free(tdb->file->lockrecs);
+ tdb->free(tdb->file);
}
}
@@ -868,7 +901,7 @@ int tdb_close(struct tdb_context *tdb)
#ifdef TDB_TRACE
close(tdb->tracefd);
#endif
- free(tdb);
+ tdb->free(tdb);
return ret;
}
diff --git a/lib/tdb2/private.h b/lib/tdb2/private.h
index 91d3ca0..474eb2b 100644
--- a/lib/tdb2/private.h
+++ b/lib/tdb2/private.h
@@ -630,6 +630,11 @@ struct tdb_context {
void *hash_data;
uint64_t hash_seed;
+ /* Allocate and free functions. */
+ void *(*alloc)(const void *owner, size_t len);
+ void *(*expand)(void *old, size_t newlen);
+ void (*free)(void *old);
+
/* Our open hook, if any. */
enum TDB_ERROR (*openhook)(int fd, void *data);
void *openhook_data;
diff --git a/lib/tdb2/summary.c b/lib/tdb2/summary.c
index f3a3a08..8efa8e2 100644
--- a/lib/tdb2/summary.c
+++ b/lib/tdb2/summary.c
@@ -287,7 +287,7 @@ enum TDB_ERROR tdb_summary(struct tdb_context *tdb,
+ (uncoalg ? strlen(uncoalg) : 0)
+ num_caps * (strlen(CAPABILITY_FORMAT) + 20*4);
- *summary = malloc(len);
+ *summary = tdb->alloc(tdb, len);
if (!*summary) {
ecode = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"tdb_summary: failed to allocate string");
@@ -335,20 +335,20 @@ enum TDB_ERROR tdb_summary(struct tdb_context *tdb,
add_capabilities(tdb, num_caps, *summary);
unlock:
- free(hashesg);
- free(freeg);
- free(keysg);
- free(datag);
- free(extrag);
- free(uncoalg);
- free(hashes);
- free(freet);
- free(keys);
- free(data);
- free(extra);
- free(uncoal);
- free(ftables);
- free(chains);
+ tdb->free(hashesg);
+ tdb->free(freeg);
+ tdb->free(keysg);
+ tdb->free(datag);
+ tdb->free(extrag);
+ tdb->free(uncoalg);
+ tdb->free(hashes);
+ tdb->free(freet);
+ tdb->free(keys);
+ tdb->free(data);
+ tdb->free(extra);
+ tdb->free(uncoal);
+ tdb->free(ftables);
+ tdb->free(chains);
tdb_allrecord_unlock(tdb, F_RDLCK);
tdb_unlock_expand(tdb, F_RDLCK);
diff --git a/lib/tdb2/tdb.c b/lib/tdb2/tdb.c
index 5e965ac..dfcdcd8 100644
--- a/lib/tdb2/tdb.c
+++ b/lib/tdb2/tdb.c
@@ -216,7 +216,7 @@ enum TDB_ERROR tdb_append(struct tdb_context *tdb,
}
/* Slow path. */
- newdata = malloc(key.dsize + old_dlen + dbuf.dsize);
+ newdata = tdb->alloc(tdb, key.dsize + old_dlen + dbuf.dsize);
if (!newdata) {
ecode = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"tdb_append:"
@@ -242,7 +242,7 @@ enum TDB_ERROR tdb_append(struct tdb_context *tdb,
ecode = replace_data(tdb, &h, key, new_dbuf, off, old_room, true);
out_free_newdata:
- free(newdata);
+ tdb->free(newdata);
out:
tdb_unlock_hashes(tdb, h.hlock_start, h.hlock_range, F_WRLCK);
return tdb->last_error = ecode;
@@ -491,16 +491,20 @@ enum TDB_ERROR COLD tdb_logerr(struct tdb_context *tdb,
return ecode;
va_start(ap, fmt);
- len = vasprintf(&message, fmt, ap);
+ len = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
- if (len < 0) {
+ message = tdb->alloc(tdb, len + 1);
+ if (!message) {
tdb->log_fn(tdb, TDB_LOG_ERROR, TDB_ERR_OOM,
"out of memory formatting message:", tdb->log_data);
tdb->log_fn(tdb, level, ecode, fmt, tdb->log_data);
} else {
+ va_start(ap, fmt);
+ vsnprintf(message, len+1, fmt, ap);
+ va_end(ap);
tdb->log_fn(tdb, level, ecode, message, tdb->log_data);
- free(message);
+ tdb->free(message);
}
errno = saved_errno;
return ecode;
diff --git a/lib/tdb2/tdb1_check.c b/lib/tdb2/tdb1_check.c
index a8e54b2..9aff370 100644
--- a/lib/tdb2/tdb1_check.c
+++ b/lib/tdb2/tdb1_check.c
@@ -151,7 +151,7 @@ static void put_bytes(struct tdb_context *tdb, TDB_DATA d)
{
if (tdb->tdb1.transaction == NULL && tdb->file->map_ptr != NULL)
return;
- free(d.dptr);
+ tdb->free(d.dptr);
}
/* We use the excellent Jenkins lookup3 hash; this is based on hash_word2.
@@ -364,16 +364,17 @@ int tdb1_check(struct tdb_context *tdb,
goto unlock;
}
- /* One big malloc: pointers then bit arrays. */
+ /* One big alloc: pointers then bit arrays. */
alloc_len = sizeof(hashes[0]) * (1+tdb->tdb1.header.hash_size)
+ BITMAP_BITS / CHAR_BIT * (1+tdb->tdb1.header.hash_size);
- hashes = (unsigned char **)calloc(1, alloc_len);
+ hashes = (unsigned char **)tdb->alloc(tdb, alloc_len);
if (!hashes) {
tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"tdb_check: could not allocate %zu",
alloc_len);
goto unlock;
}
+ memset(hashes, 0, alloc_len);
/* Initialize pointers */
hashes[0] = (unsigned char *)(&hashes[1+tdb->tdb1.header.hash_size]);
@@ -462,14 +463,14 @@ int tdb1_check(struct tdb_context *tdb,
goto free;
}
- free(hashes);
+ tdb->free(hashes);
if (locked) {
tdb_unlockall_read(tdb);
}
return 0;
free:
- free(hashes);
+ tdb->free(hashes);
unlock:
if (locked) {
tdb_unlockall_read(tdb);
diff --git a/lib/tdb2/tdb1_io.c b/lib/tdb2/tdb1_io.c
index f3d139d..49e5e6f 100644
--- a/lib/tdb2/tdb1_io.c
+++ b/lib/tdb2/tdb1_io.c
@@ -44,7 +44,7 @@ static int tdb1_oob(struct tdb_context *tdb, tdb1_off_t len, int probe)
if (tdb->flags & TDB_INTERNAL) {
if (!probe) {
tdb->last_error = tdb_logerr(tdb, TDB_ERR_IO, TDB_LOG_ERROR,
- "tdb1_oob len %d beyond internal malloc size %d",
+ "tdb1_oob len %d beyond internal alloc size %d",
(int)len, (int)tdb->file->map_size);
}
return -1;
@@ -367,8 +367,8 @@ int tdb1_expand(struct tdb_context *tdb, tdb1_off_t size)
tdb->file->map_size += size;
if (tdb->flags & TDB_INTERNAL) {
- char *new_map_ptr = (char *)realloc(tdb->file->map_ptr,
- tdb->file->map_size);
+ char *new_map_ptr = (char *)tdb->expand(tdb->file->map_ptr,
+ tdb->file->map_size);
if (!new_map_ptr) {
tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM,
TDB_LOG_ERROR,
@@ -424,15 +424,15 @@ unsigned char *tdb1_alloc_read(struct tdb_context *tdb, tdb1_off_t offset, tdb1_
/* some systems don't like zero length malloc */
- if (!(buf = (unsigned char *)malloc(len ? len : 1))) {
+ if (!(buf = (unsigned char *)tdb->alloc(tdb, len ? len : 1))) {
tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
- "tdb1_alloc_read malloc failed"
+ "tdb1_alloc_read alloc failed"
" len=%d (%s)",
len, strerror(errno));
return NULL;
}
if (tdb->tdb1.io->tdb1_read(tdb, offset, buf, len, 0) == -1) {
- SAFE_FREE(buf);
+ SAFE_FREE(tdb, buf);
return NULL;
}
return buf;
@@ -468,7 +468,7 @@ enum TDB_ERROR tdb1_parse_data(struct tdb_context *tdb, TDB_DATA key,
}
result = parser(key, data, private_data);
- free(data.dptr);
+ tdb->free(data.dptr);
return result;
}
diff --git a/lib/tdb2/tdb1_lock.c b/lib/tdb2/tdb1_lock.c
index 5cc0ad6..d6026ea 100644
--- a/lib/tdb2/tdb1_lock.c
+++ b/lib/tdb2/tdb1_lock.c
@@ -555,6 +555,6 @@ void tdb1_release_transaction_locks(struct tdb_context *tdb)
}
tdb->file->num_lockrecs = active;
if (tdb->file->num_lockrecs == 0) {
- SAFE_FREE(tdb->file->lockrecs);
+ SAFE_FREE(tdb, tdb->file->lockrecs);
}
}
diff --git a/lib/tdb2/tdb1_open.c b/lib/tdb2/tdb1_open.c
index e668616..9f30d54 100644
--- a/lib/tdb2/tdb1_open.c
+++ b/lib/tdb2/tdb1_open.c
@@ -87,10 +87,11 @@ enum TDB_ERROR tdb1_new_database(struct tdb_context *tdb,
/* We make it up in memory, then write it out if not internal */
size = sizeof(struct tdb1_header) + (hash_size+1)*sizeof(tdb1_off_t);
- if (!(newdb = (struct tdb1_header *)calloc(size, 1))) {
+ if (!(newdb = (struct tdb1_header *)tdb->alloc(tdb, size))) {
return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"Could not allocate new database header");
}
+ memset(newdb, 0, sizeof(*newdb));
/* Fill in the header */
newdb->version = TDB1_VERSION;
@@ -134,7 +135,7 @@ enum TDB_ERROR tdb1_new_database(struct tdb_context *tdb,
ret = TDB_SUCCESS;
fail:
- SAFE_FREE(newdb);
+ SAFE_FREE(tdb, newdb);
return ret;
}
diff --git a/lib/tdb2/tdb1_private.h b/lib/tdb2/tdb1_private.h
index 68dc39f..3dd131a 100644
--- a/lib/tdb2/tdb1_private.h
+++ b/lib/tdb2/tdb1_private.h
@@ -78,7 +78,7 @@
/* free memory if the pointer is valid and zero the pointer */
#ifndef SAFE_FREE
-#define SAFE_FREE(x) do { if ((x) != NULL) {free((void *)x); (x)=NULL;} } while(0)
+#define SAFE_FREE(tdb, x) do { if ((x) != NULL) { tdb->free((void *)x); (x)=NULL;} } while(0)
#endif
#define TDB1_BUCKET(hash) ((hash) % tdb->tdb1.header.hash_size)
diff --git a/lib/tdb2/tdb1_summary.c b/lib/tdb2/tdb1_summary.c
index b74b8f4..506ea49 100644
--- a/lib/tdb2/tdb1_summary.c
+++ b/lib/tdb2/tdb1_summary.c
@@ -165,7 +165,7 @@ char *tdb1_summary(struct tdb_context *tdb)
/* 20 is max length of a %zu. */
len = strlen(SUMMARY_FORMAT1) + 35*20 + 1;
- ret = (char *)malloc(len);
+ ret = (char *)tdb->alloc(tdb, len);
if (!ret)
goto unlock;
diff --git a/lib/tdb2/tdb1_tdb.c b/lib/tdb2/tdb1_tdb.c
index 869672a..2e83955 100644
--- a/lib/tdb2/tdb1_tdb.c
+++ b/lib/tdb2/tdb1_tdb.c
@@ -647,7 +647,7 @@ int tdb1_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
dbuf = _tdb1_fetch(tdb, key);
if (dbuf.dptr == NULL) {
- dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize);
+ dbuf.dptr = (unsigned char *)tdb->alloc(tdb, new_dbuf.dsize);
} else {
unsigned int new_len = dbuf.dsize + new_dbuf.dsize;
unsigned char *new_dptr;
@@ -655,9 +655,9 @@ int tdb1_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
/* realloc '0' is special: don't do that. */
if (new_len == 0)
new_len = 1;
- new_dptr = (unsigned char *)realloc(dbuf.dptr, new_len);
+ new_dptr = (unsigned char *)tdb->expand(dbuf.dptr, new_len);
if (new_dptr == NULL) {
- free(dbuf.dptr);
+ tdb->free(dbuf.dptr);
}
dbuf.dptr = new_dptr;
}
@@ -674,7 +674,7 @@ int tdb1_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
failed:
tdb1_unlock(tdb, TDB1_BUCKET(hash), F_WRLCK);
- SAFE_FREE(dbuf.dptr);
+ SAFE_FREE(tdb, dbuf.dptr);
return ret;
}
diff --git a/lib/tdb2/tdb1_transaction.c b/lib/tdb2/tdb1_transaction.c
index 411caef..d749850 100644
--- a/lib/tdb2/tdb1_transaction.c
+++ b/lib/tdb2/tdb1_transaction.c
@@ -242,10 +242,11 @@ static int transaction1_write(struct tdb_context *tdb, tdb1_off_t off,
uint8_t **new_blocks;
/* expand the blocks array */
if (tdb->tdb1.transaction->blocks == NULL) {
- new_blocks = (uint8_t **)malloc(
- (blk+1)*sizeof(uint8_t *));
+ new_blocks = (uint8_t **)
+ tdb->alloc(tdb->tdb1.transaction,
+ (blk+1)*sizeof(uint8_t *));
} else {
- new_blocks = (uint8_t **)realloc(
+ new_blocks = (uint8_t **)tdb->expand(
tdb->tdb1.transaction->blocks,
(blk+1)*sizeof(uint8_t *));
}
@@ -262,12 +263,16 @@ static int transaction1_write(struct tdb_context *tdb, tdb1_off_t off,
/* allocate and fill a block? */
if (tdb->tdb1.transaction->blocks[blk] == NULL) {
- tdb->tdb1.transaction->blocks[blk] = (uint8_t *)calloc(tdb->tdb1.transaction->block_size, 1);
+ tdb->tdb1.transaction->blocks[blk] = (uint8_t *)
+ tdb->alloc(tdb->tdb1.transaction,
+ tdb->tdb1.transaction->block_size);
if (tdb->tdb1.transaction->blocks[blk] == NULL) {
tdb->last_error = TDB_ERR_OOM;
tdb->tdb1.transaction->transaction_error = 1;
return -1;
}
+ memset(tdb->tdb1.transaction->blocks[blk], 0,
+ tdb->tdb1.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) {
@@ -276,7 +281,7 @@ static int transaction1_write(struct tdb_context *tdb, tdb1_off_t off,
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->tdb1.transaction->blocks[blk]);
+ SAFE_FREE(tdb, tdb->tdb1.transaction->blocks[blk]);
tdb->last_error = TDB_ERR_IO;
goto fail;
}
@@ -474,11 +479,12 @@ static int _tdb1_transaction_start(struct tdb_context *tdb)
}
tdb->tdb1.transaction = (struct tdb1_transaction *)
- calloc(sizeof(struct tdb1_transaction), 1);
+ tdb->alloc(tdb, sizeof(struct tdb1_transaction));
if (tdb->tdb1.transaction == NULL) {
tdb->last_error = TDB_ERR_OOM;
return -1;
}
+ memset(tdb->tdb1.transaction, 0, sizeof(*tdb->tdb1.transaction));
/* a page at a time seems like a reasonable compromise between compactness and efficiency */
tdb->tdb1.transaction->block_size = tdb->tdb1.page_size;
@@ -487,8 +493,8 @@ static int _tdb1_transaction_start(struct tdb_context *tdb)
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->tdb1.transaction->blocks);
- SAFE_FREE(tdb->tdb1.transaction);
+ SAFE_FREE(tdb, tdb->tdb1.transaction->blocks);
+ SAFE_FREE(tdb, tdb->tdb1.transaction);
return -1;
}
@@ -506,11 +512,14 @@ static int _tdb1_transaction_start(struct tdb_context *tdb)
/* setup a copy of the hash table heads so the hash scan in
traverse can be fast */
tdb->tdb1.transaction->hash_heads = (uint32_t *)
- calloc(tdb->tdb1.header.hash_size+1, sizeof(uint32_t));
+ tdb->alloc(tdb->tdb1.transaction,
+ (tdb->tdb1.header.hash_size+1) * sizeof(uint32_t));
if (tdb->tdb1.transaction->hash_heads == NULL) {
tdb->last_error = TDB_ERR_OOM;
goto fail;
}
+ memset(tdb->tdb1.transaction->hash_heads, 0,
+ (tdb->tdb1.header.hash_size+1) * sizeof(uint32_t));
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,
@@ -535,9 +544,9 @@ fail:
tdb1_allrecord_unlock(tdb, F_RDLCK);
fail_allrecord_lock:
tdb1_transaction_unlock(tdb, F_WRLCK);
- SAFE_FREE(tdb->tdb1.transaction->blocks);
- SAFE_FREE(tdb->tdb1.transaction->hash_heads);
- SAFE_FREE(tdb->tdb1.transaction);
+ SAFE_FREE(tdb, tdb->tdb1.transaction->blocks);
+ SAFE_FREE(tdb, tdb->tdb1.transaction->hash_heads);
+ SAFE_FREE(tdb, tdb->tdb1.transaction);
return -1;
}
@@ -603,10 +612,10 @@ static int _tdb1_transaction_cancel(struct tdb_context *tdb)
/* free all the transaction blocks */
for (i=0;i<tdb->tdb1.transaction->num_blocks;i++) {
if (tdb->tdb1.transaction->blocks[i] != NULL) {
- free(tdb->tdb1.transaction->blocks[i]);
+ tdb->free(tdb->tdb1.transaction->blocks[i]);
}
}
- SAFE_FREE(tdb->tdb1.transaction->blocks);
+ SAFE_FREE(tdb, tdb->tdb1.transaction->blocks);
if (tdb->tdb1.transaction->magic_offset) {
const struct tdb1_methods *methods = tdb->tdb1.transaction->io_methods;
@@ -628,8 +637,8 @@ static int _tdb1_transaction_cancel(struct tdb_context *tdb)
/* restore the normal io methods */
tdb->tdb1.io = tdb->tdb1.transaction->io_methods;
- SAFE_FREE(tdb->tdb1.transaction->hash_heads);
- SAFE_FREE(tdb->tdb1.transaction);
+ SAFE_FREE(tdb, tdb->tdb1.transaction->hash_heads);
+ SAFE_FREE(tdb, tdb->tdb1.transaction);
return ret;
}
@@ -811,7 +820,7 @@ static int transaction1_setup_recovery(struct tdb_context *tdb,
return -1;
}
- data = (unsigned char *)malloc(recovery_size + sizeof(*rec));
+ data = (unsigned char *)tdb->alloc(tdb, recovery_size + sizeof(*rec));
if (data == NULL) {
tdb->last_error = TDB_ERR_OOM;
return -1;
@@ -850,7 +859,7 @@ static int transaction1_setup_recovery(struct tdb_context *tdb,
tdb->last_error = tdb_logerr(tdb, TDB_ERR_CORRUPT,
TDB_LOG_ERROR,
"tdb1_transaction_setup_recovery: transaction data over new region boundary");
- free(data);
+ tdb->free(data);
return -1;
}
memcpy(p, &offset, 4);
@@ -862,7 +871,7 @@ static int transaction1_setup_recovery(struct tdb_context *tdb,
new data, so we have to call the original tdb1_read
method to get it */
if (methods->tdb1_read(tdb, offset, p + 8, length, 0) != 0) {
- free(data);
+ tdb->free(data);
tdb->last_error = TDB_ERR_IO;
return -1;
}
@@ -881,14 +890,14 @@ static int transaction1_setup_recovery(struct tdb_context *tdb,
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
"tdb1_transaction_setup_recovery:"
" failed to write recovery data");
- free(data);
+ tdb->free(data);
return -1;
}
if (transaction1_write_existing(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) {
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
"tdb1_transaction_setup_recovery: failed to write"
" secondary recovery data");
- free(data);
+ tdb->free(data);
return -1;
}
@@ -896,11 +905,11 @@ static int transaction1_setup_recovery(struct tdb_context *tdb,
data before we update the magic to indicate that the recovery
data is present */
if (transaction1_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) {
- free(data);
+ tdb->free(data);
return -1;
}
- free(data);
+ tdb->free(data);
magic = TDB1_RECOVERY_MAGIC;
TDB1_CONV(magic);
@@ -1138,7 +1147,7 @@ int tdb1_transaction_commit(struct tdb_context *tdb)
"tdb1_transaction_commit: write failed");
return -1;
}
- SAFE_FREE(tdb->tdb1.transaction->blocks[i]);
+ SAFE_FREE(tdb, tdb->tdb1.transaction->blocks[i]);
}
/* Do this before we drop lock or blocks. */
@@ -1146,7 +1155,7 @@ int tdb1_transaction_commit(struct tdb_context *tdb)
need_repack = repack_worthwhile(tdb);
}
- SAFE_FREE(tdb->tdb1.transaction->blocks);
+ SAFE_FREE(tdb, tdb->tdb1.transaction->blocks);
tdb->tdb1.transaction->num_blocks = 0;
/* ensure the new data is on disk */
@@ -1231,7 +1240,7 @@ int tdb1_transaction_recover(struct tdb_context *tdb)
recovery_eof = rec.key_len;
- data = (unsigned char *)malloc(rec.data_len);
+ data = (unsigned char *)tdb->alloc(tdb, rec.data_len);
if (data == NULL) {
tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"tdb1_transaction_recover:"
@@ -1259,7 +1268,7 @@ int tdb1_transaction_recover(struct tdb_context *tdb)
memcpy(&len, p+4, 4);
if (tdb->tdb1.io->tdb1_write(tdb, ofs, p+8, len) == -1) {
- free(data);
+ tdb->free(data);
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
"tdb1_transaction_recover: failed to recover"
" %d bytes at offset %d", len, ofs);
@@ -1268,7 +1277,7 @@ int tdb1_transaction_recover(struct tdb_context *tdb)
p += 8 + len;
}
- free(data);
+ tdb->free(data);
if (transaction1_sync(tdb, 0, tdb->file->map_size) == -1) {
tdb_logerr(tdb, tdb->last_error, TDB_LOG_ERROR,
diff --git a/lib/tdb2/tdb1_traverse.c b/lib/tdb2/tdb1_traverse.c
index d9d3649..4c2d692 100644
--- a/lib/tdb2/tdb1_traverse.c
+++ b/lib/tdb2/tdb1_traverse.c
@@ -191,7 +191,7 @@ static int tdb1_traverse_internal(struct tdb_context *tdb,
/* Drop chain lock, call out */
if (tdb1_unlock(tdb, tl->hash, tl->lock_rw) != 0) {
ret = -1;
- SAFE_FREE(key.dptr);
+ SAFE_FREE(tdb, key.dptr);
goto out;
}
if (fn && fn(tdb, key, dbuf, private_data)) {
@@ -202,10 +202,10 @@ static int tdb1_traverse_internal(struct tdb_context *tdb,
" unlock_record failed!");
ret = -1;
}
- SAFE_FREE(key.dptr);
+ SAFE_FREE(tdb, key.dptr);
goto out;
}
- SAFE_FREE(key.dptr);
+ SAFE_FREE(tdb, key.dptr);
}
out:
tdb->tdb1.travlocks.next = tl->next;
@@ -324,17 +324,17 @@ TDB_DATA tdb1_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
|| memcmp(k, oldkey.dptr, oldkey.dsize) != 0) {
/* No, it wasn't: unlock it and start from scratch */
if (tdb1_unlock_record(tdb, tdb->tdb1.travlocks.off) != 0) {
- SAFE_FREE(k);
+ SAFE_FREE(tdb, k);
return tdb1_null;
}
if (tdb1_unlock(tdb, tdb->tdb1.travlocks.hash, tdb->tdb1.travlocks.lock_rw) != 0) {
- SAFE_FREE(k);
+ SAFE_FREE(tdb, k);
return tdb1_null;
}
tdb->tdb1.travlocks.off = 0;
}
- SAFE_FREE(k);
+ SAFE_FREE(tdb, k);
}
if (!tdb->tdb1.travlocks.off) {
diff --git a/lib/tdb2/transaction.c b/lib/tdb2/transaction.c
index dd94510..a559f35 100644
--- a/lib/tdb2/transaction.c
+++ b/lib/tdb2/transaction.c
@@ -25,7 +25,7 @@
*/
#include "private.h"
-#define SAFE_FREE(x) do { if ((x) != NULL) {free((void *)x); (x)=NULL;} } while(0)
+#define SAFE_FREE(tdb, x) do { if ((x) != NULL) {tdb->free((void *)x); (x)=NULL;} } while(0)
/*
transaction design:
@@ -223,10 +223,10 @@ static enum TDB_ERROR transaction_write(struct tdb_context *tdb, tdb_off_t off,
uint8_t **new_blocks;
/* expand the blocks array */
if (tdb->tdb2.transaction->blocks == NULL) {
- new_blocks = (uint8_t **)malloc(
+ new_blocks = (uint8_t **)tdb->alloc(tdb,
(blk+1)*sizeof(uint8_t *));
} else {
- new_blocks = (uint8_t **)realloc(
+ new_blocks = (uint8_t **)tdb->expand(
tdb->tdb2.transaction->blocks,
(blk+1)*sizeof(uint8_t *));
}
@@ -245,13 +245,15 @@ static enum TDB_ERROR transaction_write(struct tdb_context *tdb, tdb_off_t off,
/* allocate and fill a block? */
if (tdb->tdb2.transaction->blocks[blk] == NULL) {
- tdb->tdb2.transaction->blocks[blk] = (uint8_t *)calloc(PAGESIZE, 1);
+ tdb->tdb2.transaction->blocks[blk] = (uint8_t *)
+ tdb->alloc(tdb->tdb2.transaction->blocks, PAGESIZE);
if (tdb->tdb2.transaction->blocks[blk] == NULL) {
ecode = tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"transaction_write:"
" failed to allocate");
goto fail;
}
+ memset(tdb->tdb2.transaction->blocks[blk], 0, PAGESIZE);
if (tdb->tdb2.transaction->old_map_size > blk * PAGESIZE) {
tdb_len_t len2 = PAGESIZE;
if (len2 + (blk * PAGESIZE) > tdb->tdb2.transaction->old_map_size) {
@@ -268,7 +270,7 @@ 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->tdb2.transaction->blocks[blk]);
+ SAFE_FREE(tdb, tdb->tdb2.transaction->blocks[blk]);
goto fail;
}
if (blk == tdb->tdb2.transaction->num_blocks-1) {
@@ -479,7 +481,7 @@ static void _tdb_transaction_cancel(struct tdb_context *tdb)
free(tdb->tdb2.transaction->blocks[i]);
}
}
- SAFE_FREE(tdb->tdb2.transaction->blocks);
+ SAFE_FREE(tdb, tdb->tdb2.transaction->blocks);
if (tdb->tdb2.transaction->magic_offset) {
const struct tdb_methods *methods = tdb->tdb2.transaction->io_methods;
@@ -510,7 +512,7 @@ static void _tdb_transaction_cancel(struct tdb_context *tdb)
if (tdb_has_open_lock(tdb))
tdb_unlock_open(tdb, F_WRLCK);
- SAFE_FREE(tdb->tdb2.transaction);
+ SAFE_FREE(tdb, tdb->tdb2.transaction);
}
/*
@@ -574,21 +576,22 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
}
tdb->tdb2.transaction = (struct tdb_transaction *)
- calloc(sizeof(struct tdb_transaction), 1);
+ tdb->alloc(tdb, sizeof(struct tdb_transaction));
if (tdb->tdb2.transaction == NULL) {
return tdb->last_error = tdb_logerr(tdb, TDB_ERR_OOM,
TDB_LOG_ERROR,
"tdb_transaction_start:"
" cannot allocate");
}
+ memset(tdb->tdb2.transaction, 0, sizeof(*tdb->tdb2.transaction));
/* 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 */
ecode = tdb_transaction_lock(tdb, F_WRLCK);
if (ecode != TDB_SUCCESS) {
- SAFE_FREE(tdb->tdb2.transaction->blocks);
- SAFE_FREE(tdb->tdb2.transaction);
+ SAFE_FREE(tdb, tdb->tdb2.transaction->blocks);
+ SAFE_FREE(tdb, tdb->tdb2.transaction);
return tdb->last_error = ecode;
}
@@ -612,8 +615,8 @@ enum TDB_ERROR tdb_transaction_start(struct tdb_context *tdb)
fail_allrecord_lock:
tdb_transaction_unlock(tdb, F_WRLCK);
- SAFE_FREE(tdb->tdb2.transaction->blocks);
- SAFE_FREE(tdb->tdb2.transaction);
+ SAFE_FREE(tdb, tdb->tdb2.transaction->blocks);
+ SAFE_FREE(tdb, tdb->tdb2.transaction);
return tdb->last_error = ecode;
}
@@ -738,7 +741,7 @@ static struct tdb_recovery_record *alloc_recovery(struct tdb_context *tdb,
unsigned char *p;
const struct tdb_methods *old_methods = tdb->tdb2.io;
- rec = malloc(sizeof(*rec) + tdb_recovery_size(tdb));
+ rec = tdb->alloc(tdb, sizeof(*rec) + tdb_recovery_size(tdb));
if (!rec) {
tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"transaction_setup_recovery:"
@@ -820,7 +823,7 @@ static struct tdb_recovery_record *alloc_recovery(struct tdb_context *tdb,
return rec;
fail:
- free(rec);
+ tdb->free(rec);
tdb->tdb2.io = old_methods;
return TDB_ERR_PTR(ecode);
}
@@ -1148,10 +1151,10 @@ enum TDB_ERROR tdb_transaction_commit(struct tdb_context *tdb)
return tdb->last_error = ecode;
}
- SAFE_FREE(tdb->tdb2.transaction->blocks[i]);
+ SAFE_FREE(tdb, tdb->tdb2.transaction->blocks[i]);
}
- SAFE_FREE(tdb->tdb2.transaction->blocks);
+ SAFE_FREE(tdb, tdb->tdb2.transaction->blocks);
tdb->tdb2.transaction->num_blocks = 0;
/* ensure the new data is on disk */
@@ -1231,7 +1234,7 @@ enum TDB_ERROR tdb_transaction_recover(struct tdb_context *tdb)
recovery_eof = rec.eof;
- data = (unsigned char *)malloc(rec.len);
+ data = (unsigned char *)tdb->alloc(tdb, rec.len);
if (data == NULL) {
return tdb_logerr(tdb, TDB_ERR_OOM, TDB_LOG_ERROR,
"tdb_transaction_recover:"
More information about the samba-technical
mailing list