2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file ats/gnunet-service-ats-solver_ril.c
23 * @brief ATS reinforcement learning solver
24 * @author Fabian Oehlmann
25 * @author Matthias Wachs
29 #include "gnunet_util_lib.h"
30 #include "gnunet-service-ats_addresses.h"
31 #include "gnunet_statistics_service.h"
33 #define RIL_DEFAULT_STEP_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 3000)
34 #define RIL_DEFAULT_DISCOUNT_FACTOR 0.5
35 #define RIL_DEFAULT_GRADIENT_STEP_SIZE 0.4
36 #define RIL_DEFAULT_TRACE_DECAY 0.6
37 #define RIL_EXPLORE_RATIO 0.1
40 * ATS reinforcement learning solver
47 RIL_ACTION_BW_IN_DBL = 0,
48 RIL_ACTION_BW_OUT_DBL = 1,
49 RIL_ACTION_BW_IN_HLV = 2,
50 RIL_ACTION_BW_OUT_HLV = 3,
51 RIL_ACTION_TYPE_NUM = 4
53 //TODO! add the rest of the actions
61 enum RIL_E_Modification
70 * Global learning parameters
72 struct RIL_Learning_Parameters
75 * The TD-algorithm to use
77 enum RIL_Algorithm algorithm;
80 * Learning discount factor in the TD-update
85 * Gradient-descent step-size
90 * Trace-decay factor for eligibility traces
98 * Next agent in solver's linked list
100 struct RIL_Peer_Agent *next;
103 * Previous agent in solver's linked list
105 struct RIL_Peer_Agent *prev;
110 struct GAS_RIL_Handle *envi;
115 struct GNUNET_PeerIdentity peer;
118 * Whether the agent is active or not
123 * Number of performed time-steps
125 unsigned long long step_count;
128 * Experience matrix W
133 * Number of rows of W / Number of state-vector features
138 * Number of columns of W / Number of actions
143 * Last perceived state feature vector
153 * Eligibility trace vector
160 struct ATS_Address * address;
163 * Inbound bandwidth assigned by the agent
165 unsigned long long bw_in;
168 * Outbound bandwidth assigned by the agent
170 unsigned long long bw_out;
178 enum GNUNET_ATS_Network_Type type;
181 * Total available inbound bandwidth
183 unsigned long long bw_in_available;
186 * Total assigned outbound bandwidth
188 unsigned long long bw_in_assigned;
191 * Total available outbound bandwidth
193 unsigned long long bw_out_available;
196 * Total assigned outbound bandwidth
198 unsigned long long bw_out_assigned;
204 * Bandwidth changed callback
206 GAS_bandwidth_changed_cb bw_changed;
209 * Bandwidth changed callback cls
211 void *bw_changed_cls;
214 * ATS function to get preferences
216 GAS_get_preferences get_preferences;
219 * Closure for ATS function to get preferences
221 void *get_preferences_cls;
224 * ATS function to get properties
226 GAS_get_properties get_properties;
229 * Closure for ATS function to get properties
231 void *get_properties_cls;
235 * A handle for the reinforcement learning solver
237 struct GAS_RIL_Handle
242 struct GNUNET_STATISTICS_Handle *stats;
245 * Hashmap containing all valid addresses
247 const struct GNUNET_CONTAINER_MultiHashMap *addresses;
250 * Callbacks for the solver
252 struct RIL_Callbacks *callbacks;
260 * Number of changes while solver was locked
265 * Number of performed time-steps
267 unsigned long long step_count;
270 * Interval time between steps in milliseconds //TODO? put in agent
272 struct GNUNET_TIME_Relative step_time;
275 * Task identifier of the next time-step to be executed //TODO? put in agent
277 GNUNET_SCHEDULER_TaskIdentifier next_step;
280 * Learning parameters
282 struct RIL_Learning_Parameters parameters;
285 * Array of networks with global assignment state
287 struct RIL_Network * network_entries;
292 unsigned int networks_count;
295 * List of active peer-agents
297 struct RIL_Peer_Agent * agents_head;
298 struct RIL_Peer_Agent * agents_tail;
303 * ---------------------------
307 * Estimate the current action-value for state s and action a
308 * @param agent agent performing the estimation
311 * @return estimation value
314 agent_estimate_q (struct RIL_Peer_Agent *agent,
321 for (i = 0; i < agent->m; i++)
323 result += state[i] * (agent->W)[agent->m][action];
330 * Decide whether to do exploration (i.e. taking a new action) or exploitation (i.e. taking the
331 * currently estimated best action) in the current step
332 * @param agent agent performing the step
333 * @return yes, if exploring
336 agent_decide_exploration (struct RIL_Peer_Agent *agent)
338 double r = (double) GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX) / (double) UINT32_MAX;
340 if (r < RIL_EXPLORE_RATIO)
348 * Gets the action, with the maximal estimated Q-value (i.e. the one currently estimated to bring the
349 * most reward in the future)
350 * @param agent agent performing the calculation
351 * @param state the state from which to take the action
352 * @return the action promising most future reward
355 agent_get_action_best (struct RIL_Peer_Agent *agent,
361 double max_q = DBL_MIN;
363 for (i = 0; i < agent->n; i++)
365 cur_q = agent_estimate_q (agent, state, i);
373 GNUNET_assert(-1 != max_i);
379 * Gets any action, to explore the action space from that state
380 * @param agent agent performing the calculation
381 * @param state the state from which to take the action
385 agent_get_action_explore (struct RIL_Peer_Agent *agent,
388 return GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, agent->n);
392 * Updates the weights (i.e. coefficients) of the weight vector in matrix W for action a
393 * @param agent the agent performing the update
394 * @param reward the reward received for the last action
395 * @param s_next the new state, the last step got the agent into
396 * @param a_prime the new
399 agent_update_weights (struct RIL_Peer_Agent *agent,
406 double *theta = (agent->W)[agent->a_old];
408 delta = reward + agent_estimate_q (agent, s_next, a_prime) -
409 agent_estimate_q (agent, agent->s_old, agent->a_old);
410 for (i = 0; i < agent->m; i++)
412 theta[i] += agent->envi->parameters.alpha * delta * (agent->e)[i];
417 * Changes the eligibility trace vector e in various manners:
418 * RIL_E_ACCUMULATE - adds 1 to each component as in accumulating eligibility traces
419 * RIL_E_REPLACE - resets each component to 1 as in replacing traces
420 * RIL_E_SET - multiplies e with gamma and lambda as in the update rule
421 * RIL_E_ZERO - sets e to 0 as in Watkin's Q-learning algorithm when exploring and when initializing
426 agent_modify_eligibility (struct RIL_Peer_Agent *agent,
427 enum RIL_E_Modification mod)
430 double *e = agent->e;
431 double gamma = agent->envi->parameters.gamma;
432 double lambda = agent->envi->parameters.lambda;
434 for (i = 0; i < agent->m; i++)
438 case RIL_E_ACCUMULATE:
445 e[i] = gamma * lambda;
455 * Allocates a state vector and fills it with the features present
456 * @param solver the solver handle
457 * @return pointer to the state vector
460 envi_get_state (struct GAS_RIL_Handle *solver)
463 struct RIL_Network *net;
464 double *state = GNUNET_malloc (sizeof (double) * solver->networks_count * 4);
466 for (i = 0; i < solver->networks_count; i += 4)
468 net = (&solver->network_entries)[i];
469 state[i] = (double) net->bw_in_assigned;
470 state[i+1] = (double) net->bw_in_available;
471 state[i+2] = (double) net->bw_out_assigned;
472 state[i+3] = (double) net->bw_out_available;
479 * Gets the reward of the last performed step
480 * @param solver solver handle
484 envi_get_reward (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent)
486 //TODO! implement reward calculation
488 return (double) GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX) / (double) UINT32_MAX;
492 envi_action_bw_double (struct GAS_RIL_Handle *solver,
493 struct RIL_Peer_Agent *agent,
499 agent->address->assigned_bw_in.value__ = htonl (agent->bw_in);
500 solver->callbacks->bw_changed (solver->callbacks->bw_changed_cls, agent->address);
505 agent->address->assigned_bw_out.value__ = htonl (agent->bw_out);
506 solver->callbacks->bw_changed (solver->callbacks->bw_changed_cls, agent->address);
511 envi_action_bw_halven (struct GAS_RIL_Handle *solver,
512 struct RIL_Peer_Agent *agent,
515 if ((direction_in && 1 == agent->bw_in) ||
516 (!direction_in && 1 == agent->bw_out))
523 agent->address->assigned_bw_in.value__ = htonl (agent->bw_in);
524 solver->callbacks->bw_changed (solver->callbacks->bw_changed_cls, agent->address);
529 agent->address->assigned_bw_out.value__ = htonl (agent->bw_out);
530 solver->callbacks->bw_changed (solver->callbacks->bw_changed_cls, agent->address);
535 * Puts the action into effect
536 * @param solver solver handle
537 * @param action action to perform by the solver
540 envi_do_action (struct GAS_RIL_Handle *solver,
541 struct RIL_Peer_Agent *agent,
546 case RIL_ACTION_BW_IN_DBL:
547 envi_action_bw_double (solver, agent, GNUNET_YES);
549 case RIL_ACTION_BW_IN_HLV:
550 envi_action_bw_halven (solver, agent, GNUNET_YES);
552 case RIL_ACTION_BW_OUT_DBL:
553 envi_action_bw_double (solver, agent, GNUNET_NO);
555 case RIL_ACTION_BW_OUT_HLV:
556 envi_action_bw_halven (solver, agent, GNUNET_NO);
562 * Performs one step of the Markov Decision Process. Other than in the literature the step starts
563 * after having done the last action a_old. It observes the new state s_next and the reward
564 * received. Then the coefficient update is done according to the SARSA or Q-learning method. The
565 * next action is put into effect.
566 * @param agent the agent performing the step
569 agent_step (struct RIL_Peer_Agent *agent)
575 s_next = envi_get_state(agent->envi);
576 reward = envi_get_reward(agent->envi, agent);
578 switch (agent->envi->parameters.algorithm)
581 agent_modify_eligibility (agent, RIL_E_SET);
582 if (agent_decide_exploration (agent))
584 a_next = agent_get_action_explore (agent, s_next);
588 a_next = agent_get_action_best (agent, s_next);
590 //updates weights with selected action (on-policy)
591 agent_update_weights (agent, reward, s_next, a_next);
595 //updates weights with best action, disregarding actually selected action (off-policy)
596 a_next = agent_get_action_best (agent, s_next);
597 agent_update_weights (agent, reward, s_next, a_next);
598 if (agent_decide_exploration (agent))
600 a_next = agent_get_action_explore (agent, s_next);
601 agent_modify_eligibility(agent, RIL_E_ZERO);
605 a_next = agent_get_action_best (agent, s_next);
606 agent_modify_eligibility(agent, RIL_E_SET);
611 GNUNET_assert (-1 != a_next);
613 agent_modify_eligibility (agent, RIL_E_ACCUMULATE);
615 envi_do_action(agent->envi, agent, a_next);
617 GNUNET_free(agent->s_old);
618 agent->s_old = s_next;
619 agent->a_old = a_next;
621 agent->step_count += 1;
625 * Cycles through all agents and lets the active ones do a step. Schedules the next step.
626 * @param solver the solver handle
627 * @param tc task context for the scheduler
630 ril_periodic_step (void *cls,
631 const struct GNUNET_SCHEDULER_TaskContext *tc)
633 struct GAS_RIL_Handle *solver = cls;
634 struct RIL_Peer_Agent *cur;
636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RIL step number %d\n", solver->step_count);
638 for (cur = solver->agents_head; NULL != cur; cur = cur->next)
646 solver->step_count += 1;
647 solver->next_step = GNUNET_SCHEDULER_add_delayed (
654 * Initialize an agent without addresses and its knowledge base
655 * @param s ril solver
656 * @param peer the one in question
657 * @return handle to the new agent
659 static struct RIL_Peer_Agent *
661 const struct GNUNET_PeerIdentity *peer)
664 struct GAS_RIL_Handle * solver = s;
665 struct RIL_Peer_Agent * agent = GNUNET_malloc (sizeof (struct RIL_Peer_Agent));
667 agent->envi = solver;
669 agent->step_count = 0;
670 agent->active = GNUNET_NO;
672 agent->n = RIL_ACTION_TYPE_NUM;
673 agent->m = solver->networks_count * 4;
674 agent->W = (double **) GNUNET_malloc (sizeof (double) * agent->n);
675 for (i = 0; i < agent->n; i++)
677 (agent->W)[i] = (double *) GNUNET_malloc (sizeof (double) * agent->m);
680 agent->e = (double *) GNUNET_malloc (sizeof (double) * agent->m);
681 agent_modify_eligibility (agent, RIL_E_ZERO);
683 GNUNET_CONTAINER_DLL_insert_tail (solver->agents_head, solver->agents_tail, agent);
690 * @param s solver handle
691 * @param agent the agent to retire
694 agent_die (struct GAS_RIL_Handle *solver,
695 struct RIL_Peer_Agent *agent)
699 for (i = 0; i < agent->n; i++)
701 GNUNET_free((agent->W)[i]);
703 GNUNET_free(agent->W);
704 GNUNET_free(agent->e);
705 GNUNET_free(agent->s_old);
709 * Counts the (active) agents
710 * @param solver solver handle
711 * @param active_only whether only active agents should be counted
712 * @return number of agents
715 ril_count_agents (struct GAS_RIL_Handle *solver,
719 struct RIL_Peer_Agent *cur;
722 for (cur = solver->agents_head; NULL != cur; cur = cur->next)
724 if ((!active_only) || (active_only && cur->active))
733 * Returns the agent for a peer
734 * @param s solver handle
735 * @param peer identity of the peer
738 static struct RIL_Peer_Agent *
739 ril_get_agent (struct GAS_RIL_Handle *solver,
740 const struct GNUNET_PeerIdentity *peer)
742 struct RIL_Peer_Agent *cur;
744 for (cur = solver->agents_head; NULL != cur; cur = cur->next)
746 if (0 == GNUNET_CRYPTO_hash_cmp (&peer->hashPubKey, &cur->peer.hashPubKey))
752 return agent_init (solver, peer);
756 * Iterator, which allocates one agent per peer
759 * @param key peer identity
760 * @param value address
761 * @return whether iterator should continue
764 ril_init_agents_it (void *cls,
765 const struct GNUNET_HashCode *key,
768 struct GAS_RIL_Handle *solver = cls;
769 struct ATS_Address *address = value;
770 struct RIL_Peer_Agent *agent;
771 uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
773 agent = ril_get_agent (solver, &address->peer);
775 GNUNET_assert (NULL != agent);
777 if (NULL == agent->address)
779 agent->address = address;
780 agent->address->active = GNUNET_YES;
781 agent->bw_in = min_bw;
782 agent->address->assigned_bw_in.value__ = htonl (min_bw);
783 agent->bw_out = min_bw;
784 agent->address->assigned_bw_out.value__ = htonl (min_bw);
791 * Lookup network struct by type
793 * @param s the solver handle
794 * @param type the network type
795 * @return the network struct
797 static struct RIL_Network *
798 ril_get_network (struct GAS_RIL_Handle *s, uint32_t type)
801 for (i = 0 ; i < s->networks_count; i++)
803 if (s->network_entries[i].type == type)
804 return &s->network_entries[i];
812 * Solver API functions
813 * ---------------------------
817 * Changes the preferences for a peer in the problem
819 * @param solver the solver handle
820 * @param peer the peer to change the preference for
821 * @param kind the kind to change the preference
822 * @param pref_rel the normalized preference value for this kind over all clients
825 GAS_ril_address_change_preference (void *s,
826 const struct GNUNET_PeerIdentity *peer,
827 enum GNUNET_ATS_PreferenceKind kind,
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831 "API_address_change_preference() Preference `%s' for peer `%s' changed to %.2f \n",
832 GNUNET_ATS_print_preference_type (kind),
836 * Nothing to do here. Preferences are considered during reward calculation.
842 * Init the reinforcement learning problem solver
845 * network[i] contains the network type as type GNUNET_ATS_NetworkType[i]
846 * out_quota[i] contains outbound quota for network type i
847 * in_quota[i] contains inbound quota for network type i
850 * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN}
851 * network[2] == GNUNET_ATS_NET_LAN
852 * out_quota[2] == 65353
853 * in_quota[2] == 65353
855 * @param cfg configuration handle
856 * @param stats the GNUNET_STATISTICS handle
857 * @param network array of GNUNET_ATS_NetworkType with length dest_length
858 * @param addresses hashmap containing all addresses
859 * @param out_quota array of outbound quotas
860 * @param in_quota array of outbound quota
861 * @param dest_length array length for quota arrays
862 * @param bw_changed_cb callback for changed bandwidth amounts
863 * @param bw_changed_cb_cls cls for callback
864 * @param get_preference callback to get relative preferences for a peer
865 * @param get_preference_cls cls for callback to get relative preferences
866 * @param get_properties_cls for callback to get relative properties
867 * @param get_properties_cls cls for callback to get relative properties
868 * @return handle for the solver on success, NULL on fail
871 GAS_ril_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
872 const struct GNUNET_STATISTICS_Handle *stats,
873 const struct GNUNET_CONTAINER_MultiHashMap *addresses,
875 unsigned long long *out_quota,
876 unsigned long long *in_quota,
878 GAS_bandwidth_changed_cb bw_changed_cb,
879 void *bw_changed_cb_cls,
880 GAS_get_preferences get_preference,
881 void *get_preference_cls,
882 GAS_get_properties get_properties,
883 void *get_properties_cls)
886 unsigned long long tmp;
887 struct RIL_Network * cur;
888 struct GAS_RIL_Handle *solver = GNUNET_malloc (sizeof (struct GAS_RIL_Handle));
890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_init() Initializing RIL solver\n");
892 GNUNET_assert (NULL != cfg);
893 GNUNET_assert (NULL != stats);
894 GNUNET_assert (NULL != network);
895 GNUNET_assert (NULL != bw_changed_cb);
896 GNUNET_assert (NULL != get_preference);
897 GNUNET_assert (NULL != get_properties);
899 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time(cfg, "ats", "RIL_STEP_TIME", &solver->step_time))
901 solver->step_time = RIL_DEFAULT_STEP_TIME;
903 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size(cfg, "ats", "RIL_DISCOUNT_FACTOR", &tmp))
905 solver->parameters.gamma = (double) tmp / 100;;
909 solver->parameters.gamma = RIL_DEFAULT_DISCOUNT_FACTOR;
911 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size(cfg, "ats", "RIL_GRADIENT_STEP_SIZE", &tmp))
913 solver->parameters.alpha = (double) tmp / 100;;
917 solver->parameters.alpha = RIL_DEFAULT_GRADIENT_STEP_SIZE;
919 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size(cfg, "ats", "RIL_TRACE_DECAY", &tmp))
921 solver->parameters.lambda = (double) tmp / 100;;
925 solver->parameters.lambda = RIL_DEFAULT_TRACE_DECAY;
928 solver->stats = (struct GNUNET_STATISTICS_Handle *) stats;
929 solver->callbacks = GNUNET_malloc (sizeof (struct RIL_Callbacks));
930 solver->callbacks->bw_changed = bw_changed_cb;
931 solver->callbacks->bw_changed_cls = bw_changed_cb_cls;
932 solver->callbacks->get_preferences = get_preference;
933 solver->callbacks->get_preferences_cls = get_preference_cls;
934 solver->callbacks->get_properties = get_properties;
935 solver->callbacks->get_properties_cls = get_properties_cls;
936 solver->networks_count = dest_length;
937 solver->network_entries = GNUNET_malloc (dest_length * sizeof (struct RIL_Network));
938 solver->bulk_lock = GNUNET_NO;
939 solver->addresses = addresses;
940 solver->step_count = 0;
942 for (c = 0; c < dest_length; c++)
944 cur = &solver->network_entries[c];
945 cur->type = network[c];
946 cur->bw_in_available = in_quota[c];
947 cur->bw_in_assigned = 0;
948 cur->bw_out_available = out_quota[c];
949 cur->bw_out_assigned = 0;
952 c = GNUNET_CONTAINER_multihashmap_iterate (addresses, &ril_init_agents_it, solver);
954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_init() Solving ATS for %d addresses and %d peers\n",
956 ril_count_agents(solver, GNUNET_NO));
958 solver->next_step = GNUNET_SCHEDULER_add_delayed (
959 GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_get_millisecond_ (), 1000),
967 * Shutdown the reinforcement learning problem solver
969 * @param solver the respective handle to shutdown
972 GAS_ril_done (void * solver)
974 struct GAS_RIL_Handle *s = solver;
975 struct RIL_Peer_Agent *cur_agent;
976 struct RIL_Peer_Agent *next_agent;
978 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_done() Shutting down RIL solver\n");
980 cur_agent = s->agents_head;
981 while (NULL != cur_agent)
983 next_agent = cur_agent->next;
984 GNUNET_CONTAINER_DLL_remove (s->agents_head, s->agents_tail, cur_agent);
985 agent_die (s, cur_agent);
986 cur_agent = next_agent;
989 GNUNET_SCHEDULER_cancel (s->next_step);
990 GNUNET_free (s->callbacks);
991 GNUNET_free (s->network_entries);
997 * Add a single address within a network to the solver
999 * @param solver the solver Handle
1000 * @param address the address to add
1001 * @param network network type of this address
1004 GAS_ril_address_add (void *solver,
1005 struct ATS_Address *address,
1008 struct GAS_RIL_Handle *s = solver;
1009 //TODO! implement solver address add
1012 * initialize new agent
1014 * increase state vector
1020 * reiterate all addresses, create new agent if necessary and give the agent the address
1022 GNUNET_CONTAINER_multihashmap_iterate (s->addresses, &ril_init_agents_it, solver);
1024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_address_add() Added %s address for peer '%s'\n",
1025 address->plugin, GNUNET_i2s (&address->peer));
1029 * Remove an address from the solver
1031 * @param solver the solver handle
1032 * @param address the address to remove
1033 * @param session_only delete only session not whole address
1036 GAS_ril_address_delete (void *solver,
1037 struct ATS_Address *address,
1040 //TODO! implement solver address delete
1041 //TODO! delete session only
1044 * if (last address of peer)
1047 * decrease state vector
1048 * decrease knowledge matrix
1049 * decrease action vector
1051 struct GAS_RIL_Handle *s = solver;
1052 struct RIL_Peer_Agent *agent;
1054 agent = ril_get_agent(s, &address->peer);
1056 if (0 == memcmp (agent->address->addr, address->addr, address->addr_len)) //if used address deleted
1058 agent->address = NULL; //delete address
1059 GNUNET_CONTAINER_multihashmap_iterate (s->addresses, &ril_init_agents_it, solver); //put another address
1060 if (NULL == agent->address) //no other address available
1062 agent->active = GNUNET_NO;
1066 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1067 "API_address_delete() Deleted %s%s address for peer '%s'\n",
1068 session_only ? "session for " : "",
1070 GNUNET_i2s(&address->peer));
1074 * Transport properties for this address have changed
1076 * @param solver solver handle
1077 * @param address the address
1078 * @param type the ATSI type in HBO
1079 * @param abs_value the absolute value of the property
1080 * @param rel_value the normalized value
1083 GAS_ril_address_property_changed (void *solver,
1084 struct ATS_Address *address,
1089 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1090 "API_address_property_changed() Property `%s' for peer `%s' address %p changed "
1092 GNUNET_ATS_print_property_type (type),
1093 GNUNET_i2s (&address->peer),
1094 address, rel_value);
1096 * Nothing to do here, properties are considered in every reward calculation
1102 * Transport session for this address has changed
1104 * NOTE: values in addresses are already updated
1106 * @param solver solver handle
1107 * @param address the address
1108 * @param cur_session the current session
1109 * @param new_session the new session
1112 GAS_ril_address_session_changed (void *solver,
1113 struct ATS_Address *address,
1114 uint32_t cur_session,
1115 uint32_t new_session)
1117 //TODO? consider session changed in solver behaviour
1119 * Potentially add session activity as a feature in state vector
1121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_address_session_changed()\n");
1126 * Usage for this address has changed
1128 * NOTE: values in addresses are already updated
1130 * @param solver solver handle
1131 * @param address the address
1132 * @param in_use usage state
1135 GAS_ril_address_inuse_changed (void *solver,
1136 struct ATS_Address *address,
1139 //TODO! consider address_inuse_changed according to matthias' email
1141 * See matthias' email
1143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1144 "API_address_inuse_changed() Usage for %s address of peer '%s' changed to %s\n",
1146 GNUNET_i2s (&address->peer),
1147 (GNUNET_YES == in_use) ? "USED" : "UNUSED");
1151 * Network scope for this address has changed
1153 * NOTE: values in addresses are already updated
1155 * @param solver solver handle
1156 * @param address the address
1157 * @param current_network the current network
1158 * @param new_network the new network
1161 GAS_ril_address_change_network (void *solver,
1162 struct ATS_Address *address,
1163 uint32_t current_network,
1164 uint32_t new_network)
1166 struct GAS_RIL_Handle *s = solver;
1167 struct RIL_Peer_Agent *agent;
1168 struct RIL_Network *net;
1170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_address_change_network() Network type changed, moving "
1171 "%s address of peer %s from `%s' to `%s'\n",
1172 (GNUNET_YES == address->active) ? "active" : "inactive",
1173 GNUNET_i2s (&address->peer),
1174 GNUNET_ATS_print_network_type (current_network),
1175 GNUNET_ATS_print_network_type (new_network));
1177 agent = ril_get_agent(s, &address->peer);
1179 if (address->active)
1181 //remove from old network
1182 net = ril_get_network (s, current_network);
1183 net->bw_in_assigned -= agent->bw_in;
1184 net->bw_out_assigned -= agent->bw_out;
1186 //add to new network
1187 net = ril_get_network (s, new_network);
1188 net->bw_in_assigned += agent->bw_in;
1189 net->bw_out_assigned += agent->bw_out;
1191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_address_change_network() Moved %d inbound and %d "
1192 "outbound\n", agent->bw_in, agent->bw_out);
1197 * Get application feedback for a peer
1199 * @param solver the solver handle
1200 * @param application the application
1201 * @param peer the peer to change the preference for
1202 * @param scope the time interval for this feedback: [now - scope .. now]
1203 * @param kind the kind to change the preference
1204 * @param score the score
1207 GAS_ril_address_preference_feedback (void *solver,
1209 const struct GNUNET_PeerIdentity *peer,
1210 const struct GNUNET_TIME_Relative scope,
1211 enum GNUNET_ATS_PreferenceKind kind,
1214 //TODO! collect reward until next reward calculation
1215 //TODO! Find out application
1216 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1217 "API_address_preference_feedback() Peer '%s' got a feedback of %+.3f from application %s for "
1218 "preference %s for %d seconds\n",
1221 GNUNET_ATS_print_preference_type(kind),
1222 scope.rel_value_us / 1000000);
1226 * Start a bulk operation
1228 * @param solver the solver
1231 GAS_ril_bulk_start (void *solver)
1233 //TODO? consideration: keep bulk counter and stop agents during bulk
1235 * bulk counter up, but not really relevant, because there is no complete calculation of the
1236 * bandwidth assignment triggered anyway. Therefore, changes to addresses can come and go as
1237 * they want. Consideration: Step-pause during bulk-start-stop period...
1239 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_bulk_start()\n");
1244 * Bulk operation done
1247 GAS_ril_bulk_stop (void *solver)
1249 //TODO? consideration: keep bulk counter and stop agents during bulk
1251 * bulk counter down, see bulk_start()
1253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "API_bulk_stop()\n");
1257 * Get the preferred address for a specific peer
1259 * @param solver the solver handle
1260 * @param peer the identity of the peer
1262 const struct ATS_Address *
1263 GAS_ril_get_preferred_address (void *solver,
1264 const struct GNUNET_PeerIdentity *peer)
1267 * activate agent, return currently chosen address
1269 struct GAS_RIL_Handle *s = solver;
1270 struct RIL_Peer_Agent *agent;
1272 agent = ril_get_agent(s, peer);
1273 agent->active = GNUNET_YES;
1275 GNUNET_assert (NULL != agent->address);
1277 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1278 "API_get_preferred_address() Activated agent for peer '%s' with %s address\n",
1280 agent->address->plugin);
1282 return agent->address;
1286 * Stop notifying about address and bandwidth changes for this peer
1288 * @param solver the solver handle
1289 * @param peer the peer
1292 GAS_ril_stop_get_preferred_address (void *solver,
1293 const struct GNUNET_PeerIdentity *peer)
1295 struct GAS_RIL_Handle *s = solver;
1296 struct RIL_Peer_Agent *agent;
1298 agent = ril_get_agent(s, peer);
1299 agent->active = GNUNET_NO;
1301 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1302 "API_stop_get_preferred_address() Paused agent for peer '%s' with %s address\n",
1304 agent->address->plugin);
1307 /* end of gnunet-service-ats-solver_ril.c */