Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Lesson 7: timers (plus some cleanups)
authormquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Sun, 16 Jul 2006 17:45:15 +0000 (17:45 +0000)
committermquinson <mquinson@48e7efb5-ca39-0410-a469-dd3cf9ba447f>
Sun, 16 Jul 2006 17:45:15 +0000 (17:45 +0000)
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/simgrid/simgrid/trunk@2593 48e7efb5-ca39-0410-a469-dd3cf9ba447f

doc/Doxyfile.in
doc/gtut-files/.cvsignore
doc/gtut-files/7-timers.c [new file with mode: 0644]
doc/gtut-files/7-timers.output [new file with mode: 0644]
doc/gtut-files/Makefile
doc/gtut-main.doc
doc/gtut-tour-6-logs.doc
doc/gtut-tour-7-timers.doc [new file with mode: 0644]
doc/gtut-tour.doc

index f83edce..8edce6f 100644 (file)
@@ -415,6 +415,7 @@ INPUT                  = @srcdir@/index.doc \
                                @srcdir@/gtut-tour-4-callback.doc \
                                @srcdir@/gtut-tour-5-globals.doc \
                                @srcdir@/gtut-tour-6-logs.doc \
+                               @srcdir@/gtut-tour-7-timers.doc \
                         \
                          ./logcategories.doc \
                         \
index 6449498..73be037 100644 (file)
@@ -51,3 +51,12 @@ _5-globals_simulator.c
 _6-logs_client.c
 _6-logs_server.c
 _6-logs_simulator.c
