[SCM] Samba Shared Repository - branch master updated

Volker Lendecke vlendec at samba.org
Fri Apr 20 09:06:03 MDT 2012


The branch, master has been updated
       via  3f00295 s3-dbwrap: dbwrap_watch_record_stored => NT_STATUS_NOT_FOUND is ok...
       via  1be6d84 s3-g_lock: Use dbwrap_record_watch_send/recv
       via  1b5b38a s3-dbwrap: Add "listwatchers" to dbwrap_tool
       via  99fa29a s3-dbwrap: Add dbwrap_record_watch_send/recv
       via  61c9750 s3-dbwrap: Add dbwrap_set_stored_callback
       via  8e5b11b s3-dbwrap: Add "db_context" to "db_record"
       via  0f20ffb s3-dbwrap: Add dbwrap_db_id
       via  e3de5e4 s3: Fix msg_channel in the cluster case
      from  5ca8422 s3: Remove an unused variable

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 3f00295f5eba1ff9a08cb35656222c78479fae11
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Apr 19 09:06:40 2012 +0200

    s3-dbwrap: dbwrap_watch_record_stored => NT_STATUS_NOT_FOUND is ok...
    
    Autobuild-User: Volker Lendecke <vl at samba.org>
    Autobuild-Date: Fri Apr 20 17:05:52 CEST 2012 on sn-devel-104

commit 1be6d849ab9d2c992dfa94419260fc28cf573d87
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Feb 15 16:38:43 2012 +0100

    s3-g_lock: Use dbwrap_record_watch_send/recv
    
    This simplifies the g_lock implementation. The new implementation tries to
    acquire a lock. If that fails due to a lock conflict, wait for the g_lock
    record to change. Upon change, just try again. The old logic had to cope with
    pending records and an ugly hack into ctdb itself. As a bonus, we now get a
    really clean async g_lock_lock_send/recv that can asynchronously wait for a
    global lock. This would have been almost impossible to do without the
    dbwrap_record_watch infrastructure.

commit 1b5b38a61547a48fa7a51bdd634c880264553d36
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Feb 15 16:33:21 2012 +0100

    s3-dbwrap: Add "listwatchers" to dbwrap_tool

commit 99fa29ae09da5bd2e860bca914a7314586a27994
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Feb 15 15:17:33 2012 +0100

    s3-dbwrap: Add dbwrap_record_watch_send/recv
    
    With this API you can asynchronously wait for a record to be modified

commit 61c97506e8ccb878d06edae72f4216ad58b96a9b
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Feb 15 15:08:29 2012 +0100

    s3-dbwrap: Add dbwrap_set_stored_callback
    
    This is a per-db function that is called whenever some record is modified

commit 8e5b11bc143e8532aeed504e47b881ce53411ce3
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Jan 2 13:30:51 2012 +0100

    s3-dbwrap: Add "db_context" to "db_record"

commit 0f20ffbcbd41895dd073051539411f7194ae8224
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Feb 15 14:57:01 2012 +0100

    s3-dbwrap: Add dbwrap_db_id
    
    This returns a blob uniquely identifying the database

commit e3de5e4fb6703976d7592b4dd8a52495a7deb951
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Apr 20 11:52:02 2012 +0200

    s3: Fix msg_channel in the cluster case

-----------------------------------------------------------------------

