gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r29998 - in gnunet/src: ats include


From: gnunet
Subject: [GNUnet-SVN] r29998 - in gnunet/src: ats include
Date: Tue, 8 Oct 2013 18:34:07 +0200

Author: wachs
Date: 2013-10-08 18:34:07 +0200 (Tue, 08 Oct 2013)
New Revision: 29998

Added:
   gnunet/src/ats/libgnunet_plugin_ats_mlp.c
   gnunet/src/ats/libgnunet_plugin_ats_mlp.h
   gnunet/src/ats/libgnunet_plugin_ats_proportional.c
   gnunet/src/ats/libgnunet_plugin_ats_proportional.h
   gnunet/src/include/gnunet_ats_plugin.h
Removed:
   gnunet/src/ats/gnunet-service-ats-solver_mlp.c
   gnunet/src/ats/gnunet-service-ats-solver_mlp.h
   gnunet/src/ats/gnunet-service-ats-solver_proportional.c
   gnunet/src/ats/gnunet-service-ats-solver_proportional.h
Modified:
   gnunet/src/ats/Makefile.am
   gnunet/src/ats/ats_api_performance.c
   gnunet/src/ats/gnunet-service-ats_addresses.c
   gnunet/src/ats/gnunet-service-ats_addresses.h
Log:
ats solver are now implemented as plugins

initial commit: tests pass, no crashes with tests ...


Modified: gnunet/src/ats/Makefile.am
===================================================================
--- gnunet/src/ats/Makefile.am  2013-10-08 15:43:03 UTC (rev 29997)
+++ gnunet/src/ats/Makefile.am  2013-10-08 16:34:07 UTC (rev 29998)
@@ -1,5 +1,7 @@
 AM_CPPFLAGS = -I$(top_srcdir)/src/include
 
+plugindir = $(libdir)/gnunet
+
 pkgcfgdir= $(pkgdatadir)/config.d/
 
 libexecdir= $(pkglibdir)/libexec/
@@ -17,7 +19,7 @@
 
 if HAVE_LIBGLPK
   GN_LIBGLPK = -lglpk
-  GN_MLP_SRC = gnunet-service-ats-solver_mlp.c gnunet-service-ats-solver_mlp.h
+  GN_MLP_LIB = libgnunet_plugin_ats_mlp.la
   GN_MLP_TEST = test_ats_mlp
   GN_MLP_TEST_UPDATE = test_ats_mlp_update
   GN_MLP_TEST_AVG = test_ats_mlp_averaging
@@ -32,6 +34,10 @@
 
 lib_LTLIBRARIES = libgnunetats.la
 
+plugin_LTLIBRARIES = \
+  libgnunet_plugin_ats_proportional.la \
+  libgnunet_plugin_ats_mlp.la
+
 libgnunetats_la_SOURCES = \
   ats_api_scheduling.c \
   ats_api_performance.c 
@@ -48,13 +54,14 @@
 libexec_PROGRAMS = \
  gnunet-service-ats
 
+# gnunet-service-ats-solver_proportional.c 
gnunet-service-ats-solver_proportional.h
+# $(GN_MLP_SRC)
+# gnunet-service-ats-solver_ril.c gnunet-service-ats-solver_ril.h 
+
 gnunet_service_ats_SOURCES = \
  gnunet-service-ats.c gnunet-service-ats.h\
  gnunet-service-ats_addresses.c gnunet-service-ats_addresses.h \
  gnunet-service-ats_normalization.c gnunet-service-ats_normalization.h \
- gnunet-service-ats-solver_proportional.c 
gnunet-service-ats-solver_proportional.h \
- $(GN_MLP_SRC) \
- gnunet-service-ats-solver_ril.c gnunet-service-ats-solver_ril.h \
  gnunet-service-ats_performance.c gnunet-service-ats_performance.h \
  gnunet-service-ats_scheduling.c gnunet-service-ats_scheduling.h \
  gnunet-service-ats_reservations.c gnunet-service-ats_reservations.h
@@ -62,7 +69,6 @@
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   libgnunetats.la \
-  $(GN_LIBGLPK) \
   $(GN_LIBINTL)
 gnunet_service_ats_DEPENDENCIES = \
   libgnunetats.la
@@ -121,6 +127,25 @@
 TESTS = $(check_PROGRAMS)
 endif
 
+libgnunet_plugin_ats_proportional_la_SOURCES = \
+  libgnunet_plugin_ats_proportional.c
+libgnunet_plugin_ats_proportional_la_LIBADD = \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(LTLIBINTL)
+
+if HAVE_LIBGLPK        
+endif 
+libgnunet_plugin_ats_mlp_la_SOURCES = \
+  libgnunet_plugin_ats_mlp.c
+libgnunet_plugin_ats_mlp_la_LIBADD = \
+  $(top_builddir)/src/statistics/libgnunetstatistics.la \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(GN_LIBGLPK)
+libgnunet_plugin_ats_mlp_la_LDFLAGS = \
+       $(GN_LIBGLPK) 
+ 
+
 # scheduling API tests
 
 test_ats_api_scheduling_init_SOURCES = \

Modified: gnunet/src/ats/ats_api_performance.c
===================================================================
--- gnunet/src/ats/ats_api_performance.c        2013-10-08 15:43:03 UTC (rev 
29997)
+++ gnunet/src/ats/ats_api_performance.c        2013-10-08 16:34:07 UTC (rev 
29998)
@@ -1,33 +1,32 @@
 /*
-     This file is part of GNUnet.
-     (C) 2010,2011 Christian Grothoff (and other contributing authors)
+ This file is part of GNUnet.
+ (C) 2010,2011 Christian Grothoff (and other contributing authors)
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
 
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
 
-     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.
-*/
+ 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.
+ */
 /**
  * @file ats/ats_api_performance.c
  * @brief automatic transport selection and outbound bandwidth determination
  * @author Christian Grothoff
  * @author Matthias Wachs
-  */
+ */
 #include "platform.h"
 #include "gnunet_ats_service.h"
 #include "ats.h"
 
-
 /**
  * Message in linked list we should send to the ATS service.  The
  * actual binary message follows this struct.
@@ -56,7 +55,6 @@
   int is_init;
 };
 
-
 /**
  * Linked list of pending reservations.
  */
@@ -104,7 +102,6 @@
   int undo;
 };
 
-
 /**
  * Linked list of pending reservations.
  */
@@ -157,8 +154,6 @@
   uint32_t id;
 };
 
-
-
 /**
  * ATS Handle to obtain and/or modify performance information.
  */
@@ -215,7 +210,6 @@
    */
   struct GNUNET_ATS_AddressListHandle *addresslist_tail;
 
-
   /**
    * Current request for transmission to ATS.
    */
@@ -237,7 +231,6 @@
   uint32_t id;
 };
 
-
 /**
  * Re-establish the connection to the ATS service.
  *
@@ -246,7 +239,6 @@
 static void
 reconnect (struct GNUNET_ATS_PerformanceHandle *ph);
 
-
 /**
  * Re-establish the connection to the ATS service.
  *
@@ -262,7 +254,6 @@
   reconnect (ph);
 }
 
-
 /**
  * Transmit messages from the message queue to the service
  * (if there are any, and if we are not already trying).
@@ -272,7 +263,6 @@
 static void
 do_transmit (struct GNUNET_ATS_PerformanceHandle *ph);
 
-
 /**
  * Type of a function to call when we receive a message
  * from the service.
@@ -307,14 +297,13 @@
     memcpy (&cbuf[ret], &p[1], p->size);
     ret += p->size;
     size -= p->size;
-    GNUNET_CONTAINER_DLL_remove (ph->pending_head, ph->pending_tail, p);
-    GNUNET_free (p);
+    GNUNET_CONTAINER_DLL_remove(ph->pending_head, ph->pending_tail, p);
+    GNUNET_free(p);
   }
   do_transmit (ph);
   return ret;
 }
 
-
 /**
  * Transmit messages from the message queue to the service
  * (if there are any, and if we are not already trying).
@@ -331,15 +320,11 @@
   if (NULL == (p = ph->pending_head))
     return;
   if (NULL == ph->client)
-    return;                     /* currently reconnecting */
-  ph->th =
-      GNUNET_CLIENT_notify_transmit_ready (ph->client, p->size,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_YES, 
&transmit_message_to_ats,
-                                           ph);
+    return; /* currently reconnecting */
+  ph->th = GNUNET_CLIENT_notify_transmit_ready (ph->client, p->size,
+      GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_message_to_ats, ph);
 }
 
-
 /**
  * We received a peer information message.  Validate and process it.
  *
@@ -349,7 +334,7 @@
  */
 static int
 process_pi_message (struct GNUNET_ATS_PerformanceHandle *ph,
-                    const struct GNUNET_MessageHeader *msg)
+    const struct GNUNET_MessageHeader *msg)
 {
   const struct PeerInformationMessage *pi;
   const struct GNUNET_ATS_Information *atsi;
@@ -361,9 +346,9 @@
   uint32_t ats_count;
   int addr_active;
 
-  if (ntohs (msg->size) < sizeof (struct PeerInformationMessage))
+  if (ntohs (msg->size) < sizeof(struct PeerInformationMessage))
   {
-    GNUNET_break (0);
+    GNUNET_break(0);
     return GNUNET_SYSERR;
   }
 
@@ -375,31 +360,31 @@
   atsi = (const struct GNUNET_ATS_Information *) &pi[1];
   plugin_address = (const char *) &atsi[ats_count];
   plugin_name = &plugin_address[plugin_address_length];
-  if ((plugin_address_length + plugin_name_length +
-       ats_count * sizeof (struct GNUNET_ATS_Information) +
-       sizeof (struct PeerInformationMessage) != ntohs (msg->size)) ||
-      (ats_count >
-       GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information))
+  if ((plugin_address_length + plugin_name_length
+      + ats_count * sizeof(struct GNUNET_ATS_Information)
+      + sizeof(struct PeerInformationMessage) != ntohs (msg->size))
+      || (ats_count
+          > GNUNET_SERVER_MAX_MESSAGE_SIZE
+              / sizeof(struct GNUNET_ATS_Information))
       || (plugin_name[plugin_name_length - 1] != '\0'))
   {
-    GNUNET_break (0);
+    GNUNET_break(0);
     return GNUNET_SYSERR;
   }
 
   if (NULL != ph->addr_info_cb)
   {
-         address.peer = pi->peer;
-         address.address = plugin_address;
-         address.address_length = plugin_address_length;
-         address.transport_name = plugin_name;
+    address.peer = pi->peer;
+    address.address = plugin_address;
+    address.address_length = plugin_address_length;
+    address.transport_name = plugin_name;
 
-               ph->addr_info_cb (ph->addr_info_cb_cls, &address, addr_active, 
pi->bandwidth_out, pi->bandwidth_in,
-              atsi, ats_count);
+    ph->addr_info_cb (ph->addr_info_cb_cls, &address, addr_active,
+        pi->bandwidth_out, pi->bandwidth_in, atsi, ats_count);
   }
   return GNUNET_OK;
 }
 
-
 /**
  * We received a reservation result message.  Validate and process it.
  *
@@ -409,47 +394,46 @@
  */
 static int
 process_rr_message (struct GNUNET_ATS_PerformanceHandle *ph,
-                    const struct GNUNET_MessageHeader *msg)
+    const struct GNUNET_MessageHeader *msg)
 {
   const struct ReservationResultMessage *rr;
   struct GNUNET_ATS_ReservationContext *rc;
   int32_t amount;
 
-  if (ntohs (msg->size) < sizeof (struct ReservationResultMessage))
+  if (ntohs (msg->size) < sizeof(struct ReservationResultMessage))
   {
-    GNUNET_break (0);
+    GNUNET_break(0);
     return GNUNET_SYSERR;
   }
   rr = (const struct ReservationResultMessage *) msg;
   amount = ntohl (rr->amount);
   rc = ph->reservation_head;
-  if (0 != memcmp (&rr->peer, &rc->peer, sizeof (struct GNUNET_PeerIdentity)))
+  if (0 != memcmp (&rr->peer, &rc->peer, sizeof(struct GNUNET_PeerIdentity)))
   {
-    GNUNET_break (0);
+    GNUNET_break(0);
     return GNUNET_SYSERR;
   }
-  GNUNET_CONTAINER_DLL_remove (ph->reservation_head, ph->reservation_tail, rc);
-  if ((amount == 0) || (rc->rcb != NULL))
+  GNUNET_CONTAINER_DLL_remove(ph->reservation_head, ph->reservation_tail, rc);
+  if ((amount == 0) || (rc->rcb != NULL ))
   {
     /* tell client if not cancelled */
-    if (rc->rcb != NULL)
+    if (rc->rcb != NULL )
       rc->rcb (rc->rcb_cls, &rr->peer, amount,
-               GNUNET_TIME_relative_ntoh (rr->res_delay));
-    GNUNET_free (rc);
+          GNUNET_TIME_relative_ntoh (rr->res_delay));
+    GNUNET_free(rc);
     return GNUNET_OK;
   }
   /* amount non-zero, but client cancelled, consider undo! */
   if (GNUNET_YES != rc->undo)
   {
-    GNUNET_free (rc);
-    return GNUNET_OK;           /* do not try to undo failed undos or negative 
amounts */
+    GNUNET_free(rc);
+    return GNUNET_OK; /* do not try to undo failed undos or negative amounts */
   }
-  GNUNET_free (rc);
-  (void) GNUNET_ATS_reserve_bandwidth (ph, &rr->peer, -amount, NULL, NULL);
+  GNUNET_free(rc);
+  (void) GNUNET_ATS_reserve_bandwidth (ph, &rr->peer, -amount, NULL, NULL );
   return GNUNET_OK;
 }
 
-
 /**
  * We received a reservation result message.  Validate and process it.
  *
@@ -459,7 +443,7 @@
  */
 static int
 process_ar_message (struct GNUNET_ATS_PerformanceHandle *ph,
-                    const struct GNUNET_MessageHeader *msg)
+    const struct GNUNET_MessageHeader *msg)
 {
   const struct PeerInformationMessage *pi;
   struct GNUNET_ATS_AddressListHandle *alh;
@@ -476,13 +460,13 @@
   uint32_t active;
   uint32_t id;
 
-  if (ntohs (msg->size) < sizeof (struct PeerInformationMessage))
+  if (ntohs (msg->size) < sizeof(struct PeerInformationMessage))
   {
-    GNUNET_break (0);
+    GNUNET_break(0);
     return GNUNET_SYSERR;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-      _("Received %s message\n"), "ATS_ADDRESSLIST_RESPONSE");
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Received %s message\n"),
+      "ATS_ADDRESSLIST_RESPONSE");
 
   pi = (const struct PeerInformationMessage *) msg;
   id = ntohl (pi->id);
@@ -493,49 +477,47 @@
   atsi = (const struct GNUNET_ATS_Information *) &pi[1];
   plugin_address = (const char *) &atsi[ats_count];
   plugin_name = &plugin_address[plugin_address_length];
-  if ((plugin_address_length + plugin_name_length +
-       ats_count * sizeof (struct GNUNET_ATS_Information) +
-       sizeof (struct PeerInformationMessage) != ntohs (msg->size)) ||
-      (ats_count >
-       GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information))
+  if ((plugin_address_length + plugin_name_length
+      + ats_count * sizeof(struct GNUNET_ATS_Information)
+      + sizeof(struct PeerInformationMessage) != ntohs (msg->size))
+      || (ats_count
+          > GNUNET_SERVER_MAX_MESSAGE_SIZE
+              / sizeof(struct GNUNET_ATS_Information))
       || (plugin_name[plugin_name_length - 1] != '\0'))
   {
-    GNUNET_break (0);
+    GNUNET_break(0);
     return GNUNET_SYSERR;
   }
 
   next = ph->addresslist_head;
   while (NULL != (alh = next))
   {
-      next = alh->next;
-      if (alh->id == id)
-        break;
+    next = alh->next;
+    if (alh->id == id)
+      break;
   }
   if (NULL == alh)
   {
-      /* was canceled */
-      return GNUNET_SYSERR;
+    /* was canceled */
+    return GNUNET_SYSERR;
   }
 
-  memset (&allzeros, '\0', sizeof (allzeros));
-  if ((0 == memcmp (&allzeros, &pi->peer, sizeof (allzeros))) &&
-      (0 == plugin_name_length) &&
-      (0 == plugin_address_length) &&
-      (0 == ats_count))
+  memset (&allzeros, '\0', sizeof(allzeros));
+  if ((0 == memcmp (&allzeros, &pi->peer, sizeof(allzeros)))
+      && (0 == plugin_name_length) && (0 == plugin_address_length)
+      && (0 == ats_count))
   {
-      /* Done */
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-          _("Received last message for %s \n"), "ATS_ADDRESSLIST_RESPONSE");
-      bandwidth_zero.value__ = htonl (0);
-      if (NULL != alh->cb)
-        alh->cb (ph->addr_info_cb_cls,
-              NULL,
-              GNUNET_NO,
-              bandwidth_zero, bandwidth_zero,
-              NULL, 0);
-      GNUNET_CONTAINER_DLL_remove (ph->addresslist_head, ph->addresslist_tail, 
alh);
-      GNUNET_free (alh);
-      return GNUNET_OK;
+    /* Done */
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Received last message for %s \n"),
+        "ATS_ADDRESSLIST_RESPONSE");
+    bandwidth_zero.value__ = htonl (0);
+    if (NULL != alh->cb)
+      alh->cb (ph->addr_info_cb_cls, NULL, GNUNET_NO, bandwidth_zero,
+          bandwidth_zero, NULL, 0);
+    GNUNET_CONTAINER_DLL_remove(ph->addresslist_head, ph->addresslist_tail,
+        alh);
+    GNUNET_free(alh);
+    return GNUNET_OK;
   }
 
   address.peer = pi->peer;
@@ -546,16 +528,12 @@
   if ((GNUNET_YES == alh->all_addresses) || (GNUNET_YES == active))
   {
     if (NULL != alh->cb)
-      alh->cb (ph->addr_info_cb_cls,
-            &address,
-            active,
-            pi->bandwidth_out, pi->bandwidth_in,
-            atsi, ats_count);
+      alh->cb (ph->addr_info_cb_cls, &address, active, pi->bandwidth_out,
+          pi->bandwidth_in, atsi, ats_count);
   }
   return GNUNET_OK;
 }
 
-
 /**
  * Type of a function to call when we receive a message
  * from the service.
@@ -585,26 +563,23 @@
       goto reconnect;
     break;
   default:
-    GNUNET_break (0);
+    GNUNET_break(0);
     goto reconnect;
   }
   GNUNET_CLIENT_receive (ph->client, &process_ats_message, ph,
-                         GNUNET_TIME_UNIT_FOREVER_REL);
+      GNUNET_TIME_UNIT_FOREVER_REL);
   return;
-reconnect:
-  if (NULL != ph->th)
+  reconnect: if (NULL != ph->th)
   {
     GNUNET_CLIENT_notify_transmit_ready_cancel (ph->th);
     ph->th = NULL;
   }
   GNUNET_CLIENT_disconnect (ph->client);
   ph->client = NULL;
-  ph->task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task,
-                                    ph);
+  ph->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
+      &reconnect_task, ph);
 }
 
-
 /**
  * Re-establish the connection to the ATS service.
  *
@@ -616,30 +591,28 @@
   struct PendingMessage *p;
   struct ClientStartMessage *init;
 
-  GNUNET_assert (NULL == ph->client);
+  GNUNET_assert(NULL == ph->client);
   ph->client = GNUNET_CLIENT_connect ("ats", ph->cfg);
-  GNUNET_assert (NULL != ph->client);
+  GNUNET_assert(NULL != ph->client);
   GNUNET_CLIENT_receive (ph->client, &process_ats_message, ph,
-                          GNUNET_TIME_UNIT_FOREVER_REL);
+      GNUNET_TIME_UNIT_FOREVER_REL);
   if ((NULL == (p = ph->pending_head)) || (GNUNET_YES != p->is_init))
   {
     p = GNUNET_malloc (sizeof (struct PendingMessage) +
-                       sizeof (struct ClientStartMessage));
-    p->size = sizeof (struct ClientStartMessage);
+        sizeof (struct ClientStartMessage));
+    p->size = sizeof(struct ClientStartMessage);
     p->is_init = GNUNET_YES;
     init = (struct ClientStartMessage *) &p[1];
     init->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_START);
-    init->header.size = htons (sizeof (struct ClientStartMessage));
-    init->start_flag =
-        htonl ((NULL ==ph->addr_info_cb) ?
-                       START_FLAG_PERFORMANCE_NO_PIC : 
START_FLAG_PERFORMANCE_WITH_PIC);
-    GNUNET_CONTAINER_DLL_insert (ph->pending_head, ph->pending_tail, p);
+    init->header.size = htons (sizeof(struct ClientStartMessage));
+    init->start_flag = htonl (
+        (NULL == ph->addr_info_cb) ?
+            START_FLAG_PERFORMANCE_NO_PIC : START_FLAG_PERFORMANCE_WITH_PIC);
+    GNUNET_CONTAINER_DLL_insert(ph->pending_head, ph->pending_tail, p);
   }
   do_transmit (ph);
 }
 
-
-
 /**
  * Get handle to access performance API of the ATS subsystem.
  *
@@ -651,8 +624,7 @@
  */
 struct GNUNET_ATS_PerformanceHandle *
 GNUNET_ATS_performance_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                             GNUNET_ATS_AddressInformationCallback 
addr_info_cb,
-                             void *addr_info_cb_cls)
+    GNUNET_ATS_AddressInformationCallback addr_info_cb, void *addr_info_cb_cls)
 {
   struct GNUNET_ATS_PerformanceHandle *ph;
 
@@ -660,7 +632,7 @@
   ph->cfg = cfg;
   ph->addr_info_cb = addr_info_cb;
   ph->addr_info_cb_cls = addr_info_cb_cls;
-  ph->id  = 0;
+  ph->id = 0;
   reconnect (ph);
   return ph;
 }
@@ -679,21 +651,20 @@
 
   while (NULL != (p = ph->pending_head))
   {
-    GNUNET_CONTAINER_DLL_remove (ph->pending_head, ph->pending_tail, p);
-    GNUNET_free (p);
+    GNUNET_CONTAINER_DLL_remove(ph->pending_head, ph->pending_tail, p);
+    GNUNET_free(p);
   }
   while (NULL != (alh = ph->addresslist_head))
   {
-    GNUNET_CONTAINER_DLL_remove (ph->addresslist_head, ph->addresslist_tail,
-                                 alh);
-    GNUNET_free (alh);
+    GNUNET_CONTAINER_DLL_remove(ph->addresslist_head, ph->addresslist_tail,
+        alh);
+    GNUNET_free(alh);
   }
   while (NULL != (rc = ph->reservation_head))
   {
-    GNUNET_CONTAINER_DLL_remove (ph->reservation_head, ph->reservation_tail,
-                                 rc);
-    GNUNET_break (NULL == rc->rcb);
-    GNUNET_free (rc);
+    GNUNET_CONTAINER_DLL_remove(ph->reservation_head, ph->reservation_tail, 
rc);
+    GNUNET_break(NULL == rc->rcb);
+    GNUNET_free(rc);
   }
 
   if (GNUNET_SCHEDULER_NO_TASK != ph->task)
@@ -706,10 +677,9 @@
     GNUNET_CLIENT_disconnect (ph->client);
     ph->client = NULL;
   }
-  GNUNET_free (ph);
+  GNUNET_free(ph);
 }
 
-
 /**
  * Reserve inbound bandwidth from the given peer.  ATS will look at
  * the current amount of traffic we receive from the peer and ensure
@@ -726,9 +696,8 @@
  */
 struct GNUNET_ATS_ReservationContext *
 GNUNET_ATS_reserve_bandwidth (struct GNUNET_ATS_PerformanceHandle *ph,
-                              const struct GNUNET_PeerIdentity *peer,
-                              int32_t amount,
-                              GNUNET_ATS_ReservationCallback rcb, void 
*rcb_cls)
+    const struct GNUNET_PeerIdentity *peer, int32_t amount,
+    GNUNET_ATS_ReservationCallback rcb, void *rcb_cls)
 {
   struct GNUNET_ATS_ReservationContext *rc;
   struct PendingMessage *p;
@@ -739,26 +708,24 @@
   rc->peer = *peer;
   rc->rcb = rcb;
   rc->rcb_cls = rcb_cls;
-  if ((rcb != NULL) && (amount > 0))
-    rc->undo = GNUNET_YES;
-  GNUNET_CONTAINER_DLL_insert_tail (ph->reservation_head, ph->reservation_tail,
-                                    rc);
+  if ((rcb != NULL )&& (amount > 0))rc->undo = GNUNET_YES;
+  GNUNET_CONTAINER_DLL_insert_tail(ph->reservation_head, ph->reservation_tail,
+      rc);
 
   p = GNUNET_malloc (sizeof (struct PendingMessage) +
-                     sizeof (struct ReservationRequestMessage));
-  p->size = sizeof (struct ReservationRequestMessage);
+      sizeof (struct ReservationRequestMessage));
+  p->size = sizeof(struct ReservationRequestMessage);
   p->is_init = GNUNET_NO;
   m = (struct ReservationRequestMessage *) &p[1];
   m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST);
-  m->header.size = htons (sizeof (struct ReservationRequestMessage));
+  m->header.size = htons (sizeof(struct ReservationRequestMessage));
   m->amount = htonl (amount);
   m->peer = *peer;
-  GNUNET_CONTAINER_DLL_insert_tail (ph->pending_head, ph->pending_tail, p);
+  GNUNET_CONTAINER_DLL_insert_tail(ph->pending_head, ph->pending_tail, p);
   do_transmit (ph);
   return rc;
 }
 
-
 /**
  * Cancel request for reserving bandwidth.
  *
@@ -783,23 +750,22 @@
  * @return ats performance context
  */
 struct GNUNET_ATS_AddressListHandle*
-GNUNET_ATS_performance_list_addresses (struct GNUNET_ATS_PerformanceHandle 
*handle,
-                                       const struct GNUNET_PeerIdentity *peer,
-                                       int all,
-                                       GNUNET_ATS_AddressInformationCallback 
infocb,
-                                       void *infocb_cls)
+GNUNET_ATS_performance_list_addresses (
+    struct GNUNET_ATS_PerformanceHandle *handle,
+    const struct GNUNET_PeerIdentity *peer, int all,
+    GNUNET_ATS_AddressInformationCallback infocb, void *infocb_cls)
 {
   struct GNUNET_ATS_AddressListHandle *alh;
   struct PendingMessage *p;
   struct AddressListRequestMessage *m;
 
-  GNUNET_assert (NULL != handle);
+  GNUNET_assert(NULL != handle);
   if (NULL == infocb)
-    return NULL;
+    return NULL ;
 
   alh = GNUNET_malloc (sizeof (struct GNUNET_ATS_AddressListHandle));
   alh->id = handle->id;
-  handle->id ++;
+  handle->id++;
   alh->cb = infocb;
   alh->cb_cls = infocb_cls;
   alh->ph = handle;
@@ -808,49 +774,51 @@
     alh->all_peers = GNUNET_YES;
   else
   {
-      alh->all_peers = GNUNET_NO;
-      alh->peer = (*peer);
+    alh->all_peers = GNUNET_NO;
+    alh->peer = (*peer);
   }
 
-  GNUNET_CONTAINER_DLL_insert (handle->addresslist_head, 
handle->addresslist_tail, alh);
+  GNUNET_CONTAINER_DLL_insert(handle->addresslist_head,
+      handle->addresslist_tail, alh);
 
   p = GNUNET_malloc (sizeof (struct PendingMessage) +
-                     sizeof (struct AddressListRequestMessage));
-  p->size = sizeof (struct AddressListRequestMessage);
+      sizeof (struct AddressListRequestMessage));
+  p->size = sizeof(struct AddressListRequestMessage);
   m = (struct AddressListRequestMessage *) &p[1];
   m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST);
-  m->header.size = htons (sizeof (struct AddressListRequestMessage));
+  m->header.size = htons (sizeof(struct AddressListRequestMessage));
   m->all = htonl (all);
   m->id = htonl (alh->id);
   if (NULL != peer)
     m->peer = *peer;
   else
   {
-      memset (&m->peer, '\0', sizeof (struct GNUNET_PeerIdentity));
+    memset (&m->peer, '\0', sizeof(struct GNUNET_PeerIdentity));
   }
-  GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, 
handle->pending_tail, p);
+  GNUNET_CONTAINER_DLL_insert_tail(handle->pending_head, handle->pending_tail,
+      p);
 
   do_transmit (handle);
 
   return alh;
 }
 
-
 /**
  * Cancel a pending address listing operation
  *
  * @param handle the GNUNET_ATS_AddressListHandle handle to cancel
  */
 void
-GNUNET_ATS_performance_list_addresses_cancel (struct 
GNUNET_ATS_AddressListHandle *handle)
+GNUNET_ATS_performance_list_addresses_cancel (
+    struct GNUNET_ATS_AddressListHandle *handle)
 {
-  GNUNET_assert (NULL != handle);
+  GNUNET_assert(NULL != handle);
 
-  GNUNET_CONTAINER_DLL_remove (handle->ph->addresslist_head, 
handle->ph->addresslist_tail, handle);
-  GNUNET_free (handle);
+  GNUNET_CONTAINER_DLL_remove(handle->ph->addresslist_head,
+      handle->ph->addresslist_tail, handle);
+  GNUNET_free(handle);
 }
 
-
 /**
  * Convert a GNUNET_ATS_PreferenceType to a string
  *
@@ -863,10 +831,9 @@
   char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
   if (type < GNUNET_ATS_PreferenceCount)
     return prefs[type];
-  return NULL;
+  return NULL ;
 }
 
-
 /**
  * Change preferences for the given peer. Preference changes are forgotten if 
peers
  * disconnect.
@@ -876,8 +843,9 @@
  * @param ... 0-terminated specification of the desired changes
  */
 void
-GNUNET_ATS_performance_change_preference (struct GNUNET_ATS_PerformanceHandle 
*ph,
-                              const struct GNUNET_PeerIdentity *peer, ...)
+GNUNET_ATS_performance_change_preference (
+    struct GNUNET_ATS_PerformanceHandle *ph,
+    const struct GNUNET_PeerIdentity *peer, ...)
 {
   struct PendingMessage *p;
   struct ChangePreferenceMessage *m;
@@ -888,9 +856,9 @@
   enum GNUNET_ATS_PreferenceKind kind;
 
   count = 0;
-  va_start (ap, peer);
-  while (GNUNET_ATS_PREFERENCE_END !=
-         (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind)))
+  va_start(ap, peer);
+  while (GNUNET_ATS_PREFERENCE_END != (kind =
+      va_arg (ap, enum GNUNET_ATS_PreferenceKind) ))
   {
     switch (kind)
     {
@@ -905,13 +873,12 @@
 
       break;
     default:
-      GNUNET_assert (0);
+      GNUNET_assert(0);
     }
   }
-  va_end (ap);
-  msize =
-      count * sizeof (struct PreferenceInformation) +
-      sizeof (struct ChangePreferenceMessage);
+  va_end(ap);
+  msize = count * sizeof(struct PreferenceInformation)
+      + sizeof(struct ChangePreferenceMessage);
   p = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
   p->size = msize;
   p->is_init = GNUNET_NO;
@@ -922,9 +889,9 @@
   m->peer = *peer;
   pi = (struct PreferenceInformation *) &m[1];
   count = 0;
-  va_start (ap, peer);
-  while (GNUNET_ATS_PREFERENCE_END !=
-         (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind)))
+  va_start(ap, peer);
+  while (GNUNET_ATS_PREFERENCE_END != (kind =
+      va_arg (ap, enum GNUNET_ATS_PreferenceKind) ))
   {
     pi[count].preference_kind = htonl (kind);
     switch (kind)
@@ -940,11 +907,11 @@
       count++;
       break;
     default:
-      GNUNET_assert (0);
+      GNUNET_assert(0);
     }
   }
-  va_end (ap);
-  GNUNET_CONTAINER_DLL_insert_tail (ph->pending_head, ph->pending_tail, p);
+  va_end(ap);
+  GNUNET_CONTAINER_DLL_insert_tail(ph->pending_head, ph->pending_tail, p);
   do_transmit (ph);
 }
 
@@ -959,8 +926,8 @@
  */
 void
 GNUNET_ATS_performance_give_feedback (struct GNUNET_ATS_PerformanceHandle *ph,
-                                                                               
                                                                        const 
struct GNUNET_PeerIdentity *peer,
-                                                                               
                                                                        const 
struct GNUNET_TIME_Relative scope, ...)
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_TIME_Relative scope, ...)
 {
   struct PendingMessage *p;
   struct FeedbackPreferenceMessage *m;
@@ -971,9 +938,9 @@
   enum GNUNET_ATS_PreferenceKind kind;
 
   count = 0;
-  va_start (ap, scope);
-  while (GNUNET_ATS_PREFERENCE_END !=
-         (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind)))
+  va_start(ap, scope);
+  while (GNUNET_ATS_PREFERENCE_END != (kind =
+      va_arg (ap, enum GNUNET_ATS_PreferenceKind) ))
   {
     switch (kind)
     {
@@ -988,13 +955,12 @@
 
       break;
     default:
-      GNUNET_assert (0);
+      GNUNET_assert(0);
     }
   }
-  va_end (ap);
-  msize =
-      count * sizeof (struct PreferenceInformation) +
-      sizeof (struct FeedbackPreferenceMessage);
+  va_end(ap);
+  msize = count * sizeof(struct PreferenceInformation)
+      + sizeof(struct FeedbackPreferenceMessage);
   p = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
   p->size = msize;
   p->is_init = GNUNET_NO;
@@ -1006,9 +972,9 @@
   m->peer = *peer;
   pi = (struct PreferenceInformation *) &m[1];
   count = 0;
-  va_start (ap, scope);
-  while (GNUNET_ATS_PREFERENCE_END !=
-         (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind)))
+  va_start(ap, scope);
+  while (GNUNET_ATS_PREFERENCE_END != (kind =
+      va_arg (ap, enum GNUNET_ATS_PreferenceKind) ))
   {
     pi[count].preference_kind = htonl (kind);
     switch (kind)
@@ -1024,11 +990,11 @@
       count++;
       break;
     default:
-      GNUNET_assert (0);
+      GNUNET_assert(0);
     }
   }
-  va_end (ap);
-  GNUNET_CONTAINER_DLL_insert_tail (ph->pending_head, ph->pending_tail, p);
+  va_end(ap);
+  GNUNET_CONTAINER_DLL_insert_tail(ph->pending_head, ph->pending_tail, p);
   do_transmit (ph);
 }
 

Deleted: gnunet/src/ats/gnunet-service-ats-solver_mlp.c
===================================================================
--- gnunet/src/ats/gnunet-service-ats-solver_mlp.c      2013-10-08 15:43:03 UTC 
(rev 29997)
+++ gnunet/src/ats/gnunet-service-ats-solver_mlp.c      2013-10-08 16:34:07 UTC 
(rev 29998)
@@ -1,2119 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     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.
-*/
-
-/**
- * @file ats/gnunet-service-ats-solver_mlp.c
- * @brief ats mlp problem solver
- * @author Matthias Wachs
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet-service-ats-solver_mlp.h"
-#include "gnunet_statistics_service.h"
-#include "glpk.h"
-
-/**
- *
- * NOTE: Do not modify this documentation. This documentation is based on
- * gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex
- * use build_txt.sh to generate plaintext output
- *
- *    The MLP solver (mlp) tries to finds an optimal bandwidth assignmentby
- *    optimizing an mixed integer programming problem. The MLP solver uses a
- *    number of constraints to find the best adddress for a peer and an optimal
- *    bandwidth assignment. mlp uses the GNU Linear Programming Kit to solve 
the
- *    MLP problem.
- *
- *    We defined a constraint system to find an optimal bandwidth assignment.
- *    This constraint system uses as an input data addresses, bandwidth quotas,
- *    preferences and quality values. This constraint system is stored in an
- *    matrix based equotation system.
- *
- *   5 Using GLPK
- *
- *    A (M)LP problem consists of a target function to optimizes, constraints
- *    and rows and columns. FIXME GLP uses three arrays to index the matrix: 
two
- *    integer arrays storing the row and column indices in the matrix and an
- *    float array to store the coeeficient.
- *
- *    To solve the problem we first find an initial solution for the LP problem
- *    using the LP solver and then find an MLP solution based on this solution
- *    using the MLP solver.
- *
- *    Solving (M)LP problems has the property that finding an initial solution
- *    for the LP problem is computationally expensive and finding the MLP
- *    solution is cheaper. This is especially interesting an existing LP
- *    solution can be reused if only coefficients in the matrix have changed
- *    (addresses updated). Only when the problem size changes (addresses added
- *    or deleted) a new LP solution has to be found.
- *
- *    Intended usage
- *    The mlp solver solves the bandwidth assignment problem only on demand 
when
- *    an address suggestion is requested. When an address is requested mlp the
- *    solves the mlp problem and if the active address or the bandwidth 
assigned
- *    changes it calls the callback to addresses. The mlp solver gets notified
- *    about new addresses (adding sessions), removed addresses (address
- *    deletions) and address updates. To benefit from the mlp properties
- *    mentioned in section 5 the solver rembers if since the last solution
- *    addresses were added or deleted (problem size changed, problem has to be
- *    rebuild and solved from sratch) or if addresses were updated and the
- *    existing solution can be reused.
- *
- *     5.1 Input data
- *
- *    The quotas for each network segment are passed by addresses. MLP can be
- *    adapted using configuration settings and uses the following parameters:
- *      * MLP_MAX_DURATION:
- *        Maximum duration for a MLP solution procees (default: 3 sec.)
- *      * MLP_MAX_DURATION:
- *        Maximum number of iterations for a MLP solution process (default:
- *        1024)
- *      * MLP_MIN_CONNECTIONS:
- *        Minimum number of desired connections (default: 4)
- *      * MLP_MIN_BANDWIDTH:
- *        Minimum amount of bandwidth assigned to an address (default: 1024)
- *      * MLP_COEFFICIENT_D:
- *        Diversity coefficient (default: 1.0)
- *      * MLP_COEFFICIENT_R:
- *        Relativity coefficient (default: 1.0)
- *      * MLP_COEFFICIENT_U:
- *        Utilization coefficient (default: 1.0)
- *      * MLP_COEFFICIENT_D:
- *        Diversity coefficient (default: 1.0)
- *      * MLP_COEFFICIENT_QUALITY_DELAY:
- *        Quality delay coefficient (default: 1.0)
- *      * MLP_COEFFICIENT_QUALITY_DISTANCE:
- *        Quality distance coefficient (default: 1.0)
- *      * MLP_COEFFICIENT_QUALITY_DISTANCE:
- *        Quality distance coefficient (default: 1.0)
- *      * MLP_COEFFICIENT_QUALITY_DISTANCE:
- *        Quality distance coefficient (default: 1.0)
- *      * MLP_COEFFICIENT_QUALITY_DISTANCE:
- *        Quality distance coefficient (default: 1.0)
- *
- *     5.2 Data structures used
- *
- *    mlp has for each known peer a struct ATS_Peer containing information 
about
- *    a specific peer. The address field solver_information contains 
information
- *    about the mlp properties of this address.
- *
- *     5.3 Initializing
- *
- *    During initialization mlp initializes the GLPK libray used to solve the
- *    MLP problem: it initializes the glpk environment and creates an initial 
LP
- *    problem. Next it loads the configuration values from the configuration or
- *    uses the default values configured in -addresses_mlp.h. The quotas used
- *    are given by addresses but may have to be adjusted. mlp uses a upper 
limit
- *    for the bandwidth assigned called BIG M and a minimum amount of bandwidth
- *    an address gets assigned as well as a minium desired number of
- *    connections. If the configured quota is bigger than BIG M, it is reduced
- *    to BIG M. If the configured quota is smaller than MLP_MIN_CONNECTIONS
- *    *MLP_MIN_BANDWIDTH it is increased to this value.
- *
- *     5.4 Shutdown
-
- */
-
-#define LOG(kind,...) GNUNET_log_from (kind, "ats-mlp",__VA_ARGS__)
-
-/**
- * Print debug output for mlp problem creation
- */
-#define DEBUG_MLP_PROBLEM_CREATION GNUNET_NO
-
-/**
- * Enable GLPK verbose output
- */
-#define VERBOSE_GLPK GNUNET_NO
-
-/**
- * Maximize bandwidth assigned
- *
- * This option can be used to test if problem can be solved at all without
- * optimizing for utility, diversity or relativity
- *
- */
-#define MAXIMIZE_FOR_BANDWIDTH_ASSIGNED GNUNET_NO
-
-/**
- * Intercept GLPK terminal output
- * @param info the mlp handle
- * @param s the string to print
- * @return 0: glpk prints output on terminal, 0 != surpress output
- */
-static int
-mlp_term_hook (void *info, const char *s)
-{
-  /* Not needed atm struct MLP_information *mlp = info; */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s", s);
-  return 1;
-}
-
-
-/**
- * Reset peers for next problem creation
- *
- * @param cls not used
- * @param key the key
- * @param value ATS_Peer
- * @return GNUNET_OK
- */
-static int
-reset_peers (void *cls,
-            const struct GNUNET_PeerIdentity *key,
-            void *value)
- {
-   struct ATS_Peer *peer = value;
-   peer->processed = GNUNET_NO;
-   return GNUNET_OK;
- }
-
-/**
- * Delete the MLP problem and free the constrain matrix
- *
- * @param mlp the MLP handle
- */
-static void
-mlp_delete_problem (struct GAS_MLP_Handle *mlp)
-{
-  int c;
-  if (mlp == NULL)
-    return;
-  if (mlp->p.prob != NULL)
-  {
-    glp_delete_prob(mlp->p.prob);
-    mlp->p.prob = NULL;
-  }
-
-  /* delete row index */
-  if (mlp->p.ia != NULL)
-  {
-    GNUNET_free (mlp->p.ia);
-    mlp->p.ia = NULL;
-  }
-
-  /* delete column index */
-  if (mlp->p.ja != NULL)
-  {
-    GNUNET_free (mlp->p.ja);
-    mlp->p.ja = NULL;
-  }
-
-  /* delete coefficients */
-  if (mlp->p.ar != NULL)
-  {
-    GNUNET_free (mlp->p.ar);
-    mlp->p.ar = NULL;
-  }
-  mlp->p.ci = 0;
-  mlp->p.prob = NULL;
-
-  mlp->p.c_d = MLP_UNDEFINED;
-  mlp->p.c_r = MLP_UNDEFINED;
-  mlp->p.r_c2 = MLP_UNDEFINED;
-  mlp->p.r_c4 = MLP_UNDEFINED;
-  mlp->p.r_c6 = MLP_UNDEFINED;
-  mlp->p.r_c9 = MLP_UNDEFINED;
-  for (c = 0; c < mlp->pv.m_q ; c ++)
-    mlp->p.r_q[c] = MLP_UNDEFINED;
-  for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c ++)
-    mlp->p.r_quota[c] = MLP_UNDEFINED;
-  mlp->p.ci = MLP_UNDEFINED;
-
-
-  GNUNET_CONTAINER_multipeermap_iterate (mlp->requested_peers,
-                                        &reset_peers, NULL);
-}
-
-
-/**
- * Translate ATS properties to text
- * Just intended for debugging
- *
- * @param ats_index the ATS index
- * @return string with result
- */
-const char *
-mlp_ats_to_string (int ats_index)
-{
-  switch (ats_index) {
-    case GNUNET_ATS_ARRAY_TERMINATOR:
-      return "GNUNET_ATS_ARRAY_TERMINATOR";
-    case GNUNET_ATS_UTILIZATION_UP:
-      return "GNUNET_ATS_UTILIZATION_UP";
-    case GNUNET_ATS_UTILIZATION_DOWN:
-      return "GNUNET_ATS_UTILIZATION_DOWN";
-    case GNUNET_ATS_COST_LAN:
-      return "GNUNET_ATS_COST_LAN";
-    case GNUNET_ATS_COST_WAN:
-      return "GNUNET_ATS_COST_LAN";
-    case GNUNET_ATS_COST_WLAN:
-      return "GNUNET_ATS_COST_WLAN";
-    case GNUNET_ATS_NETWORK_TYPE:
-      return "GNUNET_ATS_NETWORK_TYPE";
-    case GNUNET_ATS_QUALITY_NET_DELAY:
-      return "GNUNET_ATS_QUALITY_NET_DELAY";
-    case GNUNET_ATS_QUALITY_NET_DISTANCE:
-      return "GNUNET_ATS_QUALITY_NET_DISTANCE";
-    default:
-      GNUNET_break (0);
-      return "unknown";
-  }
-}
-
-/**
- * Translate glpk status error codes to text
- * @param retcode return code
- * @return string with result
- */
-const char *
-mlp_status_to_string (int retcode)
-{
-  switch (retcode) {
-    case GLP_UNDEF:
-      return "solution is undefined";
-    case GLP_FEAS:
-      return "solution is feasible";
-    case GLP_INFEAS:
-      return "solution is infeasible";
-    case GLP_NOFEAS:
-      return "no feasible solution exists";
-    case GLP_OPT:
-      return "solution is optimal";
-    case GLP_UNBND:
-      return "solution is unbounded";
-    default:
-      GNUNET_break (0);
-      return "unknown error";
-  }
-}
-
-/**
- * Translate glpk solver error codes to text
- * @param retcode return code
- * @return string with result
- */
-const char *
-mlp_solve_to_string (int retcode)
-{
-  switch (retcode) {
-    case 0:
-      return "ok";
-    case GLP_EBADB:
-      return "invalid basis";
-    case GLP_ESING:
-      return "singular matrix";
-    case GLP_ECOND:
-      return "ill-conditioned matrix";
-    case GLP_EBOUND:
-      return "invalid bounds";
-    case GLP_EFAIL:
-      return "solver failed";
-    case GLP_EOBJLL:
-      return "objective lower limit reached";
-    case GLP_EOBJUL:
-      return "objective upper limit reached";
-    case GLP_EITLIM:
-      return "iteration limit exceeded";
-    case GLP_ETMLIM:
-      return "time limit exceeded";
-    case GLP_ENOPFS:
-      return "no primal feasible solution";
-    case GLP_ENODFS:
-      return "no dual feasible solution";
-    case GLP_EROOT:
-      return "root LP optimum not provided";
-    case GLP_ESTOP:
-      return "search terminated by application";
-    case GLP_EMIPGAP:
-      return "relative mip gap tolerance reached";
-    case GLP_ENOFEAS:
-      return "no dual feasible solution";
-    case GLP_ENOCVG:
-      return "no convergence";
-    case GLP_EINSTAB:
-      return "numerical instability";
-    case GLP_EDATA:
-      return "invalid data";
-    case GLP_ERANGE:
-      return "result out of range";
-    default:
-      GNUNET_break (0);
-      return "unknown error";
-  }
-}
-
-/**
- * Extract an ATS performance info from an address
- *
- * @param address the address
- * @param type the type to extract in HBO
- * @return the value in HBO or GNUNET_ATS_VALUE_UNDEFINED in HBO if value does 
not exist
- */
-static int
-get_performance_info (struct ATS_Address *address, uint32_t type)
-{
-  int c1;
-  GNUNET_assert (NULL != address);
-
-  if ((NULL == address->atsi) || (0 == address->atsi_count))
-      return GNUNET_ATS_VALUE_UNDEFINED;
-
-  for (c1 = 0; c1 < address->atsi_count; c1++)
-  {
-      if (ntohl(address->atsi[c1].type) == type)
-        return ntohl(address->atsi[c1].value);
-  }
-  return GNUNET_ATS_VALUE_UNDEFINED;
-}
-
-
-struct CountContext
-{
-  const struct GNUNET_CONTAINER_MultiPeerMap *peers;
-  int result;
-};
-
-static int
-mlp_create_problem_count_addresses_it (void *cls,
-                                      const struct GNUNET_PeerIdentity *key,
-                                      void *value)
-{
-  struct CountContext *cctx = cls;
-
-  /* Check if we have to add this peer due to a pending request */
-  if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (cctx->peers, key))
-    cctx->result++;
-  return GNUNET_OK;
-}
-
-
-static int
-mlp_create_problem_count_addresses (const struct GNUNET_CONTAINER_MultiPeerMap 
*peers,
-                                   const struct GNUNET_CONTAINER_MultiPeerMap 
*addresses)
-{
-  struct CountContext cctx;
-
-  cctx.peers = peers;
-  cctx.result = 0;
-  GNUNET_CONTAINER_multipeermap_iterate (addresses,
-                                        
&mlp_create_problem_count_addresses_it, &cctx);
-  return cctx.result;
-}
-
-
-/**
- * Updates an existing value in the matrix
- *
- * Extract the row, updates the value and updates the row in the problem
- *
- * @param p the mlp problem
- * @param row the row to create the value in
- * @param col the column to create the value in
- * @param val the value to set
- * @param line calling line for debbuging
- * @return GNUNET_YES value changed, GNUNET_NO value did not change, 
GNUNET_SYSERR
- * on error
- */
-static int
-mlp_create_problem_update_value (struct MLP_Problem *p,
-                              int row, int col, double val,
-                              int line)
-{
-  int c_cols;
-  int c_elems;
-  int c1;
-  int res;
-  int found;
-  double *val_array;
-  int *ind_array;
-
-  GNUNET_assert (NULL != p);
-  GNUNET_assert (NULL != p->prob);
-
-  /* Get number of columns and prepare data structure */
-  c_cols = glp_get_num_cols(p->prob);
-  if (0 >= c_cols)
-    return GNUNET_SYSERR;
-
-  val_array = GNUNET_malloc ((c_cols +1)* sizeof (double));
-  GNUNET_assert (NULL != val_array);
-  ind_array = GNUNET_malloc ((c_cols+1) * sizeof (int));
-  GNUNET_assert (NULL != ind_array);
-  /* Extract the row */
-
-  /* Update the value */
-  c_elems = glp_get_mat_row (p->prob, row, ind_array, val_array);
-  found = GNUNET_NO;
-  for (c1 = 1; c1 < (c_elems+1); c1++)
-  {
-    if (ind_array[c1] == col)
-    {
-      found = GNUNET_YES;
-      break;
-    }
-  }
-  if (GNUNET_NO == found)
-  {
-    ind_array[c_elems+1] = col;
-    val_array[c_elems+1] = val;
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Setting value in [%s : %s] to `%.2f'\n",
-        glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col),
-        val);
-    glp_set_mat_row (p->prob, row, c_elems+1, ind_array, val_array);
-    GNUNET_free (ind_array);
-    GNUNET_free (val_array);
-    return GNUNET_YES;
-  }
-  else
-  {
-    /* Update value */
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Updating value in [%s : %s] from `%.2f' 
to `%.2f'\n",
-        glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col),
-        val_array[c1], val);
-    if (val != val_array[c1])
-      res = GNUNET_YES;
-    else
-      res = GNUNET_NO;
-    val_array[c1] = val;
-    /* Update the row in the matrix */
-    glp_set_mat_row (p->prob, row, c_elems, ind_array, val_array);
-  }
-
-  GNUNET_free (ind_array);
-  GNUNET_free (val_array);
-  return res;
-}
-
-/**
- * Creates a new value in the matrix
- *
- * Sets the row and column index in the problem array and increments the
- * position field
- *
- * @param p the mlp problem
- * @param row the row to create the value in
- * @param col the column to create the value in
- * @param val the value to set
- * @param line calling line for debbuging
- */
-static void
-mlp_create_problem_set_value (struct MLP_Problem *p,
-                              int row, int col, double val,
-                              int line)
-{
-  if ((p->ci) >= p->num_elements)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: line %u: Request for index %u bigger 
than array size of %u\n",
-        line, p->ci + 1, p->num_elements);
-    GNUNET_break (0);
-    return;
-  }
-  if ((0 == row) || (0 == col))
-    GNUNET_break (0);
-  p->ia[p->ci] = row ;
-  p->ja[p->ci] = col;
-  p->ar[p->ci] = val;
-#if  DEBUG_MLP_PROBLEM_CREATION
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: line %u: Set value [%u,%u] in index %u 
==  %.2f\n",
-      line, p->ia[p->ci], p->ja[p->ci], p->ci, p->ar[p->ci]);
-#endif
-  p->ci++;
-}
-
-static int
-mlp_create_problem_create_column (struct MLP_Problem *p, char *name,
-    unsigned int type, unsigned int bound, double lb, double ub,
-    double coef)
-{
-  int col = glp_add_cols (p->prob, 1);
-  glp_set_col_name (p->prob, col, name);
-  glp_set_col_bnds (p->prob, col, bound, lb, ub);
-  glp_set_col_kind (p->prob, col, type);
-  glp_set_obj_coef (p->prob, col, coef);
-#if  DEBUG_MLP_PROBLEM_CREATION
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added column [%u] `%s': %.2f\n",
-      col, name, coef);
-#endif
-  return col;
-}
-
-static int
-mlp_create_problem_create_constraint (struct MLP_Problem *p, char *name,
-    unsigned int bound, double lb, double ub)
-{
-  char * op;
-  int row = glp_add_rows (p->prob, 1);
-  /* set row name */
-  glp_set_row_name (p->prob, row, name);
-  /* set row bounds: <= 0 */
-  glp_set_row_bnds (p->prob, row, bound, lb, ub);
-  switch (bound)
-  {
-    case GLP_UP:
-            GNUNET_asprintf(&op, "-inf <= x <= %.2f", ub);
-            break;
-    case GLP_DB:
-            GNUNET_asprintf(&op, "%.2f <= x <= %.2f", lb, ub);
-            break;
-    case GLP_FX:
-            GNUNET_asprintf(&op, "%.2f == x == %.2f", lb, ub);
-            break;
-    case GLP_LO:
-            GNUNET_asprintf(&op, "%.2f <= x <= inf", lb);
-            break;
-    default:
-            GNUNET_asprintf(&op, "ERROR");
-            break;
-  }
-#if  DEBUG_MLP_PROBLEM_CREATION
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added row [%u] `%s': %s\n",
-        row, name, op);
-#endif
-  GNUNET_free (op);
-  return row;
-}
-
-/**
- * Create the
- * - address columns b and n
- * - address dependent constraint rows c1, c3
- * - peer dependent rows c2 and c9
- * - Set address dependent entries in problem matrix as well
- */
-static int
-mlp_create_problem_add_address_information (void *cls,
-                                           const struct GNUNET_PeerIdentity 
*key,
-                                           void *value)
-{
-  struct GAS_MLP_Handle *mlp = cls;
-  struct MLP_Problem *p = &mlp->p;
-  struct ATS_Address *address = value;
-  struct ATS_Peer *peer;
-  struct MLP_information *mlpi;
-  char *name;
-  const double *props;
-  uint32_t addr_net;
-  int c;
-
-  /* Check if we have to add this peer due to a pending request */
-  if (GNUNET_NO == 
GNUNET_CONTAINER_multipeermap_contains(mlp->requested_peers, key))
-    return GNUNET_OK;
-
-  mlpi = address->solver_information;
-  if (NULL == mlpi)
-  {
-      fprintf (stderr, "%s %p\n",GNUNET_i2s (&address->peer), address);
-      GNUNET_break (0);
-      return GNUNET_OK;
-  }
-
-  /* Get peer */
-  peer = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, key);
-  if (peer->processed == GNUNET_NO)
-  {
-      /* Add peer dependent constraints */
-      /* Add constraint c2 */
-      GNUNET_asprintf(&name, "c2_%s", GNUNET_i2s(&address->peer));
-      peer->r_c2 = mlp_create_problem_create_constraint (p, name, GLP_FX, 1.0, 
1.0);
-      GNUNET_free (name);
-      /* Add constraint c9 */
-      GNUNET_asprintf(&name, "c9_%s", GNUNET_i2s(&address->peer));
-      peer->r_c9 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 
0.0);
-      GNUNET_free (name);
-      /* c 9) set coefficient */
-      mlp_create_problem_set_value (p, peer->r_c9, p->c_r, -peer->f, __LINE__);
-      peer->processed = GNUNET_YES;
-  }
-
-  /* Reset addresses' solver information */
-  mlpi->c_b = 0;
-  mlpi->c_n = 0;
-  mlpi->n = 0;
-  mlpi->r_c1 = 0;
-  mlpi->r_c3 = 0;
-
-  /* Add bandwidth column */
-  GNUNET_asprintf (&name, "b_%s_%s_%p", GNUNET_i2s (&address->peer), 
address->plugin, address);
-#if TEST_MAX_BW_ASSIGNMENT
-  mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 
0.0, 1.0);
-#else
-  mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 
0.0, 0.0);
-#endif
-
-  GNUNET_free (name);
-
-  /* Add usage column */
-  GNUNET_asprintf (&name, "n_%s_%s_%p", GNUNET_i2s (&address->peer), 
address->plugin, address);
-  mlpi->c_n = mlp_create_problem_create_column (p, name, GLP_IV, GLP_DB, 0.0, 
1.0, 0.0);
-  GNUNET_free (name);
-
-  /* Add address dependent constraints */
-  /* Add constraint c1) bandwidth capping
-   * b_t  + (-M) * n_t <= 0
-   * */
-  GNUNET_asprintf(&name, "c1_%s_%s_%p", GNUNET_i2s(&address->peer), 
address->plugin, address);
-  mlpi->r_c1 = mlp_create_problem_create_constraint (p, name, GLP_UP, 0.0, 
0.0);
-  GNUNET_free (name);
-
-  /*  c1) set b = 1 coefficient */
-  mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_b, 1, __LINE__);
-  /*  c1) set n = -M coefficient */
-  mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_n, -mlp->pv.BIG_M, 
__LINE__);
-
-  /* Add constraint c 3) minimum bandwidth
-   * b_t + (-n_t * b_min) >= 0
-   * */
-  GNUNET_asprintf(&name, "c3_%s_%s_%p", GNUNET_i2s(&address->peer), 
address->plugin, address);
-  mlpi->r_c3 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 
0.0);
-  GNUNET_free (name);
-
-  /*  c3) set b = 1 coefficient */
-  mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_b, 1, __LINE__);
-  /*  c3) set n = -b_min coefficient */
-  mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_n, - ((double 
)mlp->pv.b_min), __LINE__);
-
-
-  /* Set coefficient entries in invariant rows */
-  /* c 4) minimum connections */
-  mlp_create_problem_set_value (p, p->r_c4, mlpi->c_n, 1, __LINE__);
-  /* c 6) maximize diversity */
-  mlp_create_problem_set_value (p, p->r_c6, mlpi->c_n, 1, __LINE__);
-  /* c 2) 1 address peer peer */
-  mlp_create_problem_set_value (p, peer->r_c2, mlpi->c_n, 1, __LINE__);
-  /* c 9) relativity */
-  mlp_create_problem_set_value (p, peer->r_c9, mlpi->c_b, 1, __LINE__);
-  /* c 8) utility */
-  mlp_create_problem_set_value (p, p->r_c8, mlpi->c_b, 1, __LINE__);
-
-  /* c 10) obey network specific quotas
-   * (1)*b_1 + ... + (1)*b_m <= quota_n
-   */
-  for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
-  {
-    addr_net = get_performance_info (address, GNUNET_ATS_NETWORK_TYPE);
-    if (GNUNET_ATS_VALUE_UNDEFINED == addr_net)
-            addr_net = GNUNET_ATS_NET_UNSPECIFIED;
-
-    if (mlp->pv.quota_index[c] == addr_net)
-    {
-      mlp_create_problem_set_value (p, p->r_quota[c], mlpi->c_b, 1, __LINE__);
-      break;
-    }
-  }
-
-  /* c 7) Optimize quality */
-  /* For all quality metrics, set quality of this address */
-  props = mlp->get_properties (mlp->get_properties_cls, address);
-  for (c = 0; c < mlp->pv.m_q; c++)
-    mlp_create_problem_set_value (p, p->r_q[c], mlpi->c_b, props[c], __LINE__);
-
-  return GNUNET_OK;
-}
-
-/**
- * Create the invariant columns c4, c6, c10, c8, c7
- */
-static void
-mlp_create_problem_add_invariant_rows (struct GAS_MLP_Handle *mlp, struct 
MLP_Problem *p)
-{
-  char *name;
-  int c;
-
-  /* Row for c4) minimum connection */
-  /* Number of minimum connections is min(|Peers|, n_min) */
-  p->r_c4 = mlp_create_problem_create_constraint (p, "c4", GLP_LO, 
(mlp->pv.n_min > p->num_peers) ? p->num_peers : mlp->pv.n_min, 0.0);
-
-  /* Add row for c6) */
-  p->r_c6 = mlp_create_problem_create_constraint (p, "c6", GLP_FX, 0.0, 0.0);
-  /* c6 )Setting -D */
-  mlp_create_problem_set_value (p, p->r_c6, p->c_d, -1, __LINE__);
-
-  /* Add rows for c 10) */
-  for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
-  {
-    char * text;
-    GNUNET_asprintf(&text, "c10_quota_ats_%s",
-        GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]));
-    p->r_quota[c] = mlp_create_problem_create_constraint (p, text, GLP_DB, 
0.0, mlp->pv.quota_out[c]);
-    GNUNET_free (text);
-  }
-
-  /* Adding rows for c 8) */
-  p->r_c8 = mlp_create_problem_create_constraint (p, "c8", GLP_FX, 0.0, 0.0);
-  /* -u */
-  mlp_create_problem_set_value (p, p->r_c8, p->c_u, -1, __LINE__);
-
-  /* c 7) For all quality metrics */
-  for (c = 0; c < mlp->pv.m_q; c++)
-  {
-    GNUNET_asprintf(&name, "c7_q%i_%s", c, mlp_ats_to_string(mlp->pv.q[c]));
-    p->r_q[c] = mlp_create_problem_create_constraint (p, name, GLP_FX, 0.0, 
0.0);
-    GNUNET_free (name);
-    mlp_create_problem_set_value (p, p->r_q[c], p->c_q[c], -1, __LINE__);
-  }
-}
-
-
-/**
- * Create the invariant columns d, u, r, q0 ... qm
- */
-static void
-mlp_create_problem_add_invariant_columns (struct GAS_MLP_Handle *mlp, struct 
MLP_Problem *p)
-{
-  char *name;
-  int c;
-
-#if TEST_MAX_BW_ASSIGNMENT
-  mlp->pv.co_D = 0.0;
-  mlp->pv.co_U = 0.0;
-
-#endif
-  //mlp->pv.co_R = 0.0;
-
-  /* Diversity d column  */
-  p->c_d = mlp_create_problem_create_column (p, "d", GLP_CV, GLP_LO, 0.0, 0.0, 
mlp->pv.co_D);
-
-  /* Utilization u column  */
-  p->c_u = mlp_create_problem_create_column (p, "u", GLP_CV, GLP_LO, 0.0, 0.0, 
mlp->pv.co_U);
-
-  /* Relativity r column  */
-  p->c_r = mlp_create_problem_create_column (p, "r", GLP_CV, GLP_LO, 0.0, 0.0, 
mlp->pv.co_R);
-
-  /* Quality metric columns */
-  for (c = 0; c < mlp->pv.m_q; c++)
-  {
-    GNUNET_asprintf (&name, "q_%u", mlp->pv.q[c]);
-#if TEST_MAX_BW_ASSIGNMENT
-    p->c_q[c] = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 
0.0, 0.0, 0.0);
-#else
-    p->c_q[c] = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 
0.0, 0.0, mlp->pv.co_Q[c]);
-#endif
-    GNUNET_free (name);
-  }
-}
-
-
-/**
- * Create the MLP problem
- *
- * @param mlp the MLP handle
- * @return GNUNET_OK or GNUNET_SYSERR
- */
-static int
-mlp_create_problem (struct GAS_MLP_Handle *mlp)
-{
-  struct MLP_Problem *p = &mlp->p;
-  int res = GNUNET_OK;
-
-  GNUNET_assert (p->prob == NULL);
-  GNUNET_assert (p->ia == NULL);
-  GNUNET_assert (p->ja == NULL);
-  GNUNET_assert (p->ar == NULL);
-  /* Reset MLP problem struct */
-
-  /* create the glpk problem */
-  p->prob = glp_create_prob ();
-  GNUNET_assert (NULL != p->prob);
-  p->num_peers = GNUNET_CONTAINER_multipeermap_size (mlp->requested_peers);
-  p->num_addresses = mlp_create_problem_count_addresses (mlp->requested_peers, 
mlp->addresses);
-
-  /* Create problem matrix: 10 * #addresses + #q * #addresses + #q, + #peer + 
2 + 1 */
-  p->num_elements = (10 * p->num_addresses + mlp->pv.m_q * p->num_addresses +
-      mlp->pv.m_q + p->num_peers + 2 + 1);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Rebuilding problem for %u peer(s) and %u addresse(s) and %u quality 
metrics == %u elements\n",
-       p->num_peers,
-       p->num_addresses,
-       mlp->pv.m_q,
-       p->num_elements);
-
-  /* Set a problem name */
-  glp_set_prob_name (p->prob, "GNUnet ATS bandwidth distribution");
-  /* Set optimization direction to maximize */
-  glp_set_obj_dir (p->prob, GLP_MAX);
-
-  /* Create problem matrix */
-  /* last +1 caused by glpk index starting with one: [1..elements]*/
-  p->ci = 1;
-  /* row index */
-  p->ia = GNUNET_malloc (p->num_elements * sizeof (int));
-  /* column index */
-  p->ja = GNUNET_malloc (p->num_elements * sizeof (int));
-  /* coefficient */
-  p->ar = GNUNET_malloc (p->num_elements * sizeof (double));
-
-  if ((NULL == p->ia) || (NULL == p->ja) || (NULL == p->ar))
-  {
-      LOG (GNUNET_ERROR_TYPE_ERROR, _("Problem size too large, cannot allocate 
memory!\n"));
-      return GNUNET_SYSERR;
-  }
-
-  /* Adding invariant columns */
-  mlp_create_problem_add_invariant_columns (mlp, p);
-
-  /* Adding address independent constraint rows */
-  mlp_create_problem_add_invariant_rows (mlp, p);
-
-  /* Adding address dependent columns constraint rows */
-  GNUNET_CONTAINER_multipeermap_iterate (mlp->addresses,
-                                        
&mlp_create_problem_add_address_information,
-                                        mlp);
-
-  /* Load the matrix */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Loading matrix\n");
-  glp_load_matrix(p->prob, (p->ci)-1, p->ia, p->ja, p->ar);
-
-  return res;
-}
-
-/**
- * Solves the LP problem
- *
- * @param mlp the MLP Handle
- * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
- */
-static int
-mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp)
-{
-  int res = 0;
-
-  res = glp_simplex(mlp->p.prob, &mlp->control_param_lp);
-  if (0 == res)
-          LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: 0x%02X %s\n", 
res, mlp_solve_to_string(res));
-  else
-          LOG (GNUNET_ERROR_TYPE_WARNING, "Solving LP problem failed: 0x%02X 
%s\n", res, mlp_solve_to_string(res));
-
-  /* Analyze problem status  */
-  res = glp_get_status (mlp->p.prob);
-  switch (res) {
-    /* solution is optimal */
-    case GLP_OPT:
-    /* solution is feasible */
-    case GLP_FEAS:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: 0x%02X %s\n",
-          res, mlp_status_to_string(res));
-      return GNUNET_OK;
-    /* Problem was ill-defined, no way to handle that */
-    default:
-      LOG (GNUNET_ERROR_TYPE_WARNING, "Solving LP problem failed, no solution: 
0x%02X %s\n",
-          res, mlp_status_to_string(res));
-      return GNUNET_SYSERR;
-  }
-}
-
-
-/**
- * Solves the MLP problem
- *
- * @param mlp the MLP Handle
- * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
- */
-int
-mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp)
-{
-  int res = 0;
-  res = glp_intopt(mlp->p.prob, &mlp->control_param_mlp);
-  if (0 == res)
-          LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving MLP problem: 0x%02X %s\n", 
res, mlp_solve_to_string(res));
-  else
-          LOG (GNUNET_ERROR_TYPE_WARNING, "Solving MLP problem failed: 0x%02X 
%s\n", res, mlp_solve_to_string(res));
-  /* Analyze problem status  */
-  res = glp_mip_status(mlp->p.prob);
-  switch (res) {
-    /* solution is optimal */
-    case GLP_OPT:
-    /* solution is feasible */
-    case GLP_FEAS:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving MLP problem: 0x%02X %s\n", res, 
mlp_status_to_string(res));
-      return GNUNET_OK;
-    /* Problem was ill-defined, no way to handle that */
-    default:
-      LOG (GNUNET_ERROR_TYPE_WARNING,"Solving MLP problem failed, 0x%02X 
%s\n\n", res, mlp_status_to_string(res));
-      return GNUNET_SYSERR;
-  }
-}
-
-/**
- * Propagates the results when MLP problem was solved
- *
- * @param cls the MLP handle
- * @param key the peer identity
- * @param value the address
- * @return #GNUNET_OK to continue
- */
-int
-mlp_propagate_results (void *cls,
-                      const struct GNUNET_PeerIdentity *key,
-                      void *value)
-{
-  struct GAS_MLP_Handle *mlp = cls;
-  struct ATS_Address *address;
-  struct MLP_information *mlpi;
-  double mlp_bw_in = MLP_NaN;
-  double mlp_bw_out = MLP_NaN;
-  double mlp_use = MLP_NaN;
-
-  /* Check if we have to add this peer due to a pending request */
-  if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains 
(mlp->requested_peers,
-                                                          key))
-  {
-    return GNUNET_OK;
-  }
-  address = value;
-  GNUNET_assert (address->solver_information != NULL);
-  mlpi = address->solver_information;
-
-  mlp_bw_in = glp_mip_col_val(mlp->p.prob, mlpi->c_b);/* FIXME */
-  if (mlp_bw_in > (double) UINT32_MAX)
-  {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Overflow in assigned bandwidth, reducing 
...\n" );
-      mlp_bw_in = (double) UINT32_MAX;
-  }
-  mlp_bw_out = glp_mip_col_val(mlp->p.prob, mlpi->c_b);
-  if (mlp_bw_out > (double) UINT32_MAX)
-  {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Overflow in assigned bandwidth, reducing 
...\n" );
-      mlp_bw_out = (double) UINT32_MAX;
-  }
-  mlp_use = glp_mip_col_val(mlp->p.prob, mlpi->c_n);
-
-  /*
-   * Debug: solution
-   * LOG (GNUNET_ERROR_TYPE_INFO, "MLP result address: `%s' `%s' length %u 
session %u, mlp use %f\n",
-   *    GNUNET_i2s(&address->peer), address->plugin,
-   *    address->addr_len, address->session_id);
-   */
-
-  if (GLP_YES == mlp_use)
-  {
-    /* This address was selected by the solver to be used */
-    mlpi->n = GNUNET_YES;
-    if (GNUNET_NO == address->active)
-    {
-            /* Address was not used before, enabling address */
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : enabling address\n",
-          (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
-      address->active = GNUNET_YES;
-      address->assigned_bw_in.value__ = htonl (mlp_bw_in);
-      mlpi->b_in.value__ = htonl(mlp_bw_in);
-      address->assigned_bw_out.value__ = htonl (mlp_bw_out);
-      mlpi->b_out.value__ = htonl(mlp_bw_out);
-      if ((NULL == mlp->exclude_peer) || (0 != memcmp (&address->peer, 
mlp->exclude_peer, sizeof (address->peer))))
-        mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
-      return GNUNET_OK;
-    }
-    else if (GNUNET_YES == address->active)
-    {
-      /* Address was used before, check for bandwidth change */
-      if ((mlp_bw_out != ntohl(address->assigned_bw_out.value__)) ||
-              (mlp_bw_in != ntohl(address->assigned_bw_in.value__)))
-      {
-          LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : bandwidth changed\n",
-              (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
-          address->assigned_bw_in.value__ = htonl (mlp_bw_in);
-          mlpi->b_in.value__ = htonl(mlp_bw_in);
-          address->assigned_bw_out.value__ = htonl (mlp_bw_out);
-          mlpi->b_out.value__ = htonl(mlp_bw_out);
-          if ((NULL == mlp->exclude_peer) || (0 != memcmp (&address->peer, 
mlp->exclude_peer, sizeof (address->peer))))
-            mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
-          return GNUNET_OK;
-      }
-    }
-    else
-      GNUNET_break (0);
-  }
-  else if (GLP_NO == mlp_use)
-  {
-    /* This address was selected by the solver to be not used */
-    mlpi->n = GNUNET_NO;
-    if (GNUNET_NO == address->active)
-    {
-      /* Address was not used before, nothing to do */
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : no change\n",
-          (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
-      return GNUNET_OK;
-    }
-    else if (GNUNET_YES == address->active)
-    {
-    /* Address was used before, disabling address */
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : disabling address\n",
-        (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
-      address->active = GNUNET_NO;
-      /* Set bandwidth to 0 */
-      address->assigned_bw_in = BANDWIDTH_ZERO;
-      mlpi->b_in.value__ = htonl(mlp_bw_in);
-      address->assigned_bw_out = BANDWIDTH_ZERO;
-      mlpi->b_out.value__ = htonl(mlp_bw_out);
-      //mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
-      return GNUNET_OK;
-    }
-    else
-      GNUNET_break (0);
-  }
-  else
-    GNUNET_break (0);
-
-  return GNUNET_OK;
-}
-
-/**
- * Solves the MLP problem
- *
- * @param solver the MLP Handle
- * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
- */
-int
-GAS_mlp_solve_problem (void *solver)
-{
-  struct GAS_MLP_Handle *mlp = solver;
-  char *filename;
-  int res_lp = 0;
-  int res_mip = 0;
-  struct GNUNET_TIME_Absolute start_build;
-  struct GNUNET_TIME_Relative duration_build;
-  struct GNUNET_TIME_Absolute start_lp;
-  struct GNUNET_TIME_Relative duration_lp;
-  struct GNUNET_TIME_Absolute start_mlp;
-  struct GNUNET_TIME_Relative duration_mlp;
-  GNUNET_assert (NULL != solver);
-
-  if (GNUNET_YES == mlp->bulk_lock)
-  {
-    mlp->bulk_request ++;
-    return GNUNET_NO;
-  }
-
-  if (0 == GNUNET_CONTAINER_multipeermap_size (mlp->requested_peers))
-    return GNUNET_OK; /* No pending requests */
-  if (0 == GNUNET_CONTAINER_multipeermap_size (mlp->addresses))
-    return GNUNET_OK; /* No addresses available */
-
-  if ((GNUNET_NO == mlp->mlp_prob_changed) && (GNUNET_NO == 
mlp->mlp_prob_updated))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "No changes to problem\n");
-    return GNUNET_OK;
-  }
-  if (GNUNET_YES == mlp->mlp_prob_changed)
-  {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem size changed, rebuilding\n");
-      mlp_delete_problem (mlp);
-      start_build = GNUNET_TIME_absolute_get();
-      if (GNUNET_SYSERR == mlp_create_problem (mlp))
-        return GNUNET_SYSERR;
-      duration_build = GNUNET_TIME_absolute_get_duration (start_build);
-      mlp->control_param_lp.presolve = GLP_YES;
-      mlp->control_param_mlp.presolve = GNUNET_NO; /* No presolver, we have LP 
solution */
-  }
-  else
-  {
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n");
-      duration_build.rel_value_us = 0;
-  }
-
-  /* Run LP solver */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Running LP solver %s\n",
-      (GLP_YES == mlp->control_param_lp.presolve)? "with presolver": "without 
presolver");
-  start_lp = GNUNET_TIME_absolute_get();
-  res_lp = mlp_solve_lp_problem (mlp);
-  duration_lp = GNUNET_TIME_absolute_get_duration (start_lp);
-
-
-  /* Run MLP solver */
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Running MLP solver \n");
-  start_mlp = GNUNET_TIME_absolute_get();
-  res_mip = mlp_solve_mlp_problem (mlp);
-
-  duration_mlp = GNUNET_TIME_absolute_get_duration (start_mlp);
-
-  /* Save stats */
-  mlp->ps.lp_res = res_lp;
-  mlp->ps.mip_res = res_mip;
-  mlp->ps.build_dur = duration_build;
-  mlp->ps.lp_dur = duration_lp;
-  mlp->ps.mip_dur = duration_mlp;
-  mlp->ps.lp_presolv = mlp->control_param_lp.presolve;
-  mlp->ps.mip_presolv = mlp->control_param_mlp.presolve;
-  mlp->ps.p_cols = glp_get_num_cols (mlp->p.prob);
-  mlp->ps.p_rows = glp_get_num_rows (mlp->p.prob);
-  mlp->ps.p_elements = mlp->p.num_elements;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Execution time: Build %s\n",
-       GNUNET_STRINGS_relative_time_to_string (duration_build, GNUNET_NO));
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Execution time: LP %s\n",
-       GNUNET_STRINGS_relative_time_to_string (duration_lp, GNUNET_NO));
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Execution time: MLP %s\n",
-       GNUNET_STRINGS_relative_time_to_string (duration_mlp, GNUNET_NO));
-
-  /* Propagate result*/
-  if ((GNUNET_OK == res_lp) && (GNUNET_OK == res_mip))
-  {
-    GNUNET_CONTAINER_multipeermap_iterate (mlp->addresses, 
&mlp_propagate_results, mlp);
-  }
-
-  struct GNUNET_TIME_Absolute time = GNUNET_TIME_absolute_get();
-  if (GNUNET_YES == mlp->write_mip_mps)
-  {
-    /* Write problem to disk */
-    GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.mps", mlp->p.num_peers, 
mlp->p.num_addresses, time.abs_value_us);
-    LOG (GNUNET_ERROR_TYPE_ERROR, "DUMP: %s \n", filename);
-    glp_write_lp(mlp->p.prob, NULL, filename);
-    GNUNET_free (filename);
-  }
-  if (GNUNET_YES == mlp->write_mip_sol)
-  {
-    /* Write solution to disk */
-    GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.sol", mlp->p.num_peers, 
mlp->p.num_addresses, time.abs_value_us);
-    glp_print_mip (mlp->p.prob, filename );
-    LOG (GNUNET_ERROR_TYPE_ERROR, "DUMP: %s \n", filename);
-    GNUNET_free (filename);
-  }
-
-  /* Reset change and update marker */
-  mlp->control_param_lp.presolve = GLP_NO;
-  mlp->mlp_prob_updated = GNUNET_NO;
-  mlp->mlp_prob_changed = GNUNET_NO;
-
-  if ((GNUNET_OK == res_lp) && (GNUNET_OK == res_mip))
-    return GNUNET_OK;
-  else
-    return GNUNET_SYSERR;
-}
-
-/**
- * Add a single address to the solve
- *
- * @param solver the solver Handle
- * @param address the address to add
- * @param network network type of this address
- */
-void
-GAS_mlp_address_add (void *solver,
-                    struct ATS_Address *address,
-                    uint32_t network)
-{
-  struct GAS_MLP_Handle *mlp = solver;
-  struct ATS_Peer *p;
-
-  GNUNET_assert (NULL != solver);
-  GNUNET_assert (NULL != address);
-
-  if (NULL == address->solver_information)
-  {
-      address->solver_information = GNUNET_new (struct MLP_information);
-  }
-  else
-      LOG (GNUNET_ERROR_TYPE_ERROR,
-          _("Adding address for peer `%s' multiple times\n"),
-          GNUNET_i2s(&address->peer));
-
-  /* Is this peer included in the problem? */
-  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
-                                                     &address->peer)))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer `%s' without 
address request \n", GNUNET_i2s(&address->peer));
-    return;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer `%s' with address 
request \n", GNUNET_i2s(&address->peer));
-  /* Problem size changed: new address for peer with pending request */
-  mlp->mlp_prob_changed = GNUNET_YES;
-  if (GNUNET_YES == mlp->mlp_auto_solve)
-    GAS_mlp_solve_problem (solver);
-}
-
-
-/**
- * Transport properties for this address have changed
- *
- * @param solver solver handle
- * @param address the address
- * @param type the ATSI type in HBO
- * @param abs_value the absolute value of the property
- * @param rel_value the normalized value
- */
-void
-GAS_mlp_address_property_changed (void *solver,
-                                  struct ATS_Address *address,
-                                  uint32_t type,
-                                  uint32_t abs_value,
-                                  double rel_value)
-{
-  struct MLP_information *mlpi = address->solver_information;
-  struct GAS_MLP_Handle *mlp = solver;
-  struct ATS_Peer *p;
-  int c1;
-  int type_index;
-
-  GNUNET_assert (NULL != solver);
-  GNUNET_assert (NULL != address);
-
-  if (NULL == mlpi)
-  {
-      LOG (GNUNET_ERROR_TYPE_ERROR,
-          _("Updating address property `%s' for peer `%s' %p not added 
before\n"),
-          GNUNET_ATS_print_property_type (type),
-          GNUNET_i2s(&address->peer),
-          address);
-      GNUNET_break (0);
-      return;
-  }
-
-  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
-                                                     &address->peer)))
-  {
-    /* Peer is not requested, so no need to update problem */
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Updating property `%s' address for peer 
`%s'\n",
-      GNUNET_ATS_print_property_type (type),
-      GNUNET_i2s(&address->peer));
-
-  /* Find row index */
-  type_index = -1;
-  for (c1 = 0; c1 < mlp->pv.m_q; c1++)
-  {
-    if (type == mlp->pv.q[c1])
-    {
-      type_index = c1;
-      break;
-    }
-  }
-  if (-1 == type_index)
-  {
-    GNUNET_break (0);
-    return; /* quality index not found */
-  }
-
-  /* Update c7) [r_q[index]][c_b] = f_q * q_averaged[type_index] */
-  if (GNUNET_YES == mlp_create_problem_update_value (&mlp->p,
-      mlp->p.r_q[type_index], mlpi->c_b, rel_value, __LINE__))
-  {
-    mlp->mlp_prob_updated = GNUNET_YES;
-    if (GNUNET_YES == mlp->mlp_auto_solve)
-      GAS_mlp_solve_problem (solver);
-  }
-}
-
-
-/**
- * Transport session for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param cur_session the current session
- * @param new_session the new session
- */
-void
-GAS_mlp_address_session_changed (void *solver,
-                                  struct ATS_Address *address,
-                                  uint32_t cur_session,
-                                  uint32_t new_session)
-{
-  /* Nothing to do here */
-  return;
-}
-
-
-/**
- * Transport session for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param in_use usage state
- */
-void
-GAS_mlp_address_inuse_changed (void *solver,
-                               struct ATS_Address *address,
-                               int in_use)
-{
-  /* Nothing to do here */
-  return;
-}
-
-
-/**
- * Network scope for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param current_network the current network
- * @param new_network the new network
- */
-void
-GAS_mlp_address_change_network (void *solver,
-                               struct ATS_Address *address,
-                               uint32_t current_network,
-                               uint32_t new_network)
-{
-  struct MLP_information *mlpi = address->solver_information;
-  struct GAS_MLP_Handle *mlp = solver;
-  struct ATS_Peer *p;
-  int nets_avail[] = GNUNET_ATS_NetworkType;
-  int c1;
-
-  GNUNET_assert (NULL != solver);
-  GNUNET_assert (NULL != address);
-
-  if (NULL == mlpi)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  if (mlpi->c_b == MLP_UNDEFINED)
-    return; /* This address is not yet in the matrix*/
-
-  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
-                                                     &address->peer)))
-  {
-    /* Peer is not requested, so no need to update problem */
-    GNUNET_break (0);
-    return;
-  }
-
-  if (current_network == new_network)
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  for (c1 = 0; c1 < GNUNET_ATS_NetworkTypeCount ; c1 ++)
-  {
-    if (nets_avail[c1] == new_network)
-      break;
-  }
-
-  if (GNUNET_ATS_NetworkTypeCount == c1)
-  {
-    /* Invalid network */
-    GNUNET_break (0);
-    return;
-  }
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Updating network for peer `%s' from `%s' to 
`%s'\n",
-      GNUNET_i2s (&address->peer),
-      GNUNET_ATS_print_network_type(current_network),
-      GNUNET_ATS_print_network_type(new_network));
-
-  for (c1 = 0; c1 < GNUNET_ATS_NetworkTypeCount; c1++)
-  {
-    if (mlp->pv.quota_index[c1] == current_network)
-    {
-      /* Remove from old network */
-      mlp_create_problem_update_value (&mlp->p,
-          mlp->p.r_quota[c1],
-          mlpi->c_b, 0.0, __LINE__);
-      break;
-    }
-  }
-
-  for (c1 = 0; c1 < GNUNET_ATS_NetworkTypeCount; c1++)
-  {
-    if (mlp->pv.quota_index[c1] == new_network)
-    {
-      /* Remove from old network */
-      if (GNUNET_SYSERR == mlp_create_problem_update_value (&mlp->p,
-          mlp->p.r_quota[c1],
-          mlpi->c_b, 1.0, __LINE__))
-      {
-        /* This quota did not exist in the problem, recreate */
-        GNUNET_break (0);
-      }
-      break;
-    }
-  }
-
-  mlp->mlp_prob_changed = GNUNET_YES;
-}
-
-
-/**
- * Deletes a single address in the MLP problem
- *
- * The MLP problem has to be recreated and the problem has to be resolved
- *
- * @param solver the MLP Handle
- * @param address the address to delete
- * @param session_only delete only session not whole address
- */
-void
-GAS_mlp_address_delete (void *solver,
-    struct ATS_Address *address,
-    int session_only)
-{
-  struct ATS_Peer *p;
-  struct GAS_MLP_Handle *mlp = solver;
-  struct MLP_information *mlpi;
-  int was_active;
-
-  GNUNET_assert (NULL != solver);
-  GNUNET_assert (NULL != address);
-
-  mlpi = address->solver_information;
-  if ((GNUNET_NO == session_only) && (NULL != mlpi))
-  {
-    /* Remove full address */
-    GNUNET_free (mlpi);
-    address->solver_information = NULL;
-  }
-  was_active = address->active;
-  address->active = GNUNET_NO;
-  address->assigned_bw_in = BANDWIDTH_ZERO;
-  address->assigned_bw_out = BANDWIDTH_ZERO;
-
-  /* Is this peer included in the problem? */
-  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
-                                                     &address->peer)))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Deleting %s for peer `%s' without address 
request \n",
-        (session_only == GNUNET_YES) ? "session" : "address",
-        GNUNET_i2s(&address->peer));
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_INFO, "Deleting %s for peer `%s' with address request 
\n",
-      (session_only == GNUNET_YES) ? "session" : "address",
-      GNUNET_i2s(&address->peer));
-
-  /* Problem size changed: new address for peer with pending request */
-  mlp->mlp_prob_changed = GNUNET_YES;
-  if (GNUNET_YES == mlp->mlp_auto_solve)
-  {
-    GAS_mlp_solve_problem (solver);
-  }
-  if (GNUNET_YES == was_active)
-  {
-    if (NULL == GAS_mlp_get_preferred_address (solver, &address->peer))
-    {
-      /* No alternative address, disconnecting peer */
-      mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
-    }
-  }
-
-  return;
-}
-
-
-/**
- * Find the active address in the set of addresses of a peer
- * @param cls destination
- * @param key peer id
- * @param value address
- * @return GNUNET_OK
- */
-static int
-mlp_get_preferred_address_it (void *cls,
-                             const struct GNUNET_PeerIdentity *key,
-                             void *value)
-{
-  static int counter = 0;
-  struct ATS_Address **aa = cls;
-  struct ATS_Address *addr = value;
-  struct MLP_information *mlpi = addr->solver_information;
-
-  if (mlpi == NULL)
-    return GNUNET_YES;
-
-  /*
-   * Debug output
-   * GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-   *           "MLP [%u] Peer `%s' %s length %u session %u active %s mlp 
active %s\n",
-   *           counter, GNUNET_i2s (&addr->peer), addr->plugin, 
addr->addr_len, addr->session_id,
-   *           (GNUNET_YES == addr->active) ? "active" : "inactive",
-   *           (GNUNET_YES == mlpi->n) ? "active" : "inactive");
-   */
-
-  if (GNUNET_YES == mlpi->n)
-  {
-
-    (*aa) = addr;
-    (*aa)->assigned_bw_in = mlpi->b_in;
-    (*aa)->assigned_bw_out = mlpi->b_out;
-    return GNUNET_NO;
-  }
-  counter ++;
-  return GNUNET_YES;
-}
-
-
-static double
-get_peer_pref_value (struct GAS_MLP_Handle *mlp, const struct 
GNUNET_PeerIdentity *peer)
-{
-  double res;
-  const double *preferences = NULL;
-  int c;
-  preferences = mlp->get_preferences (mlp->get_preferences_cls, peer);
-
-  res = 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]);
-      res += preferences[c];
-    }
-  }
-  res /= (GNUNET_ATS_PreferenceCount -1);
-  return res;
-}
-
-
-/**
- * Get the preferred address for a specific peer
- *
- * @param solver the MLP Handle
- * @param peer the peer
- * @return suggested address
- */
-const struct ATS_Address *
-GAS_mlp_get_preferred_address (void *solver,
-                               const struct GNUNET_PeerIdentity *peer)
-{
-  struct GAS_MLP_Handle *mlp = solver;
-  struct ATS_Peer *p;
-  struct ATS_Address *res;
-
-  GNUNET_assert (NULL != solver);
-  GNUNET_assert (NULL != peer);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Getting preferred address for `%s'\n",
-      GNUNET_i2s (peer));
-
-  /* Is this peer included in the problem? */
-  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
-                                                     peer)))
-    {
-      LOG (GNUNET_ERROR_TYPE_INFO, "Adding peer `%s' to list of 
requested_peers with requests\n",
-          GNUNET_i2s (peer));
-
-      p = GNUNET_malloc (sizeof (struct ATS_Peer));
-      p->id = (*peer);
-      p->f = get_peer_pref_value (mlp, peer);
-      GNUNET_CONTAINER_multipeermap_put (mlp->requested_peers,
-                                        peer, p,
-                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
-
-      /* Added new peer, we have to rebuild problem before solving */
-      mlp->mlp_prob_changed = GNUNET_YES;
-
-      if ((GNUNET_YES == mlp->mlp_auto_solve)&&
-          (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains(mlp->addresses,
-                                                               peer)))
-      {
-        mlp->exclude_peer = peer;
-        GAS_mlp_solve_problem (mlp);
-        mlp->exclude_peer = NULL;
-      }
-  }
-  /* Get prefered address */
-  res = NULL;
-  GNUNET_CONTAINER_multipeermap_get_multiple (mlp->addresses, peer,
-                                              mlp_get_preferred_address_it, 
&res);
-  return res;
-}
-
-
-/**
- * Start a bulk operation
- *
- * @param solver the solver
- */
-void
-GAS_mlp_bulk_start (void *solver)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Locking solver for bulk operation ...\n");
-  struct GAS_MLP_Handle *s = (struct GAS_MLP_Handle *) solver;
-
-  GNUNET_assert (NULL != solver);
-
-  s->bulk_lock ++;
-}
-
-void
-GAS_mlp_bulk_stop (void *solver)
-{
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Unlocking solver from bulk operation ...\n");
-
-  struct GAS_MLP_Handle *s = (struct GAS_MLP_Handle *) solver;
-  GNUNET_assert (NULL != solver);
-
-  if (s->bulk_lock < 1)
-  {
-    GNUNET_break (0);
-    return;
-  }
-  s->bulk_lock --;
-
-  if (0 < s->bulk_request)
-  {
-    GAS_mlp_solve_problem (solver);
-    s->bulk_request= 0;
-  }
-}
-
-
-
-/**
- * Stop notifying about address and bandwidth changes for this peer
- *
- * @param solver the MLP handle
- * @param peer the peer
- */
-void
-GAS_mlp_stop_get_preferred_address (void *solver,
-                                     const struct GNUNET_PeerIdentity *peer)
-{
-  struct GAS_MLP_Handle *mlp = solver;
-  struct ATS_Peer *p = NULL;
-
-  GNUNET_assert (NULL != solver);
-  GNUNET_assert (NULL != peer);
-  if (NULL != (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, 
peer)))
-  {
-    GNUNET_CONTAINER_multipeermap_remove (mlp->requested_peers, peer, p);
-    GNUNET_free (p);
-
-    mlp->mlp_prob_changed = GNUNET_YES;
-    if (GNUNET_YES == mlp->mlp_auto_solve)
-    {
-      GAS_mlp_solve_problem (solver);
-    }
-  }
-}
-
-
-/**
- * Changes the preferences for a peer in the MLP problem
- *
- * @param solver the MLP Handle
- * @param peer the peer
- * @param kind the kind to change the preference
- * @param pref_rel the relative score
- */
-void
-GAS_mlp_address_change_preference (void *solver,
-                   const struct GNUNET_PeerIdentity *peer,
-                   enum GNUNET_ATS_PreferenceKind kind,
-                   double pref_rel)
-{
-  struct GAS_MLP_Handle *mlp = solver;
-  struct ATS_Peer *p = NULL;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Changing preference for address for peer `%s' 
to %.2f\n",
-      GNUNET_i2s(peer), pref_rel);
-
-  GNUNET_STATISTICS_update (mlp->stats,"# LP address preference changes", 1, 
GNUNET_NO);
-  /* Update the constraints with changed preferences */
-
-  /* Update quality constraint c7 */
-
-  /* Update relativity constraint c9 */
-  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, 
peer)))
-  {
-    LOG (GNUNET_ERROR_TYPE_ERROR, "Updating preference for unknown peer 
`%s'\n", GNUNET_i2s(peer));
-    return;
-  }
-  p->f = get_peer_pref_value (mlp, peer);
-  LOG (GNUNET_ERROR_TYPE_ERROR, "PEER PREF: %s %.2f\n",
-      GNUNET_i2s(peer), p->f);
-  mlp_create_problem_update_value (&mlp->p, p->r_c9, mlp->p.c_r, -p->f, 
__LINE__);
-
-  /* Problem size changed: new address for peer with pending request */
-  mlp->mlp_prob_updated = GNUNET_YES;
-  if (GNUNET_YES == mlp->mlp_auto_solve)
-    GAS_mlp_solve_problem (solver);
-  return;
-}
-
-
-/**
- * Get application feedback for a peer
- *
- * @param solver the solver handle
- * @param application the application
- * @param peer the peer to change the preference for
- * @param scope the time interval for this feedback: [now - scope .. now]
- * @param kind the kind to change the preference
- * @param score the score
- */
-void
-GAS_mlp_address_preference_feedback (void *solver,
-                                    void *application,
-                                    const struct GNUNET_PeerIdentity *peer,
-                                    const struct GNUNET_TIME_Relative scope,
-                                    enum GNUNET_ATS_PreferenceKind kind,
-                                    double score)
-{
-  struct GAS_PROPORTIONAL_Handle *s = solver;
-  GNUNET_assert (NULL != solver);
-  GNUNET_assert (NULL != peer);
-
-  GNUNET_assert (NULL != s);
-}
-
-
-static int
-mlp_free_peers (void *cls,
-               const struct GNUNET_PeerIdentity *key, void *value)
-{
-  struct GNUNET_CONTAINER_MultiPeerMap *map = cls;
-  struct ATS_Peer *p = value;
-
-  GNUNET_CONTAINER_multipeermap_remove (map, key, value);
-  GNUNET_free (p);
-
-  return GNUNET_OK;
-}
-
-
-/**
- * Shutdown the MLP problem solving component
- *
- * @param solver the solver handle
- */
-void
-GAS_mlp_done (void *solver)
-{
-  struct GAS_MLP_Handle *mlp = solver;
-  GNUNET_assert (mlp != NULL);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down mlp solver\n");
-  mlp_delete_problem (mlp);
-
-  GNUNET_CONTAINER_multipeermap_iterate (mlp->requested_peers,
-                                        &mlp_free_peers,
-                                        mlp->requested_peers);
-  GNUNET_CONTAINER_multipeermap_destroy (mlp->requested_peers);
-  mlp->requested_peers = NULL;
-
-  /* Clean up GLPK environment */
-  glp_free_env();
-  GNUNET_free (mlp);
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutdown down of mlp solver complete\n");
-}
-
-
-/**
- * Init the MLP problem solving component
- *
- * @param cfg the GNUNET_CONFIGURATION_Handle handle
- * @param stats the GNUNET_STATISTICS handle
- * @param addresses the address hashmap
- * @param network array of GNUNET_ATS_NetworkType with length dest_length
- * @param out_dest array of outbound quotas
- * @param in_dest array of outbound quota
- * @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
- * @param get_properties callback to get relative properties
- * @param get_properties_cls cls for callback to get relative properties
- * @return struct GAS_MLP_Handle on success, NULL on fail
- */
-void *
-GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
-              const struct GNUNET_STATISTICS_Handle *stats,
-              const struct GNUNET_CONTAINER_MultiPeerMap *addresses,
-              int *network,
-              unsigned long long *out_dest,
-              unsigned long long *in_dest,
-              int dest_length,
-              GAS_bandwidth_changed_cb bw_changed_cb,
-              void *bw_changed_cb_cls,
-              GAS_get_preferences get_preference,
-              void *get_preference_cls,
-              GAS_get_properties get_properties,
-              void *get_properties_cls)
-{
-  struct GAS_MLP_Handle * mlp = GNUNET_malloc (sizeof (struct GAS_MLP_Handle));
-
-  double D;
-  double R;
-  double U;
-  unsigned long long tmp;
-  unsigned int b_min;
-  unsigned int n_min;
-  int c;
-  int c2;
-  int found;
-
-  struct GNUNET_TIME_Relative max_duration;
-  long long unsigned int max_iterations;
-
-  GNUNET_assert (NULL != cfg);
-  GNUNET_assert (NULL != stats);
-  GNUNET_assert (NULL != addresses);
-  GNUNET_assert (NULL != bw_changed_cb);
-  GNUNET_assert (NULL != get_preference);
-  GNUNET_assert (NULL != get_properties);
-
-  /* Init GLPK environment */
-  int res = glp_init_env();
-  switch (res) {
-    case 0:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
-          "initialization successful");
-      break;
-    case 1:
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
-          "environment is already initialized");
-      break;
-    case 2:
-      LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
-          "initialization failed (insufficient memory)");
-      GNUNET_free(mlp);
-      return NULL;
-      break;
-    case 3:
-      LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
-          "initialization failed (unsupported programming model)");
-      GNUNET_free(mlp);
-      return NULL;
-      break;
-    default:
-      break;
-  }
-
-   mlp->write_mip_mps = GNUNET_CONFIGURATION_get_value_yesno (cfg, "ats",
-          "DUMP_MLP");
-   if (GNUNET_SYSERR == mlp->write_mip_mps)
-     mlp->write_mip_mps = GNUNET_NO;
-   mlp->write_mip_sol = GNUNET_CONFIGURATION_get_value_yesno (cfg, "ats",
-          "DUMP_SOLUTION");
-   if (GNUNET_SYSERR == mlp->write_mip_sol)
-     mlp->write_mip_sol = GNUNET_NO;
-
-  mlp->pv.BIG_M = (double) BIG_M_VALUE;
-
-  /* Get timeout for iterations */
-  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time(cfg, "ats", 
"MLP_MAX_DURATION", &max_duration))
-  {
-    max_duration = MLP_MAX_EXEC_DURATION;
-  }
-
-  /* Get maximum number of iterations */
-  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_size(cfg, "ats", 
"MLP_MAX_ITERATIONS", &max_iterations))
-  {
-    max_iterations = MLP_MAX_ITERATIONS;
-  }
-
-  /* Get diversity coefficient from configuration */
-  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
-                                                      "MLP_COEFFICIENT_D",
-                                                      &tmp))
-    D = (double) tmp / 100;
-  else
-    D = DEFAULT_D;
-
-  /* Get proportionality coefficient from configuration */
-  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
-                                                      "MLP_COEFFICIENT_R",
-                                                      &tmp))
-    R = (double) tmp / 100;
-  else
-    R = DEFAULT_R;
-
-  /* Get utilization coefficient from configuration */
-  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
-                                                      "MLP_COEFFICIENT_U",
-                                                      &tmp))
-    U = (double) tmp / 100;
-  else
-    U = DEFAULT_U;
-
-  /* Get quality metric coefficients from configuration */
-  int i_delay = MLP_NaN;
-  int i_distance = MLP_NaN;
-  int q[GNUNET_ATS_QualityPropertiesCount] = GNUNET_ATS_QualityProperties;
-  for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++)
-  {
-    /* initialize quality coefficients with default value 1.0 */
-      mlp->pv.co_Q[c] = DEFAULT_QUALITY;
-
-    mlp->pv.q[c] = q[c];
-    if (q[c] == GNUNET_ATS_QUALITY_NET_DELAY)
-      i_delay = c;
-    if (q[c] == GNUNET_ATS_QUALITY_NET_DISTANCE)
-      i_distance = c;
-  }
-
-  if ((i_delay != MLP_NaN) && (GNUNET_OK == 
GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
-                                                      
"MLP_COEFFICIENT_QUALITY_DELAY",
-                                                      &tmp)))
-
-    mlp->pv.co_Q[i_delay] = (double) tmp / 100;
-  else
-    mlp->pv.co_Q[i_delay] = DEFAULT_QUALITY;
-
-  if ((i_distance != MLP_NaN) && (GNUNET_OK == 
GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
-                                                      
"MLP_COEFFICIENT_QUALITY_DISTANCE",
-                                                      &tmp)))
-    mlp->pv.co_Q[i_distance] = (double) tmp / 100;
-  else
-    mlp->pv.co_Q[i_distance] = DEFAULT_QUALITY;
-
-  /* Get minimum bandwidth per used address from configuration */
-  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
-                                                      "MLP_MIN_BANDWIDTH",
-                                                      &tmp))
-    b_min = tmp;
-  else
-  {
-    b_min = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
-  }
-
-  /* Get minimum number of connections from configuration */
-  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (cfg, "ats",
-                                                      "MLP_MIN_CONNECTIONS",
-                                                      &tmp))
-    n_min = tmp;
-  else
-    n_min = DEFAULT_MIN_CONNECTIONS;
-
-  /* Init network quotas */
-  int quotas[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
-  for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
-  {
-      found = GNUNET_NO;
-      for (c2 = 0; c2 < dest_length; c2++)
-      {
-          if (quotas[c] == network[c2])
-          {
-              mlp->pv.quota_index[c] = network[c2];
-              mlp->pv.quota_out[c] = out_dest[c2];
-              mlp->pv.quota_in[c] = in_dest[c2];
-              found = GNUNET_YES;
-              LOG (GNUNET_ERROR_TYPE_DEBUG, "Quota for network `%s' (in/out) 
%llu/%llu\n",
-                          
GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
-                          mlp->pv.quota_out[c],
-                          mlp->pv.quota_in[c]);
-              break;
-          }
-      }
-
-      /* Check if defined quota could make problem unsolvable */
-      if ((n_min * b_min) > mlp->pv.quota_out[c])
-      {
-        LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting inconsistent outbound quota 
configuration for network `%s', is %llu must be at least %llu\n"),
-            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
-            mlp->pv.quota_out[c],
-            (n_min * b_min));
-        mlp->pv.quota_out[c] = (n_min * b_min);
-      }
-      if ((n_min * b_min) > mlp->pv.quota_in[c])
-      {
-        LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting inconsistent inbound quota 
configuration for network `%s', is %llu must be at least %llu\n"),
-            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
-            mlp->pv.quota_in[c],
-            (n_min * b_min));
-        mlp->pv.quota_in[c] = (n_min * b_min);
-      }
-
-      /* Check if bandwidth is too big to make problem solvable */
-      if (mlp->pv.BIG_M < mlp->pv.quota_out[c])
-      {
-        LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting outbound quota configuration 
for network `%s'from %llu to %.0f\n"),
-            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
-            mlp->pv.quota_out[c],
-            mlp->pv.BIG_M);
-        mlp->pv.quota_out[c] = mlp->pv.BIG_M ;
-      }
-      if (mlp->pv.BIG_M < mlp->pv.quota_in[c])
-      {
-        LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting inbound quota configuration 
for network `%s' from %llu to %.0f\n"),
-            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
-            mlp->pv.quota_in[c],
-            mlp->pv.BIG_M);
-        mlp->pv.quota_in[c] = mlp->pv.BIG_M ;
-      }
-
-      if (GNUNET_NO == found)
-      {
-        mlp->pv.quota_in[c] = 
ntohl(GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
-        mlp->pv.quota_out[c] = 
ntohl(GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
-        LOG (GNUNET_ERROR_TYPE_INFO, _("Using default quota configuration for 
network `%s' (in/out) %llu/%llu\n"),
-            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
-            mlp->pv.quota_in[c],
-            mlp->pv.quota_out[c]);
-      }
-  }
-
-  /* Assign options to handle */
-  mlp->stats = (struct GNUNET_STATISTICS_Handle *) stats;
-  mlp->addresses = addresses;
-  mlp->bw_changed_cb = bw_changed_cb;
-  mlp->bw_changed_cb_cls = bw_changed_cb_cls;
-  mlp->get_preferences = get_preference;
-  mlp->get_preferences_cls = get_preference_cls;
-  mlp->get_properties = get_properties;
-  mlp->get_properties_cls = get_properties_cls;
-  /* Setting MLP Input variables */
-  mlp->pv.co_D = D;
-  mlp->pv.co_R = R;
-  mlp->pv.co_U = U;
-  mlp->pv.b_min = b_min;
-  mlp->pv.n_min = n_min;
-  mlp->pv.m_q = GNUNET_ATS_QualityPropertiesCount;
-  mlp->mlp_prob_changed = GNUNET_NO;
-  mlp->mlp_prob_updated = GNUNET_NO;
-  mlp->mlp_auto_solve = GNUNET_YES;
-  mlp->requested_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
-  mlp->bulk_request = 0;
-  mlp->bulk_lock = 0;
-
-  /* Setup GLPK */
-  /* Redirect GLPK output to GNUnet logging */
-  glp_term_hook (&mlp_term_hook, (void *) mlp);
-
-  /* Init LP solving parameters */
-  glp_init_smcp(&mlp->control_param_lp);
-  mlp->control_param_lp.msg_lev = GLP_MSG_OFF;
-#if VERBOSE_GLPK
-  mlp->control_param_lp.msg_lev = GLP_MSG_ALL;
-#endif
-  mlp->control_param_lp.it_lim = max_iterations;
-  mlp->control_param_lp.tm_lim = max_duration.rel_value_us / 1000LL;
-
-  /* Init MLP solving parameters */
-  glp_init_iocp(&mlp->control_param_mlp);
-  mlp->control_param_mlp.msg_lev = GLP_MSG_OFF;
-#if VERBOSE_GLPK
-  mlp->control_param_mlp.msg_lev = GLP_MSG_ALL;
-#endif
-  mlp->control_param_mlp.tm_lim = max_duration.rel_value_us / 1000LL;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "solver ready\n");
-
-  return mlp;
-}
-
-/* end of gnunet-service-ats_addresses_mlp.c */

Deleted: gnunet/src/ats/gnunet-service-ats-solver_mlp.h
===================================================================
--- gnunet/src/ats/gnunet-service-ats-solver_mlp.h      2013-10-08 15:43:03 UTC 
(rev 29997)
+++ gnunet/src/ats/gnunet-service-ats-solver_mlp.h      2013-10-08 16:34:07 UTC 
(rev 29998)
@@ -1,551 +0,0 @@
-/*
- (C) 2011 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- 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.
- */
-
-/**
- * @file ats/gnunet-service-ats-solver_mlp.h
- * @brief ats MLP problem solver
- * @author Matthias Wachs
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet-service-ats_addresses.h"
-#if HAVE_LIBGLPK
-#include "glpk.h"
-#endif
-
-#ifndef GNUNET_SERVICE_ATS_ADDRESSES_MLP_H
-#define GNUNET_SERVICE_ATS_ADDRESSES_MLP_H
-
-#define BIG_M_VALUE (UINT32_MAX) /10
-#define BIG_M_STRING "unlimited"
-
-#define MLP_AVERAGING_QUEUE_LENGTH 3
-
-#define MLP_MAX_EXEC_DURATION   
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10)
-#define MLP_MAX_ITERATIONS      4096
-
-#define DEFAULT_D 1.0
-#define DEFAULT_R 1.0
-#define DEFAULT_U 1.0
-#define DEFAULT_QUALITY 1.0
-#define DEFAULT_MIN_CONNECTIONS 4
-#define DEFAULT_PEER_PREFERENCE 1.0
-
-#define MLP_NaN -1
-#define MLP_UNDEFINED 0
-#define GLP_YES 1.0
-#define GLP_NO  0.0
-
-struct MLP_Solution
-{
-  struct GNUNET_TIME_Relative build_dur;
-  struct GNUNET_TIME_Relative lp_dur;
-  struct GNUNET_TIME_Relative mip_dur;
-
-  int lp_res;
-  int lp_presolv;
-  int mip_res;
-  int mip_presolv;
-
-  int p_elements;
-  int p_cols;
-  int p_rows;
-
-  int n_peers;
-  int n_addresses;
-
-};
-
-struct ATS_Peer
-{
-  struct GNUNET_PeerIdentity id;
-
-  /* Was this peer already added to the current problem? */
-  int processed;
-
-  /* constraint 2: 1 address per peer*/
-  unsigned int r_c2;
-
-  /* constraint 9: relativity */
-  unsigned int r_c9;
-
-  /* Legacy preference value */
-  double f;
-};
-
-struct MLP_Problem
-{
-  /**
-   * GLPK (MLP) problem object
-   */
-#if HAVE_LIBGLPK
-  glp_prob *prob;
-#else
-  void *prob;
-#endif
-
-  /* Number of addresses in problem */
-  unsigned int num_addresses;
-  /* Number of peers in problem */
-  unsigned int num_peers;
-  /* Number of elements in problem matrix */
-  unsigned int num_elements;
-
-  /* Row index constraint 2: */
-  unsigned int r_c2;
-  /* Row index constraint 4: minimum connections */
-  unsigned int r_c4;
-  /* Row index constraint 6: maximize diversity */
-  unsigned int r_c6;
-  /* Row index constraint 8: utilization*/
-  unsigned int r_c8;
-  /* Row index constraint 9: relativity*/
-  unsigned int r_c9;
-  /* Row indices quality metrics  */
-  int r_q[GNUNET_ATS_QualityPropertiesCount];
-  /* Row indices ATS network quotas */
-  int r_quota[GNUNET_ATS_NetworkTypeCount];
-
-  /* Column index Diversity (D) column */
-  int c_d;
-  /* Column index Utilization (U) column */
-  int c_u;
-  /* Column index Proportionality (R) column */
-  int c_r;
-  /* Column index quality metrics  */
-  int c_q[GNUNET_ATS_QualityPropertiesCount];
-
-  /* Problem matrix */
-  /* Current index */
-  unsigned int ci;
-  /* Row index array */
-  int *ia;
-  /* Column index array */
-  int *ja;
-  /* Column index value */
-  double *ar;
-
-};
-
-struct MLP_Variables
-{
-  /* Big M value for bandwidth capping */
-  double BIG_M;
-
-  /* ATS Quality metrics
-   *
-   * Array with GNUNET_ATS_QualityPropertiesCount elements
-   * contains mapping to GNUNET_ATS_Property*/
-  int q[GNUNET_ATS_QualityPropertiesCount];
-
-  /* Number of quality metrics */
-  int m_q;
-
-  /* Number of quality metrics */
-  int m_rc;
-
-  /* Quality metric coefficients*/
-  double co_Q[GNUNET_ATS_QualityPropertiesCount];
-
-  /* Ressource costs coefficients*/
-  double co_RC[GNUNET_ATS_QualityPropertiesCount];
-
-  /* Diversity coefficient */
-  double co_D;
-
-  /* Utility coefficient */
-  double co_U;
-
-  /* Relativity coefficient */
-  double co_R;
-
-  /* Minimum bandwidth assigned to an address */
-  unsigned int b_min;
-
-  /* Minimum number of addresses with bandwidth assigned */
-  unsigned int n_min;
-
-  /* Quotas */
-  /* Array mapping array index to ATS network */
-  int quota_index[GNUNET_ATS_NetworkTypeCount];
-  /* Outbound quotas */
-  unsigned long long quota_out[GNUNET_ATS_NetworkTypeCount];
-  /* Inbound quotas */
-
-  unsigned long long quota_in[GNUNET_ATS_NetworkTypeCount];
-
-  /* ATS ressource costs
-   * array with GNUNET_ATS_QualityPropertiesCount elements
-   * contains mapping to GNUNET_ATS_Property
-   * */
-  int rc[GNUNET_ATS_QualityPropertiesCount];
-
-};
-
-/**
- * MLP Handle
- */
-struct GAS_MLP_Handle
-{
-  /**
-   * Statistics handle
-   */
-  struct GNUNET_STATISTICS_Handle *stats;
-
-  /**
-   * Address hashmap for lookups
-   */
-  const struct GNUNET_CONTAINER_MultiPeerMap *addresses;
-
-  /**
-   * Addresses' bandwidth changed callback
-   */
-  GAS_bandwidth_changed_cb bw_changed_cb;
-
-  /**
-   * Addresses' bandwidth changed callback closure
-   */
-  void *bw_changed_cb_cls;
-
-  /**
-   * ATS function to get preferences
-   */
-  GAS_get_preferences get_preferences;
-
-  /**
-   * Closure for ATS function to get preferences
-   */
-  void *get_preferences_cls;
-
-  /**
-   * ATS function to get properties
-   */
-  GAS_get_properties get_properties;
-
-  /**
-   * Closure for ATS function to get properties
-   */
-  void *get_properties_cls;
-
-  /**
-   * Exclude peer from next result propagation
-   */
-  const struct GNUNET_PeerIdentity *exclude_peer;
-
-  /**
-   * Encapsulation for the MLP problem
-   */
-  struct MLP_Problem p;
-
-  /**
-   * Encapsulation for the MLP problem variables
-   */
-  struct MLP_Variables pv;
-
-  /**
-   * Encapsulation for the MLP solution
-   */
-  struct MLP_Solution ps;
-
-  /**
-   * Bulk lock
-   */
-
-  int bulk_lock;
-
-  /**
-   * Number of changes while solver was locked
-   */
-  int bulk_request;
-
-  /**
-   * GLPK LP control parameter
-   */
-#if HAVE_LIBGLPK
-  glp_smcp control_param_lp;
-#else
-  void *control_param_lp;
-#endif
-
-  /**
-   * GLPK LP control parameter
-   */
-#if HAVE_LIBGLPK
-  glp_iocp control_param_mlp;
-#else
-  void *control_param_mlp;
-#endif
-
-  /**
-   * Peers with pending address requests
-   */
-  struct GNUNET_CONTAINER_MultiPeerMap *requested_peers;
-
-  /**
-   * Was the problem updated since last solution
-   */
-  int mlp_prob_updated;
-
-  /**
-   * Has the problem size changed since last solution
-   */
-  int mlp_prob_changed;
-
-  /**
-   * Solve the problem automatically when updates occur?
-   * Default: GNUNET_YES
-   * Can be disabled for test and measurements
-   */
-  int mlp_auto_solve;
-
-  /**
-   * Write MILP problem to a MPS file
-   */
-  int write_mip_mps;
-
-  /**
-   * Write MILP problem to a MPS file
-   */
-  int write_mip_sol;
-
-};
-
-/**
- * Address specific MLP information
- */
-struct MLP_information
-{
-
-  /* Bandwidth assigned */
-  struct GNUNET_BANDWIDTH_Value32NBO b_out;
-  struct GNUNET_BANDWIDTH_Value32NBO b_in;
-
-  /* Address selected */
-  int n;
-
-  /* bandwidth column index */
-  signed int c_b;
-
-  /* address usage column */
-  signed int c_n;
-
-  /* row indexes */
-
-  /* constraint 1: bandwidth capping */
-  unsigned int r_c1;
-
-  /* constraint 3: minimum bandwidth */
-  unsigned int r_c3;
-};
-
-
-/**
- * Solves the MLP problem
- *
- * @param solver the MLP Handle
- * @return #GNUNET_OK if could be solved, GNUNET_SYSERR on failure
- */
-int
-GAS_mlp_solve_problem (void *solver);
-
-
-/**
- * Init the MLP problem solving component
- *
- * @param cfg the GNUNET_CONFIGURATION_Handle handle
- * @param stats the GNUNET_STATISTICS handle
- * @param network array of GNUNET_ATS_NetworkType with length dest_length
- * @param out_dest array of outbound quotas
- * @param in_dest array of outbound quota
- * @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 callback to get relative preferences for a peer
- * @param get_properties_cls for callback to get relative properties
- * @param get_properties_cls cls for callback to get relative properties
- * @return struct GAS_MLP_Handle on success, NULL on fail
- */
-void *
-GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
-             const struct GNUNET_STATISTICS_Handle *stats,
-    const struct GNUNET_CONTAINER_MultiPeerMap *addresses, int *network,
-    unsigned long long *out_dest, unsigned long long *in_dest, int dest_length,
-    GAS_bandwidth_changed_cb bw_changed_cb, void *bw_changed_cb_cls,
-    GAS_get_preferences get_preference, void *get_preference_cls,
-    GAS_get_properties get_properties, void *get_properties_cls);
-
-
-/**
- * Add a single address within a network to the solver
- *
- * @param solver the solver Handle
- * @param address the address to add
- * @param network network type of this address
- */
-void
-GAS_mlp_address_add (void *solver, struct ATS_Address *address,
-    uint32_t network);
-
-
-/**
- * Transport properties for this address have changed
- *
- * @param solver solver handle
- * @param address the address
- * @param type the ATSI type in HBO
- * @param abs_value the absolute value of the property
- * @param rel_value the normalized value
- */
-void
-GAS_mlp_address_property_changed (void *solver, struct ATS_Address *address,
-    uint32_t type, uint32_t abs_value, double rel_value);
-
-
-/**
- * Transport session for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param cur_session the current session
- * @param new_session the new session
- */
-void
-GAS_mlp_address_session_changed (void *solver, struct ATS_Address *address,
-                                uint32_t cur_session, uint32_t new_session);
-
-
-/**
- * Usage for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param in_use usage state
- */
-void
-GAS_mlp_address_inuse_changed (void *solver, struct ATS_Address *address,
-    int in_use);
-
-/**
- * Network scope for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param current_network the current network
- * @param new_network the new network
- */
-void
-GAS_mlp_address_change_network (void *solver, struct ATS_Address *address,
-    uint32_t current_network, uint32_t new_network);
-
-/**
- * Deletes a single address in the MLP problem
- *
- * The MLP problem has to be recreated and the problem has to be resolved
- *
- * @param solver the MLP Handle
- * @param address the address to delete
- * @param session_only delete only session not whole address
- */
-void
-GAS_mlp_address_delete (void *solver, struct ATS_Address *address,
-    int session_only);
-
-/**
- * Changes the preferences for a peer in the MLP problem
- *
- * @param solver the MLP Handle
- * @param peer the peer
- * @param kind the kind to change the preference
- * @param pref_rel the relative score
- */
-void
-GAS_mlp_address_change_preference (void *solver,
-    const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind 
kind,
-    double pref_rel);
-
-/**
- * Get application feedback for a peer
- *
- * @param solver the solver handle
- * @param application the application
- * @param peer the peer to change the preference for
- * @param scope the time interval for this feedback: [now - scope .. now]
- * @param kind the kind to change the preference
- * @param score the score
- */
-void
-GAS_mlp_address_preference_feedback (void *solver, void *application,
-    const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_TIME_Relative scope,
-    enum GNUNET_ATS_PreferenceKind kind, double score);
-
-/**
- * Start a bulk operation
- *
- * @param solver the solver
- */
-void
-GAS_mlp_bulk_start (void *solver);
-
-/**
- * Bulk operation done
- */
-void
-GAS_mlp_bulk_stop (void *solver);
-
-/**
- * Get the preferred address for a specific peer until
- * GAS_mlp_stop_get_preferred_address is called
- *
- * @param solver the MLP Handle
- * @param peer the peer
- * @return suggested address
- */
-const struct ATS_Address *
-GAS_mlp_get_preferred_address (void *solver,
-    const struct GNUNET_PeerIdentity *peer);
-
-/**
- * Stop notifying about address and bandwidth changes for this peer
- *
- * @param solver the MLP handle
- * @param peer the peer
- */
-void
-GAS_mlp_stop_get_preferred_address (void *solver,
-    const struct GNUNET_PeerIdentity *peer);
-
-/**
- * Shutdown the MLP problem solving component
- *
- * @param solver the solver handle
- */
-void
-GAS_mlp_done (void *solver);
-
-#endif
-/* end of gnunet-service-ats_addresses_mlp.h */

Deleted: gnunet/src/ats/gnunet-service-ats-solver_proportional.c
===================================================================
--- gnunet/src/ats/gnunet-service-ats-solver_proportional.c     2013-10-08 
15:43:03 UTC (rev 29997)
+++ gnunet/src/ats/gnunet-service-ats-solver_proportional.c     2013-10-08 
16:34:07 UTC (rev 29998)
@@ -1,1528 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2011 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- 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.
- */
-
-/**
- * @file ats/gnunet-service-ats-solver_proportional.c
- * @brief ATS proportional solver
- * @author Matthias Wachs
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet-service-ats_addresses.h"
-#include "gnunet_statistics_service.h"
-
-#define LOG(kind,...) GNUNET_log_from (kind, "ats-proportional",__VA_ARGS__)
-
-/**
- *
- * NOTE: Do not change this documentation. This documentation is based
- * on gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex
- * use build_txt.sh to generate plaintext output
- *
- * ATS addresses : proportional solver
- *
- *    The proportional solver ("proportional") distributes the available
- *    bandwidth fair over all the addresses influenced by the
- *    preference values. For each available network type an in- and
- *    outbound quota is configured and the bandwidth available in
- *    these networks is distributed over the addresses.  The solver
- *    first assigns every addresses the minimum amount of bandwidth
- *    GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT and then distributes the
- *    remaining bandwidth available according to the preference
- *    values. For each peer only a single address gets bandwidth
- *    assigned and only one address marked as active.  The most
- *    important functionality for the solver is implemented in: *
- *    find_address_it is an hashmap iterator returning the prefered
- *    address for an peer * update_quota_per_network distributes
- *    available bandwidth for a network over active addresses
- *
- *    Changes to addresses automatically have an impact on the the
- *    bandwidth assigned to other addresses in the same network since
- *    the solver distributes the remaining bandwidth over the
- *    addresses in the network.  When changes to the addresses occur,
- *    the solver first performs the changes, like adding or deleting
- *    addresses, and then updates bandwidth assignment for the
- *    affected network. Bandwidth assignment is only recalculated on
- *    demand when an address is requested by a client for a peer or
- *    when the addresses available have changed or an address changed
- *    the network it is located in. When the bandwidth assignment has
- *    changed the callback is called with the new bandwidth
- *    assignments. The bandwidth distribution for a network is
- *    recalculated due to: * address suggestion requests * address
- *    deletions * address switching networks during address update *
- *    preference changes
- *
- *     3.1 Data structures used
- *
- *    For each ATS network (e.g. WAN, LAN, loopback) a struct Network
- *    is used to specify network related information as total adresses
- *    and active addresses in this network and the configured in- and
- *    outbound quota. Each network also contains a list of addresses
- *    added to the solver located in this network. The proportional
- *    solver uses the addresses' solver_information field to store the
- *    proportional network it belongs to for each address.
- *
- *     3.2 Initializing
- *
- *    When the proportional solver is initialized the solver creates a
- *    new solver handle and initializes the network structures with
- *    the quotas passed from addresses and returns the handle solver.
- *
- *     3.3 Adding an address
- *
- *    When a new address is added to the solver using s_add, a lookup
- *    for the network for this address is done and the address is
- *    enqueued in in the linked list of the network.
- *
- *     3.4 Updating an address
- *
- *    The main purpose of address updates is to update the ATS
- *    information for addresse selection. Important for the proportional
- *    solver is when an address switches network it is located
- *    in. This is common because addresses added by transport's
- *    validation mechanism are commonly located in
- *    GNUNET_ATS_NET_UNSPECIFIED. Addresses in validation are located
- *    in this network type and only if a connection is successful on
- *    return of payload data transport switches to the real network
- *    the address is located in.  When an address changes networks it
- *    is first of all removed from the old network using the solver
- *    API function GAS_proportional_address_delete and the network in
- *    the address struct is updated. A lookup for the respective new
- *    proportional network is done and stored in the addresse's
- *    solver_information field. Next the address is re-added to the
- *    solver using the solver API function
- *    GAS_proportional_address_add. If the address was marked as in
- *    active, the solver checks if bandwidth is available in the
- *    network and if yes sets the address to active and updates the
- *    bandwidth distribution in this network. If no bandwidth is
- *    available it sets the bandwidth for this address to 0 and tries
- *    to suggest an alternative address. If an alternative address was
- *    found, addresses' callback is called for this address.
- *
- *     3.5 Deleting an address
- *
- *    When an address is removed from the solver, it removes the
- *    respective address from the network and if the address was
- *    marked as active, it updates the bandwidth distribution for this
- *    network.
- *
- *     3.6 Requesting addresses
- *
- *    When an address is requested for a peer the solver performs a
- *    lookup for the peer entry in addresses address hashmap and
- *    selects the best address.  The selection of the most suitable
- *    address is done in the find_address_it hashmap iterator
- *    described in detail in section 3.7. If no address is returned,
- *    no address can be suggested at the moment. If the address
- *    returned is marked as active, the solver can return this
- *    address. If the address is not marked as active, the solver
- *    checks if another address belongign to this peer is marked as
- *    active and marks the address as inactive, updates the bandwidth
- *    for this address to 0, call the bandwidth changed callback for
- *    this address due to the change and updates quota assignment for
- *    the addresse's network. the now in-active address is belonging
- *    to. The solver marks the new address as active and updates the
- *    bandwidth assignment for this network.
- *
- *     3.7 Choosing addresses
- *
- *    Choosing the best possible address for suggestion is done by
- *    iterating over all addresses of a peer stored in addresses'
- *    hashmap and using the hashmap iterator find_address_it to select
- *    the best available address.  Several checks are done when an
- *    address is selected. First if this address is currently blocked
- *    by addresses from being suggested. An address is blocked for the
- *    duration of ATS_BLOCKING_DELTA when it is suggested to
- *    transport. Next it is checked if at least
- *    GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT bytes bandwidth is available
- *    in the addresse's network, because suggesting an address without
- *    bandwidth does not make sense. This also ensures that all active
- *    addresses in this network get at least the minimum amount of
- *    bandwidth assigned. In the next step the solver ensures that for
- *    tcp connections inbound connections are prefered over outbound
- *    connections. In the next stet the solver ensures that
- *    connections are prefered in the following order: * connections
- *    are already established and have bandwidth assigned *
- *    connections with a shorter distance * connectes have a shorter
- *    latency
- *
- *     3.8 Changing preferences
- *
- *     3.9 Shutdown
- *
- *    During shutdown all network entries and aging processes are
- *    destroyed and freed.
- *
- *
- * OLD DOCUMENTATION
- *
- * This solver assigns in and outbound bandwidth equally for all
- * addresses in specific network type (WAN, LAN) based on configured
- * in and outbound quota for this network.
- *
- * The solver is notified by addresses about changes to the addresses
- * and recalculates the bandwith assigned if required. The solver
- * notifies addresses by calling the GAS_bandwidth_changed_cb
- * callback.
- *
- * - Initialization
- *
- *
- *
- *
- * For each peer only a single is selected and marked as "active" in the 
address
- * struct.
- *
- * E.g.:
- *
- * You have the networks WAN and LAN and quotas
- * WAN_TOTAL_IN, WAN_TOTAL_OUT
- * LAN_TOTAL_IN, LAN_TOTAL_OUT
- *
- * If you have x addresses in the network segment LAN, the quotas are
- * QUOTA_PER_ADDRESS = LAN_TOTAL_OUT / x
- *
- * Quotas are automatically recalculated and reported back when addresses are
- * - requested
- *
- */
-
-#define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_SECONDS, 10)
-#define PREF_AGING_FACTOR 0.95
-
-#define DEFAULT_REL_PREFERENCE 1.0
-#define DEFAULT_ABS_PREFERENCE 0.0
-#define MIN_UPDATE_INTERVAL GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_SECONDS, 10)
-
-/**
- * A handle for the proportional solver
- */
-struct GAS_PROPORTIONAL_Handle
-{
-  /**
-   * Statistics handle
-   */
-  struct GNUNET_STATISTICS_Handle *stats;
-
-  /**
-   * Hashmap containing all valid addresses
-   */
-  const struct GNUNET_CONTAINER_MultiPeerMap *addresses;
-
-  /**
-   * Pending address requests
-   */
-  struct GNUNET_CONTAINER_MultiPeerMap *requests;
-
-  /**
-   * 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;
-
-  /**
-   * ATS function to get properties
-   */
-  GAS_get_properties get_properties;
-
-  /**
-   * Closure for ATS function to get properties
-   */
-  void *get_properties_cls;
-
-  /**
-   * Bulk lock
-   */
-  int bulk_lock;
-
-  /**
-   * Number of changes while solver was locked
-   */
-  int bulk_requests;
-
-  /**
-   * Total number of addresses for solver
-   */
-  unsigned int total_addresses;
-
-  /**
-   * Number of active addresses for solver
-   */
-  unsigned int active_addresses;
-
-  /**
-   * Networks array
-   */
-  struct Network *network_entries;
-
-  /**
-   * Number of networks
-   */
-  unsigned int networks;
-
-};
-
-/**
- * Representation of a network
- */
-struct Network
-{
-  /**
-   * ATS network type
-   */
-  unsigned int type;
-
-  /**
-   * Network description
-   */
-  char *desc;
-
-  /**
-   * Total inbound quota
-   *
-   */
-  unsigned long long total_quota_in;
-
-  /**
-   * Total outbound quota
-   *
-   */
-  unsigned long long total_quota_out;
-
-  /**
-   * Number of active addresses for this network
-   */
-  unsigned int active_addresses;
-
-  /**
-   * Number of total addresses for this network
-   */
-  unsigned int total_addresses;
-
-  /**
-   * String for statistics total addresses
-   */
-  char *stat_total;
-
-  /**
-   * String for statistics active addresses
-   */
-  char *stat_active;
-
-  struct AddressWrapper *head;
-  struct AddressWrapper *tail;
-};
-
-/**
- * Wrapper for addresses to store them in network's linked list
- */
-struct AddressWrapper
-{
-  /**
-   * Next in DLL
-   */
-  struct AddressWrapper *next;
-
-  /**
-   * Previous in DLL
-   */
-  struct AddressWrapper *prev;
-
-  /**
-   * The address
-   */
-  struct ATS_Address *addr;
-};
-
-/**
- *  Important solver functions
- *  ---------------------------
- */
-
-/**
- * Test if bandwidth is available in this network to add an additional address
- *
- * @param net the network type to update
- * @return GNUNET_YES or GNUNET_NO
- */
-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)
-      && ((net->total_quota_out / na) > min_bw))
-  {
-    LOG(GNUNET_ERROR_TYPE_DEBUG,
-        "Enough bandwidth available for %u active addresses in network `%s'\n",
-        na, net->desc);
-
-    return GNUNET_YES;
-  }
-  LOG(GNUNET_ERROR_TYPE_DEBUG,
-      "Not enough bandwidth available for %u active addresses in network 
`%s'\n",
-      na, net->desc);
-  return GNUNET_NO;
-}
-
-/**
- * Update bandwidth assigned to peers in this network
- *
- * @param s the solver handle
- * @param net the network type to update
- * @param address_except address excluded from notification, since we suggest
- * this address
- */
-static void
-distribute_bandwidth_in_network (struct GAS_PROPORTIONAL_Handle *s,
-    struct Network *net, struct ATS_Address *address_except)
-{
-  unsigned long long remaining_quota_in = 0;
-  unsigned long long quota_out_used = 0;
-
-  unsigned long long remaining_quota_out = 0;
-  unsigned long long quota_in_used = 0;
-  uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
-  double peer_prefs;
-  double total_prefs; /* Important: has to be double not float due to 
precision */
-  double cur_pref; /* Important: has to be double not float due to precision */
-  const double *t = NULL; /* Important: has to be double not float due to 
precision */
-  int c;
-
-  unsigned long long assigned_quota_in = 0;
-  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 (net->active_addresses == 0)
-    return; /* no addresses to update */
-
-  /* Idea
-   * Assign every peer in network minimum Bandwidth
-   * Distribute bandwidth left according to preference
-   */
-
-  if ((net->active_addresses * min_bw) > net->total_quota_in)
-  {
-    GNUNET_break(0);
-    return;
-  }
-  if ((net->active_addresses * min_bw) > net->total_quota_out)
-  {
-    GNUNET_break(0);
-    return;
-  }
-
-  remaining_quota_in = net->total_quota_in - (net->active_addresses * min_bw);
-  remaining_quota_out = net->total_quota_out - (net->active_addresses * 
min_bw);
-  LOG(GNUNET_ERROR_TYPE_DEBUG, "Remaining bandwidth : (in/out): %llu/%llu \n",
-      remaining_quota_in, remaining_quota_out);
-  total_prefs = 0.0;
-  for (cur = net->head; NULL != cur; cur = cur->next)
-  {
-    if (GNUNET_YES == cur->addr->active)
-    {
-      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;
-      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);
-
-      LOG(GNUNET_ERROR_TYPE_DEBUG,
-          "New quota for peer `%s' with preference (cur/total) %.3f/%.3f 
(in/out): %llu / %llu\n",
-          GNUNET_i2s (&cur->addr->peer), cur_pref, total_prefs,
-          assigned_quota_in, assigned_quota_out);
-    }
-    else
-    {
-      assigned_quota_in = 0;
-      assigned_quota_out = 0;
-    }
-
-    quota_in_used += assigned_quota_in;
-    quota_out_used += assigned_quota_out;
-    /* Prevent overflow due to rounding errors */
-    if (assigned_quota_in > UINT32_MAX)
-      assigned_quota_in = UINT32_MAX;
-    if (assigned_quota_out > UINT32_MAX)
-      assigned_quota_out = UINT32_MAX;
-
-    /* Compare to current bandwidth assigned */
-    if ((assigned_quota_in != ntohl (cur->addr->assigned_bw_in.value__))
-        || (assigned_quota_out != ntohl (cur->addr->assigned_bw_out.value__)))
-    {
-      cur->addr->assigned_bw_in.value__ = htonl (assigned_quota_in);
-      cur->addr->assigned_bw_out.value__ = htonl (assigned_quota_out);
-      /* Notify on change */
-      if ((GNUNET_YES == cur->addr->active) && (cur->addr != address_except))
-        s->bw_changed (s->bw_changed_cls, cur->addr);
-    }
-
-  }
-  LOG(GNUNET_ERROR_TYPE_DEBUG,
-      "Total bandwidth assigned is (in/out): %llu /%llu\n", quota_in_used,
-      quota_out_used);
-  if (quota_out_used > net->total_quota_out + 1) /* +1 is required due to 
rounding errors */
-  {
-    LOG(GNUNET_ERROR_TYPE_ERROR,
-        "Total outbound bandwidth assigned is larger than allowed 
(used/allowed) for %u active addresses: %llu / %llu\n",
-        net->active_addresses, quota_out_used, net->total_quota_out);
-  }
-  if (quota_in_used > net->total_quota_in + 1) /* +1 is required due to 
rounding errors */
-  {
-    LOG(GNUNET_ERROR_TYPE_ERROR,
-        "Total inbound bandwidth assigned is larger than allowed 
(used/allowed) for %u active addresses: %llu / %llu\n",
-        net->active_addresses, quota_in_used, net->total_quota_in);
-  }
-}
-
-struct FindBestAddressCtx
-{
-  struct GAS_PROPORTIONAL_Handle *s;
-  struct ATS_Address *best;
-};
-
-static int
-find_property_index (uint32_t type)
-{
-  int existing_types[] = GNUNET_ATS_QualityProperties;
-  int c;
-  for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++)
-    if (existing_types[c] == type)
-      return c;
-  return GNUNET_SYSERR;
-}
-
-/**
- * Find a "good" address to use for a peer by iterating over the addresses for 
this peer.
- * If we already have an existing address, we stick to it.
- * Otherwise, we pick by lowest distance and then by lowest latency.
- *
- * @param cls the 'struct ATS_Address**' where we store the result
- * @param key unused
- * @param value another 'struct ATS_Address*' to consider using
- * @return GNUNET_OK (continue to iterate)
- */
-static int
-find_best_address_it (void *cls,
-                     const struct GNUNET_PeerIdentity *key,
-                     void *value)
-{
-  struct FindBestAddressCtx *fba_ctx = (struct FindBestAddressCtx *) cls;
-  struct ATS_Address *current = (struct ATS_Address *) value;
-  struct GNUNET_TIME_Absolute now;
-  struct Network *net = (struct Network *) current->solver_information;
-  const double *norm_prop_cur;
-  const double *norm_prop_prev;
-  int index;
-
-  now = GNUNET_TIME_absolute_get ();
-
-  if (current->blocked_until.abs_value_us
-      == GNUNET_TIME_absolute_max (now, current->blocked_until).abs_value_us)
-  {
-    /* This address is blocked for suggestion */
-    LOG(GNUNET_ERROR_TYPE_DEBUG, "Address %p blocked for suggestion for %s \n",
-        current,
-        GNUNET_STRINGS_relative_time_to_string 
(GNUNET_TIME_absolute_get_difference (now, current->blocked_until), 
GNUNET_YES));
-    return GNUNET_OK;
-  }
-  if (GNUNET_NO == is_bandwidth_available_in_network (net))
-    return GNUNET_OK; /* There's no bandwidth available in this network */
-  if (NULL != fba_ctx->best)
-  {
-    GNUNET_assert(NULL != fba_ctx->best->plugin);
-    GNUNET_assert(NULL != current->plugin);
-    if (0 == strcmp (fba_ctx->best->plugin, current->plugin))
-    {
-      if ((0 != fba_ctx->best->addr_len) && (0 == current->addr_len))
-      {
-        /* saved address was an outbound address, but we have an inbound 
address */
-        fba_ctx->best = current;
-        return GNUNET_OK;
-      }
-      if (0 == fba_ctx->best->addr_len)
-      {
-        /* saved address was an inbound address, so do not overwrite */
-        return GNUNET_OK;
-      }
-    }
-  }
-  if (NULL == fba_ctx->best)
-  {
-    fba_ctx->best = current;
-    return GNUNET_OK;
-  }
-  if ((ntohl (fba_ctx->best->assigned_bw_in.value__) == 0)
-      && (ntohl (current->assigned_bw_in.value__) > 0))
-  {
-    /* stick to existing connection */
-    fba_ctx->best = current;
-    return GNUNET_OK;
-  }
-
-  norm_prop_cur = fba_ctx->s->get_properties (fba_ctx->s->get_properties_cls,
-      (const struct ATS_Address *) current);
-  norm_prop_prev = fba_ctx->s->get_properties (fba_ctx->s->get_properties_cls,
-      (const struct ATS_Address *) fba_ctx->best);
-  /*
-   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s previous %.2f current %.2f\n",
-   "DISTANCE", norm_prop_cur[1], norm_prop_cur[1]);
-   */
-  index = find_property_index (GNUNET_ATS_QUALITY_NET_DISTANCE);
-  if (GNUNET_SYSERR == index)
-  {
-    GNUNET_break(0);
-    return GNUNET_OK;
-  }
-  if (norm_prop_cur[index] < norm_prop_prev[index])
-  {
-    /* user shorter distance */
-    fba_ctx->best = current;
-    return GNUNET_OK;
-  }
-  /*
-   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s previous %.2f current %.2f\n",
-   "DELAY", norm_prop_cur[1], norm_prop_cur[1]);
-   */
-  index = find_property_index (GNUNET_ATS_QUALITY_NET_DELAY);
-  if (GNUNET_SYSERR == index)
-  {
-    GNUNET_break(0);
-    return GNUNET_OK;
-  }
-  if (norm_prop_cur[index] < norm_prop_prev[index])
-  {
-    /* user shorter delay */
-    fba_ctx->best = current;
-    return GNUNET_OK;
-  }
-
-  /* don't care */
-  return GNUNET_OK;
-}
-
-/**
- *  Helper functions
- *  ---------------------------
- */
-
-/**
- * Update bandwidth assignment for all networks
- *
- * @param s the solver handle
- */
-static void
-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 );
-}
-
-/**
- * Lookup network struct by type
- *
- * @param s the solver handle
- * @param type the network type
- * @return the network struct
- */
-static struct Network *
-get_network (struct GAS_PROPORTIONAL_Handle *s, uint32_t type)
-{
-  int c;
-  for (c = 0; c < s->networks; c++)
-  {
-    if (s->network_entries[c].type == type)
-      return &s->network_entries[c];
-
-  }
-  return NULL ;
-}
-
-/**
- * Hashmap Iterator to find current active address for peer
- *
- * @param cls last active address
- * @param key peer's key
- * @param value address to check
- * @return #GNUNET_NO on double active address else #GNUNET_YES;
- */
-static int
-get_active_address_it (void *cls,
-                      const struct GNUNET_PeerIdentity *key,
-                      void *value)
-{
-  struct ATS_Address **dest = cls;
-  struct ATS_Address *aa = (struct ATS_Address *) value;
-
-  if (GNUNET_YES == aa->active)
-  {
-
-    if (NULL != (*dest))
-    {
-      /* should never happen */
-      LOG(GNUNET_ERROR_TYPE_ERROR, "Multiple active addresses for peer `%s'\n",
-          GNUNET_i2s (&aa->peer));
-      GNUNET_break(0);
-      return GNUNET_NO;
-    }
-    (*dest) = aa;
-  }
-  return GNUNET_OK;
-}
-
-/**
- * Find current active address for peer
- *
- * @param solver the solver handle
- * @param addresses the address set
- * @param peer the peer
- * @return active address or NULL
- */
-static struct ATS_Address *
-get_active_address (void *solver,
-                   const struct GNUNET_CONTAINER_MultiPeerMap * addresses,
-                   const struct GNUNET_PeerIdentity *peer)
-{
-  struct ATS_Address * dest = NULL;
-
-  GNUNET_CONTAINER_multipeermap_get_multiple (addresses, peer,
-                                             &get_active_address_it, &dest);
-  return dest;
-}
-
-
-static void
-addresse_increment (struct GAS_PROPORTIONAL_Handle *s, struct Network *net,
-    int total, int active)
-{
-  if (GNUNET_YES == total)
-  {
-    s->total_addresses++;
-    net->total_addresses++;
-    GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", 1, GNUNET_NO);
-    GNUNET_STATISTICS_update (s->stats, net->stat_total, 1, GNUNET_NO);
-  }
-  if (GNUNET_YES == active)
-  {
-    net->active_addresses++;
-    s->active_addresses++;
-    GNUNET_STATISTICS_update (s->stats, "# ATS active addresses total", 1,
-        GNUNET_NO);
-    GNUNET_STATISTICS_update (s->stats, net->stat_active, 1, GNUNET_NO);
-  }
-
-}
-
-
-static int
-addresse_decrement (struct GAS_PROPORTIONAL_Handle *s, struct Network *net,
-    int total, int active)
-{
-  int res = GNUNET_OK;
-  if (GNUNET_YES == total)
-  {
-    if (s->total_addresses < 1)
-    {
-      GNUNET_break(0);
-      res = GNUNET_SYSERR;
-    }
-    else
-    {
-      s->total_addresses--;
-      GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1,
-          GNUNET_NO);
-    }
-    if (net->total_addresses < 1)
-    {
-      GNUNET_break(0);
-      res = GNUNET_SYSERR;
-    }
-    else
-    {
-      net->total_addresses--;
-      GNUNET_STATISTICS_update (s->stats, net->stat_total, -1, GNUNET_NO);
-    }
-  }
-
-  if (GNUNET_YES == active)
-  {
-    if (net->active_addresses < 1)
-    {
-      GNUNET_break(0);
-      res = GNUNET_SYSERR;
-    }
-    else
-    {
-      net->active_addresses--;
-      GNUNET_STATISTICS_update (s->stats, net->stat_active, -1, GNUNET_NO);
-    }
-    if (s->active_addresses < 1)
-    {
-      GNUNET_break(0);
-      res = GNUNET_SYSERR;
-    }
-    else
-    {
-      s->active_addresses--;
-      GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1,
-          GNUNET_NO);
-    }
-  }
-  return res;
-}
-
-/**
- *  Solver API functions
- *  ---------------------------
- */
-
-/**
- * Changes the preferences for a peer in the problem
- *
- * @param solver the solver handle
- * @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
- */
-void
-GAS_proportional_address_change_preference (void *solver,
-                                           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 != peer);
-
-  distribute_bandwidth_in_all_networks (s);
-}
-
-
-/**
- * Get application feedback for a peer
- *
- * @param solver the solver handle
- * @param application the application
- * @param peer the peer to change the preference for
- * @param scope the time interval for this feedback: [now - scope .. now]
- * @param kind the kind to change the preference
- * @param score the score
- */
-void
-GAS_proportional_address_preference_feedback (void *solver, void *application,
-    const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_TIME_Relative scope,
-    enum GNUNET_ATS_PreferenceKind kind, double score)
-{
-  struct GAS_PROPORTIONAL_Handle *s = solver;
-  GNUNET_assert(NULL != solver);
-  GNUNET_assert(NULL != peer);
-
-  GNUNET_assert(NULL != s);
-  GNUNET_break(0);
-}
-
-/**
- * Get the preferred address for a specific peer
- *
- * @param solver the solver handle
- * @param peer the identity of the peer
- */
-const struct ATS_Address *
-GAS_proportional_get_preferred_address (void *solver,
-    const struct GNUNET_PeerIdentity *peer)
-{
-  struct GAS_PROPORTIONAL_Handle *s = solver;
-  struct Network *net_prev;
-  struct Network *net_cur;
-  struct ATS_Address *prev;
-  struct FindBestAddressCtx fba_ctx;
-
-  GNUNET_assert(s != NULL);
-  GNUNET_assert(peer != NULL);
-
-  /* Add to list of pending requests */
-  if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (s->requests,
-                                                          peer))
-  {
-    GNUNET_assert (GNUNET_OK ==
-                  GNUNET_CONTAINER_multipeermap_put (s->requests,
-                                                     peer, NULL,
-                                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  }
-
-  /* Get address with: stick to current address, lower distance, lower latency 
*/
-  fba_ctx.s = s;
-  fba_ctx.best = NULL;
-
-  GNUNET_CONTAINER_multipeermap_get_multiple (s->addresses, peer,
-                                             &find_best_address_it, &fba_ctx);
-  if (NULL == fba_ctx.best)
-  {
-    LOG(GNUNET_ERROR_TYPE_INFO, "Cannot suggest address for peer `%s'\n",
-        GNUNET_i2s (peer));
-    return NULL ;
-  }
-
-  LOG(GNUNET_ERROR_TYPE_INFO, "Suggesting %s address %p for peer `%s'\n",
-      (GNUNET_NO == fba_ctx.best->active) ? "inactive" : "active", 
fba_ctx.best,
-      GNUNET_i2s (peer));
-  net_cur = (struct Network *) fba_ctx.best->solver_information;
-  if (NULL == fba_ctx.best)
-  {
-    LOG(GNUNET_ERROR_TYPE_ERROR,
-        "Trying to suggesting unknown address peer `%s'\n", GNUNET_i2s (peer));
-    GNUNET_break(0);
-    return NULL ;
-  }
-  if (GNUNET_YES == fba_ctx.best->active)
-  {
-    /* This address was selected previously, so no need to update quotas */
-    return fba_ctx.best;
-  }
-
-  /* This address was not active, so we have to:
-   *
-   * - mark previous active address as not active
-   * - update quota for previous address network
-   * - update quota for this address network
-   */
-  prev = get_active_address (s,
-                            s->addresses, peer);
-  if (NULL != prev)
-  {
-    net_prev = (struct Network *) prev->solver_information;
-    prev->active = GNUNET_NO; /* No active any longer */
-    prev->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */
-    prev->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */
-    if (GNUNET_SYSERR == addresse_decrement (s, net_prev, GNUNET_NO, 
GNUNET_YES))
-      GNUNET_break(0);
-    distribute_bandwidth_in_network (s, net_prev, NULL );
-  }
-
-  if (GNUNET_NO == (is_bandwidth_available_in_network 
(fba_ctx.best->solver_information)))
-  {
-    GNUNET_break(0); /* This should never happen*/
-    return NULL ;
-  }
-
-  fba_ctx.best->active = GNUNET_YES;
-  addresse_increment (s, net_cur, GNUNET_NO, GNUNET_YES);
-  distribute_bandwidth_in_network (s, net_cur, fba_ctx.best );
-  return fba_ctx.best;
-}
-
-/**
- * Stop notifying about address and bandwidth changes for this peer
- *
- * @param solver the solver handle
- * @param peer the peer
- */
-void
-GAS_proportional_stop_get_preferred_address (void *solver,
-    const struct GNUNET_PeerIdentity *peer)
-{
-  struct GAS_PROPORTIONAL_Handle *s = solver;
-  struct ATS_Address *cur;
-  struct Network *cur_net;
-
-  if (GNUNET_YES
-      == GNUNET_CONTAINER_multipeermap_contains (s->requests,
-                                                peer))
-    GNUNET_CONTAINER_multipeermap_remove (s->requests, peer,
-                                         NULL);
-
-  cur = get_active_address (s,
-                           s->addresses, peer);
-  if (NULL != cur)
-  {
-    /* Disabling current address */
-    cur_net = (struct Network *) cur->solver_information;
-    cur->active = GNUNET_NO; /* No active any longer */
-    cur->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */
-    cur->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */
-    if (GNUNET_SYSERR == addresse_decrement (s, cur_net, GNUNET_NO, 
GNUNET_YES))
-      GNUNET_break(0);
-    distribute_bandwidth_in_network (s, cur_net, NULL );
-  }
-  return;
-}
-
-/**
- * Remove an address from the solver
- *
- * @param solver the solver handle
- * @param address the address to remove
- * @param session_only delete only session not whole address
- */
-void
-GAS_proportional_address_delete (void *solver, struct ATS_Address *address,
-    int session_only)
-{
-  struct GAS_PROPORTIONAL_Handle *s = solver;
-  struct Network *net;
-  struct AddressWrapper *aw;
-  const struct ATS_Address *new_address;
-
-
-  /* Remove an adress completely, we have to:
-   * - Remove from specific network
-   * - Decrease number of total addresses
-   * - If active:
-   *   - decrease number of active addreses
-   *   - update quotas
-   */
-
-  net = (struct Network *) address->solver_information;
-
-  if (GNUNET_NO == session_only)
-  {
-    LOG(GNUNET_ERROR_TYPE_INFO,
-        "Deleting %s address %p for peer `%s' from network `%s' (total: %u/ 
active: %u)\n",
-        (GNUNET_NO == address->active) ? "inactive" : "active", address,
-        GNUNET_i2s (&address->peer), net->desc, net->total_addresses,
-        net->active_addresses);
-
-    /* Remove address */
-    addresse_decrement (s, net, GNUNET_YES, GNUNET_NO);
-    for (aw = net->head; NULL != aw; aw = aw->next)
-    {
-      if (aw->addr == address)
-        break;
-    }
-    if (NULL == aw)
-    {
-      GNUNET_break(0);
-      return;
-    }
-    GNUNET_CONTAINER_DLL_remove(net->head, net->tail, aw);
-    GNUNET_free(aw);
-  }
-  else
-  {
-    /* Remove session only: remove if active and update */
-    LOG(GNUNET_ERROR_TYPE_INFO,
-        "Deleting %s session %p for peer `%s' from network `%s' (total: %u/ 
active: %u)\n",
-        (GNUNET_NO == address->active) ? "inactive" : "active", address,
-        GNUNET_i2s (&address->peer), net->desc, net->total_addresses,
-        net->active_addresses);
-  }
-
-  if (GNUNET_YES == address->active)
-  {
-    /* Address was active, remove from network and update quotas*/
-    address->active = GNUNET_NO;
-    address->assigned_bw_in = BANDWIDTH_ZERO;
-    address->assigned_bw_out = BANDWIDTH_ZERO;
-
-    if (GNUNET_SYSERR == addresse_decrement (s, net, GNUNET_NO, GNUNET_YES))
-      GNUNET_break(0);
-    distribute_bandwidth_in_network (s, net, NULL );
-    if (NULL == (new_address = GAS_proportional_get_preferred_address (s, 
&address->peer)))
-    {
-      /* No alternative address found, disconnect peer */
-      s->bw_changed (s->bw_changed_cls, address);
-    }
-    else
-    {
-      s->bw_changed (s->bw_changed_cls, (struct ATS_Address *) new_address);
-    }
-  }
-  LOG(GNUNET_ERROR_TYPE_DEBUG,
-      "After deleting address now total %u and active %u addresses in network 
`%s'\n",
-      net->total_addresses, net->active_addresses, net->desc);
-
-}
-
-/**
- * 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_DEBUG, "No lock pending, recalculating\n");
-    distribute_bandwidth_in_all_networks (s);
-    s->bulk_requests = 0;
-  }
-}
-
-
-/**
- * Add a new single address to a network
- *
- * @param solver the solver Handle
- * @param address the address to add
- * @param network network type of this address
- */
-void
-GAS_proportional_address_add (void *solver, struct ATS_Address *address,
-    uint32_t network);
-
-/**
- * Transport properties for this address have changed
- *
- * @param solver solver handle
- * @param address the address
- * @param type the ATSI type in HBO
- * @param abs_value the absolute value of the property
- * @param rel_value the normalized value
- */
-void
-GAS_proportional_address_property_changed (void *solver,
-    struct ATS_Address *address, uint32_t type, uint32_t abs_value,
-    double rel_value)
-{
-  struct GAS_PROPORTIONAL_Handle *s;
-  struct Network *n;
-
-  GNUNET_assert(NULL != solver);
-  GNUNET_assert(NULL != address);
-
-  s = (struct GAS_PROPORTIONAL_Handle *) solver;
-  n = (struct Network *) address->solver_information;
-
-  if (NULL == n)
-  {
-    GNUNET_break(0);
-    return;
-  }
-
-  LOG(GNUNET_ERROR_TYPE_DEBUG,
-      "Property `%s' for peer `%s' address %p changed to %.2f \n",
-      GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer),
-      address, rel_value);
-  switch (type)
-  {
-  case GNUNET_ATS_UTILIZATION_UP:
-  case GNUNET_ATS_UTILIZATION_DOWN:
-  case GNUNET_ATS_QUALITY_NET_DELAY:
-  case GNUNET_ATS_QUALITY_NET_DISTANCE:
-  case GNUNET_ATS_COST_WAN:
-  case GNUNET_ATS_COST_LAN:
-  case GNUNET_ATS_COST_WLAN:
-    distribute_bandwidth_in_network (s, n, GNUNET_NO);
-    break;
-  }
-}
-
-/**
- * Transport session for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param cur_session the current session
- * @param new_session the new session
- */
-void
-GAS_proportional_address_session_changed (void *solver,
-    struct ATS_Address *address, uint32_t cur_session, uint32_t new_session)
-{
-  if (cur_session != new_session)
-  {
-    LOG(GNUNET_ERROR_TYPE_DEBUG, "Session changed from %u to %u\n", 
cur_session,
-        new_session);
-  }
-}
-
-/**
- * Usage for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param in_use usage state
- */
-void
-GAS_proportional_address_inuse_changed (void *solver,
-    struct ATS_Address *address, int in_use)
-{
-  LOG(GNUNET_ERROR_TYPE_DEBUG, "Usage changed to %s\n",
-      (GNUNET_YES == in_use) ? "USED" : "UNUSED");
-}
-
-/**
- * Network scope for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param current_network the current network
- * @param new_network the new network
- */
-void
-GAS_proportional_address_change_network (void *solver,
-    struct ATS_Address *address, uint32_t current_network, uint32_t 
new_network)
-{
-  struct ATS_Address *new;
-  struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) 
solver;
-  int save_active = GNUNET_NO;
-  struct Network *new_net = NULL;
-
-  if (current_network == new_network)
-  {
-    GNUNET_break(0);
-    return;
-  }
-
-  /* Network changed */
-  LOG(GNUNET_ERROR_TYPE_DEBUG,
-      "Network type changed, moving %s address from `%s' to `%s'\n",
-      (GNUNET_YES == address->active) ? "active" : "inactive",
-      GNUNET_ATS_print_network_type (current_network),
-      GNUNET_ATS_print_network_type (new_network));
-
-  save_active = address->active;
-
-  /* Disable and assign no bandwidth */
-  address->active = GNUNET_NO;
-  address->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */
-  address->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */
-
-  /* Remove from old network */
-  GAS_proportional_address_delete (solver, address, GNUNET_NO);
-
-  /* Set new network type */
-  if (NULL == (new_net = get_network (solver, new_network)))
-  {
-    /* Address changed to invalid network... */
-    LOG(GNUNET_ERROR_TYPE_ERROR,
-        _("Invalid network type `%u' `%s': Disconnect!\n"), new_network,
-        GNUNET_ATS_print_network_type (new_network));
-
-    /* Find new address to suggest since no bandwidth in network*/
-    if (NULL == (new = (struct ATS_Address *) 
GAS_proportional_get_preferred_address (s, &address->peer)))
-    {
-      /* No alternative address found, disconnect peer */
-      s->bw_changed (s->bw_changed_cls, address);
-    }
-    return;
-  }
-
-  /* Add to new network and update*/
-  address->solver_information = new_net;
-  GAS_proportional_address_add (solver, address, new_network);
-  if (GNUNET_YES == save_active)
-  {
-    /* check if bandwidth available in new network */
-    if (GNUNET_YES == (is_bandwidth_available_in_network (new_net)))
-    {
-      /* Assign bandwidth to updated address */
-      address->active = GNUNET_YES;
-      addresse_increment (s, new_net, GNUNET_NO, GNUNET_YES);
-      distribute_bandwidth_in_network (solver, new_net, NULL );
-    }
-    else
-    {
-      LOG(GNUNET_ERROR_TYPE_DEBUG,
-          "Not enough bandwidth in new network, suggesting alternative address 
..\n");
-      /* Find new address to suggest since no bandwidth in network*/
-      if (NULL
-          == (new =
-              (struct ATS_Address *) GAS_proportional_get_preferred_address (s,
-                  &address->peer)))
-      {
-        /* No alternative address found, disconnect peer */
-        s->bw_changed (s->bw_changed_cls, address);
-      }
-    }
-  }
-}
-
-/**
- * Add a new single address to a network
- *
- * @param solver the solver Handle
- * @param address the address to add
- * @param network network type of this address
- */
-void
-GAS_proportional_address_add (void *solver, struct ATS_Address *address,
-    uint32_t network)
-{
-  struct GAS_PROPORTIONAL_Handle *s = solver;
-  struct Network *net = NULL;
-  struct AddressWrapper *aw = NULL;
-  const struct ATS_Address *new_address;
-
-  GNUNET_assert(NULL != s);
-
-
-  net = get_network (s, network);
-  if (NULL == net)
-  {
-    GNUNET_break(0);
-    return;
-  }
-
-  aw = GNUNET_malloc (sizeof (struct AddressWrapper));
-  aw->addr = address;
-  GNUNET_CONTAINER_DLL_insert(net->head, net->tail, aw);
-  addresse_increment (s, net, GNUNET_YES, GNUNET_NO);
-  aw->addr->solver_information = net;
-
-  if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (s->requests, 
&address->peer))
-  {
-    if (NULL == get_active_address (s, s->addresses, &address->peer))
-    {
-      if (NULL != (new_address = GAS_proportional_get_preferred_address (s, 
&address->peer)))
-          s->bw_changed (s->bw_changed_cls, (struct ATS_Address *) address);
-    }
-  }
-  LOG(GNUNET_ERROR_TYPE_DEBUG,
-      "After adding address now total %u and active %u addresses in network 
`%s'\n",
-      net->total_addresses, net->active_addresses, net->desc);
-}
-
-/**
- * Init the proportional problem solver
- *
- * Quotas:
- * network[i] contains the network type as type GNUNET_ATS_NetworkType[i]
- * out_quota[i] contains outbound quota for network type i
- * in_quota[i] contains inbound quota for network type i
- *
- * Example
- * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, 
GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN}
- * network[2]   == GNUNET_ATS_NET_LAN
- * out_quota[2] == 65353
- * in_quota[2]  == 65353
- *
- * @param cfg configuration handle
- * @param stats the GNUNET_STATISTICS handle
- * @param addresses hashmap containing all addresses
- * @param network array of GNUNET_ATS_NetworkType with length dest_length
- * @param out_quota array of outbound quotas
- * @param in_quota array of outbound quota
- * @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
- * @param get_properties for callback to get relative properties
- * @param get_properties_cls cls for callback to get relative properties
- * @return handle for the solver on success, NULL on fail
- */
-void *
-GAS_proportional_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                      const struct GNUNET_STATISTICS_Handle *stats,
-                      const struct GNUNET_CONTAINER_MultiPeerMap *addresses, 
int *network,
-                      unsigned long long *out_quota, unsigned long long 
*in_quota,
-                      int dest_length, GAS_bandwidth_changed_cb bw_changed_cb,
-                      void *bw_changed_cb_cls, GAS_get_preferences 
get_preference,
-                      void *get_preference_cls, GAS_get_properties 
get_properties,
-                      void *get_properties_cls)
-{
-  int c;
-  struct GAS_PROPORTIONAL_Handle *s =
-      GNUNET_malloc (sizeof (struct GAS_PROPORTIONAL_Handle));
-  struct Network * cur;
-  char * net_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
-
-  GNUNET_assert(NULL != cfg);
-  GNUNET_assert(NULL != stats);
-  GNUNET_assert(NULL != network);
-  GNUNET_assert(NULL != bw_changed_cb);
-  GNUNET_assert(NULL != get_preference);
-  GNUNET_assert(NULL != get_properties);
-
-  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->get_properties = get_properties;
-  s->get_properties_cls = get_properties_cls;
-  s->networks = dest_length;
-  s->network_entries = GNUNET_malloc (dest_length * sizeof (struct Network));
-  s->active_addresses = 0;
-  s->total_addresses = 0;
-  s->bulk_lock = GNUNET_NO;
-  s->addresses = addresses;
-
-  s->requests = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
-
-  for (c = 0; c < dest_length; c++)
-  {
-    cur = &s->network_entries[c];
-    cur->total_addresses = 0;
-    cur->active_addresses = 0;
-    cur->type = network[c];
-    cur->total_quota_in = in_quota[c];
-    cur->total_quota_out = out_quota[c];
-    cur->desc = net_str[c];
-    GNUNET_asprintf (&cur->stat_total, "# ATS addresses %s total", cur->desc);
-    GNUNET_asprintf (&cur->stat_active, "# ATS active addresses %s total",
-        cur->desc);
-  }
-  return s;
-}
-
-/**
- * Shutdown the proportional problem solver
- *
- * @param solver the respective handle to shutdown
- */
-void
-GAS_proportional_done (void *solver)
-{
-  struct GAS_PROPORTIONAL_Handle *s = solver;
-  struct AddressWrapper *cur;
-  struct AddressWrapper *next;
-  int c;
-  GNUNET_assert(s != NULL);
-
-  for (c = 0; c < s->networks; c++)
-  {
-    if (s->network_entries[c].total_addresses > 0)
-    {
-      LOG(GNUNET_ERROR_TYPE_ERROR,
-          "Had %u addresses for network `%s' not deleted during shutdown\n",
-          s->network_entries[c].total_addresses, s->network_entries[c].desc);
-      GNUNET_break(0);
-    }
-
-    if (s->network_entries[c].active_addresses > 0)
-    {
-      LOG(GNUNET_ERROR_TYPE_ERROR,
-          "Had %u active addresses for network `%s' not deleted during 
shutdown\n",
-          s->network_entries[c].active_addresses, s->network_entries[c].desc);
-      GNUNET_break(0);
-    }
-
-    next = s->network_entries[c].head;
-    while (NULL != (cur = next))
-    {
-      next = cur->next;
-      GNUNET_CONTAINER_DLL_remove(s->network_entries[c].head,
-          s->network_entries[c].tail, cur);
-      GNUNET_free(cur);
-    }
-    GNUNET_free(s->network_entries[c].stat_total);
-    GNUNET_free(s->network_entries[c].stat_active);
-  }
-  if (s->total_addresses > 0)
-  {
-    LOG(GNUNET_ERROR_TYPE_ERROR,
-        "Had %u addresses not deleted during shutdown\n", s->total_addresses);
-    GNUNET_break(0);
-  }
-  if (s->active_addresses > 0)
-  {
-    LOG(GNUNET_ERROR_TYPE_ERROR,
-        "Had %u active addresses not deleted during shutdown\n",
-        s->active_addresses);
-    GNUNET_break (0);
-  }
-  GNUNET_free (s->network_entries);
-  GNUNET_CONTAINER_multipeermap_destroy (s->requests);
-  GNUNET_free (s);
-}
-
-/* end of gnunet-service-ats-solver_proportional.c */

Deleted: gnunet/src/ats/gnunet-service-ats-solver_proportional.h
===================================================================
--- gnunet/src/ats/gnunet-service-ats-solver_proportional.h     2013-10-08 
15:43:03 UTC (rev 29997)
+++ gnunet/src/ats/gnunet-service-ats-solver_proportional.h     2013-10-08 
16:34:07 UTC (rev 29998)
@@ -1,224 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2011 Christian Grothoff (and other contributing authors)
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- 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.
- */
-
-/**
- * @file ats/gnunet-service-ats-solver_proportional.h
- * @brief ATS proportional solver
- * @author Matthias Wachs
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_statistics_service.h"
-#include "gnunet-service-ats_addresses.h"
-
-/**
- * ATS proportional solver
- *
- * General description
- */
-
-/**
- * Changes the preferences for a peer in the problem
- *
- * @param solver the solver handle
- * @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
- */
-void
-GAS_proportional_address_change_preference (void *solver,
-    const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind 
kind,
-    double pref_rel);
-
-/**
- * Get application feedback for a peer
- *
- * @param solver the solver handle
- * @param application the application
- * @param peer the peer to change the preference for
- * @param scope the time interval for this feedback: [now - scope .. now]
- * @param kind the kind to change the preference
- * @param score the score
- */
-void
-GAS_proportional_address_preference_feedback (void *solver, void *application,
-    const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_TIME_Relative scope,
-    enum GNUNET_ATS_PreferenceKind kind, double score);
-
-/**
- * Init the proportional problem solver
- *
- * Quotas:
- * network[i] contains the network type as type GNUNET_ATS_NetworkType[i]
- * out_quota[i] contains outbound quota for network type i
- * in_quota[i] contains inbound quota for network type i
- *
- * Example
- * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, 
GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN}
- * network[2]   == GNUNET_ATS_NET_LAN
- * out_quota[2] == 65353
- * in_quota[2]  == 65353
- *
- * @param cfg configuration handle
- * @param stats the GNUNET_STATISTICS handle
- * @param network array of GNUNET_ATS_NetworkType with length dest_length
- * @param addresses hashmap containing all addresses
- * @param out_quota array of outbound quotas
- * @param in_quota array of outbound quota
- * @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
- * @param get_properties_cls for callback to get relative properties
- * @param get_properties_cls cls for callback to get relative properties
- * @return handle for the solver on success, NULL on fail
- */
-void *
-GAS_proportional_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
-    const struct GNUNET_STATISTICS_Handle *stats,
-    const struct GNUNET_CONTAINER_MultiPeerMap *addresses, int *network,
-    unsigned long long *out_quota, unsigned long long *in_quota,
-    int dest_length, GAS_bandwidth_changed_cb bw_changed_cb,
-    void *bw_changed_cb_cls, GAS_get_preferences get_preference,
-    void *get_preference_cls, GAS_get_properties get_properties,
-    void *get_properties_cls);
-
-/**
- * Shutdown the proportional problem solver
- *
- * @param solver the respective handle to shutdown
- */
-void
-GAS_proportional_done (void * solver);
-
-/**
- * Add a single address within a network to the solver
- *
- * @param solver the solver Handle
- * @param address the address to add
- * @param network network type of this address
- */
-void
-GAS_proportional_address_add (void *solver, struct ATS_Address *address,
-    uint32_t network);
-
-/**
- * Transport properties for this address have changed
- *
- * @param solver solver handle
- * @param address the address
- * @param type the ATSI type in HBO
- * @param abs_value the absolute value of the property
- * @param rel_value the normalized value
- */
-void
-GAS_proportional_address_property_changed (void *solver,
-    struct ATS_Address *address, uint32_t type, uint32_t abs_value,
-    double rel_value);
-
-/**
- * Transport session for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param cur_session the current session
- * @param new_session the new session
- */
-void
-GAS_proportional_address_session_changed (void *solver,
-    struct ATS_Address *address, uint32_t cur_session, uint32_t new_session);
-
-/**
- * Usage for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param in_use usage state
- */
-void
-GAS_proportional_address_inuse_changed (void *solver,
-    struct ATS_Address *address, int in_use);
-
-/**
- * Network scope for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param current_network the current network
- * @param new_network the new network
- */
-void
-GAS_proportional_address_change_network (void *solver,
-    struct ATS_Address *address, uint32_t current_network, uint32_t 
new_network);
-
-/**
- * Remove an address from the solver
- *
- * @param solver the solver handle
- * @param address the address to remove
- * @param session_only delete only session not whole address
- */
-void
-GAS_proportional_address_delete (void *solver, struct ATS_Address *address,
-    int session_only);
-
-/**
- * Start a bulk operation
- *
- * @param solver the solver
- */
-void
-GAS_proportional_bulk_start (void *solver);
-
-/**
- * Bulk operation done
- */
-void
-GAS_proportional_bulk_stop (void *solver);
-
-/**
- * Stop notifying about address and bandwidth changes for this peer
- *
- * @param solver the proportional handle
- * @param peer the peer
- */
-void
-GAS_proportional_stop_get_preferred_address (void *solver,
-    const struct GNUNET_PeerIdentity *peer);
-
-/**
- * Get the prefered address for a specific peer
- *
- * @param solver the solver handle
- * @param peer the identity of the peer
- */
-const struct ATS_Address *
-GAS_proportional_get_preferred_address (void *solver,
-    const struct GNUNET_PeerIdentity *peer);
-
-/* end of gnunet-service-ats-solver_proportional.c */

Modified: gnunet/src/ats/gnunet-service-ats_addresses.c
===================================================================
--- gnunet/src/ats/gnunet-service-ats_addresses.c       2013-10-08 15:43:03 UTC 
(rev 29997)
+++ gnunet/src/ats/gnunet-service-ats_addresses.c       2013-10-08 16:34:07 UTC 
(rev 29998)
@@ -26,17 +26,21 @@
  */
 #include "platform.h"
 #include "gnunet_ats_service.h"
+#include "gnunet_ats_plugin.h"
 #include "gnunet-service-ats.h"
 #include "gnunet-service-ats_addresses.h"
 #include "gnunet-service-ats_normalization.h"
 #include "gnunet-service-ats_performance.h"
 #include "gnunet-service-ats_scheduling.h"
 #include "gnunet-service-ats_reservations.h"
+
+#if 0
 #if HAVE_LIBGLPK
 #include "gnunet-service-ats-solver_mlp.h"
 #endif
 #include "gnunet-service-ats-solver_proportional.h"
 #include "gnunet-service-ats-solver_ril.h"
+#endif
 
 /**
  * NOTE: Do not change this documentation. This documentation is based on
@@ -332,64 +336,9 @@
   struct GAS_Addresses_Suggestion_Requests *r_tail;
 
   /* Solver functions */
+  struct GNUNET_ATS_PluginEnvironment env;
 
-  /**
-   * Initialize solver
-   */
-  GAS_solver_init s_init;
-
-  /**
-   * Add an address to the solver
-   */
-  GAS_solver_address_add s_add;
-
-  GAS_solver_address_property_changed s_address_update_property;
-
-  GAS_solver_address_session_changed s_address_update_session;
-
-  GAS_solver_address_inuse_changed s_address_update_inuse;
-
-  GAS_solver_address_network_changed s_address_update_network;
-
-  /**
-   * Get address from solver
-   */
-  GAS_solver_get_preferred_address s_get;
-
-  /**
-   * Get address from solver
-   */
-  GAS_solver_stop_get_preferred_address s_get_stop;
-
-  /**
-   * Delete address in solver
-   */
-  GAS_solver_address_delete s_del;
-
-  /**
-   * Change relative preference for quality in solver
-   */
-  GAS_solver_address_change_preference s_pref;
-
-  /**
-   * Give feedback about the current assignment
-   */
-  GAS_solver_address_feedback_preference s_feedback;
-
-  /**
-   * Start a bulk operation
-   */
-  GAS_solver_bulk_start s_bulk_start;
-
-  /**
-   * Bulk operation done
-   */
-  GAS_solver_bulk_stop s_bulk_stop;
-
-  /**
-   * Shutdown solver
-   */
-  GAS_solver_done s_done;
+  char *plugin;
 };
 
 /**
@@ -805,12 +754,12 @@
         GNUNET_ATS_print_network_type (addr_net));
 
     /* Tell solver about new address */
-    handle->s_add (handle->solver, new_address, addr_net);
+    handle->env.sf.s_add (handle->solver, new_address, addr_net);
 
-    handle->s_bulk_start (handle->solver);
+    handle->env.sf.s_bulk_start (handle->solver);
     GAS_normalization_normalize_property (handle->addresses, new_address, atsi,
         atsi_count);
-    handle->s_bulk_stop (handle->solver);
+    handle->env.sf.s_bulk_stop (handle->solver);
 
     /* Notify performance clients about new address */
     GAS_performance_notify_all_clients (&new_address->peer, 
new_address->plugin,
@@ -866,7 +815,7 @@
             GNUNET_i2s (peer), existing_address,
             GNUNET_ATS_print_network_type (addr_net),
             GNUNET_ATS_print_network_type (ntohl (atsi_delta[c1].value)));
-        handle->s_address_update_network (handle->solver, existing_address,
+        handle->env.sf.s_address_update_network (handle->solver, 
existing_address,
             ntohl (atsi_delta[c1].value),
             get_performance_info (existing_address, GNUNET_ATS_NETWORK_TYPE));
         addr_net = get_performance_info (existing_address,
@@ -874,10 +823,10 @@
       }
     }
     /* Notify solver about update with atsi information and session */
-    handle->s_bulk_start (handle->solver);
+    handle->env.sf.s_bulk_start (handle->solver);
     GAS_normalization_normalize_property (handle->addresses, existing_address,
         atsi, atsi_count);
-    handle->s_bulk_stop (handle->solver);
+    handle->env.sf.s_bulk_stop (handle->solver);
   }
   GNUNET_free_non_null(atsi_delta);
 
@@ -887,7 +836,7 @@
 
   previous_session = existing_address->session_id;
   existing_address->session_id = session_id;
-  handle->s_address_update_session (handle->solver, existing_address,
+  handle->env.sf.s_address_update_session (handle->solver, existing_address,
       previous_session, session_id);
 
   GNUNET_log(GNUNET_ERROR_TYPE_INFO,
@@ -956,7 +905,7 @@
     /* Session changed */
     prev_session = aa->session_id;
     aa->session_id = session_id;
-    handle->s_address_update_session (handle->solver, aa, prev_session,
+    handle->env.sf.s_address_update_session (handle->solver, aa, prev_session,
         aa->session_id);
   }
 
@@ -972,7 +921,7 @@
       if (GNUNET_ATS_NETWORK_TYPE == ntohl (atsi_delta[c1].type))
       {
         /* Network type changed */
-        handle->s_address_update_network (handle->solver, aa,
+        handle->env.sf.s_address_update_network (handle->solver, aa,
             ntohl (atsi_delta[c1].value),
             get_performance_info (aa, GNUNET_ATS_NETWORK_TYPE));
       }
@@ -983,10 +932,10 @@
         aa->addr_len, aa->session_id, aa->atsi, aa->atsi_count,
         aa->assigned_bw_out, aa->assigned_bw_in);
 
-    handle->s_bulk_start (handle->solver);
+    handle->env.sf.s_bulk_start (handle->solver);
     GAS_normalization_normalize_property (handle->addresses, aa, atsi,
         atsi_count);
-    handle->s_bulk_stop (handle->solver);
+    handle->env.sf.s_bulk_stop (handle->solver);
   }
   GNUNET_free_non_null(atsi_delta);
 }
@@ -1046,7 +995,7 @@
           GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove 
(handle->addresses,
                                                              &aa->peer,
                                                              aa));
-      handle->s_del (handle->solver, aa, GNUNET_NO);
+      handle->env.sf.s_del (handle->solver, aa, GNUNET_NO);
       free_address (aa);
       dc->result = GNUNET_NO;
       return GNUNET_OK; /* Continue iteration */
@@ -1078,7 +1027,7 @@
       GNUNET_assert(
           GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove 
(handle->addresses,
                                                              &aa->peer, aa));
-      handle->s_del (handle->solver, aa, GNUNET_NO);
+      handle->env.sf.s_del (handle->solver, aa, GNUNET_NO);
       free_address (aa);
       dc->result = GNUNET_NO;
       return GNUNET_OK; /* Continue iteration */
@@ -1090,7 +1039,7 @@
           "Deleting session for peer `%s': `%s' %u\n", GNUNET_i2s (&aa->peer),
           aa->plugin, aa->session_id);
       /* Notify solver to delete session */
-      handle->s_del (handle->solver, aa, GNUNET_YES);
+      handle->env.sf.s_del (handle->solver, aa, GNUNET_YES);
       aa->session_id = 0;
       aa->active = GNUNET_NO;
       return GNUNET_OK;
@@ -1203,7 +1152,7 @@
 
   /* Tell solver about update */
   ea->used = in_use;
-  handle->s_address_update_inuse (handle->solver, ea, ea->used);
+  handle->env.sf.s_address_update_inuse (handle->solver, ea, ea->used);
   return GNUNET_OK;
 }
 
@@ -1236,7 +1185,7 @@
         GNUNET_i2s (peer));
     return;
   }
-  handle->s_get_stop (handle->solver, peer);
+  handle->env.sf.s_get_stop (handle->solver, peer);
   GAS_addresses_handle_backoff_reset (handle, peer);
   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Removed request pending for peer `%s\n",
       GNUNET_i2s (peer));
@@ -1287,7 +1236,7 @@
    */
 
   /* Get prefered address from solver */
-  aa = (struct ATS_Address *) handle->s_get (handle->solver, peer);
+  aa = (struct ATS_Address *) handle->env.sf.s_get (handle->solver, peer);
   if (NULL == aa)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Cannot suggest address for peer 
`%s'\n",
@@ -1378,7 +1327,7 @@
   struct GAS_Addresses_Handle *handle = cls;
 
   /* Tell solver about update */
-  handle->s_pref (handle->solver, peer, kind, pref_rel);
+  handle->env.sf.s_pref (handle->solver, peer, kind, pref_rel);
 }
 
 /**
@@ -1401,7 +1350,7 @@
       GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer),
       prop_rel);
 
-  ah->s_address_update_property (ah->solver, address, type, 0, prop_rel);
+  ah->env.sf.s_address_update_property (ah->solver, address, type, 0, 
prop_rel);
 }
 
 /**
@@ -1463,10 +1412,10 @@
     return;
   }
 
-  handle->s_bulk_start (handle->solver);
+  handle->env.sf.s_bulk_start (handle->solver);
   /* Tell normalization about change, normalization will call callback if 
preference changed */
   GAS_normalization_normalize_preference (client, peer, kind, score_abs);
-  handle->s_bulk_stop (handle->solver);
+  handle->env.sf.s_bulk_stop (handle->solver);
 }
 
 /**
@@ -1502,7 +1451,7 @@
     return;
   }
 
-  handle->s_feedback (handle->solver, application, peer, scope, kind,
+  handle->env.sf.s_feedback (handle->solver, application, peer, scope, kind,
       score_abs);
 }
 
@@ -1704,11 +1653,10 @@
     const struct GNUNET_STATISTICS_Handle *stats)
 {
   struct GAS_Addresses_Handle *ah;
-  int quotas[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
   unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount];
   unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount];
-  int quota_count;
   char *mode_str;
+  char *plugin_short;
   int c;
 
   ah = GNUNET_malloc (sizeof (struct GAS_Addresses_Handle));
@@ -1734,20 +1682,24 @@
     if (0 == strcmp (mode_str, "PROPORTIONAL"))
     {
       ah->ats_mode = MODE_PROPORTIONAL;
+      plugin_short = "proportional";
     }
     else if (0 == strcmp (mode_str, "MLP"))
     {
       ah->ats_mode = MODE_MLP;
+      plugin_short = "mlp";
 #if !HAVE_LIBGLPK
       GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
           "Assignment method `%s' configured, but GLPK is not available, 
please install \n",
           mode_str);
       ah->ats_mode = MODE_PROPORTIONAL;
+      plugin_short = "proportional";
 #endif
     }
     else if (0 == strcmp (mode_str, "RIL"))
     {
       ah->ats_mode = MODE_RIL;
+      plugin_short = "ril";
     }
     else
     {
@@ -1755,100 +1707,56 @@
           "Invalid resource assignment method `%s' configured, using 
proportional approach\n",
           mode_str);
       ah->ats_mode = MODE_PROPORTIONAL;
+      plugin_short = "proportional";
     }
     GNUNET_free(mode_str);
   }
-  /* Start configured solution method */
-  switch (ah->ats_mode)
+
+  load_quotas (cfg, quotas_in, quotas_out, GNUNET_ATS_NetworkTypeCount);
+  ah->env.bandwidth_changed_cb = &bandwidth_changed_cb;
+  ah->env.bw_changed_cb_cls = ah;
+  ah->env.get_preferences_cb = &get_preferences_cb;
+  ah->env.get_preference_cls = ah;
+  ah->env.get_property_cb = &get_property_cb;
+  ah->env.get_property_cls = ah;
+  ah->env.cfg = cfg;
+  ah->env.stats = stats;
+  ah->env.addresses = ah->addresses;
+
+  ah->env.network_count = GNUNET_ATS_NetworkTypeCount;
+  int networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
+  for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
   {
-  case MODE_MLP:
-    /* Init the MLP solver with default values */
-#if HAVE_LIBGLPK
-    ah->s_init = &GAS_mlp_init;
-    ah->s_add = &GAS_mlp_address_add;
-    ah->s_address_update_property = &GAS_mlp_address_property_changed;
-    ah->s_address_update_session = &GAS_mlp_address_session_changed;
-    ah->s_address_update_inuse = &GAS_mlp_address_inuse_changed;
-    ah->s_address_update_network = &GAS_mlp_address_change_network;
-    ah->s_get = &GAS_mlp_get_preferred_address;
-    ah->s_get_stop = &GAS_mlp_stop_get_preferred_address;
-    ah->s_pref = &GAS_mlp_address_change_preference;
-    ah->s_feedback = &GAS_mlp_address_preference_feedback;
-    ah->s_del = &GAS_mlp_address_delete;
-    ah->s_bulk_start = &GAS_mlp_bulk_start;
-    ah->s_bulk_stop = &GAS_mlp_bulk_stop;
-    ah->s_done = &GAS_mlp_done;
-#else
-    GNUNET_free(ah);
-    return NULL ;
-#endif
-    break;
-  case MODE_PROPORTIONAL:
-    /* Init the proportional solver with default values */
-    ah->s_init = &GAS_proportional_init;
-    ah->s_add = &GAS_proportional_address_add;
-    ah->s_address_update_property = &GAS_proportional_address_property_changed;
-    ah->s_address_update_session = &GAS_proportional_address_session_changed;
-    ah->s_address_update_inuse = &GAS_proportional_address_inuse_changed;
-    ah->s_address_update_network = &GAS_proportional_address_change_network;
-    ah->s_get = &GAS_proportional_get_preferred_address;
-    ah->s_get_stop = &GAS_proportional_stop_get_preferred_address;
-    ah->s_pref = &GAS_proportional_address_change_preference;
-    ah->s_feedback = &GAS_proportional_address_preference_feedback;
-    ah->s_del = &GAS_proportional_address_delete;
-    ah->s_bulk_start = &GAS_proportional_bulk_start;
-    ah->s_bulk_stop = &GAS_proportional_bulk_stop;
-    ah->s_done = &GAS_proportional_done;
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "ATS started in %s mode\n",
-        "PROPORTIONAL");
-    break;
-  case MODE_RIL:
-    /* Init the ril solver with default values */
-    ah->s_init = &GAS_ril_init;
-    ah->s_add = &GAS_ril_address_add;
-    ah->s_address_update_property = &GAS_ril_address_property_changed;
-    ah->s_address_update_session = &GAS_ril_address_session_changed;
-    ah->s_address_update_inuse = &GAS_ril_address_inuse_changed;
-    ah->s_address_update_network = &GAS_ril_address_change_network;
-    ah->s_get = &GAS_ril_get_preferred_address;
-    ah->s_get_stop = &GAS_ril_stop_get_preferred_address;
-    ah->s_pref = &GAS_ril_address_change_preference;
-    ah->s_feedback = &GAS_ril_address_preference_feedback;
-    ah->s_del = &GAS_ril_address_delete;
-    ah->s_bulk_start = &GAS_ril_bulk_start;
-    ah->s_bulk_stop = &GAS_ril_bulk_stop;
-    ah->s_done = &GAS_ril_done;
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "ATS started in %s mode\n", "RIL");
-    break;
-  default:
-    return NULL ;
-    break;
+    ah->env.networks[c] = networks[c];
+    ah->env.out_quota[c] = quotas_out[c];
+    ah->env.in_quota[c] = quotas_in[c];
   }
 
-  GNUNET_assert (NULL != ah->s_init);
-  GNUNET_assert (NULL != ah->s_add);
-  GNUNET_assert (NULL != ah->s_address_update_inuse);
-  GNUNET_assert (NULL != ah->s_address_update_property);
-  GNUNET_assert (NULL != ah->s_address_update_session);
-  GNUNET_assert (NULL != ah->s_address_update_network);
-  GNUNET_assert (NULL != ah->s_get);
-  GNUNET_assert (NULL != ah->s_get_stop);
-  GNUNET_assert (NULL != ah->s_pref);
-  GNUNET_assert (NULL != ah->s_feedback);
-  GNUNET_assert (NULL != ah->s_del);
-  GNUNET_assert (NULL != ah->s_done);
-  GNUNET_assert (NULL != ah->s_bulk_start);
-  GNUNET_assert (NULL != ah->s_bulk_stop);
+  GNUNET_asprintf (&ah->plugin, "libgnunet_plugin_ats_%s", plugin_short);
+  GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initializing solver `%s '`%s'\n"), 
plugin_short, ah->plugin);
+  if  (NULL == (ah->solver = GNUNET_PLUGIN_load (ah->plugin, &ah->env)))
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver 
`%s'!\n"), ah->plugin);
+    return NULL;
+  }
 
+  GNUNET_assert (NULL != ah->env.sf.s_add);
+  GNUNET_assert (NULL != ah->env.sf.s_address_update_inuse);
+  GNUNET_assert (NULL != ah->env.sf.s_address_update_property);
+  GNUNET_assert (NULL != ah->env.sf.s_address_update_session);
+  GNUNET_assert (NULL != ah->env.sf.s_address_update_network);
+  GNUNET_assert (NULL != ah->env.sf.s_get);
+  GNUNET_assert (NULL != ah->env.sf.s_get_stop);
+  GNUNET_assert (NULL != ah->env.sf.s_pref);
+  GNUNET_assert (NULL != ah->env.sf.s_feedback);
+  GNUNET_assert (NULL != ah->env.sf.s_del);
+  GNUNET_assert (NULL != ah->env.sf.s_bulk_start);
+  GNUNET_assert (NULL != ah->env.sf.s_bulk_stop);
+
+
   GAS_normalization_start (&normalized_preference_changed_cb, ah,
       &normalized_property_changed_cb, ah);
-  quota_count = load_quotas (cfg, quotas_in, quotas_out,
-                            GNUNET_ATS_NetworkTypeCount);
 
-  ah->solver = ah->s_init (cfg, stats, ah->addresses, quotas, quotas_in,
-                          quotas_out, quota_count,
-                          &bandwidth_changed_cb, ah, &get_preferences_cb,
-                          NULL, &get_property_cb, NULL );
   if (NULL == ah->solver)
   {
     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver!\n"));
@@ -1884,7 +1792,7 @@
   GNUNET_assert(GNUNET_YES ==
                GNUNET_CONTAINER_multipeermap_remove (handle->addresses, key, 
value));
   /* Notify */
-  handle->s_del (handle->solver, aa, GNUNET_NO);
+  handle->env.sf.s_del (handle->solver, aa, GNUNET_NO);
   /* Destroy */
   free_address (aa);
 
@@ -1904,12 +1812,12 @@
     return;
 
   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Destroying all addresses\n");
-  handle->s_bulk_start (handle->solver);
+  handle->env.sf.s_bulk_start (handle->solver);
   if (handle->addresses != NULL )
     GNUNET_CONTAINER_multipeermap_iterate (handle->addresses,
                                           &destroy_all_address_it,
                                           handle);
-  handle->s_bulk_start (handle->solver);
+  handle->env.sf.s_bulk_start (handle->solver);
 }
 
 
@@ -1934,7 +1842,9 @@
     GNUNET_CONTAINER_DLL_remove(handle->r_head, handle->r_tail, cur);
     GNUNET_free(cur);
   }
-  handle->s_done (handle->solver);
+
+  GNUNET_PLUGIN_unload (handle->plugin, handle->solver);
+  GNUNET_free (handle->plugin);
   GNUNET_free(handle);
   /* Stop configured solution method */
   GAS_normalization_stop ();

Modified: gnunet/src/ats/gnunet-service-ats_addresses.h
===================================================================
--- gnunet/src/ats/gnunet-service-ats_addresses.h       2013-10-08 15:43:03 UTC 
(rev 29997)
+++ gnunet/src/ats/gnunet-service-ats_addresses.h       2013-10-08 16:34:07 UTC 
(rev 29998)
@@ -348,236 +348,9 @@
   struct GAS_NormalizationInfo atsin[GNUNET_ATS_QualityPropertiesCount];
 };
 
-/**
- * Callback to call from solver when bandwidth for address has changed
- *
- * @param address the with changed bandwidth assigned
- */
-typedef void
-(*GAS_bandwidth_changed_cb) (void *cls, struct ATS_Address *address);
 
-/**
- * Callback to call from solver to obtain application preference values for a
- * peer
- *
- * @param cls the cls
- * @param id the peer id
- * @return carry of double values containing the preferences with
- *     GNUNET_ATS_PreferenceCount elements
- */
-typedef const double *
-(*GAS_get_preferences) (void *cls, const struct GNUNET_PeerIdentity *id);
 
 /**
- * Callback to call from solver to obtain transport properties for an
- * address
- *
- * @param cls the cls
- * @param address the address
- * @return carry of double values containing the preferences with
- *     GNUNET_ATS_PreferenceCount elements
- */
-typedef const double *
-(*GAS_get_properties) (void *cls, const struct ATS_Address *address);
-
-/*
- * Solver API
- * ----------
- */
-
-/**
- * Init the problem solving component
- *
- * Quotas:
- * network[i] contains the network type as type GNUNET_ATS_NetworkType[i]
- * out_quota[i] contains outbound quota for network type i
- * in_quota[i] contains inbound quota for network type i
- *
- * Example
- * network = {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, 
GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN}
- * network[2]   == GNUNET_ATS_NET_LAN
- * out_quota[2] == 65353
- * in_quota[2]  == 65353
- *
- * @param cfg configuration handle
- * @param stats the GNUNET_STATISTICS handle
- * @param addresses hashmap containing all addresses
- * @param network array of GNUNET_ATS_NetworkType with length dest_length
- * @param out_quota array of outbound quotas
- * @param in_quota array of outbound quota
- * @param bw_changed_cb callback to call when assigned changes
- * @return handle for the solver on success, NULL on fail
- */
-typedef void *
-(*GAS_solver_init) (const struct GNUNET_CONFIGURATION_Handle *cfg,
-    const struct GNUNET_STATISTICS_Handle *stats,
-    const struct GNUNET_CONTAINER_MultiPeerMap *addresses, int *network,
-    unsigned long long *out_quota, unsigned long long *in_quota,
-    int dest_length, GAS_bandwidth_changed_cb bw_changed_cb,
-    void *bw_changed_cb_cls, GAS_get_preferences get_preference,
-    void *get_preference_cls, GAS_get_properties get_properties,
-    void *get_properties_cls);
-
-/**
- * Change the preference for a peer
- *
- * @param handle the solver handle
- * @param client the client sending this request
- * @param peer the peer id
- * @param kind the preference kind to change
- * @param score the new preference score
- * @param pref_rel the normalized preference value for this kind over all 
clients
- */
-typedef void
-(*GAS_solver_address_change_preference) (void *solver,
-    const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind 
kind,
-    double pref_rel);
-
-/**
- * Give feedback about the current assignment
- *
- * @param handle the solver handle
- * @param application the application sending this request
- * @param peer the peer id
- * @param scope the time interval for this feedback: [now - scope .. now]
- * @param kind the preference kind for this feedback
- * @param score the feedback score
- */
-typedef void
-(*GAS_solver_address_feedback_preference) (void *solver, void *application,
-    const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_TIME_Relative scope,
-    enum GNUNET_ATS_PreferenceKind kind, double score);
-
-/**
- * Notify the solver about a bulk operation changing possibly a lot of values
- * Solver will not resolve until all bulk operations are marked as done
- *
- * @param solver the solver
- */
-typedef void
-(*GAS_solver_bulk_start) (void *solver);
-
-/**
- * Mark a bulk operation as done
- * Solver will resolve if values have changed
- *
- * @param solver the solver
- */
-typedef void
-(*GAS_solver_bulk_stop) (void *solver);
-
-/**
- * Add a single address within a network to the solver
- *
- * @param solver the solver Handle
- * @param addresses the address hashmap containing all addresses
- * @param address the address to add
- * @param network network type of this address
- */
-typedef void
-(*GAS_solver_address_add) (void *solver, struct ATS_Address *address,
-    uint32_t network);
-
-/**
- * Delete an address or just the session from the solver
- *
- * @param solver the solver Handle
- * @param addresses the address hashmap containing all addresses
- * @param address the address to delete
- * @param session_only remove address or just session
- */
-typedef void
-(*GAS_solver_address_delete) (void *solver, struct ATS_Address *address,
-    int session_only);
-
-/**
- * Transport properties for this address have changed
- *
- * @param solver solver handle
- * @param address the address
- * @param type the ATSI type in HBO
- * @param abs_value the absolute value of the property
- * @param rel_value the normalized value
- */
-typedef void
-(*GAS_solver_address_property_changed) (void *solver,
-    struct ATS_Address *address, uint32_t type, uint32_t abs_value,
-    double rel_value);
-
-/**
- * Transport session for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param cur_session the current session
- * @param new_session the new session
- */
-typedef void
-(*GAS_solver_address_session_changed) (void *solver,
-    struct ATS_Address *address, uint32_t cur_session, uint32_t new_session);
-
-/**
- * Transport session for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param in_use usage state
- */
-typedef void
-(*GAS_solver_address_inuse_changed) (void *solver, struct ATS_Address *address,
-    int in_use);
-
-/**
- * Network scope for this address has changed
- *
- * NOTE: values in addresses are already updated
- *
- * @param solver solver handle
- * @param address the address
- * @param current_network the current network
- * @param new_network the new network
- */
-typedef void
-(*GAS_solver_address_network_changed) (void *solver,
-    struct ATS_Address *address, uint32_t current_network, uint32_t 
new_network);
-
-/**
- * Get the prefered address for a peer from solver
- *
- * @param solver the solver to use
- * @param addresses the address hashmap containing all addresses
- * @param peer the peer
- */
-typedef const struct ATS_Address *
-(*GAS_solver_get_preferred_address) (void *solver,
-    const struct GNUNET_PeerIdentity *peer);
-
-/**
- * Stop getting the prefered address for a peer from solver
- *
- * @param solver the solver to use
- * @param addresses the address hashmap containing all addresses
- * @param peer the peer
- */
-typedef void
-(*GAS_solver_stop_get_preferred_address) (void *solver,
-    const struct GNUNET_PeerIdentity *peer);
-
-/**
- * Shutdown solver
- *
- * @param solver the solver to shutdown
- */
-
-typedef void
-(*GAS_solver_done) (void *solver);
-
-/**
  * Initialize address subsystem. The addresses subsystem manages the addresses
  * known and current performance information. It has a solver component
  * responsible for the resource allocation. It tells the solver about changes

Copied: gnunet/src/ats/libgnunet_plugin_ats_mlp.c (from rev 29953, 
gnunet/src/ats/gnunet-service-ats-solver_mlp.c)
===================================================================
--- gnunet/src/ats/libgnunet_plugin_ats_mlp.c                           (rev 0)
+++ gnunet/src/ats/libgnunet_plugin_ats_mlp.c   2013-10-08 16:34:07 UTC (rev 
29998)
@@ -0,0 +1,2104 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     GNUnet is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published
+     by the Free Software Foundation; either version 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     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.
+*/
+
+/**
+ * @file ats/gnunet-service-ats-solver_mlp.c
+ * @brief ats mlp problem solver
+ * @author Matthias Wachs
+ * @author Christian Grothoff
+ */
+
+#include "libgnunet_plugin_ats_mlp.h"
+
+
+/**
+ *
+ * NOTE: Do not modify this documentation. This documentation is based on
+ * gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex
+ * use build_txt.sh to generate plaintext output
+ *
+ *    The MLP solver (mlp) tries to finds an optimal bandwidth assignmentby
+ *    optimizing an mixed integer programming problem. The MLP solver uses a
+ *    number of constraints to find the best adddress for a peer and an optimal
+ *    bandwidth assignment. mlp uses the GNU Linear Programming Kit to solve 
the
+ *    MLP problem.
+ *
+ *    We defined a constraint system to find an optimal bandwidth assignment.
+ *    This constraint system uses as an input data addresses, bandwidth quotas,
+ *    preferences and quality values. This constraint system is stored in an
+ *    matrix based equotation system.
+ *
+ *   5 Using GLPK
+ *
+ *    A (M)LP problem consists of a target function to optimizes, constraints
+ *    and rows and columns. FIXME GLP uses three arrays to index the matrix: 
two
+ *    integer arrays storing the row and column indices in the matrix and an
+ *    float array to store the coeeficient.
+ *
+ *    To solve the problem we first find an initial solution for the LP problem
+ *    using the LP solver and then find an MLP solution based on this solution
+ *    using the MLP solver.
+ *
+ *    Solving (M)LP problems has the property that finding an initial solution
+ *    for the LP problem is computationally expensive and finding the MLP
+ *    solution is cheaper. This is especially interesting an existing LP
+ *    solution can be reused if only coefficients in the matrix have changed
+ *    (addresses updated). Only when the problem size changes (addresses added
+ *    or deleted) a new LP solution has to be found.
+ *
+ *    Intended usage
+ *    The mlp solver solves the bandwidth assignment problem only on demand 
when
+ *    an address suggestion is requested. When an address is requested mlp the
+ *    solves the mlp problem and if the active address or the bandwidth 
assigned
+ *    changes it calls the callback to addresses. The mlp solver gets notified
+ *    about new addresses (adding sessions), removed addresses (address
+ *    deletions) and address updates. To benefit from the mlp properties
+ *    mentioned in section 5 the solver rembers if since the last solution
+ *    addresses were added or deleted (problem size changed, problem has to be
+ *    rebuild and solved from sratch) or if addresses were updated and the
+ *    existing solution can be reused.
+ *
+ *     5.1 Input data
+ *
+ *    The quotas for each network segment are passed by addresses. MLP can be
+ *    adapted using configuration settings and uses the following parameters:
+ *      * MLP_MAX_DURATION:
+ *        Maximum duration for a MLP solution procees (default: 3 sec.)
+ *      * MLP_MAX_DURATION:
+ *        Maximum number of iterations for a MLP solution process (default:
+ *        1024)
+ *      * MLP_MIN_CONNECTIONS:
+ *        Minimum number of desired connections (default: 4)
+ *      * MLP_MIN_BANDWIDTH:
+ *        Minimum amount of bandwidth assigned to an address (default: 1024)
+ *      * MLP_COEFFICIENT_D:
+ *        Diversity coefficient (default: 1.0)
+ *      * MLP_COEFFICIENT_R:
+ *        Relativity coefficient (default: 1.0)
+ *      * MLP_COEFFICIENT_U:
+ *        Utilization coefficient (default: 1.0)
+ *      * MLP_COEFFICIENT_D:
+ *        Diversity coefficient (default: 1.0)
+ *      * MLP_COEFFICIENT_QUALITY_DELAY:
+ *        Quality delay coefficient (default: 1.0)
+ *      * MLP_COEFFICIENT_QUALITY_DISTANCE:
+ *        Quality distance coefficient (default: 1.0)
+ *      * MLP_COEFFICIENT_QUALITY_DISTANCE:
+ *        Quality distance coefficient (default: 1.0)
+ *      * MLP_COEFFICIENT_QUALITY_DISTANCE:
+ *        Quality distance coefficient (default: 1.0)
+ *      * MLP_COEFFICIENT_QUALITY_DISTANCE:
+ *        Quality distance coefficient (default: 1.0)
+ *
+ *     5.2 Data structures used
+ *
+ *    mlp has for each known peer a struct ATS_Peer containing information 
about
+ *    a specific peer. The address field solver_information contains 
information
+ *    about the mlp properties of this address.
+ *
+ *     5.3 Initializing
+ *
+ *    During initialization mlp initializes the GLPK libray used to solve the
+ *    MLP problem: it initializes the glpk environment and creates an initial 
LP
+ *    problem. Next it loads the configuration values from the configuration or
+ *    uses the default values configured in -addresses_mlp.h. The quotas used
+ *    are given by addresses but may have to be adjusted. mlp uses a upper 
limit
+ *    for the bandwidth assigned called BIG M and a minimum amount of bandwidth
+ *    an address gets assigned as well as a minium desired number of
+ *    connections. If the configured quota is bigger than BIG M, it is reduced
+ *    to BIG M. If the configured quota is smaller than MLP_MIN_CONNECTIONS
+ *    *MLP_MIN_BANDWIDTH it is increased to this value.
+ *
+ *     5.4 Shutdown
+
+ */
+
+#define LOG(kind,...) GNUNET_log_from (kind, "ats-mlp",__VA_ARGS__)
+
+/**
+ * Print debug output for mlp problem creation
+ */
+#define DEBUG_MLP_PROBLEM_CREATION GNUNET_NO
+
+/**
+ * Enable GLPK verbose output
+ */
+#define VERBOSE_GLPK GNUNET_NO
+
+/**
+ * Maximize bandwidth assigned
+ *
+ * This option can be used to test if problem can be solved at all without
+ * optimizing for utility, diversity or relativity
+ *
+ */
+#define MAXIMIZE_FOR_BANDWIDTH_ASSIGNED GNUNET_NO
+
+/**
+ * Intercept GLPK terminal output
+ * @param info the mlp handle
+ * @param s the string to print
+ * @return 0: glpk prints output on terminal, 0 != surpress output
+ */
+static int
+mlp_term_hook (void *info, const char *s)
+{
+  /* Not needed atm struct MLP_information *mlp = info; */
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s", s);
+  return 1;
+}
+
+
+/**
+ * Reset peers for next problem creation
+ *
+ * @param cls not used
+ * @param key the key
+ * @param value ATS_Peer
+ * @return GNUNET_OK
+ */
+static int
+reset_peers (void *cls,
+            const struct GNUNET_PeerIdentity *key,
+            void *value)
+ {
+   struct ATS_Peer *peer = value;
+   peer->processed = GNUNET_NO;
+   return GNUNET_OK;
+ }
+
+/**
+ * Delete the MLP problem and free the constrain matrix
+ *
+ * @param mlp the MLP handle
+ */
+static void
+mlp_delete_problem (struct GAS_MLP_Handle *mlp)
+{
+  int c;
+  if (mlp == NULL)
+    return;
+  if (mlp->p.prob != NULL)
+  {
+    glp_delete_prob(mlp->p.prob);
+    mlp->p.prob = NULL;
+  }
+
+  /* delete row index */
+  if (mlp->p.ia != NULL)
+  {
+    GNUNET_free (mlp->p.ia);
+    mlp->p.ia = NULL;
+  }
+
+  /* delete column index */
+  if (mlp->p.ja != NULL)
+  {
+    GNUNET_free (mlp->p.ja);
+    mlp->p.ja = NULL;
+  }
+
+  /* delete coefficients */
+  if (mlp->p.ar != NULL)
+  {
+    GNUNET_free (mlp->p.ar);
+    mlp->p.ar = NULL;
+  }
+  mlp->p.ci = 0;
+  mlp->p.prob = NULL;
+
+  mlp->p.c_d = MLP_UNDEFINED;
+  mlp->p.c_r = MLP_UNDEFINED;
+  mlp->p.r_c2 = MLP_UNDEFINED;
+  mlp->p.r_c4 = MLP_UNDEFINED;
+  mlp->p.r_c6 = MLP_UNDEFINED;
+  mlp->p.r_c9 = MLP_UNDEFINED;
+  for (c = 0; c < mlp->pv.m_q ; c ++)
+    mlp->p.r_q[c] = MLP_UNDEFINED;
+  for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c ++)
+    mlp->p.r_quota[c] = MLP_UNDEFINED;
+  mlp->p.ci = MLP_UNDEFINED;
+
+
+  GNUNET_CONTAINER_multipeermap_iterate (mlp->requested_peers,
+                                        &reset_peers, NULL);
+}
+
+
+/**
+ * Translate ATS properties to text
+ * Just intended for debugging
+ *
+ * @param ats_index the ATS index
+ * @return string with result
+ */
+const char *
+mlp_ats_to_string (int ats_index)
+{
+  switch (ats_index) {
+    case GNUNET_ATS_ARRAY_TERMINATOR:
+      return "GNUNET_ATS_ARRAY_TERMINATOR";
+    case GNUNET_ATS_UTILIZATION_UP:
+      return "GNUNET_ATS_UTILIZATION_UP";
+    case GNUNET_ATS_UTILIZATION_DOWN:
+      return "GNUNET_ATS_UTILIZATION_DOWN";
+    case GNUNET_ATS_COST_LAN:
+      return "GNUNET_ATS_COST_LAN";
+    case GNUNET_ATS_COST_WAN:
+      return "GNUNET_ATS_COST_LAN";
+    case GNUNET_ATS_COST_WLAN:
+      return "GNUNET_ATS_COST_WLAN";
+    case GNUNET_ATS_NETWORK_TYPE:
+      return "GNUNET_ATS_NETWORK_TYPE";
+    case GNUNET_ATS_QUALITY_NET_DELAY:
+      return "GNUNET_ATS_QUALITY_NET_DELAY";
+    case GNUNET_ATS_QUALITY_NET_DISTANCE:
+      return "GNUNET_ATS_QUALITY_NET_DISTANCE";
+    default:
+      GNUNET_break (0);
+      return "unknown";
+  }
+}
+
+/**
+ * Translate glpk status error codes to text
+ * @param retcode return code
+ * @return string with result
+ */
+const char *
+mlp_status_to_string (int retcode)
+{
+  switch (retcode) {
+    case GLP_UNDEF:
+      return "solution is undefined";
+    case GLP_FEAS:
+      return "solution is feasible";
+    case GLP_INFEAS:
+      return "solution is infeasible";
+    case GLP_NOFEAS:
+      return "no feasible solution exists";
+    case GLP_OPT:
+      return "solution is optimal";
+    case GLP_UNBND:
+      return "solution is unbounded";
+    default:
+      GNUNET_break (0);
+      return "unknown error";
+  }
+}
+
+/**
+ * Translate glpk solver error codes to text
+ * @param retcode return code
+ * @return string with result
+ */
+const char *
+mlp_solve_to_string (int retcode)
+{
+  switch (retcode) {
+    case 0:
+      return "ok";
+    case GLP_EBADB:
+      return "invalid basis";
+    case GLP_ESING:
+      return "singular matrix";
+    case GLP_ECOND:
+      return "ill-conditioned matrix";
+    case GLP_EBOUND:
+      return "invalid bounds";
+    case GLP_EFAIL:
+      return "solver failed";
+    case GLP_EOBJLL:
+      return "objective lower limit reached";
+    case GLP_EOBJUL:
+      return "objective upper limit reached";
+    case GLP_EITLIM:
+      return "iteration limit exceeded";
+    case GLP_ETMLIM:
+      return "time limit exceeded";
+    case GLP_ENOPFS:
+      return "no primal feasible solution";
+    case GLP_ENODFS:
+      return "no dual feasible solution";
+    case GLP_EROOT:
+      return "root LP optimum not provided";
+    case GLP_ESTOP:
+      return "search terminated by application";
+    case GLP_EMIPGAP:
+      return "relative mip gap tolerance reached";
+    case GLP_ENOFEAS:
+      return "no dual feasible solution";
+    case GLP_ENOCVG:
+      return "no convergence";
+    case GLP_EINSTAB:
+      return "numerical instability";
+    case GLP_EDATA:
+      return "invalid data";
+    case GLP_ERANGE:
+      return "result out of range";
+    default:
+      GNUNET_break (0);
+      return "unknown error";
+  }
+}
+
+/**
+ * Extract an ATS performance info from an address
+ *
+ * @param address the address
+ * @param type the type to extract in HBO
+ * @return the value in HBO or GNUNET_ATS_VALUE_UNDEFINED in HBO if value does 
not exist
+ */
+static int
+get_performance_info (struct ATS_Address *address, uint32_t type)
+{
+  int c1;
+  GNUNET_assert (NULL != address);
+
+  if ((NULL == address->atsi) || (0 == address->atsi_count))
+      return GNUNET_ATS_VALUE_UNDEFINED;
+
+  for (c1 = 0; c1 < address->atsi_count; c1++)
+  {
+      if (ntohl(address->atsi[c1].type) == type)
+        return ntohl(address->atsi[c1].value);
+  }
+  return GNUNET_ATS_VALUE_UNDEFINED;
+}
+
+
+struct CountContext
+{
+  const struct GNUNET_CONTAINER_MultiPeerMap *peers;
+  int result;
+};
+
+static int
+mlp_create_problem_count_addresses_it (void *cls,
+                                      const struct GNUNET_PeerIdentity *key,
+                                      void *value)
+{
+  struct CountContext *cctx = cls;
+
+  /* Check if we have to add this peer due to a pending request */
+  if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (cctx->peers, key))
+    cctx->result++;
+  return GNUNET_OK;
+}
+
+
+static int
+mlp_create_problem_count_addresses (const struct GNUNET_CONTAINER_MultiPeerMap 
*peers,
+                                   const struct GNUNET_CONTAINER_MultiPeerMap 
*addresses)
+{
+  struct CountContext cctx;
+
+  cctx.peers = peers;
+  cctx.result = 0;
+  GNUNET_CONTAINER_multipeermap_iterate (addresses,
+                                        
&mlp_create_problem_count_addresses_it, &cctx);
+  return cctx.result;
+}
+
+
+/**
+ * Updates an existing value in the matrix
+ *
+ * Extract the row, updates the value and updates the row in the problem
+ *
+ * @param p the mlp problem
+ * @param row the row to create the value in
+ * @param col the column to create the value in
+ * @param val the value to set
+ * @param line calling line for debbuging
+ * @return GNUNET_YES value changed, GNUNET_NO value did not change, 
GNUNET_SYSERR
+ * on error
+ */
+static int
+mlp_create_problem_update_value (struct MLP_Problem *p,
+                              int row, int col, double val,
+                              int line)
+{
+  int c_cols;
+  int c_elems;
+  int c1;
+  int res;
+  int found;
+  double *val_array;
+  int *ind_array;
+
+  GNUNET_assert (NULL != p);
+  GNUNET_assert (NULL != p->prob);
+
+  /* Get number of columns and prepare data structure */
+  c_cols = glp_get_num_cols(p->prob);
+  if (0 >= c_cols)
+    return GNUNET_SYSERR;
+
+  val_array = GNUNET_malloc ((c_cols +1)* sizeof (double));
+  GNUNET_assert (NULL != val_array);
+  ind_array = GNUNET_malloc ((c_cols+1) * sizeof (int));
+  GNUNET_assert (NULL != ind_array);
+  /* Extract the row */
+
+  /* Update the value */
+  c_elems = glp_get_mat_row (p->prob, row, ind_array, val_array);
+  found = GNUNET_NO;
+  for (c1 = 1; c1 < (c_elems+1); c1++)
+  {
+    if (ind_array[c1] == col)
+    {
+      found = GNUNET_YES;
+      break;
+    }
+  }
+  if (GNUNET_NO == found)
+  {
+    ind_array[c_elems+1] = col;
+    val_array[c_elems+1] = val;
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Setting value in [%s : %s] to `%.2f'\n",
+        glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col),
+        val);
+    glp_set_mat_row (p->prob, row, c_elems+1, ind_array, val_array);
+    GNUNET_free (ind_array);
+    GNUNET_free (val_array);
+    return GNUNET_YES;
+  }
+  else
+  {
+    /* Update value */
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Updating value in [%s : %s] from `%.2f' 
to `%.2f'\n",
+        glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col),
+        val_array[c1], val);
+    if (val != val_array[c1])
+      res = GNUNET_YES;
+    else
+      res = GNUNET_NO;
+    val_array[c1] = val;
+    /* Update the row in the matrix */
+    glp_set_mat_row (p->prob, row, c_elems, ind_array, val_array);
+  }
+
+  GNUNET_free (ind_array);
+  GNUNET_free (val_array);
+  return res;
+}
+
+/**
+ * Creates a new value in the matrix
+ *
+ * Sets the row and column index in the problem array and increments the
+ * position field
+ *
+ * @param p the mlp problem
+ * @param row the row to create the value in
+ * @param col the column to create the value in
+ * @param val the value to set
+ * @param line calling line for debbuging
+ */
+static void
+mlp_create_problem_set_value (struct MLP_Problem *p,
+                              int row, int col, double val,
+                              int line)
+{
+  if ((p->ci) >= p->num_elements)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: line %u: Request for index %u bigger 
than array size of %u\n",
+        line, p->ci + 1, p->num_elements);
+    GNUNET_break (0);
+    return;
+  }
+  if ((0 == row) || (0 == col))
+    GNUNET_break (0);
+  p->ia[p->ci] = row ;
+  p->ja[p->ci] = col;
+  p->ar[p->ci] = val;
+#if  DEBUG_MLP_PROBLEM_CREATION
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: line %u: Set value [%u,%u] in index %u 
==  %.2f\n",
+      line, p->ia[p->ci], p->ja[p->ci], p->ci, p->ar[p->ci]);
+#endif
+  p->ci++;
+}
+
+static int
+mlp_create_problem_create_column (struct MLP_Problem *p, char *name,
+    unsigned int type, unsigned int bound, double lb, double ub,
+    double coef)
+{
+  int col = glp_add_cols (p->prob, 1);
+  glp_set_col_name (p->prob, col, name);
+  glp_set_col_bnds (p->prob, col, bound, lb, ub);
+  glp_set_col_kind (p->prob, col, type);
+  glp_set_obj_coef (p->prob, col, coef);
+#if  DEBUG_MLP_PROBLEM_CREATION
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added column [%u] `%s': %.2f\n",
+      col, name, coef);
+#endif
+  return col;
+}
+
+static int
+mlp_create_problem_create_constraint (struct MLP_Problem *p, char *name,
+    unsigned int bound, double lb, double ub)
+{
+  char * op;
+  int row = glp_add_rows (p->prob, 1);
+  /* set row name */
+  glp_set_row_name (p->prob, row, name);
+  /* set row bounds: <= 0 */
+  glp_set_row_bnds (p->prob, row, bound, lb, ub);
+  switch (bound)
+  {
+    case GLP_UP:
+            GNUNET_asprintf(&op, "-inf <= x <= %.2f", ub);
+            break;
+    case GLP_DB:
+            GNUNET_asprintf(&op, "%.2f <= x <= %.2f", lb, ub);
+            break;
+    case GLP_FX:
+            GNUNET_asprintf(&op, "%.2f == x == %.2f", lb, ub);
+            break;
+    case GLP_LO:
+            GNUNET_asprintf(&op, "%.2f <= x <= inf", lb);
+            break;
+    default:
+            GNUNET_asprintf(&op, "ERROR");
+            break;
+  }
+#if  DEBUG_MLP_PROBLEM_CREATION
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added row [%u] `%s': %s\n",
+        row, name, op);
+#endif
+  GNUNET_free (op);
+  return row;
+}
+
+/**
+ * Create the
+ * - address columns b and n
+ * - address dependent constraint rows c1, c3
+ * - peer dependent rows c2 and c9
+ * - Set address dependent entries in problem matrix as well
+ */
+static int
+mlp_create_problem_add_address_information (void *cls,
+                                           const struct GNUNET_PeerIdentity 
*key,
+                                           void *value)
+{
+  struct GAS_MLP_Handle *mlp = cls;
+  struct MLP_Problem *p = &mlp->p;
+  struct ATS_Address *address = value;
+  struct ATS_Peer *peer;
+  struct MLP_information *mlpi;
+  char *name;
+  const double *props;
+  uint32_t addr_net;
+  int c;
+
+  /* Check if we have to add this peer due to a pending request */
+  if (GNUNET_NO == 
GNUNET_CONTAINER_multipeermap_contains(mlp->requested_peers, key))
+    return GNUNET_OK;
+
+  mlpi = address->solver_information;
+  if (NULL == mlpi)
+  {
+      fprintf (stderr, "%s %p\n",GNUNET_i2s (&address->peer), address);
+      GNUNET_break (0);
+      return GNUNET_OK;
+  }
+
+  /* Get peer */
+  peer = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, key);
+  if (peer->processed == GNUNET_NO)
+  {
+      /* Add peer dependent constraints */
+      /* Add constraint c2 */
+      GNUNET_asprintf(&name, "c2_%s", GNUNET_i2s(&address->peer));
+      peer->r_c2 = mlp_create_problem_create_constraint (p, name, GLP_FX, 1.0, 
1.0);
+      GNUNET_free (name);
+      /* Add constraint c9 */
+      GNUNET_asprintf(&name, "c9_%s", GNUNET_i2s(&address->peer));
+      peer->r_c9 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 
0.0);
+      GNUNET_free (name);
+      /* c 9) set coefficient */
+      mlp_create_problem_set_value (p, peer->r_c9, p->c_r, -peer->f, __LINE__);
+      peer->processed = GNUNET_YES;
+  }
+
+  /* Reset addresses' solver information */
+  mlpi->c_b = 0;
+  mlpi->c_n = 0;
+  mlpi->n = 0;
+  mlpi->r_c1 = 0;
+  mlpi->r_c3 = 0;
+
+  /* Add bandwidth column */
+  GNUNET_asprintf (&name, "b_%s_%s_%p", GNUNET_i2s (&address->peer), 
address->plugin, address);
+#if TEST_MAX_BW_ASSIGNMENT
+  mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 
0.0, 1.0);
+#else
+  mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 
0.0, 0.0);
+#endif
+
+  GNUNET_free (name);
+
+  /* Add usage column */
+  GNUNET_asprintf (&name, "n_%s_%s_%p", GNUNET_i2s (&address->peer), 
address->plugin, address);
+  mlpi->c_n = mlp_create_problem_create_column (p, name, GLP_IV, GLP_DB, 0.0, 
1.0, 0.0);
+  GNUNET_free (name);
+
+  /* Add address dependent constraints */
+  /* Add constraint c1) bandwidth capping
+   * b_t  + (-M) * n_t <= 0
+   * */
+  GNUNET_asprintf(&name, "c1_%s_%s_%p", GNUNET_i2s(&address->peer), 
address->plugin, address);
+  mlpi->r_c1 = mlp_create_problem_create_constraint (p, name, GLP_UP, 0.0, 
0.0);
+  GNUNET_free (name);
+
+  /*  c1) set b = 1 coefficient */
+  mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_b, 1, __LINE__);
+  /*  c1) set n = -M coefficient */
+  mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_n, -mlp->pv.BIG_M, 
__LINE__);
+
+  /* Add constraint c 3) minimum bandwidth
+   * b_t + (-n_t * b_min) >= 0
+   * */
+  GNUNET_asprintf(&name, "c3_%s_%s_%p", GNUNET_i2s(&address->peer), 
address->plugin, address);
+  mlpi->r_c3 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 
0.0);
+  GNUNET_free (name);
+
+  /*  c3) set b = 1 coefficient */
+  mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_b, 1, __LINE__);
+  /*  c3) set n = -b_min coefficient */
+  mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_n, - ((double 
)mlp->pv.b_min), __LINE__);
+
+
+  /* Set coefficient entries in invariant rows */
+  /* c 4) minimum connections */
+  mlp_create_problem_set_value (p, p->r_c4, mlpi->c_n, 1, __LINE__);
+  /* c 6) maximize diversity */
+  mlp_create_problem_set_value (p, p->r_c6, mlpi->c_n, 1, __LINE__);
+  /* c 2) 1 address peer peer */
+  mlp_create_problem_set_value (p, peer->r_c2, mlpi->c_n, 1, __LINE__);
+  /* c 9) relativity */
+  mlp_create_problem_set_value (p, peer->r_c9, mlpi->c_b, 1, __LINE__);
+  /* c 8) utility */
+  mlp_create_problem_set_value (p, p->r_c8, mlpi->c_b, 1, __LINE__);
+
+  /* c 10) obey network specific quotas
+   * (1)*b_1 + ... + (1)*b_m <= quota_n
+   */
+  for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
+  {
+    addr_net = get_performance_info (address, GNUNET_ATS_NETWORK_TYPE);
+    if (GNUNET_ATS_VALUE_UNDEFINED == addr_net)
+            addr_net = GNUNET_ATS_NET_UNSPECIFIED;
+
+    if (mlp->pv.quota_index[c] == addr_net)
+    {
+      mlp_create_problem_set_value (p, p->r_quota[c], mlpi->c_b, 1, __LINE__);
+      break;
+    }
+  }
+
+  /* c 7) Optimize quality */
+  /* For all quality metrics, set quality of this address */
+  props = mlp->get_properties (mlp->get_properties_cls, address);
+  for (c = 0; c < mlp->pv.m_q; c++)
+    mlp_create_problem_set_value (p, p->r_q[c], mlpi->c_b, props[c], __LINE__);
+
+  return GNUNET_OK;
+}
+
+/**
+ * Create the invariant columns c4, c6, c10, c8, c7
+ */
+static void
+mlp_create_problem_add_invariant_rows (struct GAS_MLP_Handle *mlp, struct 
MLP_Problem *p)
+{
+  char *name;
+  int c;
+
+  /* Row for c4) minimum connection */
+  /* Number of minimum connections is min(|Peers|, n_min) */
+  p->r_c4 = mlp_create_problem_create_constraint (p, "c4", GLP_LO, 
(mlp->pv.n_min > p->num_peers) ? p->num_peers : mlp->pv.n_min, 0.0);
+
+  /* Add row for c6) */
+  p->r_c6 = mlp_create_problem_create_constraint (p, "c6", GLP_FX, 0.0, 0.0);
+  /* c6 )Setting -D */
+  mlp_create_problem_set_value (p, p->r_c6, p->c_d, -1, __LINE__);
+
+  /* Add rows for c 10) */
+  for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
+  {
+    char * text;
+    GNUNET_asprintf(&text, "c10_quota_ats_%s",
+        GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]));
+    p->r_quota[c] = mlp_create_problem_create_constraint (p, text, GLP_DB, 
0.0, mlp->pv.quota_out[c]);
+    GNUNET_free (text);
+  }
+
+  /* Adding rows for c 8) */
+  p->r_c8 = mlp_create_problem_create_constraint (p, "c8", GLP_FX, 0.0, 0.0);
+  /* -u */
+  mlp_create_problem_set_value (p, p->r_c8, p->c_u, -1, __LINE__);
+
+  /* c 7) For all quality metrics */
+  for (c = 0; c < mlp->pv.m_q; c++)
+  {
+    GNUNET_asprintf(&name, "c7_q%i_%s", c, mlp_ats_to_string(mlp->pv.q[c]));
+    p->r_q[c] = mlp_create_problem_create_constraint (p, name, GLP_FX, 0.0, 
0.0);
+    GNUNET_free (name);
+    mlp_create_problem_set_value (p, p->r_q[c], p->c_q[c], -1, __LINE__);
+  }
+}
+
+
+/**
+ * Create the invariant columns d, u, r, q0 ... qm
+ */
+static void
+mlp_create_problem_add_invariant_columns (struct GAS_MLP_Handle *mlp, struct 
MLP_Problem *p)
+{
+  char *name;
+  int c;
+
+#if TEST_MAX_BW_ASSIGNMENT
+  mlp->pv.co_D = 0.0;
+  mlp->pv.co_U = 0.0;
+
+#endif
+  //mlp->pv.co_R = 0.0;
+
+  /* Diversity d column  */
+  p->c_d = mlp_create_problem_create_column (p, "d", GLP_CV, GLP_LO, 0.0, 0.0, 
mlp->pv.co_D);
+
+  /* Utilization u column  */
+  p->c_u = mlp_create_problem_create_column (p, "u", GLP_CV, GLP_LO, 0.0, 0.0, 
mlp->pv.co_U);
+
+  /* Relativity r column  */
+  p->c_r = mlp_create_problem_create_column (p, "r", GLP_CV, GLP_LO, 0.0, 0.0, 
mlp->pv.co_R);
+
+  /* Quality metric columns */
+  for (c = 0; c < mlp->pv.m_q; c++)
+  {
+    GNUNET_asprintf (&name, "q_%u", mlp->pv.q[c]);
+#if TEST_MAX_BW_ASSIGNMENT
+    p->c_q[c] = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 
0.0, 0.0, 0.0);
+#else
+    p->c_q[c] = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 
0.0, 0.0, mlp->pv.co_Q[c]);
+#endif
+    GNUNET_free (name);
+  }
+}
+
+
+/**
+ * Create the MLP problem
+ *
+ * @param mlp the MLP handle
+ * @return GNUNET_OK or GNUNET_SYSERR
+ */
+static int
+mlp_create_problem (struct GAS_MLP_Handle *mlp)
+{
+  struct MLP_Problem *p = &mlp->p;
+  int res = GNUNET_OK;
+
+  GNUNET_assert (p->prob == NULL);
+  GNUNET_assert (p->ia == NULL);
+  GNUNET_assert (p->ja == NULL);
+  GNUNET_assert (p->ar == NULL);
+  /* Reset MLP problem struct */
+
+  /* create the glpk problem */
+  p->prob = glp_create_prob ();
+  GNUNET_assert (NULL != p->prob);
+  p->num_peers = GNUNET_CONTAINER_multipeermap_size (mlp->requested_peers);
+  p->num_addresses = mlp_create_problem_count_addresses (mlp->requested_peers, 
mlp->addresses);
+
+  /* Create problem matrix: 10 * #addresses + #q * #addresses + #q, + #peer + 
2 + 1 */
+  p->num_elements = (10 * p->num_addresses + mlp->pv.m_q * p->num_addresses +
+      mlp->pv.m_q + p->num_peers + 2 + 1);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Rebuilding problem for %u peer(s) and %u addresse(s) and %u quality 
metrics == %u elements\n",
+       p->num_peers,
+       p->num_addresses,
+       mlp->pv.m_q,
+       p->num_elements);
+
+  /* Set a problem name */
+  glp_set_prob_name (p->prob, "GNUnet ATS bandwidth distribution");
+  /* Set optimization direction to maximize */
+  glp_set_obj_dir (p->prob, GLP_MAX);
+
+  /* Create problem matrix */
+  /* last +1 caused by glpk index starting with one: [1..elements]*/
+  p->ci = 1;
+  /* row index */
+  p->ia = GNUNET_malloc (p->num_elements * sizeof (int));
+  /* column index */
+  p->ja = GNUNET_malloc (p->num_elements * sizeof (int));
+  /* coefficient */
+  p->ar = GNUNET_malloc (p->num_elements * sizeof (double));
+
+  if ((NULL == p->ia) || (NULL == p->ja) || (NULL == p->ar))
+  {
+      LOG (GNUNET_ERROR_TYPE_ERROR, _("Problem size too large, cannot allocate 
memory!\n"));
+      return GNUNET_SYSERR;
+  }
+
+  /* Adding invariant columns */
+  mlp_create_problem_add_invariant_columns (mlp, p);
+
+  /* Adding address independent constraint rows */
+  mlp_create_problem_add_invariant_rows (mlp, p);
+
+  /* Adding address dependent columns constraint rows */
+  GNUNET_CONTAINER_multipeermap_iterate (mlp->addresses,
+                                        
&mlp_create_problem_add_address_information,
+                                        mlp);
+
+  /* Load the matrix */
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Loading matrix\n");
+  glp_load_matrix(p->prob, (p->ci)-1, p->ia, p->ja, p->ar);
+
+  return res;
+}
+
+/**
+ * Solves the LP problem
+ *
+ * @param mlp the MLP Handle
+ * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
+ */
+static int
+mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp)
+{
+  int res = 0;
+
+  res = glp_simplex(mlp->p.prob, &mlp->control_param_lp);
+  if (0 == res)
+          LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: 0x%02X %s\n", 
res, mlp_solve_to_string(res));
+  else
+          LOG (GNUNET_ERROR_TYPE_WARNING, "Solving LP problem failed: 0x%02X 
%s\n", res, mlp_solve_to_string(res));
+
+  /* Analyze problem status  */
+  res = glp_get_status (mlp->p.prob);
+  switch (res) {
+    /* solution is optimal */
+    case GLP_OPT:
+    /* solution is feasible */
+    case GLP_FEAS:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: 0x%02X %s\n",
+          res, mlp_status_to_string(res));
+      return GNUNET_OK;
+    /* Problem was ill-defined, no way to handle that */
+    default:
+      LOG (GNUNET_ERROR_TYPE_WARNING, "Solving LP problem failed, no solution: 
0x%02X %s\n",
+          res, mlp_status_to_string(res));
+      return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Solves the MLP problem
+ *
+ * @param mlp the MLP Handle
+ * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
+ */
+int
+mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp)
+{
+  int res = 0;
+  res = glp_intopt(mlp->p.prob, &mlp->control_param_mlp);
+  if (0 == res)
+          LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving MLP problem: 0x%02X %s\n", 
res, mlp_solve_to_string(res));
+  else
+          LOG (GNUNET_ERROR_TYPE_WARNING, "Solving MLP problem failed: 0x%02X 
%s\n", res, mlp_solve_to_string(res));
+  /* Analyze problem status  */
+  res = glp_mip_status(mlp->p.prob);
+  switch (res) {
+    /* solution is optimal */
+    case GLP_OPT:
+    /* solution is feasible */
+    case GLP_FEAS:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving MLP problem: 0x%02X %s\n", res, 
mlp_status_to_string(res));
+      return GNUNET_OK;
+    /* Problem was ill-defined, no way to handle that */
+    default:
+      LOG (GNUNET_ERROR_TYPE_WARNING,"Solving MLP problem failed, 0x%02X 
%s\n\n", res, mlp_status_to_string(res));
+      return GNUNET_SYSERR;
+  }
+}
+
+/**
+ * Propagates the results when MLP problem was solved
+ *
+ * @param cls the MLP handle
+ * @param key the peer identity
+ * @param value the address
+ * @return #GNUNET_OK to continue
+ */
+int
+mlp_propagate_results (void *cls,
+                      const struct GNUNET_PeerIdentity *key,
+                      void *value)
+{
+  struct GAS_MLP_Handle *mlp = cls;
+  struct ATS_Address *address;
+  struct MLP_information *mlpi;
+  double mlp_bw_in = MLP_NaN;
+  double mlp_bw_out = MLP_NaN;
+  double mlp_use = MLP_NaN;
+
+  /* Check if we have to add this peer due to a pending request */
+  if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains 
(mlp->requested_peers,
+                                                          key))
+  {
+    return GNUNET_OK;
+  }
+  address = value;
+  GNUNET_assert (address->solver_information != NULL);
+  mlpi = address->solver_information;
+
+  mlp_bw_in = glp_mip_col_val(mlp->p.prob, mlpi->c_b);/* FIXME */
+  if (mlp_bw_in > (double) UINT32_MAX)
+  {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Overflow in assigned bandwidth, reducing 
...\n" );
+      mlp_bw_in = (double) UINT32_MAX;
+  }
+  mlp_bw_out = glp_mip_col_val(mlp->p.prob, mlpi->c_b);
+  if (mlp_bw_out > (double) UINT32_MAX)
+  {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Overflow in assigned bandwidth, reducing 
...\n" );
+      mlp_bw_out = (double) UINT32_MAX;
+  }
+  mlp_use = glp_mip_col_val(mlp->p.prob, mlpi->c_n);
+
+  /*
+   * Debug: solution
+   * LOG (GNUNET_ERROR_TYPE_INFO, "MLP result address: `%s' `%s' length %u 
session %u, mlp use %f\n",
+   *    GNUNET_i2s(&address->peer), address->plugin,
+   *    address->addr_len, address->session_id);
+   */
+
+  if (GLP_YES == mlp_use)
+  {
+    /* This address was selected by the solver to be used */
+    mlpi->n = GNUNET_YES;
+    if (GNUNET_NO == address->active)
+    {
+            /* Address was not used before, enabling address */
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : enabling address\n",
+          (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
+      address->active = GNUNET_YES;
+      address->assigned_bw_in.value__ = htonl (mlp_bw_in);
+      mlpi->b_in.value__ = htonl(mlp_bw_in);
+      address->assigned_bw_out.value__ = htonl (mlp_bw_out);
+      mlpi->b_out.value__ = htonl(mlp_bw_out);
+      if ((NULL == mlp->exclude_peer) || (0 != memcmp (&address->peer, 
mlp->exclude_peer, sizeof (address->peer))))
+        mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
+      return GNUNET_OK;
+    }
+    else if (GNUNET_YES == address->active)
+    {
+      /* Address was used before, check for bandwidth change */
+      if ((mlp_bw_out != ntohl(address->assigned_bw_out.value__)) ||
+              (mlp_bw_in != ntohl(address->assigned_bw_in.value__)))
+      {
+          LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : bandwidth changed\n",
+              (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
+          address->assigned_bw_in.value__ = htonl (mlp_bw_in);
+          mlpi->b_in.value__ = htonl(mlp_bw_in);
+          address->assigned_bw_out.value__ = htonl (mlp_bw_out);
+          mlpi->b_out.value__ = htonl(mlp_bw_out);
+          if ((NULL == mlp->exclude_peer) || (0 != memcmp (&address->peer, 
mlp->exclude_peer, sizeof (address->peer))))
+            mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
+          return GNUNET_OK;
+      }
+    }
+    else
+      GNUNET_break (0);
+  }
+  else if (GLP_NO == mlp_use)
+  {
+    /* This address was selected by the solver to be not used */
+    mlpi->n = GNUNET_NO;
+    if (GNUNET_NO == address->active)
+    {
+      /* Address was not used before, nothing to do */
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : no change\n",
+          (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
+      return GNUNET_OK;
+    }
+    else if (GNUNET_YES == address->active)
+    {
+    /* Address was used before, disabling address */
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : disabling address\n",
+        (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
+      address->active = GNUNET_NO;
+      /* Set bandwidth to 0 */
+      address->assigned_bw_in = BANDWIDTH_ZERO;
+      mlpi->b_in.value__ = htonl(mlp_bw_in);
+      address->assigned_bw_out = BANDWIDTH_ZERO;
+      mlpi->b_out.value__ = htonl(mlp_bw_out);
+      //mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
+      return GNUNET_OK;
+    }
+    else
+      GNUNET_break (0);
+  }
+  else
+    GNUNET_break (0);
+
+  return GNUNET_OK;
+}
+
+/**
+ * Solves the MLP problem
+ *
+ * @param solver the MLP Handle
+ * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
+ */
+int
+GAS_mlp_solve_problem (void *solver)
+{
+  struct GAS_MLP_Handle *mlp = solver;
+  char *filename;
+  int res_lp = 0;
+  int res_mip = 0;
+  struct GNUNET_TIME_Absolute start_build;
+  struct GNUNET_TIME_Relative duration_build;
+  struct GNUNET_TIME_Absolute start_lp;
+  struct GNUNET_TIME_Relative duration_lp;
+  struct GNUNET_TIME_Absolute start_mlp;
+  struct GNUNET_TIME_Relative duration_mlp;
+  GNUNET_assert (NULL != solver);
+
+  if (GNUNET_YES == mlp->bulk_lock)
+  {
+    mlp->bulk_request ++;
+    return GNUNET_NO;
+  }
+
+  if (0 == GNUNET_CONTAINER_multipeermap_size (mlp->requested_peers))
+    return GNUNET_OK; /* No pending requests */
+  if (0 == GNUNET_CONTAINER_multipeermap_size (mlp->addresses))
+    return GNUNET_OK; /* No addresses available */
+
+  if ((GNUNET_NO == mlp->mlp_prob_changed) && (GNUNET_NO == 
mlp->mlp_prob_updated))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "No changes to problem\n");
+    return GNUNET_OK;
+  }
+  if (GNUNET_YES == mlp->mlp_prob_changed)
+  {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem size changed, rebuilding\n");
+      mlp_delete_problem (mlp);
+      start_build = GNUNET_TIME_absolute_get();
+      if (GNUNET_SYSERR == mlp_create_problem (mlp))
+        return GNUNET_SYSERR;
+      duration_build = GNUNET_TIME_absolute_get_duration (start_build);
+      mlp->control_param_lp.presolve = GLP_YES;
+      mlp->control_param_mlp.presolve = GNUNET_NO; /* No presolver, we have LP 
solution */
+  }
+  else
+  {
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n");
+      duration_build.rel_value_us = 0;
+  }
+
+  /* Run LP solver */
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Running LP solver %s\n",
+      (GLP_YES == mlp->control_param_lp.presolve)? "with presolver": "without 
presolver");
+  start_lp = GNUNET_TIME_absolute_get();
+  res_lp = mlp_solve_lp_problem (mlp);
+  duration_lp = GNUNET_TIME_absolute_get_duration (start_lp);
+
+
+  /* Run MLP solver */
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Running MLP solver \n");
+  start_mlp = GNUNET_TIME_absolute_get();
+  res_mip = mlp_solve_mlp_problem (mlp);
+
+  duration_mlp = GNUNET_TIME_absolute_get_duration (start_mlp);
+
+  /* Save stats */
+  mlp->ps.lp_res = res_lp;
+  mlp->ps.mip_res = res_mip;
+  mlp->ps.build_dur = duration_build;
+  mlp->ps.lp_dur = duration_lp;
+  mlp->ps.mip_dur = duration_mlp;
+  mlp->ps.lp_presolv = mlp->control_param_lp.presolve;
+  mlp->ps.mip_presolv = mlp->control_param_mlp.presolve;
+  mlp->ps.p_cols = glp_get_num_cols (mlp->p.prob);
+  mlp->ps.p_rows = glp_get_num_rows (mlp->p.prob);
+  mlp->ps.p_elements = mlp->p.num_elements;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Execution time: Build %s\n",
+       GNUNET_STRINGS_relative_time_to_string (duration_build, GNUNET_NO));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Execution time: LP %s\n",
+       GNUNET_STRINGS_relative_time_to_string (duration_lp, GNUNET_NO));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Execution time: MLP %s\n",
+       GNUNET_STRINGS_relative_time_to_string (duration_mlp, GNUNET_NO));
+
+  /* Propagate result*/
+  if ((GNUNET_OK == res_lp) && (GNUNET_OK == res_mip))
+  {
+    GNUNET_CONTAINER_multipeermap_iterate (mlp->addresses, 
&mlp_propagate_results, mlp);
+  }
+
+  struct GNUNET_TIME_Absolute time = GNUNET_TIME_absolute_get();
+  if (GNUNET_YES == mlp->write_mip_mps)
+  {
+    /* Write problem to disk */
+    GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.mps", mlp->p.num_peers, 
mlp->p.num_addresses, time.abs_value_us);
+    LOG (GNUNET_ERROR_TYPE_ERROR, "DUMP: %s \n", filename);
+    glp_write_lp(mlp->p.prob, NULL, filename);
+    GNUNET_free (filename);
+  }
+  if (GNUNET_YES == mlp->write_mip_sol)
+  {
+    /* Write solution to disk */
+    GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.sol", mlp->p.num_peers, 
mlp->p.num_addresses, time.abs_value_us);
+    glp_print_mip (mlp->p.prob, filename );
+    LOG (GNUNET_ERROR_TYPE_ERROR, "DUMP: %s \n", filename);
+    GNUNET_free (filename);
+  }
+
+  /* Reset change and update marker */
+  mlp->control_param_lp.presolve = GLP_NO;
+  mlp->mlp_prob_updated = GNUNET_NO;
+  mlp->mlp_prob_changed = GNUNET_NO;
+
+  if ((GNUNET_OK == res_lp) && (GNUNET_OK == res_mip))
+    return GNUNET_OK;
+  else
+    return GNUNET_SYSERR;
+}
+
+/**
+ * Add a single address to the solve
+ *
+ * @param solver the solver Handle
+ * @param address the address to add
+ * @param network network type of this address
+ */
+void
+GAS_mlp_address_add (void *solver,
+                    struct ATS_Address *address,
+                    uint32_t network)
+{
+  struct GAS_MLP_Handle *mlp = solver;
+  struct ATS_Peer *p;
+
+  GNUNET_assert (NULL != solver);
+  GNUNET_assert (NULL != address);
+
+  if (NULL == address->solver_information)
+  {
+      address->solver_information = GNUNET_new (struct MLP_information);
+  }
+  else
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+          _("Adding address for peer `%s' multiple times\n"),
+          GNUNET_i2s(&address->peer));
+
+  /* Is this peer included in the problem? */
+  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
+                                                     &address->peer)))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer `%s' without 
address request \n", GNUNET_i2s(&address->peer));
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer `%s' with address 
request \n", GNUNET_i2s(&address->peer));
+  /* Problem size changed: new address for peer with pending request */
+  mlp->mlp_prob_changed = GNUNET_YES;
+  if (GNUNET_YES == mlp->mlp_auto_solve)
+    GAS_mlp_solve_problem (solver);
+}
+
+
+/**
+ * Transport properties for this address have changed
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param type the ATSI type in HBO
+ * @param abs_value the absolute value of the property
+ * @param rel_value the normalized value
+ */
+void
+GAS_mlp_address_property_changed (void *solver,
+                                  struct ATS_Address *address,
+                                  uint32_t type,
+                                  uint32_t abs_value,
+                                  double rel_value)
+{
+  struct MLP_information *mlpi = address->solver_information;
+  struct GAS_MLP_Handle *mlp = solver;
+  struct ATS_Peer *p;
+  int c1;
+  int type_index;
+
+  GNUNET_assert (NULL != solver);
+  GNUNET_assert (NULL != address);
+
+  if (NULL == mlpi)
+  {
+      LOG (GNUNET_ERROR_TYPE_ERROR,
+          _("Updating address property `%s' for peer `%s' %p not added 
before\n"),
+          GNUNET_ATS_print_property_type (type),
+          GNUNET_i2s(&address->peer),
+          address);
+      GNUNET_break (0);
+      return;
+  }
+
+  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
+                                                     &address->peer)))
+  {
+    /* Peer is not requested, so no need to update problem */
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Updating property `%s' address for peer 
`%s'\n",
+      GNUNET_ATS_print_property_type (type),
+      GNUNET_i2s(&address->peer));
+
+  /* Find row index */
+  type_index = -1;
+  for (c1 = 0; c1 < mlp->pv.m_q; c1++)
+  {
+    if (type == mlp->pv.q[c1])
+    {
+      type_index = c1;
+      break;
+    }
+  }
+  if (-1 == type_index)
+  {
+    GNUNET_break (0);
+    return; /* quality index not found */
+  }
+
+  /* Update c7) [r_q[index]][c_b] = f_q * q_averaged[type_index] */
+  if (GNUNET_YES == mlp_create_problem_update_value (&mlp->p,
+      mlp->p.r_q[type_index], mlpi->c_b, rel_value, __LINE__))
+  {
+    mlp->mlp_prob_updated = GNUNET_YES;
+    if (GNUNET_YES == mlp->mlp_auto_solve)
+      GAS_mlp_solve_problem (solver);
+  }
+}
+
+
+/**
+ * Transport session for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param cur_session the current session
+ * @param new_session the new session
+ */
+void
+GAS_mlp_address_session_changed (void *solver,
+                                  struct ATS_Address *address,
+                                  uint32_t cur_session,
+                                  uint32_t new_session)
+{
+  /* Nothing to do here */
+  return;
+}
+
+
+/**
+ * Transport session for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param in_use usage state
+ */
+void
+GAS_mlp_address_inuse_changed (void *solver,
+                               struct ATS_Address *address,
+                               int in_use)
+{
+  /* Nothing to do here */
+  return;
+}
+
+
+/**
+ * Network scope for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param current_network the current network
+ * @param new_network the new network
+ */
+void
+GAS_mlp_address_change_network (void *solver,
+                               struct ATS_Address *address,
+                               uint32_t current_network,
+                               uint32_t new_network)
+{
+  struct MLP_information *mlpi = address->solver_information;
+  struct GAS_MLP_Handle *mlp = solver;
+  struct ATS_Peer *p;
+  int nets_avail[] = GNUNET_ATS_NetworkType;
+  int c1;
+
+  GNUNET_assert (NULL != solver);
+  GNUNET_assert (NULL != address);
+
+  if (NULL == mlpi)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  if (mlpi->c_b == MLP_UNDEFINED)
+    return; /* This address is not yet in the matrix*/
+
+  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
+                                                     &address->peer)))
+  {
+    /* Peer is not requested, so no need to update problem */
+    GNUNET_break (0);
+    return;
+  }
+
+  if (current_network == new_network)
+  {
+    GNUNET_break (0);
+    return;
+  }
+
+  for (c1 = 0; c1 < GNUNET_ATS_NetworkTypeCount ; c1 ++)
+  {
+    if (nets_avail[c1] == new_network)
+      break;
+  }
+
+  if (GNUNET_ATS_NetworkTypeCount == c1)
+  {
+    /* Invalid network */
+    GNUNET_break (0);
+    return;
+  }
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Updating network for peer `%s' from `%s' to 
`%s'\n",
+      GNUNET_i2s (&address->peer),
+      GNUNET_ATS_print_network_type(current_network),
+      GNUNET_ATS_print_network_type(new_network));
+
+  for (c1 = 0; c1 < GNUNET_ATS_NetworkTypeCount; c1++)
+  {
+    if (mlp->pv.quota_index[c1] == current_network)
+    {
+      /* Remove from old network */
+      mlp_create_problem_update_value (&mlp->p,
+          mlp->p.r_quota[c1],
+          mlpi->c_b, 0.0, __LINE__);
+      break;
+    }
+  }
+
+  for (c1 = 0; c1 < GNUNET_ATS_NetworkTypeCount; c1++)
+  {
+    if (mlp->pv.quota_index[c1] == new_network)
+    {
+      /* Remove from old network */
+      if (GNUNET_SYSERR == mlp_create_problem_update_value (&mlp->p,
+          mlp->p.r_quota[c1],
+          mlpi->c_b, 1.0, __LINE__))
+      {
+        /* This quota did not exist in the problem, recreate */
+        GNUNET_break (0);
+      }
+      break;
+    }
+  }
+
+  mlp->mlp_prob_changed = GNUNET_YES;
+}
+
+
+/**
+ * Deletes a single address in the MLP problem
+ *
+ * The MLP problem has to be recreated and the problem has to be resolved
+ *
+ * @param solver the MLP Handle
+ * @param address the address to delete
+ * @param session_only delete only session not whole address
+ */
+void
+GAS_mlp_address_delete (void *solver,
+    struct ATS_Address *address,
+    int session_only)
+{
+  struct ATS_Peer *p;
+  struct GAS_MLP_Handle *mlp = solver;
+  struct MLP_information *mlpi;
+  int was_active;
+
+  GNUNET_assert (NULL != solver);
+  GNUNET_assert (NULL != address);
+
+  mlpi = address->solver_information;
+  if ((GNUNET_NO == session_only) && (NULL != mlpi))
+  {
+    /* Remove full address */
+    GNUNET_free (mlpi);
+    address->solver_information = NULL;
+  }
+  was_active = address->active;
+  address->active = GNUNET_NO;
+  address->assigned_bw_in = BANDWIDTH_ZERO;
+  address->assigned_bw_out = BANDWIDTH_ZERO;
+
+  /* Is this peer included in the problem? */
+  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
+                                                     &address->peer)))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "Deleting %s for peer `%s' without address 
request \n",
+        (session_only == GNUNET_YES) ? "session" : "address",
+        GNUNET_i2s(&address->peer));
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_INFO, "Deleting %s for peer `%s' with address request 
\n",
+      (session_only == GNUNET_YES) ? "session" : "address",
+      GNUNET_i2s(&address->peer));
+
+  /* Problem size changed: new address for peer with pending request */
+  mlp->mlp_prob_changed = GNUNET_YES;
+  if (GNUNET_YES == mlp->mlp_auto_solve)
+  {
+    GAS_mlp_solve_problem (solver);
+  }
+  if (GNUNET_YES == was_active)
+  {
+    if (NULL == GAS_mlp_get_preferred_address (solver, &address->peer))
+    {
+      /* No alternative address, disconnecting peer */
+      mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
+    }
+  }
+
+  return;
+}
+
+
+/**
+ * Find the active address in the set of addresses of a peer
+ * @param cls destination
+ * @param key peer id
+ * @param value address
+ * @return GNUNET_OK
+ */
+static int
+mlp_get_preferred_address_it (void *cls,
+                             const struct GNUNET_PeerIdentity *key,
+                             void *value)
+{
+  static int counter = 0;
+  struct ATS_Address **aa = cls;
+  struct ATS_Address *addr = value;
+  struct MLP_information *mlpi = addr->solver_information;
+
+  if (mlpi == NULL)
+    return GNUNET_YES;
+
+  /*
+   * Debug output
+   * GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+   *           "MLP [%u] Peer `%s' %s length %u session %u active %s mlp 
active %s\n",
+   *           counter, GNUNET_i2s (&addr->peer), addr->plugin, 
addr->addr_len, addr->session_id,
+   *           (GNUNET_YES == addr->active) ? "active" : "inactive",
+   *           (GNUNET_YES == mlpi->n) ? "active" : "inactive");
+   */
+
+  if (GNUNET_YES == mlpi->n)
+  {
+
+    (*aa) = addr;
+    (*aa)->assigned_bw_in = mlpi->b_in;
+    (*aa)->assigned_bw_out = mlpi->b_out;
+    return GNUNET_NO;
+  }
+  counter ++;
+  return GNUNET_YES;
+}
+
+
+static double
+get_peer_pref_value (struct GAS_MLP_Handle *mlp, const struct 
GNUNET_PeerIdentity *peer)
+{
+  double res;
+  const double *preferences = NULL;
+  int c;
+  preferences = mlp->get_preferences (mlp->get_preferences_cls, peer);
+
+  res = 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]);
+      res += preferences[c];
+    }
+  }
+  res /= (GNUNET_ATS_PreferenceCount -1);
+  return res;
+}
+
+
+/**
+ * Get the preferred address for a specific peer
+ *
+ * @param solver the MLP Handle
+ * @param peer the peer
+ * @return suggested address
+ */
+const struct ATS_Address *
+GAS_mlp_get_preferred_address (void *solver,
+                               const struct GNUNET_PeerIdentity *peer)
+{
+  struct GAS_MLP_Handle *mlp = solver;
+  struct ATS_Peer *p;
+  struct ATS_Address *res;
+
+  GNUNET_assert (NULL != solver);
+  GNUNET_assert (NULL != peer);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Getting preferred address for `%s'\n",
+      GNUNET_i2s (peer));
+
+  /* Is this peer included in the problem? */
+  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
+                                                     peer)))
+    {
+      LOG (GNUNET_ERROR_TYPE_INFO, "Adding peer `%s' to list of 
requested_peers with requests\n",
+          GNUNET_i2s (peer));
+
+      p = GNUNET_malloc (sizeof (struct ATS_Peer));
+      p->id = (*peer);
+      p->f = get_peer_pref_value (mlp, peer);
+      GNUNET_CONTAINER_multipeermap_put (mlp->requested_peers,
+                                        peer, p,
+                                        
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+
+      /* Added new peer, we have to rebuild problem before solving */
+      mlp->mlp_prob_changed = GNUNET_YES;
+
+      if ((GNUNET_YES == mlp->mlp_auto_solve)&&
+          (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains(mlp->addresses,
+                                                               peer)))
+      {
+        mlp->exclude_peer = peer;
+        GAS_mlp_solve_problem (mlp);
+        mlp->exclude_peer = NULL;
+      }
+  }
+  /* Get prefered address */
+  res = NULL;
+  GNUNET_CONTAINER_multipeermap_get_multiple (mlp->addresses, peer,
+                                              mlp_get_preferred_address_it, 
&res);
+  return res;
+}
+
+
+/**
+ * Start a bulk operation
+ *
+ * @param solver the solver
+ */
+void
+GAS_mlp_bulk_start (void *solver)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Locking solver for bulk operation ...\n");
+  struct GAS_MLP_Handle *s = (struct GAS_MLP_Handle *) solver;
+
+  GNUNET_assert (NULL != solver);
+
+  s->bulk_lock ++;
+}
+
+void
+GAS_mlp_bulk_stop (void *solver)
+{
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Unlocking solver from bulk operation ...\n");
+
+  struct GAS_MLP_Handle *s = (struct GAS_MLP_Handle *) solver;
+  GNUNET_assert (NULL != solver);
+
+  if (s->bulk_lock < 1)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  s->bulk_lock --;
+
+  if (0 < s->bulk_request)
+  {
+    GAS_mlp_solve_problem (solver);
+    s->bulk_request= 0;
+  }
+}
+
+
+
+/**
+ * Stop notifying about address and bandwidth changes for this peer
+ *
+ * @param solver the MLP handle
+ * @param peer the peer
+ */
+void
+GAS_mlp_stop_get_preferred_address (void *solver,
+                                     const struct GNUNET_PeerIdentity *peer)
+{
+  struct GAS_MLP_Handle *mlp = solver;
+  struct ATS_Peer *p = NULL;
+
+  GNUNET_assert (NULL != solver);
+  GNUNET_assert (NULL != peer);
+  if (NULL != (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, 
peer)))
+  {
+    GNUNET_CONTAINER_multipeermap_remove (mlp->requested_peers, peer, p);
+    GNUNET_free (p);
+
+    mlp->mlp_prob_changed = GNUNET_YES;
+    if (GNUNET_YES == mlp->mlp_auto_solve)
+    {
+      GAS_mlp_solve_problem (solver);
+    }
+  }
+}
+
+
+/**
+ * Changes the preferences for a peer in the MLP problem
+ *
+ * @param solver the MLP Handle
+ * @param peer the peer
+ * @param kind the kind to change the preference
+ * @param pref_rel the relative score
+ */
+void
+GAS_mlp_address_change_preference (void *solver,
+                   const struct GNUNET_PeerIdentity *peer,
+                   enum GNUNET_ATS_PreferenceKind kind,
+                   double pref_rel)
+{
+  struct GAS_MLP_Handle *mlp = solver;
+  struct ATS_Peer *p = NULL;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Changing preference for address for peer `%s' 
to %.2f\n",
+      GNUNET_i2s(peer), pref_rel);
+
+  GNUNET_STATISTICS_update (mlp->stats,"# LP address preference changes", 1, 
GNUNET_NO);
+  /* Update the constraints with changed preferences */
+
+  /* Update quality constraint c7 */
+
+  /* Update relativity constraint c9 */
+  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, 
peer)))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR, "Updating preference for unknown peer 
`%s'\n", GNUNET_i2s(peer));
+    return;
+  }
+  p->f = get_peer_pref_value (mlp, peer);
+  LOG (GNUNET_ERROR_TYPE_ERROR, "PEER PREF: %s %.2f\n",
+      GNUNET_i2s(peer), p->f);
+  mlp_create_problem_update_value (&mlp->p, p->r_c9, mlp->p.c_r, -p->f, 
__LINE__);
+
+  /* Problem size changed: new address for peer with pending request */
+  mlp->mlp_prob_updated = GNUNET_YES;
+  if (GNUNET_YES == mlp->mlp_auto_solve)
+    GAS_mlp_solve_problem (solver);
+  return;
+}
+
+
+/**
+ * Get application feedback for a peer
+ *
+ * @param solver the solver handle
+ * @param application the application
+ * @param peer the peer to change the preference for
+ * @param scope the time interval for this feedback: [now - scope .. now]
+ * @param kind the kind to change the preference
+ * @param score the score
+ */
+void
+GAS_mlp_address_preference_feedback (void *solver,
+                                    void *application,
+                                    const struct GNUNET_PeerIdentity *peer,
+                                    const struct GNUNET_TIME_Relative scope,
+                                    enum GNUNET_ATS_PreferenceKind kind,
+                                    double score)
+{
+  struct GAS_PROPORTIONAL_Handle *s = solver;
+  GNUNET_assert (NULL != solver);
+  GNUNET_assert (NULL != peer);
+
+  GNUNET_assert (NULL != s);
+}
+
+
+static int
+mlp_free_peers (void *cls,
+               const struct GNUNET_PeerIdentity *key, void *value)
+{
+  struct GNUNET_CONTAINER_MultiPeerMap *map = cls;
+  struct ATS_Peer *p = value;
+
+  GNUNET_CONTAINER_multipeermap_remove (map, key, value);
+  GNUNET_free (p);
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Shutdown the MLP problem solving component
+ *
+ * @param solver the solver handle
+ */
+void *
+libgnunet_plugin_ats_mlp_done (void *cls)
+{
+  struct GAS_MLP_Handle *mlp = cls;
+  GNUNET_assert (mlp != NULL);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down mlp solver\n");
+  mlp_delete_problem (mlp);
+
+  GNUNET_CONTAINER_multipeermap_iterate (mlp->requested_peers,
+                                        &mlp_free_peers,
+                                        mlp->requested_peers);
+  GNUNET_CONTAINER_multipeermap_destroy (mlp->requested_peers);
+  mlp->requested_peers = NULL;
+
+  /* Clean up GLPK environment */
+  glp_free_env();
+  GNUNET_free (mlp);
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutdown down of mlp solver complete\n");
+  return NULL;
+}
+
+
+void *
+libgnunet_plugin_ats_mlp_init (void *cls)
+{
+  struct GNUNET_ATS_PluginEnvironment *env = cls;
+  struct GAS_MLP_Handle * mlp = GNUNET_malloc (sizeof (struct GAS_MLP_Handle));
+
+  double D;
+  double R;
+  double U;
+  unsigned long long tmp;
+  unsigned int b_min;
+  unsigned int n_min;
+  int c;
+  int c2;
+  int found;
+
+  struct GNUNET_TIME_Relative max_duration;
+  long long unsigned int max_iterations;
+
+  GNUNET_assert (NULL != env->cfg);
+  GNUNET_assert (NULL != env->stats);
+  GNUNET_assert (NULL != env->addresses);
+  GNUNET_assert (NULL != env->bandwidth_changed_cb);
+  GNUNET_assert (NULL != env->get_preferences_cb);
+  GNUNET_assert (NULL != env->get_property_cb);
+
+  /* Init GLPK environment */
+  int res = glp_init_env();
+  switch (res) {
+    case 0:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
+          "initialization successful");
+      break;
+    case 1:
+      LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
+          "environment is already initialized");
+      break;
+    case 2:
+      LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
+          "initialization failed (insufficient memory)");
+      GNUNET_free(mlp);
+      return NULL;
+      break;
+    case 3:
+      LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
+          "initialization failed (unsupported programming model)");
+      GNUNET_free(mlp);
+      return NULL;
+      break;
+    default:
+      break;
+  }
+
+   mlp->write_mip_mps = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "ats",
+          "DUMP_MLP");
+   if (GNUNET_SYSERR == mlp->write_mip_mps)
+     mlp->write_mip_mps = GNUNET_NO;
+   mlp->write_mip_sol = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "ats",
+          "DUMP_SOLUTION");
+   if (GNUNET_SYSERR == mlp->write_mip_sol)
+     mlp->write_mip_sol = GNUNET_NO;
+
+  mlp->pv.BIG_M = (double) BIG_M_VALUE;
+
+  /* Get timeout for iterations */
+  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time(env->cfg, "ats", 
"MLP_MAX_DURATION", &max_duration))
+  {
+    max_duration = MLP_MAX_EXEC_DURATION;
+  }
+
+  /* Get maximum number of iterations */
+  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_size(env->cfg, "ats", 
"MLP_MAX_ITERATIONS", &max_iterations))
+  {
+    max_iterations = MLP_MAX_ITERATIONS;
+  }
+
+  /* Get diversity coefficient from configuration */
+  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats",
+                                                      "MLP_COEFFICIENT_D",
+                                                      &tmp))
+    D = (double) tmp / 100;
+  else
+    D = DEFAULT_D;
+
+  /* Get proportionality coefficient from configuration */
+  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats",
+                                                      "MLP_COEFFICIENT_R",
+                                                      &tmp))
+    R = (double) tmp / 100;
+  else
+    R = DEFAULT_R;
+
+  /* Get utilization coefficient from configuration */
+  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats",
+                                                      "MLP_COEFFICIENT_U",
+                                                      &tmp))
+    U = (double) tmp / 100;
+  else
+    U = DEFAULT_U;
+
+  /* Get quality metric coefficients from configuration */
+  int i_delay = MLP_NaN;
+  int i_distance = MLP_NaN;
+  int q[GNUNET_ATS_QualityPropertiesCount] = GNUNET_ATS_QualityProperties;
+  for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++)
+  {
+    /* initialize quality coefficients with default value 1.0 */
+      mlp->pv.co_Q[c] = DEFAULT_QUALITY;
+
+    mlp->pv.q[c] = q[c];
+    if (q[c] == GNUNET_ATS_QUALITY_NET_DELAY)
+      i_delay = c;
+    if (q[c] == GNUNET_ATS_QUALITY_NET_DISTANCE)
+      i_distance = c;
+  }
+
+  if ((i_delay != MLP_NaN) && (GNUNET_OK == 
GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats",
+                                                      
"MLP_COEFFICIENT_QUALITY_DELAY",
+                                                      &tmp)))
+
+    mlp->pv.co_Q[i_delay] = (double) tmp / 100;
+  else
+    mlp->pv.co_Q[i_delay] = DEFAULT_QUALITY;
+
+  if ((i_distance != MLP_NaN) && (GNUNET_OK == 
GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats",
+                                                      
"MLP_COEFFICIENT_QUALITY_DISTANCE",
+                                                      &tmp)))
+    mlp->pv.co_Q[i_distance] = (double) tmp / 100;
+  else
+    mlp->pv.co_Q[i_distance] = DEFAULT_QUALITY;
+
+  /* Get minimum bandwidth per used address from configuration */
+  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats",
+                                                      "MLP_MIN_BANDWIDTH",
+                                                      &tmp))
+    b_min = tmp;
+  else
+  {
+    b_min = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
+  }
+
+  /* Get minimum number of connections from configuration */
+  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats",
+                                                      "MLP_MIN_CONNECTIONS",
+                                                      &tmp))
+    n_min = tmp;
+  else
+    n_min = DEFAULT_MIN_CONNECTIONS;
+
+  /* Init network quotas */
+  int quotas[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType;
+  for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
+  {
+      found = GNUNET_NO;
+      for (c2 = 0; c2 < env->network_count; c2++)
+      {
+          if (quotas[c] == env->networks[c2])
+          {
+              mlp->pv.quota_index[c] = env->networks[c2];
+              mlp->pv.quota_out[c] = env->out_quota[c2];
+              mlp->pv.quota_in[c] = env->in_quota[c2];
+              found = GNUNET_YES;
+              LOG (GNUNET_ERROR_TYPE_DEBUG, "Quota for network `%s' (in/out) 
%llu/%llu\n",
+                          
GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
+                          mlp->pv.quota_out[c],
+                          mlp->pv.quota_in[c]);
+              break;
+          }
+      }
+
+      /* Check if defined quota could make problem unsolvable */
+      if ((n_min * b_min) > mlp->pv.quota_out[c])
+      {
+        LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting inconsistent outbound quota 
configuration for network `%s', is %llu must be at least %llu\n"),
+            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
+            mlp->pv.quota_out[c],
+            (n_min * b_min));
+        mlp->pv.quota_out[c] = (n_min * b_min);
+      }
+      if ((n_min * b_min) > mlp->pv.quota_in[c])
+      {
+        LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting inconsistent inbound quota 
configuration for network `%s', is %llu must be at least %llu\n"),
+            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
+            mlp->pv.quota_in[c],
+            (n_min * b_min));
+        mlp->pv.quota_in[c] = (n_min * b_min);
+      }
+
+      /* Check if bandwidth is too big to make problem solvable */
+      if (mlp->pv.BIG_M < mlp->pv.quota_out[c])
+      {
+        LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting outbound quota configuration 
for network `%s'from %llu to %.0f\n"),
+            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
+            mlp->pv.quota_out[c],
+            mlp->pv.BIG_M);
+        mlp->pv.quota_out[c] = mlp->pv.BIG_M ;
+      }
+      if (mlp->pv.BIG_M < mlp->pv.quota_in[c])
+      {
+        LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting inbound quota configuration 
for network `%s' from %llu to %.0f\n"),
+            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
+            mlp->pv.quota_in[c],
+            mlp->pv.BIG_M);
+        mlp->pv.quota_in[c] = mlp->pv.BIG_M ;
+      }
+
+      if (GNUNET_NO == found)
+      {
+        mlp->pv.quota_in[c] = 
ntohl(GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
+        mlp->pv.quota_out[c] = 
ntohl(GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
+        LOG (GNUNET_ERROR_TYPE_INFO, _("Using default quota configuration for 
network `%s' (in/out) %llu/%llu\n"),
+            GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]),
+            mlp->pv.quota_in[c],
+            mlp->pv.quota_out[c]);
+      }
+  }
+  mlp->env = env;
+  env->sf.s_add = &GAS_mlp_address_add;
+  env->sf.s_address_update_property = &GAS_mlp_address_property_changed;
+  env->sf.s_address_update_session = &GAS_mlp_address_session_changed;
+  env->sf.s_address_update_inuse = &GAS_mlp_address_inuse_changed;
+  env->sf.s_address_update_network = &GAS_mlp_address_change_network;
+  env->sf.s_get = &GAS_mlp_get_preferred_address;
+  env->sf.s_get_stop = &GAS_mlp_stop_get_preferred_address;
+  env->sf.s_pref = &GAS_mlp_address_change_preference;
+  env->sf.s_feedback = &GAS_mlp_address_preference_feedback;
+  env->sf.s_del = &GAS_mlp_address_delete;
+  env->sf.s_bulk_start = &GAS_mlp_bulk_start;
+  env->sf.s_bulk_stop = &GAS_mlp_bulk_stop;
+
+
+  /* Assign options to handle */
+  mlp->stats = (struct GNUNET_STATISTICS_Handle *) env->stats;
+  mlp->addresses = env->addresses;
+  mlp->bw_changed_cb = env->bandwidth_changed_cb;
+  mlp->bw_changed_cb_cls = env->bw_changed_cb_cls;
+  mlp->get_preferences =  env->get_preferences_cb;
+  mlp->get_preferences_cls = env->get_preference_cls;
+  mlp->get_properties = env->get_property_cb;
+  mlp->get_properties_cls = env->get_property_cls;
+  /* Setting MLP Input variables */
+
+  mlp->pv.co_D = D;
+  mlp->pv.co_R = R;
+  mlp->pv.co_U = U;
+  mlp->pv.b_min = b_min;
+  mlp->pv.n_min = n_min;
+  mlp->pv.m_q = GNUNET_ATS_QualityPropertiesCount;
+  mlp->mlp_prob_changed = GNUNET_NO;
+  mlp->mlp_prob_updated = GNUNET_NO;
+  mlp->mlp_auto_solve = GNUNET_YES;
+  mlp->requested_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
+  mlp->bulk_request = 0;
+  mlp->bulk_lock = 0;
+
+  /* Setup GLPK */
+  /* Redirect GLPK output to GNUnet logging */
+  glp_term_hook (&mlp_term_hook, (void *) mlp);
+
+  /* Init LP solving parameters */
+  glp_init_smcp(&mlp->control_param_lp);
+  mlp->control_param_lp.msg_lev = GLP_MSG_OFF;
+#if VERBOSE_GLPK
+  mlp->control_param_lp.msg_lev = GLP_MSG_ALL;
+#endif
+  mlp->control_param_lp.it_lim = max_iterations;
+  mlp->control_param_lp.tm_lim = max_duration.rel_value_us / 1000LL;
+
+  /* Init MLP solving parameters */
+  glp_init_iocp(&mlp->control_param_mlp);
+  mlp->control_param_mlp.msg_lev = GLP_MSG_OFF;
+#if VERBOSE_GLPK
+  mlp->control_param_mlp.msg_lev = GLP_MSG_ALL;
+#endif
+  mlp->control_param_mlp.tm_lim = max_duration.rel_value_us / 1000LL;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "solver ready\n");
+
+  return mlp;
+}
+
+/* end of gnunet-service-ats_addresses_mlp.c */

Copied: gnunet/src/ats/libgnunet_plugin_ats_mlp.h (from rev 29953, 
gnunet/src/ats/gnunet-service-ats-solver_mlp.h)
===================================================================
--- gnunet/src/ats/libgnunet_plugin_ats_mlp.h                           (rev 0)
+++ gnunet/src/ats/libgnunet_plugin_ats_mlp.h   2013-10-08 16:34:07 UTC (rev 
29998)
@@ -0,0 +1,556 @@
+/*
+ (C) 2011 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ 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.
+ */
+
+/**
+ * @file ats/gnunet-service-ats-solver_mlp.h
+ * @brief ats MLP problem solver
+ * @author Matthias Wachs
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_ats_service.h"
+#include "gnunet_ats_plugin.h"
+#include "gnunet-service-ats_addresses.h"
+#include "gnunet_statistics_service.h"
+#if HAVE_LIBGLPK
+#include "glpk.h"
+#endif
+
+#ifndef GNUNET_SERVICE_ATS_ADDRESSES_MLP_H
+#define GNUNET_SERVICE_ATS_ADDRESSES_MLP_H
+
+#define BIG_M_VALUE (UINT32_MAX) /10
+#define BIG_M_STRING "unlimited"
+
+#define MLP_AVERAGING_QUEUE_LENGTH 3
+
+#define MLP_MAX_EXEC_DURATION   
GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10)
+#define MLP_MAX_ITERATIONS      4096
+
+#define DEFAULT_D 1.0
+#define DEFAULT_R 1.0
+#define DEFAULT_U 1.0
+#define DEFAULT_QUALITY 1.0
+#define DEFAULT_MIN_CONNECTIONS 4
+#define DEFAULT_PEER_PREFERENCE 1.0
+
+#define MLP_NaN -1
+#define MLP_UNDEFINED 0
+#define GLP_YES 1.0
+#define GLP_NO  0.0
+
+struct MLP_Solution
+{
+  struct GNUNET_TIME_Relative build_dur;
+  struct GNUNET_TIME_Relative lp_dur;
+  struct GNUNET_TIME_Relative mip_dur;
+
+  int lp_res;
+  int lp_presolv;
+  int mip_res;
+  int mip_presolv;
+
+  int p_elements;
+  int p_cols;
+  int p_rows;
+
+  int n_peers;
+  int n_addresses;
+
+};
+
+struct ATS_Peer
+{
+  struct GNUNET_PeerIdentity id;
+
+  /* Was this peer already added to the current problem? */
+  int processed;
+
+  /* constraint 2: 1 address per peer*/
+  unsigned int r_c2;
+
+  /* constraint 9: relativity */
+  unsigned int r_c9;
+
+  /* Legacy preference value */
+  double f;
+};
+
+struct MLP_Problem
+{
+  /**
+   * GLPK (MLP) problem object
+   */
+#if HAVE_LIBGLPK
+  glp_prob *prob;
+#else
+  void *prob;
+#endif
+
+  /* Number of addresses in problem */
+  unsigned int num_addresses;
+  /* Number of peers in problem */
+  unsigned int num_peers;
+  /* Number of elements in problem matrix */
+  unsigned int num_elements;
+
+  /* Row index constraint 2: */
+  unsigned int r_c2;
+  /* Row index constraint 4: minimum connections */
+  unsigned int r_c4;
+  /* Row index constraint 6: maximize diversity */
+  unsigned int r_c6;
+  /* Row index constraint 8: utilization*/
+  unsigned int r_c8;
+  /* Row index constraint 9: relativity*/
+  unsigned int r_c9;
+  /* Row indices quality metrics  */
+  int r_q[GNUNET_ATS_QualityPropertiesCount];
+  /* Row indices ATS network quotas */
+  int r_quota[GNUNET_ATS_NetworkTypeCount];
+
+  /* Column index Diversity (D) column */
+  int c_d;
+  /* Column index Utilization (U) column */
+  int c_u;
+  /* Column index Proportionality (R) column */
+  int c_r;
+  /* Column index quality metrics  */
+  int c_q[GNUNET_ATS_QualityPropertiesCount];
+
+  /* Problem matrix */
+  /* Current index */
+  unsigned int ci;
+  /* Row index array */
+  int *ia;
+  /* Column index array */
+  int *ja;
+  /* Column index value */
+  double *ar;
+
+};
+
+struct MLP_Variables
+{
+  /* Big M value for bandwidth capping */
+  double BIG_M;
+
+  /* ATS Quality metrics
+   *
+   * Array with GNUNET_ATS_QualityPropertiesCount elements
+   * contains mapping to GNUNET_ATS_Property*/
+  int q[GNUNET_ATS_QualityPropertiesCount];
+
+  /* Number of quality metrics */
+  int m_q;
+
+  /* Number of quality metrics */
+  int m_rc;
+
+  /* Quality metric coefficients*/
+  double co_Q[GNUNET_ATS_QualityPropertiesCount];
+
+  /* Ressource costs coefficients*/
+  double co_RC[GNUNET_ATS_QualityPropertiesCount];
+
+  /* Diversity coefficient */
+  double co_D;
+
+  /* Utility coefficient */
+  double co_U;
+
+  /* Relativity coefficient */
+  double co_R;
+
+  /* Minimum bandwidth assigned to an address */
+  unsigned int b_min;
+
+  /* Minimum number of addresses with bandwidth assigned */
+  unsigned int n_min;
+
+  /* Quotas */
+  /* Array mapping array index to ATS network */
+  int quota_index[GNUNET_ATS_NetworkTypeCount];
+  /* Outbound quotas */
+  unsigned long long quota_out[GNUNET_ATS_NetworkTypeCount];
+  /* Inbound quotas */
+
+  unsigned long long quota_in[GNUNET_ATS_NetworkTypeCount];
+
+  /* ATS ressource costs
+   * array with GNUNET_ATS_QualityPropertiesCount elements
+   * contains mapping to GNUNET_ATS_Property
+   * */
+  int rc[GNUNET_ATS_QualityPropertiesCount];
+
+};
+
+/**
+ * MLP Handle
+ */
+struct GAS_MLP_Handle
+{
+  struct GNUNET_ATS_PluginEnvironment *env;
+
+  /**
+   * Statistics handle
+   */
+  struct GNUNET_STATISTICS_Handle *stats;
+
+  /**
+   * Address hashmap for lookups
+   */
+  const struct GNUNET_CONTAINER_MultiPeerMap *addresses;
+
+  /**
+   * Addresses' bandwidth changed callback
+   */
+  GAS_bandwidth_changed_cb bw_changed_cb;
+
+  /**
+   * Addresses' bandwidth changed callback closure
+   */
+  void *bw_changed_cb_cls;
+
+  /**
+   * ATS function to get preferences
+   */
+  GAS_get_preferences get_preferences;
+
+  /**
+   * Closure for ATS function to get preferences
+   */
+  void *get_preferences_cls;
+
+  /**
+   * ATS function to get properties
+   */
+  GAS_get_properties get_properties;
+
+  /**
+   * Closure for ATS function to get properties
+   */
+  void *get_properties_cls;
+
+  /**
+   * Exclude peer from next result propagation
+   */
+  const struct GNUNET_PeerIdentity *exclude_peer;
+
+  /**
+   * Encapsulation for the MLP problem
+   */
+  struct MLP_Problem p;
+
+  /**
+   * Encapsulation for the MLP problem variables
+   */
+  struct MLP_Variables pv;
+
+  /**
+   * Encapsulation for the MLP solution
+   */
+  struct MLP_Solution ps;
+
+  /**
+   * Bulk lock
+   */
+
+  int bulk_lock;
+
+  /**
+   * Number of changes while solver was locked
+   */
+  int bulk_request;
+
+  /**
+   * GLPK LP control parameter
+   */
+#if HAVE_LIBGLPK
+  glp_smcp control_param_lp;
+#else
+  void *control_param_lp;
+#endif
+
+  /**
+   * GLPK LP control parameter
+   */
+#if HAVE_LIBGLPK
+  glp_iocp control_param_mlp;
+#else
+  void *control_param_mlp;
+#endif
+
+  /**
+   * Peers with pending address requests
+   */
+  struct GNUNET_CONTAINER_MultiPeerMap *requested_peers;
+
+  /**
+   * Was the problem updated since last solution
+   */
+  int mlp_prob_updated;
+
+  /**
+   * Has the problem size changed since last solution
+   */
+  int mlp_prob_changed;
+
+  /**
+   * Solve the problem automatically when updates occur?
+   * Default: GNUNET_YES
+   * Can be disabled for test and measurements
+   */
+  int mlp_auto_solve;
+
+  /**
+   * Write MILP problem to a MPS file
+   */
+  int write_mip_mps;
+
+  /**
+   * Write MILP problem to a MPS file
+   */
+  int write_mip_sol;
+
+};
+
+/**
+ * Address specific MLP information
+ */
+struct MLP_information
+{
+
+  /* Bandwidth assigned */
+  struct GNUNET_BANDWIDTH_Value32NBO b_out;
+  struct GNUNET_BANDWIDTH_Value32NBO b_in;
+
+  /* Address selected */
+  int n;
+
+  /* bandwidth column index */
+  signed int c_b;
+
+  /* address usage column */
+  signed int c_n;
+
+  /* row indexes */
+
+  /* constraint 1: bandwidth capping */
+  unsigned int r_c1;
+
+  /* constraint 3: minimum bandwidth */
+  unsigned int r_c3;
+};
+
+
+/**
+ * Solves the MLP problem
+ *
+ * @param solver the MLP Handle
+ * @return #GNUNET_OK if could be solved, GNUNET_SYSERR on failure
+ */
+int
+GAS_mlp_solve_problem (void *solver);
+
+
+/**
+ * Init the MLP problem solving component
+ *
+ * @param cfg the GNUNET_CONFIGURATION_Handle handle
+ * @param stats the GNUNET_STATISTICS handle
+ * @param network array of GNUNET_ATS_NetworkType with length dest_length
+ * @param out_dest array of outbound quotas
+ * @param in_dest array of outbound quota
+ * @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 callback to get relative preferences for a peer
+ * @param get_properties_cls for callback to get relative properties
+ * @param get_properties_cls cls for callback to get relative properties
+ * @return struct GAS_MLP_Handle on success, NULL on fail
+ */
+void *
+GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg,
+             const struct GNUNET_STATISTICS_Handle *stats,
+    const struct GNUNET_CONTAINER_MultiPeerMap *addresses, int *network,
+    unsigned long long *out_dest, unsigned long long *in_dest, int dest_length,
+    GAS_bandwidth_changed_cb bw_changed_cb, void *bw_changed_cb_cls,
+    GAS_get_preferences get_preference, void *get_preference_cls,
+    GAS_get_properties get_properties, void *get_properties_cls);
+
+
+/**
+ * Add a single address within a network to the solver
+ *
+ * @param solver the solver Handle
+ * @param address the address to add
+ * @param network network type of this address
+ */
+void
+GAS_mlp_address_add (void *solver, struct ATS_Address *address,
+    uint32_t network);
+
+
+/**
+ * Transport properties for this address have changed
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param type the ATSI type in HBO
+ * @param abs_value the absolute value of the property
+ * @param rel_value the normalized value
+ */
+void
+GAS_mlp_address_property_changed (void *solver, struct ATS_Address *address,
+    uint32_t type, uint32_t abs_value, double rel_value);
+
+
+/**
+ * Transport session for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param cur_session the current session
+ * @param new_session the new session
+ */
+void
+GAS_mlp_address_session_changed (void *solver, struct ATS_Address *address,
+                                uint32_t cur_session, uint32_t new_session);
+
+
+/**
+ * Usage for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param in_use usage state
+ */
+void
+GAS_mlp_address_inuse_changed (void *solver, struct ATS_Address *address,
+    int in_use);
+
+/**
+ * Network scope for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param current_network the current network
+ * @param new_network the new network
+ */
+void
+GAS_mlp_address_change_network (void *solver, struct ATS_Address *address,
+    uint32_t current_network, uint32_t new_network);
+
+/**
+ * Deletes a single address in the MLP problem
+ *
+ * The MLP problem has to be recreated and the problem has to be resolved
+ *
+ * @param solver the MLP Handle
+ * @param address the address to delete
+ * @param session_only delete only session not whole address
+ */
+void
+GAS_mlp_address_delete (void *solver, struct ATS_Address *address,
+    int session_only);
+
+/**
+ * Changes the preferences for a peer in the MLP problem
+ *
+ * @param solver the MLP Handle
+ * @param peer the peer
+ * @param kind the kind to change the preference
+ * @param pref_rel the relative score
+ */
+void
+GAS_mlp_address_change_preference (void *solver,
+    const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind 
kind,
+    double pref_rel);
+
+/**
+ * Get application feedback for a peer
+ *
+ * @param solver the solver handle
+ * @param application the application
+ * @param peer the peer to change the preference for
+ * @param scope the time interval for this feedback: [now - scope .. now]
+ * @param kind the kind to change the preference
+ * @param score the score
+ */
+void
+GAS_mlp_address_preference_feedback (void *solver, void *application,
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_TIME_Relative scope,
+    enum GNUNET_ATS_PreferenceKind kind, double score);
+
+/**
+ * Start a bulk operation
+ *
+ * @param solver the solver
+ */
+void
+GAS_mlp_bulk_start (void *solver);
+
+/**
+ * Bulk operation done
+ */
+void
+GAS_mlp_bulk_stop (void *solver);
+
+/**
+ * Get the preferred address for a specific peer until
+ * GAS_mlp_stop_get_preferred_address is called
+ *
+ * @param solver the MLP Handle
+ * @param peer the peer
+ * @return suggested address
+ */
+const struct ATS_Address *
+GAS_mlp_get_preferred_address (void *solver,
+    const struct GNUNET_PeerIdentity *peer);
+
+/**
+ * Stop notifying about address and bandwidth changes for this peer
+ *
+ * @param solver the MLP handle
+ * @param peer the peer
+ */
+void
+GAS_mlp_stop_get_preferred_address (void *solver,
+    const struct GNUNET_PeerIdentity *peer);
+
+/**
+ * Shutdown the MLP problem solving component
+ *
+ * @param solver the solver handle
+ */
+void
+GAS_mlp_done (void *solver);
+
+#endif
+/* end of gnunet-service-ats_addresses_mlp.h */

Copied: gnunet/src/ats/libgnunet_plugin_ats_proportional.c (from rev 29953, 
gnunet/src/ats/gnunet-service-ats-solver_proportional.c)
===================================================================
--- gnunet/src/ats/libgnunet_plugin_ats_proportional.c                          
(rev 0)
+++ gnunet/src/ats/libgnunet_plugin_ats_proportional.c  2013-10-08 16:34:07 UTC 
(rev 29998)
@@ -0,0 +1,1507 @@
+/*
+ This file is part of GNUnet.
+ (C) 2011 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ 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.
+ */
+
+/**
+ * @file ats/gnunet-service-ats-solver_proportional.c
+ * @brief ATS proportional solver
+ * @author Matthias Wachs
+ * @author Christian Grothoff
+ */
+#include "libgnunet_plugin_ats_proportional.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "ats-proportional",__VA_ARGS__)
+
+
+/**
+ *
+ * NOTE: Do not change this documentation. This documentation is based
+ * on gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex
+ * use build_txt.sh to generate plaintext output
+ *
+ * ATS addresses : proportional solver
+ *
+ *    The proportional solver ("proportional") distributes the available
+ *    bandwidth fair over all the addresses influenced by the
+ *    preference values. For each available network type an in- and
+ *    outbound quota is configured and the bandwidth available in
+ *    these networks is distributed over the addresses.  The solver
+ *    first assigns every addresses the minimum amount of bandwidth
+ *    GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT and then distributes the
+ *    remaining bandwidth available according to the preference
+ *    values. For each peer only a single address gets bandwidth
+ *    assigned and only one address marked as active.  The most
+ *    important functionality for the solver is implemented in: *
+ *    find_address_it is an hashmap iterator returning the prefered
+ *    address for an peer * update_quota_per_network distributes
+ *    available bandwidth for a network over active addresses
+ *
+ *    Changes to addresses automatically have an impact on the the
+ *    bandwidth assigned to other addresses in the same network since
+ *    the solver distributes the remaining bandwidth over the
+ *    addresses in the network.  When changes to the addresses occur,
+ *    the solver first performs the changes, like adding or deleting
+ *    addresses, and then updates bandwidth assignment for the
+ *    affected network. Bandwidth assignment is only recalculated on
+ *    demand when an address is requested by a client for a peer or
+ *    when the addresses available have changed or an address changed
+ *    the network it is located in. When the bandwidth assignment has
+ *    changed the callback is called with the new bandwidth
+ *    assignments. The bandwidth distribution for a network is
+ *    recalculated due to: * address suggestion requests * address
+ *    deletions * address switching networks during address update *
+ *    preference changes
+ *
+ *     3.1 Data structures used
+ *
+ *    For each ATS network (e.g. WAN, LAN, loopback) a struct Network
+ *    is used to specify network related information as total adresses
+ *    and active addresses in this network and the configured in- and
+ *    outbound quota. Each network also contains a list of addresses
+ *    added to the solver located in this network. The proportional
+ *    solver uses the addresses' solver_information field to store the
+ *    proportional network it belongs to for each address.
+ *
+ *     3.2 Initializing
+ *
+ *    When the proportional solver is initialized the solver creates a
+ *    new solver handle and initializes the network structures with
+ *    the quotas passed from addresses and returns the handle solver.
+ *
+ *     3.3 Adding an address
+ *
+ *    When a new address is added to the solver using s_add, a lookup
+ *    for the network for this address is done and the address is
+ *    enqueued in in the linked list of the network.
+ *
+ *     3.4 Updating an address
+ *
+ *    The main purpose of address updates is to update the ATS
+ *    information for addresse selection. Important for the proportional
+ *    solver is when an address switches network it is located
+ *    in. This is common because addresses added by transport's
+ *    validation mechanism are commonly located in
+ *    GNUNET_ATS_NET_UNSPECIFIED. Addresses in validation are located
+ *    in this network type and only if a connection is successful on
+ *    return of payload data transport switches to the real network
+ *    the address is located in.  When an address changes networks it
+ *    is first of all removed from the old network using the solver
+ *    API function GAS_proportional_address_delete and the network in
+ *    the address struct is updated. A lookup for the respective new
+ *    proportional network is done and stored in the addresse's
+ *    solver_information field. Next the address is re-added to the
+ *    solver using the solver API function
+ *    GAS_proportional_address_add. If the address was marked as in
+ *    active, the solver checks if bandwidth is available in the
+ *    network and if yes sets the address to active and updates the
+ *    bandwidth distribution in this network. If no bandwidth is
+ *    available it sets the bandwidth for this address to 0 and tries
+ *    to suggest an alternative address. If an alternative address was
+ *    found, addresses' callback is called for this address.
+ *
+ *     3.5 Deleting an address
+ *
+ *    When an address is removed from the solver, it removes the
+ *    respective address from the network and if the address was
+ *    marked as active, it updates the bandwidth distribution for this
+ *    network.
+ *
+ *     3.6 Requesting addresses
+ *
+ *    When an address is requested for a peer the solver performs a
+ *    lookup for the peer entry in addresses address hashmap and
+ *    selects the best address.  The selection of the most suitable
+ *    address is done in the find_address_it hashmap iterator
+ *    described in detail in section 3.7. If no address is returned,
+ *    no address can be suggested at the moment. If the address
+ *    returned is marked as active, the solver can return this
+ *    address. If the address is not marked as active, the solver
+ *    checks if another address belongign to this peer is marked as
+ *    active and marks the address as inactive, updates the bandwidth
+ *    for this address to 0, call the bandwidth changed callback for
+ *    this address due to the change and updates quota assignment for
+ *    the addresse's network. the now in-active address is belonging
+ *    to. The solver marks the new address as active and updates the
+ *    bandwidth assignment for this network.
+ *
+ *     3.7 Choosing addresses
+ *
+ *    Choosing the best possible address for suggestion is done by
+ *    iterating over all addresses of a peer stored in addresses'
+ *    hashmap and using the hashmap iterator find_address_it to select
+ *    the best available address.  Several checks are done when an
+ *    address is selected. First if this address is currently blocked
+ *    by addresses from being suggested. An address is blocked for the
+ *    duration of ATS_BLOCKING_DELTA when it is suggested to
+ *    transport. Next it is checked if at least
+ *    GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT bytes bandwidth is available
+ *    in the addresse's network, because suggesting an address without
+ *    bandwidth does not make sense. This also ensures that all active
+ *    addresses in this network get at least the minimum amount of
+ *    bandwidth assigned. In the next step the solver ensures that for
+ *    tcp connections inbound connections are prefered over outbound
+ *    connections. In the next stet the solver ensures that
+ *    connections are prefered in the following order: * connections
+ *    are already established and have bandwidth assigned *
+ *    connections with a shorter distance * connectes have a shorter
+ *    latency
+ *
+ *     3.8 Changing preferences
+ *
+ *     3.9 Shutdown
+ *
+ *    During shutdown all network entries and aging processes are
+ *    destroyed and freed.
+ *
+ *
+ * OLD DOCUMENTATION
+ *
+ * This solver assigns in and outbound bandwidth equally for all
+ * addresses in specific network type (WAN, LAN) based on configured
+ * in and outbound quota for this network.
+ *
+ * The solver is notified by addresses about changes to the addresses
+ * and recalculates the bandwith assigned if required. The solver
+ * notifies addresses by calling the GAS_bandwidth_changed_cb
+ * callback.
+ *
+ * - Initialization
+ *
+ *
+ *
+ *
+ * For each peer only a single is selected and marked as "active" in the 
address
+ * struct.
+ *
+ * E.g.:
+ *
+ * You have the networks WAN and LAN and quotas
+ * WAN_TOTAL_IN, WAN_TOTAL_OUT
+ * LAN_TOTAL_IN, LAN_TOTAL_OUT
+ *
+ * If you have x addresses in the network segment LAN, the quotas are
+ * QUOTA_PER_ADDRESS = LAN_TOTAL_OUT / x
+ *
+ * Quotas are automatically recalculated and reported back when addresses are
+ * - requested
+ *
+ */
+
+#define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_SECONDS, 10)
+#define PREF_AGING_FACTOR 0.95
+
+#define DEFAULT_REL_PREFERENCE 1.0
+#define DEFAULT_ABS_PREFERENCE 0.0
+#define MIN_UPDATE_INTERVAL GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_SECONDS, 10)
+
+/**
+ * A handle for the proportional solver
+ */
+struct GAS_PROPORTIONAL_Handle
+{
+   struct GNUNET_ATS_PluginEnvironment *env;
+
+  /**
+   * Statistics handle
+   */
+  struct GNUNET_STATISTICS_Handle *stats;
+
+  /**
+   * Hashmap containing all valid addresses
+   */
+  const struct GNUNET_CONTAINER_MultiPeerMap *addresses;
+
+  /**
+   * Pending address requests
+   */
+  struct GNUNET_CONTAINER_MultiPeerMap *requests;
+
+  /**
+   * 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;
+
+  /**
+   * ATS function to get properties
+   */
+  GAS_get_properties get_properties;
+
+  /**
+   * Closure for ATS function to get properties
+   */
+  void *get_properties_cls;
+
+  /**
+   * Bulk lock
+   */
+  int bulk_lock;
+
+  /**
+   * Number of changes while solver was locked
+   */
+  int bulk_requests;
+
+  /**
+   * Total number of addresses for solver
+   */
+  unsigned int total_addresses;
+
+  /**
+   * Number of active addresses for solver
+   */
+  unsigned int active_addresses;
+
+  /**
+   * Networks array
+   */
+  struct Network *network_entries;
+
+  /**
+   * Number of networks
+   */
+  unsigned int network_count;
+
+};
+
+/**
+ * Representation of a network
+ */
+struct Network
+{
+  /**
+   * ATS network type
+   */
+  unsigned int type;
+
+  /**
+   * Network description
+   */
+  char *desc;
+
+  /**
+   * Total inbound quota
+   *
+   */
+  unsigned long long total_quota_in;
+
+  /**
+   * Total outbound quota
+   *
+   */
+  unsigned long long total_quota_out;
+
+  /**
+   * Number of active addresses for this network
+   */
+  unsigned int active_addresses;
+
+  /**
+   * Number of total addresses for this network
+   */
+  unsigned int total_addresses;
+
+  /**
+   * String for statistics total addresses
+   */
+  char *stat_total;
+
+  /**
+   * String for statistics active addresses
+   */
+  char *stat_active;
+
+  struct AddressWrapper *head;
+  struct AddressWrapper *tail;
+};
+
+/**
+ * Wrapper for addresses to store them in network's linked list
+ */
+struct AddressWrapper
+{
+  /**
+   * Next in DLL
+   */
+  struct AddressWrapper *next;
+
+  /**
+   * Previous in DLL
+   */
+  struct AddressWrapper *prev;
+
+  /**
+   * The address
+   */
+  struct ATS_Address *addr;
+};
+
+/**
+ *  Important solver functions
+ *  ---------------------------
+ */
+
+void *
+libgnunet_plugin_ats_proportional_init (void *cls)
+{
+  struct GNUNET_ATS_PluginEnvironment *env = cls;
+  struct GAS_PROPORTIONAL_Handle *s;
+  struct Network * cur;
+  char * net_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString;
+  int c;
+
+  GNUNET_assert (NULL != env);
+  GNUNET_assert(NULL != env->cfg);
+  GNUNET_assert(NULL != env->stats);
+  GNUNET_assert(NULL != env->bandwidth_changed_cb);
+  GNUNET_assert(NULL != env->get_preferences_cb);
+  GNUNET_assert(NULL != env->get_property_cb);
+
+  s = GNUNET_malloc (sizeof (struct GAS_PROPORTIONAL_Handle));
+  s->env = env;
+  env->sf.s_add = &GAS_proportional_address_add;
+  env->sf.s_address_update_property = 
&GAS_proportional_address_property_changed;
+  env->sf.s_address_update_session = &GAS_proportional_address_session_changed;
+  env->sf.s_address_update_inuse = &GAS_proportional_address_inuse_changed;
+  env->sf.s_address_update_network = &GAS_proportional_address_change_network;
+  env->sf.s_get = &GAS_proportional_get_preferred_address;
+  env->sf.s_get_stop = &GAS_proportional_stop_get_preferred_address;
+  env->sf.s_pref = &GAS_proportional_address_change_preference;
+  env->sf.s_feedback = &GAS_proportional_address_preference_feedback;
+  env->sf.s_del = &GAS_proportional_address_delete;
+  env->sf.s_bulk_start = &GAS_proportional_bulk_start;
+  env->sf.s_bulk_stop = &GAS_proportional_bulk_stop;
+
+  s->stats = (struct GNUNET_STATISTICS_Handle *) env->stats;
+  s->bw_changed = env->bandwidth_changed_cb;
+  s->bw_changed_cls = env->bw_changed_cb_cls;
+  s->get_preferences = env->get_preferences_cb;
+  s->get_preferences_cls = env->get_preference_cls;
+  s->get_properties = env->get_property_cb;
+  s->get_properties_cls = env->get_property_cls;
+  s->network_count = env->network_count;
+  s->network_entries = GNUNET_malloc (env->network_count * sizeof (struct 
Network));
+
+  /* Init */
+  s->active_addresses = 0;
+  s->total_addresses = 0;
+  s->bulk_lock = GNUNET_NO;
+  s->addresses = env->addresses;
+  s->requests = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
+
+  for (c = 0; c < env->network_count; c++)
+  {
+    cur = &s->network_entries[c];
+    cur->total_addresses = 0;
+    cur->active_addresses = 0;
+    cur->type = env->networks[c];
+    cur->total_quota_in = env->in_quota[c];
+    cur->total_quota_out = env->out_quota[c];
+    cur->desc = net_str[c];
+    GNUNET_asprintf (&cur->stat_total,
+        "# ATS addresses %s total", cur->desc);
+    GNUNET_asprintf (&cur->stat_active,
+        "# ATS active addresses %s total", cur->desc);
+    LOG (GNUNET_ERROR_TYPE_INFO, "Added network %u `%s' %p\n", c, cur->desc, 
s);
+  }
+  return s;
+}
+
+void *
+libgnunet_plugin_ats_proportional_done (void *cls)
+{
+  struct GAS_PROPORTIONAL_Handle *s = cls;
+  struct AddressWrapper *cur;
+  struct AddressWrapper *next;
+  int c;
+  GNUNET_assert(s != NULL);
+  for (c = 0; c < s->network_count; c++)
+  {
+    if (s->network_entries[c].total_addresses > 0)
+    {
+      LOG(GNUNET_ERROR_TYPE_DEBUG,
+          "Had %u addresses for network `%s' not deleted during shutdown\n",
+          s->network_entries[c].total_addresses, s->network_entries[c].desc);
+      GNUNET_break(0);
+    }
+
+    if (s->network_entries[c].active_addresses > 0)
+    {
+      LOG(GNUNET_ERROR_TYPE_ERROR,
+          "Had %u active addresses for network `%s' not deleted during 
shutdown\n",
+          s->network_entries[c].active_addresses, s->network_entries[c].desc);
+      GNUNET_break(0);
+    }
+
+    next = s->network_entries[c].head;
+    while (NULL != (cur = next))
+    {
+      next = cur->next;
+      GNUNET_CONTAINER_DLL_remove(s->network_entries[c].head,
+          s->network_entries[c].tail, cur);
+      GNUNET_free(cur);
+    }
+    GNUNET_free(s->network_entries[c].stat_total);
+    GNUNET_free(s->network_entries[c].stat_active);
+  }
+  if (s->total_addresses > 0)
+  {
+    LOG(GNUNET_ERROR_TYPE_ERROR,
+        "Had %u addresses not deleted during shutdown\n", s->total_addresses);
+    GNUNET_break(0);
+  }
+  if (s->active_addresses > 0)
+  {
+    LOG(GNUNET_ERROR_TYPE_ERROR,
+        "Had %u active addresses not deleted during shutdown\n",
+        s->active_addresses);
+    GNUNET_break (0);
+  }
+  GNUNET_free (s->network_entries);
+  GNUNET_CONTAINER_multipeermap_destroy (s->requests);
+  GNUNET_free (s);
+  return NULL;
+}
+
+
+/**
+ * Test if bandwidth is available in this network to add an additional address
+ *
+ * @param net the network type to update
+ * @return GNUNET_YES or GNUNET_NO
+ */
+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)
+      && ((net->total_quota_out / na) > min_bw))
+  {
+    LOG(GNUNET_ERROR_TYPE_DEBUG,
+        "Enough bandwidth available for %u active addresses in network `%s'\n",
+        na, net->desc);
+
+    return GNUNET_YES;
+  }
+  LOG(GNUNET_ERROR_TYPE_DEBUG,
+      "Not enough bandwidth available for %u active addresses in network 
`%s'\n",
+      na, net->desc);
+  return GNUNET_NO;
+}
+
+/**
+ * Update bandwidth assigned to peers in this network
+ *
+ * @param s the solver handle
+ * @param net the network type to update
+ * @param address_except address excluded from notification, since we suggest
+ * this address
+ */
+static void
+distribute_bandwidth_in_network (struct GAS_PROPORTIONAL_Handle *s,
+    struct Network *net, struct ATS_Address *address_except)
+{
+  unsigned long long remaining_quota_in = 0;
+  unsigned long long quota_out_used = 0;
+
+  unsigned long long remaining_quota_out = 0;
+  unsigned long long quota_in_used = 0;
+  uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
+  double peer_prefs;
+  double total_prefs; /* Important: has to be double not float due to 
precision */
+  double cur_pref; /* Important: has to be double not float due to precision */
+  const double *t = NULL; /* Important: has to be double not float due to 
precision */
+  int c;
+
+  unsigned long long assigned_quota_in = 0;
+  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 (net->active_addresses == 0)
+    return; /* no addresses to update */
+
+  /* Idea
+   * Assign every peer in network minimum Bandwidth
+   * Distribute bandwidth left according to preference
+   */
+
+  if ((net->active_addresses * min_bw) > net->total_quota_in)
+  {
+    GNUNET_break(0);
+    return;
+  }
+  if ((net->active_addresses * min_bw) > net->total_quota_out)
+  {
+    GNUNET_break(0);
+    return;
+  }
+
+  remaining_quota_in = net->total_quota_in - (net->active_addresses * min_bw);
+  remaining_quota_out = net->total_quota_out - (net->active_addresses * 
min_bw);
+  LOG(GNUNET_ERROR_TYPE_DEBUG, "Remaining bandwidth : (in/out): %llu/%llu \n",
+      remaining_quota_in, remaining_quota_out);
+  total_prefs = 0.0;
+  for (cur = net->head; NULL != cur; cur = cur->next)
+  {
+    if (GNUNET_YES == cur->addr->active)
+    {
+      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;
+      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);
+
+      LOG(GNUNET_ERROR_TYPE_DEBUG,
+          "New quota for peer `%s' with preference (cur/total) %.3f/%.3f 
(in/out): %llu / %llu\n",
+          GNUNET_i2s (&cur->addr->peer), cur_pref, total_prefs,
+          assigned_quota_in, assigned_quota_out);
+    }
+    else
+    {
+      assigned_quota_in = 0;
+      assigned_quota_out = 0;
+    }
+
+    quota_in_used += assigned_quota_in;
+    quota_out_used += assigned_quota_out;
+    /* Prevent overflow due to rounding errors */
+    if (assigned_quota_in > UINT32_MAX)
+      assigned_quota_in = UINT32_MAX;
+    if (assigned_quota_out > UINT32_MAX)
+      assigned_quota_out = UINT32_MAX;
+
+    /* Compare to current bandwidth assigned */
+    if ((assigned_quota_in != ntohl (cur->addr->assigned_bw_in.value__))
+        || (assigned_quota_out != ntohl (cur->addr->assigned_bw_out.value__)))
+    {
+      cur->addr->assigned_bw_in.value__ = htonl (assigned_quota_in);
+      cur->addr->assigned_bw_out.value__ = htonl (assigned_quota_out);
+      /* Notify on change */
+      if ((GNUNET_YES == cur->addr->active) && (cur->addr != address_except))
+        s->bw_changed (s->bw_changed_cls, cur->addr);
+    }
+
+  }
+  LOG(GNUNET_ERROR_TYPE_DEBUG,
+      "Total bandwidth assigned is (in/out): %llu /%llu\n", quota_in_used,
+      quota_out_used);
+  if (quota_out_used > net->total_quota_out + 1) /* +1 is required due to 
rounding errors */
+  {
+    LOG(GNUNET_ERROR_TYPE_ERROR,
+        "Total outbound bandwidth assigned is larger than allowed 
(used/allowed) for %u active addresses: %llu / %llu\n",
+        net->active_addresses, quota_out_used, net->total_quota_out);
+  }
+  if (quota_in_used > net->total_quota_in + 1) /* +1 is required due to 
rounding errors */
+  {
+    LOG(GNUNET_ERROR_TYPE_ERROR,
+        "Total inbound bandwidth assigned is larger than allowed 
(used/allowed) for %u active addresses: %llu / %llu\n",
+        net->active_addresses, quota_in_used, net->total_quota_in);
+  }
+}
+
+struct FindBestAddressCtx
+{
+  struct GAS_PROPORTIONAL_Handle *s;
+  struct ATS_Address *best;
+};
+
+static int
+find_property_index (uint32_t type)
+{
+  int existing_types[] = GNUNET_ATS_QualityProperties;
+  int c;
+  for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++)
+    if (existing_types[c] == type)
+      return c;
+  return GNUNET_SYSERR;
+}
+
+/**
+ * Find a "good" address to use for a peer by iterating over the addresses for 
this peer.
+ * If we already have an existing address, we stick to it.
+ * Otherwise, we pick by lowest distance and then by lowest latency.
+ *
+ * @param cls the 'struct ATS_Address**' where we store the result
+ * @param key unused
+ * @param value another 'struct ATS_Address*' to consider using
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+find_best_address_it (void *cls,
+                     const struct GNUNET_PeerIdentity *key,
+                     void *value)
+{
+  struct FindBestAddressCtx *fba_ctx = (struct FindBestAddressCtx *) cls;
+  struct ATS_Address *current = (struct ATS_Address *) value;
+  struct GNUNET_TIME_Absolute now;
+  struct Network *net = (struct Network *) current->solver_information;
+  const double *norm_prop_cur;
+  const double *norm_prop_prev;
+  int index;
+
+  now = GNUNET_TIME_absolute_get ();
+
+  if (current->blocked_until.abs_value_us
+      == GNUNET_TIME_absolute_max (now, current->blocked_until).abs_value_us)
+  {
+    /* This address is blocked for suggestion */
+    LOG(GNUNET_ERROR_TYPE_DEBUG, "Address %p blocked for suggestion for %s \n",
+        current,
+        GNUNET_STRINGS_relative_time_to_string 
(GNUNET_TIME_absolute_get_difference (now, current->blocked_until), 
GNUNET_YES));
+    return GNUNET_OK;
+  }
+  if (GNUNET_NO == is_bandwidth_available_in_network (net))
+    return GNUNET_OK; /* There's no bandwidth available in this network */
+  if (NULL != fba_ctx->best)
+  {
+    GNUNET_assert(NULL != fba_ctx->best->plugin);
+    GNUNET_assert(NULL != current->plugin);
+    if (0 == strcmp (fba_ctx->best->plugin, current->plugin))
+    {
+      if ((0 != fba_ctx->best->addr_len) && (0 == current->addr_len))
+      {
+        /* saved address was an outbound address, but we have an inbound 
address */
+        fba_ctx->best = current;
+        return GNUNET_OK;
+      }
+      if (0 == fba_ctx->best->addr_len)
+      {
+        /* saved address was an inbound address, so do not overwrite */
+        return GNUNET_OK;
+      }
+    }
+  }
+  if (NULL == fba_ctx->best)
+  {
+    fba_ctx->best = current;
+    return GNUNET_OK;
+  }
+  if ((ntohl (fba_ctx->best->assigned_bw_in.value__) == 0)
+      && (ntohl (current->assigned_bw_in.value__) > 0))
+  {
+    /* stick to existing connection */
+    fba_ctx->best = current;
+    return GNUNET_OK;
+  }
+
+  norm_prop_cur = fba_ctx->s->get_properties (fba_ctx->s->get_properties_cls,
+      (const struct ATS_Address *) current);
+  norm_prop_prev = fba_ctx->s->get_properties (fba_ctx->s->get_properties_cls,
+      (const struct ATS_Address *) fba_ctx->best);
+  /*
+   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s previous %.2f current %.2f\n",
+   "DISTANCE", norm_prop_cur[1], norm_prop_cur[1]);
+   */
+  index = find_property_index (GNUNET_ATS_QUALITY_NET_DISTANCE);
+  if (GNUNET_SYSERR == index)
+  {
+    GNUNET_break(0);
+    return GNUNET_OK;
+  }
+  if (norm_prop_cur[index] < norm_prop_prev[index])
+  {
+    /* user shorter distance */
+    fba_ctx->best = current;
+    return GNUNET_OK;
+  }
+  /*
+   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s previous %.2f current %.2f\n",
+   "DELAY", norm_prop_cur[1], norm_prop_cur[1]);
+   */
+  index = find_property_index (GNUNET_ATS_QUALITY_NET_DELAY);
+  if (GNUNET_SYSERR == index)
+  {
+    GNUNET_break(0);
+    return GNUNET_OK;
+  }
+  if (norm_prop_cur[index] < norm_prop_prev[index])
+  {
+    /* user shorter delay */
+    fba_ctx->best = current;
+    return GNUNET_OK;
+  }
+
+  /* don't care */
+  return GNUNET_OK;
+}
+
+/**
+ *  Helper functions
+ *  ---------------------------
+ */
+
+/**
+ * Update bandwidth assignment for all networks
+ *
+ * @param s the solver handle
+ */
+static void
+distribute_bandwidth_in_all_networks (struct GAS_PROPORTIONAL_Handle *s)
+{
+  int i;
+  for (i = 0; i < s->network_count; i++)
+    distribute_bandwidth_in_network (s, &s->network_entries[i], NULL );
+}
+
+/**
+ * Lookup network struct by type
+ *
+ * @param s the solver handle
+ * @param type the network type
+ * @return the network struct
+ */
+static struct Network *
+get_network (struct GAS_PROPORTIONAL_Handle *s, uint32_t type)
+{
+  int c;
+  for (c = 0; c < s->network_count; c++)
+  {
+    if (s->network_entries[c].type == type)
+      return &s->network_entries[c];
+
+  }
+  return NULL ;
+}
+
+/**
+ * Hashmap Iterator to find current active address for peer
+ *
+ * @param cls last active address
+ * @param key peer's key
+ * @param value address to check
+ * @return #GNUNET_NO on double active address else #GNUNET_YES;
+ */
+static int
+get_active_address_it (void *cls,
+                      const struct GNUNET_PeerIdentity *key,
+                      void *value)
+{
+  struct ATS_Address **dest = cls;
+  struct ATS_Address *aa = (struct ATS_Address *) value;
+
+  if (GNUNET_YES == aa->active)
+  {
+
+    if (NULL != (*dest))
+    {
+      /* should never happen */
+      LOG(GNUNET_ERROR_TYPE_ERROR, "Multiple active addresses for peer `%s'\n",
+          GNUNET_i2s (&aa->peer));
+      GNUNET_break(0);
+      return GNUNET_NO;
+    }
+    (*dest) = aa;
+  }
+  return GNUNET_OK;
+}
+
+/**
+ * Find current active address for peer
+ *
+ * @param solver the solver handle
+ * @param addresses the address set
+ * @param peer the peer
+ * @return active address or NULL
+ */
+static struct ATS_Address *
+get_active_address (void *solver,
+                   const struct GNUNET_CONTAINER_MultiPeerMap * addresses,
+                   const struct GNUNET_PeerIdentity *peer)
+{
+  struct ATS_Address * dest = NULL;
+
+  GNUNET_CONTAINER_multipeermap_get_multiple (addresses, peer,
+                                             &get_active_address_it, &dest);
+  return dest;
+}
+
+
+static void
+addresse_increment (struct GAS_PROPORTIONAL_Handle *s, struct Network *net,
+    int total, int active)
+{
+  if (GNUNET_YES == total)
+  {
+    s->total_addresses++;
+    net->total_addresses++;
+    GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", 1, GNUNET_NO);
+    GNUNET_STATISTICS_update (s->stats, net->stat_total, 1, GNUNET_NO);
+  }
+  if (GNUNET_YES == active)
+  {
+    net->active_addresses++;
+    s->active_addresses++;
+    GNUNET_STATISTICS_update (s->stats, "# ATS active addresses total", 1,
+        GNUNET_NO);
+    GNUNET_STATISTICS_update (s->stats, net->stat_active, 1, GNUNET_NO);
+  }
+
+}
+
+
+static int
+addresse_decrement (struct GAS_PROPORTIONAL_Handle *s, struct Network *net,
+    int total, int active)
+{
+  int res = GNUNET_OK;
+  if (GNUNET_YES == total)
+  {
+    if (s->total_addresses < 1)
+    {
+      GNUNET_break(0);
+      res = GNUNET_SYSERR;
+    }
+    else
+    {
+      s->total_addresses--;
+      GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1,
+          GNUNET_NO);
+    }
+    if (net->total_addresses < 1)
+    {
+      GNUNET_break(0);
+      res = GNUNET_SYSERR;
+    }
+    else
+    {
+      net->total_addresses--;
+      GNUNET_STATISTICS_update (s->stats, net->stat_total, -1, GNUNET_NO);
+    }
+  }
+
+  if (GNUNET_YES == active)
+  {
+    if (net->active_addresses < 1)
+    {
+      GNUNET_break(0);
+      res = GNUNET_SYSERR;
+    }
+    else
+    {
+      net->active_addresses--;
+      GNUNET_STATISTICS_update (s->stats, net->stat_active, -1, GNUNET_NO);
+    }
+    if (s->active_addresses < 1)
+    {
+      GNUNET_break(0);
+      res = GNUNET_SYSERR;
+    }
+    else
+    {
+      s->active_addresses--;
+      GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1,
+          GNUNET_NO);
+    }
+  }
+  return res;
+}
+
+/**
+ *  Solver API functions
+ *  ---------------------------
+ */
+
+/**
+ * Changes the preferences for a peer in the problem
+ *
+ * @param solver the solver handle
+ * @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
+ */
+void
+GAS_proportional_address_change_preference (void *solver,
+                                           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 != peer);
+
+  distribute_bandwidth_in_all_networks (s);
+}
+
+
+/**
+ * Get application feedback for a peer
+ *
+ * @param solver the solver handle
+ * @param application the application
+ * @param peer the peer to change the preference for
+ * @param scope the time interval for this feedback: [now - scope .. now]
+ * @param kind the kind to change the preference
+ * @param score the score
+ */
+void
+GAS_proportional_address_preference_feedback (void *solver, void *application,
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_TIME_Relative scope,
+    enum GNUNET_ATS_PreferenceKind kind, double score)
+{
+  struct GAS_PROPORTIONAL_Handle *s = solver;
+  GNUNET_assert(NULL != solver);
+  GNUNET_assert(NULL != peer);
+
+  GNUNET_assert(NULL != s);
+  GNUNET_break(0);
+}
+
+/**
+ * Get the preferred address for a specific peer
+ *
+ * @param solver the solver handle
+ * @param peer the identity of the peer
+ */
+const struct ATS_Address *
+GAS_proportional_get_preferred_address (void *solver,
+    const struct GNUNET_PeerIdentity *peer)
+{
+  struct GAS_PROPORTIONAL_Handle *s = solver;
+  struct Network *net_prev;
+  struct Network *net_cur;
+  struct ATS_Address *prev;
+  struct FindBestAddressCtx fba_ctx;
+
+  GNUNET_assert(s != NULL);
+  GNUNET_assert(peer != NULL);
+
+  /* Add to list of pending requests */
+  if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (s->requests,
+                                                          peer))
+  {
+    GNUNET_assert (GNUNET_OK ==
+                  GNUNET_CONTAINER_multipeermap_put (s->requests,
+                                                     peer, NULL,
+                                                     
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  }
+
+  /* Get address with: stick to current address, lower distance, lower latency 
*/
+  fba_ctx.s = s;
+  fba_ctx.best = NULL;
+
+  GNUNET_CONTAINER_multipeermap_get_multiple (s->addresses, peer,
+                                             &find_best_address_it, &fba_ctx);
+  if (NULL == fba_ctx.best)
+  {
+    LOG(GNUNET_ERROR_TYPE_INFO, "Cannot suggest address for peer `%s'\n",
+        GNUNET_i2s (peer));
+    return NULL ;
+  }
+
+  LOG(GNUNET_ERROR_TYPE_INFO, "Suggesting %s address %p for peer `%s'\n",
+      (GNUNET_NO == fba_ctx.best->active) ? "inactive" : "active", 
fba_ctx.best,
+      GNUNET_i2s (peer));
+  net_cur = (struct Network *) fba_ctx.best->solver_information;
+  if (NULL == fba_ctx.best)
+  {
+    LOG(GNUNET_ERROR_TYPE_ERROR,
+        "Trying to suggesting unknown address peer `%s'\n", GNUNET_i2s (peer));
+    GNUNET_break(0);
+    return NULL ;
+  }
+  if (GNUNET_YES == fba_ctx.best->active)
+  {
+    /* This address was selected previously, so no need to update quotas */
+    return fba_ctx.best;
+  }
+
+  /* This address was not active, so we have to:
+   *
+   * - mark previous active address as not active
+   * - update quota for previous address network
+   * - update quota for this address network
+   */
+  prev = get_active_address (s,
+                            s->addresses, peer);
+  if (NULL != prev)
+  {
+    net_prev = (struct Network *) prev->solver_information;
+    prev->active = GNUNET_NO; /* No active any longer */
+    prev->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */
+    prev->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */
+    if (GNUNET_SYSERR == addresse_decrement (s, net_prev, GNUNET_NO, 
GNUNET_YES))
+      GNUNET_break(0);
+    distribute_bandwidth_in_network (s, net_prev, NULL );
+  }
+
+  if (GNUNET_NO == (is_bandwidth_available_in_network 
(fba_ctx.best->solver_information)))
+  {
+    GNUNET_break(0); /* This should never happen*/
+    return NULL ;
+  }
+
+  fba_ctx.best->active = GNUNET_YES;
+  addresse_increment (s, net_cur, GNUNET_NO, GNUNET_YES);
+  distribute_bandwidth_in_network (s, net_cur, fba_ctx.best );
+  return fba_ctx.best;
+}
+
+/**
+ * Stop notifying about address and bandwidth changes for this peer
+ *
+ * @param solver the solver handle
+ * @param peer the peer
+ */
+void
+GAS_proportional_stop_get_preferred_address (void *solver,
+    const struct GNUNET_PeerIdentity *peer)
+{
+  struct GAS_PROPORTIONAL_Handle *s = solver;
+  struct ATS_Address *cur;
+  struct Network *cur_net;
+
+  if (GNUNET_YES
+      == GNUNET_CONTAINER_multipeermap_contains (s->requests,
+                                                peer))
+    GNUNET_CONTAINER_multipeermap_remove (s->requests, peer,
+                                         NULL);
+
+  cur = get_active_address (s,
+                           s->addresses, peer);
+  if (NULL != cur)
+  {
+    /* Disabling current address */
+    cur_net = (struct Network *) cur->solver_information;
+    cur->active = GNUNET_NO; /* No active any longer */
+    cur->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */
+    cur->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */
+    if (GNUNET_SYSERR == addresse_decrement (s, cur_net, GNUNET_NO, 
GNUNET_YES))
+      GNUNET_break(0);
+    distribute_bandwidth_in_network (s, cur_net, NULL );
+  }
+  return;
+}
+
+/**
+ * Remove an address from the solver
+ *
+ * @param solver the solver handle
+ * @param address the address to remove
+ * @param session_only delete only session not whole address
+ */
+void
+GAS_proportional_address_delete (void *solver, struct ATS_Address *address,
+    int session_only)
+{
+  struct GAS_PROPORTIONAL_Handle *s = solver;
+  struct Network *net;
+  struct AddressWrapper *aw;
+  const struct ATS_Address *new_address;
+
+
+  /* Remove an adress completely, we have to:
+   * - Remove from specific network
+   * - Decrease number of total addresses
+   * - If active:
+   *   - decrease number of active addreses
+   *   - update quotas
+   */
+
+  net = (struct Network *) address->solver_information;
+
+  if (GNUNET_NO == session_only)
+  {
+    LOG(GNUNET_ERROR_TYPE_INFO,
+        "Deleting %s address %p for peer `%s' from network `%s' (total: %u/ 
active: %u)\n",
+        (GNUNET_NO == address->active) ? "inactive" : "active", address,
+        GNUNET_i2s (&address->peer), net->desc, net->total_addresses,
+        net->active_addresses);
+
+    /* Remove address */
+    addresse_decrement (s, net, GNUNET_YES, GNUNET_NO);
+    for (aw = net->head; NULL != aw; aw = aw->next)
+    {
+      if (aw->addr == address)
+        break;
+    }
+    if (NULL == aw)
+    {
+      GNUNET_break(0);
+      return;
+    }
+    GNUNET_CONTAINER_DLL_remove(net->head, net->tail, aw);
+    GNUNET_free(aw);
+  }
+  else
+  {
+    /* Remove session only: remove if active and update */
+    LOG(GNUNET_ERROR_TYPE_INFO,
+        "Deleting %s session %p for peer `%s' from network `%s' (total: %u/ 
active: %u)\n",
+        (GNUNET_NO == address->active) ? "inactive" : "active", address,
+        GNUNET_i2s (&address->peer), net->desc, net->total_addresses,
+        net->active_addresses);
+  }
+
+  if (GNUNET_YES == address->active)
+  {
+    /* Address was active, remove from network and update quotas*/
+    address->active = GNUNET_NO;
+    address->assigned_bw_in = BANDWIDTH_ZERO;
+    address->assigned_bw_out = BANDWIDTH_ZERO;
+
+    if (GNUNET_SYSERR == addresse_decrement (s, net, GNUNET_NO, GNUNET_YES))
+      GNUNET_break(0);
+    distribute_bandwidth_in_network (s, net, NULL );
+    if (NULL == (new_address = GAS_proportional_get_preferred_address (s, 
&address->peer)))
+    {
+      /* No alternative address found, disconnect peer */
+      s->bw_changed (s->bw_changed_cls, address);
+    }
+    else
+    {
+      s->bw_changed (s->bw_changed_cls, (struct ATS_Address *) new_address);
+    }
+  }
+  LOG(GNUNET_ERROR_TYPE_DEBUG,
+      "After deleting address now total %u and active %u addresses in network 
`%s'\n",
+      net->total_addresses, net->active_addresses, net->desc);
+
+}
+
+/**
+ * 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_DEBUG, "No lock pending, recalculating\n");
+    distribute_bandwidth_in_all_networks (s);
+    s->bulk_requests = 0;
+  }
+}
+
+
+/**
+ * Add a new single address to a network
+ *
+ * @param solver the solver Handle
+ * @param address the address to add
+ * @param network network type of this address
+ */
+void
+GAS_proportional_address_add (void *solver, struct ATS_Address *address,
+    uint32_t network);
+
+/**
+ * Transport properties for this address have changed
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param type the ATSI type in HBO
+ * @param abs_value the absolute value of the property
+ * @param rel_value the normalized value
+ */
+void
+GAS_proportional_address_property_changed (void *solver,
+    struct ATS_Address *address, uint32_t type, uint32_t abs_value,
+    double rel_value)
+{
+  struct GAS_PROPORTIONAL_Handle *s;
+  struct Network *n;
+
+  GNUNET_assert(NULL != solver);
+  GNUNET_assert(NULL != address);
+
+  s = (struct GAS_PROPORTIONAL_Handle *) solver;
+  n = (struct Network *) address->solver_information;
+
+  if (NULL == n)
+  {
+    GNUNET_break(0);
+    return;
+  }
+
+  LOG(GNUNET_ERROR_TYPE_DEBUG,
+      "Property `%s' for peer `%s' address %p changed to %.2f \n",
+      GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer),
+      address, rel_value);
+  switch (type)
+  {
+  case GNUNET_ATS_UTILIZATION_UP:
+  case GNUNET_ATS_UTILIZATION_DOWN:
+  case GNUNET_ATS_QUALITY_NET_DELAY:
+  case GNUNET_ATS_QUALITY_NET_DISTANCE:
+  case GNUNET_ATS_COST_WAN:
+  case GNUNET_ATS_COST_LAN:
+  case GNUNET_ATS_COST_WLAN:
+    distribute_bandwidth_in_network (s, n, GNUNET_NO);
+    break;
+  }
+}
+
+/**
+ * Transport session for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param cur_session the current session
+ * @param new_session the new session
+ */
+void
+GAS_proportional_address_session_changed (void *solver,
+    struct ATS_Address *address, uint32_t cur_session, uint32_t new_session)
+{
+  if (cur_session != new_session)
+  {
+    LOG(GNUNET_ERROR_TYPE_DEBUG, "Session changed from %u to %u\n", 
cur_session,
+        new_session);
+  }
+}
+
+/**
+ * Usage for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param in_use usage state
+ */
+void
+GAS_proportional_address_inuse_changed (void *solver,
+    struct ATS_Address *address, int in_use)
+{
+  LOG(GNUNET_ERROR_TYPE_DEBUG, "Usage changed to %s\n",
+      (GNUNET_YES == in_use) ? "USED" : "UNUSED");
+}
+
+/**
+ * Network scope for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param current_network the current network
+ * @param new_network the new network
+ */
+void
+GAS_proportional_address_change_network (void *solver,
+    struct ATS_Address *address, uint32_t current_network, uint32_t 
new_network)
+{
+  struct ATS_Address *new;
+  struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) 
solver;
+  int save_active = GNUNET_NO;
+  struct Network *new_net = NULL;
+
+  if (current_network == new_network)
+  {
+    GNUNET_break(0);
+    return;
+  }
+
+  /* Network changed */
+  LOG(GNUNET_ERROR_TYPE_DEBUG,
+      "Network type changed, moving %s address from `%s' to `%s'\n",
+      (GNUNET_YES == address->active) ? "active" : "inactive",
+      GNUNET_ATS_print_network_type (current_network),
+      GNUNET_ATS_print_network_type (new_network));
+
+  save_active = address->active;
+
+  /* Disable and assign no bandwidth */
+  address->active = GNUNET_NO;
+  address->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */
+  address->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */
+
+  /* Remove from old network */
+  GAS_proportional_address_delete (solver, address, GNUNET_NO);
+
+  /* Set new network type */
+  if (NULL == (new_net = get_network (solver, new_network)))
+  {
+    /* Address changed to invalid network... */
+    LOG(GNUNET_ERROR_TYPE_ERROR,
+        _("Invalid network type `%u' `%s': Disconnect!\n"), new_network,
+        GNUNET_ATS_print_network_type (new_network));
+
+    /* Find new address to suggest since no bandwidth in network*/
+    if (NULL == (new = (struct ATS_Address *) 
GAS_proportional_get_preferred_address (s, &address->peer)))
+    {
+      /* No alternative address found, disconnect peer */
+      s->bw_changed (s->bw_changed_cls, address);
+    }
+    return;
+  }
+
+  /* Add to new network and update*/
+  address->solver_information = new_net;
+  GAS_proportional_address_add (solver, address, new_network);
+  if (GNUNET_YES == save_active)
+  {
+    /* check if bandwidth available in new network */
+    if (GNUNET_YES == (is_bandwidth_available_in_network (new_net)))
+    {
+      /* Assign bandwidth to updated address */
+      address->active = GNUNET_YES;
+      addresse_increment (s, new_net, GNUNET_NO, GNUNET_YES);
+      distribute_bandwidth_in_network (solver, new_net, NULL );
+    }
+    else
+    {
+      LOG(GNUNET_ERROR_TYPE_DEBUG,
+          "Not enough bandwidth in new network, suggesting alternative address 
..\n");
+      /* Find new address to suggest since no bandwidth in network*/
+      if (NULL
+          == (new =
+              (struct ATS_Address *) GAS_proportional_get_preferred_address (s,
+                  &address->peer)))
+      {
+        /* No alternative address found, disconnect peer */
+        s->bw_changed (s->bw_changed_cls, address);
+      }
+    }
+  }
+}
+
+/**
+ * Add a new single address to a network
+ *
+ * @param solver the solver Handle
+ * @param address the address to add
+ * @param network network type of this address
+ */
+void
+GAS_proportional_address_add (void *solver, struct ATS_Address *address,
+    uint32_t network)
+{
+  struct GAS_PROPORTIONAL_Handle *s = solver;
+  struct Network *net = NULL;
+  struct AddressWrapper *aw = NULL;
+  const struct ATS_Address *new_address;
+
+  GNUNET_assert(NULL != s);
+
+
+  net = get_network (s, network);
+  if (NULL == net)
+  {
+    GNUNET_break(0);
+    return;
+  }
+
+  aw = GNUNET_malloc (sizeof (struct AddressWrapper));
+  aw->addr = address;
+  GNUNET_CONTAINER_DLL_insert(net->head, net->tail, aw);
+  addresse_increment (s, net, GNUNET_YES, GNUNET_NO);
+  aw->addr->solver_information = net;
+
+  if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (s->requests, 
&address->peer))
+  {
+    if (NULL == get_active_address (s, s->addresses, &address->peer))
+    {
+      if (NULL != (new_address = GAS_proportional_get_preferred_address (s, 
&address->peer)))
+          s->bw_changed (s->bw_changed_cls, (struct ATS_Address *) address);
+    }
+  }
+  LOG(GNUNET_ERROR_TYPE_DEBUG,
+      "After adding address now total %u and active %u addresses in network 
`%s'\n",
+      net->total_addresses, net->active_addresses, net->desc);
+}
+
+
+/* end of gnunet-service-ats-solver_proportional.c */

Copied: gnunet/src/ats/libgnunet_plugin_ats_proportional.h (from rev 29953, 
gnunet/src/ats/gnunet-service-ats-solver_proportional.h)
===================================================================
--- gnunet/src/ats/libgnunet_plugin_ats_proportional.h                          
(rev 0)
+++ gnunet/src/ats/libgnunet_plugin_ats_proportional.h  2013-10-08 16:34:07 UTC 
(rev 29998)
@@ -0,0 +1,186 @@
+/*
+ This file is part of GNUnet.
+ (C) 2011 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ 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.
+ */
+
+/**
+ * @file ats/gnunet-service-ats-solver_proportional.h
+ * @brief ATS proportional solver
+ * @author Matthias Wachs
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_ats_plugin.h"
+#include "gnunet-service-ats_addresses.h"
+
+/**
+ * ATS proportional solver
+ *
+ * General description
+ */
+
+/**
+ * Changes the preferences for a peer in the problem
+ *
+ * @param solver the solver handle
+ * @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
+ */
+void
+GAS_proportional_address_change_preference (void *solver,
+    const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind 
kind,
+    double pref_rel);
+
+/**
+ * Get application feedback for a peer
+ *
+ * @param solver the solver handle
+ * @param application the application
+ * @param peer the peer to change the preference for
+ * @param scope the time interval for this feedback: [now - scope .. now]
+ * @param kind the kind to change the preference
+ * @param score the score
+ */
+void
+GAS_proportional_address_preference_feedback (void *solver, void *application,
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_TIME_Relative scope,
+    enum GNUNET_ATS_PreferenceKind kind, double score);
+
+/**
+ * Shutdown the proportional problem solver
+ *
+ * @param solver the respective handle to shutdown
+ */
+void
+GAS_proportional_done (void * solver);
+
+/**
+ * Add a single address within a network to the solver
+ *
+ * @param solver the solver Handle
+ * @param address the address to add
+ * @param network network type of this address
+ */
+void
+GAS_proportional_address_add (void *solver, struct ATS_Address *address,
+    uint32_t network);
+
+/**
+ * Transport properties for this address have changed
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param type the ATSI type in HBO
+ * @param abs_value the absolute value of the property
+ * @param rel_value the normalized value
+ */
+void
+GAS_proportional_address_property_changed (void *solver,
+    struct ATS_Address *address, uint32_t type, uint32_t abs_value,
+    double rel_value);
+
+/**
+ * Transport session for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param cur_session the current session
+ * @param new_session the new session
+ */
+void
+GAS_proportional_address_session_changed (void *solver,
+    struct ATS_Address *address, uint32_t cur_session, uint32_t new_session);
+
+/**
+ * Usage for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param in_use usage state
+ */
+void
+GAS_proportional_address_inuse_changed (void *solver,
+    struct ATS_Address *address, int in_use);
+
+/**
+ * Network scope for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param current_network the current network
+ * @param new_network the new network
+ */
+void
+GAS_proportional_address_change_network (void *solver,
+    struct ATS_Address *address, uint32_t current_network, uint32_t 
new_network);
+
+/**
+ * Remove an address from the solver
+ *
+ * @param solver the solver handle
+ * @param address the address to remove
+ * @param session_only delete only session not whole address
+ */
+void
+GAS_proportional_address_delete (void *solver, struct ATS_Address *address,
+    int session_only);
+
+/**
+ * Start a bulk operation
+ *
+ * @param solver the solver
+ */
+void
+GAS_proportional_bulk_start (void *solver);
+
+/**
+ * Bulk operation done
+ */
+void
+GAS_proportional_bulk_stop (void *solver);
+
+/**
+ * Stop notifying about address and bandwidth changes for this peer
+ *
+ * @param solver the proportional handle
+ * @param peer the peer
+ */
+void
+GAS_proportional_stop_get_preferred_address (void *solver,
+    const struct GNUNET_PeerIdentity *peer);
+
+/**
+ * Get the prefered address for a specific peer
+ *
+ * @param solver the solver handle
+ * @param peer the identity of the peer
+ */
+const struct ATS_Address *
+GAS_proportional_get_preferred_address (void *solver,
+    const struct GNUNET_PeerIdentity *peer);
+
+/* end of gnunet-service-ats-solver_proportional.c */

Added: gnunet/src/include/gnunet_ats_plugin.h
===================================================================
--- gnunet/src/include/gnunet_ats_plugin.h                              (rev 0)
+++ gnunet/src/include/gnunet_ats_plugin.h      2013-10-08 16:34:07 UTC (rev 
29998)
@@ -0,0 +1,328 @@
+/*
+ This file is part of GNUnet
+ (C) 2009, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ 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.
+ */
+
+/**
+ * @file include/gnunet_solver_plugin.h
+ * @brief API for the ATS solvers.  This header
+ *        specifies the struct that is given to the plugin's entry
+ *        method and the other struct that must be returned.
+ *        Note that the destructors of ATS plugins will
+ *        be given the value returned by the constructor
+ *        and is expected to return a NULL pointer.
+ * @author Christian Grothoff
+ */
+#ifndef PLUGIN_ATS_H
+#define PLUGIN_ATS_H
+
+#include "gnunet_ats_service.h"
+#include "gnunet_statistics_service.h"
+
+struct ATS_Address;
+
+
+/*
+ * Solver API
+ * ----------
+ */
+
+
+/**
+ * Change the preference for a peer
+ *
+ * @param handle the solver handle
+ * @param client the client sending this request
+ * @param peer the peer id
+ * @param kind the preference kind to change
+ * @param score the new preference score
+ * @param pref_rel the normalized preference value for this kind over all 
clients
+ */
+typedef void
+(*GAS_solver_address_change_preference) (void *solver,
+    const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind 
kind,
+    double pref_rel);
+
+/**
+ * Give feedback about the current assignment
+ *
+ * @param handle the solver handle
+ * @param application the application sending this request
+ * @param peer the peer id
+ * @param scope the time interval for this feedback: [now - scope .. now]
+ * @param kind the preference kind for this feedback
+ * @param score the feedback score
+ */
+typedef void
+(*GAS_solver_address_feedback_preference) (void *solver, void *application,
+    const struct GNUNET_PeerIdentity *peer,
+    const struct GNUNET_TIME_Relative scope,
+    enum GNUNET_ATS_PreferenceKind kind, double score);
+
+/**
+ * Notify the solver about a bulk operation changing possibly a lot of values
+ * Solver will not resolve until all bulk operations are marked as done
+ *
+ * @param solver the solver
+ */
+typedef void
+(*GAS_solver_bulk_start) (void *solver);
+
+/**
+ * Mark a bulk operation as done
+ * Solver will resolve if values have changed
+ *
+ * @param solver the solver
+ */
+typedef void
+(*GAS_solver_bulk_stop) (void *solver);
+
+/**
+ * Add a single address within a network to the solver
+ *
+ * @param solver the solver Handle
+ * @param addresses the address hashmap containing all addresses
+ * @param address the address to add
+ * @param network network type of this address
+ */
+typedef void
+(*GAS_solver_address_add) (void *solver, struct ATS_Address *address,
+    uint32_t network);
+
+/**
+ * Delete an address or just the session from the solver
+ *
+ * @param solver the solver Handle
+ * @param addresses the address hashmap containing all addresses
+ * @param address the address to delete
+ * @param session_only remove address or just session
+ */
+typedef void
+(*GAS_solver_address_delete) (void *solver, struct ATS_Address *address,
+    int session_only);
+
+/**
+ * Transport properties for this address have changed
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param type the ATSI type in HBO
+ * @param abs_value the absolute value of the property
+ * @param rel_value the normalized value
+ */
+typedef void
+(*GAS_solver_address_property_changed) (void *solver,
+    struct ATS_Address *address, uint32_t type, uint32_t abs_value,
+    double rel_value);
+
+/**
+ * Transport session for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param cur_session the current session
+ * @param new_session the new session
+ */
+typedef void
+(*GAS_solver_address_session_changed) (void *solver,
+    struct ATS_Address *address, uint32_t cur_session, uint32_t new_session);
+
+/**
+ * Transport session for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param in_use usage state
+ */
+typedef void
+(*GAS_solver_address_inuse_changed) (void *solver, struct ATS_Address *address,
+    int in_use);
+
+/**
+ * Network scope for this address has changed
+ *
+ * NOTE: values in addresses are already updated
+ *
+ * @param solver solver handle
+ * @param address the address
+ * @param current_network the current network
+ * @param new_network the new network
+ */
+typedef void
+(*GAS_solver_address_network_changed) (void *solver,
+    struct ATS_Address *address, uint32_t current_network, uint32_t 
new_network);
+
+/**
+ * Get the prefered address for a peer from solver
+ *
+ * @param solver the solver to use
+ * @param addresses the address hashmap containing all addresses
+ * @param peer the peer
+ */
+typedef const struct ATS_Address *
+(*GAS_solver_get_preferred_address) (void *solver,
+    const struct GNUNET_PeerIdentity *peer);
+
+/**
+ * Stop getting the prefered address for a peer from solver
+ *
+ * @param solver the solver to use
+ * @param addresses the address hashmap containing all addresses
+ * @param peer the peer
+ */
+typedef void
+(*GAS_solver_stop_get_preferred_address) (void *solver,
+    const struct GNUNET_PeerIdentity *peer);
+
+
+/**
+ * Each plugin is required to return a pointer to a struct of this
+ * type as the return value from its entry point.
+ */
+struct GNUNET_ATS_SolverFunctions
+{
+
+  /**
+   * Closure for all of the callbacks.
+   */
+  void *cls;
+
+  /**
+   * Add an address to the solver
+   */
+  GAS_solver_address_add s_add;
+
+  GAS_solver_address_property_changed s_address_update_property;
+
+  GAS_solver_address_session_changed s_address_update_session;
+
+  GAS_solver_address_inuse_changed s_address_update_inuse;
+
+  GAS_solver_address_network_changed s_address_update_network;
+
+  /**
+   * Get address from solver
+   */
+  GAS_solver_get_preferred_address s_get;
+
+  /**
+   * Get address from solver
+   */
+  GAS_solver_stop_get_preferred_address s_get_stop;
+
+  /**
+   * Delete address in solver
+   */
+  GAS_solver_address_delete s_del;
+
+  /**
+   * Change relative preference for quality in solver
+   */
+  GAS_solver_address_change_preference s_pref;
+
+  /**
+   * Give feedback about the current assignment
+   */
+  GAS_solver_address_feedback_preference s_feedback;
+
+  /**
+   * Start a bulk operation
+   */
+  GAS_solver_bulk_start s_bulk_start;
+
+  /**
+   * Bulk operation done
+   */
+  GAS_solver_bulk_stop s_bulk_stop;
+
+};
+
+
+/**
+ * Callback to call from solver when bandwidth for address has changed
+ *
+ * @param address the with changed bandwidth assigned
+ */
+typedef void
+(*GAS_bandwidth_changed_cb) (void *cls, struct ATS_Address *address);
+
+/**
+ * Callback to call from solver to obtain application preference values for a
+ * peer
+ *
+ * @param cls the cls
+ * @param id the peer id
+ * @return carry of double values containing the preferences with
+ *      GNUNET_ATS_PreferenceCount elements
+ */
+typedef const double *
+(*GAS_get_preferences) (void *cls, const struct GNUNET_PeerIdentity *id);
+
+/**
+ * Callback to call from solver to obtain transport properties for an
+ * address
+ *
+ * @param cls the cls
+ * @param address the address
+ * @return carry of double values containing the preferences with
+ *      GNUNET_ATS_PreferenceCount elements
+ */
+typedef const double *
+(*GAS_get_properties) (void *cls, const struct ATS_Address *address);
+
+
+/**
+ * The transport service will pass a pointer to a struct
+ * of this type as the first and only argument to the
+ * entry point of each transport plugin.
+ */
+struct GNUNET_ATS_PluginEnvironment
+{
+  /**
+   * Closure for the various callbacks.
+   */
+  void *cls;
+
+  GAS_bandwidth_changed_cb bandwidth_changed_cb;
+  void *bw_changed_cb_cls;
+
+  GAS_get_preferences get_preferences_cb;
+  void *get_preference_cls;
+
+  GAS_get_properties get_property_cb;
+  void *get_property_cls;
+
+  struct GNUNET_ATS_SolverFunctions sf;
+
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+  struct GNUNET_STATISTICS_Handle *stats;
+  struct GNUNET_CONTAINER_MultiPeerMap *addresses;
+
+  /* Available networks */
+  int networks[GNUNET_ATS_NetworkTypeCount];
+  int network_count;
+
+  unsigned long long out_quota[GNUNET_ATS_NetworkTypeCount];
+  unsigned long long in_quota[GNUNET_ATS_NetworkTypeCount];
+};
+
+#endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]