gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r12176 - in gnunet: . contrib doc/man src/core src/dht src/


From: gnunet
Subject: [GNUnet-SVN] r12176 - in gnunet: . contrib doc/man src/core src/dht src/dv src/fs src/hostlist src/include src/peerinfo src/peerinfo-tool src/statistics src/testing src/topology src/transport src/util
Date: Wed, 7 Jul 2010 08:27:10 +0200

Author: grothoff
Date: 2010-07-07 08:27:10 +0200 (Wed, 07 Jul 2010)
New Revision: 12176

Modified:
   gnunet/TODO
   gnunet/contrib/defaults.conf
   gnunet/doc/man/gnunet-peerinfo.1
   gnunet/mkinstalldirs
   gnunet/src/core/core.h
   gnunet/src/core/core_api.c
   gnunet/src/core/gnunet-service-core.c
   gnunet/src/core/test_core_api.c
   gnunet/src/core/test_core_api_reliability.c
   gnunet/src/core/test_core_api_start_only.c
   gnunet/src/dht/gnunet-service-dht.c
   gnunet/src/dv/gnunet-service-dv.c
   gnunet/src/dv/test_transport_api_dv.c
   gnunet/src/fs/gnunet-service-fs.c
   gnunet/src/hostlist/gnunet-daemon-hostlist.c
   gnunet/src/hostlist/hostlist-server.c
   gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c
   gnunet/src/include/gnunet_core_service.h
   gnunet/src/include/gnunet_peerinfo_service.h
   gnunet/src/include/gnunet_protocols.h
   gnunet/src/include/gnunet_statistics_service.h
   gnunet/src/peerinfo-tool/gnunet-peerinfo.c
   gnunet/src/peerinfo-tool/test_gnunet_peerinfo.py.in
   gnunet/src/peerinfo/gnunet-service-peerinfo.c
   gnunet/src/peerinfo/peerinfo.h
   gnunet/src/peerinfo/peerinfo_api.c
   gnunet/src/peerinfo/peerinfo_api_notify.c
   gnunet/src/peerinfo/test_peerinfo_api.c
   gnunet/src/statistics/gnunet-service-statistics.c
   gnunet/src/statistics/statistics.h
   gnunet/src/statistics/statistics_api.c
   gnunet/src/statistics/test_statistics_api.c
   gnunet/src/statistics/test_statistics_api_data.conf
   gnunet/src/testing/test_testing_topology.c
   gnunet/src/testing/testing.c
   gnunet/src/topology/gnunet-daemon-topology.c
   gnunet/src/transport/gnunet-service-transport.c
   gnunet/src/util/server_nc.c
Log:
hacks from trip

Modified: gnunet/TODO
===================================================================
--- gnunet/TODO 2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/TODO 2010-07-07 06:27:10 UTC (rev 12176)
@@ -1,67 +1,42 @@
-0.9.0pre1:
-* TRANSPORT:
-  - HTTP backend [MW]
-* CORE:
-  - derived key generation [Nils]
+0.9.0pre2:
 * UTIL:
   - only connect() sockets that are ready (select()) [Nils]
     [On W32, we need to select after calling socket before doing connect etc.]
-* BUGS:
-  Jun 27 11:51:54 core-7670 ERROR Assertion failed at 
gnunet-service-core.c:3616.
-  (transport notified us that we connected to ourselves!!!)
-
-0.9.0pre2:
+* TRANSPORT:
+  - HTTP backend [MW]
+  - Jun 27 11:51:54 core-7670 ERROR Assertion failed at 
gnunet-service-core.c:3616.
+    (transport notified us that we connected to ourselves!!!)
 * CORE:
   - transport-level disconnect (i.e. TCP) does not cause core-level
     disconnect in a timely fashion (waits for connection timeout);
     need to figure a way to make it near-instant in those cases 
-    (i.e. rapid reduction in timeout on transport-level disconnect)
-  - encrypted P2P transmission (loopback) tops at 2 MB/s on my quad-core;
-    why is it so slow? Fix! (see core_api_reliability test)
-  - implement API to get notifications about bandwidth assignments to 
individual peers
-  - implement API to get notifications about updates to liveness of individual 
peers (before disconnect)
-* STATISTICS:
-  - implement notification-based statistics API
-* PEERINFO [CG]
-  - better API for trust management (or move into FS!?)
-* TOPOLOGY:
-  - needs more testing (especially F2F topology) & transport blacklisting
-* TBENCH: [MW]
-  - good to have for transport/DV evaluation! 
-* DV: [Nate]
-  - implement performance tests (needs tbench)
+    (i.e. rapid reduction in timeout on transport-level disconnect) [CG]
+  - derived key generation [Nils]
 * DHT: [Nate]
   - implement DHT service 
   - implement testcases
   - implement performance tests
-* MONKEY: [Safey]
-  - better crash management (attach debugging support, capture and analyze
-    debug output, detect random vs. deterministic crashes)
-* ARM: [CG]
-  - handle gnunet-arm -k in combination with auto-start magic (what is the 
right thing here?)
-  - discover dependencies between services
 * FS: [CG]
-  - trust & peerinfo integration
-  - load considerations (migration, routing)
+  - publishing a directory sets the embedded filename to "empty" 
+    (likely an issue with cutting off everything before '/' in the filename,
+     which in the case of a directory would leave nothing)
+  - trust: do not charge when "idle" / load considerations (migration, routing)
   - bound our priorities based on priorities used by other peers
-  - artificial delays
-  - active reply route caching design & implementation of service; gap 
extension!
   - datastore reservation (publishing)
-  - location URIs (publish, search, download)
   - unindex on index failure
+  - listing of learned namespaces
+  - collection API & tests
+    + gnunet-pseudonym (collection support)
+  - artificial delays
+  - active reply route caching design & implementation of service; gap 
extension!
   - utilize in-line files in meta data always (including in search results or
     when download is triggered manually and for probes); currently the data is
     only used when users do a general 'recursive' download
+  - location URIs (publish, search, download)
   - non-anonymous FS service (needs DHT)
     + DHT integration for search
     + CS-DHT-functions (DHT-put of LOC)
     + P2P-functions (DHT-get)
-  - listing of learned namespaces
-  - collection API & tests
-    + gnunet-pseudonym (collection support)
-  - publishing a directory sets the embedded filename to "empty" 
-    (likely an issue with cutting off everything before '/' in the filename,
-     which in the case of a directory would leave nothing)
   - implement FS performance tests
     + insert
     + download
@@ -101,6 +76,13 @@
   - implement download by URI dialog; figure out where to display those 
downloads!
   - figure out where in the GUI we should show active uploads/unindex 
operations and allow aborts
   - handle 'lost parent' case for recursive downloads (need to move children!)
+* MONKEY: [Safey]
+  - better crash management (attach debugging support, capture and analyze
+    debug output, detect random vs. deterministic crashes)
+* TBENCH: [MW]
+  - good to have for transport/DV evaluation! 
+* DV: [Nate]
+  - implement performance tests (needs tbench)
 
 
 0.9.0pre3:
@@ -113,6 +95,8 @@
   - test basic peer re-configure 
   - consider changing API for peer-group termination to 
     call continuation when done
+* TOPOLOGY:
+  - needs more testing (especially F2F topology) & transport blacklisting
 * NAT/UPNP: [MW]
   - finalize API design
   - code clean up
@@ -127,6 +111,10 @@
   - use different 'priority' for probe downloads vs. normal downloads
 * ARM: [CG/Safey]
   - better tracking of which config changes actually need to cause process 
restarts by ARM.
+  - handle gnunet-arm -k in combination with auto-start magic (what is the 
right thing here?)
+  - discover dependencies between services
+* STATISTICS:
+  - test notification-based statistics API
 * SETUP:
   - design & implement new setup tool
 
@@ -175,6 +163,8 @@
     to track actual 'use')
   - make sue we also trigger notifications whenever HELLOs expire
 * VPN
+* UTIL:
+  - allow limiting UNIX socket access by UID/GID
 
 
 
@@ -193,6 +183,9 @@
     (theoretically reduces overhead; bounds messgae queue size)
 * FS:
   - use different queue prioritization for probe-downloads vs. normal 
downloads (!?)
+* CORE:
+  - encrypted P2P transmission (loopback) tops at 2 MB/s on my quad-core;
+    why is it so slow? Fix! (see core_api_reliability test)
 
 Minor features:
 * TCP:

Modified: gnunet/contrib/defaults.conf
===================================================================
--- gnunet/contrib/defaults.conf        2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/contrib/defaults.conf        2010-07-07 06:27:10 UTC (rev 12176)
@@ -107,7 +107,6 @@
 # REJECT_FROM6 =
 # PREFIX =
 HOSTS = $SERVICEHOME/data/hosts/
-TRUST = $SERVICEHOME/data/credit/
 
 
 [transport]
@@ -201,6 +200,7 @@
 [fs]
 AUTOSTART = YES
 INDEXDB = $SERVICEHOME/idxinfo.lst
+TRUST = $SERVICEHOME/data/credit/
 IDENTITY_DIR = $SERVICEHOME/identities/
 STATE_DIR = $SERVICEHOME/persistence/
 PORT = 2094

Modified: gnunet/doc/man/gnunet-peerinfo.1
===================================================================
--- gnunet/doc/man/gnunet-peerinfo.1    2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/doc/man/gnunet-peerinfo.1    2010-07-07 06:27:10 UTC (rev 12176)
@@ -10,7 +10,7 @@
 
 .SH DESCRIPTION
 .PP
-\fBgnunet\-peerinfo\fP display the known addresses and trust of known peers.  
The tool can also be used to change the amount of trust we have in another 
peer.  For this, the options should be first the amount of trust changed 
(prefix it with "\-\- " if the amount is negative) followed by the peer 
identity.
+\fBgnunet\-peerinfo\fP display the known addresses and trust of known peers.  
 
 .SH OPTIONS
 .B
@@ -35,17 +35,7 @@
 .IP "\-L LOGLEVEL, \-\-loglelvel=LOGLEVEL"
 Set the loglevel
 
-.SH EXAMPLE
-.TP
-gnunet\-peerinfo 4 
S9LBDF6V770H8CELVKBFJMOTS25LB272JB81MRJHSRJI9B1FBVOSGJVSEIRIS5J4SRDU4HT3TBPLM4MNEND7FFUHMGCK4NBR8R2UTSG
-Increase the trust in a peer by 4
-.TP
-gnunet\-peerinfo \-\- \-2 
S9LBDF6V770H8CELVKBFJMOTS25LB272JB81MRJHSRJI9B1FBVOSGJVSEIRIS5J4SRDU4HT3TBPLM4MNEND7FFUHMGCK4NBR8R2UTSG
-Decrease the trust in a peer by 2
 
-
-
-
 .SH BUGS
 Report bugs by using mantis <https://gnunet.org/bugs/> or by sending 
electronic mail to <address@hidden>
 

Modified: gnunet/mkinstalldirs
===================================================================
--- gnunet/mkinstalldirs        2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/mkinstalldirs        2010-07-07 06:27:10 UTC (rev 12176)
@@ -1,7 +1,7 @@
 #! /bin/sh
 # mkinstalldirs --- make directory hierarchy
 
-scriptversion=2009-04-28.21; # UTC
+scriptversion=2006-05-11.19
 
 # Original author: Noah Friedman <address@hidden>
 # Created: 1993-05-16
@@ -157,6 +157,5 @@
 # eval: (add-hook 'write-file-hooks 'time-stamp)
 # time-stamp-start: "scriptversion="
 # time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-time-zone: "UTC"
-# time-stamp-end: "; # UTC"
+# time-stamp-end: "$"
 # End:

Modified: gnunet/src/core/core.h
===================================================================
--- gnunet/src/core/core.h      2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/core/core.h      2010-07-07 06:27:10 UTC (rev 12176)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -23,6 +23,7 @@
  * @brief common internal definitions for core service
  * @author Christian Grothoff
  */
+#include "gnunet_bandwidth_lib.h"
 #include "gnunet_crypto_lib.h"
 #include "gnunet_time_lib.h"
 
@@ -45,10 +46,11 @@
 #define GNUNET_CORE_OPTION_NOTHING             0
 #define GNUNET_CORE_OPTION_SEND_CONNECT        1
 #define GNUNET_CORE_OPTION_SEND_DISCONNECT     2
-#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND   4
-#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND    8
-#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 16
-#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND  32
+#define GNUNET_CORE_OPTION_SEND_STATUS_CHANGE  4
+#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND   8
+#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND   16
+#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32
+#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND  64
 
 
 /**
@@ -100,13 +102,12 @@
 
 /**
  * Message sent by the service to clients to notify them
- * about a peer connecting or disconnecting.
+ * about a peer connecting.
  */
 struct ConnectNotifyMessage
 {
   /**
    * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
-   * or GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT.
    */
   struct GNUNET_MessageHeader header;
 
@@ -128,7 +129,50 @@
 };
 
 
+/**
+ * Message sent by the service to clients to notify them
+ * about a peer changing status.
+ */
+struct PeerStatusNotifyMessage
+{
+  /**
+   * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PEER_STATUS
+   */
+  struct GNUNET_MessageHeader header;
 
+  /**
+   * Distance to the peer.
+   */
+  uint32_t distance GNUNET_PACKED;
+
+  /**
+   * Currently observed latency.
+   */
+  struct GNUNET_TIME_RelativeNBO latency;
+
+  /**
+   * When the peer would time out (unless we see activity)
+   */
+  struct GNUNET_TIME_AbsoluteNBO timeout;
+
+  /**
+   * Available bandwidth from the peer.
+   */
+  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
+
+  /**
+   * Available bandwidth to the peer.
+   */
+  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
+
+  /**
+   * Identity of the peer.
+   */
+  struct GNUNET_PeerIdentity peer;
+
+};
+
+
 /**
  * Message sent by the service to clients to notify them
  * about a peer disconnecting.

Modified: gnunet/src/core/core_api.c
===================================================================
--- gnunet/src/core/core_api.c  2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/core/core_api.c  2010-07-07 06:27:10 UTC (rev 12176)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -67,6 +67,11 @@
   GNUNET_CORE_DisconnectEventHandler disconnects;
 
   /**
+   * Function to call whenever we're notified about a peer changing status.
+   */  
+  GNUNET_CORE_PeerStatusEventHandler status_events;
+  
+  /**
    * Function to call whenever we receive an inbound message.
    */
   GNUNET_CORE_MessageCallback inbound_notify;
@@ -381,6 +386,7 @@
   const struct DisconnectNotifyMessage *dnm;
   const struct NotifyTrafficMessage *ntm;
   const struct GNUNET_MessageHeader *em;
+  const struct PeerStatusNotifyMessage *psnm;
   uint16_t msize;
   uint16_t et;
   const struct GNUNET_CORE_MessageHandler *mh;
