-fix
authorSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>
Sun, 25 Feb 2018 15:23:42 +0000 (16:23 +0100)
committerSchanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de>
Sun, 25 Feb 2018 15:23:42 +0000 (16:23 +0100)
16 files changed:
AUTHORS
doc/documentation/chapters/developer.texi
doc/documentation/chapters/installation.texi
doc/documentation/chapters/user.texi
doc/documentation/index.html
src/consensus/gnunet-service-consensus.c
src/datastore/plugin_datastore_sqlite.c
src/include/gnunet_scheduler_lib.h
src/multicast/gnunet-service-multicast.c
src/psyc/gnunet-service-psyc.c
src/rps/gnunet-service-rps.c
src/rps/rps-test_util.h
src/rps/test_rps.c
src/social/gnunet-service-social.c
src/util/mq.c
src/util/scheduler.c

diff --git a/AUTHORS b/AUTHORS
index 136848e3fde6d63ed1aee587c0240058885ecb94..98cce2507ef80a2673aca694e0e500829066dc11 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -59,19 +59,19 @@ Jake Dust <jakedust@gmail.com>
 James Blackwell <jblack@linuxguru.net>
 Jean-Luc Cooke <jlcooke@certainkey.com> [ SHA-512]
 Jussi Eloranta <eloranta@cc.jyu.fi>
-Jürgen Appel <jappel@linux01.gwdg.de>
+Jürgen Appel <jappel@linux01.gwdg.de>
 Kevin Vandersloot <kfv101@psu.edu> [original code of gnome-system-monitor]
 Krista Bennett Grothoff <krista@grothoff.org>
 Kyle McMartin <kyle@debian.org> [ SHA-512]
 Larry Waldo
-Ludovic Courtès <ludo@chbouib.org>
-Marko Räihä
+Ludovic Courtès <ludo@chbouib.org>
+Marko Räihä
 Michael John Wensley <michael@wensley.org.uk>
 Milan Bouchet-Valat <nalimilan@club.fr>
 Nathan Evans <evans@net.in.tum.de>
 ng0 <ng0@infotropique.org> [ Documentation export to Texinfo ]
 Paul Ruth <ruth@cs.purdue.edu>
-Philipp Tölke <toelke@in.tum.de>, <pt@philipptoelke.de>
+Philipp Tölke <toelke@in.tum.de>, <pt@philipptoelke.de>
 Renaldo Ferreira <rf@cs.purdue.edu>
 Risto Saarelma
 Roman Zippel
@@ -105,7 +105,7 @@ Kinyarwanda: Steven Michael Murphy <murf@e-tools.com>
 Vietnamese : Phan Vinh Thinh <teppi82@gmail.com> and Clytie Siddall <clytie@riverland.net.au>
 Swedish    : Daniel Nylander <po@danielnylander.se>
 Spanish    : Miguel Angel Arruga Vivas <miguel.13@telefonica.net>
-Turkish    : Nilgün Belma Bugüner <nilgun@buguner.name.tr>
+Turkish    : Nilgün Belma Bugüner <nilgun@buguner.name.tr>
 
 Logos:
 GNU in Net    : Christian Muellner <chris@flop.de>
index befc135b0b3b34311838932537ed6b1224c62823..41db89df8a61a2eaa2642d71df50c16b77a88804 100644 (file)
@@ -11,7 +11,7 @@ For developers, GNUnet is:
 @itemize @bullet
 @item developed by a community that believes in the GNU philosophy
 @item Free Software (Free as in Freedom), licensed under the
