]> rtime.felk.cvut.cz Git - frescor/fna.git/blobdiff - src_frescan/frescan_servers.c
restore the configuration flags and add a CONNECTED flag
[frescor/fna.git] / src_frescan / frescan_servers.c
index 52562b6209ab8233990f22ce2ccd81cb5213d6ae..8f8d3bfc100e0fc0049caeef23a43c2b69354d7d 100644 (file)
  *
  * @license
  *
- * See MaRTE OS license
+ * -----------------------------------------------------------------------
+ *  Copyright (C) 2006 - 2008 FRESCOR consortium partners:
+ *
+ *    Universidad de Cantabria,              SPAIN
+ *    University of York,                    UK
+ *    Scuola Superiore Sant'Anna,            ITALY
+ *    Kaiserslautern University,             GERMANY
+ *    Univ. Politécnica  Valencia,           SPAIN
+ *    Czech Technical University in Prague,  CZECH REPUBLIC
+ *    ENEA                                   SWEDEN
+ *    Thales Communication S.A.              FRANCE
+ *    Visual Tools S.A.                      SPAIN
+ *    Rapita Systems Ltd                     UK
+ *    Evidence                               ITALY
+ *
+ *    See http://www.frescor.org for a link to partners' websites
+ *
+ *           FRESCOR project (FP6/2005/IST/5-034026) is funded
+ *        in part by the European Union Sixth Framework Programme
+ *        The European Union is not liable of any use that may be
+ *        made of this code.
+ *
+ *  This file is part of FRESCAN
+ *
+ *  FRESCAN 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 2, or (at  your option)
+ *  any later version.
+ *
+ *  FRESCAN  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
+ *  distributed  with  FRESCAN;  see file COPYING.   If not,  write to the
+ *  Free Software  Foundation,  59 Temple Place  -  Suite 330,  Boston, MA
+ *  02111-1307, USA.
+ *
+ * As a special exception, including FRESCAN header files in a file,
+ * instantiating FRESCAN generics or templates, or linking other files
+ * with FRESCAN objects to produce an executable application, does not
+ * by itself cause the resulting executable application to be covered
+ * by the GNU General Public License. This exception does not
+ * however invalidate any other reasons why the executable file might be
+ * covered by the GNU Public License.
+ * -----------------------------------------------------------------------
  *
  */
 
 #include "frescan_servers.h"
 #include "frescan_servers_replenishments.h" // frescan_replenishments_xxx
 #include "frescan_debug.h"
+#include "frescan_packets.h"
 #include "frescan_data.h"
-#include <misc/linux_list.h>
-#include <misc/timespec_operations.h>
 #include <signal.h>
 #include <time.h>