@@ -433,6 +439,26 @@
       h->disconnects (h->cls,
                      &dnm->peer);
       break;
+    case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE:
+      if (NULL == h->status_events)
+        {
+          GNUNET_break (0);
+          break;
+        }
+      if (msize != sizeof (struct PeerStatusNotifyMessage))
+        {
+          GNUNET_break (0);
+          break;
+        }
+      psnm = (const struct PeerStatusNotifyMessage *) msg;
+      h->status_events (h->cls,
+                       &psnm->peer,
+                       GNUNET_TIME_relative_ntoh (psnm->latency),
+                       ntohl (psnm->distance),
+                       psnm->bandwidth_in,
+                       psnm->bandwidth_out,
+                       GNUNET_TIME_absolute_ntoh (psnm->timeout));
+      break;
     case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND:
       if (msize <
           sizeof (struct NotifyTrafficMessage) +
@@ -658,6 +684,8 @@
     opt |= GNUNET_CORE_OPTION_SEND_CONNECT;
   if (h->disconnects != NULL)
     opt |= GNUNET_CORE_OPTION_SEND_DISCONNECT;
+  if (h->status_events != NULL)
+    opt |= GNUNET_CORE_OPTION_SEND_STATUS_CHANGE;
   if (h->inbound_notify != NULL)
     {
       if (h->inbound_hdr_only)
@@ -717,6 +745,7 @@
                      GNUNET_CORE_StartupCallback init,
                      GNUNET_CORE_ConnectEventHandler connects,
                      GNUNET_CORE_DisconnectEventHandler disconnects,
+                    GNUNET_CORE_PeerStatusEventHandler status_events,
                      GNUNET_CORE_MessageCallback inbound_notify,
                      int inbound_hdr_only,
                      GNUNET_CORE_MessageCallback outbound_notify,
@@ -732,6 +761,7 @@
   h->init = init;
   h->connects = connects;
   h->disconnects = disconnects;
+  h->status_events = status_events;
   h->inbound_notify = inbound_notify;
   h->outbound_notify = outbound_notify;
   h->inbound_hdr_only = inbound_hdr_only;

Modified: gnunet/src/core/gnunet-service-core.c
===================================================================
--- gnunet/src/core/gnunet-service-core.c       2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/core/gnunet-service-core.c       2010-07-07 06:27:10 UTC (rev 
12176)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -830,6 +830,43 @@
 
 
 /**
+ * Function called by transport telling us that a peer
+ * changed status.
+ *
+ * @param peer the peer that changed status
+ */
+static void
+handle_peer_status_change (struct Neighbour *n)
+{
+  struct PeerStatusNotifyMessage psnm;
+
+  if (! n->is_connected)
+    return;
+#if DEBUG_CORE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Peer `%4s' changed status\n",
+             GNUNET_i2s (peer));
+#endif
+  psnm.header.size = htons (sizeof (struct PeerStatusNotifyMessage));
+  psnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE);
+  psnm.distance = htonl (n->last_distance);
+  psnm.latency = GNUNET_TIME_relative_hton (n->last_latency);
+  psnm.timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add 
(n->last_activity,
+                                                                     
GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
+  psnm.bandwidth_in = n->bw_in;
+  psnm.bandwidth_out = n->bw_out;
+  psnm.peer = n->peer;
+  send_to_all_clients (&psnm.header, 
+                      GNUNET_YES, 
+                      GNUNET_CORE_OPTION_SEND_STATUS_CHANGE);
+  GNUNET_STATISTICS_update (stats, 
+                           gettext_noop ("# peer status changes"), 
+                           1, 
+                           GNUNET_NO);
+}
+
+
+/**
  * Handle CORE_INIT request.
  */
 static void
@@ -997,16 +1034,21 @@
       if (n->bw_out_internal_limit.value__ != rcm->limit_outbound.value__)
        {
          n->bw_out_internal_limit = rcm->limit_outbound;
-         n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
-                                                 n->bw_out_external_limit);
-         GNUNET_BANDWIDTH_tracker_update_quota (&n->available_recv_window,
-                                                n->bw_out);
-         GNUNET_TRANSPORT_set_quota (transport,
-                                     &n->peer,
-                                     n->bw_in,
-                                     n->bw_out,
-                                     GNUNET_TIME_UNIT_FOREVER_REL,
-                                     NULL, NULL); 
+         if (n->bw_out.value__ != GNUNET_BANDWIDTH_value_min 
(n->bw_out_internal_limit,
+                                                              
n->bw_out_external_limit).value__)
+           {
+             n->bw_out = GNUNET_BANDWIDTH_value_min (n->bw_out_internal_limit,
+                                                     n->bw_out_external_limit);
+             GNUNET_BANDWIDTH_tracker_update_quota (&n->available_recv_window,
+                                                    n->bw_out);
+             GNUNET_TRANSPORT_set_quota (transport,
+                                         &n->peer,
+                                         n->bw_in,
+                                         n->bw_out,
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
+                                         NULL, NULL); 
+             handle_peer_status_change (n);
+           }
        }
       if (want_reserv < 0)
         {
@@ -2359,13 +2401,11 @@
  * @param cls the 'struct Neighbour' to retry sending the key for
  * @param peer the peer for which this is the HELLO
  * @param hello HELLO message of that peer
- * @param trust amount of trust we currently have in that peer
  */
 static void
 process_hello_retry_send_key (void *cls,
                               const struct GNUNET_PeerIdentity *peer,
-                              const struct GNUNET_HELLO_Message *hello,
-                              uint32_t trust)
+                              const struct GNUNET_HELLO_Message *hello)
 {
   struct Neighbour *n = cls;
 
@@ -2516,7 +2556,6 @@
       GNUNET_assert (n->pitr == NULL);
       n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
                                         &n->peer,
-                                        0,
                                         
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 20),
                                         &process_hello_retry_send_key, n);
       return;
@@ -2666,13 +2705,11 @@
  * @param cls pointer to the set key message
  * @param peer the peer for which this is the HELLO
  * @param hello HELLO message of that peer
- * @param trust amount of trust we currently have in that peer
  */
 static void
 process_hello_retry_handle_set_key (void *cls,
                                     const struct GNUNET_PeerIdentity *peer,
-                                    const struct GNUNET_HELLO_Message *hello,
-                                    uint32_t trust)
+                                    const struct GNUNET_HELLO_Message *hello)
 {
   struct Neighbour *n = cls;
   struct SetKeyMessage *sm = n->skm;
@@ -2922,6 +2959,7 @@
                                        GNUNET_TIME_relative_divide 
(GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
                                        &send_keep_alive,
                                        n);
+      handle_peer_status_change (n);
       break;
     default:
       GNUNET_break (0);
@@ -2974,7 +3012,6 @@
       n->skm = m_cpy;
       n->pitr = GNUNET_PEERINFO_iterate (peerinfo,
                                         &n->peer,
-                                        0,
                                         GNUNET_TIME_UNIT_MINUTES,
                                         &process_hello_retry_handle_set_key, 
n);
       GNUNET_STATISTICS_update (stats, 
@@ -3364,7 +3401,8 @@
   GNUNET_STATISTICS_set (stats,
                         gettext_noop ("# bytes of payload decrypted"),
                         size - sizeof (struct EncryptedMessage),
-                        GNUNET_NO);      
+                        GNUNET_NO);
+  handle_peer_status_change (n);
   if (GNUNET_OK != GNUNET_SERVER_mst_receive (mst, 
                                              n,
                                              &buf[sizeof (struct 
EncryptedMessage)], 
@@ -3396,6 +3434,7 @@
   int up;
   uint16_t type;
   uint16_t size;
+  int changed;
 
 #if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -3411,6 +3450,7 @@
   n = find_neighbour (peer);
   if (n == NULL)
     n = create_neighbour (peer);
+  changed = (latency.value != n->last_latency.value) || (distance != 
n->last_distance);
   n->last_latency = latency;
   n->last_distance = distance;
   up = (n->status == PEER_STATE_KEY_CONFIRMED);
@@ -3496,6 +3536,7 @@
     {
       now = GNUNET_TIME_absolute_get ();
       n->last_activity = now;
+      changed = GNUNET_YES;
       if (!up)
        {
          GNUNET_STATISTICS_update (stats, gettext_noop ("# established 
sessions"), 1, GNUNET_NO);
@@ -3509,6 +3550,8 @@
                                        &send_keep_alive,
                                        n);
     }
+  if (changed)
+    handle_peer_status_change (n);
 }
 
 
@@ -3591,6 +3634,7 @@
                                    n->bw_out,
                                    GNUNET_TIME_UNIT_FOREVER_REL,
                                    NULL, NULL);
+      handle_peer_status_change (n);
     }
   schedule_quota_update (n);
 }

Modified: gnunet/src/core/test_core_api.c
===================================================================
--- gnunet/src/core/test_core_api.c     2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/core/test_core_api.c     2010-07-07 06:27:10 UTC (rev 12176)
@@ -228,6 +228,7 @@
                            &init_notify,                        
                            &connect_notify,
                            &disconnect_notify,
+                          NULL,
                            &inbound_notify,
                            GNUNET_YES,
                            &outbound_notify, GNUNET_YES, handlers);
@@ -321,6 +322,7 @@
                        &init_notify,
                       &connect_notify,
                        &disconnect_notify,
+                      NULL,
                        &inbound_notify,
                        GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);
 }

Modified: gnunet/src/core/test_core_api_reliability.c
===================================================================
--- gnunet/src/core/test_core_api_reliability.c 2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/core/test_core_api_reliability.c 2010-07-07 06:27:10 UTC (rev 
12176)
@@ -375,6 +375,7 @@
                            &init_notify,                        
                            &connect_notify,
                            &disconnect_notify,
+                          NULL,
                            &inbound_notify,
                            GNUNET_YES,
                            &outbound_notify, GNUNET_YES, handlers);
@@ -468,6 +469,7 @@
                        &init_notify,
                       &connect_notify,
                        &disconnect_notify,
+                      NULL,
                        &inbound_notify,
                        GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);
 }

Modified: gnunet/src/core/test_core_api_start_only.c
===================================================================
--- gnunet/src/core/test_core_api_start_only.c  2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/core/test_core_api_start_only.c  2010-07-07 06:27:10 UTC (rev 
12176)
@@ -133,6 +133,7 @@
                            &init_notify,                        
                            &connect_notify,
                            &disconnect_notify,
+                          NULL,
                            &inbound_notify,
                            GNUNET_YES,
                            &outbound_notify, GNUNET_YES, handlers);
@@ -182,6 +183,7 @@
                        &init_notify,
                       &connect_notify,
                        &disconnect_notify,
+                      NULL,
                        &inbound_notify,
                        GNUNET_YES, &outbound_notify, GNUNET_YES, handlers);
 }

Modified: gnunet/src/dht/gnunet-service-dht.c
===================================================================
--- gnunet/src/dht/gnunet-service-dht.c 2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/dht/gnunet-service-dht.c 2010-07-07 06:27:10 UTC (rev 12176)
@@ -834,6 +834,7 @@
                                  &core_init,    /* Call core_init once 
connected */
                                  &handle_core_connect,  /* Don't care about 
connects */
                                  NULL,  /* Don't care about disconnects */
+                                NULL,  /* Don't care about peer status changes 
*/
                                  NULL,  /* Don't want notified about all 
incoming messages */
                                  GNUNET_NO,     /* For header only inbound 
notification */
                                  NULL,  /* Don't want notified about all 
outbound messages */

Modified: gnunet/src/dv/gnunet-service-dv.c
===================================================================
--- gnunet/src/dv/gnunet-service-dv.c   2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/dv/gnunet-service-dv.c   2010-07-07 06:27:10 UTC (rev 12176)
@@ -2755,12 +2755,11 @@
  * @param cls closure
  * @param peer id of the peer, NULL for last call
  * @param hello hello message for the peer (can be NULL)
- * @param trust amount of trust we have in the peer
  */
 static void
 process_peerinfo (void *cls,
                   const struct GNUNET_PeerIdentity *peer,
-                  const struct GNUNET_HELLO_Message *hello, uint32_t trust)
+                  const struct GNUNET_HELLO_Message *hello)
 {
   struct PeerIteratorContext *peerinfo_iterator = cls;
   struct DirectNeighbor *neighbor = peerinfo_iterator->neighbor;
@@ -2779,7 +2778,6 @@
 #endif
           peerinfo_iterator->ic = GNUNET_PEERINFO_iterate(peerinfo_handle,
                                                           
&peerinfo_iterator->neighbor->identity,
-                                                          0,
                                                           
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
                                                           &process_peerinfo,
                                                           peerinfo_iterator);
@@ -2856,7 +2854,6 @@
     peerinfo_iterator->neighbor = neighbor;
     peerinfo_iterator->ic = GNUNET_PEERINFO_iterate (peerinfo_handle,
                                                      peer,
-                                                     0,
                                                      
GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
                                                      &process_peerinfo,
                                                      peerinfo_iterator);
@@ -2988,6 +2985,7 @@
                        &core_init,
                        &handle_core_connect,
                        &handle_core_disconnect,
+                      NULL,
                        NULL,
                        GNUNET_NO,
                        NULL,

Modified: gnunet/src/dv/test_transport_api_dv.c
===================================================================
--- gnunet/src/dv/test_transport_api_dv.c       2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/dv/test_transport_api_dv.c       2010-07-07 06:27:10 UTC (rev 
12176)
@@ -534,14 +534,14 @@
    * Connect to the receiving peer
    */
   pos->peer2handle = GNUNET_CORE_connect (sched,
-                       pos->peer2->cfg,
-                       TIMEOUT,
-                       pos,
-                       &init_notify_peer2,
-                       NULL,
-                       NULL,
-                       NULL,
-                       GNUNET_YES, NULL, GNUNET_YES, handlers);
+                                         pos->peer2->cfg,
+                                         TIMEOUT,
+                                         pos,
+                                         &init_notify_peer2,
+                                         NULL,
+                                         NULL,
+                                         NULL, NULL,
+                                         GNUNET_YES, NULL, GNUNET_YES, 
handlers);
 
 }
 
@@ -578,9 +578,9 @@
                                           TIMEOUT,
                                           pos,
                                           &init_notify_peer1,
+                                          NULL, NULL,
                                           NULL,
                                           NULL,
-                                          NULL,
                                           GNUNET_NO, NULL, GNUNET_NO, 
no_handlers);
 
   GNUNET_assert(pos->peer1handle != NULL);
