-only trigger check config if we actually need it
[oweals/gnunet.git] / src / fs / gnunet-service-fs_cp.c
index d866a003afb1c60230894c90096606a0ce69f17f..ceb74a2714437436f5825104dfaf783c42faaa04 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2011 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2011 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 /**
  * @file fs/gnunet-service-fs_cp.c
@@ -171,12 +171,12 @@ struct PeerRequest
 {
 
   /**
-   * Handle to generic request.
+   * Handle to generic request (generic: from peer or local client).
    */
   struct GSF_PendingRequest *pr;
 
   /**
-   * Handle to specific peer.
+   * Which specific peer issued this request?
    */
   struct GSF_ConnectedPeer *cp;
 
@@ -250,7 +250,7 @@ struct GSF_ConnectedPeer
   struct GNUNET_SCHEDULER_Task *rc_delay_task;
 
   /**
-   * Active requests from this neighbour, map of query to 'struct PeerRequest'.
+   * Active requests from this neighbour, map of query to `struct PeerRequest`.
    */
   struct GNUNET_CONTAINER_MultiHashMap *request_map;
 
@@ -335,6 +335,11 @@ static struct GNUNET_CONTAINER_MultiPeerMap *cp_map;
  */
 static struct GNUNET_PEERSTORE_Handle *peerstore;
 
+/**
+ * Task used to flush respect values to disk.
+ */
+static struct GNUNET_SCHEDULER_Task *fr_task;
+
 
 /**
  * Update the latency information kept for the given peer.
@@ -522,11 +527,9 @@ peer_transmit_ready_cb (void *cls,
  * (re)try to reserve bandwidth from the given peer.
  *
  * @param cls the `struct GSF_ConnectedPeer` to reserve from
- * @param tc scheduler context
  */
 static void