+#include <misc/linux_list.h>
+#include "fosa_time_timespec.h" // smaller_timespec
 
 /**
  * frescan_servers_init() - initialize server structures
@@ -43,16 +90,16 @@ int frescan_servers_init(frescan_network_t net)
 
         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "initializing servers\n");
 
-        ret = freelist_init(&the_servers_pool_freelist[net], FRESCAN_MX_IDS);
+        ret = freelist_init(&frescan_data[net].ss_id_freelist, FRESCAN_MX_IDS);
         if (ret != 0) return ret;
 
         for (i=0; i<FRESCAN_MX_NETWORKS; i++) {
-                INIT_LIST_HEAD(&the_active_servers[net].servers_list);
+                INIT_LIST_HEAD(&frescan_data[net].ss_active_head.servers_list);
         }
 
         ret = frescan_replenishments_init(net);
         if (ret != 0) {
-                ERROR("could not initialize the replenishments\n");
+                FRESCAN_ERROR("could not initialize the replenishments\n");
                 return -1;
         }
 
@@ -74,28 +121,28 @@ int frescan_servers_create(frescan_network_t net,
 {
         int i, ret, pos;
         struct sigevent evp;
-        frescan_server_data_t *server;
+        frescan_ss_data_t *server;
         frescan_repl_op_t *repl;
 
-        FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
-        pos = freelist_alloc(&the_servers_pool_freelist[net]);
-        FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
+        FRESCAN_ACQUIRE_LOCK(&frescan_data[net].lock);
+        pos = freelist_alloc(&frescan_data[net].ss_id_freelist);
+        FRESCAN_RELEASE_LOCK(&frescan_data[net].lock);
 
         if (pos == -1) {
-                ERROR("could not allocate servers\n");
+                FRESCAN_ERROR("could not allocate servers\n");
                 return -1;
         }
 
         *id = (frescan_ss_t)pos;
 
-        server = &the_servers_pool[net][*id];
+        server = &frescan_data[net].ss_data[*id];
 
         server->net = net;
         server->id  = *id;
-        server->params = *params;
-        server->current_budget = params->values.budget;
+        server->committed_params = *params;
+        server->perceived_params = server->committed_params;
         server->current_priority = params->prio;
-        server->pending_packets = 0;
+        server->pending_packets  = 0;
 
         // the first act_time is set to the server creation time
         clock_gettime (CLOCK_MONOTONIC, &server->act_time);
@@ -105,7 +152,7 @@ int frescan_servers_create(frescan_network_t net,
 
         // allocate the replenishment capacity queue
         INIT_LIST_HEAD(&server->replenishments.repl_list);
-        for (i=0; i < params->values.budget; i++) {
+        for (i=0; i < params->budget; i++) {
                 repl = frescan_repl_op_alloc();
                 repl->when = server->act_time;
                 repl->amount = 1;
@@ -120,13 +167,85 @@ int frescan_servers_create(frescan_network_t net,
 
         ret = timer_create (CLOCK_MONOTONIC, &evp, &server->repl_timer);
         if (ret != 0) {
-                ERROR("could not create timer\n");
+                FRESCAN_ERROR("could not create timer\n");
                 return ret;
         }
 
         DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG,
               "server created, id:%u budget:%u prio:%u\n",
-              *id, server->params.values.budget, server->params.prio);
+              *id, server->committed_params.budget,
+              server->committed_params.prio);
+
+        return 0;
+}
+
+/**
+ * frescan_servers_set_perceived() - update a sporadic server perceived data
+ *
+ * @net: the network instance
+ * @params: the parameters for the server
+ * @id: the identificator for the server
+ *
+ */
+
+int frescan_servers_set_perceived(frescan_network_t net,
+                                  const frescan_server_params_t *params,
+                                  frescan_ss_t id)
+{
+        frescan_data[net].ss_data[id].perceived_params = *params;
+        return 0;
+}
+
+/**
+ * frescan_servers_commit_perceived() - commit sporadic server perceived data
+ *
+ * Add or remove repl operations according to the budget change
+ *
+ * @net: the network instance
+ * @id: the identificator for the server
+ *
+ */
+
+int frescan_servers_commit_perceived(frescan_network_t net,
+                                     frescan_ss_t id)
+{
+        int i, ret;
+        frescan_ss_data_t *server;
+        int budget_variation;
+        frescan_repl_op_t *repl = NULL;
+        struct list_head *pos;
+
+        server = &frescan_data[net].ss_data[id];
+        budget_variation = server->perceived_params.budget -
+                           server->committed_params.budget;
+
+        if (budget_variation > 0) {
+                // we have more budget: add repl ops to the tail
+                for (i=0; i < budget_variation; i++) {
+                        repl = frescan_repl_op_alloc();
+                        repl->when = server->act_time; // TODO: check when!
+                        repl->amount = 1;
+                        list_add_tail(&repl->repl_list,
+                                      &server->replenishments.repl_list);
+                }
+        } else {
+                // we have less budget: remove repl ops from the tail
+                for (i=0; i > budget_variation; i--) {
+                        list_for_each_prev(pos,
+                                           &server->replenishments.repl_list) {
+                                repl = list_entry(pos,
+                                                  frescan_repl_op_t,
+                                                  repl_list);
+                                break;
+                        }
+                        list_del(&repl->repl_list);
+
+                        ret = frescan_repl_op_free(repl);
+                        if (ret != 0) return ret;
+                }
+        }
+
+        server->committed_params = server->perceived_params;
 
         return 0;
 }
@@ -144,7 +263,14 @@ int frescan_servers_update(frescan_network_t net,
                            const frescan_server_params_t *params,
                            frescan_ss_t id)
 {
-        the_servers_pool[net][id].params = *params;
+        int ret;
+
+        ret = frescan_servers_set_perceived(net, params, id);
+        if (ret != 0) return ret;
+
+        ret = frescan_servers_commit_perceived(net, id);
+        if (ret != 0) return ret;
+
         return 0;
 }
 