@@ -893,7 +893,7 @@
   GNUNET_assert(GNUNET_SYSERR != 
GNUNET_CONTAINER_multihashmap_put(peer_daemon_hash, &id->hashPubKey, d, 
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 
   new_peer = GNUNET_malloc(sizeof(struct PeerContext));
-  new_peer->peer_handle = GNUNET_CORE_connect(sched, cfg, 
GNUNET_TIME_UNIT_FOREVER_REL, d, NULL, &all_connect_handler, NULL, NULL, 
GNUNET_NO, NULL, GNUNET_NO, no_handlers);
+  new_peer->peer_handle = GNUNET_CORE_connect(sched, cfg, 
GNUNET_TIME_UNIT_FOREVER_REL, d, NULL, &all_connect_handler, NULL, NULL, NULL, 
GNUNET_NO, NULL, GNUNET_NO, no_handlers);
   new_peer->daemon = d;
   new_peer->next = all_peers;
   all_peers = new_peer;

Modified: gnunet/src/fs/gnunet-service-fs.c
===================================================================
--- gnunet/src/fs/gnunet-service-fs.c   2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/fs/gnunet-service-fs.c   2010-07-07 06:27:10 UTC (rev 12176)
@@ -55,6 +55,12 @@
 #define MAX_QUEUE_PER_PEER 16
 
 /**
+ * How often do we flush trust values to disk?
+ */
+#define TRUST_FLUSH_FREQ GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 5)
+
+
+/**
  * Inverse of the probability that we will submit the same query
  * to the same peer again.  If the same peer already got the query
  * repeatedly recently, the probability is multiplied by the inverse
@@ -211,11 +217,16 @@
   uint64_t inc_preference;
 
   /**
-   * Trust delta to still commit to the system.
+   * Trust rating for this peer
    */
-  uint32_t trust_delta;
+  uint32_t trust;
 
   /**
+   * Trust rating for this peer on disk.
+   */
+  uint32_t disk_trust;
+
+  /**
    * The peer's identity.
    */
   GNUNET_PEER_Id pid;  
@@ -680,6 +691,11 @@
 static struct GNUNET_DATASTORE_QueueEntry *mig_qe;
 
 /**
+ * Where do we store trust information?
+ */
+static char *trustDirectory;
+
+/**
  * ID of task that collects blocks for migration.
  */
 static GNUNET_SCHEDULER_TaskIdentifier mig_task;
@@ -702,6 +718,24 @@
 
 
 /**
+ * Get the filename under which we would store the GNUNET_HELLO_Message
+ * for the given host and protocol.
+ * @return filename of the form DIRECTORY/HOSTID
+ */
+static char *
+get_trust_filename (const struct GNUNET_PeerIdentity *id)
+{
+  struct GNUNET_CRYPTO_HashAsciiEncoded fil;
+  char *fn;
+
+  GNUNET_CRYPTO_hash_to_enc (&id->hashPubKey, &fil);
+  GNUNET_asprintf (&fn, "%s%s%s", trustDirectory, DIR_SEPARATOR_STR, &fil);
+  return fn;
+}
+
+
+
+/**
  * Transmit messages by copying it to the target buffer
  * "buf".  "buf" will be NULL and "size" zero if the socket was closed
  * for writing in the meantime.  In that case, do nothing
@@ -1148,9 +1182,18 @@
 {
   struct ConnectedPeer *cp;
   struct MigrationReadyBlock *pos;
+  char *fn;
+  uint32_t trust;
   
   cp = GNUNET_malloc (sizeof (struct ConnectedPeer));
   cp->pid = GNUNET_PEER_intern (peer);
+
+  fn = get_trust_filename (peer);
+  if ((GNUNET_DISK_file_test (fn) == GNUNET_YES) &&
+      (sizeof (trust) == GNUNET_DISK_fn_read (fn, &trust, sizeof (trust))))
+    cp->disk_trust = cp->trust = ntohl (trust);
+  GNUNET_free (fn);
+
   GNUNET_break (GNUNET_OK ==
                GNUNET_CONTAINER_multihashmap_put (connected_peers,
                                                   &peer->hashPubKey,
@@ -1166,8 +1209,107 @@
 }
 
 
+/**
+ * Increase the host credit by a value.
+ *
+ * @param host which peer to change the trust value on
+ * @param value is the int value by which the
+ *  host credit is to be increased or decreased
+ * @returns the actual change in trust (positive or negative)
+ */
+static int
+change_host_trust (struct ConnectedPeer *host, int value)
+{
+  unsigned int old_trust;
 
+  if (value == 0)
+    return 0;
+  GNUNET_assert (host != NULL);
+  old_trust = host->trust;
+  if (value > 0)
+    {
+      if (host->trust + value < host->trust)
+        {
+          value = UINT32_MAX - host->trust;
+          host->trust = UINT32_MAX;
+        }
+      else
+        host->trust += value;
+    }
+  else
+    {
+      if (host->trust < -value)
+        {
+          value = -host->trust;
+          host->trust = 0;
+        }
+      else
+        host->trust += value;
+    }
+  return value;
+}
+
+
 /**
+ * Write host-trust information to a file - flush the buffer entry!
+ */
+static int
+flush_trust (void *cls,
+            const GNUNET_HashCode *key,
+            void *value)
+{
+  struct ConnectedPeer *host = value;
+  char *fn;
+  uint32_t trust;
+  struct GNUNET_PeerIdentity pid;
+
+  if (host->trust == host->disk_trust)
+    return GNUNET_OK;                     /* unchanged */
+  GNUNET_PEER_resolve (host->pid,
+                      &pid);
+  fn = get_trust_filename (&pid);
+  if (host->trust == 0)
+    {
+      if ((0 != UNLINK (fn)) && (errno != ENOENT))
+        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
+                                  GNUNET_ERROR_TYPE_BULK, "unlink", fn);
+    }
+  else
+    {
+      trust = htonl (host->trust);
+      if (sizeof(uint32_t) == GNUNET_DISK_fn_write (fn, &trust, 
+                                                   sizeof(uint32_t),
+                                                   GNUNET_DISK_PERM_USER_READ 
| GNUNET_DISK_PERM_USER_WRITE
+                                                   | 
GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ))
+        host->disk_trust = host->trust;
+    }
+  GNUNET_free (fn);
+  return GNUNET_OK;
+}
+
+/**
+ * Call this method periodically to scan data/hosts for new hosts.
+ */
+static void
+cron_flush_trust (void *cls,
+                 const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+  if (NULL == connected_peers)
+    return;
+  GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
+                                        &flush_trust,
+                                        NULL);
+  if (NULL == tc)
+    return;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+  GNUNET_SCHEDULER_add_delayed (tc->sched,
+                               TRUST_FLUSH_FREQ, &cron_flush_trust, NULL);
+}
+
+
+/**
  * Free (each) request made by the peer.
  *
  * @param cls closure, points to peer that the request belongs to
@@ -1253,7 +1395,7 @@
                                             &consider_migration,
                                             pos);
     }
-  if (cp->trust_delta > 0)
+  if (cp->trust > 0)
     {
       /* FIXME: push trust back to peerinfo! 
         (need better peerinfo API!) */
@@ -1400,6 +1542,7 @@
   while (client_list != NULL)
     handle_client_disconnect (NULL,
                              client_list->client);
+  cron_flush_trust (NULL, NULL);
   GNUNET_CONTAINER_multihashmap_iterate (connected_peers,
                                         &clean_peer,
                                         NULL);
@@ -1430,6 +1573,8 @@
   dsh = NULL;
   sched = NULL;
   cfg = NULL;  
+  GNUNET_free_non_null (trustDirectory);
+  trustDirectory = NULL;
 }
 
 
@@ -2674,7 +2819,7 @@
   if (prq.sender != NULL)
     {
       prq.sender->inc_preference += CONTENT_BANDWIDTH_VALUE + 1000 * 
prq.priority;
-      prq.sender->trust_delta += prq.priority;
+      prq.sender->trust += prq.priority;
     }
   if (GNUNET_YES == active_migration)
     {
@@ -2954,13 +3099,9 @@
 bound_priority (uint32_t prio_in,
                struct ConnectedPeer *cp)
 {
-  if (cp->trust_delta > prio_in)
-    {
-      cp->trust_delta -= prio_in;
-      return prio_in;
-    }
-  // FIXME: get out trust in the target peer from peerinfo!
-  return 0; 
+  /* FIXME: check if load is low and we
+     hence should not charge... */
+  return change_host_trust (cp, prio_in);
 }
 
 
@@ -3510,6 +3651,7 @@
                              NULL,
                              &peer_connect_handler,
                              &peer_disconnect_handler,
+                             NULL,
                              NULL, GNUNET_NO,
                              NULL, GNUNET_NO,
                              p2p_handlers);
@@ -3543,6 +3685,17 @@
   GNUNET_SERVER_disconnect_notify (server, 
                                   &handle_client_disconnect,
                                   NULL);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                                          "fs",
+                                                          "TRUST",
+                                                          &trustDirectory));
+  GNUNET_DISK_directory_create (trustDirectory);
+  GNUNET_SCHEDULER_add_with_priority (sched,
+                                     GNUNET_SCHEDULER_PRIORITY_HIGH,
+                                     &cron_flush_trust, NULL);
+
+
   GNUNET_SERVER_add_handlers (server, handlers);
   GNUNET_SCHEDULER_add_delayed (sched,
                                GNUNET_TIME_UNIT_FOREVER_REL,

Modified: gnunet/src/hostlist/gnunet-daemon-hostlist.c
===================================================================
--- gnunet/src/hostlist/gnunet-daemon-hostlist.c        2010-07-06 16:25:08 UTC 
(rev 12175)
+++ gnunet/src/hostlist/gnunet-daemon-hostlist.c        2010-07-07 06:27:10 UTC 
(rev 12176)
@@ -274,7 +274,7 @@
                              GNUNET_TIME_UNIT_FOREVER_REL,
                              NULL,
                              &core_init,
-                             &connect_handler, &disconnect_handler,
+                             &connect_handler, &disconnect_handler, NULL,
                              NULL, GNUNET_NO,
                              NULL, GNUNET_NO,
                              learning? learn_handlers : no_learn_handlers);

Modified: gnunet/src/hostlist/hostlist-server.c
===================================================================
--- gnunet/src/hostlist/hostlist-server.c       2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/hostlist/hostlist-server.c       2010-07-07 06:27:10 UTC (rev 
12176)
@@ -183,8 +183,7 @@
 static void
 host_processor (void *cls,
                const struct GNUNET_PeerIdentity * peer,
-                const struct GNUNET_HELLO_Message *hello,
-               uint32_t trust)
+                const struct GNUNET_HELLO_Message *hello)
 {
   struct HostSet *results = cls;
   size_t old;
@@ -447,13 +446,11 @@
  * @param cls closure (not used)
  * @param peer potential peer to connect to
  * @param hello HELLO for this peer (or NULL)
- * @param trust how much we trust the peer (not used)
  */
 static void
 process_notify (void *cls,
                 const struct GNUNET_PeerIdentity *peer,
-                const struct GNUNET_HELLO_Message *hello,
-                uint32_t trust)
+                const struct GNUNET_HELLO_Message *hello)
 {
   struct HostSet *results;
 #if DEBUG_HOSTLIST_SERVER
@@ -464,7 +461,6 @@
   GNUNET_assert (peerinfo != NULL);
   pitr = GNUNET_PEERINFO_iterate (peerinfo,
                                   NULL,
-                                  0,
                                   GNUNET_TIME_UNIT_MINUTES,
                                   &host_processor,
                                   results);

Modified: gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c
===================================================================
--- gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c  2010-07-06 
16:25:08 UTC (rev 12175)
+++ gnunet/src/hostlist/test_gnunet_daemon_hostlist_learning.c  2010-07-07 
06:27:10 UTC (rev 12176)
@@ -383,13 +383,13 @@
   if ( NULL != filename)  GNUNET_free ( filename );
 
   p->core = GNUNET_CORE_connect (sched, p->cfg,
-                              GNUNET_TIME_UNIT_FOREVER_REL,
-                              NULL,
-                              NULL,
-                              NULL, NULL,
-                              NULL, GNUNET_NO,
-                              NULL, GNUNET_NO,
-                              learn_handlers );
+                                GNUNET_TIME_UNIT_FOREVER_REL,
+                                NULL,
+                                NULL,
+                                NULL, NULL, NULL,
+                                NULL, GNUNET_NO,
+                                NULL, GNUNET_NO,
+                                learn_handlers );
   GNUNET_assert ( NULL != p->core );
   p->stats = GNUNET_STATISTICS_create (sched, "hostlist", p->cfg);
   GNUNET_assert ( NULL != p->stats );

Modified: gnunet/src/include/gnunet_core_service.h
===================================================================
--- gnunet/src/include/gnunet_core_service.h    2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/include/gnunet_core_service.h    2010-07-07 06:27:10 UTC (rev 
12176)
@@ -64,6 +64,26 @@
                                                 struct GNUNET_TIME_Relative 
latency,
                                                 uint32_t distance);
 
+/**
+ * Method called whenever a given peer has a status change.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ * @param latency reported latency of the connection with 'other'
+ * @param distance reported distance (DV) to 'other' 
+ * @param bandwidth_in available amount of inbound bandwidth
+ * @param bandwidth_out available amount of outbound bandwidth
+ * @param timeout absolute time when this peer will time out
+ *        unless we see some further activity from it
+ */
+typedef void (*GNUNET_CORE_PeerStatusEventHandler) (void *cls,
+                                                   const struct
+                                                   GNUNET_PeerIdentity * peer,
+                                                   struct GNUNET_TIME_Relative 
latency,
+                                                   uint32_t distance,
+                                                   struct 
GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
+                                                   struct 
GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
+                                                   struct GNUNET_TIME_Absolute 
timeout);
 
 
 /**
@@ -166,6 +186,7 @@
  *        connected to the core service; note that timeout is only meaningful 
if init is not NULL
  * @param connects function to call on peer connect, can be NULL
  * @param disconnects function to call on peer disconnect / timeout, can be 
NULL
+ * @param status_events function to call on peer status changes, can be NULL
  * @param inbound_notify function to call for all inbound messages, can be NULL
  *                note that the core is allowed to drop notifications about 
inbound
  *                messages if the client does not process them fast enough 
(for this
@@ -201,6 +222,7 @@
                      GNUNET_CORE_StartupCallback init,
                      GNUNET_CORE_ConnectEventHandler connects,
                      GNUNET_CORE_DisconnectEventHandler disconnects,
+                    GNUNET_CORE_PeerStatusEventHandler status_events,
                      GNUNET_CORE_MessageCallback inbound_notify,
                      int inbound_hdr_only,
                      GNUNET_CORE_MessageCallback outbound_notify,

Modified: gnunet/src/include/gnunet_peerinfo_service.h
===================================================================
--- gnunet/src/include/gnunet_peerinfo_service.h        2010-07-06 16:25:08 UTC 
(rev 12175)
+++ gnunet/src/include/gnunet_peerinfo_service.h        2010-07-07 06:27:10 UTC 
(rev 12176)
@@ -20,8 +20,7 @@
 /**
  * @file include/gnunet_peerinfo_service.h
  * @brief Code to maintain the list of currently known hosts
- *   (in memory structure of data/hosts) and their trust ratings
- *   (in memory structure of data/trust)
+ *   (in memory structure of data/hosts).
  * @author Christian Grothoff
  */
 
