Bachelor thesis - tevent

Michael Adam obnox at samba.org
Wed Nov 28 04:14:53 MST 2012


On 2012-11-28 at 10:33 +0100, Volker Lendecke wrote:
> On Wed, Nov 28, 2012 at 10:26:13AM +0100, Jakub Hrozek wrote:
> > On Sun, Nov 25, 2012 at 09:19:19PM +0100, Volker Lendecke wrote:
> > > On Sun, Nov 25, 2012 at 06:23:11PM +0100, Koňař David wrote:
> > > > I'm working on a bachelor thesis about tevent event system under
> > > > supervision of Red Hat branch in Brno. One of its parts is to create
> > > > a tutorial for tevent.
> > > > 
> > > > Right now I'm at the beginning of my work and I would like to ask
> > > > you if there are some important parts in tevent which I should pay
> > > > extra attention?
> > > 
> > > Tevent as such is "just" another event library similar to
> > > libevent or libev or many others. It has two additional
> > > twists: It is based on talloc, and it can pass on the
> > > siginfo signal information. Beyond that's there is not
> > > really much that it adds.
> > > 
> > > The piece that makes a difference is the tevent_req API.
> > > This enables composable async sequences of events to be
> > > coded in C relatively easy. See
> > > https://tevent.samba.org/group__tevent__request.html for a
> > > quick overview, and source3/winbind/*.c for a lot of
> > > examples how it is used.
> > > 
> > > With best regards,
> > > 
> > > Volker Lendecke
> > 
> > I think I had an audio recording of your SambaXP talk on tevent a while
> > ago. It was only audio, though, no slides or video. Was there any more
> > recording of that talk? Maybe that would be helpful to David.
> 
> Sorry, I do not have any slides, because I was showing code.
> At one time I went through developing a simple example
> online. We did not videotape that. I am happy to answer
> questions about tevent though.
> 
> Someone might still have that example I developed in their
> samba-team folders. I have that archived somewhere, maybe
> someone else has quick access to that. Günther? Andreas
> maybe?

Attached find the git patchset to master from May.
I applied Volker's demo program, added it
also to the waf build and then worked some with the
demo code to learn/understand myself.

Cheers - Michael

-------------- next part --------------
From 81fdb2fb66eb0865b34d0454cb0b8f42c0c45baa Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Thu, 10 May 2012 12:01:25 +0200
Subject: [PATCH 1/3] SambaXP test code

---
 source3/Makefile.in               |    1 +
 source3/torture/proto.h           |    1 +
 source3/torture/test_tevent_req.c |  151 +++++++++++++++++++++++++++++++++++++
 source3/torture/torture.c         |    1 +
 4 files changed, 154 insertions(+)
 create mode 100644 source3/torture/test_tevent_req.c

diff --git a/source3/Makefile.in b/source3/Makefile.in
index e289252..c429a75 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -1280,6 +1280,7 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/uta
 		torture/test_notify.o \
 		torture/test_dbwrap_watch.o \
 		torture/test_idmap_tdb_common.o \
+		torture/test_tevent_req.o \
 		torture/t_strappend.o
 
 SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) $(TLDAP_OBJ) \
diff --git a/source3/torture/proto.h b/source3/torture/proto.h
index 80618ce..4232390 100644
--- a/source3/torture/proto.h
+++ b/source3/torture/proto.h
@@ -110,5 +110,6 @@ bool run_notify_bench2(int dummy);
 bool run_notify_bench3(int dummy);
 bool run_dbwrap_watch1(int dummy);
 bool run_idmap_tdb_common_test(int dummy);
+bool run_test_tevent_req(int dummy);
 
 #endif /* __TORTURE_H__ */
