#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet-service-ats_addresses.h"
-#include "gnunet-service-ats_normalization.h"
#include "gnunet_statistics_service.h"
#define LOG(kind,...) GNUNET_log_from (kind, "ats-proportional",__VA_ARGS__)
/**
* Statistics handle
*/
-
struct GNUNET_STATISTICS_Handle *stats;
+ /**
+ * Bandwidth changed callback
+ */
+ GAS_bandwidth_changed_cb bw_changed;
+
+ /**
+ * Bandwidth changed callback cls
+ */
+ void *bw_changed_cls;
+
+ /**
+ * ATS function to get preferences
+ */
+ GAS_get_preferences get_preferences;
+
+ /**
+ * Closure for ATS function to get preferences
+ */
+ void *get_preferences_cls;
+
+ /**
+ * Bulk lock
+ */
+ int bulk_lock;
+
+ /**
+ * Number of changes while solver was locked
+ */
+ int bulk_requests;
+
+
/**
* Total number of addresses for solver
*/
*/
unsigned int networks;
- /**
- * Callback
- */
- GAS_bandwidth_changed_cb bw_changed;
-
- /**
- * Callback cls
- */
- void *bw_changed_cls;
-
- struct GNUNET_CONTAINER_MultiHashMap *prefs;
-
- struct PreferenceClient *pc_head;
- struct PreferenceClient *pc_tail;
};
static int
is_bandwidth_available_in_network (struct Network *net)
{
+ GNUNET_assert (NULL != net);
unsigned int na = net->active_addresses + 1;
uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
if (((net->total_quota_in / na) > min_bw) &&
unsigned long long assigned_quota_out = 0;
struct AddressWrapper *cur;
+
+ if (GNUNET_YES == s->bulk_lock)
+ {
+ s->bulk_requests++;
+ return;
+ }
+
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Recalculate quota for network type `%s' for %u addresses (in/out): %llu/%llu \n",
net->desc, net->active_addresses, net->total_quota_in, net->total_quota_in);
{
if (GNUNET_YES == cur->addr->active)
{
- t = GAS_normalization_get_preferences (&cur->addr->peer);
- if (NULL == t)
- {
- total_prefs += DEFAULT_REL_PREFERENCE;
- }
- else
- {
- peer_prefs = 0.0;
- for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
- {
- if (c != GNUNET_ATS_PREFERENCE_END)
- {
- //fprintf (stderr, "VALUE[%u] %s %.3f \n", c, GNUNET_i2s (&cur->addr->peer), t[c]);
- peer_prefs += t[c];
- }
- }
- total_prefs += (peer_prefs / (GNUNET_ATS_PreferenceCount -1));
- }
+ GNUNET_assert (NULL != (t = s->get_preferences (s->get_preferences_cls, &cur->addr->peer)));
+
+ peer_prefs = 0.0;
+ for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
+ {
+ if (c != GNUNET_ATS_PREFERENCE_END)
+ {
+ //fprintf (stderr, "VALUE[%u] %s %.3f \n", c, GNUNET_i2s (&cur->addr->peer), t[c]);
+ peer_prefs += t[c];
+ }
+ }
+ total_prefs += (peer_prefs / (GNUNET_ATS_PreferenceCount -1));
}
}
for (cur = net->head; NULL != cur; cur = cur->next)
if (GNUNET_YES == cur->addr->active)
{
cur_pref = 0.0;
- t = GAS_normalization_get_preferences (&cur->addr->peer);
- if (NULL != t)
- {
- for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
- {
- if (c != GNUNET_ATS_PREFERENCE_END)
- cur_pref += t[c];
- }
- cur_pref /= 2;
- }
- else
- {
- cur_pref = DEFAULT_REL_PREFERENCE;
- }
+ GNUNET_assert (NULL != (t = s->get_preferences (s->get_preferences_cls, &cur->addr->peer)));
+
+ for (c = 0; c < GNUNET_ATS_PreferenceCount; c++)
+ {
+ if (c != GNUNET_ATS_PREFERENCE_END)
+ cur_pref += t[c];
+ }
+ cur_pref /= 2;
assigned_quota_in = min_bw + ((cur_pref / total_prefs) * remaining_quota_in);
assigned_quota_out = min_bw + ((cur_pref / total_prefs) * remaining_quota_out);
distribute_bandwidth_in_all_networks (struct GAS_PROPORTIONAL_Handle *s)
{
int i;
+
for (i = 0; i < s->networks; i++)
distribute_bandwidth_in_network (s, &s->network_entries[i], NULL);
{
if (s->network_entries[c].type == type)
return &s->network_entries[c];
+
}
return NULL;
}
* Changes the preferences for a peer in the problem
*
* @param solver the solver handle
- * @param client the client with this preference
+ * @param addresses the address hashmap
* @param peer the peer to change the preference for
* @param kind the kind to change the preference
* @param pref_rel the normalized preference value for this kind over all clients
- * @param score the score
*/
void
GAS_proportional_address_change_preference (void *solver,
- void *client,
- const struct GNUNET_PeerIdentity *peer,
- enum GNUNET_ATS_PreferenceKind kind,
- double pref_rel)
+ struct GNUNET_CONTAINER_MultiHashMap *addresses,
+ const struct GNUNET_PeerIdentity *peer,
+ enum GNUNET_ATS_PreferenceKind kind,
+ double pref_rel)
{
struct GAS_PROPORTIONAL_Handle *s = solver;
GNUNET_assert (NULL != solver);
- GNUNET_assert (NULL != client);
GNUNET_assert (NULL != peer);
- distribute_bandwidth_in_all_networks (s);
-
+ distribute_bandwidth_in_all_networks (s);
}
/**
(GNUNET_NO == cur->active) ? "inactive" : "active",
cur, GNUNET_i2s (peer));
net_cur = (struct Network *) cur->solver_information;
+ if (NULL == cur)
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR, "Trying to suggesting unknown address peer `%s'\n",
+ GNUNET_i2s (peer));
+ GNUNET_break (0);
+ return NULL;
+ }
if (GNUNET_YES == cur->active)
{
/* This address was selected previously, so no need to update quotas */
s->bw_changed (s->bw_changed_cls, prev); /* notify about bw change, REQUIRED? */
if (GNUNET_SYSERR == addresse_decrement (s, net_prev, GNUNET_NO, GNUNET_YES))
GNUNET_break (0);
- distribute_bandwidth_in_network (s, net_prev, NULL);
+ distribute_bandwidth_in_network (s, net_prev, NULL);
}
if (GNUNET_NO == (is_bandwidth_available_in_network (cur->solver_information)))
cur->active = GNUNET_YES;
addresse_increment(s, net_cur, GNUNET_NO, GNUNET_YES);
distribute_bandwidth_in_network (s, net_cur, cur);
-
return cur;
}
}
+/**
+ * Start a bulk operation
+ *
+ * @param solver the solver
+ */
+void
+GAS_proportional_bulk_start (void *solver)
+{
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Locking solver for bulk operation ...\n");
+ struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver;
+
+ GNUNET_assert (NULL != solver);
+ s->bulk_lock ++;
+}
+
+/**
+ * Bulk operation done
+ */
+void
+GAS_proportional_bulk_stop (void *solver)
+{
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Unlocking solver from bulk operation ...\n");
+
+ struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver;
+ GNUNET_assert (NULL != solver);
+
+ if (s->bulk_lock < 1)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ s->bulk_lock --;
+ if ((0 == s->bulk_lock) && (0 < s->bulk_requests))
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR, "No lock pending, recalculating\n");
+ distribute_bandwidth_in_all_networks (s);
+ s->bulk_requests = 0;
+ }
+}
+
+
/**
* Add a new single address to a network
*
/* set new network type */
new_net = get_network (solver, addr_net);
+ if (NULL == new_net)
+ {
+ /* Address changed to invalid network... */
+ LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot find network of type `%u' %s\n"),
+ addr_net, GNUNET_ATS_print_network_type (addr_net));
+ address->assigned_bw_in = GNUNET_BANDWIDTH_value_init (0);
+ address->assigned_bw_out = GNUNET_BANDWIDTH_value_init (0);
+ s->bw_changed (s->bw_changed_cls, address);
+ return;
+ }
address->solver_information = new_net;
/* Add to new network and update*/
* @param dest_length array length for quota arrays
* @param bw_changed_cb callback for changed bandwidth amounts
* @param bw_changed_cb_cls cls for callback
+ * @param get_preference callback to get relative preferences for a peer
+ * @param get_preference_cls cls for callback to get relative preferences
* @return handle for the solver on success, NULL on fail
*/
void *
unsigned long long *in_quota,
int dest_length,
GAS_bandwidth_changed_cb bw_changed_cb,
- void *bw_changed_cb_cls)
+ void *bw_changed_cb_cls,
+ GAS_get_preferences get_preference,
+ void *get_preference_cls)
{
int c;
struct GAS_PROPORTIONAL_Handle *s = GNUNET_malloc (sizeof (struct GAS_PROPORTIONAL_Handle));
s->stats = (struct GNUNET_STATISTICS_Handle *) stats;
s->bw_changed = bw_changed_cb;
s->bw_changed_cls = bw_changed_cb_cls;
+ s->get_preferences = get_preference;
+ s->get_preferences_cls = get_preference_cls;
s->networks = dest_length;
s->network_entries = GNUNET_malloc (dest_length * sizeof (struct Network));
s->active_addresses = 0;
s->total_addresses = 0;
- s->prefs = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+ s->bulk_lock = GNUNET_NO;
for (c = 0; c < dest_length; c++)
{