[SCM] Samba Shared Repository - branch v3-6-test updated

Jeremy Allison jra at samba.org
Thu Dec 30 11:21:15 MST 2010


The branch, v3-6-test has been updated
       via  06e02df s3: Fix two uninitialized variables
       via  61186b5 s3: Allow more control over smbsock_[any_]connect
       via  5ea88af Use sockaddr_storage in async sendto/recvfrom (cherry picked from commit 65f4f22cb4a201fb3f4f4adbb576d3a8909d4bfd)
       via  2a833a4 s3: Make name_query return NTSTATUS
       via  d7c32ae s3: AllowDebugChange is gone (cherry picked from commit 28d997a89056f144de6a7b95af0e54a044c5e5b3)
       via  030f2ff Fix a crash in libnss_wins
       via  073f002 s3: Make node_status_query return NTSTATUS
       via  ef6cb55 s3: Remove an ancient typedef (cherry picked from commit e1ab3c3470a7f1159d52ed0c1eacf4a5a7b6bc2b)
       via  522cbb3 s3: Fix some typos (cherry picked from commit b0ff97d8d37957fc34861214b6cbab513072bef1)
       via  80ef019 async_send->sendto, async_recv->recvfrom (cherry picked from commit c4b18bd860bc18529249a8c54c7db6aba2347591)
       via  7371bf5 tdb:tdbtorture: use TEST_DATA_PREFIX for files
       via  8b916ab tdb:tdbtest: use TEST_DATA_PREFIX for files
       via  94d4655 testprogs: testspoolss.exe: pretty print FILETIME in driver info 6 and 8.
       via  72b35f9 tevent: More documentation updates
      from  489b1c1 s3:lib/netapi: don't set SAMR_FIELD_FULL_NAME if we just want to set the account name (bug #7896)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test


- Log -----------------------------------------------------------------
commit 06e02dfb9316ec96d711fa7455b4e947587a7f9a
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Dec 30 12:42:50 2010 +0100

    s3: Fix two uninitialized variables
    
    Autobuild-User: Volker Lendecke <vlendec at samba.org>
    Autobuild-Date: Thu Dec 30 12:52:47 CET 2010 on sn-devel-104
    (cherry picked from commit d05fb4b7b79fa5ef240864f0f0f544bbba1b59e3)

commit 61186b5281d23823a7ee99b7d552b2d8d7e07acc
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Dec 23 15:20:22 2010 +0100

    s3: Allow more control over smbsock_[any_]connect
    
    Autobuild-User: Volker Lendecke <vlendec at samba.org>
    Autobuild-Date: Wed Dec 29 23:30:44 CET 2010 on sn-devel-104
    (cherry picked from commit 86ff8cf227c759189080ade0deb4f5b184bb14f7)

commit 5ea88afaf4982d4f327897c6474034f9aae04d85
Author: Volker Lendecke <vl at samba.org>
Date:   Wed Dec 29 08:46:08 2010 +0100

    Use sockaddr_storage in async sendto/recvfrom
    (cherry picked from commit 65f4f22cb4a201fb3f4f4adbb576d3a8909d4bfd)

commit 2a833a4621f3d7155dc7dfc5a7633dc68eba2dd0
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Dec 28 13:47:35 2010 +0100

    s3: Make name_query return NTSTATUS
    
    Also use talloc for the result
    
    Autobuild-User: Volker Lendecke <vlendec at samba.org>
    Autobuild-Date: Tue Dec 28 18:21:05 CET 2010 on sn-devel-104
    (cherry picked from commit 4622812a41eb5ce07dd8f74534217e858743883f)

commit d7c32ae6fcab9205abf86b0d8fd1f92f410ccecf
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Dec 28 17:17:04 2010 +0100

    s3: AllowDebugChange is gone
    (cherry picked from commit 28d997a89056f144de6a7b95af0e54a044c5e5b3)

commit 030f2ff39a64a8d378c1c2a9027e5152e17e83b3
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Dec 28 17:05:18 2010 +0100

    Fix a crash in libnss_wins
    
    lp_set_parm accesses the case tables
    (cherry picked from commit 181cd3281c4f2c53dc507f59d281a2517579cfe1)

commit 073f0023dac2be067f15f29d6efd02491de457ed
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Dec 28 12:53:12 2010 +0100

    s3: Make node_status_query return NTSTATUS
    
    Also make the result talloc'ed
    
    Autobuild-User: Volker Lendecke <vlendec at samba.org>
    Autobuild-Date: Tue Dec 28 13:46:59 CET 2010 on sn-devel-104
    (cherry picked from commit 571711431885e8e556822c14b3d117025860bf81)