@@ -159,23 +285,46 @@ int frescan_servers_update(frescan_network_t net,
 int frescan_servers_destroy(frescan_network_t net, frescan_ss_t id)
 {
         int ret;
+        frescan_repl_op_t *repl;
+        frescan_packet_t *packet;
+        frescan_ss_data_t *server;
 
-        // TODO: free the replenishment operations and the packets for the
-        // server.
+        server = &frescan_data[net].ss_data[id];
 
-        ret = timer_delete (the_servers_pool[net][id].repl_timer);
+        ret = timer_delete (server->repl_timer);
         if (ret != 0) {
-                ERROR("could not delete timer\n");
+                FRESCAN_ERROR("could not delete timer\n");
                 return ret;
         }
 
-        FRESCAN_ACQUIRE_LOCK(&the_networks[net].lock);
-        list_del(&the_servers_pool[net][id].servers_list);
+        // remove packets associated to the server
+        if (!list_empty(&server->packet_list.fifo_list)) {
+                FRESCAN_WARNING("destroying a server with packets enqueued\n");
+                list_for_each_entry(packet,
+                                    &server->packet_list.fifo_list,
+                                    fifo_list) {
+                        ret = frescan_packets_free(packet);
+                        if (ret != 0) return ret;
+                }
+                INIT_LIST_HEAD(&server->packet_list.fifo_list);
+        }
+
+        // remove the servers replenishment capacity queue
+        list_for_each_entry(repl,
+                            &server->replenishments.repl_list,
+                            repl_list) {
+                ret = frescan_repl_op_free(repl);
+                if (ret != 0) return ret;
+        }
+        INIT_LIST_HEAD(&server->replenishments.repl_list);
+
+        FRESCAN_ACQUIRE_LOCK(&frescan_data[net].lock);
+        list_del(&server->servers_list);
+        ret = freelist_free(&frescan_data[net].ss_id_freelist, id);
+        FRESCAN_RELEASE_LOCK(&frescan_data[net].lock);
 
-        ret = freelist_free(&the_servers_pool_freelist[net], id);
-        FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
         if (ret != 0) {
-                ERROR("could not free server data from pool\n");
+                FRESCAN_ERROR("could not free server data from pool\n");
                 return ret;
         }
 
@@ -195,24 +344,58 @@ int frescan_servers_get_data(frescan_network_t net,
                              frescan_server_params_t *params,
                              frescan_ss_t id)
 {
-        *params = the_servers_pool[net][id].params;
+        *params = frescan_data[net].ss_data[id].perceived_params;
         return 0;
 }
 
 /**
- * frescan_servers_get_current_budget() - get the current sporadic server budget
+ * frescan_servers_get_current_budget() - get the current ss budget
  *
  * @net: the network instance
  * @id: the identificator for the server
  * @current_budget: the current budget of the server
  *
+ * Traverse the capacity queue until we find a replenishment operation
+ * that was programmed for a time later than now. The number of iterations
+ * is the budget in the capacity queue.
+ *
+ * That budget must be modified if the perceived budget has not been
+ * committed yet.
+ *
  */
 
 int frescan_servers_get_current_budget(frescan_network_t net,
                                        frescan_ss_t id,
                                        frescan_budget_t *current_budget)
 {
-        *current_budget = the_servers_pool[net][id].current_budget;
+        struct timespec now;
+        frescan_repl_op_t *repl;
+        frescan_ss_data_t *server;
+        int count;
+
+        server = &frescan_data[net].ss_data[id];
+
+        // first we get the current real budget in the capacity queue
+        clock_gettime (CLOCK_MONOTONIC, &now);
+
+        count = 0;
+        list_for_each_entry(repl,
+                            &server->replenishments.repl_list,
+                            repl_list) {
+                if (smaller_timespec(now, repl->when)) break;
+                count = count + 1;
+        }
+
+        // if the perceived budget is less than the real budget
+        // we have to give a _perceived_ current budget
+        if (server->perceived_params.budget < server->committed_params.budget) {
+                count = server->perceived_params.budget -
+                        (server->committed_params.budget - count);
+                if (count < 0) count = 0;
+        }
+
+        *current_budget = (frescan_budget_t)count;
+
         return 0;
 }
 
@@ -235,16 +418,17 @@ int frescan_servers_get_highest_prio(frescan_network_t net,
                                      frescan_ss_t *id,
                                      frescan_prio_t *prio)
 {
-        frescan_server_data_t *server;
+        frescan_ss_data_t *server;
 
-        if (list_empty(&the_active_servers->servers_list)) {
+        if (list_empty(&frescan_data[net].ss_active_head.servers_list)) {
                 DEBUG(FRESCAN_SERVERS_ENABLE_DEBUG, "server list is empty\n");
                 *id = FRESCAN_MX_IDS;
                 return 0;
         }
 
         *prio = 0;
-        list_for_each_entry(server, &the_active_servers[net].servers_list,
+        list_for_each_entry(server,
+                            &frescan_data[net].ss_active_head.servers_list,
                             servers_list) {
                 if (server->current_priority >= *prio) {
                         *id = server->id;
@@ -279,16 +463,17 @@ int frescan_servers_frame_sent(frescan_network_t net,
 {
         int ret;
         struct timespec *repl_time;
-        frescan_server_data_t *server;
+        frescan_ss_data_t *server;
 
-        server = &the_servers_pool[net][id];
+        server = &frescan_data[net].ss_data[id];
 
         if (server->current_priority != FRESCAN_BACKGROUND_PRIO) {
-                if (smaller_timespec(&packet->timestamp, &server->act_time)) {
+                if (smaller_timespec(packet->timestamp, server->act_time)) {
                         repl_time = &server->act_time;
                 } else {
                         repl_time = &packet->timestamp;
                 }
+
                 ret = frescan_replenishment_program(net, id, repl_time);
                 if (ret != 0) return -1;
         }