Summary of changes:
 source3/Makefile.in                 |    2 +
 source3/include/g_lock.h            |    5 -
 source3/lib/dbwrap/dbwrap.c         |   49 +++-
 source3/lib/dbwrap/dbwrap.h         |    7 +
 source3/lib/dbwrap/dbwrap_ctdb.c    |   12 +
 source3/lib/dbwrap/dbwrap_private.h |    5 +
 source3/lib/dbwrap/dbwrap_rbt.c     |    8 +
 source3/lib/dbwrap/dbwrap_tdb.c     |   28 ++
 source3/lib/dbwrap/dbwrap_watch.c   |  486 +++++++++++++++++++++++++++
 source3/lib/dbwrap/dbwrap_watch.h   |   46 +++
 source3/lib/g_lock.c                |  616 ++++++++++-------------------------
 source3/lib/msg_channel.c           |    9 +-
 source3/librpc/idl/messaging.idl    |    3 +-
 source3/torture/proto.h             |    1 +
 source3/torture/test_dbwrap_watch.c |   96 ++++++
 source3/torture/torture.c           |    1 +
 source3/utils/dbwrap_tool.c         |   71 ++++-
 source3/utils/net_g_lock.c          |    5 +-
 source3/wscript_build               |    2 +
 19 files changed, 983 insertions(+), 469 deletions(-)
 create mode 100644 source3/lib/dbwrap/dbwrap_watch.c
 create mode 100644 source3/lib/dbwrap/dbwrap_watch.h
 create mode 100644 source3/torture/test_dbwrap_watch.c


Changeset truncated at 500 lines:

diff --git a/source3/Makefile.in b/source3/Makefile.in
index 21b41df..d48d298 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -263,6 +263,7 @@ TDB_LIB_OBJ = lib/util_tdb.o ../lib/util/util_tdb.o \
 	  lib/dbwrap/dbwrap_ctdb.o \
 	  lib/g_lock.o \
 	  lib/dbwrap/dbwrap_cache.o \
+	  lib/dbwrap/dbwrap_watch.o \
 	  lib/dbwrap/dbwrap_rbt.o
 
 TDB_VALIDATE_OBJ = lib/tdb_validate.o
@@ -1280,6 +1281,7 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/uta
 		torture/test_ctdbconn.o \
 		torture/test_msg.o \
 		torture/test_notify.o \
+		torture/test_dbwrap_watch.o \
 		torture/t_strappend.o
 
 SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) $(TLDAP_OBJ) \
diff --git a/source3/include/g_lock.h b/source3/include/g_lock.h
index f4b7809..1ac8418 100644
--- a/source3/include/g_lock.h
+++ b/source3/include/g_lock.h
@@ -29,11 +29,6 @@ enum g_lock_type {
 	G_LOCK_WRITE = 1,
 };
 
-/*
- * Or'ed with g_lock_type
- */
-#define G_LOCK_PENDING (2)
-
 struct g_lock_ctx *g_lock_ctx_init(TALLOC_CTX *mem_ctx,
 				   struct messaging_context *msg);
 
diff --git a/source3/lib/dbwrap/dbwrap.c b/source3/lib/dbwrap/dbwrap.c
index c78ee74..14562bb 100644
--- a/source3/lib/dbwrap/dbwrap.c
+++ b/source3/lib/dbwrap/dbwrap.c
@@ -67,12 +67,46 @@ TDB_DATA dbwrap_record_get_value(const struct db_record *rec)
 
 NTSTATUS dbwrap_record_store(struct db_record *rec, TDB_DATA data, int flags)
 {
-	return rec->store(rec, data, flags);
+	NTSTATUS status;
+	struct db_context *db;
+
+	status = rec->store(rec, data, flags);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+	db = rec->db;
+	if (db->stored_callback != NULL) {
+		db->stored_callback(db, rec,
+				    db->stored_callback_private_data);
+	}
+	return NT_STATUS_OK;
+}
+
+void dbwrap_set_stored_callback(
+	struct db_context *db,
+	void (*cb)(struct db_context *db, struct db_record *rec,
+		   void *private_data),
+	void *private_data)
+{
+	db->stored_callback = cb;
+	db->stored_callback_private_data = private_data;
 }
 
 NTSTATUS dbwrap_record_delete(struct db_record *rec)
 {
-	return rec->delete_rec(rec);
+	NTSTATUS status;
+	struct db_context *db;
+
+	status = rec->delete_rec(rec);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+	db = rec->db;
+	if (db->stored_callback != NULL) {
+		db->stored_callback(db, rec,
+				    db->stored_callback_private_data);
+	}
+	return NT_STATUS_OK;
 }
 
 struct dbwrap_lock_order_state {
@@ -161,6 +195,7 @@ static struct db_record *dbwrap_fetch_locked_internal(
 		return NULL;
 	}
 	(void)talloc_steal(rec, lock_order);
+	rec->db = db;
 	TALLOC_FREE(frame);
 	return rec;
 }