commit ef6cb55db8457654d5d19d4c4f9d859864d40ca8
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Dec 28 11:55:47 2010 +0100

    s3: Remove an ancient typedef
    (cherry picked from commit e1ab3c3470a7f1159d52ed0c1eacf4a5a7b6bc2b)

commit 522cbb353ff988d3275f4449d97485a42a76d5af
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Dec 28 11:48:43 2010 +0100

    s3: Fix some typos
    (cherry picked from commit b0ff97d8d37957fc34861214b6cbab513072bef1)

commit 80ef0195bd42a3d4fcd1a03e85ea06dc85cee757
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Dec 26 16:03:58 2010 +0100

    async_send->sendto, async_recv->recvfrom
    (cherry picked from commit c4b18bd860bc18529249a8c54c7db6aba2347591)

commit 7371bf53f793e5857c4bb43fdd58e8f121e7007d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Dec 24 11:54:51 2010 +0100

    tdb:tdbtorture: use TEST_DATA_PREFIX for files
    
    metze
    
    Autobuild-User: Stefan Metzmacher <metze at samba.org>
    Autobuild-Date: Fri Dec 24 18:17:53 CET 2010 on sn-devel-104
    (cherry picked from commit b83672b36c1ea8c35833c40c3919b63809f16624)

commit 8b916ab9203188bd47c8f9afcdb17d183ccd2167
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Dec 24 11:54:03 2010 +0100

    tdb:tdbtest: use TEST_DATA_PREFIX for files
    
    metze
    (cherry picked from commit d81ceeb9833ec80d7ab21b34e4b3af3d79aeb845)

commit 94d4655d04c02d79e5ce4517a8bf9c4f63719688
Author: Günther Deschner <gd at samba.org>
Date:   Thu Dec 23 14:43:10 2010 +0100

    testprogs: testspoolss.exe: pretty print FILETIME in driver info 6 and 8.
    
    Guenther
    
    Autobuild-User: Günther Deschner <gd at samba.org>
    Autobuild-Date: Thu Dec 23 23:40:21 CET 2010 on sn-devel-104
    (cherry picked from commit 821b2a9d1197d927ab6081bcd953a0540888dcf3)

commit 72b35f9a81029c1c336df8a48a7534970d4d89f6
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Dec 26 15:00:53 2010 +0100

    tevent: More documentation updates
    
    Autobuild-User: Volker Lendecke <vlendec at samba.org>
    Autobuild-Date: Sun Dec 26 15:49:59 CET 2010 on sn-devel-104
    (cherry picked from commit b2c983149cd498e633c5c17c1d39e10c70fef630)

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

Summary of changes:
 lib/async_req/async_sock.c                 |   91 ++++++++++++++--------
 lib/async_req/async_sock.h                 |   21 +++---
 lib/tdb/tools/tdbtest.c                    |   31 +++++++-
 lib/tdb/tools/tdbtorture.c                 |   38 +++++++--
 lib/tevent/tevent.h                        |   73 ++++++++++++++++++-
 nsswitch/wins.c                            |   17 ++--
 source3/client/client.c                    |    1 -
 source3/include/proto.h                    |   47 ++++++++----
 source3/include/smb.h                      |    4 +-
 source3/libsmb/namequery.c                 |  108 +++++++++++++++-----------
 source3/libsmb/smbsock_connect.c           |  113 +++++++++++++++++++++------
 source3/torture/test_smbsock_any_connect.c |    5 +-
 source3/utils/nmblookup.c                  |   39 ++++++----
 source3/web/diagnose.c                     |   10 ++-
 source3/winbindd/winbindd_cm.c             |    7 +-
 source3/winbindd/winbindd_wins.c           |   51 ++++++++-----
 testprogs/win32/spoolss/printlib.c         |  102 ++++++++++++++++++++++++-
 testprogs/win32/spoolss/printlib_proto.h   |    2 +
 18 files changed, 562 insertions(+), 198 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index 18adb42..7ea66f5 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -36,28 +36,29 @@
 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
 #endif
 