@@ -98,13 +97,11 @@
  * @param cls closure
  * @param peer id of the peer, NULL for last call
  * @param hello hello message for the peer (can be NULL)
- * @param trust amount of trust we have in the peer
  */
 typedef void
   (*GNUNET_PEERINFO_Processor) (void *cls,
                                 const struct GNUNET_PeerIdentity * peer,
-                                const struct GNUNET_HELLO_Message * hello,
-                                uint32_t trust);
+                                const struct GNUNET_HELLO_Message * hello);
 
 
 /**
@@ -123,12 +120,11 @@
  * being done; however, the trust argument will be set to zero if we
  * are done, 1 if we timed out and 2 for fatal error.
  *
- * Instead of calling this function with 'peer == NULL' and 'trust ==
- * 0', it is often better to use 'GNUNET_PEERINFO_notify'.
+ * Instead of calling this function with 'peer == NULL' 
+ * it is often better to use 'GNUNET_PEERINFO_notify'.
  * 
  * @param h handle to the peerinfo service
  * @param peer restrict iteration to this peer only (can be NULL)
- * @param trust_delta how much to change the trust in all matching peers
  * @param timeout how long to wait until timing out
  * @param callback the method to call for each peer
  * @param callback_cls closure for callback
@@ -138,7 +134,6 @@
 struct GNUNET_PEERINFO_IteratorContext *
 GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
                         const struct GNUNET_PeerIdentity *peer,
-                        int trust_delta,
                         struct GNUNET_TIME_Relative timeout,
                         GNUNET_PEERINFO_Processor callback,
                         void *callback_cls);

Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/include/gnunet_protocols.h       2010-07-07 06:27:10 UTC (rev 
12176)
@@ -52,28 +52,8 @@
 #define GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE 3
 
 
-/**
- * Set a statistical value.
- */
-#define GNUNET_MESSAGE_TYPE_STATISTICS_SET 4
 
 /**
- * Get a statistical value(s).
- */
-#define GNUNET_MESSAGE_TYPE_STATISTICS_GET 5
-
-/**
- * Response to a STATISTICS_GET message (with value).
- */
-#define GNUNET_MESSAGE_TYPE_STATISTICS_VALUE 6
-
-/**
- * Response to a STATISTICS_GET message (end of value stream).
- */
-#define GNUNET_MESSAGE_TYPE_STATISTICS_END 7
-
-
-/**
  * Request to ARM to start a service.
  */
 #define GNUNET_MESSAGE_TYPE_ARM_START 8
@@ -345,35 +325,40 @@
 #define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT 68
 
 /**
+ * Notify clients about peer status change.
+ */
+#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE 69
+
+/**
  * Notify clients about incoming P2P messages.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 69
+#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 70
 
 /**
  * Notify clients about outgoing P2P transmissions.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND 70
+#define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND 71
 
 /**
  * Request from client to "configure" P2P connection.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO 71
+#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO 72
 
 /**
  * Response from server about (possibly updated) P2P
  * connection configuration.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 72
+#define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 73
 
 /**
  * Request from client with message to transmit.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_SEND 73
+#define GNUNET_MESSAGE_TYPE_CORE_SEND 74
 
 /**
  * Request from client asking to connect to a peer.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 74
+#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 75
 
 
 /**
@@ -584,7 +569,40 @@
  */
 #define GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT 160
 
+
 /**
+ * Set a statistical value.
+ */
+#define GNUNET_MESSAGE_TYPE_STATISTICS_SET 168
+
+/**
+ * Get a statistical value(s).
+ */
+#define GNUNET_MESSAGE_TYPE_STATISTICS_GET 169
+
+/**
+ * Response to a STATISTICS_GET message (with value).
+ */
+#define GNUNET_MESSAGE_TYPE_STATISTICS_VALUE 170
+
+/**
+ * Response to a STATISTICS_GET message (end of value stream).
+ */
+#define GNUNET_MESSAGE_TYPE_STATISTICS_END 171
+
+/**
+ * Watch changes to a statistical value.  Message format is the same
+ * as for GET, except that the subsystem and entry name must be given.
+ */
+#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH 172
+
+/**
+ * Changes to a watched value.
+ */
+#define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE 173
+
+
+/**
  * Type used to match 'all' message types.
  */
 #define GNUNET_MESSAGE_TYPE_ALL 65535

Modified: gnunet/src/include/gnunet_statistics_service.h
===================================================================
--- gnunet/src/include/gnunet_statistics_service.h      2010-07-06 16:25:08 UTC 
(rev 12175)
+++ gnunet/src/include/gnunet_statistics_service.h      2010-07-07 06:27:10 UTC 
(rev 12176)
@@ -1,6 +1,6 @@
 /*
       This file is part of GNUnet
-      (C) 2009 Christian Grothoff (and other contributing authors)
+      (C) 2009, 2010 Christian Grothoff (and other contributing authors)
 
       GNUnet is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
@@ -94,6 +94,26 @@
 
 
 /**
+ * Watch statistics from the peer (be notified whenever they change).
+ * Note that the only way to cancel a "watch" request is to destroy
+ * the statistics handle given as the first argument to this call.
+ *
+ * @param handle identification of the statistics service
+ * @param subsystem limit to the specified subsystem, never NULL
+ * @param name name of the statistic value, never NULL
+ * @param proc function to call on each value
+ * @param proc_cls closure for proc
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_STATISTICS_watch (struct GNUNET_STATISTICS_Handle *handle,
+                        const char *subsystem,
+                        const char *name,
+                        GNUNET_STATISTICS_Iterator proc, 
+                        void *proc_cls);
+
+
+/**
  * Continuation called by the "get_all" and "get" functions.
  *
  * @param cls closure

Modified: gnunet/src/peerinfo/gnunet-service-peerinfo.c
===================================================================
--- gnunet/src/peerinfo/gnunet-service-peerinfo.c       2010-07-06 16:25:08 UTC 
(rev 12175)
+++ gnunet/src/peerinfo/gnunet-service-peerinfo.c       2010-07-07 06:27:10 UTC 
(rev 12176)
@@ -23,7 +23,7 @@
  * @brief maintains list of known peers
  *
  * Code to maintain the list of currently known hosts (in memory
- * structure of data/hosts/ and data/credit/).
+ * structure of data/hosts/).
  *
  * @author Christian Grothoff
  *
@@ -46,11 +46,6 @@
 #define DATA_HOST_FREQ GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 15)
 
 /**
- * How often do we flush trust values to disk?
- */
-#define TRUST_FLUSH_FREQ GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 5)
-
-/**
  * How often do we discard old entries in data/hosts/?
  */
 #define DATA_HOST_CLEAN_FREQ GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 60)
@@ -76,16 +71,6 @@
    */
   struct GNUNET_HELLO_Message *hello;
 
-  /**
-   * Trust rating for this peer
-   */
-  uint32_t trust;
-
-  /**
-   * Trust rating for this peer on disk.
-   */
-  uint32_t disk_trust;
-
 };
 
 
@@ -105,11 +90,6 @@
 static char *networkIdDirectory;
 
 /**
- * Where do we store trust information?
- */
-static char *trustDirectory;
-
-/**
  * Handle for reporting statistics.
  */
 static struct GNUNET_STATISTICS_Handle *stats;
@@ -129,7 +109,6 @@
   im = GNUNET_malloc (sizeof (struct InfoMessage) + hs);
   im->header.size = htons (hs + sizeof (struct InfoMessage));
   im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
-  im->trust = htonl (he->trust);
   im->peer = he->identity;
   if (he->hello != NULL)
     memcpy (&im[1], he->hello, hs);
@@ -184,25 +163,7 @@
 
 
 /**
- * Get the filename under which we would store the GNUNET_HELLO_Message
- * for the given host and protocol.
- * @return filename of the form DIRECTORY/HOSTID
- */
-static char *
-get_trust_filename (const struct GNUNET_PeerIdentity *id)
-{
-  struct GNUNET_CRYPTO_HashAsciiEncoded fil;
-  char *fn;
-
-  GNUNET_CRYPTO_hash_to_enc (&id->hashPubKey, &fil);
-  GNUNET_asprintf (&fn, "%s%s%s", trustDirectory, DIR_SEPARATOR_STR, &fil);
-  return fn;
-}
-
-
-/**
- * Find the host entry for the given peer.  Call
- * only when synchronized!
+ * Find the host entry for the given peer.  FIXME: replace by hash map!
  * @return NULL if not found
  */
 static struct HostEntry *
@@ -247,13 +208,12 @@
 add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
 {
   struct HostEntry *entry;
-  char *fn;
-  uint32_t trust;
   char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
   const struct GNUNET_HELLO_Message *hello;
   struct GNUNET_HELLO_Message *hello_clean;
   int size;
   struct GNUNET_TIME_Absolute now;
+  char *fn;
 
   entry = lookup_host_entry (identity);
   if (entry != NULL)
@@ -264,11 +224,6 @@
                            GNUNET_NO);
   entry = GNUNET_malloc (sizeof (struct HostEntry));
   entry->identity = *identity;
-  fn = get_trust_filename (identity);
-  if ((GNUNET_DISK_file_test (fn) == GNUNET_YES) &&
-      (sizeof (trust) == GNUNET_DISK_fn_read (fn, &trust, sizeof (trust))))
-    entry->disk_trust = entry->trust = ntohl (trust);
-  GNUNET_free (fn);
 
   fn = get_host_filename (identity);
   if (GNUNET_DISK_file_test (fn) == GNUNET_YES)
@@ -302,56 +257,6 @@
 
 
 /**
- * Increase the host credit by a value.
- *
- * @param hostId is the identity of the host
- * @param value is the int value by which the
- *  host credit is to be increased or decreased
- * @returns the actual change in trust (positive or negative)
- */
-static int
-change_host_trust (const struct GNUNET_PeerIdentity *hostId, int value)
-{
-  struct HostEntry *host;
-  unsigned int old_trust;
-
-  if (value == 0)
-    return 0;
-  host = lookup_host_entry (hostId);
-  if (host == NULL)
-    {
-      add_host_to_known_hosts (hostId);
-      host = lookup_host_entry (hostId);
-    }
-  GNUNET_assert (host != NULL);
-  old_trust = host->trust;
-  if (value > 0)
-    {
-      if (host->trust + value < host->trust)
-        {
-          value = UINT32_MAX - host->trust;
-          host->trust = UINT32_MAX;
-        }
-      else
-        host->trust += value;
-    }
-  else
-    {
-      if (host->trust < -value)
-        {
-          value = -host->trust;
-          host->trust = 0;
-        }
-      else
-        host->trust += value;
-    }
-  if (host->trust != old_trust)
-    notify_all (host);    
-  return value;
-}
-
-
-/**
  * Remove a file that should not be there.  LOG
  * success or failure.
  */
@@ -480,16 +385,14 @@
 
 /**
  * Do transmit info either for only the host matching the given
- * argument or for all known hosts and change their trust values by
- * the given delta.
+ * argument or for all known hosts.
  *
  * @param only NULL to hit all hosts, otherwise specifies a particular target
- * @param trust_change how much should the trust be changed
  * @param client who is making the request (and will thus receive our 
confirmation)
  */
 static void
 send_to_each_host (const struct GNUNET_PeerIdentity *only,
-                   int trust_change, struct GNUNET_SERVER_Client *client)
+                   struct GNUNET_SERVER_Client *client)
 {
   struct HostEntry *pos;
   struct InfoMessage *im;
@@ -508,7 +411,6 @@
            memcmp (only, &pos->identity,
                    sizeof (struct GNUNET_PeerIdentity))))
         {
-          change_host_trust (&pos->identity, trust_change);
           hs = 0;
           im = (struct InfoMessage *) buf;
           if (pos->hello != NULL)
@@ -522,7 +424,7 @@
             }
          im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
          im->header.size = htons (sizeof (struct InfoMessage) + hs);
-          im->trust = htonl (pos->trust);
+          im->reserved = htonl (0);
           im->peer = pos->identity;
           GNUNET_SERVER_transmit_context_append_message (tc,
                                                         &im->header);
@@ -542,58 +444,6 @@
 
 
 /**
- * Write host-trust information to a file - flush the buffer entry!
- * Assumes synchronized access.
- */
-static void
-flush_trust (struct HostEntry *host)
-{
-  char *fn;
-  uint32_t trust;
-
-  if (host->trust == host->disk_trust)
-    return;                     /* unchanged */
-  fn = get_trust_filename (&host->identity);
-  if (host->trust == 0)
-    {
-      if ((0 != UNLINK (fn)) && (errno != ENOENT))
-        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
-                                  GNUNET_ERROR_TYPE_BULK, "unlink", fn);
-    }
-  else
-    {
-      trust = htonl (host->trust);
-      if (sizeof(uint32_t) == GNUNET_DISK_fn_write (fn, &trust, 
-                                                   sizeof(uint32_t),
-                                                   GNUNET_DISK_PERM_USER_READ 
| GNUNET_DISK_PERM_USER_WRITE
-                                                   | 
GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ))
-        host->disk_trust = host->trust;
-    }
-  GNUNET_free (fn);
-}
-
-/**
- * Call this method periodically to scan data/hosts for new hosts.
- */
-static void
-cron_flush_trust (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct HostEntry *pos;
-
-  pos = hosts;
-  while (pos != NULL)
-    {
-      flush_trust (pos);
-      pos = pos->next;
-    }
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  GNUNET_SCHEDULER_add_delayed (tc->sched,
-                               TRUST_FLUSH_FREQ, &cron_flush_trust, NULL);
-}
-
-
-/**
  * @brief delete expired HELLO entries in data/hosts/
  */
 static int
@@ -711,7 +561,7 @@
              "GET",
              GNUNET_i2s (&lpm->peer));
 #endif
-  send_to_each_host (&lpm->peer, ntohl (lpm->trust_change), client);
+  send_to_each_host (&lpm->peer, client);
 }
 
 
@@ -727,15 +577,12 @@
                 struct GNUNET_SERVER_Client *client,
                 const struct GNUNET_MessageHeader *message)
 {
-  const struct ListAllPeersMessage *lpm;
-
-  lpm = (const struct ListAllPeersMessage *) message;
 #if DEBUG_PEERINFO
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "`%s' message received\n",
              "GET_ALL");
 #endif
-  send_to_each_host (NULL, ntohl (lpm->trust_change), client);
+  send_to_each_host (NULL, client);
 }
 
 
