[PATCH] Add vectorized tdb_storev

Volker Lendecke vl at samba.org
Mon Aug 29 13:56:03 UTC 2016


Hi!

Attached find a patchset that implements a writev-style tdb_store. In
many places in Samba we assemble a tdb record from multiple pieces,
and without tdb_storev this always involves a malloc and memcpy calls.
This can be used in a lot more places in Samba, ctdb_ltdb_store() being
a very obvious candidate (Amitay, hint, hint :-). I've just fixed two
calls that I've seen in profiles.

That has just survived the tdb piece of autobuild, still waiting for the
full one. It has successfully survived an autobuild as part of a larger
patchset a few days ago.

Review appreciated!

Thanks, Volker
-------------- next part --------------
>From e31ebe288693196e66c7258e538f88c9f0bb1bb6 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 10:16:05 +0200
Subject: [PATCH 01/11] tdb: Fix a signed/unsigned hickup

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/common/tdb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index dd93680..e75f50c 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -790,7 +790,7 @@ static int tdb_free_region(struct tdb_context *tdb, tdb_off_t offset, ssize_t le
  */
 _PUBLIC_ int tdb_wipe_all(struct tdb_context *tdb)
 {
-	int i;
+	uint32_t i;
 	tdb_off_t offset = 0;
 	ssize_t data_len;
 	tdb_off_t recovery_head;
-- 
2.1.4


>From 6c8599519b21b9e07afca2230db0de2bbed8a1d8 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 10:49:04 +0200
Subject: [PATCH 02/11] tdb: Do an overflow check

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/common/tdb.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index e75f50c..b3dbc71 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -496,8 +496,15 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
 {
 	struct tdb_record rec;
 	tdb_off_t rec_ptr;
+	tdb_len_t rec_len;
 	int ret = -1;
 
+	rec_len = key.dsize + dbuf.dsize;
+	if ((rec_len < key.dsize) || (rec_len < dbuf.dsize)) {
+		tdb->ecode = TDB_ERR_OOM;
+		goto fail;
+	}
+
 	/* check for it existing, on insert. */
 	if (flag == TDB_INSERT) {
 		if (tdb_exists_hash(tdb, key, hash)) {
@@ -526,7 +533,7 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
 		tdb_delete_hash(tdb, key, hash);
 
 	/* we have to allocate some space */
-	rec_ptr = tdb_allocate(tdb, hash, key.dsize + dbuf.dsize, &rec);
+	rec_ptr = tdb_allocate(tdb, hash, rec_len, &rec);
 
 	if (rec_ptr == 0) {
 		goto fail;
-- 
2.1.4


>From 8a257eb490dce8e7454ca919a6e1d6352a0526f5 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 11:31:44 +0200
Subject: [PATCH 03/11] tdb: Remove unnecessary checks

This has already been done in tdb_find()

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/common/tdb.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index b3dbc71..0f362cf 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -157,9 +157,7 @@ static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
 
 	/* it could be an exact duplicate of what is there - this is
 	 * surprisingly common (eg. with a ldb re-index). */
-	if (rec.key_len == key.dsize &&
-	    rec.data_len == dbuf.dsize &&
-	    rec.full_hash == hash &&
+	if (rec.data_len == dbuf.dsize &&
 	    tdb_parse_record(tdb, key, tdb_update_hash_cmp, &dbuf) == 0) {
 		return 0;
 	}
-- 
2.1.4


>From 8fa6ec919c8b300e1e97846d5ef2072419c0660d Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 12:37:13 +0200
Subject: [PATCH 04/11] tdb: Allow _v variant in tdb_update_hash_cmp

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/common/tdb.c | 38 +++++++++++++++++++++++++++++++-------
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index 0f362cf..45a2990 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -129,16 +129,32 @@ tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t has
 
 static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key);
 
+struct tdb_update_hash_state {
+	const TDB_DATA *dbufs;
+	int num_dbufs;
+	tdb_len_t dbufs_len;
+};
+
 static int tdb_update_hash_cmp(TDB_DATA key, TDB_DATA data, void *private_data)
 {
-	TDB_DATA *dbuf = (TDB_DATA *)private_data;
+	struct tdb_update_hash_state *state = private_data;
+	unsigned char *dptr = data.dptr;
+	int i;
 
-	if (dbuf->dsize != data.dsize) {
+	if (state->dbufs_len != data.dsize) {
 		return -1;
 	}
-	if (memcmp(dbuf->dptr, data.dptr, data.dsize) != 0) {
-		return -1;
+
+	for (i=0; i<state->num_dbufs; i++) {
+		TDB_DATA dbuf = state->dbufs[i];
+		int ret;
+		ret = memcmp(dptr, dbuf.dptr, dbuf.dsize);
+		if (ret != 0) {
+			return -1;
+		}
+		dptr += dbuf.dsize;
 	}
+
 	return 0;
 }
 
@@ -157,9 +173,17 @@ static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
 
 	/* it could be an exact duplicate of what is there - this is
 	 * surprisingly common (eg. with a ldb re-index). */
-	if (rec.data_len == dbuf.dsize &&
-	    tdb_parse_record(tdb, key, tdb_update_hash_cmp, &dbuf) == 0) {
-		return 0;
+	if (rec.data_len == dbuf.dsize) {
+		struct tdb_update_hash_state state = {
+			.dbufs = &dbuf, .num_dbufs = 1,
+			.dbufs_len = dbuf.dsize
+		};
+		int ret;
+
+		ret = tdb_parse_record(tdb, key, tdb_update_hash_cmp, &state);
+		if (ret == 0) {
+			return 0;
+		}
 	}
 
 	/* must be long enough key, data and tailer */
-- 
2.1.4


>From 0e921dd1fe4ed22046bee9a595501e8959494ef4 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 13:47:49 +0200
Subject: [PATCH 05/11] tdb: Vectorize tdb_update_hash

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/common/tdb.c | 38 ++++++++++++++++++++++++++------------
 1 file changed, 26 insertions(+), 12 deletions(-)

diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index 45a2990..b854516 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -162,10 +162,14 @@ static int tdb_update_hash_cmp(TDB_DATA key, TDB_DATA data, void *private_data)
    is <= the old data size and the key exists.
    on failure return -1.
 */
-static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, TDB_DATA dbuf)
+static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key,
+			   uint32_t hash,
+			   const TDB_DATA *dbufs, int num_dbufs,
+			   tdb_len_t dbufs_len)
 {
 	struct tdb_record rec;
-	tdb_off_t rec_ptr;
+	tdb_off_t rec_ptr, ofs;
+	int i;
 
 	/* find entry */
 	if (!(rec_ptr = tdb_find(tdb, key, hash, &rec)))
@@ -173,10 +177,10 @@ static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
 
 	/* it could be an exact duplicate of what is there - this is
 	 * surprisingly common (eg. with a ldb re-index). */
-	if (rec.data_len == dbuf.dsize) {
+	if (rec.data_len == dbufs_len) {
 		struct tdb_update_hash_state state = {
-			.dbufs = &dbuf, .num_dbufs = 1,
-			.dbufs_len = dbuf.dsize
+			.dbufs = dbufs, .num_dbufs = num_dbufs,
+			.dbufs_len = dbufs_len
 		};
 		int ret;
 
@@ -187,18 +191,27 @@ static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
 	}
 
 	/* must be long enough key, data and tailer */
-	if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) {
+	if (rec.rec_len < key.dsize + dbufs_len + sizeof(tdb_off_t)) {
 		tdb->ecode = TDB_SUCCESS; /* Not really an error */
 		return -1;
 	}
 
-	if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len,
-		      dbuf.dptr, dbuf.dsize) == -1)
-		return -1;
+	ofs = rec_ptr + sizeof(rec) + rec.key_len;
+
+	for (i=0; i<num_dbufs; i++) {
+		TDB_DATA dbuf = dbufs[i];
+		int ret;
+
+		ret = tdb->methods->tdb_write(tdb, ofs, dbuf.dptr, dbuf.dsize);
+		if (ret == -1) {
+			return -1;
+		}
+		ofs += dbuf.dsize;
+	}
 
-	if (dbuf.dsize != rec.data_len) {
+	if (dbufs_len != rec.data_len) {
 		/* update size */
-		rec.data_len = dbuf.dsize;
+		rec.data_len = dbufs_len;
 		return tdb_rec_write(tdb, rec_ptr, &rec);
 	}
 
@@ -535,7 +548,8 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
 		}
 	} else {
 		/* first try in-place update, on modify or replace. */
-		if (tdb_update_hash(tdb, key, hash, dbuf) == 0) {
+		if (tdb_update_hash(tdb, key, hash, &dbuf, 1,
+				    dbuf.dsize) == 0) {
 			goto done;
 		}
 		if (tdb->ecode == TDB_ERR_NOEXIST &&
-- 
2.1.4


>From 35411dbdefe443fda21b2cfb85c7f215e288b6ef Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 14:11:03 +0200
Subject: [PATCH 06/11] tdb: Vectorize _tdb_store

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/common/tdb.c | 69 ++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 54 insertions(+), 15 deletions(-)

diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index b854516..6d4ad6d 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -526,16 +526,30 @@ tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
 	return best_rec_ptr;
 }
 
-static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
-		       TDB_DATA dbuf, int flag, uint32_t hash)
+static int _tdb_storev(struct tdb_context *tdb, TDB_DATA key,
+		       const TDB_DATA *dbufs, int num_dbufs,
+		       int flag, uint32_t hash)
 {
 	struct tdb_record rec;
-	tdb_off_t rec_ptr;
-	tdb_len_t rec_len;
+	tdb_off_t rec_ptr, ofs;
+	tdb_len_t rec_len, dbufs_len;
+	int i;
 	int ret = -1;
 
-	rec_len = key.dsize + dbuf.dsize;
-	if ((rec_len < key.dsize) || (rec_len < dbuf.dsize)) {
+	dbufs_len = 0;
+
+	for (i=0; i<num_dbufs; i++) {
+		size_t dsize = dbufs[i].dsize;
+
+		dbufs_len += dsize;
+		if (dbufs_len < dsize) {
+			tdb->ecode = TDB_ERR_OOM;
+			goto fail;
+		}
+	}
+
+	rec_len = key.dsize + dbufs_len;
+	if ((rec_len < key.dsize) || (rec_len < dbufs_len)) {
 		tdb->ecode = TDB_ERR_OOM;
 		goto fail;
 	}
@@ -548,8 +562,8 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
 		}
 	} else {
 		/* first try in-place update, on modify or replace. */
-		if (tdb_update_hash(tdb, key, hash, &dbuf, 1,
-				    dbuf.dsize) == 0) {
+		if (tdb_update_hash(tdb, key, hash, dbufs, num_dbufs,
+				    dbufs_len) == 0) {
 			goto done;
 		}
 		if (tdb->ecode == TDB_ERR_NOEXIST &&
@@ -580,17 +594,36 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
 		goto fail;
 
 	rec.key_len = key.dsize;
-	rec.data_len = dbuf.dsize;
+	rec.data_len = dbufs_len;
 	rec.full_hash = hash;
 	rec.magic = TDB_MAGIC;
 
+	ofs = rec_ptr;
+
 	/* write out and point the top of the hash chain at it */
-	if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
-	    || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec),
-				       key.dptr, key.dsize) == -1
-	    || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec)+key.dsize,
-				       dbuf.dptr, dbuf.dsize) == -1
-	    || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) {
+	ret = tdb_rec_write(tdb, ofs, &rec);
+	if (ret == -1) {
+		goto fail;
+	}
+	ofs += sizeof(rec);
+
+	ret = tdb->methods->tdb_write(tdb, ofs, key.dptr, key.dsize);
+	if (ret == -1) {
+		goto fail;
+	}
+	ofs += key.dsize;
+
+	for (i=0; i<num_dbufs; i++) {
+		ret = tdb->methods->tdb_write(tdb, ofs, dbufs[i].dptr,
+					      dbufs[i].dsize);
+		if (ret == -1) {
+			goto fail;
+		}
+		ofs += dbufs[i].dsize;
+	}
+
+	ret = tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr);
+	if (ret == -1) {
 		/* Need to tdb_unallocate() here */
 		goto fail;
 	}
@@ -604,6 +637,12 @@ static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
 	return ret;
 }
 
+static int _tdb_store(struct tdb_context *tdb, TDB_DATA key,
+		      TDB_DATA dbuf, int flag, uint32_t hash)
+{
+	return _tdb_storev(tdb, key, &dbuf, 1, flag, hash);
+}
+
 /* store an element in the database, replacing any existing element
    with the same key
 
-- 
2.1.4


>From 55604a492b9add45df11db2dcea10415ab9a8f92 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 20:45:10 +0200
Subject: [PATCH 07/11] tdb: Add tdb_trace_1plusn_rec_flag_ret

Needed for tdb_storev

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/common/tdb.c         | 19 +++++++++++++++++++
 lib/tdb/common/tdb_private.h |  5 +++++
 2 files changed, 24 insertions(+)

diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index 6d4ad6d..6869d15 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -1214,6 +1214,25 @@ void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op,
 	tdb_trace_end_ret(tdb, ret);
 }
 
+void tdb_trace_1plusn_rec_flag_ret(struct tdb_context *tdb, const char *op,
+				   TDB_DATA rec,
+				   const TDB_DATA *recs, int num_recs,
+				   unsigned flag, int ret)
+{
+	char msg[1 + sizeof(ret) * 4];
+	int i;
+
+	snprintf(msg, sizeof(msg), " %#x", flag);
+	tdb_trace_start(tdb);
+	tdb_trace_write(tdb, op);
+	tdb_trace_record(tdb, rec);
+	for (i=0; i<num_recs; i++) {
+		tdb_trace_record(tdb, recs[i]);
+	}
+	tdb_trace_write(tdb, msg);
+	tdb_trace_end_ret(tdb, ret);
+}
+
 void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
 			   TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret)
 {
diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h
index de8d9e6..7ff29aa 100644
--- a/lib/tdb/common/tdb_private.h
+++ b/lib/tdb/common/tdb_private.h
@@ -96,6 +96,10 @@ void tdb_trace_1rec_retrec(struct tdb_context *tdb, const char *op,
 void tdb_trace_2rec_flag_ret(struct tdb_context *tdb, const char *op,
 			     TDB_DATA rec1, TDB_DATA rec2, unsigned flag,
 			     int ret);
+void tdb_trace_1plusn_rec_flag_ret(struct tdb_context *tdb, const char *op,
+				   TDB_DATA rec,
+				   const TDB_DATA *recs, int num_recs,
+				   unsigned flag, int ret);
 void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
 			   TDB_DATA rec1, TDB_DATA rec2, TDB_DATA ret);
 #else
@@ -108,6 +112,7 @@ void tdb_trace_2rec_retrec(struct tdb_context *tdb, const char *op,
 #define tdb_trace_1rec_ret(tdb, op, rec, ret)
 #define tdb_trace_1rec_retrec(tdb, op, rec, ret)
 #define tdb_trace_2rec_flag_ret(tdb, op, rec1, rec2, flag, ret)
+#define tdb_trace_1plusn_rec_flag_ret(tdb, op, rec, recs, num_recs, flag, ret);
 #define tdb_trace_2rec_retrec(tdb, op, rec1, rec2, ret)
 #endif /* !TDB_TRACE */
 
-- 
2.1.4


>From 1b87f4e73f456e6cac1d1567dade27bfc2872e42 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 20:46:07 +0200
Subject: [PATCH 08/11] tdb: Add tdb_storev

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/ABI/tdb-1.3.11.sigs | 70 +++++++++++++++++++++++++++++++++++++++++++++
 lib/tdb/common/tdb.c        | 25 ++++++++++++++++
 lib/tdb/include/tdb.h       | 26 +++++++++++++++++
 lib/tdb/wscript             |  2 +-
 4 files changed, 122 insertions(+), 1 deletion(-)
 create mode 100644 lib/tdb/ABI/tdb-1.3.11.sigs

diff --git a/lib/tdb/ABI/tdb-1.3.11.sigs b/lib/tdb/ABI/tdb-1.3.11.sigs
new file mode 100644
index 0000000..48f4278
--- /dev/null
+++ b/lib/tdb/ABI/tdb-1.3.11.sigs
@@ -0,0 +1,70 @@
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_jenkins_hash: unsigned int (TDB_DATA *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: dptr = 0xXXXX, dsize = 0
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_rescue: int (struct tdb_context *, void (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_runtime_check_for_robust_mutexes: bool (void)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+tdb_storev: int (struct tdb_context *, TDB_DATA, const TDB_DATA *, int, int)
+tdb_summary: char *(struct tdb_context *)
+tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_start_nonblock: int (struct tdb_context *)
+tdb_transaction_write_lock_mark: int (struct tdb_context *)
+tdb_transaction_write_lock_unmark: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index 6869d15..9de0607 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -670,6 +670,31 @@ _PUBLIC_ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int
 	return ret;
 }
 
+_PUBLIC_ int tdb_storev(struct tdb_context *tdb, TDB_DATA key,
+			const TDB_DATA *dbufs, int num_dbufs, int flag)
+{
+	uint32_t hash;
+	int ret;
+
+	if (tdb->read_only || tdb->traverse_read) {
+		tdb->ecode = TDB_ERR_RDONLY;
+		tdb_trace_1plusn_rec_flag_ret(tdb, "tdb_storev", key,
+					      dbufs, num_dbufs, flag, -1);
+		return -1;
+	}
+
+	/* find which hash bucket it is in */
+	hash = tdb->hash_fn(&key);
+	if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
+		return -1;
+
+	ret = _tdb_storev(tdb, key, dbufs, num_dbufs, flag, hash);
+	tdb_trace_1plusn_rec_flag_ret(tdb, "tdb_storev", key,
+				      dbufs, num_dbufs, flag, -1);
+	tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
+	return ret;
+}
+
 /* Append to an entry. Create if not exist. */
 _PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
 {
diff --git a/lib/tdb/include/tdb.h b/lib/tdb/include/tdb.h
index 8478ca2..e86d267 100644
--- a/lib/tdb/include/tdb.h
+++ b/lib/tdb/include/tdb.h
@@ -357,6 +357,32 @@ int tdb_delete(struct tdb_context *tdb, TDB_DATA key);
  */
 int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
 
+
+/**
+ * @brief Store an element in the database.
+ *
+ * This replaces any existing element with the same key.
+ *
+ * @param[in]  tdb      The tdb to store the entry.
+ *
+ * @param[in]  key      The key to use to store the entry.
+ *
+ * @param[in]  dbufs    A vector of memory chunks to write
+ *
+ * @param[in]  num_dbufs Length of the dbufs vector
+ *
+ * @param[in]  flag     The flags to store the key:\n\n
+ *                      TDB_INSERT: Don't overwrite an existing entry.\n
+ *                      TDB_MODIFY: Don't create a new entry\n
+ *
+ * @return              0 on success, -1 on error with error code set.
+ *
+ * @see tdb_error()
+ * @see tdb_errorstr()
+ */
+int tdb_storev(struct tdb_context *tdb, TDB_DATA key,
+	       const TDB_DATA *dbufs, int num_dbufs, int flag);
+
 /**
  * @brief Append data to an entry.
  *
diff --git a/lib/tdb/wscript b/lib/tdb/wscript
index c854a21..4e52b6c 100644
--- a/lib/tdb/wscript
+++ b/lib/tdb/wscript
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 APPNAME = 'tdb'
-VERSION = '1.3.10'
+VERSION = '1.3.11'
 
 blddir = 'bin'
 
-- 
2.1.4


>From 4ac6897e27e80095827a4f59724f04943df07cdf Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 20:57:42 +0200
Subject: [PATCH 09/11] tdb: Use tdb_storev in tdb_append

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 lib/tdb/common/tdb.c | 36 ++++++------------------------------
 1 file changed, 6 insertions(+), 30 deletions(-)

diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index 9de0607..a67d8fb 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -699,7 +699,7 @@ _PUBLIC_ int tdb_storev(struct tdb_context *tdb, TDB_DATA key,
 _PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
 {
 	uint32_t hash;
-	TDB_DATA dbuf;
+	TDB_DATA dbufs[2];
 	int ret = -1;
 
 	/* find which hash bucket it is in */
@@ -707,38 +707,14 @@ _PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf
 	if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
 		return -1;
 
-	dbuf = _tdb_fetch(tdb, key);
+	dbufs[0] = _tdb_fetch(tdb, key);
+	dbufs[1] = new_dbuf;
 
-	if (dbuf.dptr == NULL) {
-		dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize);
-	} else {
-		unsigned int new_len = dbuf.dsize + new_dbuf.dsize;
-		unsigned char *new_dptr;
-
-		/* realloc '0' is special: don't do that. */
-		if (new_len == 0)
-			new_len = 1;
-		new_dptr = (unsigned char *)realloc(dbuf.dptr, new_len);
-		if (new_dptr == NULL) {
-			free(dbuf.dptr);
-		}
-		dbuf.dptr = new_dptr;
-	}
-
-	if (dbuf.dptr == NULL) {
-		tdb->ecode = TDB_ERR_OOM;
-		goto failed;
-	}
-
-	memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize);
-	dbuf.dsize += new_dbuf.dsize;
+	ret = _tdb_storev(tdb, key, dbufs, 2, 0, hash);
+	tdb_trace_2rec_retrec(tdb, "tdb_append", key, dbufs[0], dbufs[1]);
 
-	ret = _tdb_store(tdb, key, dbuf, 0, hash);
-	tdb_trace_2rec_retrec(tdb, "tdb_append", key, new_dbuf, dbuf);
-
-failed:
 	tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
-	SAFE_FREE(dbuf.dptr);
+	SAFE_FREE(dbufs[0].dptr);
 	return ret;
 }
 
-- 
2.1.4


>From bfc324e2c0662a94a68353b9ed29b54136704b15 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 10 Aug 2016 21:12:06 +0200
Subject: [PATCH 10/11] dbwrap: Use tdb_storev in dbwrap_ctdb

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/dbwrap/dbwrap_ctdb.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c
index 10f5f50..34aad45 100644
--- a/source3/lib/dbwrap/dbwrap_ctdb.c
+++ b/source3/lib/dbwrap/dbwrap_ctdb.c
@@ -128,22 +128,14 @@ static NTSTATUS db_ctdb_ltdb_store(struct db_ctdb_ctx *db,
 				   struct ctdb_ltdb_header *header,
 				   TDB_DATA data)
 {
-	TDB_DATA rec;
+	TDB_DATA recs[2];
 	int ret;
 
-	rec.dsize = data.dsize + sizeof(struct ctdb_ltdb_header);
-	rec.dptr = (uint8_t *)talloc_size(talloc_tos(), rec.dsize);
-
-	if (rec.dptr == NULL) {
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	memcpy(rec.dptr, header, sizeof(struct ctdb_ltdb_header));
-	memcpy(sizeof(struct ctdb_ltdb_header) + (uint8_t *)rec.dptr, data.dptr, data.dsize);
-
-	ret = tdb_store(db->wtdb->tdb, key, rec, TDB_REPLACE);
+	recs[0] = (TDB_DATA) { .dptr = (uint8_t *)header,
+			       .dsize = sizeof(struct ctdb_ltdb_header) };
+	recs[1] = data;
 
-	talloc_free(rec.dptr);
+	ret = tdb_storev(db->wtdb->tdb, key, recs, 2, TDB_REPLACE);
 
 	return (ret == 0) ? NT_STATUS_OK
 			  : tdb_error_to_ntstatus(db->wtdb->tdb);
-- 
2.1.4


>From 5fea44d828ea3da9f6d382bbac4893a94fa23bd7 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 12 Aug 2016 20:57:26 +0200
Subject: [PATCH 11/11] lib: Use tdb_storev in gencache

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/gencache.c | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c
index 84d273e..5af6eb8 100644
--- a/source3/lib/gencache.c
+++ b/source3/lib/gencache.c
@@ -278,9 +278,9 @@ bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob,
 	int ret;
 	fstring hdr;
 	int hdr_len;
-	char* val;
 	time_t last_stabilize;
 	static int writecount;
+	TDB_DATA dbufs[2];
 
 	if (tdb_data_cmp(string_term_tdb_data(keystr),
 			 last_stabilize_key()) == 0) {
@@ -311,13 +311,8 @@ bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob,
 		return false;
 	}
 
-	val = talloc_array(talloc_tos(), char, hdr_len + blob->length);
-	if (val == NULL) {
-		return false;
-	}
-
-	memcpy(val, hdr, hdr_len);
-	memcpy(val+hdr_len, blob->data, blob->length);
+	dbufs[0] = (TDB_DATA) { .dptr = (uint8_t *)hdr, .dsize = hdr_len };
+	dbufs[1] = (TDB_DATA) { .dptr = blob->data, .dsize = blob->length };
 
 	DEBUG(10, ("Adding cache entry with key=[%s] and timeout="
 	           "[%s] (%d seconds %s)\n", keystr,
@@ -325,12 +320,8 @@ bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob,
 		   (int)(timeout - time(NULL)), 
 		   timeout > time(NULL) ? "ahead" : "in the past"));
 
-	ret = tdb_store_bystring(
-		cache_notrans->tdb, keystr,
-		make_tdb_data((uint8_t *)val, talloc_array_length(val)),
-		0);
-	TALLOC_FREE(val);
-
+	ret = tdb_storev(cache_notrans->tdb, string_term_tdb_data(keystr),
+			 dbufs, 2, 0);
 	if (ret != 0) {
 		return false;
 	}
-- 
2.1.4



More information about the samba-technical mailing list