@@ -183,6 +218,11 @@ struct db_record *dbwrap_try_fetch_locked(struct db_context *db,
 		? db->try_fetch_locked : db->fetch_locked);
 }
 
+struct db_context *dbwrap_record_get_db(struct db_record *rec)
+{
+	return rec->db;
+}
+
 struct dbwrap_fetch_state {
 	TALLOC_CTX *mem_ctx;
 	TDB_DATA data;
@@ -351,3 +391,8 @@ int dbwrap_transaction_cancel(struct db_context *db)
 {
 	return db->transaction_cancel(db);
 }
+
+void dbwrap_db_id(struct db_context *db, const uint8_t **id, size_t *idlen)
+{
+	db->id(db, id, idlen);
+}
diff --git a/source3/lib/dbwrap/dbwrap.h b/source3/lib/dbwrap/dbwrap.h
index 9981b6d..3304bcf 100644
--- a/source3/lib/dbwrap/dbwrap.h
+++ b/source3/lib/dbwrap/dbwrap.h
@@ -37,6 +37,12 @@ struct db_record *dbwrap_fetch_locked(struct db_context *db,
 struct db_record *dbwrap_try_fetch_locked(struct db_context *db,
 					  TALLOC_CTX *mem_ctx,
 					  TDB_DATA key);
+struct db_context *dbwrap_record_get_db(struct db_record *rec);
+void dbwrap_set_stored_callback(
+	struct db_context *db,
+	void (*cb)(struct db_context *db, struct db_record *rec,
+		   void *private_data),
+	void *private_data);
 
 NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key);
 NTSTATUS dbwrap_store(struct db_context *db, TDB_DATA key,
@@ -62,6 +68,7 @@ int dbwrap_get_flags(struct db_context *db);
 int dbwrap_transaction_start(struct db_context *db);
 int dbwrap_transaction_commit(struct db_context *db);
 int dbwrap_transaction_cancel(struct db_context *db);
+void dbwrap_db_id(struct db_context *db, const uint8_t **id, size_t *idlen);
 
 
 /* The following definitions come from lib/dbwrap_util.c  */
diff --git a/source3/lib/dbwrap/dbwrap_ctdb.c b/source3/lib/dbwrap/dbwrap_ctdb.c
index 3d08d1c..933cad5 100644
--- a/source3/lib/dbwrap/dbwrap_ctdb.c
+++ b/source3/lib/dbwrap/dbwrap_ctdb.c
@@ -1490,6 +1490,16 @@ static int db_ctdb_get_flags(struct db_context *db)
 	return tdb_get_flags(ctx->wtdb->tdb);
 }
 
+static void db_ctdb_id(struct db_context *db, const uint8_t **id,
+		       size_t *idlen)
+{
+	struct db_ctdb_ctx *ctx = talloc_get_type_abort(
+		db->private_data, struct db_ctdb_ctx);
+
+	*id = (uint8_t *)&ctx->db_id;
+	*idlen = sizeof(ctx->db_id);
+}
+
 struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
 				const char *name,
 				int hash_size, int tdb_flags,
@@ -1599,6 +1609,8 @@ struct db_context *db_open_ctdb(TALLOC_CTX *mem_ctx,
 	result->transaction_start = db_ctdb_transaction_start;
 	result->transaction_commit = db_ctdb_transaction_commit;
 	result->transaction_cancel = db_ctdb_transaction_cancel;
+	result->id = db_ctdb_id;
+	result->stored_callback = NULL;
 
 	DEBUG(3,("db_open_ctdb: opened database '%s' with dbid 0x%x\n",
 		 name, db_ctdb->db_id));
diff --git a/source3/lib/dbwrap/dbwrap_private.h b/source3/lib/dbwrap/dbwrap_private.h
index f95e305..9499342 100644
--- a/source3/lib/dbwrap/dbwrap_private.h
+++ b/source3/lib/dbwrap/dbwrap_private.h
@@ -26,6 +26,7 @@
 #include "dbwrap/dbwrap_open.h"
 
 struct db_record {
+	struct db_context *db;
 	TDB_DATA key, value;
 	NTSTATUS (*store)(struct db_record *rec, TDB_DATA data, int flag);
 	NTSTATUS (*delete_rec)(struct db_record *rec);
@@ -58,9 +59,13 @@ struct db_context {
 				 void *private_data);
 	int (*exists)(struct db_context *db,TDB_DATA key);
 	int (*wipe)(struct db_context *db);
+	void (*id)(struct db_context *db, const uint8_t **id, size_t *idlen);
 	void *private_data;
 	enum dbwrap_lock_order lock_order;
 	bool persistent;
+	void (*stored_callback)(struct db_context *db, struct db_record *rec,
+				void *private_data);
+	void *stored_callback_private_data;
 };
 
 #endif /* __DBWRAP_PRIVATE_H__ */
diff --git a/source3/lib/dbwrap/dbwrap_rbt.c b/source3/lib/dbwrap/dbwrap_rbt.c
index 95cd3e8..0d0fb02 100644
--- a/source3/lib/dbwrap/dbwrap_rbt.c
+++ b/source3/lib/dbwrap/dbwrap_rbt.c
@@ -408,6 +408,12 @@ static int db_rbt_trans_dummy(struct db_context *db)
 	return 0;
 }
 
+static void db_rbt_id(struct db_context *db, const uint8_t **id, size_t *idlen)
+{
+	*id = (uint8_t *)db;
+	*idlen = sizeof(db);
+}
+
 struct db_context *db_open_rbt(TALLOC_CTX *mem_ctx)
 {
 	struct db_context *result;
@@ -437,6 +443,8 @@ struct db_context *db_open_rbt(TALLOC_CTX *mem_ctx)
 	result->wipe = db_rbt_wipe;
 	result->parse_record = db_rbt_parse_record;
 	result->lock_order = 0;
+	result->id = db_rbt_id;
+	result->stored_callback = NULL;
 
 	return result;
 }
diff --git a/source3/lib/dbwrap/dbwrap_tdb.c b/source3/lib/dbwrap/dbwrap_tdb.c
index 59ed791..fbbe757 100644
--- a/source3/lib/dbwrap/dbwrap_tdb.c
+++ b/source3/lib/dbwrap/dbwrap_tdb.c
@@ -23,9 +23,15 @@
 #include "dbwrap/dbwrap_tdb.h"
 #include "lib/tdb_wrap/tdb_wrap.h"
 #include "util_tdb.h"
+#include "system/filesys.h"
 
 struct db_tdb_ctx {
 	struct tdb_wrap *wtdb;
+
+	struct {
+		dev_t dev;
+		ino_t ino;
+	} id;
 };
 
 static NTSTATUS db_tdb_store(struct db_record *rec, TDB_DATA data, int flag);
@@ -270,6 +276,7 @@ static int db_tdb_traverse_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
 	rec.store = db_tdb_store;
 	rec.delete_rec = db_tdb_delete;
 	rec.private_data = ctx->db->private_data;
+	rec.db = ctx->db;
 
 	return ctx->f(&rec, ctx->private_data);
 }
