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 <[email protected]>
Date:   Thu Dec 30 12:42:50 2010 +0100

    s3: Fix two uninitialized variables
    
    Autobuild-User: Volker Lendecke <[email protected]>
    Autobuild-Date: Thu Dec 30 12:52:47 CET 2010 on sn-devel-104
    (cherry picked from commit d05fb4b7b79fa5ef240864f0f0f544bbba1b59e3)

commit 61186b5281d23823a7ee99b7d552b2d8d7e07acc
Author: Volker Lendecke <[email protected]>
Date:   Thu Dec 23 15:20:22 2010 +0100

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

commit 5ea88afaf4982d4f327897c6474034f9aae04d85
Author: Volker Lendecke <[email protected]>
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 <[email protected]>
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 <[email protected]>
    Autobuild-Date: Tue Dec 28 18:21:05 CET 2010 on sn-devel-104
    (cherry picked from commit 4622812a41eb5ce07dd8f74534217e858743883f)

commit d7c32ae6fcab9205abf86b0d8fd1f92f410ccecf
Author: Volker Lendecke <[email protected]>
Date:   Tue Dec 28 17:17:04 2010 +0100

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

commit 030f2ff39a64a8d378c1c2a9027e5152e17e83b3
Author: Volker Lendecke <[email protected]>
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 <[email protected]>
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 <[email protected]>
    Autobuild-Date: Tue Dec 28 13:46:59 CET 2010 on sn-devel-104
    (cherry picked from commit 571711431885e8e556822c14b3d117025860bf81)

commit ef6cb55db8457654d5d19d4c4f9d859864d40ca8
Author: Volker Lendecke <[email protected]>
Date:   Tue Dec 28 11:55:47 2010 +0100

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

commit 522cbb353ff988d3275f4449d97485a42a76d5af
Author: Volker Lendecke <[email protected]>
Date:   Tue Dec 28 11:48:43 2010 +0100

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

commit 80ef0195bd42a3d4fcd1a03e85ea06dc85cee757
Author: Volker Lendecke <[email protected]>
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 <[email protected]>
Date:   Fri Dec 24 11:54:51 2010 +0100

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

commit 8b916ab9203188bd47c8f9afcdb17d183ccd2167
Author: Stefan Metzmacher <[email protected]>
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 <[email protected]>
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 <[email protected]>
    Autobuild-Date: Thu Dec 23 23:40:21 CET 2010 on sn-devel-104
    (cherry picked from commit 821b2a9d1197d927ab6081bcd953a0540888dcf3)

commit 72b35f9a81029c1c336df8a48a7534970d4d89f6
Author: Volker Lendecke <[email protected]>
Date:   Sun Dec 26 15:00:53 2010 +0100

    tevent: More documentation updates
    
    Autobuild-User: Volker Lendecke <[email protected]>
    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

Reply via email to