+
+7-timers.mk
+7-timers.trace
+7-timers_client
+7-timers_server
+7-timers_simulator
+_7-timers_client.c
+_7-timers_server.c
+_7-timers_simulator.c
diff --git a/doc/gtut-files/7-timers.c b/doc/gtut-files/7-timers.c
new file mode 100644 (file)
index 0000000..6622034
--- /dev/null
@@ -0,0 +1,113 @@
+#include <gras.h>
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(test,"My little example");
+
+/* *********************** Server *********************** */
+typedef struct {
+   int killed;
+} server_data_t;   
+
+int server_kill_cb(gras_msg_cb_ctx_t ctx, void *payload) {
+  gras_socket_t client = gras_msg_cb_ctx_from(ctx);
+  server_data_t *globals=(server_data_t*)gras_userdata_get();
+   
+  CRITICAL2("Argh, killed by %s:%d! Bye folks...",
+       gras_socket_peer_name(client), gras_socket_peer_port(client));
+  
+  globals->killed = 1;
+   
+  return 1;
+} /* end_of_kill_callback */
+
+int server_hello_cb(gras_msg_cb_ctx_t ctx, void *payload) {
+  gras_socket_t client = gras_msg_cb_ctx_from(ctx);
+
+  INFO2("Cool, we received the message from %s:%d.",
+       gras_socket_peer_name(client), gras_socket_peer_port(client));
+  
+  return 1;
+} /* end_of_hello_callback */
+
+int server(int argc, char *argv[]) {
+  gras_socket_t mysock;   /* socket on which I listen */
+  server_data_t *globals;
+  
+  gras_init(&argc,argv);
+
+  globals=gras_userdata_new(server_data_t*);
+  globals->killed=0;
+
+  gras_msgtype_declare("hello", NULL);
+  gras_msgtype_declare("kill", NULL);
+  mysock = gras_socket_server(atoi(argv[1]));
+   
+  gras_cb_register(gras_msgtype_by_name("hello"),&server_hello_cb);   
+  gras_cb_register(gras_msgtype_by_name("kill"),&server_kill_cb);
+
+  while (!globals->killed) {
+     gras_msg_handle(60);
+  }
+    
+  gras_exit();
+  return 0;
+}
+
+/* *********************** Client *********************** */
+/* client_data */
+typedef struct {
+   gras_socket_t toserver;
+   int done;
+} client_data_t;
+
+void client_do_hello(void) {
+  client_data_t *globals=(client_data_t*)gras_userdata_get();
+   
+  gras_msg_send(globals->toserver,gras_msgtype_by_name("hello"), NULL);
+  INFO0("Hello sent to server");
+} /* end_of_client_do_hello */
+
+void client_do_stop(void) {
+  client_data_t *globals=(client_data_t*)gras_userdata_get();
+   
+  gras_msg_send(globals->toserver,gras_msgtype_by_name("kill"), NULL);
+  INFO0("Kill sent to server");
+   
+  gras_timer_cancel_repeat(0.5,client_do_hello);
+  globals->done = 1;
+  INFO0("Break the client's while loop");
+} /* end_of_client_do_stop */
+
+int client(int argc, char *argv[]) {
+  gras_socket_t mysock;   /* socket on which I listen */
+  client_data_t *globals;
+
+  gras_init(&argc,argv);
+
+  gras_msgtype_declare("hello", NULL);
+  gras_msgtype_declare("kill", NULL);
+  mysock = gras_socket_server_range(1024, 10000, 0, 0);
+  
+  VERB1("Client ready; listening on %d", gras_socket_my_port(mysock));
+  
+  globals=gras_userdata_new(server_data_t*);
+  globals->done = 0;
+  
+  gras_os_sleep(1.5); /* sleep 1 second and half */
+  globals->toserver = gras_socket_client(argv[1], atoi(argv[2]));
+   
+  INFO0("Programming the repetitive action with a frequency of 0.5 sec");
+  gras_timer_repeat(0.5,client_do_hello);
+  
+  INFO0("Programming the delayed action in 5 secs");
+  gras_timer_delay(5,client_do_stop);
+  
+  while (!globals->done) {
+     gras_msg_handle(60);
+  }
+
+  gras_exit();
+  return 0;
+}
+
diff --git a/doc/gtut-files/7-timers.output b/doc/gtut-files/7-timers.output
new file mode 100644 (file)
index 0000000..152b70a
--- /dev/null
@@ -0,0 +1,57 @@
+$ ./test_server 12345 & ./test_client 127.0.0.1 12345
+[blaise:server:(23608) 0.000005] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024.
+[blaise:server:(23608) 0.500361] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024.
+[blaise:server:(23608) 1.003121] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024.
+[blaise:server:(23608) 1.507935] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024.
+[blaise:server:(23608) 2.010545] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024.
+[blaise:server:(23608) 2.516219] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024.
+[blaise:server:(23608) 3.018509] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024.
+[blaise:server:(23608) 3.518713] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024.
+[blaise:server:(23608) 4.022585] test.c:26: [test/INFO] Cool, we received the message from 127.0.0.1:1024.
+[blaise:server:(23608) 4.482905] test.c:15: [test/CRITICAL] Argh, killed by 127.0.0.1:1024! Bye folks...
+[blaise:server:(23608) 4.482930] gras/gras.c:79: [gras/INFO] Exiting GRAS
+[blaise:client:(23611) 0.000005] test.c:99: [test/INFO] Programming the repetitive action with a frequency of 0.5 sec
+[blaise:client:(23611) 0.000071] test.c:102: [test/INFO] Programming the delayed action in 5 secs
+[blaise:client:(23611) 0.518553] test.c:66: [test/INFO] Hello sent to server
+[blaise:client:(23611) 1.020515] test.c:66: [test/INFO] Hello sent to server
+[blaise:client:(23611) 1.523454] test.c:66: [test/INFO] Hello sent to server
+[blaise:client:(23611) 2.027895] test.c:66: [test/INFO] Hello sent to server
+[blaise:client:(23611) 2.530948] test.c:66: [test/INFO] Hello sent to server
+[blaise:client:(23611) 3.035530] test.c:66: [test/INFO] Hello sent to server
+[blaise:client:(23611) 3.538912] test.c:66: [test/INFO] Hello sent to server
+[blaise:client:(23611) 4.038965] test.c:66: [test/INFO] Hello sent to server
+[blaise:client:(23611) 4.542989] test.c:66: [test/INFO] Hello sent to server
+[blaise:client:(23611) 5.003026] test.c:73: [test/INFO] Kill sent to server
+[blaise:client:(23611) 5.003056] test.c:78: [test/INFO] Break the client's while loop
+[blaise:client:(23611) 5.003071] gras/gras.c:79: [gras/INFO] Exiting GRAS
+$
+$ ./test_simulator platform.xml test.xml
+[Boivin:client:(2) 0.000000] test.c:99: [test/INFO] Programming the repetitive action with a frequency of 0.5 sec
+[Boivin:client:(2) 0.000000] test.c:102: [test/INFO] Programming the delayed action in 5 secs
+[Boivin:client:(2) 0.500537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 0.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 1.000537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 1.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 1.500537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 1.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 2.000537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 2.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 2.500537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 2.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 3.000537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 3.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 3.500537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 3.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 4.000537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 4.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 4.500537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 4.500537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 5.000537] test.c:66: [test/INFO] Hello sent to server
+[Jacquelin:server:(1) 5.000537] test.c:26: [test/INFO] Cool, we received the message from Boivin:1024.
+[Boivin:client:(2) 5.001074] test.c:73: [test/INFO] Kill sent to server
+[Boivin:client:(2) 5.001074] test.c:78: [test/INFO] Break the client's while loop
+[Boivin:client:(2) 5.001074] gras/gras.c:79: [gras/INFO] Exiting GRAS
+[Jacquelin:server:(1) 5.001074] test.c:15: [test/CRITICAL] Argh, killed by Boivin:1024! Bye folks...
+[Jacquelin:server:(1) 5.001074] gras/gras.c:79: [gras/INFO] Exiting GRAS
+[5.001074] msg/global.c:475: [msg_kernel/INFO] Congratulations ! Simulation terminated : all processes are over
+$
index ca8f5e7..1331e0d 100644 (file)
@@ -2,7 +2,7 @@
 export LD_LIBRARY_PATH=$(GRAS_ROOT)/lib
 
 all: 1-bones.output 2-simple.output 3-args.output 4-callback.output \