-struct async_send_state {
+struct sendto_state {
 	int fd;
 	const void *buf;
 	size_t len;
 	int flags;
+	const struct sockaddr_storage *addr;
+	socklen_t addr_len;
 	ssize_t sent;
 };
 
-static void async_send_handler(struct tevent_context *ev,
+static void sendto_handler(struct tevent_context *ev,
 			       struct tevent_fd *fde,
 			       uint16_t flags, void *private_data);
 
-struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
-				   struct tevent_context *ev,
-				   int fd, const void *buf, size_t len,
-				   int flags)
+struct tevent_req *sendto_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+			       int fd, const void *buf, size_t len, int flags,
+			       const struct sockaddr_storage *addr)
 {
 	struct tevent_req *result;
-	struct async_send_state *state;
+	struct sendto_state *state;
 	struct tevent_fd *fde;
 
-	result = tevent_req_create(mem_ctx, &state, struct async_send_state);
+	result = tevent_req_create(mem_ctx, &state, struct sendto_state);
 	if (result == NULL) {
 		return result;
 	}
@@ -65,8 +66,26 @@ struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
 	state->buf = buf;
 	state->len = len;
 	state->flags = flags;
+	state->addr = addr;
+
+	switch (addr->ss_family) {
+	case AF_INET:
+		state->addr_len = sizeof(struct sockaddr_in);
+		break;
+#if defined(HAVE_IPV6)
+	case AF_INET6:
+		state->addr_len = sizeof(struct sockaddr_in6);
+		break;
+#endif
+	case AF_UNIX:
+		state->addr_len = sizeof(struct sockaddr_un);
+		break;
+	default:
+		state->addr_len = sizeof(struct sockaddr_storage);
+		break;
+	}
 
-	fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, async_send_handler,
+	fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, sendto_handler,
 			    result);
 	if (fde == NULL) {
 		TALLOC_FREE(result);
@@ -75,16 +94,17 @@ struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
 	return result;
 }
 
