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 <[email protected]>
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 <[email protected]>
    Autobuild-Date: Fri Apr 20 17:05:52 CEST 2012 on sn-devel-104

commit 1be6d849ab9d2c992dfa94419260fc28cf573d87
Author: Volker Lendecke <[email protected]>
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 <[email protected]>
Date:   Wed Feb 15 16:33:21 2012 +0100

    s3-dbwrap: Add "listwatchers" to dbwrap_tool

commit 99fa29ae09da5bd2e860bca914a7314586a27994
Author: Volker Lendecke <[email protected]>
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 <[email protected]>
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 <[email protected]>
Date:   Mon Jan 2 13:30:51 2012 +0100

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

commit 0f20ffbcbd41895dd073051539411f7194ae8224
Author: Volker Lendecke <[email protected]>
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 <[email protected]>
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

Reply via email to