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
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>
@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
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.
@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
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.
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.
@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
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)) @{
@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
@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
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
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
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::
@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:
@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:
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
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
@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
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?
@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
-<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 & GNU inquiries to
-<a href="mailto:gnu@gnu.org"><gnu@gnu.org></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"><gnunet-developers@gnu.org></a>.</p>
-</div>
-
-<p>Copyright © 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 & GNU inquiries to
+ <a href="mailto:gnu@gnu.org"><gnu@gnu.org></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"><gnunet-developers@gnu.org></a>.</p>
+ </div>
+
+ <p>Copyright © 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>
/**
* @file consensus/gnunet-service-consensus.c
* @brief multi-peer set reconciliation
- * @author Florian Dold
+ * @author Florian Dold <flo@dold.me>
*/
#include "platform.h"
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,
/**
- * 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
{
(*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);
-
};
/**
- * 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);
/**
/**
* 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);
* 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
* 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
* 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
* 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
* @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!
*/
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,
* 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
* 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
* (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?
* @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,
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)
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;
}
else
{
/* FIXME: not yet connected to origin */
+
GNUNET_assert (0);
GNUNET_SERVICE_client_drop (client);
return;
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);
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
{
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
{
} 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",
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);\
* 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 */
};
&churn_cb,
entry,
(PEER_GO_OFFLINE == delta) ? 0 : 1);
+ rps_peers[j].entry_op_manage = entry;
}
- rps_peers[j].entry_op_manage = entry;
}
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.
*
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:
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;
}
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),
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 |
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;
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;
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
}
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);
/* 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);
#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__)
/**
* 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
* @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
};
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().
*/
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).
}
+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
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);
}
/**
* 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
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;
* 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
* 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
* 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
* 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
* 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
* 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
* 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
* || 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?
/**
- * 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;
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
}
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,
/* 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 */
&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);
{
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);
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
{
rs,
ws,
NULL,
- context->timeout);
+ time_remaining);
}
if (select_result == GNUNET_SYSERR)
{
}
}
}
- 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);
}
+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;
}
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;