@@ -814,7 +661,7 @@
     {&handle_get, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET,
      sizeof (struct ListPeerMessage)},
     {&handle_get_all, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL,
-     sizeof (struct ListAllPeersMessage)},
+     sizeof (struct GNUNET_MessageHeader)},
     {&handle_notify, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY,
      sizeof (struct GNUNET_MessageHeader)},
     {NULL, NULL, 0, 0}
@@ -826,20 +673,11 @@
                                                           "peerinfo",
                                                           "HOSTS",
                                                           
&networkIdDirectory));
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_get_value_filename (cfg,
-                                                          "peerinfo",
-                                                          "TRUST",
-                                                          &trustDirectory));
   GNUNET_DISK_directory_create (networkIdDirectory);
-  GNUNET_DISK_directory_create (trustDirectory);
   GNUNET_SCHEDULER_add_with_priority (sched,
                                      GNUNET_SCHEDULER_PRIORITY_IDLE,
                                      &cron_scan_directory_data_hosts, NULL);
   GNUNET_SCHEDULER_add_with_priority (sched,
-                                     GNUNET_SCHEDULER_PRIORITY_HIGH,
-                                     &cron_flush_trust, NULL);
-  GNUNET_SCHEDULER_add_with_priority (sched,
                                      GNUNET_SCHEDULER_PRIORITY_IDLE,
                                      &cron_clean_data_hosts, NULL);
   GNUNET_SCHEDULER_add_delayed (sched,
@@ -868,7 +706,6 @@
                             GNUNET_SERVICE_OPTION_NONE,
                             &run, NULL)) ? 0 : 1;
   GNUNET_free_non_null (networkIdDirectory);
-  GNUNET_free_non_null (trustDirectory);
   return ret;
 }
 

Modified: gnunet/src/peerinfo/peerinfo.h
===================================================================
--- gnunet/src/peerinfo/peerinfo.h      2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/peerinfo/peerinfo.h      2010-07-07 06:27:10 UTC (rev 12176)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -31,8 +31,7 @@
 
 /**
  * Message requesting a listing of all known peers,
- * possibly modified by the specified trust value
- * and restricted to the specified peer identity.
+ * possibly restricted to the specified peer identity.
  */
 struct ListPeerMessage
 {
@@ -43,10 +42,9 @@
   struct GNUNET_MessageHeader header;
 
   /**
-   * How much to change the trust in each returned peer,
-   * in network byte order.
+   * Always zero.
    */
-  int32_t trust_change GNUNET_PACKED;
+  uint32_t reserved GNUNET_PACKED;
 
   /**
    * Restrict to peers with this identity (optional
@@ -58,28 +56,6 @@
 
 
 /**
- * Message requesting a listing of all known peers,
- * possibly modified by the specified trust value
- * and restricted to the specified peer identity.
- */
-struct ListAllPeersMessage
-{
-
-  /**
-   * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_GET
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * How much to change the trust in each returned peer,
-   * in network byte order.
-   */
-  int32_t trust_change GNUNET_PACKED;
-
-};
-
-
-/**
  * Message used to inform the client about
  * a particular peer; this message is optionally followed
  * by a HELLO message for the respective peer (if available).
@@ -95,10 +71,9 @@
   struct GNUNET_MessageHeader header;
 
   /**
-   * Amount of trust we now have in the peer,
-   * in network byte order.
+   * Always zero.
    */
-  uint32_t trust GNUNET_PACKED;
+  uint32_t reserved GNUNET_PACKED;
 
   /**
    * About which peer are we talking here?

Modified: gnunet/src/peerinfo/peerinfo_api.c
===================================================================
--- gnunet/src/peerinfo/peerinfo_api.c  2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/peerinfo/peerinfo_api.c  2010-07-07 06:27:10 UTC (rev 12176)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2001, 2002, 2004, 2005, 2007, 2009 Christian Grothoff (and other 
contributing authors)
+     (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010 Christian Grothoff (and 
other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -397,7 +397,7 @@
        GNUNET_SCHEDULER_cancel (ic->h->sched, 
                                 ic->timeout_task);
       if (ic->callback != NULL)
-       ic->callback (ic->callback_cls, NULL, NULL, 1);
+       ic->callback (ic->callback_cls, NULL, NULL);
       GNUNET_free (ic);
       return;
     }
@@ -413,7 +413,7 @@
        GNUNET_SCHEDULER_cancel (ic->h->sched, 
                                 ic->timeout_task);
       if (ic->callback != NULL)
-       ic->callback (ic->callback_cls, NULL, NULL, 0);
+       ic->callback (ic->callback_cls, NULL, NULL);
       GNUNET_free (ic);
       return;
     }
@@ -428,7 +428,7 @@
        GNUNET_SCHEDULER_cancel (ic->h->sched, 
                                 ic->timeout_task);
       if (ic->callback != NULL)
-       ic->callback (ic->callback_cls, NULL, NULL, 2);
+       ic->callback (ic->callback_cls, NULL, NULL);
       GNUNET_free (ic);
       return;
     }
@@ -446,7 +446,7 @@
            GNUNET_SCHEDULER_cancel (ic->h->sched, 
                                     ic->timeout_task);
          if (ic->callback != NULL)
-           ic->callback (ic->callback_cls, NULL, NULL, 2);
+           ic->callback (ic->callback_cls, NULL, NULL);
          GNUNET_free (ic);
           return;
         }
@@ -461,7 +461,7 @@
 #endif
   ic->h->in_receive = GNUNET_YES;
   if (ic->callback != NULL)
-    ic->callback (ic->callback_cls, &im->peer, hello, ntohl (im->trust));
+    ic->callback (ic->callback_cls, &im->peer, hello);
   GNUNET_CLIENT_receive (ic->h->client,
                          &peerinfo_handler,
                          ic,
@@ -497,7 +497,7 @@
       reconnect (ic->h);
       trigger_transmit (ic->h);
       if (ic->callback != NULL)
-       ic->callback (ic->callback_cls, NULL, NULL, 1);
+       ic->callback (ic->callback_cls, NULL, NULL);
       GNUNET_free (ic);
       return;
     }  
@@ -536,7 +536,7 @@
     GNUNET_CONTAINER_DLL_remove (ic->h->tq_head,
                                 ic->h->tq_tail,
                                 ic->tqe);
-  ic->callback (ic->callback_cls, NULL, NULL, 1);
+  ic->callback (ic->callback_cls, NULL, NULL);
   ic->callback = NULL;
   if (ic->in_receive)
     return;
@@ -551,16 +551,11 @@
  * host and then finally once with a NULL pointer.  After that final
  * invocation, the iterator context must no longer be used.
  *
- * Note that the last call can be triggered by timeout or by simply
- * being done; however, the trust argument will be set to zero if we
- * are done, 1 if we timed out and 2 for fatal error.
- *
- * Instead of calling this function with 'peer == NULL' and 'trust ==
- * 0', it is often better to use 'GNUNET_PEERINFO_notify'.
+ * Instead of calling this function with 'peer == NULL' it is often
+ * better to use 'GNUNET_PEERINFO_notify'.
  * 
  * @param h handle to the peerinfo service
  * @param peer restrict iteration to this peer only (can be NULL)
- * @param trust_delta how much to change the trust in all matching peers
  * @param timeout how long to wait until timing out
  * @param callback the method to call for each peer
  * @param callback_cls closure for callback
@@ -570,12 +565,11 @@
 struct GNUNET_PEERINFO_IteratorContext *
 GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
                         const struct GNUNET_PeerIdentity *peer,
-                        int trust_delta,
                         struct GNUNET_TIME_Relative timeout,
                         GNUNET_PEERINFO_Processor callback,
                         void *callback_cls)
 {
-  struct ListAllPeersMessage *lapm;
+  struct GNUNET_MessageHeader *lapm;
   struct ListPeerMessage *lpm;
   struct GNUNET_PEERINFO_IteratorContext *ic;
   struct TransmissionQueueEntry *tqe;
@@ -587,12 +581,11 @@
                  "Requesting list of peers from PEERINFO service\n");
 #endif
       tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) +
-                          sizeof (struct ListAllPeersMessage));
-      tqe->size = sizeof (struct ListAllPeersMessage);
-      lapm = (struct ListAllPeersMessage *) &tqe[1];
-      lapm->header.size = htons (sizeof (struct ListAllPeersMessage));
-      lapm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
-      lapm->trust_change = htonl (trust_delta);
+                          sizeof (struct GNUNET_MessageHeader));
+      tqe->size = sizeof (struct GNUNET_MessageHeader);
+      lapm = (struct GNUNET_MessageHeader *) &tqe[1];
+      lapm->size = htons (sizeof (struct GNUNET_MessageHeader));
+      lapm->type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
     }
   else
     {
@@ -607,7 +600,6 @@
       lpm = (struct ListPeerMessage *) &tqe[1];
       lpm->header.size = htons (sizeof (struct ListPeerMessage));
       lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET);
-      lpm->trust_change = htonl (trust_delta);
       memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity));
     }
   ic = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_IteratorContext));

Modified: gnunet/src/peerinfo/peerinfo_api_notify.c
===================================================================
--- gnunet/src/peerinfo/peerinfo_api_notify.c   2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/peerinfo/peerinfo_api_notify.c   2010-07-07 06:27:10 UTC (rev 
12176)
@@ -142,7 +142,7 @@
              "Received information about peer `%s' from peerinfo database\n",
              GNUNET_i2s (&im->peer));
 #endif
-  nc->callback (nc->callback_cls, &im->peer, hello, ntohl (im->trust));
+  nc->callback (nc->callback_cls, &im->peer, hello);
   receive_notifications (nc);
 }
 

Modified: gnunet/src/peerinfo/test_peerinfo_api.c
===================================================================
--- gnunet/src/peerinfo/test_peerinfo_api.c     2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/peerinfo/test_peerinfo_api.c     2010-07-07 06:27:10 UTC (rev 
12176)
@@ -102,7 +102,7 @@
 static void
 process (void *cls,
          const struct GNUNET_PeerIdentity *peer,
-         const struct GNUNET_HELLO_Message *hello, uint32_t trust)
+         const struct GNUNET_HELLO_Message *hello)
 {
   int *ok = cls;
   unsigned int agc;
@@ -118,7 +118,6 @@
          add_peer ();
          ic = GNUNET_PEERINFO_iterate (h,
                                        NULL,
-                                       0,
                                        GNUNET_TIME_relative_multiply
                                        (GNUNET_TIME_UNIT_SECONDS, 15), 
                                        &process, cls);
@@ -126,7 +125,6 @@
        }
       GNUNET_assert (peer == NULL);
       GNUNET_assert (2 == *ok);
-      GNUNET_assert (trust == 0);
       GNUNET_PEERINFO_disconnect (h);
       h = NULL;
       *ok = 0;
@@ -156,7 +154,6 @@
   add_peer ();
   ic = GNUNET_PEERINFO_iterate (h,
                                NULL,
-                               0,
                                GNUNET_TIME_relative_multiply
                                (GNUNET_TIME_UNIT_SECONDS, 15),
                                &process, cls);

Modified: gnunet/src/peerinfo-tool/gnunet-peerinfo.c
===================================================================
--- gnunet/src/peerinfo-tool/gnunet-peerinfo.c  2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/peerinfo-tool/gnunet-peerinfo.c  2010-07-07 06:27:10 UTC (rev 
12176)
@@ -49,7 +49,6 @@
   char **address_list;
   unsigned int num_addresses;
   uint32_t off;
-  uint32_t trust;
 };
 
 
@@ -60,9 +59,8 @@
   unsigned int i;
 
   GNUNET_CRYPTO_hash_to_enc (&pc->peer.hashPubKey, &enc);
-  printf (_("Peer `%s' with trust %8u\n"), 
-         (const char *) &enc,
-         pc->trust);
+  printf (_("Peer `%s'\n"), 
+         (const char *) &enc);
   for (i=0;i<pc->num_addresses;i++)
     {
       printf ("\t%s\n",
@@ -156,13 +154,13 @@
 
 /**
  * Print information about the peer.
- * Currently prints the GNUNET_PeerIdentity, trust and the IP.
+ * Currently prints the GNUNET_PeerIdentity and the IP.
  * Could of course do more (e.g. resolve via DNS).
  */
 static void
 print_peer_info (void *cls,
                  const struct GNUNET_PeerIdentity *peer,
-                 const struct GNUNET_HELLO_Message *hello, uint32_t trust)
+                 const struct GNUNET_HELLO_Message *hello)
 {
   struct GNUNET_CRYPTO_HashAsciiEncoded enc;
   struct PrintContext *pc;
@@ -170,22 +168,8 @@
   if (peer == NULL)    
     {
       GNUNET_PEERINFO_disconnect (peerinfo);
-      switch (trust)
-       {
-       case 0:
-         break;
-       case 1:
-         fprintf (stderr,
-                  _("Timeout trying to interact with PEERINFO service\n"));
-         break;
-       case 2:
-         fprintf (stderr,
-                  _("Error in communication with PEERINFO service\n"));
-         break;
-       default:
-         GNUNET_break (0);
-         break;
-       }
+      fprintf (stderr,
+              _("Error in communication with PEERINFO service\n"));
       return;    
     }
   if (be_quiet)
@@ -196,7 +180,6 @@
     }
   pc = GNUNET_malloc (sizeof (struct PrintContext));
   pc->peer = *peer;  
