/*
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];
};
/**
* Client handle
*/
- struct GNUNET_SERVER_Client *client;
+ struct GNUNET_SERVICE_Client *client;
/**
* Mapping peer identities to `struct PreferencePeer` entry
* 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];
};
*
* @param id peer id of the peer for which we should do the update
* @param kind the kind of preference value to update
- * @param rp the relative peer struct where we store the global result
* @return the new relative preference
*/
static void
}
+/**
+ * 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
{
* changed, update the global preferences for the given
* peer and notify the plugin.
*
- * @param value the kind of preference to calculate the
+ * @param cls the kind of preference to calculate the
* new global relative preference values for
* @param key the peer to update relative preference values for
* @param value a `struct PeerRelative`, unused
* @param score_abs the normalized score
*/
static void
-update_preference (struct GNUNET_SERVER_Client *client,
+update_preference (struct GNUNET_SERVICE_Client *client,
const struct GNUNET_PeerIdentity *peer,
enum GNUNET_ATS_PreferenceKind kind,
float score_abs)
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;
/**
* Handle 'preference change' messages from clients.
*
- * @param cls unused, NULL
- * @param client client that sent the request
- * @param message the request message
+ * @param client the client that sent the request
+ * @param msg the request message
*/
void
-GAS_handle_preference_change (void *cls,
- struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
+GAS_handle_preference_change (struct GNUNET_SERVICE_Client *client,
+ const struct ChangePreferenceMessage *msg)
{
- const struct ChangePreferenceMessage *msg;
const struct PreferenceInformation *pi;
- uint16_t msize;
uint32_t nump;
- uint32_t i;
- msize = ntohs (message->size);
- if (msize < sizeof (struct ChangePreferenceMessage))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client,
- GNUNET_SYSERR);
- return;
- }
- msg = (const struct ChangePreferenceMessage *) message;
nump = ntohl (msg->num_preferences);
- if ( (msize !=
- sizeof (struct ChangePreferenceMessage) +
- nump * sizeof (struct PreferenceInformation)) ||
- (UINT16_MAX / sizeof (struct PreferenceInformation) < nump) )
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client,
- GNUNET_SYSERR);
- return;
- }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received PREFERENCE_CHANGE message for peer `%s'\n",
GNUNET_i2s (&msg->peer));
GNUNET_NO);
pi = (const struct PreferenceInformation *) &msg[1];
GAS_plugin_solver_lock ();
- for (i = 0; i < nump; i++)
+ for (uint32_t i = 0; i < nump; i++)
update_preference (client,
&msg->peer,
(enum GNUNET_ATS_PreferenceKind) ntohl (pi[i].preference_kind),
pi[i].preference_value);
GAS_plugin_solver_unlock ();
- GNUNET_SERVER_receive_done (client,
- GNUNET_OK);
}
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.
*/
* @param client the client
*/
void
-GAS_preference_client_disconnect (struct GNUNET_SERVER_Client *client)
+GAS_preference_client_disconnect (struct GNUNET_SERVICE_Client *client)
{
struct PreferenceClient *c_cur;