-GNU General Public License
+GNU General Public License@footnote{@uref{https://www.gnu.org/licenses/licenses.html#GPL, https://www.gnu.org/licenses/licenses.html#GPL}}
 @item A set of standards, including coding conventions and
 architectural rules
 @item A set of layered protocols, both specifying the communication
@@ -24,7 +24,7 @@ writing extensions
 In particular, the architecture specifies that a peer consists of many
 processes communicating via protocols. Processes can be written in almost
 any language.
-C and Java @footnote{As well as Guile} APIs exist for accessing existing
+@code{C}, @code{Java} and @code{Guile} APIs exist for accessing existing
 services and for writing extensions.
 It is possible to write extensions in other languages by
 implementing the necessary IPC protocols.
@@ -111,6 +111,9 @@ operations. If you want (or require) access, you should contact
 @uref{http://grothoff.org/christian/, Christian Grothoff},
 GNUnet's maintainer.
 
+@c FIXME: A good part of this belongs on the website or should be
+@c extended in subsections explaining usage of this. A simple list
+@c is just taking space people have to read.
 The public subsystems on the GNUnet server that help developers are:
 
 @itemize @bullet
@@ -119,20 +122,21 @@ The public subsystems on the GNUnet server that help developers are:
 distributed development.
 It is publicly accessible at @uref{https://gnunet.org/git/}.
 Only developers with write access can commit code, everyone else is
-encouraged to submit patches to the
-@uref{https://lists.gnu.org/mailman/listinfo/gnunet-developers, GNUnet-developers mailinglist}.
+encouraged to submit patches to the GNUnet-developers mailinglist:
+@uref{https://lists.gnu.org/mailman/listinfo/gnunet-developers, https://lists.gnu.org/mailman/listinfo/gnunet-developers}
 
 @item The bugtracking system (Mantis).
 We use it to track feature requests, open bug reports and their
 resolutions.
-It can be accessed at @uref{https://gnunet.org/bugs/}.
-Anyone can report bugs, but only developers can claim to have fixed them.
+It can be accessed at
+@uref{https://gnunet.org/bugs/, https://gnunet.org/bugs/}.
+Anyone can report bugs.
 
 @item Our site installation of the
 CI@footnote{Continuous Integration} system @code{Buildbot} is used
 to check GNUnet builds automatically on a range of platforms.
 The web interface of this CI is exposed at
-@uref{https://gnunet.org/buildbot/}.
+@uref{https://gnunet.org/buildbot/, https://gnunet.org/buildbot/}.
 Builds are triggered automatically 30 minutes after the last commit to
 our repository was made.
 
@@ -149,12 +153,13 @@ as possibly problematic. Nevertheless, developers are encouraged to at
 least be aware of all issues in their code that are listed.
 
 @item We use Gauger for automatic performance regression visualization.
+@c FIXME: LINK!
 Details on how to use Gauger are here.
 
 @item We use @uref{http://junit.org/, junit} to automatically test
 @command{gnunet-java}.
 Automatically generated, current reports on the test suite are here.
-@c FIXME: URL.
+@c FIXME: Likewise.
 
 @item We use Cobertura to generate test coverage reports for gnunet-java.
 Current reports on test coverage are here.
@@ -450,15 +455,20 @@ on a set of values via a distributed set union computation.
 @item @file{rest/}
 The rest API allows access to GNUnet services using RESTful interaction.
 The services provide plugins that can exposed by the rest server.
-@item @file{experimentation/}
-The experimentation daemon coordinates distributed
-experimentation to evaluate transport and ATS properties.
+@c FIXME: Where did this disappear to?
+@c @item @file{experimentation/}
+@c The experimentation daemon coordinates distributed
+@c experimentation to evaluate transport and ATS properties.
 @end table
 
 @c ***********************************************************************
 @node System Architecture
 @section System Architecture
 
+@c FIXME: For those irritated by the textflow, we are missing images here,
+@c in the short term we should add them back, in the long term this should
+@c work without images or have images with alt-text.
+
 GNUnet developers like LEGOs. The blocks are indestructible, can be
 stacked together to construct complex buildings and it is generally easy
 to swap one block for a different one that has the same shape. GNUnet's
@@ -805,8 +815,8 @@ Each variable type should be chosen with care.
 statements (free, close, etc.) can be acceptable.
 
 @item Conditions should be written with constants on the left (to avoid
-accidental assignment) and with the 'true' target being either the
-'error' case or the significantly simpler continuation. For example:
+accidental assignment) and with the @code{true} target being either the
+@code{error} case or the significantly simpler continuation. For example:
 
 @example
 if (0 != stat ("filename," &sbuf)) @{
@@ -829,8 +839,8 @@ if (stat ("filename," &sbuf) == 0) @{
 @end example
 
 @noindent
-If possible, the error clause should be terminated with a 'return' (or
-'goto' to some cleanup routine) and in this case, the 'else' clause
+If possible, the error clause should be terminated with a @code{return} (or
+@code{goto} to some cleanup routine) and in this case, the @code{else} clause
 should be omitted:
 
 @example
@@ -1896,16 +1906,25 @@ subsystem.
 @node CORE must be started
 @subsubsection CORE must be started
 
-A simple issue is #3993: Your configuration MUST somehow ensure that for
-each peer the CORE service is started when the peer is setup, otherwise
-TESTBED may fail to connect peers when the topology is initialized, as
-TESTBED will start some CORE services but not necessarily all (but it
-relies on all of them running). The easiest way is to set
-'FORCESTART = YES' in the '[core]' section of the configuration file.
+A uncomplicated issue is bug #3993@footnote{@uref{https://gnunet.org/bugs/view.php?id=3993, https://gnunet.org/bugs/view.php?id=3993}}:
+Your configuration MUST somehow ensure that for each peer the
+@code{CORE} service is started when the peer is setup, otherwise
+@code{TESTBED} may fail to connect peers when the topology is initialized,
+as @code{TESTBED} will start some @code{CORE} services but not
+necessarily all (but it relies on all of them running). The easiest way
+is to set
+
+@example
+[core]
+FORCESTART = YES
+@end example
+
+@noindent
+in the configuration file.
 Alternatively, having any service that directly or indirectly depends on
-CORE being started with FORCESTART will also do. This issue largely arises
-if users try to over-optimize by not starting any services with
-FORCESTART.
+@code{CORE} being started with @code{FORCESTART} will also do.
+This issue largely arises if users try to over-optimize by not
+starting any services with @code{FORCESTART}.
 
 @c ***********************************************************************
 @node ATS must want the connections
@@ -2140,7 +2159,7 @@ any attempts to make the same call later will be allowed or disallowed
 right away. Because of that runtime log level evaluation should not
 significantly affect the process performance.
 Log definition parsing is only done once, at the first call to
-GNUNET_log_setup () made by the process (which is usually done soon after
+@code{GNUNET_log_setup ()} made by the process (which is usually done soon after
 it starts).
 
 At the moment of writing there is no way to specify logging definitions
@@ -2304,18 +2323,21 @@ topology\n")); #endif unblacklisted_connections = create_small_world_ring
 Pretty hard to follow, huh?
 
 From now on, it is not necessary to include the #if / #endif statements to
-achieve the same behavior. The GNUNET_log and GNUNET_log_from macros take
+achieve the same behavior. The @code{GNUNET_log} and @code{GNUNET_log_from}
+macros take
 care of it for you, depending on the configure option:
 
 @itemize @bullet
 @item If @code{--enable-logging} is set to @code{no}, the binary will
 contain no log messages at all.
 @item If @code{--enable-logging} is set to @code{yes}, the binary will
-contain no DEBUG messages, and therefore running with -L DEBUG will have
+contain no DEBUG messages, and therefore running with @command{-L DEBUG}
+will have
 no effect. Other messages (ERROR, WARNING, INFO, etc) will be included.
 @item If @code{--enable-logging} is set to @code{verbose}, or
 @code{veryverbose} the binary will contain DEBUG messages (still, it will
-be neccessary to run with -L DEBUG or set the DEBUG config option to show
+be neccessary to run with @command{-L DEBUG} or set the DEBUG config option
+to show
 them).
 @end itemize
 
index 45aeba9b09bb8519024cdd102f4a2f3f34b49ac9..be2da87021b3fb9d3f58c103cb279a4e9fc9624d 100644 (file)
@@ -6,8 +6,8 @@ setup (configure, start) GNUnet @value{VERSION}. After following these
 instructions you should be able to install and then start user-interfaces
 to interact with the network.
 
-Note: This manual is far from complete, and we welcome informed
-contributions, be it in the form of new chapters or insightful comments.
+Note: This manual is far from complete, and we welcome contributions, be
+it in the form of new chapters or insightful comments.
 
 @menu
 * Dependencies::
@@ -3088,8 +3088,9 @@ ProxyPassReverse http://gnunet.foo.org:1080/
 @subsubsection Reverse Proxy - Configure your Apache2 HTTPS webserver
 
 We assume that you already have an HTTPS server running, if not please
-check how to configure a HTTPS host. An easy to use example is the
-@file{apache2/sites-available/default-ssl} example configuration file.
+check how to configure a HTTPS host. An uncomplicated to use example
+is the example configuration file for Apache2/HTTPD provided in
+@file{apache2/sites-available/default-ssl}.
 
 In the respective HTTPS @code{server config},@code{virtual host} or
 @code{directory} section add the following lines:
@@ -3106,14 +3107,13 @@ ProxyPassReverse https://gnunet.foo.org:4433/
 
 @noindent
 More information about the apache mod_proxy configuration can be found
-here: @uref{http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass}
-.
+in the Apache documentation@footnote{@uref{http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass, http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass}}
 
 @node Reverse Proxy - Configure your nginx HTTPS webserver
 @subsubsection Reverse Proxy - Configure your nginx HTTPS webserver
 
 Since nginx does not support chunked encoding, you first of all have to
-install @code{chunkin}: @uref{http://wiki.nginx.org/HttpChunkinModule}.
+install the @code{chunkin} module@footnote{@uref{http://wiki.nginx.org/HttpChunkinModule, http://wiki.nginx.org/HttpChunkinModule}}
 
 To enable chunkin add:
 
@@ -3132,8 +3132,7 @@ the site-specific configuration file.
 In the @code{server} section add:
 
 @example
-location /bar/
-@{
+location /bar/ @{
 proxy_pass http://gnunet.foo.org:1080/;
 proxy_buffering off;
 proxy_connect_timeout 5; # more than http_server
index 1a30a7336dfb22ccc1bb0446a131aaa74625245d..998ba37eb488f7d0a40de6d651d971b2f83d1649 100644 (file)
@@ -6,7 +6,7 @@ This tutorial is supposed to give a first introduction for end-users
 trying to do something "real" with GNUnet. Installation and
 configuration are specifically outside of the scope of this tutorial.
 Instead, we start by briefly checking that the installation works, and
-then dive into simple, concrete practical things that can be done
+then dive into uncomplicated, concrete practical things that can be done
 with the network.
 
 This chapter of the GNUnet Reference Documentation documents
@@ -430,8 +430,8 @@ You can now go back to the shell running @code{gnunet-bcd} and press
 @c %**end of header
 
 Next, you should try resolving your own GNS records.
-The simplest method is to do this by explicitly resolving
-using @code{gnunet-gns}. In the shell, type:
+The method we found to be the most uncomplicated is to do this
+by explicitly resolving using @code{gnunet-gns}. In the shell, type:
 
 @example
 $ gnunet-gns -u test.gnu # what follows is the reply
@@ -597,12 +597,12 @@ Also, the calculation is deliberately expensive, to deter people from
 doing this just for fun (as the actual revocation operation is expensive
 for the network, not for the peer performing the revocation).
 
-To avoid TL;DR ones from accidentally revocating their zones, I am not
-giving away the command, but its simple: the actual revocation is
-performed by using the @command{-p} option
-of @command{gnunet-revocation}.
-
 
+@c FIXME: The Manual should give away the command using an example that is
+@c very likely to never exist.
+To avoid TL;DR ones from accidentally revocating their zones, we are not
+giving away the command, but it is uncomplicated: the actual revocation is
+performed by using the @command{-p} option of @command{gnunet-revocation}.
 
 @node What's Next?
 @subsection What's Next?
@@ -1495,17 +1495,19 @@ $ gnunet-identity -C "new_zone"
 
 @noindent
 Now you can add (or edit, or remove) records in your GNS zone using the
-gnunet-setup GUI or using the gnunet-namestore command-line tool.
+@command{gnunet-setup} GUI or using the @command{gnunet-namestore}
+command-line tool.
 In either case, your records will be stored in an SQL database under
-control of the gnunet-service-namestore. Note that if multiple users
-use one peer, the namestore database will include the combined records
-of all users. However, users will not be able to see each other's records
+control of the @command{gnunet-service-namestore}.
+Note that if multiple users use one peer, the namestore database will
+include the combined records of all users.
+However, users will not be able to see each other's records
 if they are marked as private.
 
-To provide a simple example for editing your own zone, suppose you
-have your own web server with IP 1.2.3.4. Then you can put an
-A record (A records in DNS are for IPv4 IP addresses) into your
-local zone using the command:
+To provide a short example for editing your own zone, suppose you
+have your own web server with the IP @code{1.2.3.4}. Then you can put an
+@code{A} record (@code{A} records in DNS are for IPv4 IP addresses)
+into your local zone using the command:
 
 @example
 $ gnunet-namestore -z master-zone -a -n www -t A -V 1.2.3.4 -e never
index 660544ced85be6047a1aa47ea4e8874f9e5f6c9a..1bd6da033f4c35724dfd364cadf823e735509897 100644 (file)
@@ -1,37 +1,58 @@
-<title>GNUnet - GNUnet Manuals and Handbooks</title>
-<h2>GNUnet - GNUnet Manuals and Handbooks</h2>
-
-<blockquote><address>
-GNUnet e.V.<br/>
-Fakultät für Informatik -- I8<br/>
-Technische Universität München<br/>
-Boltzmannstraße 3<br/>
-85748 Garching<br/>
-GERMANY<br/>
-</address></blockquote>
-
-<p>The following handbooks and manuals are available:</p>
-
-<ul>
-<li><a href="gnunet/index.html">GNUnet Reference Manual</li>
-<li><a href="gnunet-c-tutorial/index.html">GNUnet C Tutorial</li>
-</ul>
-
-<div id="footer">
-<div class="unprintable">
-
-<p>Please send general FSF &amp; GNU inquiries to
-<a href="mailto:gnu@gnu.org">&lt;gnu@gnu.org&gt;</a>.
-There are also <a href="/contact/">other ways to contact</a>
-the FSF.  Broken links and other corrections or suggestions can be sent
-to <a href="mailto:gnunet-developers@gnu.org">&lt;gnunet-developers@gnu.org&gt;</a>.</p>
-</div>
-
-<p>Copyright &copy; 2001 - 2017 GNUnet e.V.</p>
-
-<p>This page is licensed under a FIXME License.</p>
-
-</div>
-</div>
-</body>
+<html>
+  <head>
+    <title>GNUnet - GNUnet Manuals and Handbooks</title>
+    <meta charset="utf-8">
+    <meta name="keywords" content="gnunet,GNUnet,Manual,Manuals,preview,developer-preview,inofficial,GNU">
+    <meta name="description" content="The GNUnet Manuals">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+  </head>
+
+  <body>
+    <h2>GNUnet - GNUnet Manuals and Handbooks</h2>
+
+    <blockquote><address>
+        GNUnet e.V.<br/>
+        Fakultät für Informatik -- I8<br/>
+        Technische Universität München<br/>
+        Boltzmannstraße 3<br/>
+        85748 Garching<br/>
+        GERMANY<br/>
+    </address></blockquote>
+
+    <p>The following handbooks and manuals are available:</p>
+
+    <ul>
+      <li><a href="gnunet/index.html">GNUnet Reference Manual</li>
+      <li><a href="gnunet-c-tutorial/index.html">GNUnet C Tutorial</li>
+    </ul>
+
+    <div id="footer">
+      <div class="unprintable">
+
+        <p>Please send general FSF &amp; GNU inquiries to
+          <a href="mailto:gnu@gnu.org">&lt;gnu@gnu.org&gt;</a>.
+          There are also <a href="/contact/">other ways to contact</a>
+          the FSF.  Broken links and other corrections or suggestions can be sent
+          to <a href="mailto:gnunet-developers@gnu.org">&lt;gnunet-developers@gnu.org&gt;</a>.</p>
+      </div>
+
+      <p>Copyright &copy; 2001 - 2018 GNUnet e.V.</p>
+
+      <p>
+        <a rel="license" href="http://creativecommons.org/licenses/by-nd/4.0/">
+          <img alt="Creative Commons License"
+               style="border-width:0"
+               src="https://i.creativecommons.org/l/by-nd/4.0/88x31.png" />
+        </a>
+        <br />
+        This page is licensed under a
+        <a rel="license"
+           href="http://creativecommons.org/licenses/by-nd/4.0/">
+          Creative Commons Attribution-NoDerivatives 4.0 International License
+        </a>. Individual Manuals are licensed under the licenses mentioned within
+        the books (GNU Free Documentation License, GNU General Public License).
+      </p>
+    </div>
+
+  </body>
 </html>
index 84b1cbe553dcd22ce348d74b8098a6b97ad82144..90a3a36f197b616f9fbbeba02e7abb900868e709 100644 (file)
@@ -21,7 +21,7 @@
 /**
  * @file consensus/gnunet-service-consensus.c
  * @brief multi-peer set reconciliation
- * @author Florian Dold
+ * @author Florian Dold <flo@dold.me>
  */
 
 #include "platform.h"
index d51fd3e01f34792bbacc5561ea7a8ad53826b424..4980f8109b3fcdc7cbf7bb6b71c6f645725b430e 100644 (file)
@@ -908,6 +908,19 @@ sqlite_plugin_get_key (void *cls,
     GNUNET_SQ_query_param_end
   };
 
+  /* SQLite doesn't like it when you try to bind a parameter greater than the
+   * last numbered parameter, but unused parameters in the middle are OK.
+   */
+  if (! use_type)
+  {
+    params[3] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
+    if (! use_key)
+    {
+      params[2] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
+      if (! use_rvalue)
+        params[1] = (struct GNUNET_SQ_QueryParam) GNUNET_SQ_query_param_end;
+    }
+  }
   if (random)
   {
     rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
index d2805a68503caa2751753172499158de9eef1cdd..f9b2736e426fdc57196a122b22386281935ab90e 100644 (file)
@@ -237,29 +237,32 @@ struct GNUNET_SCHEDULER_Handle;
 
 
 /**
- * Function called by the driver to tell the scheduler to run some of
- * the tasks that are ready.  This function may return even though
- * there are tasks left to run just to give other tasks a chance as
- * well.  If we return #GNUNET_YES, the driver should call this
- * function again as soon as possible, while if we return #GNUNET_NO
- * it must block until either the operating system has more work (the
- * scheduler has no more work to do right now) or the timeout set by
- * the scheduler (using the set_wakeup callback) is reached.
- *
- * @param sh scheduler handle that was given to the `loop`
- * @return #GNUNET_OK if there are more tasks that are ready,
- *          and thus we would like to run more (yield to avoid
- *          blocking other activities for too long)
- *         #GNUNET_NO if we are done running tasks (yield to block)
- *         #GNUNET_SYSERR on error, e.g. no tasks were ready
+ * Function called by external event loop implementations to tell the
+ * scheduler to run some of the tasks that are ready. Must be called
+ * only after #GNUNET_SCHEDULER_driver_init has been called and before 
+ * #GNUNET_SCHEDULER_driver_done is called.
+ * This function may return even though there are tasks left to run
+ * just to give other tasks a chance as well.  If we return #GNUNET_YES,
+ * the event loop implementation should call this function again as
+ * soon as possible, while if we return #GNUNET_NO it must block until
+ * either the operating system has more work (the scheduler has no more
+ * work to do right now) or the timeout set by the scheduler (using the
+ * set_wakeup callback) is reached.
+ *
+ * @param sh scheduler handle that was returned by
+ *        #GNUNET_SCHEDULER_driver_init
+ * @return #GNUNET_YES if there are more tasks that are ready,
+ *         and thus we would like to run more (yield to avoid
+ *         blocking other activities for too long) #GNUNET_NO
+ *         if we are done running tasks (yield to block)
  */
 int
-GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh);
+GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh);
 
 
 /**
- * API a driver has to implement for
- * #GNUNET_SCHEDULER_run_with_driver().
+ * API an external event loop has to implement for
+ * #GNUNET_SCHEDULER_driver_init.
  */
 struct GNUNET_SCHEDULER_Driver
 {
@@ -311,23 +314,6 @@ struct GNUNET_SCHEDULER_Driver
   (*set_wakeup)(void *cls,
                struct GNUNET_TIME_Absolute dt);
 
-  /**
-   * Event loop's "main" function, to be called from
-   * #GNUNET_SCHEDULER_run_with_driver() to actually
-   * launch the loop. The loop should run as long as
-   * tasks (added by the add callback) are available 
-   * OR the wakeup time (added by the set_wakeup
-   * callback) is not FOREVER.
-   *
-   * @param cls closure
-   * @param sh scheduler handle to pass to
-   *     #GNUNET_SCHEDULER_run_from_driver()
-   * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
-   */
-  int
-  (*loop)(void *cls,
-         struct GNUNET_SCHEDULER_Handle *sh);
-
 };
 
 
@@ -341,25 +327,56 @@ typedef void
 
 
 /**
- * Initialize and run scheduler.  This function will return when all
- * tasks have completed.  On systems with signals, receiving a SIGTERM
- * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown
- * to be run after the active task is complete.  As a result, SIGTERM
- * causes all shutdown tasks to be scheduled with reason
- * #GNUNET_SCHEDULER_REASON_SHUTDOWN.  (However, tasks added
- * afterwards will execute normally!).  Note that any particular
- * signal will only shut down one scheduler; applications should
- * always only create a single scheduler.
+ * Function called by external event loop implementations to initialize
+ * the scheduler. An external implementation has to provide @a driver
+ * which contains callbacks for the scheduler (see definition of struct
+ * #GNUNET_SCHEDULER_Driver). The callbacks are used to instruct the 
+ * external implementation to watch for events. If it detects any of
+ * those events it is expected to call #GNUNET_SCHEDULER_do_work to let
+ * the scheduler handle it. If an event is related to a specific task
+ * (e.g. the scheduler gave instructions to watch a file descriptor),
+ * the external implementation is expected to mark that task ready
+ * before by calling #GNUNET_SCHEDULER_task_ready.
  *
- * @param driver drive to use for the event loop
- * @param task task to run first (and immediately)
- * @param task_cls closure of @a task
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+ * This function has to be called before any tasks are scheduled and
+ * before GNUNET_SCHEDULER_do_work is called for the first time. It 
+ * allocates resources that have to be freed again by calling
+ * #GNUNET_SCHEDULER_driver_done.
+ *
+ * This function installs the same signal handlers as 
+ * #GNUNET_SCHEDULER_run. This means SIGTERM (and other similar signals)
+ * will induce a call to #GNUNET_SCHEDULER_shutdown during the next
+ * call to #GNUNET_SCHEDULER_do_work. As a result, SIGTERM causes all
+ * active tasks to be scheduled with reason
+ * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added afterwards
+ * will execute normally!). Note that any particular signal will only
+ * shut down one scheduler; applications should always only create a
+ * single scheduler.
+ *
+ * @param driver to use for the event loop
+ * @return handle to be passed to #GNUNET_SCHEDULER_do_work and
+ *         #GNUNET_SCHEDULER_driver_done
  */
-int
-GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
-                                 GNUNET_SCHEDULER_TaskCallback task,
-                                 void *task_cls);
+struct GNUNET_SCHEDULER_Handle *
+GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver);
+
+
+/**
+ * Counter-part of #GNUNET_SCHEDULER_driver_init. Has to be called
+ * by external event loop implementations after the scheduler has
+ * shut down. This is the case if both of the following conditions
+ * are met:
+ * 
+ * - all tasks the scheduler has added through the driver's add
+ *   callback have been removed again through the driver's del
+ *   callback
+ * - the timeout the scheduler has set through the driver's
+ *   add_wakeup callback is FOREVER
+ *
+ * @param sh the handle returned by #GNUNET_SCHEDULER_driver_init
+ */
+void
+GNUNET_SCHEDULER_driver_done (struct GNUNET_SCHEDULER_Handle *sh);
 
 
 /**
@@ -462,10 +479,15 @@ GNUNET_SCHEDULER_get_task_context (void);
 
 /**
  * Cancel the task with the specified identifier.
- * The task must not yet have run.
+ * The task must not yet have run. Only allowed to be called as long as the
+ * scheduler is running, that is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param task id of the task to cancel
- * @return the closure of the callback of the cancelled task
+ * @return original closure of the task
  */
 void *
 GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task);
@@ -634,6 +656,12 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at,
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready.  It will be run with the DEFAULT priority.
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param rfd read file-descriptor
@@ -656,6 +684,12 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
  * socket being ready.  The task will be scheduled for execution once
  * either the delay has expired or the socket operation is ready.  It
  * will be run with the DEFAULT priority.
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param priority priority to use for the task
@@ -678,9 +712,16 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay,
  * specified file descriptor is ready for writing.  The delay can be
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
- * socket operation is ready.  It will be run with the DEFAULT priority.
+ * socket operation is ready.  It will be run with the priority of
+ * the calling task.
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
- * @param delay when should this operation time out?
+ * @param delay when should this operation time out?
  * @param wfd write file-descriptor
  * @param task main function of the task
  * @param task_cls closure of @a task
@@ -700,6 +741,12 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready.
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param priority priority of the task
@@ -707,7 +754,7 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
  * @param on_read whether to poll the file-descriptor for readability
  * @param on_write whether to poll the file-descriptor for writability
  * @param task main function of the task
- * @param task_cls closure of @a task
+ * @param task_cls closure of task
  * @return unique task identifier for the job
  *         only valid until "task" is started!
  */
@@ -720,19 +767,26 @@ GNUNET_SCHEDULER_add_net_with_priority  (struct GNUNET_TIME_Relative delay,
                                          GNUNET_SCHEDULER_TaskCallback task,
                                          void *task_cls);
 
+
 /**
  * Schedule a new task to be run with a specified delay or when the
  * specified file descriptor is ready for reading.  The delay can be
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready. It will be run with the DEFAULT priority.
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
- * @param delay when should this operation time out?
+ * @param delay when should this operation time out?
  * @param rfd read file-descriptor
  * @param task main function of the task
  * @param task_cls closure of @a task
  * @return unique task identifier for the job
- *         only valid until "task" is started!
+ *         only valid until @a task is started!
  */
 struct GNUNET_SCHEDULER_Task *
 GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
@@ -747,8 +801,14 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready. It will be run with the DEFAULT priority.
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
- * @param delay when should this operation time out?
+ * @param delay when should this operation time out?
  * @param wfd write file-descriptor
  * @param task main function of the task
  * @param task_cls closure of @a task
@@ -768,6 +828,12 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready.
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param priority priority of the task
@@ -801,8 +867,14 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
  * (prerequisite-run)
  * && (delay-ready
  *     || any-rs-ready
- *     || any-ws-ready)
+ *     || any-ws-ready) )
  * </code>
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param prio how important is this task?
  * @param delay how long should we wait?
@@ -811,7 +883,7 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay,
  * @param task main function of the task
  * @param task_cls closure of @a task
  * @return unique task identifier for the job
- *         only valid until "task" is started!
+ *         only valid until @a task is started!
  */
 struct GNUNET_SCHEDULER_Task *
 GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
index d01227e2c9675ea82f92a887916be56ddd77431f..81921238892162a906523b50ae03f0be053a58b6 100644 (file)
@@ -1450,7 +1450,12 @@ check_client_member_join (void *cls,
   uint16_t msg_size = ntohs (msg->header.size);
   struct GNUNET_PeerIdentity *relays = (struct GNUNET_PeerIdentity *) &msg[1];
   uint32_t relay_count = ntohl (msg->relay_count);
-  uint16_t relay_size = relay_count * sizeof (*relays);
+  if (UINT32_MAX / relay_count > sizeof (*relays)){
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "relay_size exceeds UINT32_MAX!");
+      return GNUNET_SYSERR;
+  }
+  uint32_t relay_size = relay_count * sizeof (*relays);
   struct GNUNET_MessageHeader *join_msg = NULL;
   uint16_t join_msg_size = 0;
   if (sizeof (*msg) + relay_size + sizeof (struct GNUNET_MessageHeader)
@@ -1459,11 +1464,19 @@ check_client_member_join (void *cls,
     join_msg = (struct GNUNET_MessageHeader *)
       (((char *) &msg[1]) + relay_size);
     join_msg_size = ntohs (join_msg->size);
+    if (UINT16_MAX - join_msg_size > sizeof (struct MulticastJoinRequestMessage)){
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "join_msg_size exceeds UINT16_MAX!");
+        return GNUNET_SYSERR;
+    } 
+  }
+  if (msg_size != (sizeof (*msg) + relay_size + join_msg_size)){
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "msg_size does not match real size of message!");
+      return GNUNET_SYSERR;
+  }else{
+      return GNUNET_OK;
   }
-  return
-    msg_size == (sizeof (*msg) + relay_size + join_msg_size)
-    ? GNUNET_OK
-    : GNUNET_SYSERR;
 }
 
 
@@ -1887,6 +1900,7 @@ handle_client_replay_request (void *cls,
     else
     {
       /* FIXME: not yet connected to origin */
+      
       GNUNET_assert (0);
       GNUNET_SERVICE_client_drop (client);
       return;
@@ -1975,7 +1989,7 @@ static int
 check_client_replay_response (void *cls,
                               const struct MulticastReplayResponseMessage *res)
 {
-  const struct GNUNET_MessageHeader *msg = &res->header;
+  const struct GNUNET_MessageHeader *msg;
   if (GNUNET_MULTICAST_REC_OK == res->error_code)
   {
     msg = GNUNET_MQ_extract_nested_mh (res);
index cf161435a626269ac4525bd852f0fc40956fb628..49779ef2c39242ef9c9936ed333de0e26b526f75 100644 (file)
@@ -2185,13 +2185,11 @@ master_transmit_message (struct Master *mst)
     return;
   if (NULL == mst->tmit_handle)
   {
-    mst->tmit_handle = (void *) &mst->tmit_handle;
-    struct GNUNET_MULTICAST_OriginTransmitHandle *
-      tmit_handle = GNUNET_MULTICAST_origin_to_all (mst->origin, tmit_msg->id,
-                                                    mst->max_group_generation,
-                                                    master_transmit_notify, mst);
-    if (NULL != mst->tmit_handle)
-      mst->tmit_handle = tmit_handle;
+    mst->tmit_handle = GNUNET_MULTICAST_origin_to_all (mst->origin,
+                                                       tmit_msg->id,
+                                                       mst->max_group_generation,
+                                                       &master_transmit_notify,
+                                                       mst);
   }
   else
   {
@@ -2210,12 +2208,10 @@ slave_transmit_message (struct Slave *slv)
     return;
   if (NULL == slv->tmit_handle)
   {
-    slv->tmit_handle = (void *) &slv->tmit_handle;
-    struct GNUNET_MULTICAST_MemberTransmitHandle *
-      tmit_handle = GNUNET_MULTICAST_member_to_origin (slv->member, slv->channel.tmit_head->id,
-                                                       slave_transmit_notify, slv);
-    if (NULL != slv->tmit_handle)
-      slv->tmit_handle = tmit_handle;
+    slv->tmit_handle = GNUNET_MULTICAST_member_to_origin (slv->member,
+                                                          slv->channel.tmit_head->id,
+                                                          &slave_transmit_notify,
+                                                          slv);
   }
   else
   {
index aeb0eabc2657fe7305815561e9bb9f52606bce3d..56c3c52b6f86ffab95b497d18c7b1127cf7c0de8 100644 (file)
@@ -3727,14 +3727,36 @@ do_round (void *cls)
   } else {
     LOG (GNUNET_ERROR_TYPE_DEBUG, "No update of the view.\n");
     GNUNET_STATISTICS_update(stats, "# rounds blocked", 1, GNUNET_NO);
-    if (CustomPeerMap_size (push_map) > alpha * View_size ())
+    if (CustomPeerMap_size (push_map) > alpha * View_size () &&
+        !(0 >= CustomPeerMap_size (pull_map)))
       GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes", 1, GNUNET_NO);
-    if (0 >= CustomPeerMap_size (push_map))
+    if (CustomPeerMap_size (push_map) > alpha * View_size () &&
+        (0 >= CustomPeerMap_size (pull_map)))
+      GNUNET_STATISTICS_update(stats, "# rounds blocked - too many pushes, no pull replies", 1, GNUNET_NO);
+    if (0 >= CustomPeerMap_size (push_map) &&
+        !(0 >= CustomPeerMap_size (pull_map)))
       GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes", 1, GNUNET_NO);
-    if (0 >= CustomPeerMap_size (pull_map))
+    if (0 >= CustomPeerMap_size (push_map) &&
+        (0 >= CustomPeerMap_size (pull_map)))
+      GNUNET_STATISTICS_update(stats, "# rounds blocked - no pushes, no pull replies", 1, GNUNET_NO);
+    if (0 >= CustomPeerMap_size (pull_map) &&
+        CustomPeerMap_size (push_map) > alpha * View_size () &&
+        0 >= CustomPeerMap_size (push_map))
       GNUNET_STATISTICS_update(stats, "# rounds blocked - no pull replies", 1, GNUNET_NO);
   }
   // TODO independent of that also get some peers from CADET_get_peers()?
+  GNUNET_STATISTICS_set (stats,
+      "# peers in push map at end of round",
+      CustomPeerMap_size (push_map),
+      GNUNET_NO);
+  GNUNET_STATISTICS_set (stats,
+      "# peers in pull map at end of round",
+      CustomPeerMap_size (pull_map),
+      GNUNET_NO);
+  GNUNET_STATISTICS_set (stats,
+      "# peers in view at end of round",
+      View_size (),
+      GNUNET_NO);
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Received %u pushes and %u pulls last round (alpha (%.2f) * view_size (%u) = %.2f)\n",
index 209152151c65bab4860f617ad038b5631d09c5f2..225db4b1da8b13a87691588b0e7b66f3251766b9 100644 (file)
@@ -53,7 +53,7 @@ create_file (const char *name);
     int size;\
     size = GNUNET_snprintf(tmp_buf,sizeof(tmp_buf),__VA_ARGS__);\
     if (0 > size)\
-      LOG (GNUNET_ERROR_TYPE_WARNING,\
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,\
            "Failed to create tmp_buf\n");\
     else\
       to_file_(file_name,tmp_buf);\
index c5a2c04582b4044fef9f2cdf62125d515222b4f3..4ef97ad925da7ebd1795ed5dd5a850787cbdeb70 100644 (file)
@@ -253,24 +253,31 @@ struct RPSPeer
    * Used to check whether we are able to shutdown.
    */
   uint32_t stat_collected_flags;
+
+  /**
+   * @brief File name of the file the stats are finally written to
+   */
+  char *file_name_stats;
 };
 
 enum STAT_TYPE
 {
-  STAT_TYPE_ROUNDS           =    0x1, /*   1 */
-  STAT_TYPE_BLOCKS           =    0x2, /*   2 */
-  STAT_TYPE_BLOCKS_MANY_PUSH =    0x4, /*   3 */
-  STAT_TYPE_BLOCKS_FEW_PUSH  =    0x8, /*   4 */
-  STAT_TYPE_BLOCKS_FEW_PULL  =   0x10, /*   5 */
-  STAT_TYPE_ISSUED_PUSH_SEND =   0x20, /*   6 */
-  STAT_TYPE_ISSUED_PULL_REQ  =   0x40, /*   7 */
-  STAT_TYPE_ISSUED_PULL_REP  =   0x80, /*   8 */
-  STAT_TYPE_SENT_PUSH_SEND   =  0x100, /*   9 */
-  STAT_TYPE_SENT_PULL_REQ    =  0x200, /*  10 */
-  STAT_TYPE_SENT_PULL_REP    =  0x400, /*  11 */
-  STAT_TYPE_RECV_PUSH_SEND   =  0x800, /*  12 */
-  STAT_TYPE_RECV_PULL_REQ    = 0x1000, /*  13 */
-  STAT_TYPE_RECV_PULL_REP    = 0x2000, /*  14 */
+  STAT_TYPE_ROUNDS                    =    0x1, /*   1 */
+  STAT_TYPE_BLOCKS                    =    0x2, /*   2 */
+  STAT_TYPE_BLOCKS_MANY_PUSH          =    0x4, /*   3 */
+  STAT_TYPE_BLOCKS_NO_PUSH            =    0x8, /*   4 */
+  STAT_TYPE_BLOCKS_NO_PULL            =   0x10, /*   5 */
+  STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL  =   0x20, /*   6 */
+  STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL    =   0x40, /*   7 */
+  STAT_TYPE_ISSUED_PUSH_SEND          =   0x80, /*   8 */
+  STAT_TYPE_ISSUED_PULL_REQ           =  0x100, /*   9 */
+  STAT_TYPE_ISSUED_PULL_REP           =  0x200, /*  10 */
+  STAT_TYPE_SENT_PUSH_SEND            =  0x400, /*  11 */
+  STAT_TYPE_SENT_PULL_REQ             =  0x800, /*  12 */
+  STAT_TYPE_SENT_PULL_REP             = 0x1000, /*  13 */
+  STAT_TYPE_RECV_PUSH_SEND            = 0x2000, /*  14 */
+  STAT_TYPE_RECV_PULL_REQ             = 0x4000, /*  15 */
+  STAT_TYPE_RECV_PULL_REP             = 0x8000, /*  16 */
   STAT_TYPE_MAX          = 0x80000000, /*  32 */
 };
 
@@ -1527,8 +1534,8 @@ manage_service_wrapper (unsigned int i, unsigned int j,
                                                     &churn_cb,
                                                     entry,
                                                     (PEER_GO_OFFLINE == delta) ? 0 : 1);
+    rps_peers[j].entry_op_manage = entry;
   }
-  rps_peers[j].entry_op_manage = entry;
 }
 
 
@@ -1737,6 +1744,50 @@ profiler_eval (void)
   return evaluate ();
 }
 
+/**
+ * @brief Try to ensure that `/tmp/rps` exists.
+ *
+ * @return #GNUNET_YES on success
+ *         #GNUNET_SYSERR on failure
+ */
+static int ensure_folder_exist (void)
+{
+  if (GNUNET_NO == GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO))
+  {
+    GNUNET_DISK_directory_create ("/tmp/rps");
+  }
+  if (GNUNET_YES != GNUNET_DISK_directory_test ("/tmp/rps/", GNUNET_NO))
+  {
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_YES;
+}
+
+static void
+store_stats_file_name (struct RPSPeer *rps_peer)
+{
+  unsigned int len_file_name;
+  unsigned int out_size;
+  char *file_name;
+
+  if (GNUNET_SYSERR == ensure_folder_exist()) return;
+  len_file_name = (14 + strlen (GNUNET_i2s_full (rps_peer->peer_id)) + 1) * sizeof (char);
+  file_name = GNUNET_malloc (len_file_name);
+  out_size = GNUNET_snprintf (file_name,
+                              len_file_name,
+                              "/tmp/rps/stat-%s",
+                              GNUNET_i2s_full (rps_peer->peer_id));
+  if (len_file_name < out_size ||
+      0 > out_size)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               "Failed to write string to buffer (size: %i, out_size: %i)\n",
+               len_file_name,
+               out_size);
+  }
+  rps_peer->file_name_stats = file_name;
+}
+
 /**
  * Continuation called by #GNUNET_STATISTICS_get() functions.
  *
@@ -1801,10 +1852,14 @@ char* stat_type_2_str (enum STAT_TYPE stat_type)
       return "# rounds blocked";
     case STAT_TYPE_BLOCKS_MANY_PUSH:
       return "# rounds blocked - too many pushes";
-    case STAT_TYPE_BLOCKS_FEW_PUSH:
+    case STAT_TYPE_BLOCKS_NO_PUSH:
       return "# rounds blocked - no pushes";
-    case STAT_TYPE_BLOCKS_FEW_PULL:
+    case STAT_TYPE_BLOCKS_NO_PULL:
       return "# rounds blocked - no pull replies";
+    case STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL:
+      return "# rounds blocked - too many pushes, no pull replies";
+    case STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL:
+      return "# rounds blocked - no pushes, no pull replies";
     case STAT_TYPE_ISSUED_PUSH_SEND:
       return "# push send issued";
     case STAT_TYPE_ISSUED_PULL_REQ:
@@ -1848,9 +1903,15 @@ stat_iterator (void *cls,
                int is_persistent)
 {
   const struct STATcls *stat_cls = (const struct STATcls *) cls;
+  const struct RPSPeer *rps_peer = (const struct RPSPeer *) stat_cls->rps_peer;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got stat value: %s - %" PRIu64 "\n",
-      stat_type_2_str (stat_cls->stat_type),
+      //stat_type_2_str (stat_cls->stat_type),
+      name,
       value);
+  to_file (rps_peer->file_name_stats,
+          "%s: %" PRIu64 "\n",
+          name,
+          value);
   return GNUNET_OK;
 }
 
@@ -1876,6 +1937,7 @@ void post_profiler (struct RPSPeer *rps_peer)
       stat_cls = GNUNET_malloc (sizeof (struct STATcls));
       stat_cls->rps_peer = rps_peer;
       stat_cls->stat_type = stat_type;
+      store_stats_file_name (rps_peer);
       GNUNET_STATISTICS_get (rps_peer->stats_h,
                              "rps",
                              stat_type_2_str (stat_type),
@@ -2141,8 +2203,10 @@ main (int argc, char *argv[])
     cur_test_run.stat_collect_flags = STAT_TYPE_ROUNDS |
                                       STAT_TYPE_BLOCKS |
                                       STAT_TYPE_BLOCKS_MANY_PUSH |
-                                      STAT_TYPE_BLOCKS_FEW_PUSH |
-                                      STAT_TYPE_BLOCKS_FEW_PULL |
+                                      STAT_TYPE_BLOCKS_NO_PUSH |
+                                      STAT_TYPE_BLOCKS_NO_PULL |
+                                      STAT_TYPE_BLOCKS_MANY_PUSH_NO_PULL |
+                                      STAT_TYPE_BLOCKS_NO_PUSH_NO_PULL |
                                       STAT_TYPE_ISSUED_PUSH_SEND |
                                       STAT_TYPE_ISSUED_PULL_REQ |
                                       STAT_TYPE_ISSUED_PULL_REP |
index 31e3a3dc227196a9888b96d94771d5c8c933aae1..bac08ae9da0ea27dea901f81401dc5e8f5031973 100644 (file)
@@ -1774,12 +1774,13 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
               plc_gst,
               gst);
 
-  new_guest = GNUNET_NO;
   if (NULL == gst)
   {
     gst = GNUNET_new (struct Guest);
     new_guest = GNUNET_YES;
   }
+  else new_guest = GNUNET_NO;
+
   if (NULL == gst->slave)
   {
     gst->origin = greq->origin;
@@ -1878,7 +1879,7 @@ guest_enter (const struct GuestEnterRequest *greq, struct Guest **ret_gst)
     ret = GNUNET_YES;
   }
 
-  // TODO: explain why free(gst) not necessary
+  // TODO: explain to automatic code scanners why free(gst) not necessary
   if (NULL != ret_gst)
     *ret_gst = gst;
   return ret;
@@ -3598,30 +3599,34 @@ identity_recv_ego (void *cls, struct GNUNET_IDENTITY_Ego *id_ego,
   GNUNET_CRYPTO_hash (&ego_pub_key, sizeof (ego_pub_key), &ego_pub_hash);
 
   struct Ego *ego = GNUNET_CONTAINER_multihashmap_get (egos, &ego_pub_hash);
+  if (NULL == ego && NULL == name)
+  {
+    // an ego that is none of our business has been deleted
+    return;
+  }
   if (NULL != ego)
   {
+    // one of our egos has been changed
     GNUNET_free (ego->name);
-    if (NULL == name) // deleted
+    if (NULL == name)
     {
+      // one of our egos has been deleted
       GNUNET_CONTAINER_multihashmap_remove (egos, &ego_pub_hash, ego);
       GNUNET_free (ego);
-      ego = NULL;
+      return;
     }
   }
   else
   {
     ego = GNUNET_malloc (sizeof (*ego));
   }
-  if (NULL != ego)
-  {
-    ego->key = *(GNUNET_IDENTITY_ego_get_private_key (id_ego));
-    size_t name_size = strlen (name) + 1;
-    ego->name = GNUNET_malloc (name_size);
-    GNUNET_memcpy (ego->name, name, name_size);
+  ego->key = *(GNUNET_IDENTITY_ego_get_private_key (id_ego));
+  size_t name_size = strlen (name) + 1;
+  ego->name = GNUNET_malloc (name_size);
+  GNUNET_memcpy (ego->name, name, name_size);
 
-    GNUNET_CONTAINER_multihashmap_put (egos, &ego_pub_hash, ego,
-                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
-  }
+  GNUNET_CONTAINER_multihashmap_put (egos, &ego_pub_hash, ego,
+                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
 
   // FIXME: notify clients about changed ego
 }
index 8d71359ac441f8a1de4020ab244b4f0024e44425..33bbaa6ad42531e5eea69cd4ca19f646ace774cf 100644 (file)
@@ -851,7 +851,7 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq)
                                 ev);
     GNUNET_assert (0 < mq->queue_length);
     mq->queue_length--;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "MQ destroy drops message of type %u\n",
                 ntohs (ev->mh->type));
     GNUNET_MQ_discard (ev);
@@ -861,7 +861,7 @@ GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq)
     /* we can only discard envelopes that
      * are not queued! */
     mq->current_envelope->parent_queue = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "MQ destroy drops current message of type %u\n",
                 ntohs (mq->current_envelope->mh->type));
     GNUNET_MQ_discard (mq->current_envelope);
index 6cf5e1168f7b3cb41e0e3f4d8aa74587e6cfd16d..51afc85e55b0970fcc427fe2c3bf4313edd67179 100644 (file)
@@ -25,6 +25,8 @@
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "disk.h"
+// DEBUG
+#include <inttypes.h>
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__)
 
@@ -71,7 +73,7 @@
 
 /**
  * Argument to be passed from the driver to
- * #GNUNET_SCHEDULER_run_from_driver().  Contains the
+ * #GNUNET_SCHEDULER_do_work().  Contains the
  * scheduler's internal state.
  */
 struct GNUNET_SCHEDULER_Handle
@@ -89,6 +91,40 @@ struct GNUNET_SCHEDULER_Handle
    * @deprecated
    */
   struct GNUNET_NETWORK_FDSet *ws;
+
+  /**
+   * context of the SIGINT handler
+   */
+  struct GNUNET_SIGNAL_Context *shc_int;
+
+  /**
+   * context of the SIGTERM handler
+   */
+  struct GNUNET_SIGNAL_Context *shc_term;
+
+#if (SIGTERM != GNUNET_TERM_SIG)
+  /**
+   * context of the TERM_SIG handler
+   */
+  struct GNUNET_SIGNAL_Context *shc_gterm;
+#endif
+
+#ifndef MINGW
+  /**
+   * context of the SIGQUIT handler
+   */
+  struct GNUNET_SIGNAL_Context *shc_quit;
+
+  /**
+   * context of the SIGHUP handler
+   */
+  struct GNUNET_SIGNAL_Context *shc_hup;
+
+  /**
+   * context of hte SIGPIPE handler
+   */
+  struct GNUNET_SIGNAL_Context *shc_pipe;
+#endif
 };
 
 
@@ -254,16 +290,16 @@ struct DriverContext
   struct Scheduled *scheduled_tail;
 
   /**
-   * the time until the select driver will wake up again (after
+   * the time when the select driver will wake up again (after
    * calling select)
    */
-  struct GNUNET_TIME_Relative timeout;
+  struct GNUNET_TIME_Absolute timeout;
 };
 
 
 /**
  * The driver used for the event loop. Will be handed over to
- * the scheduler in #GNUNET_SCHEDULER_run_from_driver(), peristed
+ * the scheduler in #GNUNET_SCHEDULER_do_work(), persisted
  * there in this variable for later use in functions like
  * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and
  * #GNUNET_SCHEDULER_cancel().
@@ -380,11 +416,6 @@ static struct GNUNET_SCHEDULER_TaskContext tc;
  */
 static void *scheduler_select_cls;
 
-/**
- * Scheduler handle used for the driver functions
- */
-static struct GNUNET_SCHEDULER_Handle sh;
-
 
 /**
  * Sets the select function to use in the scheduler (scheduler_select).
@@ -657,6 +688,10 @@ shutdown_if_no_lifeness ()
 }
 
 
+int
+select_loop (struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context);
+
+
 /**
  * Initialize and run scheduler.  This function will return when all
  * tasks have completed.  On systems with signals, receiving a SIGTERM
@@ -675,16 +710,21 @@ void
 GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task,
                       void *task_cls)
 {
+  struct GNUNET_SCHEDULER_Handle *sh;
   struct GNUNET_SCHEDULER_Driver *driver;
   struct DriverContext context = {.scheduled_head = NULL,
                                   .scheduled_tail = NULL,
-                                  .timeout = GNUNET_TIME_UNIT_FOREVER_REL};
+                                  .timeout = GNUNET_TIME_absolute_get ()};
 
   driver = GNUNET_SCHEDULER_driver_select ();
   driver->cls = &context;
-
-  GNUNET_SCHEDULER_run_with_driver (driver, task, task_cls);
-
+  sh = GNUNET_SCHEDULER_driver_init (driver);
+  GNUNET_SCHEDULER_add_with_reason_and_priority (task,
+                                                 task_cls,
+                                                 GNUNET_SCHEDULER_REASON_STARTUP,
+                                                 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
+  select_loop (sh, &context);
+  GNUNET_SCHEDULER_driver_done (sh);
   GNUNET_free (driver);
 }
 
@@ -898,8 +938,11 @@ shutdown_pipe_cb (void *cls)
 /**
  * Cancel the task with the specified identifier.
  * The task must not yet have run. Only allowed to be called as long as the
- * scheduler is running (#GNUNET_SCHEDULER_run or
- * #GNUNET_SCHEDULER_run_with_driver has been called and has not returned yet).
+ * scheduler is running, that is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param task id of the task to cancel
  * @return original closure of the task
@@ -1085,9 +1128,7 @@ GNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at,
       pos = pending_timeout_head;
     else
       pos = prev->next;
-    while ( (NULL != pos) &&
-            ( (pos->timeout.abs_value_us <= t->timeout.abs_value_us) ||
-              (0 != pos->reason) ) )
+    while ((NULL != pos) && (pos->timeout.abs_value_us <= t->timeout.abs_value_us))
     {
       prev = pos;
       pos = pos->next;
@@ -1401,9 +1442,12 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready.  It will be run with the DEFAULT priority.
- * Only allowed to be called as long as the scheduler is running
- * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
- * called and has not returned yet).
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param rfd read file-descriptor
@@ -1431,9 +1475,12 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay,
  * socket being ready.  The task will be scheduled for execution once
  * either the delay has expired or the socket operation is ready.  It
  * will be run with the DEFAULT priority.
- * Only allowed to be called as long as the scheduler is running
- * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
- * called and has not returned yet).
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param priority priority to use for the task
@@ -1465,9 +1512,12 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay,
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready.  It will be run with the priority of
  * the calling task.
- * Only allowed to be called as long as the scheduler is running
- * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
- * called and has not returned yet).
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param wfd write file-descriptor
@@ -1495,9 +1545,12 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay,
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready.
- * Only allowed to be called as long as the scheduler is running
- * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
- * called and has not returned yet).
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param priority priority of the task
@@ -1554,9 +1607,12 @@ GNUNET_SCHEDULER_add_net_with_priority  (struct GNUNET_TIME_Relative delay,
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready. It will be run with the DEFAULT priority.
- * Only allowed to be called as long as the scheduler is running
- * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
- * called and has not returned yet).
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param rfd read file-descriptor
@@ -1583,9 +1639,12 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay,
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready. It will be run with the DEFAULT priority.
- * Only allowed to be called as long as the scheduler is running
- * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
- * called and has not returned yet).
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param wfd write file-descriptor
@@ -1612,9 +1671,12 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay,
  * used as a timeout on the socket being ready.  The task will be
  * scheduled for execution once either the delay has expired or the
  * socket operation is ready.
- * Only allowed to be called as long as the scheduler is running
- * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
- * called and has not returned yet).
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param delay when should this operation time out?
  * @param priority priority of the task
@@ -1729,9 +1791,12 @@ extract_handles (const struct GNUNET_NETWORK_FDSet *fdset,
  *     || any-rs-ready
  *     || any-ws-ready) )
  * </code>
- * Only allowed to be called as long as the scheduler is running
- * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been
- * called and has not returned yet).
+ * Only allowed to be called as long as the scheduler is running, that
+ * is one of the following conditions is met:
+ *
+ * - #GNUNET_SCHEDULER_run has been called and has not returned yet
+ * - #GNUNET_SCHEDULER_driver_init has been run and
+ *   #GNUNET_SCHEDULER_driver_done has not been called yet
  *
  * @param prio how important is this task?
  * @param delay how long should we wait?
@@ -1886,24 +1951,27 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
 
 
 /**
- * Function called by the driver to tell the scheduler to run some of
- * the tasks that are ready.  This function may return even though
- * there are tasks left to run just to give other tasks a chance as
- * well.  If we return #GNUNET_YES, the driver should call this
- * function again as soon as possible, while if we return #GNUNET_NO
- * it must block until either the operating system has more work (the
- * scheduler has no more work to do right now) or the timeout set by
- * the scheduler (using the set_wakeup callback) is reached.
+ * Function called by external event loop implementations to tell the
+ * scheduler to run some of the tasks that are ready. Must be called
+ * only after #GNUNET_SCHEDULER_driver_init has been called and before 
+ * #GNUNET_SCHEDULER_driver_done is called.
+ * This function may return even though there are tasks left to run
+ * just to give other tasks a chance as well.  If we return #GNUNET_YES,
+ * the event loop implementation should call this function again as
+ * soon as possible, while if we return #GNUNET_NO it must block until
+ * either the operating system has more work (the scheduler has no more
+ * work to do right now) or the timeout set by the scheduler (using the
+ * set_wakeup callback) is reached.
  *
- * @param sh scheduler handle that was given to the `loop`
- * @return #GNUNET_OK if there are more tasks that are ready,
- *          and thus we would like to run more (yield to avoid
- *          blocking other activities for too long)
- *         #GNUNET_NO if we are done running tasks (yield to block)
- *         #GNUNET_SYSERR on error, e.g. no tasks were ready
+ * @param sh scheduler handle that was returned by
+ *        #GNUNET_SCHEDULER_driver_init
+ * @return #GNUNET_YES if there are more tasks that are ready,
+ *         and thus we would like to run more (yield to avoid
+ *         blocking other activities for too long) #GNUNET_NO
+ *         if we are done running tasks (yield to block)
  */
 int
-GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
+GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh)
 {
   enum GNUNET_SCHEDULER_Priority p;
   struct GNUNET_SCHEDULER_Task *pos;
@@ -1944,9 +2012,27 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
 
   if (0 == ready_count)
   {
-    LOG (GNUNET_ERROR_TYPE_ERROR,
-         "GNUNET_SCHEDULER_run_from_driver was called, but no tasks are ready!\n");
-    return GNUNET_SYSERR;
+    struct GNUNET_TIME_Absolute timeout = get_timeout ();
+
+    if (timeout.abs_value_us > now.abs_value_us)
+    {
+      /**
+       * The driver called this function before the current timeout was
+       * reached (and no FD tasks are ready). This can happen in the
+       * rare case when the system time is changed while the driver is
+       * waiting for the timeout, so we handle this gracefully. It might
+       * also be a programming error in the driver though.
+       */
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "GNUNET_SCHEDULER_do_work did not find any ready "
+                  "tasks and timeout has not been reached yet.");
+      return GNUNET_NO;
+    }
+    /**
+     * the current timeout was reached but no ready tasks were found,
+     * internal scheduler error!
+     */
+    GNUNET_assert (0);
   }
 
   /* find out which task priority level we are going to
@@ -2034,48 +2120,52 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
   }
   scheduler_driver->set_wakeup (scheduler_driver->cls,
                                 GNUNET_TIME_absolute_get ());
-  return GNUNET_OK;
+  return GNUNET_YES;
 }
 
 
 /**
- * Initialize and run scheduler.  This function will return when all
- * tasks have completed.  On systems with signals, receiving a SIGTERM
- * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown
- * to be run after the active task is complete.  As a result, SIGTERM
- * causes all shutdown tasks to be scheduled with reason
- * #GNUNET_SCHEDULER_REASON_SHUTDOWN.  (However, tasks added
- * afterwards will execute normally!).  Note that any particular
- * signal will only shut down one scheduler; applications should
- * always only create a single scheduler.
+ * Function called by external event loop implementations to initialize
+ * the scheduler. An external implementation has to provide @a driver
+ * which contains callbacks for the scheduler (see definition of struct
+ * #GNUNET_SCHEDULER_Driver). The callbacks are used to instruct the 
+ * external implementation to watch for events. If it detects any of
+ * those events it is expected to call #GNUNET_SCHEDULER_do_work to let
+ * the scheduler handle it. If an event is related to a specific task
+ * (e.g. the scheduler gave instructions to watch a file descriptor),
+ * the external implementation is expected to mark that task ready
+ * before by calling #GNUNET_SCHEDULER_task_ready.
+
+ * This function has to be called before any tasks are scheduled and
+ * before GNUNET_SCHEDULER_do_work is called for the first time. It 
+ * allocates resources that have to be freed again by calling
+ * #GNUNET_SCHEDULER_driver_done.
  *
- * @param driver drive to use for the event loop
- * @param task task to run first (and immediately)
- * @param task_cls closure of @a task
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+ * This function installs the same signal handlers as 
+ * #GNUNET_SCHEDULER_run. This means SIGTERM (and other similar signals)
+ * will induce a call to #GNUNET_SCHEDULER_shutdown during the next
+ * call to #GNUNET_SCHEDULER_do_work. As a result, SIGTERM causes all
+ * active tasks to be scheduled with reason
+ * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added afterwards
+ * will execute normally!). Note that any particular signal will only
+ * shut down one scheduler; applications should always only create a
+ * single scheduler.
+ *
+ * @param driver to use for the event loop
+ * @return handle to be passed to #GNUNET_SCHEDULER_do_work and
+ *         #GNUNET_SCHEDULER_driver_done
  */
-int
-GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
-                                  GNUNET_SCHEDULER_TaskCallback task,
-                                  void *task_cls)
+struct GNUNET_SCHEDULER_Handle *
+GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver)
 {
-  int ret;
-  struct GNUNET_SIGNAL_Context *shc_int;
-  struct GNUNET_SIGNAL_Context *shc_term;
-#if (SIGTERM != GNUNET_TERM_SIG)
-  struct GNUNET_SIGNAL_Context *shc_gterm;
-#endif
-#ifndef MINGW
-  struct GNUNET_SIGNAL_Context *shc_quit;
-  struct GNUNET_SIGNAL_Context *shc_hup;
-  struct GNUNET_SIGNAL_Context *shc_pipe;
-#endif
+  struct GNUNET_SCHEDULER_Handle *sh;
   struct GNUNET_SCHEDULER_Task tsk;
   const struct GNUNET_DISK_FileHandle *pr;
 
   /* general set-up */
   GNUNET_assert (NULL == active_task);
   GNUNET_assert (NULL == shutdown_pipe_handle);
+  sh = GNUNET_new (struct GNUNET_SCHEDULER_Handle);
   shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO,
                                            GNUNET_NO,
                                            GNUNET_NO,
@@ -2089,21 +2179,21 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
   /* install signal handlers */
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Registering signal handlers\n");
-  shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
-             &sighandler_shutdown);
-  shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
-              &sighandler_shutdown);
+  sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
+                                               &sighandler_shutdown);
+  sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
+                                                &sighandler_shutdown);
 #if (SIGTERM != GNUNET_TERM_SIG)