-  pc->trust = trust;
   GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &count_address, pc);
   if (0 == pc->off)
     {
@@ -228,28 +211,11 @@
   struct GNUNET_PeerIdentity pid;
   struct GNUNET_CRYPTO_HashAsciiEncoded enc;
   char *fn;
-  int delta;
 
   sched = s;
   cfg = c;
-  delta = 0;
-  if ( (args[0] != NULL) &&
-       (args[1] != NULL) &&
-       (1 == sscanf(args[0], "%d", &delta)) &&
-       (GNUNET_OK == 
-       GNUNET_CRYPTO_hash_from_string (args[1],
-                                       &pid.hashPubKey)) )
+  if (args[0] != NULL)
     {
-      peerinfo = GNUNET_PEERINFO_connect (sched, cfg);
-      GNUNET_PEERINFO_iterate (peerinfo,
-                              &pid,
-                              delta,
-                              GNUNET_TIME_UNIT_SECONDS,
-                              &print_peer_info, NULL);                         
   
-      return;
-    }
-  else if (args[0] != NULL)
-    {
       fprintf (stderr,
               _("Invalid command line argument `%s'\n"),
               args[0]);
@@ -266,7 +232,6 @@
        }
       (void) GNUNET_PEERINFO_iterate (peerinfo,
                                      NULL,
-                                     0,
                                      GNUNET_TIME_relative_multiply
                                      (GNUNET_TIME_UNIT_SECONDS, 2),
                                      &print_peer_info, NULL);

Modified: gnunet/src/peerinfo-tool/test_gnunet_peerinfo.py.in
===================================================================
--- gnunet/src/peerinfo-tool/test_gnunet_peerinfo.py.in 2010-07-06 16:25:08 UTC 
(rev 12175)
+++ gnunet/src/peerinfo-tool/test_gnunet_peerinfo.py.in 2010-07-07 06:27:10 UTC 
(rev 12176)
@@ -46,12 +46,12 @@
   os.system ('gnunet-arm -q -i transport -c test_gnunet_peerinfo_data.conf')
   os.system ('sleep 1')
   pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf')
-  pinfo.expect (re.compile ("Peer `.*\' with trust  *0\r"));
+  pinfo.expect (re.compile ("Peer `.*\'\r"));
   pinfo.expect (re.compile (" *localhost:24357\r"));
   pinfo.expect (pexpect.EOF);
 
   pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf 
-n')
-  pinfo.expect (re.compile ("Peer `.*\' with trust  *0\r"));
+  pinfo.expect (re.compile ("Peer `.*\'\r"));
   pinfo.expect (re.compile (" *127..*:24357\r"));
   pinfo.expect (pexpect.EOF);
 
@@ -59,14 +59,6 @@
   pid = pinfo.read (-1)
   pid = pid.strip ()
 
-  pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf 4 
' + pid)
-  pinfo.expect (re.compile ("Peer `" + pid + "\' with trust  *4\r"));
-  pinfo.expect (pexpect.EOF);  
-
-  pinfo = pexpect.spawn ('gnunet-peerinfo -c test_gnunet_peerinfo_data.conf -- 
-4 ' + pid)
-  pinfo.expect (re.compile ("Peer `" + pid + "\' with trust  *0\r"));
-  pinfo.expect (pexpect.EOF);  
-
 finally:
   os.system ('gnunet-arm -c test_gnunet_peerinfo_data.conf -eq')
   os.system ('rm -rf /tmp/gnunet-test-peerinfo/')

Modified: gnunet/src/statistics/gnunet-service-statistics.c
===================================================================
--- gnunet/src/statistics/gnunet-service-statistics.c   2010-07-06 16:25:08 UTC 
(rev 12175)
+++ gnunet/src/statistics/gnunet-service-statistics.c   2010-07-07 06:27:10 UTC 
(rev 12176)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -27,6 +27,7 @@
  * - use BIO for IO operations
  */
 #include "platform.h"
+#include "gnunet_container_lib.h"
 #include "gnunet_disk_lib.h"
 #include "gnunet_getopt_lib.h"
 #include "gnunet_protocols.h"
@@ -37,6 +38,41 @@
 #include "statistics.h"
 
 /**
+ * Watch entry.
+ */
+struct WatchEntry
+{
+
+  struct WatchEntry *next;
+
+  struct WatchEntry *prev;
+
+  struct GNUNET_SERVER_Client *client;
+
+  uint64_t last_value;
+  
+  uint32_t wid;
+
+};
+
+
+/**
+ * Client entry.
+ */
+struct ClientEntry
+{
+
+  struct ClientEntry *next;
+
+  struct ClientEntry *prev;
+
+  struct GNUNET_SERVER_Client *client;
+  
+  uint32_t max_wid;
+
+};
+
+/**
  * Entry in the statistics list.
  */
 struct StatsEntry
@@ -66,6 +102,18 @@
   struct GNUNET_STATISTICS_SetMessage *msg;
 
   /**
+   * Watch context for changes to this
+   * value, or NULL for none.
+   */
+  struct WatchEntry *we_head;
+
+  /**
+   * Watch context for changes to this
+   * value, or NULL for none.
+   */
+  struct WatchEntry *we_tail;
+
+  /**
    * Our value.
    */
   uint64_t value;
@@ -92,7 +140,22 @@
  */
 static struct StatsEntry *start;
 
+static struct ClientEntry *client_head;
+
+static struct ClientEntry *client_tail;
+
 /**
+ * Our notification context.
+ */
+static struct GNUNET_SERVER_NotificationContext *nc;
+
+/**
+ * Counter used to generate unique values.
+ */
+static uint32_t uidgen;
+
+
+/**
  * Load persistent values from disk.  Disk format is
  * exactly the same format that we also use for
  * setting the values over the network.
@@ -209,7 +272,7 @@
  * Transmit the given stats value.
  */
 static void
-transmit (struct GNUNET_SERVER_TransmitContext *tc,
+transmit (struct GNUNET_SERVER_Client *client,
           const struct StatsEntry *e)
 {
   struct GNUNET_STATISTICS_ReplyMessage *m;
@@ -232,10 +295,11 @@
                                                      2, e->service, e->name));
 #if DEBUG_STATISTICS
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Transmitting value for `%s:%s': %llu\n",
-              e->service, e->name, e->value);
+              "Transmitting value for `%s:%s' (%d): %llu\n",
+              e->service, e->name,
+             e->persistent, e->value);
 #endif
-  GNUNET_SERVER_transmit_context_append_message (tc, &m->header);
+  GNUNET_SERVER_notification_context_unicast (nc, client, &m->header, 
GNUNET_NO);
   GNUNET_free (m);
 }
 
@@ -252,6 +316,32 @@
 }
 
 
+static struct ClientEntry *
+make_client_entry (struct GNUNET_SERVER_Client *client)
+{
+  struct ClientEntry *ce;
+
+  if (client == NULL)
+    return NULL;
+  ce = client_head;
+  while (ce != NULL)
+    {
+      if (ce->client == client)
+       return ce;
+      ce = ce->next;
+    }
+  ce = GNUNET_malloc (sizeof (struct ClientEntry));
+  ce->client = client;
+  GNUNET_SERVER_client_keep (client);
+  GNUNET_CONTAINER_DLL_insert (client_head,
+                              client_tail,
+                              ce);
+  GNUNET_SERVER_notification_context_add (nc,
+                                         client);
+  return ce;
+}
+
+
 /**
  * Handle GET-message.
  *
@@ -266,12 +356,13 @@
             struct GNUNET_SERVER_Client *client,
             const struct GNUNET_MessageHeader *message)
 {
+  struct GNUNET_MessageHeader end;
   char *service;
   char *name;
   struct StatsEntry *pos;
-  struct GNUNET_SERVER_TransmitContext *tc;
   size_t size;
 
+  make_client_entry (client);
   size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
   if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
                                               size, 2, &service, &name))
@@ -285,20 +376,51 @@
               "Received request for statistics on `%s:%s'\n",
               strlen (service) ? service : "*", strlen (name) ? name : "*");
 #endif
-  tc = GNUNET_SERVER_transmit_context_create (client);
   pos = start;
   while (pos != NULL)
     {
       if (matches (pos, service, name))
-        transmit (tc, pos);
+        transmit (client, pos);
       pos = pos->next;
     }
-  GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
-                                             
GNUNET_MESSAGE_TYPE_STATISTICS_END);
-  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
+  end.size = htons (sizeof (struct GNUNET_MessageHeader));
+  end.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_END);
+  GNUNET_SERVER_notification_context_unicast (nc,
+                                             client,
+                                             &end,
+                                             GNUNET_NO);
+  GNUNET_SERVER_receive_done (client,
+                             GNUNET_OK);
 }
 
 
+static void
+notify_change (struct StatsEntry *se)
+{
+  struct GNUNET_STATISTICS_WatchValueMessage wvm;
+  struct WatchEntry *pos;
+
+  pos = se->we_head;
+  while (pos != NULL)
+    {
+      if (pos->last_value != se->value)
+       {
+         wvm.header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE);
+         wvm.header.size = htons (sizeof (struct 
GNUNET_STATISTICS_WatchValueMessage));
+         wvm.flags = htonl (se->persistent ? GNUNET_STATISTICS_PERSIST_BIT : 
0);
+         wvm.wid = htonl (pos->wid);
+         wvm.reserved = htonl (0);
+         wvm.value = GNUNET_htonll (se->value);
+         GNUNET_SERVER_notification_context_unicast (nc,
+                                                     pos->client,
+                                                     &wvm.header,
+                                                     GNUNET_NO);
+         pos->last_value = se->value;
+       }
+      pos = pos->next;
+    }
+}
+
 /**
  * Handle SET-message.
  *
@@ -311,11 +433,6 @@
             struct GNUNET_SERVER_Client *client,
             const struct GNUNET_MessageHeader *message)
 {
-  /**
-   * Counter used to generate unique values.
-   */
-  static uint32_t uidgen;
-
   char *service;
   char *name;
   uint16_t msize;
@@ -326,7 +443,9 @@
   uint32_t flags;
   uint64_t value;
   int64_t delta;
+  int changed;
 
+  make_client_entry (client);
   msize = ntohs (message->size);
   if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage))
     {
@@ -344,13 +463,15 @@
       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
       return;
     }
+  flags = ntohl (msg->flags);
+  value = GNUNET_ntohll (msg->value);
 #if DEBUG_STATISTICS
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received request to update statistic on `%s:%s'\n",
-              service, name);
+              "Received request to update statistic on `%s:%s' (%u) to/by 
%llu\n",
+              service, name,
+             (unsigned int) flags,
+             (unsigned long long) value);
 #endif
-  flags = ntohl (msg->flags);
-  value = GNUNET_ntohll (msg->value);
   pos = start;
   prev = NULL;
   while (pos != NULL)
@@ -359,17 +480,20 @@
         {
           if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0)
             {
+             changed = (pos->value != value);
               pos->value = value;
             }
           else
             {
               delta = (int64_t) value;
               if ((delta < 0) && (pos->value < -delta))
-                {
-                  pos->value = 0;
+               {
+                 changed = (pos->value != 0);
+                 pos->value = 0;
                 }
               else
                 {
+                 changed = (delta != 0);
                   GNUNET_break ((delta <= 0) ||
                                 (pos->value + delta > pos->value));
                   pos->value += delta;
@@ -391,6 +515,8 @@
                       "Statistic `%s:%s' updated to value %llu.\n",
                       service, name, pos->value);
 #endif
+         if (changed) 
+           notify_change (pos);
           GNUNET_SERVER_receive_done (client, GNUNET_OK);
           return;
         }
@@ -420,6 +546,86 @@
 
 
 /**
+ * Handle WATCH-message.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_watch (void *cls,
+             struct GNUNET_SERVER_Client *client,
+             const struct GNUNET_MessageHeader *message)
+{
+  char *service;
+  char *name;
+  uint16_t msize;
+  uint16_t size;
+  struct StatsEntry *pos;
+  struct ClientEntry *ce;
+  struct WatchEntry *we;
+
+  ce = make_client_entry (client);
+  msize = ntohs (message->size);
+  if (msize < sizeof (struct GNUNET_MessageHeader))
+    {
+      GNUNET_break (0);
+      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      return;
+    }
+  size = msize - sizeof (struct GNUNET_MessageHeader);
+  if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1],
+                                              size, 2, &service, &name))
+    {
+      GNUNET_break (0);
+      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      return;
+    }
+#if DEBUG_STATISTICS
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received request to watch statistic on `%s:%s'\n",
+              service, name);
+#endif
+  pos = start;
+  while (pos != NULL)
+    {
+      if (matches (pos, service, name))
+        break;
+      pos = pos->next;
+    }
+  if (pos == NULL)
+    {
+      pos = GNUNET_malloc (sizeof (struct StatsEntry) + 
+                          sizeof (struct GNUNET_STATISTICS_SetMessage) + 
+                          size);
+      pos->next = start;
+      pos->uid = uidgen++;
+      pos->msg = (void *) &pos[1];
+      pos->msg->header.size = htons (sizeof (struct 
GNUNET_STATISTICS_SetMessage) + 
+                                    size);
+      pos->msg->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_SET);
+      memcpy (pos->msg, message, ntohs (message->size));
+      pos->service = (const char *) &pos->msg[1];
+      memcpy (&pos->msg[1], service, strlen (service)+1);
+      pos->name = &pos->service[strlen (pos->service) + 1];
+      memcpy ((void*) pos->name, name, strlen (name)+1);
+      start = pos;
+    }
+  we = GNUNET_malloc (sizeof (struct WatchEntry));
+  we->client = client;
+  GNUNET_SERVER_client_keep (client);
+  we->wid = ce->max_wid++;
+  GNUNET_CONTAINER_DLL_insert (pos->we_head,
+                              pos->we_tail,
+                              we);
+  if (pos->value != 0)
+    notify_change (pos);
+  GNUNET_SERVER_receive_done (client,
+                             GNUNET_OK);
+}
+
+
+/**
  * Task run during shutdown.
  *
  * @param cls unused
@@ -429,11 +635,88 @@
 shutdown_task (void *cls,
               const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  struct ClientEntry *ce;
+  struct WatchEntry *we;
+  struct StatsEntry *se;
+
   save ();
+  GNUNET_SERVER_notification_context_destroy (nc);
+  nc = NULL;
+  while (NULL != (ce = client_head))
+    {
+      GNUNET_SERVER_client_drop (ce->client);
+      GNUNET_CONTAINER_DLL_remove (client_head,
+                                  client_tail,
+                                  ce);
+      GNUNET_free (ce);
+    }
+  while (NULL != (se = start))
+    {
+      start = se->next;
+      while (NULL != (we = se->we_head))
+       {
+         GNUNET_SERVER_client_drop (we->client);
+         GNUNET_CONTAINER_DLL_remove (se->we_head,
+                                      se->we_tail,
+                                      we);
+         GNUNET_free (we);
+       }
+      GNUNET_free (se);
+    }
 }
 
 
 /**
+ * A client disconnected.  Remove all of its data structure entries.
+ *
+ * @param cls closure, NULL
+ * @param client identification of the client
+ */
+static void
+handle_client_disconnect (void *cls,
+                         struct GNUNET_SERVER_Client
+                         * client)
+{
+  struct ClientEntry *ce;
+  struct WatchEntry *we;
+  struct WatchEntry *wen;
+  struct StatsEntry *se;
+  
+  ce = client_head;
+  while (NULL != ce)
+    {
+      if (ce->client == client)
+       {
+         GNUNET_SERVER_client_drop (ce->client);
+         GNUNET_CONTAINER_DLL_remove (client_head,
+                                      client_tail,
+                                      ce);
+         GNUNET_free (ce);
+         break;
+       }
+      ce = ce->next;
+    }
+  se = start;
+  while (NULL != se)
+    {
+      wen = se->we_head;
+      while (NULL != (we = wen))
+       {
+         wen = we->next;
+         if (we->client != client)
+           continue;
+         GNUNET_SERVER_client_drop (we->client);
+         GNUNET_CONTAINER_DLL_remove (se->we_head,
+                                      se->we_tail,
+                                      we);
+         GNUNET_free (we);
+       }
+      se = se->next;
+    }
+}
+
+
+/**
  * Process statistics requests.
  *
  * @param cls closure
@@ -450,10 +733,15 @@
   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
     {&handle_set, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_SET, 0},
     {&handle_get, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_GET, 0},
+    {&handle_watch, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_WATCH, 0},
     {NULL, NULL, 0, 0}
   };
   cfg = c;
   GNUNET_SERVER_add_handlers (server, handlers);
+  nc = GNUNET_SERVER_notification_context_create (server, 16);
+  GNUNET_SERVER_disconnect_notify (server, 
+                                  &handle_client_disconnect,
+                                  NULL);
   load (server);
   GNUNET_SCHEDULER_add_delayed (sched,
                                GNUNET_TIME_UNIT_FOREVER_REL,

Modified: gnunet/src/statistics/statistics.h
===================================================================
--- gnunet/src/statistics/statistics.h  2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/statistics/statistics.h  2010-07-07 06:27:10 UTC (rev 12176)
@@ -91,4 +91,43 @@
 
 };
 
+
+/**
+ * Message transmitted if a watched value changes.
+ */
+struct GNUNET_STATISTICS_WatchValueMessage
+{
+  /**
+   * Type: GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * 0 for absolute value, 1 for relative value; 2 to make persistent
+   * (see GNUNET_STATISTICS_SETFLAG_*).
+   */
+  uint32_t flags GNUNET_PACKED;
+
+  /**
+   * Unique watch identification number (watch
+   * requests are enumerated in the order they 
+   * are received, the first request having 
+   * a wid of zero). 
+   */
+  uint32_t wid GNUNET_PACKED;
+
+  /**
+   * Reserved (always 0).
+   */
+  uint32_t reserved GNUNET_PACKED;
+
+  /**
+   * Value. Note that if this is a relative value, it will
+   * be signed even though the type given here is unsigned.
+   */
+  uint64_t value GNUNET_PACKED;
+  
+};
+
+
 #endif

Modified: gnunet/src/statistics/statistics_api.c
===================================================================
--- gnunet/src/statistics/statistics_api.c      2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/statistics/statistics_api.c      2010-07-07 06:27:10 UTC (rev 
12176)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
+     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -25,6 +25,7 @@
  */
 #include "platform.h"
 #include "gnunet_client_lib.h"
+#include "gnunet_constants.h"
 #include "gnunet_container_lib.h"
 #include "gnunet_protocols.h"
 #include "gnunet_server_lib.h"
@@ -47,11 +48,41 @@
 {
   ACTION_GET,
   ACTION_SET,
-  ACTION_UPDATE
+  ACTION_UPDATE,
+  ACTION_WATCH
 };
 
 
 /**
+ * Entry kept for each value we are watching.
+ */
+struct GNUNET_STATISTICS_WatchEntry
+{
+ 
+  /**
+   * What subsystem is this action about? (never NULL)
+   */
+  char *subsystem;
+
+  /**
+   * What value is this action about? (never NULL)
+   */
+  char *name;
+
+  /**
+   * Function to call
+   */
+  GNUNET_STATISTICS_Iterator proc;
+
+  /**
+   * Closure for proc
+   */
+  void *proc_cls;
+
+};
+
+
+/**
  * Linked list of things we still need to do.
  */
 struct GNUNET_STATISTICS_GetHandle
@@ -118,7 +149,7 @@
   int aborted;
 
   /**
-   * Is this a GET, SET or UPDATE?
+   * Is this a GET, SET, UPDATE or WATCH?
    */
   enum ActionType type;
 
@@ -179,27 +210,121 @@
   struct GNUNET_STATISTICS_GetHandle *current;
 
   /**
+   * Array of watch entries.
+   */
+  struct GNUNET_STATISTICS_WatchEntry **watches;
+
+  /**
+   * Task doing exponential back-off trying to reconnect.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier backoff_task;
+
+  /**
+   * Time for next connect retry.
+   */
+  struct GNUNET_TIME_Relative backoff;
+
+  /**
+   * Size of the 'watches' array.
+   */
+  unsigned int watches_size;
+
+  /**
    * Should this handle auto-destruct once all actions have
    * been processed?
    */
   int do_destroy;
 
+  /**
+   * Are we currently receiving from the service?
+   */
+  int receiving;
+
 };
 
 
