server->net = net;
server->id = *id;
server->params = *params;
- server->current_budget = params->budget;
server->current_priority = params->prio;
server->pending_packets = 0;
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_server_data_t *server;
+
+ server = &the_servers_pool[net][id];
+
+ server->old_params = server->params;
+ server->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_server_data_t *server;
+ int budget_variation;
+ frescan_repl_op_t *repl;
+ struct list_head *pos;
+
+ server = &the_servers_pool[net][id];
+ budget_variation = server->params.budget - server->old_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;
+ }
+ }
+
+ return 0;
+}
+
/**
* frescan_servers_update() - update a sporadic server data
*
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;
}
int frescan_servers_destroy(frescan_network_t net, frescan_ss_t id)
{
int ret;
+ frescan_repl_op_t *repl;
+ frescan_packet_t *packet;
+ frescan_server_data_t *server;
- // TODO: free the replenishment operations and the packets for the
- // server.
+ server = &the_servers_pool[net][id];
- ret = timer_delete (the_servers_pool[net][id].repl_timer);
+ ret = timer_delete (server->repl_timer);
if (ret != 0) {
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(&the_networks[net].lock);
+ list_del(&server->servers_list);
ret = freelist_free(&the_servers_pool_freelist[net], id);
FRESCAN_RELEASE_LOCK(&the_networks[net].lock);
+
if (ret != 0) {
FRESCAN_ERROR("could not free server data from pool\n");
return ret;
}
/**
- * 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.
+ *
*/
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_server_data_t *server;
+
+ server = &the_servers_pool[net][id];
+
+ clock_gettime (CLOCK_MONOTONIC, &now);
+
+ *current_budget = 0;
+
+ list_for_each_entry(repl,
+ &server->replenishments.repl_list,
+ repl_list) {
+ if (smaller_timespec(now, repl->when)) break;
+ *current_budget = *current_budget + 1;
+ }
+
return 0;
}
} else {
repl_time = &packet->timestamp;
}
+
ret = frescan_replenishment_program(net, id, repl_time);
if (ret != 0) return -1;
}