-  shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG,
-               &sighandler_shutdown);
+  sh->shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG,
+                                                 &sighandler_shutdown);
 #endif
 #ifndef MINGW
-  shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
-              &sighandler_pipe);
-  shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
-              &sighandler_shutdown);
-  shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
-             &sighandler_shutdown);
+  sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
+                                                &sighandler_pipe);
+  sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
+                                                &sighandler_shutdown);
+  sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
+                                               &sighandler_shutdown);
 #endif
 
   /* Setup initial tasks */
@@ -2122,19 +2212,33 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
                                     &shutdown_pipe_cb,
                                     NULL);
   current_lifeness = GNUNET_YES;
-  GNUNET_SCHEDULER_add_with_reason_and_priority (task,
-                                                 task_cls,
-                                                 GNUNET_SCHEDULER_REASON_STARTUP,
-                                                 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
   active_task = NULL;
   scheduler_driver->set_wakeup (scheduler_driver->cls,
                                 get_timeout ());
   /* begin main event loop */
-  sh.rs = GNUNET_NETWORK_fdset_create ();
-  sh.ws = GNUNET_NETWORK_fdset_create ();
-  GNUNET_NETWORK_fdset_handle_set (sh.rs, pr);
-  ret = driver->loop (driver->cls,
-                      &sh);
+  sh->rs = GNUNET_NETWORK_fdset_create ();
+  sh->ws = GNUNET_NETWORK_fdset_create ();
+  GNUNET_NETWORK_fdset_handle_set (sh->rs, pr);
+  return sh;
+}
+
+
+/**
+ * Counter-part of #GNUNET_SCHEDULER_driver_init. Has to be called
+ * by external event loop implementations after the scheduler has
+ * shut down. This is the case if both of the following conditions
+ * are met:
+ * 
+ * - all tasks the scheduler has added through the driver's add
+ *   callback have been removed again through the driver's del
+ *   callback
+ * - the timeout the scheduler has set through the driver's
+ *   add_wakeup callback is FOREVER
+ *
+ * @param sh the handle returned by #GNUNET_SCHEDULER_driver_init
+ */
+void GNUNET_SCHEDULER_driver_done (struct GNUNET_SCHEDULER_Handle *sh)
+{
   GNUNET_assert (NULL == pending_head);
   GNUNET_assert (NULL == pending_timeout_head);
   GNUNET_assert (NULL == shutdown_head);
@@ -2142,108 +2246,43 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
   {
     GNUNET_assert (NULL == ready_head[i]);
   }
-  GNUNET_NETWORK_fdset_destroy (sh.rs);
-  GNUNET_NETWORK_fdset_destroy (sh.ws);
+  GNUNET_NETWORK_fdset_destroy (sh->rs);
+  GNUNET_NETWORK_fdset_destroy (sh->ws);
 
   /* uninstall signal handlers */
-  GNUNET_SIGNAL_handler_uninstall (shc_int);
-  GNUNET_SIGNAL_handler_uninstall (shc_term);
+  GNUNET_SIGNAL_handler_uninstall (sh->shc_int);
+  GNUNET_SIGNAL_handler_uninstall (sh->shc_term);
 #if (SIGTERM != GNUNET_TERM_SIG)
-  GNUNET_SIGNAL_handler_uninstall (shc_gterm);
+  GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm);
 #endif
 #ifndef MINGW