+
 /**
+ * Schedule the next action to be performed.
+ */
+static void schedule_action (struct GNUNET_STATISTICS_Handle *h);
+
+/**
  * Try to (re)connect to the statistics service.
  *
  * @return GNUNET_YES on success, GNUNET_NO on failure.
  */
 static int
+try_connect (struct GNUNET_STATISTICS_Handle *ret);
+
+
+static void
+insert_ai (struct GNUNET_STATISTICS_Handle *h, struct 
GNUNET_STATISTICS_GetHandle *ai)
+{
+  GNUNET_CONTAINER_DLL_insert_after (h->action_head,
+                                    h->action_tail,
+                                    h->action_tail,
+                                    ai);                                    
+  if (h->action_head == ai)
+    schedule_action (h);
+}
+
+
+static void
+schedule_watch_request (struct GNUNET_STATISTICS_Handle *h,
+                       struct GNUNET_STATISTICS_WatchEntry *watch)
+{
+
+  struct GNUNET_STATISTICS_GetHandle *ai;
+  size_t slen;
+  size_t nlen;
+  size_t nsize;
+  
+  GNUNET_assert (h != NULL);
+  if (GNUNET_YES != try_connect (h))
+    {
+      schedule_action (h);
+      return;
+    }
+  slen = strlen (watch->subsystem) + 1;
+  nlen = strlen (watch->name) + 1;
+  nsize = sizeof (struct GNUNET_MessageHeader) + slen + nlen;
+  if (nsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  ai = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_GetHandle));
+  ai->sh = h;
+  ai->subsystem = GNUNET_strdup (watch->subsystem);
+  ai->name = GNUNET_strdup (watch->name);
+  ai->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
+  ai->msize = nsize;
+  ai->type = ACTION_WATCH;
+  ai->proc = watch->proc;
+  ai->cls = watch->proc_cls;
+  insert_ai (h, ai);
+}
+
+
+/**
+ * Try to (re)connect to the statistics service.
+ *
+ * @return GNUNET_YES on success, GNUNET_NO on failure.
+ */
+static int
 try_connect (struct GNUNET_STATISTICS_Handle *ret)
 {
+  unsigned int i;
   if (ret->client != NULL)
     return GNUNET_YES;
   ret->client = GNUNET_CLIENT_connect (ret->sched, "statistics", ret->cfg);
   if (ret->client != NULL)
-    return GNUNET_YES;
+    {
+      for (i=0;i<ret->watches_size;i++)
+       schedule_watch_request (ret, ret->watches[i]);
+      return GNUNET_YES;
+    }
 #if DEBUG_STATISTICS
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               _("Failed to connect to statistics service!\n"));
@@ -221,12 +346,6 @@
 
 
 /**
- * Schedule the next action to be performed.
- */
-static void schedule_action (struct GNUNET_STATISTICS_Handle *h);
-
-
-/**
  * GET processing is complete, tell client about it.
  */
 static void
@@ -259,7 +378,13 @@
   uint16_t size;
 
   if (h->current->aborted)
-    return GNUNET_OK;           /* don't bother */
+    {
+#if DEBUG_STATISTICS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Iteration was aborted, ignoring VALUE\n");
+#endif      
+      return GNUNET_OK;           /* don't bother */
+    }
   size = ntohs (msg->size);
   if (size < sizeof (struct GNUNET_STATISTICS_ReplyMessage))
     {
@@ -293,10 +418,46 @@
 #endif
       h->current->aborted = GNUNET_YES;    
     }
+#if DEBUG_STATISTICS
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "VALUE processed successfully\n");
+#endif      
   return GNUNET_OK;
 }
 
 
+static int
+process_watch_value (struct GNUNET_STATISTICS_Handle *h,
+                    const struct GNUNET_MessageHeader *msg)
+{
+  const struct GNUNET_STATISTICS_WatchValueMessage *wvm;
+  struct GNUNET_STATISTICS_WatchEntry *w;
+  uint32_t wid;
+
+  if (sizeof(struct GNUNET_STATISTICS_WatchValueMessage) !=
+      ntohs (msg->size))
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+  wvm = (const struct GNUNET_STATISTICS_WatchValueMessage *)msg;
+  wid = ntohl (wvm->wid);
+  if (wid >= h->watches_size)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+  w = h->watches[wid];
+  (void) w->proc (w->proc_cls,
+                 w->subsystem,
+                 w->name,
+                 GNUNET_ntohll (wvm->value),
+                 0 !=
+                 (ntohl (wvm->flags) & GNUNET_STATISTICS_PERSIST_BIT));
+  return GNUNET_OK;
+}
+
+
 /**
  * Function called with messages from stats service.
  *
@@ -329,21 +490,53 @@
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Received end of statistics marker\n");
 #endif
+      h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
       finish (h, GNUNET_OK);
+      if (h->watches_size > 0)
+       {
+         GNUNET_CLIENT_receive (h->client,
+                                &receive_stats,
+                                h,
+                                GNUNET_TIME_UNIT_FOREVER_REL);
+       }
+      else
+       {
+         h->receiving = GNUNET_NO;
+       }
       return;
     case GNUNET_MESSAGE_TYPE_STATISTICS_VALUE:
       if (GNUNET_OK == process_message (h, msg))
         {
           /* finally, look for more! */
+#if DEBUG_STATISTICS
+         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                     "Processing VALUE done, now reading more\n");
+#endif      
           GNUNET_CLIENT_receive (h->client,
                                  &receive_stats,
                                  h,
                                  GNUNET_TIME_absolute_get_remaining
                                  (h->current->timeout));
+         h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
           return;
         }
       GNUNET_break (0);
       break;
+    case GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE:
+      if (GNUNET_OK ==
+         process_watch_value (h, 
+                              msg))
+       {
+         h->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
+         GNUNET_assert (h->watches_size > 0);
+         GNUNET_CLIENT_receive (h->client,
+                                &receive_stats,
+                                h,
+                                GNUNET_TIME_UNIT_FOREVER_REL);
+         return;
+       }
+      GNUNET_break (0);
+      break;
     default:
       GNUNET_break (0);
       break;
@@ -392,16 +585,70 @@
                                              2,
                                              handle->current->subsystem,
                                              handle->current->name));
-  GNUNET_CLIENT_receive (handle->client,
-                         &receive_stats,
-                         handle,
-                         GNUNET_TIME_absolute_get_remaining (handle->
-                                                             
current->timeout));
+  if (! handle->receiving)
+    {
+#if DEBUG_STATISTICS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Transmission of GET done, now reading response\n");
+#endif      
+      handle->receiving = GNUNET_YES;
+      GNUNET_CLIENT_receive (handle->client,
+                            &receive_stats,
+                            handle,
+                            GNUNET_TIME_absolute_get_remaining (handle->
+                                                                
current->timeout));
+    }
   return msize;
 }
 
 
+/**
+ * Transmit a WATCH request (and if successful, start to receive
+ * the response).
+ */
+static size_t
+transmit_watch (struct GNUNET_STATISTICS_Handle *handle, size_t size, void 
*buf)
+{
+  struct GNUNET_MessageHeader *hdr;
+  size_t slen1;
+  size_t slen2;
+  uint16_t msize;
 
+  if (buf == NULL)
+    {
+      /* timeout / error */
+#if DEBUG_STATISTICS
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Transmission of request for statistics failed!\n");
+#endif
+      finish (handle, GNUNET_SYSERR);
+      return 0;
+    }
+  slen1 = strlen (handle->current->subsystem) + 1;
+  slen2 = strlen (handle->current->name) + 1;
+  msize = slen1 + slen2 + sizeof (struct GNUNET_MessageHeader);
+  GNUNET_assert (msize <= size);
+  hdr = (struct GNUNET_MessageHeader *) buf;
+  hdr->size = htons (msize);
+  hdr->type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH);
+  GNUNET_assert (slen1 + slen2 ==
+                 GNUNET_STRINGS_buffer_fill ((char *) &hdr[1],
+                                             slen1 + slen2,
+                                             2,
+                                             handle->current->subsystem,
+                                             handle->current->name));
+  if (! handle->receiving)
+    {
+      handle->receiving = GNUNET_YES;
+      GNUNET_CLIENT_receive (handle->client,
+                            &receive_stats,
+                            handle,
+                            GNUNET_TIME_UNIT_FOREVER_REL);
+    }
+  return msize;
+}
+
+
 /**
  * Transmit a SET/UPDATE request.
  */
@@ -464,6 +711,9 @@
     case ACTION_UPDATE:
       ret = transmit_set (handle, size, buf);
       break;
+    case ACTION_WATCH:
+      ret = transmit_watch (handle, size, buf);
+      break;
     default:
       ret = 0;
       GNUNET_break (0);
@@ -495,6 +745,7 @@
   ret->sched = sched;
   ret->cfg = cfg;
   ret->subsystem = GNUNET_strdup (subsystem);
+  ret->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
   try_connect (ret);
   return ret;
 }
@@ -516,7 +767,11 @@
   struct GNUNET_STATISTICS_GetHandle *next;
   struct GNUNET_STATISTICS_GetHandle *prev;
   struct GNUNET_TIME_Relative timeout;
+  int i;
 
+  if (GNUNET_SCHEDULER_NO_TASK != h->backoff_task)
+    GNUNET_SCHEDULER_cancel (h->sched,
+                            h->backoff_task);
   if (sync_first)
     {
       if (h->current != NULL)
@@ -591,12 +846,31 @@
       GNUNET_CLIENT_disconnect (h->client, GNUNET_YES);
       h->client = NULL;
     }
+  for (i=0;i<h->watches_size;i++)
+    {
+      GNUNET_free (h->watches[i]->subsystem);
+      GNUNET_free (h->watches[i]->name);
+      GNUNET_free (h->watches[i]);
+    }
+  GNUNET_array_grow (h->watches,
+                    h->watches_size,
+                    0);
   GNUNET_free (h->subsystem);
   GNUNET_free (h);
 }
 
 
+static void
+finish_task (void *cls,
+            const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_STATISTICS_Handle *h = cls;
 
+  h->backoff_task = GNUNET_SCHEDULER_NO_TASK;
+  finish (h, GNUNET_SYSERR);
+}
+
+
 /**
  * Schedule the next action to be performed.
  */