-static void async_send_handler(struct tevent_context *ev,
+static void sendto_handler(struct tevent_context *ev,
 			       struct tevent_fd *fde,
 			       uint16_t flags, void *private_data)
 {
 	struct tevent_req *req = talloc_get_type_abort(
 		private_data, struct tevent_req);
-	struct async_send_state *state =
-		tevent_req_data(req, struct async_send_state);
+	struct sendto_state *state =
+		tevent_req_data(req, struct sendto_state);
 
-	state->sent = send(state->fd, state->buf, state->len, state->flags);
+	state->sent = sendto(state->fd, state->buf, state->len, state->flags,
+			     (struct sockaddr *)state->addr, state->addr_len);
 	if ((state->sent == -1) && (errno == EINTR)) {
 		/* retry */
 		return;
@@ -96,10 +116,10 @@ static void async_send_handler(struct tevent_context *ev,
 	tevent_req_done(req);
 }
 
-ssize_t async_send_recv(struct tevent_req *req, int *perrno)
+ssize_t sendto_recv(struct tevent_req *req, int *perrno)
 {
-	struct async_send_state *state =
-		tevent_req_data(req, struct async_send_state);
+	struct sendto_state *state =
+		tevent_req_data(req, struct sendto_state);
 
 	if (tevent_req_is_unix_error(req, perrno)) {
 		return -1;
@@ -107,27 +127,31 @@ ssize_t async_send_recv(struct tevent_req *req, int *perrno)
 	return state->sent;
 }
 
-struct async_recv_state {
+struct recvfrom_state {
 	int fd;
 	void *buf;
 	size_t len;
 	int flags;
+	struct sockaddr_storage *addr;
+	socklen_t *addr_len;
 	ssize_t received;
 };
 
-static void async_recv_handler(struct tevent_context *ev,
+static void recvfrom_handler(struct tevent_context *ev,
 			       struct tevent_fd *fde,
 			       uint16_t flags, void *private_data);
 
-struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx,
-				   struct tevent_context *ev,
-				   int fd, void *buf, size_t len, int flags)
+struct tevent_req *recvfrom_send(TALLOC_CTX *mem_ctx,
+				 struct tevent_context *ev,
+				 int fd, void *buf, size_t len, int flags,
+				 struct sockaddr_storage *addr,
+				 socklen_t *addr_len)
 {
 	struct tevent_req *result;
-	struct async_recv_state *state;
+	struct recvfrom_state *state;
 	struct tevent_fd *fde;
 
-	result = tevent_req_create(mem_ctx, &state, struct async_recv_state);
+	result = tevent_req_create(mem_ctx, &state, struct recvfrom_state);
 	if (result == NULL) {
 		return result;
 	}
@@ -135,8 +159,10 @@ struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx,
 	state->buf = buf;
 	state->len = len;
 	state->flags = flags;
+	state->addr = addr;
+	state->addr_len = addr_len;
 
-	fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, async_recv_handler,
+	fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, recvfrom_handler,
 			    result);
 	if (fde == NULL) {
 		TALLOC_FREE(result);
@@ -145,17 +171,18 @@ struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx,
 	return result;
 }
 
-static void async_recv_handler(struct tevent_context *ev,
+static void recvfrom_handler(struct tevent_context *ev,
 			       struct tevent_fd *fde,
 			       uint16_t flags, void *private_data)
 {
 	struct tevent_req *req = talloc_get_type_abort(
 		private_data, struct tevent_req);
-	struct async_recv_state *state =
-		tevent_req_data(req, struct async_recv_state);
+	struct recvfrom_state *state =
+		tevent_req_data(req, struct recvfrom_state);
 
-	state->received = recv(state->fd, state->buf, state->len,
-			       state->flags);
+	state->received = recvfrom(state->fd, state->buf, state->len,
+				   state->flags, (struct sockaddr *)state->addr,
+				   state->addr_len);
 	if ((state->received == -1) && (errno == EINTR)) {
 		/* retry */
 		return;
@@ -171,10 +198,10 @@ static void async_recv_handler(struct tevent_context *ev,
 	tevent_req_done(req);
 }
 
-ssize_t async_recv_recv(struct tevent_req *req, int *perrno)
+ssize_t recvfrom_recv(struct tevent_req *req, int *perrno)
 {
-	struct async_recv_state *state =
-		tevent_req_data(req, struct async_recv_state);
+	struct recvfrom_state *state =
+		tevent_req_data(req, struct recvfrom_state);
 
 	if (tevent_req_is_unix_error(req, perrno)) {
 		return -1;
diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h
index e7ddff8..8d98886 100644
--- a/lib/async_req/async_sock.h
+++ b/lib/async_req/async_sock.h
@@ -27,16 +27,17 @@
 #include <talloc.h>
 #include <tevent.h>
 
-struct tevent_req *async_send_send(TALLOC_CTX *mem_ctx,
-				   struct tevent_context *ev,
-				   int fd, const void *buf, size_t len,
-				   int flags);
-ssize_t async_send_recv(struct tevent_req *req, int *perrno);
-
-struct tevent_req *async_recv_send(TALLOC_CTX *mem_ctx,
-				   struct tevent_context *ev,
-				   int fd, void *buf, size_t len, int flags);
-ssize_t async_recv_recv(struct tevent_req *req, int *perrno);
+struct tevent_req *sendto_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+			       int fd, const void *buf, size_t len, int flags,
+			       const struct sockaddr_storage *addr);
+ssize_t sendto_recv(struct tevent_req *req, int *perrno);
+
+struct tevent_req *recvfrom_send(TALLOC_CTX *mem_ctx,
+				 struct tevent_context *ev,
+				 int fd, void *buf, size_t len, int flags,
+				 struct sockaddr_storage *addr,
+				 socklen_t *addr_len);
+ssize_t recvfrom_recv(struct tevent_req *req, int *perrno);
 
 struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx,
 				      struct tevent_context *ev,
diff --git a/lib/tdb/tools/tdbtest.c b/lib/tdb/tools/tdbtest.c
index 416bc50..44c78ef 100644
--- a/lib/tdb/tools/tdbtest.c
+++ b/lib/tdb/tools/tdbtest.c
@@ -215,16 +215,38 @@ static void merge_test(void)
 	tdb_delete(db, key);
 }
 
+static char *test_path(const char *filename)
+{
+	const char *prefix = getenv("TEST_DATA_PREFIX");
+
+	if (prefix) {
+		char *path = NULL;
+		int ret;
+
+		ret = asprintf(&path, "%s/%s", prefix, filename);
+		if (ret == -1) {
+			return NULL;
+		}
+		return path;
+	}
+
+	return strdup(filename);
+}
+
  int main(int argc, const char *argv[])
 {
 	int i, seed=0;
 	int loops = 10000;
 	int num_entries;
-	char test_gdbm[] = "test.gdbm";
+	char test_gdbm[1] = "test.gdbm";
+	char *test_tdb;
 
-	unlink("test.gdbm");
+	test_gdbm[0] = test_path("test.gdbm");
+	test_tdb = test_path("test.tdb");
 
-	db = tdb_open("test.tdb", 0, TDB_CLEAR_IF_FIRST, 
+	unlink(test_gdbm[0]);
+
+	db = tdb_open(test_tdb, 0, TDB_CLEAR_IF_FIRST,
 		      O_RDWR | O_CREAT | O_TRUNC, 0600);
 	gdbm = gdbm_open(test_gdbm, 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST, 
 			 0600, NULL);
@@ -261,5 +283,8 @@ static void merge_test(void)
 	tdb_close(db);
 	gdbm_close(gdbm);
 
+	free(test_gdbm[0]);
+	free(test_tdb);
+
 	return 0;
 }
diff --git a/lib/tdb/tools/tdbtorture.c b/lib/tdb/tools/tdbtorture.c
index 79fe3cd..64c5043 100644
--- a/lib/tdb/tools/tdbtorture.c
+++ b/lib/tdb/tools/tdbtorture.c
@@ -228,9 +228,9 @@ static void send_count_and_suicide(int sig)
 	kill(getpid(), SIGUSR2);
 }
 
-static int run_child(int i, int seed, unsigned num_loops, unsigned start)
+static int run_child(const char *filename, int i, int seed, unsigned num_loops, unsigned start)
 {
-	db = tdb_open_ex("torture.tdb", hash_size, TDB_DEFAULT,
+	db = tdb_open_ex(filename, hash_size, TDB_DEFAULT,
 			 O_RDWR | O_CREAT, 0600, &log_ctx, NULL);
 	if (!db) {
 		fatal("db open failed");
@@ -270,6 +270,24 @@ static int run_child(int i, int seed, unsigned num_loops, unsigned start)
 	return (error_count < 100 ? error_count : 100);
 }
 
+static char *test_path(const char *filename)
+{
+	const char *prefix = getenv("TEST_DATA_PREFIX");
+
+	if (prefix) {
+		char *path = NULL;
+		int ret;
+
+		ret = asprintf(&path, "%s/%s", prefix, filename);
+		if (ret == -1) {
+			return NULL;
+		}
+		return path;
+	}
+
+	return strdup(filename);
+}
+
 int main(int argc, char * const *argv)
 {
 	int i, seed = -1;
@@ -280,6 +298,7 @@ int main(int argc, char * const *argv)
 	pid_t *pids;
 	int kill_random = 0;
 	int *done;
+	char *test_tdb;
 
 	log_ctx.log_fn = tdb_log;
 
@@ -308,7 +327,9 @@ int main(int argc, char * const *argv)
 		}
 	}
 
-	unlink("torture.tdb");
+	test_tdb = test_path("torture.tdb");
+
+	unlink(test_tdb);
 
 	if (seed == -1) {
 		seed = (getpid() + time(NULL)) & 0x7FFFFFFF;
@@ -316,7 +337,7 @@ int main(int argc, char * const *argv)
 
 	if (num_procs == 1 && !kill_random) {
 		/* Don't fork for this case, makes debugging easier. */
-		error_count = run_child(0, seed, num_loops, 0);
+		error_count = run_child(test_tdb, 0, seed, num_loops, 0);
 		goto done;
 	}
 
@@ -336,7 +357,7 @@ int main(int argc, char * const *argv)
 				printf("Testing with %d processes, %d loops, %d hash_size, seed=%d%s\n",
 				       num_procs, num_loops, hash_size, seed, always_transaction ? " (all within transactions)" : "");
 			}
-			exit(run_child(i, seed, num_loops, 0));
+			exit(run_child(test_tdb, i, seed, num_loops, 0));
 		}
 	}
 
@@ -389,8 +410,8 @@ int main(int argc, char * const *argv)
 				}
 				pids[j] = fork();
 				if (pids[j] == 0)
-					exit(run_child(j, seed, num_loops,
-						       done[j]));
+					exit(run_child(test_tdb, j, seed,
+						       num_loops, done[j]));
 				printf("Restarting child %i for %u-%u\n",
 				       j, done[j], num_loops);
 				continue;
@@ -414,7 +435,7 @@ int main(int argc, char * const *argv)
 
 done:
 	if (error_count == 0) {
-		db = tdb_open_ex("torture.tdb", hash_size, TDB_DEFAULT,
+		db = tdb_open_ex(test_tdb, hash_size, TDB_DEFAULT,
 				 O_RDWR, 0, &log_ctx, NULL);
 		if (!db) {
 			fatal("db open failed");
@@ -427,5 +448,6 @@ done:
 		printf("OK\n");
 	}
 
+	free(test_tdb);
 	return error_count;
 }
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index 1c01a63..d67e2b0 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -520,9 +520,65 @@ int tevent_set_debug_stderr(struct tevent_context *ev);
  * requests are much easier to compose than the low-level event
  * handlers called from tevent_add_fd.
  *
+ * A lot of the simplicity tevent_req has brought to the notoriously
+ * hairy async programming came via a set of conventions that every
+ * async computation programmed should follow. One central piece of
+ * these conventions is the naming of routines and variables.
+ *
+ * Every async computation needs a name (sensibly called "computation"
+ * down from here). From this name quite a few naming conventions are
+ * derived.
+ *
+ * Every computation that requires local state needs a
+ * @code
+ * struct computation_state {
+ *     int local_var;
+ * };
+ * @endcode
+ * Even if no local variables are required, such a state struct should
+ * be created containing a dummy variable. Quite a few helper
+ * functions and macros (for example tevent_req_create()) assume such
+ * a state struct.
+ *
  * An async computation is started by a computation_send
  * function. When it is finished, its result can be received by a
- * computation_recv function.
+ * computation_recv function. For an example how to set up an async
+ * computation, see the code example in the documentation for
+ * tevent_req_create() and tevent_req_post(). The prototypes for _send
+ * and _recv functions should follow some conventions:
+ *
+ * @code
+ * struct tevent_req *computation_send(TALLOC_CTX *mem_ctx,
+ *                                     struct tevent_req *ev,
+ *                                     ... further args);
+ * int computation_recv(struct tevent_req *req, ... further output args);
+ * @endcode
+ *
+ * The "int" result of computation_recv() depends on the result the
+ * sync version of the function would have, "int" is just an example
+ * here.
+ *
+ * Another important piece of the conventions is that the program flow
+ * is interrupted as little as possible. Because a blocking
+ * sub-computation requires that the flow needs to continue in a
+ * separate function that is the logical sequel of some computation,
+ * it should lexically follow sending off the blocking
+ * sub-computation. Setting the callback function via
+ * tevent_req_set_callback() requires referencing a function lexically
+ * below the call to tevent_req_set_callback(), forward declarations
+ * are required. A lot of the async computations thus begin with a
+ * sequence of declarations such as
+ *
+ * @code
+ * static void computation_step1_done(struct tevent_req *subreq);
+ * static void computation_step2_done(struct tevent_req *subreq);
+ * static void computation_step3_done(struct tevent_req *subreq);
+ * @endcode
+ *
+ * It really helps readability a lot to do these forward declarations,
+ * because the lexically sequential program flow makes the async
+ * computations almost as clear to read as a normal, sync program
+ * flow.
  *
  * It is up to the user of the async computation to talloc_free it
  * after it has finished. If an async computation should be aborted,
@@ -587,6 +643,9 @@ typedef void (*tevent_req_fn)(struct tevent_req *req);
 /**
  * @brief Set an async request callback.
  *
+ * See the documentation of tevent_req_post() for an example how this
+ * is supposed to be used.
+ *
  * @param[in]  req      The async request to set the callback.
  *
  * @param[in]  fn       The callback function to set.
@@ -642,6 +701,10 @@ void *tevent_req_callback_data_void(struct tevent_req *req);
 /**
  * @brief Get the private data from a tevent request structure.
  *
+ * When the tevent_req has been created by tevent_req_create, the
+ * result of tevent_req_data() is the state variable created by
+ * tevent_req_create() as a child of the req.
+ *
  * @param[in]  req      The structure to get the private data from.
  *
  * @param[in]  type	The type of the private data
@@ -788,6 +851,13 @@ bool _tevent_req_cancel(struct tevent_req *req, const char *location);
  * req = tevent_req_create(mem_ctx, &state, struct computation_state);
  * @endcode
  *
+ * Tevent_req_create() creates the state variable as a talloc child of
+ * its result. The state variable should be used as the talloc parent
+ * for all temporary variables that are allocated during the async
+ * computation. This way, when the user of the async computation frees
+ * the request, the state as a talloc child will be free'd along with
+ * all the temporary variables hanging off the state.
+ *
  * @param[in] mem_ctx   The memory context for the result.
  * @param[in] pstate    Pointer to the private request state.
  * @param[in] type      The name of the request.
@@ -949,6 +1019,7 @@ bool _tevent_req_nomem(const void *p,
  *     if (tevent_req_nomem(subreq, req)) {
  *         return tevent_req_post(req, ev);
  *     }
+ *     tevent_req_set_callback(subreq, computation_done, req);
  *     return req;
  * }


-- 
Samba Shared Repository


More information about the samba-cvs mailing list