-     5-globals.output 6-logs.output
+     5-globals.output 6-logs.output 7-timers.output
 
 veryclean: clean
        rm *.output*
@@ -167,3 +167,28 @@ clean::
        if [ -e 6-logs.mk ] ; then make -f 6-logs.mk clean; fi
        rm -f _6-logs_client.c _6-logs_server.c _6-logs_simulator.c 6-logs.trace 6-logs.mk
 
+
+# Lesson 7: timers
+########################################
+
+7-timers.output: 7-timers_client 7-timers_server 7-timers_simulator
+       echo '$$ ./test_server 12345 & ./test_client 127.0.0.1 12345'  > $@ 
+       ./7-timers_server 12345                             2>&1 |sed s/7-timers/test/  >> $@ 2>&1&
+       ./7-timers_client 127.0.0.1 12345                   2>&1 |sed s/7-timers/test/  >> $@ 2>&1
+       sleep 1
+       echo '$$'                                                     >> $@
+       echo '$$ ./test_simulator platform.xml test.xml'              >> $@
+       ./7-timers_simulator gtut-platform.xml 3-args.xml   2>&1 |sed s/7-timers/test/  >> $@ 2>&1
+       echo '$$'                                                     >> $@ 
+       killall 7-timers_server 7-timers_client 2>/dev/null || true
+
+7-timers_client 7-timers_server 7-timers_simulator: _7-timers_client.c _7-timers_server.c _7-timers_simulator.c
+       make -f 7-timers.mk
+
+_7-timers_client.c _7-timers_server.c _7-timers_simulator.c: 7-timers.c 3-args.xml
+       ../../tools/gras/gras_stub_generator 7-timers 3-args.xml >/dev/null
+
+clean::
+       if [ -e 7-timers.mk ] ; then make -f 7-timers.mk clean; fi
+       rm -f _7-timers_client.c _7-timers_server.c _7-timers_simulator.c 7-timers.trace 7-timers.mk
+
index 6ffeaba..cf49a72 100644 (file)
@@ -22,6 +22,8 @@ This section constitutes a tutorial to the GRAS programming environment.
    - \ref GRAS_tut_tour_callbacks
    - \ref GRAS_tut_tour_globals
    - \ref GRAS_tut_tour_logs
+   - \ref GRAS_tut_tour_timers
+   - \ref GRAS_tut_tour_exceptions
 
     \htmlonly <!-- 
       DOXYGEN_NAVBAR_LABEL="Tutorial"
index af6b40d..41fb1ab 100644 (file)
@@ -79,6 +79,9 @@ the others are not documented for sake of clarity in the relevant document).
 Ie, VERB10 does not exist, but VERB0 does exist. I may add more if someone
 wants more, but that should be enough for most purposes.
 
+Note also that there is no need to add a '\n' at the end of your format
+line, it gets automatically added.
+
 \section GRAS_tut_tour_logs_recap Recapping everything together
 
 Once we changed any fprintf of our code to some of these macros, the program
@@ -103,5 +106,5 @@ Again, you should refer to the \ref XBT_log section for more information on
 how to configure the logs. Or you can proceed with the next lesson, of
 course.
 
-\ref GRAS_tut_tour_timer
+\ref GRAS_tut_tour_timers
 */