@@ -609,7 +883,13 @@
     return;                     /* action already pending */
   if (GNUNET_YES != try_connect (h))
     {
-      finish (h, GNUNET_SYSERR);
+      h->backoff_task = GNUNET_SCHEDULER_add_delayed (h->sched,
+                                                     h->backoff,
+                                                     &finish_task,
+                                                     h);
+      h->backoff = GNUNET_TIME_relative_multiply (h->backoff, 2);
+      h->backoff = GNUNET_TIME_relative_min (h->backoff,
+                                            GNUNET_CONSTANTS_SERVICE_TIMEOUT);
       return;
     }
 
@@ -643,19 +923,6 @@
     }
 }
 
-
-static void
-insert_ai (struct GNUNET_STATISTICS_Handle *h, struct 
GNUNET_STATISTICS_GetHandle *ai)
-{
-  GNUNET_CONTAINER_DLL_insert_after (h->action_head,
-                                    h->action_tail,
-                                    h->action_tail,
-                                    ai);                                    
-  if (h->action_head == ai)
-    schedule_action (h);
-}
-
-
 /**
  * Get statistic from the peer.
  *
@@ -742,6 +1009,40 @@
 }
 
 
+/**
+ * Watch statistics from the peer (be notified whenever they change).
+ * Note that the only way to cancel a "watch" request is to destroy
+ * the statistics handle given as the first argument to this call.
+ *
+ * @param handle identification of the statistics service
+ * @param subsystem limit to the specified subsystem, never NULL
+ * @param name name of the statistic value, never NULL
+ * @param proc function to call on each value
+ * @param proc_cls closure for proc
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ */
+int
+GNUNET_STATISTICS_watch (struct GNUNET_STATISTICS_Handle *handle,
+                        const char *subsystem,
+                        const char *name,
+                        GNUNET_STATISTICS_Iterator proc, 
+                        void *proc_cls)
+{
+  struct GNUNET_STATISTICS_WatchEntry *w;
+
+  w = GNUNET_malloc (sizeof (struct GNUNET_STATISTICS_WatchEntry));
+  w->subsystem = GNUNET_strdup (subsystem);
+  w->name = GNUNET_strdup (name);
+  w->proc = proc;
+  w->proc_cls = proc_cls;
+  GNUNET_array_append (handle->watches,
+                      handle->watches_size,
+                      w);
+  schedule_watch_request (handle, w);
+  return GNUNET_OK;
+}
+
+
 static void
 add_setter_action (struct GNUNET_STATISTICS_Handle *h,
                    const char *name,
@@ -809,7 +1110,8 @@
                  ai->type = type;
                }
            }
-         ai->timeout = GNUNET_TIME_relative_to_absolute 
(SET_TRANSMIT_TIMEOUT);                  
+         ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT);
+         ai->make_persistent = make_persistent;
          return;
        }
       ai = ai->next;
@@ -824,7 +1126,6 @@
   ai->value = value;
   ai->type = type;
   insert_ai (h, ai);
-  schedule_action (h);
 }
 
 

Modified: gnunet/src/statistics/test_statistics_api.c
===================================================================
--- gnunet/src/statistics/test_statistics_api.c 2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/statistics/test_statistics_api.c 2010-07-07 06:27:10 UTC (rev 
12176)
@@ -29,7 +29,7 @@
 #include "gnunet_scheduler_lib.h"
 #include "gnunet_statistics_service.h"
 
-#define VERBOSE GNUNET_NO
+#define DEBUG_STATISTICS GNUNET_NO
 
 #define START_SERVICE GNUNET_YES
 
@@ -38,6 +38,11 @@
          const char *subsystem,
          const char *name, uint64_t value, int is_persistent)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Received value %llu for `%s:%s\n",
+             (unsigned long long) value,
+             subsystem,
+             name);
   GNUNET_assert (0 == strcmp (name, "test-1"));
   GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api"));
   GNUNET_assert (value == 1);
@@ -50,6 +55,11 @@
          const char *subsystem,
          const char *name, uint64_t value, int is_persistent)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Received value %llu for `%s:%s\n",
+             (unsigned long long) value,
+             subsystem,
+             name);
   GNUNET_assert (0 == strcmp (name, "test-2"));
   GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api"));
   GNUNET_assert (value == 2);
@@ -62,6 +72,11 @@
          const char *subsystem,
          const char *name, uint64_t value, int is_persistent)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Received value %llu for `%s:%s\n",
+             (unsigned long long) value,
+             subsystem,
+             name);
   GNUNET_assert (0 == strcmp (name, "test-3"));
   GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api"));
   GNUNET_assert (value == 3);
@@ -85,6 +100,8 @@
 next (void *cls, int success)
 {
   GNUNET_assert (success == GNUNET_OK);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Issuing GET request\n");       
   GNUNET_break (NULL !=
                GNUNET_STATISTICS_get (h, NULL, "test-2",
                                       GNUNET_TIME_UNIT_SECONDS, &next_fin, 
&check_2, cls));
@@ -102,6 +119,8 @@
   GNUNET_STATISTICS_set (h, "test-2", 2, GNUNET_NO);
   GNUNET_STATISTICS_set (h, "test-3", 2, GNUNET_NO);
   GNUNET_STATISTICS_update (h, "test-3", 1, GNUNET_YES);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Issuing GET request\n");       
   GNUNET_break (NULL != 
                GNUNET_STATISTICS_get (h, NULL, "test-1",
                                       GNUNET_TIME_UNIT_SECONDS, &next, 
&check_1, cls));
@@ -127,6 +146,11 @@
   char *const argv[] = { "test-statistics-api",
     "-c",
     "test_statistics_api_data.conf",
+#if DEBUG_STATISTICS
+                        "-L", "DEBUG",
+#else
+                        "-L", "WARNING",
+#endif
     NULL
   };
   struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -141,7 +165,7 @@
 #endif
                                  "-c", "test_statistics_api_data.conf", NULL);
 #endif
-  GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp",
+  GNUNET_PROGRAM_run (5, argv, "test-statistics-api", "nohelp",
                       options, &run, &ok);
 #if START_SERVICE
   if (0 != PLIBC_KILL (pid, SIGTERM))
@@ -163,7 +187,7 @@
 #endif
                                  "-c", "test_statistics_api_data.conf", NULL);
 #endif
-  GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp",
+  GNUNET_PROGRAM_run (5, argv, "test-statistics-api", "nohelp",
                       options, &run_more, &ok);
 #if START_SERVICE
   if (0 != PLIBC_KILL (pid, SIGTERM))
@@ -181,6 +205,13 @@
 {
   int ret;
 
+  GNUNET_log_setup ("test_statistics_api", 
+#if DEBUG_STATISTICS
+                   "DEBUG",
+#else
+                   "WARNING",
+#endif
+                   NULL);
   ret = check ();
 
   return ret;

Modified: gnunet/src/statistics/test_statistics_api_data.conf
===================================================================
--- gnunet/src/statistics/test_statistics_api_data.conf 2010-07-06 16:25:08 UTC 
(rev 12175)
+++ gnunet/src/statistics/test_statistics_api_data.conf 2010-07-07 06:27:10 UTC 
(rev 12176)
@@ -4,9 +4,12 @@
 
 [statistics]
 PORT = 22353
+UNIXPATH = /tmp/test-statistics-service-statistics.unix
+DEBUG = YES
 
 [arm]
 PORT = 22354
 DEFAULTSERVICES = 
+UNIXPATH = /tmp/test-statistics-service-arm.unix
 # DEBUG = YES
 

Modified: gnunet/src/testing/test_testing_topology.c
===================================================================
--- gnunet/src/testing/test_testing_topology.c  2010-07-06 16:25:08 UTC (rev 
12175)
+++ gnunet/src/testing/test_testing_topology.c  2010-07-07 06:27:10 UTC (rev 
12176)
@@ -443,14 +443,14 @@
    * Connect to the receiving peer
    */
   pos->peer2handle = GNUNET_CORE_connect (sched,
-                       pos->peer2->cfg,
-                       TIMEOUT,
-                       pos,
-                       &init_notify_peer2,
-                       NULL,
-                       NULL,
-                       NULL,
-                       GNUNET_YES, NULL, GNUNET_YES, handlers);
+                                         pos->peer2->cfg,
+                                         TIMEOUT,
+                                         pos,
+                                         &init_notify_peer2,
+                                         NULL,
+                                         NULL, 
+                                         NULL, NULL,
+                                         GNUNET_YES, NULL, GNUNET_YES, 
handlers);
 
 }
 
@@ -485,9 +485,9 @@
                                           TIMEOUT,
                                           pos,
                                           &init_notify_peer1,
+                                          NULL, NULL,
                                           NULL,
                                           NULL,
-                                          NULL,
                                           GNUNET_NO, NULL, GNUNET_NO, 
no_handlers);
 
   GNUNET_assert(pos->peer1handle != NULL);

Modified: gnunet/src/testing/testing.c
===================================================================
--- gnunet/src/testing/testing.c        2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/testing/testing.c        2010-07-07 06:27:10 UTC (rev 12176)
@@ -513,7 +513,7 @@
                                        ARM_START_WAIT,
                                        d,
                                        &testing_init,
-                                       NULL, NULL,
+                                       NULL, NULL, NULL,
                                        NULL, GNUNET_NO,
                                        NULL, GNUNET_NO, no_handlers);
       break;
@@ -1380,7 +1380,7 @@
                                      timeout,
                                      ctx,
                                      NULL,
-                                     &connect_notify, NULL,
+                                     &connect_notify, NULL, NULL,
                                      NULL, GNUNET_NO,
                                      NULL, GNUNET_NO, no_handlers);
   if (ctx->d1core == NULL)
@@ -1442,7 +1442,7 @@
                                      
GNUNET_TIME_absolute_get_remaining(ctx->timeout),
                                      ctx,
                                      NULL,
-                                     &connect_notify, NULL,
+                                     &connect_notify, NULL, NULL,
                                      NULL, GNUNET_NO,
                                      NULL, GNUNET_NO, no_handlers);
   if (ctx->d1core == NULL)

Modified: gnunet/src/topology/gnunet-daemon-topology.c
===================================================================
--- gnunet/src/topology/gnunet-daemon-topology.c        2010-07-06 16:25:08 UTC 
(rev 12175)
+++ gnunet/src/topology/gnunet-daemon-topology.c        2010-07-07 06:27:10 UTC 
(rev 12176)
@@ -934,13 +934,11 @@
  * @param cls closure (not used)
  * @param peer potential peer to connect to
  * @param hello HELLO for this peer (or NULL)
- * @param trust how much we trust the peer (not used)
  */
 static void
 process_peer (void *cls,
              const struct GNUNET_PeerIdentity *peer,
-             const struct GNUNET_HELLO_Message *hello,
-             uint32_t trust)
+             const struct GNUNET_HELLO_Message *hello)
 {
   struct Peer *pos;
 
@@ -1404,7 +1402,8 @@
                                NULL,
                                &core_init,
                                &connect_notify,
-                               &disconnect_notify,
+                               &disconnect_notify, 
+                               NULL,
                                NULL, GNUNET_NO,
                                NULL, GNUNET_NO,
                                handlers);

Modified: gnunet/src/transport/gnunet-service-transport.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport.c     2010-07-06 16:25:08 UTC 
(rev 12175)
+++ gnunet/src/transport/gnunet-service-transport.c     2010-07-07 06:27:10 UTC 
(rev 12176)
@@ -2612,13 +2612,11 @@
  * @param cls closure ('struct NeighbourList*')
  * @param peer id of the peer, NULL for last call
  * @param h hello message for the peer (can be NULL)
- * @param trust amount of trust we have in the peer (not used)
  */
 static void
 add_hello_for_peer (void *cls,
                    const struct GNUNET_PeerIdentity *peer,
-                   const struct GNUNET_HELLO_Message *h, 
-                   uint32_t trust)
+                   const struct GNUNET_HELLO_Message *h)
 {
   struct NeighbourList *n = cls;
 
@@ -2706,7 +2704,7 @@
   if (do_hello)
     {
       n->piter = GNUNET_PEERINFO_iterate (peerinfo, peer,
-                                         0, GNUNET_TIME_UNIT_FOREVER_REL,
+                                         GNUNET_TIME_UNIT_FOREVER_REL,
                                          &add_hello_for_peer, n);
       transmit_to_peer (NULL, NULL, 0,
                        HELLO_ADDRESS_EXPIRATION,
@@ -3870,13 +3868,11 @@
  * @param cls closure
  * @param peer id of the peer, NULL for last call
  * @param h hello message for the peer (can be NULL)
- * @param trust amount of trust we have in the peer (not used)
  */
 static void
 check_hello_validated (void *cls,
                        const struct GNUNET_PeerIdentity *peer,
-                       const struct GNUNET_HELLO_Message *h, 
-                      uint32_t trust)
+                       const struct GNUNET_HELLO_Message *h)
 {
   struct CheckHelloValidatedContext *chvc = cls;
   struct GNUNET_HELLO_Message *plain_hello;
@@ -4088,7 +4084,6 @@
      (continuation will then schedule actual validation) */
   chvc->piter = GNUNET_PEERINFO_iterate (peerinfo,
                                          &target,
-                                         0,
                                          HELLO_VERIFICATION_TIMEOUT,
                                          &check_hello_validated, chvc);
   return GNUNET_OK;

Modified: gnunet/src/util/server_nc.c
===================================================================
--- gnunet/src/util/server_nc.c 2010-07-06 16:25:08 UTC (rev 12175)
+++ gnunet/src/util/server_nc.c 2010-07-07 06:27:10 UTC (rev 12176)
@@ -164,6 +164,11 @@
     }
   if (pos == NULL)
     return;
+#if DEBUG_SERVER_NC
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Client disconnected, cleaning up %u messages in NC queue\n",
+             pos->num_pending);
+#endif
   if (prev == NULL)
     nc->clients = pos->next;
   else
@@ -285,6 +290,10 @@
   if (buf == NULL)
     {
       /* 'cl' should be freed via disconnect notification shortly */
+#if DEBUG_SERVER_NC
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Failed to transmit message from NC queue to client\n");
+#endif
       return 0;
     }
   ret = 0;
@@ -310,11 +319,18 @@
       cl->num_pending--;
     }
   if (cl->pending_head != NULL)    
-    cl->th = GNUNET_SERVER_notify_transmit_ready (cl->client,
-                                                 ntohs 
(cl->pending_head->msg->size),
-                                                 GNUNET_TIME_UNIT_FOREVER_REL,
-                                                 &transmit_message,
-                                                 cl);
+    {
+#if DEBUG_SERVER_NC
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Have %u messages left in NC queue, will try transmission 
again\n",
+                 cl->num_pending);
+#endif
+      cl->th = GNUNET_SERVER_notify_transmit_ready (cl->client,
+                                                   ntohs 
(cl->pending_head->msg->size),
+                                                   
GNUNET_TIME_UNIT_FOREVER_REL,
+                                                   &transmit_message,
+                                                   cl);
+    }
   return ret;
 }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]