-  GNUNET_SIGNAL_handler_uninstall (shc_pipe);
-  GNUNET_SIGNAL_handler_uninstall (shc_quit);
-  GNUNET_SIGNAL_handler_uninstall (shc_hup);
+  GNUNET_SIGNAL_handler_uninstall (sh->shc_pipe);
+  GNUNET_SIGNAL_handler_uninstall (sh->shc_quit);
+  GNUNET_SIGNAL_handler_uninstall (sh->shc_hup);
 #endif
   GNUNET_DISK_pipe_close (shutdown_pipe_handle);
   shutdown_pipe_handle = NULL;
   scheduler_driver = NULL;
-  return ret;
-}
-
-
-int
-select_add (void *cls,
-            struct GNUNET_SCHEDULER_Task *task,
-            struct GNUNET_SCHEDULER_FdInfo *fdi)
-{
-  struct DriverContext *context = cls;
-  GNUNET_assert (NULL != context);
-  GNUNET_assert (NULL != task);
-  GNUNET_assert (NULL != fdi);
-  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
-                 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
-
-  if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
-  {
-    /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
-    return GNUNET_SYSERR;
-  }
-
-  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
-  scheduled->task = task;
-  scheduled->fdi = fdi;
-  scheduled->et = fdi->et;
-
-  GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
-                               context->scheduled_tail,
-                               scheduled);
-  return GNUNET_OK;
+  GNUNET_free (sh);
 }
 
 
 int
