trying to fix #3576
[oweals/gnunet.git] / src / fs / gnunet-service-fs_cp.c
index 593250e2c5b6d3c6bb4fd5ecf41f8e2ebb9b1e45..bca07db328459d798ccb46dc46ca10995ef7141f 100644 (file)
@@ -31,6 +31,7 @@
 #include "gnunet-service-fs_pe.h"
 #include "gnunet-service-fs_pr.h"
 #include "gnunet-service-fs_push.h"
+#include "gnunet_peerstore_service.h"
 
 
 /**
@@ -98,7 +99,7 @@ struct GSF_PeerTransmitHandle
   struct GSF_ConnectedPeer *cp;
 
   /**
-   * Closure for 'gmc'.
+   * Closure for @e gmc.
    */
   void *gmc_cls;
 
@@ -108,7 +109,7 @@ struct GSF_PeerTransmitHandle
   size_t size;
 
   /**
-   * GNUNET_YES if this is a query, GNUNET_NO for content.
+   * #GNUNET_YES if this is a query, #GNUNET_NO for content.
    */
   int is_query;
 
@@ -268,7 +269,7 @@ struct GSF_ConnectedPeer
 
   /**
    * Set to 1 if we're currently in the process of calling
-   * 'GNUNET_CORE_notify_transmit_ready' (so while cth is
+   * #GNUNET_CORE_notify_transmit_ready() (so while @e cth is
    * NULL, we should not call notify_transmit_ready for this
    * handle right now).
    */
@@ -302,6 +303,21 @@ struct GSF_ConnectedPeer
    */
   int did_reserve;
 
+  /**
+   * Function called when the creation of this record is complete.
+   */
+  GSF_ConnectedPeerCreationCallback creation_cb;
+
+  /**
+   * Closure for @e creation_cb
+   */
+  void *creation_cb_cls;
+
+  /**
+   * Handle to the PEERSTORE iterate request for peer respect value
+   */
+  struct GNUNET_PEERSTORE_IterateContext *respect_iterate_req;
+
 };
 
 
@@ -311,30 +327,9 @@ struct GSF_ConnectedPeer
 static struct GNUNET_CONTAINER_MultiPeerMap *cp_map;
 
 /**
- * Where do we store respect information?
+ * Handle to peerstore service.
  */
-static char *respectDirectory;
-
-
-/**
- * Get the filename under which we would store respect
- * for the given peer.
- *
- * @param id peer to get the filename for
- * @return filename of the form DIRECTORY/PEERID
- */
-static char *
-get_respect_filename (const struct GNUNET_PeerIdentity *id)
-{
-  char *fn;
-
-  GNUNET_asprintf (&fn,
-                  "%s%s%s",
-                  respectDirectory,
-                  DIR_SEPARATOR_STR,
-                  GNUNET_i2s_full (id));
-  return fn;
-}
+static struct GNUNET_PEERSTORE_Handle *peerstore;
 
 
 /**
@@ -439,7 +434,8 @@ schedule_transmission (struct GSF_PeerTransmitHandle *pth)
   GNUNET_assert (NULL == cp->cth);
   cp->cth_in_progress++;
   cp->cth =
-    GNUNET_CORE_notify_transmit_ready (GSF_core, GNUNET_YES, pth->priority,
+    GNUNET_CORE_notify_transmit_ready (GSF_core, GNUNET_YES,
+                                       GNUNET_CORE_PRIO_BACKGROUND,
                                       GNUNET_TIME_absolute_get_remaining
                                       (pth->timeout), &target, pth->size,
                                       &peer_transmit_ready_cb, cp);
@@ -558,7 +554,8 @@ ats_reserve_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
     /* reservation success, try transmission now! */
     cp->cth_in_progress++;
     cp->cth =
-        GNUNET_CORE_notify_transmit_ready (GSF_core, GNUNET_YES, pth->priority,
+        GNUNET_CORE_notify_transmit_ready (GSF_core, GNUNET_YES,
+                                           GNUNET_CORE_PRIO_BACKGROUND,
                                            GNUNET_TIME_absolute_get_remaining
                                            (pth->timeout), peer, pth->size,
                                            &peer_transmit_ready_cb, cp);
@@ -567,20 +564,42 @@ ats_reserve_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
   }
 }
 