-retry_reservation (void *cls,
-                   const struct GNUNET_SCHEDULER_TaskContext *tc)
+retry_reservation (void *cls)
 {
   struct GSF_ConnectedPeer *cp = cls;
   struct GNUNET_PeerIdentity target;
@@ -602,22 +605,23 @@ ats_reserve_callback (void *cls,
  * @param cls handle to connected peer entry
  * @param record peerstore record information
  * @param emsg error message, or NULL if no errors
- * @return #GNUNET_NO to stop iterating since we only expect 0 or 1 records
  */
-static int
+static void
 peer_respect_cb (void *cls,
                  const struct GNUNET_PEERSTORE_Record *record,
                  const char *emsg)
 {
   struct GSF_ConnectedPeer *cp = cls;
 
-  cp->respect_iterate_req = NULL;
+  GNUNET_assert (NULL != cp->respect_iterate_req);
   if ((NULL != record) && (sizeof (cp->disk_respect) == record->value_size))
     cp->disk_respect = cp->ppd.respect = *((uint32_t *)record->value);
   GSF_push_start_ (cp);
   if (NULL != cp->creation_cb)
     cp->creation_cb (cp->creation_cb_cls, cp);
-  return GNUNET_NO;
+  if (NULL != record)
+    GNUNET_PEERSTORE_iterate_cancel (cp->respect_iterate_req);
+  cp->respect_iterate_req = NULL;
 }
 
 
@@ -643,22 +647,28 @@ GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer,
   cp->ppd.pid = GNUNET_PEER_intern (peer);
   cp->ppd.transmission_delay = GNUNET_LOAD_value_init (GNUNET_TIME_UNIT_ZERO);
   cp->rc =
-      GNUNET_ATS_reserve_bandwidth (GSF_ats, peer, DBLOCK_SIZE,
+      GNUNET_ATS_reserve_bandwidth (GSF_ats,
+                                    peer,
+                                    DBLOCK_SIZE,
                                     &ats_reserve_callback, cp);
-  cp->request_map = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO);
+  cp->request_map = GNUNET_CONTAINER_multihashmap_create (128,
+                                                          GNUNET_YES);
   GNUNET_break (GNUNET_OK ==
                 GNUNET_CONTAINER_multipeermap_put (cp_map,
                GSF_connected_peer_get_identity2_ (cp),
                                                    cp,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# peers connected"),
+  GNUNET_STATISTICS_set (GSF_stats,
+                         gettext_noop ("# peers connected"),
                          GNUNET_CONTAINER_multipeermap_size (cp_map),
                          GNUNET_NO);
   cp->creation_cb = creation_cb;
   cp->creation_cb_cls = creation_cb_cls;
   cp->respect_iterate_req =
-      GNUNET_PEERSTORE_iterate (peerstore, "fs", peer, "respect",
-                                GNUNET_TIME_UNIT_FOREVER_REL, &peer_respect_cb,
+      GNUNET_PEERSTORE_iterate (peerstore, "fs",
+                                peer, "respect",
+                                GNUNET_TIME_UNIT_FOREVER_REL,
+                                &peer_respect_cb,
                                 cp);
 }
 
@@ -668,11 +678,9 @@ GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer,
  * peer.  Check, and if so, restart migration.
  *
  * @param cls the `struct GSF_ConnectedPeer`
- * @param tc scheduler context
  */
 static void
-revive_migration (void *cls,
-                  const struct GNUNET_SCHEDULER_TaskContext *tc)
+revive_migration (void *cls)
 {
   struct GSF_ConnectedPeer *cp = cls;
   struct GNUNET_TIME_Relative bt;
@@ -740,7 +748,8 @@ GSF_handle_p2p_migration_stop_ (void *cls,
               GNUNET_i2s (other),
              GNUNET_STRINGS_relative_time_to_string (bt, GNUNET_YES));
   cp->ppd.migration_blocked_until = GNUNET_TIME_relative_to_absolute (bt);
-  if (NULL == cp->mig_revive_task)
+  if ( (NULL == cp->mig_revive_task) &&
+       (NULL == cp->respect_iterate_req) )
   {
     GSF_push_stop_ (cp);
     cp->mig_revive_task =
@@ -794,24 +803,27 @@ copy_reply (void *cls,
  * Free resources associated with the given peer request.
  *
  * @param peerreq request to free
- * @param query associated key for the request
  */
 static void
-free_pending_request (struct PeerRequest *peerreq,
-                     const struct GNUNET_HashCode *query)
+free_pending_request (struct PeerRequest *peerreq)
 {
   struct GSF_ConnectedPeer *cp = peerreq->cp;
+  struct GSF_PendingRequestData *prd;
 
+  prd = GSF_pending_request_get_data_ (peerreq->pr);
   if (NULL != peerreq->kill_task)
   {
     GNUNET_SCHEDULER_cancel (peerreq->kill_task);
     peerreq->kill_task = NULL;
   }
-  GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# P2P searches active"),
-                            -1, GNUNET_NO);
+  GNUNET_STATISTICS_update (GSF_stats,
+                            gettext_noop ("# P2P searches active"),
+                            -1,
+                            GNUNET_NO);
   GNUNET_break (GNUNET_YES ==
                 GNUNET_CONTAINER_multihashmap_remove (cp->request_map,
-                                                      query, peerreq));
+                                                      &prd->query,
+                                                      peerreq));
   GNUNET_free (peerreq);
 }
 
@@ -831,11 +843,10 @@ cancel_pending_request (void *cls,
 {
   struct PeerRequest *peerreq = value;
   struct GSF_PendingRequest *pr = peerreq->pr;
-  struct GSF_PendingRequestData *prd;
 
-  prd = GSF_pending_request_get_data_ (pr);
-  GSF_pending_request_cancel_ (pr, GNUNET_NO);
-  free_pending_request (peerreq, &prd->query);
+  free_pending_request (peerreq);
+  GSF_pending_request_cancel_ (pr,
+                               GNUNET_NO);
   return GNUNET_OK;
 }
 
@@ -844,11 +855,9 @@ cancel_pending_request (void *cls,
  * Free the given request.
  *
  * @param cls the request to free
- * @param tc task context
  */
 static void
-peer_request_destroy (void *cls,
-                      const struct GNUNET_SCHEDULER_TaskContext *tc)
+peer_request_destroy (void *cls)
 {
   struct PeerRequest *peerreq = cls;
   struct GSF_PendingRequest *pr = peerreq->pr;
@@ -856,7 +865,9 @@ peer_request_destroy (void *cls,
 
   peerreq->kill_task = NULL;
   prd = GSF_pending_request_get_data_ (pr);
-  cancel_pending_request (NULL, &prd->query, peerreq);
+  cancel_pending_request (NULL,
+                          &prd->query,
+                          peerreq);
 }
 
 
@@ -864,11 +875,9 @@ peer_request_destroy (void *cls,
  * The artificial delay is over, transmit the message now.
  *
  * @param cls the `struct GSF_DelayedHandle` with the message
- * @param tc scheduler context
  */
 static void
-transmit_delayed_now (void *cls,
-                      const struct GNUNET_SCHEDULER_TaskContext *tc)
+transmit_delayed_now (void *cls)
 {
   struct GSF_DelayedHandle *dh = cls;
   struct GSF_ConnectedPeer *cp = dh->cp;
@@ -877,12 +886,6 @@ transmit_delayed_now (void *cls,
                                cp->delayed_tail,
                                dh);
   cp->delay_queue_size--;
-  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-  {
-    GNUNET_free (dh->pm);
-    GNUNET_free (dh);
-    return;
-  }
   (void) GSF_peer_transmit_ (cp,
                              GNUNET_NO,
                              UINT32_MAX,
@@ -960,7 +963,7 @@ handle_p2p_reply (void *cls,
   prd = GSF_pending_request_get_data_ (pr);
   if (NULL == data)
   {
-    free_pending_request (peerreq, &prd->query);
+    free_pending_request (peerreq);
     return;
   }
   GNUNET_break (GNUNET_BLOCK_TYPE_ANY != type);
@@ -1039,9 +1042,11 @@ handle_p2p_reply (void *cls,
     GNUNET_STATISTICS_update (GSF_stats,
                               gettext_noop
                               ("# P2P searches destroyed due to ultimate reply"),
-                              1, GNUNET_NO);
+                              1,
+                              GNUNET_NO);
     peerreq->kill_task =
-        GNUNET_SCHEDULER_add_now (&peer_request_destroy, peerreq);
+        GNUNET_SCHEDULER_add_now (&peer_request_destroy,
+                                  peerreq);
   }
 }
 
@@ -1093,7 +1098,8 @@ change_peer_respect (struct GSF_ConnectedPeer *cp, int value)
  * @return effective priority
  */
 static int32_t
-bound_priority (uint32_t prio_in, struct GSF_ConnectedPeer *cp)
+bound_priority (uint32_t prio_in,
+                struct GSF_ConnectedPeer *cp)
 {
 #define N ((double)128.0)
   uint32_t ret;
@@ -1155,11 +1161,12 @@ bound_priority (uint32_t prio_in, struct GSF_ConnectedPeer *cp)
  *
  * @param ttl_in requested ttl
  * @param prio given priority
- * @return ttl_in if ttl_in is below the limit,
- *         otherwise the ttl-limit for the given priority
+ * @return @a ttl_in if @a ttl_in is below the limit,
+ *         otherwise the ttl-limit for the given @a prio
  */
 static int32_t
-bound_ttl (int32_t ttl_in, uint32_t prio)
+bound_ttl (int32_t ttl_in,
+           uint32_t prio)
 {
   unsigned long long allowed;
 
@@ -1176,6 +1183,82 @@ bound_ttl (int32_t ttl_in, uint32_t prio)
 }
 
 
+/**
+ * Closure for #test_exist_cb().
+ */
+struct TestExistClosure
+{
+
+  /**
+   * Priority of the incoming request.
+   */
+  int32_t priority;
+
+  /**
+   * Relative TTL of the incoming request.
+   */
+  int32_t ttl;
+
+  /**
+   * Type of the incoming request.
+   */
+  enum GNUNET_BLOCK_Type type;
+
+  /**
+   * Set to #GNUNET_YES if we are done handling the query.
+   */
+  int finished;
+
+};
+
+
+/**
+ * Test if the query already exists.  If so, merge it, otherwise
+ * keep `finished` at #GNUNET_NO.
+ *
+ * @param cls our `struct TestExistClosure`
+ * @param hc the key of the query
+ * @param value the existing `struct PeerRequest`.
+ * @return #GNUNET_YES to continue to iterate,
+ *         #GNUNET_NO if we successfully merged
+ */
+static int
+test_exist_cb (void *cls,
+               const struct GNUNET_HashCode *hc,
+               void *value)
+{
+  struct TestExistClosure *tec = cls;
+  struct PeerRequest *peerreq = value;
+  struct GSF_PendingRequest *pr;
+  struct GSF_PendingRequestData *prd;
+
+  pr = peerreq->pr;
+  prd = GSF_pending_request_get_data_ (pr);
+  if (prd->type != tec->type)
+    return GNUNET_YES;
+  if (prd->ttl.abs_value_us >=
+      GNUNET_TIME_absolute_get ().abs_value_us + tec->ttl * 1000LL)
+  {
+    /* existing request has higher TTL, drop new one! */
+    prd->priority += tec->priority;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Have existing request with higher TTL, dropping new request.\n");
+    GNUNET_STATISTICS_update (GSF_stats,
+                              gettext_noop
+                              ("# requests dropped due to higher-TTL request"),
+                              1, GNUNET_NO);
+    tec->finished = GNUNET_YES;
+    return GNUNET_NO;
+  }
+  /* existing request has lower TTL, drop old one! */
+  tec->priority += prd->priority;
+  free_pending_request (peerreq);
+  GSF_pending_request_cancel_ (pr,
+                               GNUNET_YES);
+  return GNUNET_NO;
+}
+
+
 /**
  * Handle P2P "QUERY" message.  Creates the pending request entry
  * and sets up all of the data structures to that we will
@@ -1193,7 +1276,6 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
 {
   struct PeerRequest *peerreq;
   struct GSF_PendingRequest *pr;
-  struct GSF_PendingRequestData *prd;
   struct GSF_ConnectedPeer *cp;
   struct GSF_ConnectedPeer *cps;
   const struct GNUNET_PeerIdentity *target;
@@ -1205,10 +1287,9 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
   uint32_t bm;
   size_t bfsize;
   uint32_t ttl_decrement;
-  int32_t priority;
-  int32_t ttl;
-  enum GNUNET_BLOCK_Type type;
+  struct TestExistClosure tec;
   GNUNET_PEER_Id spid;
+  const struct GSF_PendingRequestData *prd;
 
   msize = ntohs (message->size);
   if (msize < sizeof (struct GetMessage))
@@ -1222,7 +1303,7 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
                             1,
                             GNUNET_NO);
   gm = (const struct GetMessage *) message;
-  type = ntohl (gm->type);
+  tec.type = ntohl (gm->type);
   bm = ntohl (gm->hash_bitmap);
   bits = 0;
   while (bm > 0)
@@ -1293,9 +1374,9 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
   /* note that we can really only check load here since otherwise
    * peers could find out that we are overloaded by not being
    * disconnected after sending us a malformed query... */
-  priority = bound_priority (ntohl (gm->priority),
-                             cps);
-  if (priority < 0)
+  tec.priority = bound_priority (ntohl (gm->priority),
+                                 cps);
+  if (tec.priority < 0)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Dropping query from `%s', this peer is too busy.\n",
@@ -1305,7 +1386,7 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Received request for `%s' of type %u from peer `%s' with flags %u\n",
               GNUNET_h2s (&gm->query),
-              (unsigned int) type,
+              (unsigned int) tec.type,
               GNUNET_i2s (other),
               (unsigned int) bm);
   target =
@@ -1313,28 +1394,31 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
        (bm & GET_MESSAGE_BIT_TRANSMIT_TO)) ? (&opt[bits++]) : NULL;
   options = GSF_PRO_DEFAULTS;
   spid = 0;
-  if ((GNUNET_LOAD_get_load (cp->ppd.transmission_delay) > 3 * (1 + priority))
+  if ((GNUNET_LOAD_get_load (cp->ppd.transmission_delay) > 3 * (1 + tec.priority))
       || (GNUNET_LOAD_get_average (cp->ppd.transmission_delay) >
           GNUNET_CONSTANTS_MAX_CORK_DELAY.rel_value_us * 2 +
           GNUNET_LOAD_get_average (GSF_rt_entry_lifetime)))
   {
     /* don't have BW to send to peer, or would likely take longer than we have for it,
      * so at best indirect the query */
-    priority = 0;
+    tec.priority = 0;
     options |= GSF_PRO_FORWARD_ONLY;
     spid = GNUNET_PEER_intern (other);
     GNUNET_assert (0 != spid);
   }
-  ttl = bound_ttl (ntohl (gm->ttl), priority);
+  tec.ttl = bound_ttl (ntohl (gm->ttl),
+                       tec.priority);
   /* decrement ttl (always) */
   ttl_decrement =
       2 * TTL_DECREMENT + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
                                                     TTL_DECREMENT);
-  if ((ttl < 0) && (((int32_t) (ttl - ttl_decrement)) > 0))
+  if ((tec.ttl < 0) && (((int32_t) (tec.ttl - ttl_decrement)) > 0))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Dropping query from `%s' due to TTL underflow (%d - %u).\n",
-                GNUNET_i2s (other), ttl, ttl_decrement);
+                GNUNET_i2s (other),
+                tec.ttl,
+                ttl_decrement);
     GNUNET_STATISTICS_update (GSF_stats,
                               gettext_noop
                               ("# requests dropped due TTL underflow"), 1,
@@ -1342,41 +1426,21 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
     /* integer underflow => drop (should be very rare)! */
     return NULL;
   }
-  ttl -= ttl_decrement;
+  tec.ttl -= ttl_decrement;
 
   /* test if the request already exists */
-  peerreq = GNUNET_CONTAINER_multihashmap_get (cp->request_map,
-                                               &gm->query);
-  if (NULL != peerreq)
-  {
-    pr = peerreq->pr;
-    prd = GSF_pending_request_get_data_ (pr);
-    if (prd->type == type)
-    {
-      if (prd->ttl.abs_value_us >= GNUNET_TIME_absolute_get ().abs_value_us + ttl * 1000LL)
-      {
-        /* existing request has higher TTL, drop new one! */
-        prd->priority += priority;
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Have existing request with higher TTL, dropping new request.\n",
-                    GNUNET_i2s (other));
-        GNUNET_STATISTICS_update (GSF_stats,
-                                  gettext_noop
-                                  ("# requests dropped due to higher-TTL request"),
-                                  1, GNUNET_NO);
-        return NULL;
-      }
-      /* existing request has lower TTL, drop old one! */
-      priority += prd->priority;
-      GSF_pending_request_cancel_ (pr, GNUNET_YES);
-      free_pending_request (peerreq, &gm->query);
-    }
-  }
+  tec.finished = GNUNET_NO;
+  GNUNET_CONTAINER_multihashmap_get_multiple (cp->request_map,
+                                              &gm->query,
+                                              &test_exist_cb,
+                                              &tec);
+  if (GNUNET_YES == tec.finished)
+    return NULL; /* merged into existing request, we're done */
 
   peerreq = GNUNET_new (struct PeerRequest);
   peerreq->cp = cp;
   pr = GSF_pending_request_create_ (options,
-                                    type,
+                                    tec.type,
                                     &gm->query,
                                     target,
                                     (bfsize > 0)
@@ -1385,24 +1449,29 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
                                     bfsize,
                                     ntohl (gm->filter_mutator),
                                     1 /* anonymity */,
-                                    (uint32_t) priority,
-                                    ttl,
+                                    (uint32_t) tec.priority,
+                                    tec.ttl,
                                     spid,
                                     GNUNET_PEER_intern (other),
                                     NULL, 0,        /* replies_seen */
-                                    &handle_p2p_reply, peerreq);
+                                    &handle_p2p_reply,
+                                    peerreq);
   GNUNET_assert (NULL != pr);
+  prd = GSF_pending_request_get_data_ (pr);
   peerreq->pr = pr;
   GNUNET_break (GNUNET_OK ==
-                GNUNET_CONTAINER_multihashmap_put (cp->request_map, &gm->query,
+                GNUNET_CONTAINER_multihashmap_put (cp->request_map,
+                                                   &prd->query,
                                                    peerreq,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
   GNUNET_STATISTICS_update (GSF_stats,
-                            gettext_noop
-                            ("# P2P query messages received and processed"), 1,
+                            gettext_noop ("# P2P query messages received and processed"),
+                            1,
+                            GNUNET_NO);
+  GNUNET_STATISTICS_update (GSF_stats,
+                            gettext_noop ("# P2P searches active"),
+                            1,
                             GNUNET_NO);
-  GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# P2P searches active"),
-                            1, GNUNET_NO);
   return pr;
 }
 
@@ -1412,11 +1481,9 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
  * a transmission request.
  *
  * @param cls the `struct GSF_PeerTransmitHandle` of the request
- * @param tc scheduler context
  */
 static void
-peer_transmit_timeout (void *cls,
-                       const struct GNUNET_SCHEDULER_TaskContext *tc)
+peer_transmit_timeout (void *cls)
 {
   struct GSF_PeerTransmitHandle *pth = cls;
   struct GSF_ConnectedPeer *cp;
@@ -1432,7 +1499,8 @@ peer_transmit_timeout (void *cls,
     GNUNET_assert (0 < cp->ppd.pending_queries--);
   else if (GNUNET_NO == pth->is_query)
     GNUNET_assert (0 < cp->ppd.pending_replies--);
-  GNUNET_LOAD_update (cp->ppd.transmission_delay, UINT64_MAX);
+  GNUNET_LOAD_update (cp->ppd.transmission_delay,
+                      UINT64_MAX);
   if (NULL != cp->cth)
   {
     GNUNET_CORE_notify_transmit_ready_cancel (cp->cth);
@@ -1668,13 +1736,17 @@ GSF_peer_disconnect_handler_ (void *cls,
     cp->rc_delay_task = NULL;
   }
   GNUNET_CONTAINER_multihashmap_iterate (cp->request_map,
-                                         &cancel_pending_request, cp);
+                                         &cancel_pending_request,
+                                         cp);
   GNUNET_CONTAINER_multihashmap_destroy (cp->request_map);
   cp->request_map = NULL;
   GSF_plan_notify_peer_disconnect_ (cp);
   GNUNET_LOAD_value_free (cp->ppd.transmission_delay);
-  GNUNET_PEER_decrement_rcs (cp->ppd.last_p2p_replies, P2P_SUCCESS_LIST_SIZE);
-  memset (cp->ppd.last_p2p_replies, 0, sizeof (cp->ppd.last_p2p_replies));
+  GNUNET_PEER_decrement_rcs (cp->ppd.last_p2p_replies,
+                             P2P_SUCCESS_LIST_SIZE);
+  memset (cp->ppd.last_p2p_replies,
+          0,
+          sizeof (cp->ppd.last_p2p_replies));
   GSF_push_stop_ (cp);
   if (NULL != cp->cth)
   {
@@ -1898,23 +1970,17 @@ GSF_connected_peer_change_preference_ (struct GSF_ConnectedPeer *cp,
  * Call this method periodically to flush respect information to disk.
  *
  * @param cls closure, not used
- * @param tc task context, not used
  */
 static void
-cron_flush_respect (void *cls,
-                    const struct GNUNET_SCHEDULER_TaskContext *tc)
+cron_flush_respect (void *cls)
 {
-  if (NULL == cp_map)
-    return;
+  fr_task = NULL;
   GNUNET_CONTAINER_multipeermap_iterate (cp_map,
-                                         &flush_respect, NULL);
-  if (NULL == tc)
-    return;
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  GNUNET_SCHEDULER_add_delayed_with_priority (RESPECT_FLUSH_FREQ,
-                                             GNUNET_SCHEDULER_PRIORITY_HIGH,
-                                             &cron_flush_respect, NULL);
+                                         &flush_respect,
+                                        NULL);
+  fr_task = GNUNET_SCHEDULER_add_delayed_with_priority (RESPECT_FLUSH_FREQ,
+                                                       GNUNET_SCHEDULER_PRIORITY_HIGH,
+                                                       &cron_flush_respect, NULL);
 }
 
 
@@ -1926,8 +1992,8 @@ GSF_connected_peer_init_ ()
 {
   cp_map = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
   peerstore = GNUNET_PEERSTORE_connect (GSF_cfg);
-  GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_HIGH,
-                                      &cron_flush_respect, NULL);
+  fr_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_HIGH,
+                                               &cron_flush_respect, NULL);
 }
 
 
@@ -1955,12 +2021,19 @@ clean_peer (void *cls,
 void
 GSF_connected_peer_done_ ()
 {
-  cron_flush_respect (NULL, NULL);
   GNUNET_CONTAINER_multipeermap_iterate (cp_map,
-                                         &clean_peer, NULL);
+                                         &flush_respect,
+                                         NULL);
+  GNUNET_CONTAINER_multipeermap_iterate (cp_map,
+                                         &clean_peer,
+                                        NULL);
+  GNUNET_SCHEDULER_cancel (fr_task);
+  fr_task = NULL;
   GNUNET_CONTAINER_multipeermap_destroy (cp_map);
   cp_map = NULL;
-  GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_YES);
+  GNUNET_PEERSTORE_disconnect (peerstore,
+                              GNUNET_YES);
+  
 }