-select_del (void *cls,
-            struct GNUNET_SCHEDULER_Task *task)
-{
-  struct DriverContext *context;
-  struct Scheduled *pos;
-  int ret;
-
-  GNUNET_assert (NULL != cls);
-
-  context = cls;
-  ret = GNUNET_SYSERR;
-  pos = context->scheduled_head;
-  while (NULL != pos)
-  {
-    struct Scheduled *next = pos->next;
-    if (pos->task == task)
-    {
-      GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
-                                   context->scheduled_tail,
-                                   pos);
-      GNUNET_free (pos);
-      ret = GNUNET_OK;
-    }
-    pos = next;
-  }
-  return ret;
-}
-
-
-int
-select_loop (void *cls,
-             struct GNUNET_SCHEDULER_Handle *sh)
+select_loop (struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
 {
   struct GNUNET_NETWORK_FDSet *rs;
   struct GNUNET_NETWORK_FDSet *ws;
-  struct DriverContext *context;
   int select_result;
-  int tasks_ready;
 
-  context = cls;
   GNUNET_assert (NULL != context);
   rs = GNUNET_NETWORK_fdset_create ();
   ws = GNUNET_NETWORK_fdset_create ();
-  tasks_ready = GNUNET_NO;
   while (NULL != context->scheduled_head ||
-         GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != context->timeout.rel_value_us)
+         GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != context->timeout.abs_value_us)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "select timeout = %s\n",
-         GNUNET_STRINGS_relative_time_to_string (context->timeout, GNUNET_NO));
+         GNUNET_STRINGS_absolute_time_to_string (context->timeout));
 
     GNUNET_NETWORK_fdset_zero (rs);
     GNUNET_NETWORK_fdset_zero (ws);