@@ -310,6 +317,7 @@ static int db_tdb_traverse_read_func(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA d
 	rec.store = db_tdb_store_deny;
 	rec.delete_rec = db_tdb_delete_deny;
 	rec.private_data = ctx->db->private_data;
+	rec.db = ctx->db;
 
 	return ctx->f(&rec, ctx->private_data);
 }
@@ -366,6 +374,14 @@ static int db_tdb_transaction_cancel(struct db_context *db)
 	return 0;
 }
 
+static void db_tdb_id(struct db_context *db, const uint8_t **id, size_t *idlen)
+{
+	struct db_tdb_ctx *db_ctx =
+		talloc_get_type_abort(db->private_data, struct db_tdb_ctx);
+	*id = (uint8_t *)&db_ctx->id;
+	*idlen = sizeof(db_ctx->id);
+}
+
 struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
 			       struct loadparm_context *lp_ctx,
 			       const char *name,
@@ -375,6 +391,7 @@ struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
 {
 	struct db_context *result = NULL;
 	struct db_tdb_ctx *db_tdb;
+	struct stat st;
 
 	result = talloc_zero(mem_ctx, struct db_context);
 	if (result == NULL) {
@@ -396,6 +413,15 @@ struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
 		goto fail;
 	}
 
+	ZERO_STRUCT(db_tdb->id);
+
+	if (fstat(tdb_fd(db_tdb->wtdb->tdb), &st) == -1) {
+		DEBUG(3, ("fstat failed: %s\n", strerror(errno)));
+		goto fail;
+	}
+	db_tdb->id.dev = st.st_dev;
+	db_tdb->id.ino = st.st_ino;
+
 	result->fetch_locked = db_tdb_fetch_locked;
 	result->try_fetch_locked = db_tdb_try_fetch_locked;
 	result->traverse = db_tdb_traverse;
@@ -409,6 +435,8 @@ struct db_context *db_open_tdb(TALLOC_CTX *mem_ctx,
 	result->transaction_cancel = db_tdb_transaction_cancel;
 	result->exists = db_tdb_exists;
 	result->wipe = db_tdb_wipe;
+	result->id = db_tdb_id;
+	result->stored_callback = NULL;
 	return result;
 
  fail:
diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c
new file mode 100644
index 0000000..0c13371
--- /dev/null
+++ b/source3/lib/dbwrap/dbwrap_watch.c
@@ -0,0 +1,486 @@
+/*
+   Unix SMB/CIFS implementation.
+   Watch dbwrap record changes
+   Copyright (C) Volker Lendecke 2012
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "dbwrap.h"
+#include "dbwrap_watch.h"
+#include "dbwrap_open.h"
+#include "msg_channel.h"
+#include "lib/util/util_tdb.h"
+#include "lib/util/tevent_ntstatus.h"
+
+static struct db_context *dbwrap_record_watchers_db(void)
+{
+	static struct db_context *watchers_db;
+
+	if (watchers_db == NULL) {
+		watchers_db = db_open(NULL, lock_path("dbwrap_watchers.tdb"),
+				      0, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT,
+				      0600, DBWRAP_LOCK_ORDER_3);
+	}
+	return watchers_db;
+}
+
+static TDB_DATA dbwrap_record_watchers_key(TALLOC_CTX *mem_ctx,
+					   struct db_context *db,
+					   struct db_record *rec,
+					   TDB_DATA *rec_key)
+{
+	const uint8_t *db_id;
+	size_t db_id_len;
+	TDB_DATA key, wkey;
+
+	dbwrap_db_id(db, &db_id, &db_id_len);
+	key = dbwrap_record_get_key(rec);
+
+	wkey.dsize = sizeof(uint32_t) + db_id_len + key.dsize;
+	wkey.dptr = talloc_array(mem_ctx, uint8_t, wkey.dsize);
+	if (wkey.dptr == NULL) {
+		return make_tdb_data(NULL, 0);
+	}
+	SIVAL(wkey.dptr, 0, db_id_len);
+	memcpy(wkey.dptr + sizeof(uint32_t), db_id, db_id_len);
+	memcpy(wkey.dptr + sizeof(uint32_t) + db_id_len, key.dptr, key.dsize);
+
+	if (rec_key != NULL) {
+		rec_key->dptr = wkey.dptr + sizeof(uint32_t) + db_id_len;
+		rec_key->dsize = key.dsize;
+	}
+
+	return wkey;
+}
+
+static bool dbwrap_record_watchers_key_parse(
+	TDB_DATA wkey, uint8_t **p_db_id, size_t *p_db_id_len, TDB_DATA *key)
+{
+	size_t db_id_len;
+
+	if (wkey.dsize < sizeof(uint32_t)) {
+		DEBUG(1, ("Invalid watchers key\n"));
+		return false;
+	}
+	db_id_len = IVAL(wkey.dptr, 0);
+	if (db_id_len > (wkey.dsize - sizeof(uint32_t))) {
+		DEBUG(1, ("Invalid watchers key, wkey.dsize=%d, "
+			  "db_id_len=%d\n", (int)wkey.dsize, (int)db_id_len));
+		return false;
+	}
+	*p_db_id = wkey.dptr + sizeof(uint32_t);
+	*p_db_id_len = db_id_len;
+	key->dptr = wkey.dptr + sizeof(uint32_t) + db_id_len;
+	key->dsize = wkey.dsize - sizeof(uint32_t) - db_id_len;
+	return true;
+}
+
+static NTSTATUS dbwrap_record_add_watcher(TDB_DATA w_key, struct server_id id)
+{
+	struct TALLOC_CTX *frame = talloc_stackframe();
+	struct db_context *db;
+	struct db_record *rec;
+	TDB_DATA value;
+	struct server_id *ids;
+	size_t num_ids;
+	NTSTATUS status;
+
+	db = dbwrap_record_watchers_db();
+	if (db == NULL) {
+		status = map_nt_error_from_unix(errno);
+		goto fail;
+	}
+	rec = dbwrap_fetch_locked(db, talloc_tos(), w_key);
+	if (rec == NULL) {
+		status = map_nt_error_from_unix(errno);
+		goto fail;
+	}
+	value = dbwrap_record_get_value(rec);
+
+	if ((value.dsize % sizeof(struct server_id)) != 0) {
+		status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+		goto fail;
+	}
+
+	ids = (struct server_id *)value.dptr;
+	num_ids = value.dsize / sizeof(struct server_id);
+
+	ids = talloc_realloc(talloc_tos(), ids, struct server_id,
+			     num_ids + 1);
+	if (ids == NULL) {
+		status = NT_STATUS_NO_MEMORY;
+		goto fail;
+	}
+	ids[num_ids] = id;
+	num_ids += 1;
+
+	status = dbwrap_record_store(
+		rec, make_tdb_data((uint8_t *)ids, talloc_get_size(ids)), 0);
+fail:
+	TALLOC_FREE(frame);
+	return status;
+}
+
+static NTSTATUS dbwrap_record_del_watcher(TDB_DATA w_key, struct server_id id)
+{
+	struct TALLOC_CTX *frame = talloc_stackframe();
+	struct db_context *db;
+	struct db_record *rec;
+	struct server_id *ids;
+	size_t i, num_ids;
+	TDB_DATA value;
+	NTSTATUS status;
+
+	db = dbwrap_record_watchers_db();
+	if (db == NULL) {
+		status = map_nt_error_from_unix(errno);
+		goto fail;
+	}
+	rec = dbwrap_fetch_locked(db, talloc_tos(), w_key);
+	if (rec == NULL) {
+		status = map_nt_error_from_unix(errno);
+		goto fail;
+	}
+	value = dbwrap_record_get_value(rec);
+
+	if ((value.dsize % sizeof(struct server_id)) != 0) {
+		status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+		goto fail;
+	}
+
+	ids = (struct server_id *)value.dptr;
+	num_ids = value.dsize / sizeof(struct server_id);
+
+	for (i=0; i<num_ids; i++) {
+		if (procid_equal(&id, &ids[i])) {
+			ids[i] = ids[num_ids-1];
+			value.dsize -= sizeof(struct server_id);
+			break;
+		}
+	}
+	if (value.dsize == 0) {
+		status = dbwrap_record_delete(rec);
+		goto done;
+	}
+	status = dbwrap_record_store(rec, value, 0);
+fail:
+done:
+	TALLOC_FREE(frame);
+	return status;
+}
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list