/*
This file is part of GNUnet.
- Copyright (C) 2011-2015 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2011-2015 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
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 ats/gnunet-service-ats_preferences.c
* Array of relative preference values, to be indexed by
* an `enum GNUNET_ATS_PreferenceKind`.
*/
- double f_rel[GNUNET_ATS_PreferenceCount];
+ double f_rel[GNUNET_ATS_PREFERENCE_END];
+ /**
+ * Number of clients that are expressing a preference for
+ * this peer. When this counter reaches zero, this entry
+ * is freed.
+ */
+ unsigned int num_clients;
};
* Absolute preference values for all preference types
* as expressed by this client for this peer.
*/
- double f_abs[GNUNET_ATS_PreferenceCount];
+ double f_abs[GNUNET_ATS_PREFERENCE_END];
/**
* Relative preference values for all preference types,
* normalized in [0..1] based on how the respective
* client scored other peers.
*/
- double f_rel[GNUNET_ATS_PreferenceCount];
+ double f_rel[GNUNET_ATS_PREFERENCE_END];
};
* Array of sums of absolute preferences for all
* peers as expressed by this client.
*/
- double f_abs_sum[GNUNET_ATS_PreferenceCount];
+ double f_abs_sum[GNUNET_ATS_PREFERENCE_END];
};
}
+/**
+ * Free a peer's `struct PeerRelative`.
+ *
+ * @param cls unused
+ * @param key the key
+ * @param value the `struct PeerRelative` to free.
+ * @return #GNUNET_OK to continue
+ */
+static int
+free_peer (void *cls,
+ const struct GNUNET_PeerIdentity *key,
+ void *value)
+{
+ struct PeerRelative *rp = value;
+
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multipeermap_remove (preference_peers,
+ key,
+ value));
+ GNUNET_free (rp);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Free `struct PreferencePeer` entry in map.
+ *
+ * @param cls the `struct PreferenceClient` with the map
+ * @param key the peer the entry is for
+ * @param value the `struct PreferencePeer` entry to free
+ * @return #GNUNET_OK (continue to iterate)
+ */
+static int
+free_preference (void *cls,
+ const struct GNUNET_PeerIdentity *key,
+ void *value)
+{
+ struct PreferenceClient *pc = cls;
+ struct PreferencePeer *p = value;
+ struct PeerRelative *pr;
+
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multipeermap_remove (pc->peer2pref,
+ key,
+ p));
+ GNUNET_free (p);
+ pr = GNUNET_CONTAINER_multipeermap_get (preference_peers,
+ key);
+ GNUNET_assert (NULL != pr);
+ GNUNET_assert (pr->num_clients > 0);
+ pr->num_clients--;
+ if (0 == pr->num_clients)
+ {
+ free_peer (NULL,
+ key,
+ pr);
+ }
+ return GNUNET_OK;
+}
+
+
/**
* Closure for #age_values().
*/
int dead;
dead = GNUNET_YES;
- for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
+ for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Aging preference for peer `%s'\n",
if (GNUNET_YES == dead)
{
/* all preferences are zero, remove this entry */
- GNUNET_CONTAINER_multipeermap_remove (ac->cur_client->peer2pref,
- peer,
- p);
- GNUNET_free (p);
- /* FIXME: Consider destroying the `struct PeerRelative`
- as well here... */
+ free_preference (ac->cur_client,
+ peer,
+ p);
}
return GNUNET_OK;
}
* Reduce absolute preferences since they got old.
*
* @param cls unused
- * @param tc context
*/
static void
-preference_aging (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+preference_aging (void *cls)
{
struct AgeContext ac;
aging_task = NULL;
+ GAS_plugin_solver_lock ();
ac.values_to_update = 0;
for (ac.cur_client = pc_head; NULL != ac.cur_client; ac.cur_client = ac.cur_client->next)
GNUNET_CONTAINER_multipeermap_iterate (ac.cur_client->peer2pref,
&age_values,
&ac);
+ GAS_plugin_solver_unlock ();
if (ac.values_to_update > 0)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Rescheduling aging task due to %u elements remaining to age\n",
ac.values_to_update);
- aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL,
- &preference_aging,
- NULL);
+ if (NULL == aging_task)
+ aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL,
+ &preference_aging,
+ NULL);
}
else
{
struct PeerRelative *r_cur;
unsigned int i;
- if (kind >= GNUNET_ATS_PreferenceCount)
+ if (kind >= GNUNET_ATS_PREFERENCE_END)
{
GNUNET_break(0);
return;
if (NULL == c_cur)
{
c_cur = GNUNET_new (struct PreferenceClient);
+ c_cur->client = client;
c_cur->peer2pref = GNUNET_CONTAINER_multipeermap_create (16,
GNUNET_NO);
- for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
+ for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
c_cur->f_abs_sum[i] = DEFAULT_ABS_PREFERENCE;
GNUNET_CONTAINER_DLL_insert (pc_head,
pc_tail,
c_cur);
}
+
+ /* check global peer entry exists */
+ if (NULL ==
+ (r_cur = GNUNET_CONTAINER_multipeermap_get (preference_peers,
+ peer)))
+ {
+ /* Create struct for peer */
+ r_cur = GNUNET_new (struct PeerRelative);
+ for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
+ r_cur->f_rel[i] = DEFAULT_REL_PREFERENCE;
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multipeermap_put (preference_peers,
+ peer,
+ r_cur,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ }
+
/* Find entry for peer */
p_cur = GNUNET_CONTAINER_multipeermap_get (c_cur->peer2pref,
peer);
{
/* Not found: create new peer entry */
p_cur = GNUNET_new (struct PreferencePeer);
- for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
+ for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
{
/* Default value per peer absolute preference for a preference*/
p_cur->f_abs[i] = DEFAULT_ABS_PREFERENCE;
peer,
p_cur,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- }
-
- if (NULL ==
- GNUNET_CONTAINER_multipeermap_get (preference_peers,
- peer))
- {
- /* Create struct for peer */
- r_cur = GNUNET_new (struct PeerRelative);
- for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
- r_cur->f_rel[i] = DEFAULT_REL_PREFERENCE;
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multipeermap_put (preference_peers,
- peer,
- r_cur,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ r_cur->num_clients++;
}
p_cur->f_abs[kind] += score_abs;
preference_peers = GNUNET_CONTAINER_multipeermap_create (16,
GNUNET_NO);
- for (i = 0; i < GNUNET_ATS_PreferenceCount; i++)
+ for (i = 0; i < GNUNET_ATS_PREFERENCE_END; i++)
defvalues.f_rel[i] = DEFAULT_REL_PREFERENCE;
}
-/**
- * Free a peer's `struct PeerRelative`.
- *
- * @param cls unused
- * @param key the key
- * @param value the `struct PeerRelative` to free.
- * @return #GNUNET_OK to continue
- */
-static int
-free_peer (void *cls,
- const struct GNUNET_PeerIdentity *key,
- void *value)
-{
- struct PeerRelative *rp = value;
-
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multipeermap_remove (preference_peers,
- key,
- value));
- GNUNET_free (rp);
- return GNUNET_OK;
-}
-
-
-/**
- * Free `struct PreferencePeer` entry in map.
- *
- * @param cls the `struct PreferenceClient` with the map
- * @param key the peer the entry is for
- * @param value the `struct PreferencePeer` entry to free
- * @return #GNUNET_OK (continue to iterate)
- */
-static int
-free_preference (void *cls,
- const struct GNUNET_PeerIdentity *key,
- void *value)
-{
- struct PreferenceClient *pc = cls;
- struct PreferencePeer *p = value;
-
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multipeermap_remove (pc->peer2pref,
- key,
- p));
- GNUNET_free (p);
- return GNUNET_OK;
-}
-
-
/**
* Shutdown preferences subsystem.
*/