+/**
+ * Function called by PEERSTORE with peer respect record
+ *
+ * @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
+peer_respect_cb (void *cls, struct GNUNET_PEERSTORE_Record *record, char *emsg)
+{
+  struct GSF_ConnectedPeer *cp = cls;
+
+  cp->respect_iterate_req = NULL;
+  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;
+}
 
 /**
  * A peer connected to us.  Setup the connected peer
  * records.
  *
  * @param peer identity of peer that connected
- * @return handle to connected peer entry
+ * @param creation_cb callback function when the record is created.
+ * @param creation_cb_cls closure for @creation_cb
  */
-struct GSF_ConnectedPeer *
-GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer)
+void
+GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer,
+                           GSF_ConnectedPeerCreationCallback creation_cb,
+                           void *creation_cb_cls)
 {
   struct GSF_ConnectedPeer *cp;
-  char *fn;
-  uint32_t respect;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to peer %s\n",
               GNUNET_i2s (peer));
@@ -590,22 +609,21 @@ GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer)
   cp->rc =
       GNUNET_ATS_reserve_bandwidth (GSF_ats, peer, DBLOCK_SIZE,
                                     &ats_reserve_callback, cp);
-  fn = get_respect_filename (peer);
-  if ((GNUNET_YES == GNUNET_DISK_file_test (fn)) &&
-      (sizeof (respect) == GNUNET_DISK_fn_read (fn, &respect, sizeof (respect))))
-    cp->disk_respect = cp->ppd.respect = ntohl (respect);
-  GNUNET_free (fn);
   cp->request_map = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO);
   GNUNET_break (GNUNET_OK ==
                 GNUNET_CONTAINER_multipeermap_put (cp_map,
-                                                  GSF_connected_peer_get_identity2_ (cp),
+               GSF_connected_peer_get_identity2_ (cp),
                                                    cp,
                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
   GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# peers connected"),
                          GNUNET_CONTAINER_multipeermap_size (cp_map),
                          GNUNET_NO);
-  GSF_push_start_ (cp);
-  return cp;
+  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,
+                                cp);
 }
 
 
@@ -1116,7 +1134,7 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
   uint16_t msize;
   const struct GetMessage *gm;
   unsigned int bits;
-  const struct GNUNET_HashCode *opt;
+  const struct GNUNET_PeerIdentity *opt;
   uint32_t bm;
   size_t bfsize;
   uint32_t ttl_decrement;
@@ -1146,13 +1164,13 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
       bits++;
     bm >>= 1;
   }
-  if (msize < sizeof (struct GetMessage) + bits * sizeof (struct GNUNET_HashCode))
+  if (msize < sizeof (struct GetMessage) + bits * sizeof (struct GNUNET_PeerIdentity))
   {
     GNUNET_break_op (0);
     return NULL;
   }
-  opt = (const struct GNUNET_HashCode *) &gm[1];
-  bfsize = msize - sizeof (struct GetMessage) - bits * sizeof (struct GNUNET_HashCode);
+  opt = (const struct GNUNET_PeerIdentity *) &gm[1];
+  bfsize = msize - sizeof (struct GetMessage) - bits * sizeof (struct GNUNET_PeerIdentity);
   /* bfsize must be power of 2, check! */
   if (0 != ((bfsize - 1) & bfsize))
   {
@@ -1173,7 +1191,7 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
     return NULL;
   }
   if (0 != (bm & GET_MESSAGE_BIT_RETURN_TO))
-    cp = GSF_peer_get_ ((const struct GNUNET_PeerIdentity *) &opt[bits++]);
+    cp = GSF_peer_get_ (&opt[bits++]);
   else
     cp = cps;
   if (NULL == cp)