diff --git a/source3/torture/test_tevent_req.c b/source3/torture/test_tevent_req.c
new file mode 100644
index 0000000..c9049cd
--- /dev/null
+++ b/source3/torture/test_tevent_req.c
@@ -0,0 +1,151 @@
+/*
+   Unix SMB/CIFS implementation.
+   test tevent_req api
+   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 "torture/proto.h"
+#include "lib/util/tevent_unix.h"
+#include "lib/util/tevent_ntstatus.h"
+
+struct hello_state {
+	struct tevent_context *ev;
+	const char *msg;
+	int interval;
+	int num_loops;
+};
+
+static void hello_waited(struct tevent_req *subreq);
+
+struct tevent_req *hello_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+			      const char *msg, int interval, int num_loops)
+{
+	struct tevent_req *req, *subreq;
+	struct hello_state *state;
+
+	req = tevent_req_create(mem_ctx, &state, struct hello_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->ev = ev;
+	state->msg = msg;
+	state->interval = interval;
+	state->num_loops = num_loops;
+
+	if (strlen(msg) == 0) {
+		tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+		return tevent_req_post(req, ev);
+	}
+
+	subreq = tevent_wakeup_send(
+		state, state->ev, timeval_current_ofs(state->interval, 0));
+	if (tevent_req_nomem(subreq, req)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, hello_waited, req);
+	return req;
+}
+
+static void hello_waited(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct hello_state *state = tevent_req_data(
+		req, struct hello_state);
+	bool ret;
+
+	ret = tevent_wakeup_recv(subreq);
+	TALLOC_FREE(subreq);
+	if (!ret) {
+		tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+		return;
+	}
+
+	printf("%s\n", state->msg);
+
+	state->num_loops -= 1;
+	if (state->num_loops == 0) {
+		tevent_req_done(req);
+		return;
+	}
+
+	subreq = tevent_wakeup_send(
+		state, state->ev, timeval_current_ofs(state->interval, 0));
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq, hello_waited, req);
+}
+
+NTSTATUS hello_recv(struct tevent_req *req)
+{
+	NTSTATUS status;
+
+	if (tevent_req_is_nterror(req, &status)) {
+		return status;
+	}
+	return NT_STATUS_OK;
+}
+
+static void run_test_done(struct tevent_req *req)
+{
+	int *num_done = (int *)tevent_req_callback_data_void(req);
+	*num_done += 1;
+}
+
+bool run_test_tevent_req(int dummy)
+{
+	struct tevent_context *ev;
+	struct tevent_req *req;
+	int num_done;
+
+	printf("Running tevent_req test\n");
+
+	ev = tevent_context_init(talloc_tos());
+	if (ev == NULL) {
+		fprintf(stderr, "tevent_context_init failed\n");
+		return false;
+	}
+
+	num_done = 0;
+
+	req = hello_send(talloc_tos(), ev, "hello", 1, 5);
+	if (req == NULL) {
+		fprintf(stderr, "hello_send failed\n");
+		return false;
+	}
+	tevent_req_set_callback(req, run_test_done, &num_done);
+
+	req = hello_send(talloc_tos(), ev, "world", 2, 3);
+	if (req == NULL) {
+		fprintf(stderr, "hello_send failed\n");
+		return false;
+	}
+	tevent_req_set_callback(req, run_test_done, &num_done);
+
+	while (num_done < 2) {
+		int ret;
+
+		ret = tevent_loop_once(ev);
+		if (ret != 0) {
+			fprintf(stderr, "tevent_loop_once failed\n");
+			return false;
+		}
+	}
+
+	return true;
+}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index 83b0666..a00e638 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -9040,6 +9040,7 @@ static struct {
 	{ "LOCAL-hex_encode_buf", run_local_hex_encode_buf, 0},
 	{ "LOCAL-IDMAP-TDB-COMMON", run_idmap_tdb_common_test, 0},
 	{ "LOCAL-remove_duplicate_addrs2", run_local_remove_duplicate_addrs2, 0},
+	{ "LOCAL-TEVENT-REQ", run_test_tevent_req, 0},
 	{NULL, NULL, 0}};
 
 
-- 
1.7.9.5


From adb9032098c181057d88c2cdb1f2ae286c04be80 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 18 May 2012 15:03:39 +0200
Subject: [PATCH 2/3] s3:build: add test_tevent_req.c to the s3-torture build

---
 source3/wscript_build |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/source3/wscript_build b/source3/wscript_build
index 0b96ccc..cb6c498 100755
--- a/source3/wscript_build
+++ b/source3/wscript_build
@@ -552,7 +552,8 @@ SMBTORTURE_SRC1 = '''torture/torture.c torture/nbio.c torture/scanner.c torture/
                 lib/tevent_barrier.c
                 torture/test_dbwrap_watch.c
                 torture/test_idmap_tdb_common.c
-                torture/t_strappend.c'''
+                torture/t_strappend.c
+                torture/test_tevent_req.c'''
 
 SMBTORTURE_SRC = '''${SMBTORTURE_SRC1}
         torture/wbc_async.c'''
-- 
1.7.9.5


From f0493c0fce12a24a08b12fac26405d8112995bd8 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Fri, 18 May 2012 15:05:26 +0200
Subject: [PATCH 3/3] s3:torture:test_tevent_req: some updates

---
 source3/torture/test_tevent_req.c |   96 +++++++++++++++++++++++++++++--------
 1 file changed, 77 insertions(+), 19 deletions(-)

diff --git a/source3/torture/test_tevent_req.c b/source3/torture/test_tevent_req.c
index c9049cd..ff459d5 100644
--- a/source3/torture/test_tevent_req.c
+++ b/source3/torture/test_tevent_req.c
@@ -22,6 +22,11 @@
 #include "lib/util/tevent_unix.h"
 #include "lib/util/tevent_ntstatus.h"
 
+/*
+ * =====================================================
+ * start of implementation of the async function "hello"
+ */
+
 struct hello_state {
 	struct tevent_context *ev;
 	const char *msg;
@@ -31,6 +36,7 @@ struct hello_state {
 
 static void hello_waited(struct tevent_req *subreq);
 
+static
 struct tevent_req *hello_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 			      const char *msg, int interval, int num_loops)
 {
@@ -91,6 +97,7 @@ static void hello_waited(struct tevent_req *subreq)
 	tevent_req_set_callback(subreq, hello_waited, req);
 }
 
+static
 NTSTATUS hello_recv(struct tevent_req *req)
 {
 	NTSTATUS status;
@@ -101,17 +108,39 @@ NTSTATUS hello_recv(struct tevent_req *req)
 	return NT_STATUS_OK;
 }
 
-static void run_test_done(struct tevent_req *req)
-{
-	int *num_done = (int *)tevent_req_callback_data_void(req);
-	*num_done += 1;
-}
+/*
+ * up to here: implementation of the async function "hello"
+ * ========================================================
+ */
+
+
+/*
+ * ==================================================
+ * from here: code calling the async function "hello"
+ */
+
+
+struct hello_input {
+	const char *message;
+	int interval;
+	int num_loops;
+};
+
+static struct hello_input hello_input[] = {
+	{ "hello1", 1, 5 },
+	{ "hello2", 2, 3 },
+	{ "hello3", 1, 4 },
+	{ NULL, 0, 0},
+};
+
+static void run_test_tevent_req_done(struct tevent_req *subreq);
 
 bool run_test_tevent_req(int dummy)
 {
 	struct tevent_context *ev;
 	struct tevent_req *req;
-	int num_done;
+	int num_done, num_instances;
+	int count;
 
 	printf("Running tevent_req test\n");
 
@@ -121,23 +150,35 @@ bool run_test_tevent_req(int dummy)
 		return false;
 	}
 
-	num_done = 0;
-
-	req = hello_send(talloc_tos(), ev, "hello", 1, 5);
-	if (req == NULL) {
-		fprintf(stderr, "hello_send failed\n");
-		return false;
+	/*
+	 * determine number of instances
+	 */
+	for (count = 0; hello_input[count].message != NULL; count++) {
 	}
-	tevent_req_set_callback(req, run_test_done, &num_done);
+	num_instances = count;
 
-	req = hello_send(talloc_tos(), ev, "world", 2, 3);
-	if (req == NULL) {
-		fprintf(stderr, "hello_send failed\n");
-		return false;
+	num_done = 0;
+
+	/*
+	 * fire off the instances of hello
+	 */
+	for (count = 0; count < num_instances; count++) {
+		req = hello_send(talloc_tos(), ev,
+				 hello_input[count].message,
+				 hello_input[count].interval,
+				 hello_input[count].num_loops);
+		if (req == NULL) {
+			fprintf(stderr, "hello_send failed\n");
+			return false;
+		}
+		tevent_req_set_callback(req, run_test_tevent_req_done,
+					&num_done);
 	}
-	tevent_req_set_callback(req, run_test_done, &num_done);
 
-	while (num_done < 2) {
+	/*
+	 * wait for instances of hello to finish
+	 */
+	while (num_done < num_instances) {
 		int ret;
 
 		ret = tevent_loop_once(ev);
@@ -149,3 +190,20 @@ bool run_test_tevent_req(int dummy)
 
 	return true;
 }
+
+/**
+ * callback to get the "result" of the async fct "hello".
+ */
+static void run_test_tevent_req_done(struct tevent_req *req)
+{
+	int *num_done = (int *)tevent_req_callback_data_void(req);
+	NTSTATUS status;
+
+	status = hello_recv(req);
+	TALLOC_FREE(req);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("run_test_done: hello_recv failed: %s\n", nt_errstr(status));
+	}
+
+	*num_done += 1;
+}
-- 
1.7.9.5

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 206 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20121128/3cabb32a/attachment.pgp>


More information about the samba-technical mailing list