diff --git a/doc/gtut-tour-7-timers.doc b/doc/gtut-tour-7-timers.doc
new file mode 100644 (file)
index 0000000..0d568be
--- /dev/null
@@ -0,0 +1,92 @@
+/**
+@page GRAS_tut_tour_timers Lesson 7: Using internal timers
+
+\section GRAS_tut_tour_timers_intro Introduction
+
+The messaging primitives we saw until now allow the processes to react to
+external events. This is good, but sometimes, you want the same action to be
+done periodically. Think of a system based on a group of processes. If you
+want to give some adaptability to this system, you shouldn't hardcode the
+memberships but have the members send a message to a coordinator to register
+to the system.
+
+This add some dynamism to your system since new members can join at any
+time. To have a process leaving the system, you can imagine an "unregister"
+message symetric to the "register" one. But how will you deal with failures?
+What if a process leaves without being given the ability to inform the
+coordinator?
+
+One solution is to have the members re-register periodically, so that the
+coordinator can detect the processes which didn't do so since a while, and
+dismiss them. 
+
+To implement this in GRAS, we need some more functions: gras_timer_repeat()
+allows to specify a periodic action and gras_timer_delay() allows to get an
+action done once a given delay expires. gras_timer_cancel_delay() and
+gras_timer_cancel_repeat() allow to remove already declared timers. Actions
+must be function without argument nor result (<tt>void my_action(void){
+... }</tt>).
+
+It is important to note that timers are not prehemptive. They will not start
+as soon as they are ready. Instead, they get served when you go into
+gras_msg_handle() (and they are served before incomming messages). This is
+because allowing timers to run in parallel to the callbacks would add
+parallelism to the user code, which would have to protect data with mutexes.
+This is a level of complexity I really don't want for user code. If you
+really need several running entities, simply run several processes (see \ref
+GRAS_tut_intro_model for more details).
+
+\section GRAS_tut_tour_timers_use Putting timers into action
+
+We will change the client of our example so that it send an hello message
+every half second to the server. Then we will add a delayed action scheduled
+5 seconds later in charge of stopping every processes. For this to work, we
+first need to add a global to the server too, containing the socket binded
+onto the server (to send messages) and a boolean indicating whether we are
+done or not, just like we did on the server side in \ref
+GRAS_tut_tour_globals. Here is the resulting global structure:
+\dontinclude 7-timers.c
+\skip client_data
+\until client_data_t
+
+Then, we define the repetitive action in charge of sending messages to the
+server:
+
+\skip client_do_hello
+\until end_of_client_do_hello
+
+This timer is installed the following way. You simply tell the action to
+schedule and its periodicity.
+\skip gras_timer_repeat
+\until gras_timer_repeat
+
+Desinstalling this is not harder. You tell the action to unschedule, and the
+periodicity at which it was desinstalled (so that the same action can be
+scheduled at different intervals, and each of them be desinstallable
+separately).
+\dontinclude 7-timers.c
+\skip gras_timer_cancel_repeat
+\until gras_timer_cancel_repeat
+
+Then comes the delayed action in charge of stopping everything, which should
+be self-explanatory at this point. It could be cancelled before its
+expiration using gras_timer_cancel_delay(), which accepts exactly the same
+kind of arguments than gras_timer_cancel_repeat().
+\dontinclude 7-timers.c
+\skip client_do_stop
+\until end_of_client_do_stop
+
+Finally, we should change the client main function to adapt to these
+modifications, as you can see in the recapping below.
+
+\section GRAS_tut_tour_timers_recap Recapping everything together
+
+The program now reads:
+\include 7-timers.c
+
+Which produces the expected output:
+\include 7-timers.output
+
+\ref GRAS_tut_tour_exceptions
+
+*/
index 0f27376..e8a159a 100644 (file)
@@ -12,8 +12,9 @@ all features available in GRAS.
       DOXYGEN_NAVBAR_CHILD "2: Simple messaging"=GRAS_tut_tour_simpleexchange.html
       DOXYGEN_NAVBAR_CHILD "3: Process args"=GRAS_tut_tour_args.html
       DOXYGEN_NAVBAR_CHILD "4: Callbacks"=GRAS_tut_tour_callbacks.html
-      DOXYGEN_NAVBAR_CHILD "5: Callbacks"=GRAS_tut_tour_globals.html
+      DOXYGEN_NAVBAR_CHILD "5: Globals"=GRAS_tut_tour_globals.html
       DOXYGEN_NAVBAR_CHILD "6: Logs"=GRAS_tut_tour_logs.html
+      DOXYGEN_NAVBAR_CHILD "7: Timers"=GRAS_tut_tour_timers.html
     --> \endhtmlonly
 
  - \ref GRAS_tut_tour_install
@@ -23,6 +24,7 @@ all features available in GRAS.
  - \ref GRAS_tut_tour_callbacks
  - \ref GRAS_tut_tour_globals
  - \ref GRAS_tut_tour_logs
+ - \ref GRAS_tut_tour_timers
  
 <hr>
 
@@ -32,9 +34,8 @@ all features available in GRAS.
 Unfortunately, the tour is not terminated yet, and here are some ideas of
 missing missi^W lessons:
 
-- Lesson 5: Globals (for a kill message)
-- Lesson 6: Timers
-- Lesson 7: Using logs
+- Lesson 8: Timers
+- Lesson 7: Exceptions
 
 - Lesson 8: Exchanging simple data through ping-pong
 - Lesson 9: More complex data description (automatic parsing, manual description) and example