increase blocking on suggest in addresses, checking in solver
[oweals/gnunet.git] / src / ats / gnunet-service-ats_addresses_simplistic.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file ats/gnunet-service-ats_addresses_simplistic.h
23  * @brief ats simplistic ressource assignment
24  * @author Matthias Wachs
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet-service-ats_addresses.h"
30 #include "gnunet_statistics_service.h"
31
32 #define LOG(kind,...) GNUNET_log_from (kind, "ats-simplistic",__VA_ARGS__)
33
34 /**
35  * A handle for the simplistic solver
36  */
37 struct GAS_SIMPLISTIC_Handle
38 {
39   unsigned int active_addresses;
40   int *quota_net;
41   unsigned long long *quota_in;
42   unsigned long long *quota_out;
43 };
44
45
46 /**
47  * Init the simplistic problem solving component
48  *
49  * @param cfg configuration handle
50  * @param stats the GNUNET_STATISTICS handle
51  * @return handle for the solver on success, NULL on fail
52  */
53 void *
54 GAS_simplistic_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
55                      const struct GNUNET_STATISTICS_Handle *stats,
56                      int *network,
57                      unsigned long long *out_dest,
58                      unsigned long long *in_dest,
59                      int dest_length)
60 {
61   struct GAS_SIMPLISTIC_Handle *solver = GNUNET_malloc (sizeof (struct GAS_SIMPLISTIC_Handle));
62
63   solver->quota_net = GNUNET_malloc (dest_length * sizeof (int));
64   memcpy (solver->quota_net, network, dest_length * sizeof (int));
65
66   solver->quota_in  = GNUNET_malloc (dest_length * sizeof (unsigned long long));
67   memcpy (solver->quota_in, out_dest, dest_length * sizeof (int));
68
69   solver->quota_out = GNUNET_malloc (dest_length * sizeof (unsigned long long));
70   memcpy (solver->quota_out, out_dest, dest_length * sizeof (unsigned long long));
71
72   return solver;
73 }
74
75
76 /**
77  * Shutdown the simplistic problem solving component
78  *
79  * @param solver the respective handle to shutdown
80  */
81 void
82 GAS_simplistic_done (void *solver)
83 {
84   struct GAS_SIMPLISTIC_Handle *s = solver;
85   GNUNET_assert (s != NULL);
86   GNUNET_free (s->quota_net);
87   GNUNET_free (s->quota_in);
88   GNUNET_free (s->quota_out);
89   GNUNET_free (s);
90 }
91
92 /**
93  * Updates a single address in the solve
94  *
95  * @param solver the solver Handle
96  * @param addresses the address hashmap containing all addresses
97  * @param address the update address
98  */
99 void
100 GAS_simplistic_address_update (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address)
101 {
102
103 }
104
105
106 /**
107  * Remove an address from the solver
108  *
109  * @param solver the solver handle
110  * @param addresses the address hashmap containing all addresses
111  * @param address the address to remove
112  */
113 void
114 GAS_simplistic_address_delete (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addresses, struct ATS_Address *address)
115 {
116
117 }
118
119
120
121 /**
122  * Find a "good" address to use for a peer.  If we already have an existing
123  * address, we stick to it.  Otherwise, we pick by lowest distance and then
124  * by lowest latency.
125  *
126  * @param cls the 'struct ATS_Address**' where we store the result
127  * @param key unused
128  * @param value another 'struct ATS_Address*' to consider using
129  * @return GNUNET_OK (continue to iterate)
130  */
131 static int
132 find_address_it (void *cls, const struct GNUNET_HashCode * key, void *value)
133 {
134   struct ATS_Address **previous_p = cls;
135   struct ATS_Address *current = (struct ATS_Address *) value;
136   struct ATS_Address *previous = *previous_p;
137   struct GNUNET_TIME_Absolute now;
138
139   now = GNUNET_TIME_absolute_get();
140
141   if (current->blocked_until.abs_value == GNUNET_TIME_absolute_max (now, current->blocked_until).abs_value)
142   {
143     /* This address is blocked for suggestion */
144     LOG (GNUNET_ERROR_TYPE_DEBUG,
145                 "Address %p blocked for suggestion for %llu ms \n",
146                 current,
147                 GNUNET_TIME_absolute_get_difference(now, current->blocked_until).rel_value);
148     return GNUNET_OK;
149   }
150
151   if (NULL != previous)
152   {
153     if ((0 == strcmp (previous->plugin, "tcp")) &&
154         (0 == strcmp (current->plugin, "tcp")))
155     {
156       if ((0 != previous->addr_len) &&
157           (0 == current->addr_len))
158       {
159         /* saved address was an outbound address, but we have an inbound address */
160         *previous_p = current;
161         return GNUNET_OK;
162       }
163       if (0 == previous->addr_len)
164       {
165         /* saved address was an inbound address, so do not overwrite */
166         return GNUNET_OK;
167       }
168     }
169   }
170
171   if (NULL == previous)
172   {
173     *previous_p = current;
174     return GNUNET_OK;
175   }
176   if ((ntohl (previous->assigned_bw_in.value__) == 0) &&
177       (ntohl (current->assigned_bw_in.value__) > 0))
178   {
179     /* stick to existing connection */
180     *previous_p = current;
181     return GNUNET_OK;
182   }
183   if (previous->atsp_distance > current->atsp_distance)
184   {
185     /* user shorter distance */
186     *previous_p = current;
187     return GNUNET_OK;
188   }
189   if (previous->atsp_latency.rel_value > current->atsp_latency.rel_value)
190   {
191     /* user lower latency */
192     *previous_p = current;
193     return GNUNET_OK;
194   }
195   /* don't care */
196   return GNUNET_OK;
197 }
198
199 static int
200 update_bw_simple_it (void *cls, const struct GNUNET_HashCode * key, void *value)
201 {
202   struct GAS_SIMPLISTIC_Handle *s = cls;
203   struct ATS_Address *aa = value;
204
205   if (GNUNET_YES != aa->active)
206     return GNUNET_OK;
207   GNUNET_assert (s->active_addresses > 0);
208
209
210   /* Simple method */
211
212   aa->assigned_bw_in.value__ = htonl (UINT32_MAX / s->active_addresses);
213   aa->assigned_bw_out.value__ = htonl (UINT32_MAX / s->active_addresses);
214
215   //send_bw_notification (aa);
216
217   return GNUNET_OK;
218 }
219
220 /**
221  * Some (significant) input changed, recalculate bandwidth assignment
222  * for all peers.
223  */
224 static void
225 recalculate_assigned_bw (void *solver,
226                          struct GNUNET_CONTAINER_MultiHashMap * addresses)
227 {
228   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
229               "Recalculating bandwidth for all active connections\n");
230   GNUNET_CONTAINER_multihashmap_iterate (addresses, &update_bw_simple_it, solver);
231 }
232
233
234
235 /**
236  * Get the prefered address for a specific peer
237  *
238  * @param solver the solver handle
239  * @param addresses the address hashmap containing all addresses
240  * @param peer the identity of the peer
241  */
242 const struct ATS_Address *
243 GAS_simplistic_get_preferred_address (void *solver,
244                                struct GNUNET_CONTAINER_MultiHashMap * addresses,
245                                const struct GNUNET_PeerIdentity *peer)
246 {
247   struct GAS_SIMPLISTIC_Handle *s = solver;
248   struct ATS_Address *aa;
249
250   GNUNET_assert (s != NULL);
251   aa = NULL;
252   /* Get address with: stick to current address, lower distance, lower latency */
253   GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey,
254                                               &find_address_it, &aa);
255   if (NULL == aa)
256     LOG (GNUNET_ERROR_TYPE_DEBUG, "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer));
257   else
258   {
259     LOG (GNUNET_ERROR_TYPE_DEBUG, "Suggesting address %p for peer `%s'\n", aa, GNUNET_i2s (peer));
260
261     if (GNUNET_NO == aa->active)
262     {
263       aa->active = GNUNET_YES;
264       s->active_addresses++;
265       recalculate_assigned_bw (s, addresses);
266     }
267   }
268
269   return aa;
270 }
271
272
273 /**
274  * Changes the preferences for a peer in the problem
275  *
276  * @param solver the solver handle
277  * @param peer the peer to change the preference for
278  * @param kind the kind to change the preference
279  * @param score the score
280  */
281 void
282 GAS_simplistic_address_change_preference (void *solver,
283                                    const struct GNUNET_PeerIdentity *peer,
284                                    enum GNUNET_ATS_PreferenceKind kind,
285                                    float score)
286 {
287
288 }
289
290 /* end of gnunet-service-ats_addresses_simplistic.c */