@@ -1181,8 +1199,7 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
     if (0 != (bm & GET_MESSAGE_BIT_RETURN_TO))
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Failed to find RETURN-TO peer `%4s' in connection set. Dropping query.\n",
-                  GNUNET_i2s ((const struct GNUNET_PeerIdentity *)
-                              &opt[bits - 1]));
+                  GNUNET_i2s (&opt[bits - 1]));
 
     else
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1209,12 +1226,13 @@ GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other,
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Received request for `%s' of type %u from peer `%4s' with flags %u\n",
-              GNUNET_h2s (&gm->query), (unsigned int) type, GNUNET_i2s (other),
+              GNUNET_h2s (&gm->query),
+              (unsigned int) type,
+              GNUNET_i2s (other),
               (unsigned int) bm);
   target =
       (0 !=
-       (bm & GET_MESSAGE_BIT_TRANSMIT_TO)) ? ((const struct GNUNET_PeerIdentity
-                                               *) &opt[bits++]) : NULL;
+       (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))
@@ -1499,6 +1517,11 @@ GSF_peer_disconnect_handler_ (void *cls, const struct GNUNET_PeerIdentity *peer)
   GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# peers connected"),
                          GNUNET_CONTAINER_multipeermap_size (cp_map),
                          GNUNET_NO);
+  if (NULL != cp->respect_iterate_req)
+  {
+    GNUNET_PEERSTORE_iterate_cancel (cp->respect_iterate_req);
+    cp->respect_iterate_req = NULL;
+  }
   if (NULL != cp->migration_pth)
   {
     GSF_peer_transmit_cancel_ (cp->migration_pth);
@@ -1716,33 +1739,16 @@ static int
 flush_respect (void *cls, const struct GNUNET_PeerIdentity * key, void *value)
 {
   struct GSF_ConnectedPeer *cp = value;
-  char *fn;
-  uint32_t respect;
   struct GNUNET_PeerIdentity pid;
 
   if (cp->ppd.respect == cp->disk_respect)
     return GNUNET_OK;           /* unchanged */
   GNUNET_assert (0 != cp->ppd.pid);
   GNUNET_PEER_resolve (cp->ppd.pid, &pid);
-  fn = get_respect_filename (&pid);
-  if (cp->ppd.respect == 0)
-  {
-    if ((0 != UNLINK (fn)) && (errno != ENOENT))
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
-                                GNUNET_ERROR_TYPE_BULK, "unlink", fn);
-  }
-  else
-  {
-    respect = htonl (cp->ppd.respect);
-    if (sizeof (uint32_t) ==
-        GNUNET_DISK_fn_write (fn, &respect, sizeof (uint32_t),
-                              GNUNET_DISK_PERM_USER_READ |
-                              GNUNET_DISK_PERM_USER_WRITE |
-                              GNUNET_DISK_PERM_GROUP_READ |
-                              GNUNET_DISK_PERM_OTHER_READ))
-      cp->disk_respect = cp->ppd.respect;
-  }
-  GNUNET_free (fn);
+  GNUNET_PEERSTORE_store (peerstore, "fs", &pid, "respect", &cp->ppd.respect,
+                          sizeof (cp->ppd.respect),
+                          GNUNET_TIME_UNIT_FOREVER_ABS,
+                          GNUNET_PEERSTORE_STOREOPTION_REPLACE, NULL, NULL);
   return GNUNET_OK;
 }
 
@@ -1794,11 +1800,7 @@ void
 GSF_connected_peer_init_ ()
 {
   cp_map = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_get_value_filename (GSF_cfg, "fs",
-                                                          "RESPECT",
-                                                          &respectDirectory));
-  GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_create (respectDirectory));
+  peerstore = GNUNET_PEERSTORE_connect (GSF_cfg);
   GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_HIGH,
                                       &cron_flush_respect, NULL);
 }
@@ -1832,8 +1834,7 @@ GSF_connected_peer_done_ ()
   GNUNET_CONTAINER_multipeermap_iterate (cp_map, &clean_peer, NULL);
   GNUNET_CONTAINER_multipeermap_destroy (cp_map);
   cp_map = NULL;
-  GNUNET_free (respectDirectory);
-  respectDirectory = NULL;
+  GNUNET_PEERSTORE_disconnect (peerstore, GNUNET_YES);
 }