@@ -2259,12 +2298,14 @@ select_loop (void *cls,
         GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
       }
     }
+    struct GNUNET_TIME_Relative time_remaining =
+      GNUNET_TIME_absolute_get_remaining (context->timeout);
     if (NULL == scheduler_select)
     {
       select_result = GNUNET_NETWORK_socket_select (rs,
                                                     ws,
                                                     NULL,
-                                                    context->timeout);
+                                                    time_remaining);
     }
     else
     {
@@ -2272,7 +2313,7 @@ select_loop (void *cls,
                                         rs,
                                         ws,
                                         NULL,
-                                        context->timeout);
+                                        time_remaining);
     }
     if (select_result == GNUNET_SYSERR)
     {
@@ -2333,8 +2374,11 @@ select_loop (void *cls,
         }
       }
     }
-    tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh);
-    GNUNET_assert (GNUNET_SYSERR != tasks_ready);
+    if (GNUNET_YES == GNUNET_SCHEDULER_do_work (sh))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "scheduler has more tasks ready!\n");
+    }
   }
   GNUNET_NETWORK_fdset_destroy (rs);
   GNUNET_NETWORK_fdset_destroy (ws);
@@ -2342,14 +2386,74 @@ select_loop (void *cls,
 }
 
 
+int
+select_add (void *cls,
+            struct GNUNET_SCHEDULER_Task *task,
+            struct GNUNET_SCHEDULER_FdInfo *fdi)
+{
+  struct DriverContext *context = cls;
+  GNUNET_assert (NULL != context);
+  GNUNET_assert (NULL != task);
+  GNUNET_assert (NULL != fdi);
+  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
+                 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
+
+  if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
+  {
+    /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
+    return GNUNET_SYSERR;
+  }
+
+  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
+  scheduled->task = task;
+  scheduled->fdi = fdi;
+  scheduled->et = fdi->et;
+
+  GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
+                               context->scheduled_tail,
+                               scheduled);
+  return GNUNET_OK;
+}
+
+
+int
+select_del (void *cls,
+            struct GNUNET_SCHEDULER_Task *task)
+{
+  struct DriverContext *context;
+  struct Scheduled *pos;
+  int ret;
+
+  GNUNET_assert (NULL != cls);
+
+  context = cls;
+  ret = GNUNET_SYSERR;
+  pos = context->scheduled_head;
+  while (NULL != pos)
+  {
+    struct Scheduled *next = pos->next;
+    if (pos->task == task)
+    {
+      GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
+                                   context->scheduled_tail,
+                                   pos);
+      GNUNET_free (pos);
+      ret = GNUNET_OK;
+    }
+    pos = next;
+  }
+  return ret;
+}
+
+
 void
 select_set_wakeup (void *cls,
                    struct GNUNET_TIME_Absolute dt)
 {
   struct DriverContext *context = cls;
+  
   GNUNET_assert (NULL != context);
-
-  context->timeout = GNUNET_TIME_absolute_get_remaining (dt);
+  context->timeout = dt;
 }
 
 
@@ -2364,7 +2468,6 @@ GNUNET_SCHEDULER_driver_select ()
   struct GNUNET_SCHEDULER_Driver *select_driver;
   select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
 
-  select_driver->loop = &select_loop;
   select_driver->add = &select_add;
   select_driver->del = &select_del;
   select_driver->set_wakeup = &select_set_wakeup;