From: Paul Bédaride Date: Mon, 30 Sep 2013 11:52:07 +0000 (+0200) Subject: Replace surf by surf++ and make it compile X-Git-Tag: v3_11_beta~297^2~14 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/commitdiff_plain/5faf49cdf3f8ad8751317b857a6d3134fe07eda3 Replace surf by surf++ and make it compile --- diff --git a/buildtools/Cmake/DefinePackages.cmake b/buildtools/Cmake/DefinePackages.cmake index afb7198747..2baafd1fe3 100644 --- a/buildtools/Cmake/DefinePackages.cmake +++ b/buildtools/Cmake/DefinePackages.cmake @@ -47,14 +47,16 @@ set(EXTRA_DIST src/surf/gtnets/gtnets_interface.h src/surf/gtnets/gtnets_simulator.h src/surf/gtnets/gtnets_topology.h - src/surf/solver.hpp - src/surf/solver.h + #src/surf/solver.hpp + #src/surf/solver.h src/surf/maxmin_private.h - src/surf/maxmin_private_.h + #src/surf/maxmin_private_.h src/surf/network_gtnets_private.h + #src/surf/network_gtnets.hpp src/surf/network_ns3_private.h src/surf/network_private.h src/surf/network.hpp + src/surf/network_constant.hpp src/surf/ns3/my-point-to-point-helper.h src/surf/ns3/ns3_interface.h src/surf/ns3/ns3_simulator.h @@ -293,38 +295,33 @@ set(SURF_SRC src/surf/cpu.cpp src/surf/cpu_ti.cpp src/surf/cpu_cas01.cpp - src/surf/cpu_cas01.c - src/surf/cpu_ti.c - src/surf/fair_bottleneck.cpp + src/surf/fair_bottleneck.c src/surf/instr_routing.c src/surf/instr_surf.c - src/surf/lagrange.cpp - src/surf/solver.cpp - src/surf/solver_c.cpp + src/surf/lagrange.c + src/surf/maxmin.c src/surf/network.cpp - src/surf/network.c - src/surf/network_constant.c + src/surf/network_smpi.cpp + src/surf/network_constant.cpp src/surf/platf_generator.c src/surf/random_mgr.c src/surf/sg_platf.c - src/surf/storage.c - src/surf/surf.c + src/surf/storage.cpp src/surf/surf.cpp - src/surf/surf_action.c - src/surf/surf_model.c - src/surf/surf_routing.c - src/surf/surf_routing_cluster.c - src/surf/surf_routing_dijkstra.c - src/surf/surf_routing_floyd.c - src/surf/surf_routing_full.c - src/surf/surf_routing_generic.c - src/surf/surf_routing_none.c - src/surf/surf_routing_vivaldi.c + src/surf/surf_interface.cpp + src/surf/surf_routing.cpp + src/surf/surf_routing_cluster.cpp + src/surf/surf_routing_dijkstra.cpp + src/surf/surf_routing_floyd.cpp + src/surf/surf_routing_full.cpp + src/surf/surf_routing_generic.cpp + src/surf/surf_routing_none.cpp + src/surf/surf_routing_vivaldi.cpp src/surf/surfxml_parse.c src/surf/surfxml_parseplatf.c src/surf/trace_mgr.c - src/surf/workstation.c - src/surf/workstation_ptask_L07.c + src/surf/workstation.cpp + src/surf/workstation_ptask_L07.cpp src/xbt/xbt_sg_stubs.c ) diff --git a/include/msg/datatypes.h b/include/msg/datatypes.h index 2661276ffb..4552f55823 100644 --- a/include/msg/datatypes.h +++ b/include/msg/datatypes.h @@ -27,7 +27,7 @@ SG_BEGIN_DECL() typedef struct s_smx_rvpoint *msg_mailbox_t; /* ******************************** Environment ************************************ */ -typedef struct s_as *msg_as_t; +typedef struct As *msg_as_t; /* ******************************** Host ************************************ */ diff --git a/include/simgrid/platf.h b/include/simgrid/platf.h index 6528b4f43c..2b1f15c3cf 100644 --- a/include/simgrid/platf.h +++ b/include/simgrid/platf.h @@ -11,9 +11,15 @@ #include typedef void *sg_routing_link_t; /* The actual type is model-dependent so use void* instead*/ -typedef struct s_routing_edge *sg_routing_edge_t; +typedef struct RoutingEdge *sg_routing_edge_t; +#ifdef __cplusplus +extern "C" { +#endif XBT_PUBLIC(sg_routing_edge_t) sg_routing_edge_by_name_or_null(const char *name); +#ifdef __cplusplus +} +#endif /** Defines whether a given resource is working or not */ typedef enum { @@ -46,6 +52,9 @@ typedef struct tmgr_trace *tmgr_trace_t; /**< Opaque structure defining an avail /** opaque structure defining a event generator for availability based on a probability distribution */ typedef struct probabilist_event_generator *probabilist_event_generator_t; +#ifdef __cplusplus +extern "C" { +#endif XBT_PUBLIC(tmgr_trace_t) tmgr_trace_new_from_file(const char *filename); XBT_PUBLIC(tmgr_trace_t) tmgr_trace_new_from_string(const char *id, const char *input, @@ -70,6 +79,10 @@ XBT_PUBLIC(probabilist_event_generator_t) tmgr_event_generator_new_exponential(c XBT_PUBLIC(probabilist_event_generator_t) tmgr_event_generator_new_weibull(const char* id, double scale, double shape); +#ifdef __cplusplus +} +#endif + typedef xbt_dictelm_t sg_host_t; static inline char* sg_host_name(sg_host_t host) { return host->key; @@ -308,6 +321,10 @@ typedef struct s_sg_platf_gpu_cbarg { /* ***************************************** */ +#ifdef __cplusplus +extern "C" { +#endif + XBT_PUBLIC(void) sg_platf_begin(void); // Start a new platform XBT_PUBLIC(void) sg_platf_end(void); // Finish the creation of the platform @@ -357,5 +374,8 @@ XBT_PUBLIC(void) sg_platf_ASroute_add_link (const char* link_id, sg_platf_route_ typedef void (*sg_platf_process_cb_t)(sg_platf_process_cbarg_t); XBT_PUBLIC(void) sg_platf_process_add_cb(sg_platf_process_cb_t fct); +#ifdef __cplusplus +} +#endif #endif /* SG_PLATF_H */ diff --git a/include/surf/surf_routing.h b/include/surf/surf_routing.h index 86379ba18c..7f3ee8813f 100644 --- a/include/surf/surf_routing.h +++ b/include/surf/surf_routing.h @@ -10,6 +10,10 @@ #include "xbt/lib.h" #include "simgrid/platf_interface.h" +#ifdef __cplusplus +extern "C" { +#endif + XBT_PUBLIC(xbt_lib_t) host_lib; XBT_PUBLIC(int) ROUTING_HOST_LEVEL; //Routing level XBT_PUBLIC(int) SURF_CPU_LEVEL; //Surf cpu level @@ -45,4 +49,8 @@ void routing_AS_end(sg_platf_AS_cbarg_t AS); void routing_cluster_add_backbone(void* bb); +#ifdef __cplusplus +} +#endif + #endif /* _SURF_SURF_H */ diff --git a/include/xbt/automaton.h b/include/xbt/automaton.h index 0cdf31f64c..0994be35f3 100644 --- a/include/xbt/automaton.h +++ b/include/xbt/automaton.h @@ -28,7 +28,7 @@ typedef struct xbt_automaton { typedef struct xbt_automaton* xbt_automaton_t; typedef struct xbt_automaton_exp_label{ - enum{or=0, and=1, not=2, predicat=3, one=4} type; + enum{AUT_OR=0, AUT_AND=1, AUT_NOT=2, AUT_PREDICAT=3, AUT_ONE=4} type; union{ struct{ struct xbt_automaton_exp_label* left_exp; diff --git a/include/xbt/module.h b/include/xbt/module.h index 3fc85f9f0d..4c1096947e 100644 --- a/include/xbt/module.h +++ b/include/xbt/module.h @@ -11,6 +11,13 @@ #include /* XBT_PUBLIC */ +#ifdef __cplusplus +extern "C" { +#endif XBT_PUBLIC(void) xbt_init(int *argc, char **argv); XBT_PUBLIC(void) xbt_exit(void); +#ifdef __cplusplus +} +#endif + #endif /* _XBT_MODULE_H */ diff --git a/src/include/instr/instr_interface.h b/src/include/instr/instr_interface.h index 52664c7d4a..0f5c429c94 100644 --- a/src/include/instr/instr_interface.h +++ b/src/include/instr/instr_interface.h @@ -1,5 +1,9 @@ #include "xbt.h" +#ifdef __cplusplus +extern "C" { +#endif + XBT_PUBLIC(int) TRACE_start (void); XBT_PUBLIC(int) TRACE_end (void); XBT_PUBLIC(void) TRACE_global_init(int *argc, char **argv); @@ -8,3 +12,7 @@ XBT_PUBLIC(void) TRACE_surf_resource_utilization_alloc(void); XBT_PUBLIC(void) TRACE_surf_resource_utilization_release(void); XBT_PUBLIC(void) TRACE_add_start_function(void (*func)(void)); XBT_PUBLIC(void) TRACE_add_end_function(void (*func)(void)); + +#ifdef __cplusplus +} +#endif diff --git a/src/include/simgrid/platf_interface.h b/src/include/simgrid/platf_interface.h index 63cff21115..b110d76da5 100644 --- a/src/include/simgrid/platf_interface.h +++ b/src/include/simgrid/platf_interface.h @@ -41,6 +41,10 @@ typedef void (*sg_platf_mstorage_cb_t)(sg_platf_mstorage_cbarg_t); /* ***************************************** */ /* TUTORIAL: New TAG */ +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*sg_platf_gpu_cb_t)(sg_platf_gpu_cbarg_t); XBT_PUBLIC(void) sg_platf_gpu_add_cb(sg_platf_gpu_cb_t); /* ***************************************** */ @@ -70,6 +74,9 @@ XBT_PUBLIC(void) sg_platf_mstorage_add_cb(sg_platf_mstorage_cb_t fct); XBT_PUBLIC(void) sg_platf_storage_type_add_cb(sg_platf_storage_type_cb_t fct); XBT_PUBLIC(void) sg_platf_mount_add_cb(sg_platf_mount_cb_t fct); +#ifdef __cplusplus +} +#endif /** \brief Pick the right models for CPU, net and workstation, and call their model_init_preparse * * Must be called within parsing/creating the environment (after the s, if any, and before or friends such as ) diff --git a/src/include/simgrid/sg_config.h b/src/include/simgrid/sg_config.h index 9952bfca13..7bc098f44a 100644 --- a/src/include/simgrid/sg_config.h +++ b/src/include/simgrid/sg_config.h @@ -3,6 +3,11 @@ /*******************************************/ /*** Config Globals **************************/ /*******************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + XBT_PUBLIC_DATA(xbt_cfg_t) _sg_cfg_set; XBT_PUBLIC(int) sg_cfg_get_int(const char* name); XBT_PUBLIC(double) sg_cfg_get_double(const char* name); @@ -13,3 +18,7 @@ XBT_PUBLIC(xbt_dynar_t) sg_cfg_get_dynar(const char* name); void sg_config_init(int *argc, char **argv); void sg_config_finalize(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/include/surf/datatypes.h b/src/include/surf/datatypes.h index 1cb5edf5b1..5ef74f07c9 100644 --- a/src/include/surf/datatypes.h +++ b/src/include/surf/datatypes.h @@ -13,7 +13,7 @@ * Generic data structure for a model. The workstations, * the CPUs and the network links are examples of models. */ -typedef struct surf_model *surf_model_t; +//FIXME: typedef struct surf_model *surf_model_t; /** \ingroup SURF_actions * \brief Action datatype @@ -21,10 +21,16 @@ typedef struct surf_model *surf_model_t; * An action is some working amount on a model. * It is represented as a cost, a priority, a duration and a state. */ -typedef struct surf_action *surf_action_t; -typedef struct surf_file *surf_file_t; +//FIXME:typedef struct surf_action *surf_action_t; +//FIXME:typedef struct surf_file *surf_file_t; typedef struct surf_stat *surf_stat_t; +typedef struct lmm_element *lmm_element_t; +typedef struct lmm_variable *lmm_variable_t; +typedef struct lmm_constraint *lmm_constraint_t; +typedef struct lmm_constraint_light *lmm_constraint_light_t; +typedef struct lmm_system *lmm_system_t; + typedef struct tmgr_history *tmgr_history_t; typedef struct tmgr_trace_event *tmgr_trace_event_t; diff --git a/src/include/surf/maxmin.h b/src/include/surf/maxmin.h new file mode 100644 index 0000000000..6049913659 --- /dev/null +++ b/src/include/surf/maxmin.h @@ -0,0 +1,137 @@ +/* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#ifndef _SURF_MAXMIN_H +#define _SURF_MAXMIN_H + +#include "portable.h" +#include "xbt/misc.h" +#include "surf/datatypes.h" +#include + +extern double sg_maxmin_precision; +#define MAXMIN_PRECISION sg_maxmin_precision +static XBT_INLINE void double_update(double *variable, double value) +{ + *variable -= value; + if (*variable < MAXMIN_PRECISION) + *variable = 0.0; +} + +static XBT_INLINE int double_positive(double value) +{ + return (value > MAXMIN_PRECISION); +} + +static XBT_INLINE int double_equals(double value1, double value2) +{ + return (fabs(value1 - value2) < MAXMIN_PRECISION); +} + +#ifdef __cplusplus +extern "C" { +#endif + +XBT_PUBLIC(lmm_system_t) lmm_system_new(int selective_update); +XBT_PUBLIC(void) lmm_system_free(lmm_system_t sys); +void lmm_variable_disable(lmm_system_t sys, lmm_variable_t var); + +XBT_PUBLIC(lmm_constraint_t) lmm_constraint_new(lmm_system_t sys, void *id, + double bound_value); +void lmm_constraint_shared(lmm_constraint_t cnst); +int lmm_constraint_is_shared(lmm_constraint_t cnst); + +void lmm_constraint_free(lmm_system_t sys, lmm_constraint_t cnst); + +XBT_PUBLIC(lmm_variable_t) lmm_variable_new(lmm_system_t sys, void *id, + double weight_value, + double bound, + int number_of_constraints); +XBT_PUBLIC(void) lmm_variable_free(lmm_system_t sys, lmm_variable_t var); +XBT_PUBLIC(double) lmm_variable_getvalue(lmm_variable_t var); +XBT_PUBLIC(double) lmm_variable_getbound(lmm_variable_t var); + +XBT_PUBLIC(void) lmm_expand(lmm_system_t sys, lmm_constraint_t cnst, + lmm_variable_t var, double value); +void lmm_expand_add(lmm_system_t sys, lmm_constraint_t cnst, + lmm_variable_t var, double value); +void lmm_elem_set_value(lmm_system_t sys, lmm_constraint_t cnst, + lmm_variable_t var, double value); + +lmm_constraint_t lmm_get_cnst_from_var(lmm_system_t sys, + lmm_variable_t var, int num); +double lmm_get_cnst_weight_from_var(lmm_system_t sys, lmm_variable_t var, + int num); +int lmm_get_number_of_cnst_from_var(lmm_system_t sys, lmm_variable_t var); +lmm_variable_t lmm_get_var_from_cnst(lmm_system_t sys, + lmm_constraint_t cnst, + lmm_element_t * elem); + +lmm_constraint_t lmm_get_first_active_constraint(lmm_system_t sys); +lmm_constraint_t lmm_get_next_active_constraint(lmm_system_t sys, + lmm_constraint_t cnst); +#ifdef HAVE_LATENCY_BOUND_TRACKING +XBT_PUBLIC(int) lmm_is_variable_limited_by_latency(lmm_variable_t var); +#endif + +void *lmm_constraint_id(lmm_constraint_t cnst); +void *lmm_variable_id(lmm_variable_t var); + +void lmm_update(lmm_system_t sys, lmm_constraint_t cnst, + lmm_variable_t var, double value); +void lmm_update_variable_bound(lmm_system_t sys, lmm_variable_t var, + double bound); + + +XBT_PUBLIC(void) lmm_update_variable_weight(lmm_system_t sys, + lmm_variable_t var, + double weight); +double lmm_get_variable_weight(lmm_variable_t var); + +XBT_PUBLIC(void) lmm_update_constraint_bound(lmm_system_t sys, + lmm_constraint_t cnst, + double bound); + +int lmm_constraint_used(lmm_system_t sys, lmm_constraint_t cnst); + + +XBT_PUBLIC(void) lmm_solve(lmm_system_t sys); + +XBT_PUBLIC(void) lagrange_solve(lmm_system_t sys); +XBT_PUBLIC(void) bottleneck_solve(lmm_system_t sys); + +/** + * Default functions associated to the chosen protocol. When + * using the lagrangian approach. + */ + +XBT_PUBLIC(void) lmm_set_default_protocol_function(double (*func_f) + (lmm_variable_t var, + double x), + double (*func_fp) + (lmm_variable_t var, + double x), + double (*func_fpi) + (lmm_variable_t var, + double x)); + +XBT_PUBLIC(double func_reno_f) (lmm_variable_t var, double x); +XBT_PUBLIC(double func_reno_fp) (lmm_variable_t var, double x); +XBT_PUBLIC(double func_reno_fpi) (lmm_variable_t var, double x); + +XBT_PUBLIC(double func_reno2_f) (lmm_variable_t var, double x); +XBT_PUBLIC(double func_reno2_fp) (lmm_variable_t var, double x); +XBT_PUBLIC(double func_reno2_fpi) (lmm_variable_t var, double x); + +XBT_PUBLIC(double func_vegas_f) (lmm_variable_t var, double x); +XBT_PUBLIC(double func_vegas_fp) (lmm_variable_t var, double x); +XBT_PUBLIC(double func_vegas_fpi) (lmm_variable_t var, double x); + +#ifdef __cplusplus +} +#endif + +#endif /* _SURF_MAXMIN_H */ diff --git a/src/include/surf/surf.h b/src/include/surf/surf.h index 6290d615f6..7d783cee00 100644 --- a/src/include/surf/surf.h +++ b/src/include/surf/surf.h @@ -16,7 +16,6 @@ #include "xbt/config.h" #include "surf/datatypes.h" #include "xbt/lib.h" -#include "surf/solver.h" #include "surf/surf_routing.h" #include "simgrid/platf_interface.h" @@ -36,7 +35,6 @@ extern int sg_gtnets_jitter_seed; #endif extern xbt_dynar_t surf_path; - typedef enum { SURF_NETWORK_ELEMENT_NULL = 0, /* NULL */ SURF_NETWORK_ELEMENT_HOST, /* host type */ @@ -44,6 +42,76 @@ typedef enum { SURF_NETWORK_ELEMENT_AS /* AS type */ } e_surf_network_element_type_t; +#ifdef __cplusplus +class Model; +class CpuModel; +class WorkstationModel; +class NetworkCm02Model; +class Resource; +class ResourceLmm; +class WorkstationCLM03; +class NetworkCm02Link; +class Cpu; +class Action; +class ActionLmm; +class StorageActionLmm; +class As; +class RoutingEdge; +class RoutingPlatf; +#else +typedef struct Model Model; +typedef struct CpuModel CpuModel; +typedef struct WorkstationModel WorkstationModel; +typedef struct NetworkCm02Model NetworkCm02Model; +typedef struct Resource Resource; +typedef struct ResourceLmm ResourceLmm; +typedef struct WorkstationCLM03 WorkstationCLM03; +typedef struct NetworkCm02Link NetworkCm02Link; +typedef struct Cpu Cpu; +typedef struct Action Action; +typedef struct ActionLmm ActionLmm; +typedef struct StorageActionLmm StorageActionLmm; +typedef struct As As; +typedef struct RoutingEdge RoutingEdge; +typedef struct RoutingPlatf RoutingPlatf; +#endif + +/** \ingroup SURF_models + * \brief Model datatype + * + * Generic data structure for a model. The workstations, + * the CPUs and the network links are examples of models. + */ +typedef Model *surf_model_t; +typedef CpuModel *surf_cpu_model_t; +typedef WorkstationModel *surf_workstation_model_t; +typedef NetworkCm02Model *surf_network_model_t; + +typedef Resource *surf_resource_t; +typedef ResourceLmm *surf_resource_lmm_t; +typedef WorkstationCLM03 *surf_workstation_CLM03_t; +typedef xbt_dictelm_t surf_workstation_t; +typedef NetworkCm02Link *surf_network_link_t; +typedef Cpu *surf_cpu_t; + +/** \ingroup SURF_actions + * \brief Action structure + * + * Never create s_surf_action_t by yourself ! The actions are created + * on the fly when you call execute or communicate on a model. + * + * \see e_surf_action_state_t + */ +typedef Action *surf_action_t; +typedef ActionLmm *surf_action_lmm_t; +typedef StorageActionLmm *surf_storage_action_lmm_t; + +typedef As *AS_t; +typedef RoutingEdge *routing_edge_t; +typedef RoutingPlatf *routing_platf_t; + +typedef struct surf_file *surf_file_t; + XBT_PUBLIC(e_surf_network_element_type_t) routing_get_network_element_type(const char* name); @@ -73,57 +141,7 @@ XBT_PUBLIC(int) find_model_description(s_surf_model_description_t * table, XBT_PUBLIC(void) model_help(const char *category, s_surf_model_description_t * table); -enum heap_action_type{ - LATENCY = 100, - MAX_DURATION, - NORMAL, - NOTSET -}; - -/** \ingroup SURF_actions - * \brief Action structure - * - * Never create s_surf_action_t by yourself ! The actions are created - * on the fly when you call execute or communicate on a model. - * - * \see e_surf_action_state_t - */ -typedef struct surf_action { - s_xbt_swag_hookup_t state_hookup; - xbt_swag_t state_set; - double cost; /**< cost */ - double priority; /**< priority (1.0 by default) */ - double max_duration; /**< max_duration (may fluctuate until - the task is completed) */ - double remains; /**< How much of that cost remains to - * be done in the currently running task */ -#ifdef HAVE_LATENCY_BOUND_TRACKING - int latency_limited; /**< Set to 1 if is limited by latency, 0 otherwise */ -#endif - double start; /**< start time */ - double finish; /**< finish time : this is modified during the run - * and fluctuates until the task is completed */ - void *data; /**< for your convenience */ - int refcount; - surf_model_t model_type; -#ifdef HAVE_TRACING - char *category; /**< tracing category for categorized resource utilization monitoring */ -#endif - surf_file_t file; /**< surf_file_t for storage model */ - xbt_dict_t ls_dict; -} s_surf_action_t; - -typedef struct surf_action_lmm { - s_surf_action_t generic_action; - lmm_variable_t variable; - int suspended; - s_xbt_swag_hookup_t action_list_hookup; - int index_heap; - double last_update; - double last_value; - enum heap_action_type hat; -} s_surf_action_lmm_t, *surf_action_lmm_t; /** \ingroup SURF_actions * \brief Action states @@ -132,6 +150,7 @@ typedef struct surf_action_lmm { * * \see surf_action_t, surf_action_state_t */ + typedef enum { SURF_ACTION_READY = 0, /**< Ready */ SURF_ACTION_RUNNING, /**< Running */ @@ -142,29 +161,10 @@ typedef enum { /**< Not in the system anymore. Why did you ask ? */ } e_surf_action_state_t; -/** \ingroup SURF_actions - * \brief Action state sets - * - * This structure contains some sets of actions. - * It provides a fast access to the actions in each state. - * - * \see surf_action_t, e_surf_action_state_t - */ -typedef struct surf_action_state { - xbt_swag_t ready_action_set; - /**< Actions in state SURF_ACTION_READY */ - xbt_swag_t running_action_set; - /**< Actions in state SURF_ACTION_RUNNING */ - xbt_swag_t failed_action_set; - /**< Actions in state SURF_ACTION_FAILED */ - xbt_swag_t done_action_set; - /**< Actions in state SURF_ACTION_DONE */ -} s_surf_action_state_t, *surf_action_state_t; - /***************************/ /* Generic model object */ /***************************/ -typedef struct s_routing_platf s_routing_platf_t, *routing_platf_t; +//FIXME:REMOVE typedef struct s_routing_platf s_routing_platf_t, *routing_platf_t; XBT_PUBLIC_DATA(routing_platf_t) routing_platf; /******************************************* @@ -219,7 +219,7 @@ typedef struct surf_network_model_extension_public { } s_surf_model_extension_network_t; /* Storage model */ - +// /** \ingroup SURF_models * \brief Storage model extension public * @@ -282,70 +282,14 @@ typedef struct surf_workstation_model_extension_public { } s_surf_model_extension_workstation_t; - - -/** \ingroup SURF_models - * \brief Model datatype - * - * Generic data structure for a model. The workstations, - * the CPUs and the network links are examples of models. - */ -typedef struct surf_model { - const char *name; /**< Name of this model */ - s_surf_action_state_t states; /**< Any living action on this model */ - - e_surf_action_state_t(*action_state_get) (surf_action_t action); - /**< Return the state of an action */ - void (*action_state_set) (surf_action_t action, - e_surf_action_state_t state); - /**< Change an action state*/ - - double (*action_get_start_time) (surf_action_t action); /**< Return the start time of an action */ - double (*action_get_finish_time) (surf_action_t action); /**< Return the finish time of an action */ - int (*action_unref) (surf_action_t action); /**< Specify that we don't use that action anymore. Returns true if the action was destroyed and false if someone still has references on it. */ - void (*action_cancel) (surf_action_t action); /**< Cancel a running action */ - void (*action_recycle) (surf_action_t action); /**< Recycle an action */ - void (*action_data_set) (surf_action_t action, void *data); /**< Set the user data of an action */ - void (*suspend) (surf_action_t action); /**< Suspend an action */ - void (*resume) (surf_action_t action); /**< Resume a suspended action */ - int (*is_suspended) (surf_action_t action); /**< Return whether an action is suspended */ - void (*set_max_duration) (surf_action_t action, double duration); /**< Set the max duration of an action*/ - void (*set_priority) (surf_action_t action, double priority); /**< Set the priority of an action */ -#ifdef HAVE_TRACING - void (*set_category) (surf_action_t action, const char *category); /**< Set the category of an action */ -#endif - double (*get_remains) (surf_action_t action); /**< Get the remains of an action */ -#ifdef HAVE_LATENCY_BOUND_TRACKING - int (*get_latency_limited) (surf_action_t action); /**< Return 1 if action is limited by latency, 0 otherwise */ -#endif - - void (*gap_remove) (surf_action_lmm_t action); - - surf_model_private_t model_private; - - union extension { - s_surf_model_extension_cpu_t cpu; - s_surf_model_extension_network_t network; - s_surf_model_extension_storage_t storage; - s_surf_model_extension_workstation_t workstation; - /*******************************************/ - /* TUTORIAL: New model */ - s_surf_model_extension_new_model_t new_model; - /*******************************************/ - } extension; -} s_surf_model_t; - -surf_model_t surf_model_init(void); -void surf_model_exit(surf_model_t model); - static inline void *surf_cpu_resource_priv(const void *host) { - return xbt_lib_get_level((void *)host, SURF_CPU_LEVEL); + return xbt_lib_get_level((xbt_dictelm_t)host, SURF_CPU_LEVEL); } static inline void *surf_workstation_resource_priv(const void *host){ - return xbt_lib_get_level((void *)host, SURF_WKS_LEVEL); + return (void*)xbt_lib_get_level((xbt_dictelm_t)host, SURF_WKS_LEVEL); } static inline void *surf_storage_resource_priv(const void *host){ - return xbt_lib_get_level((void *)host, SURF_STORAGE_LEVEL); + return (void*)xbt_lib_get_level((xbt_dictelm_t)host, SURF_STORAGE_LEVEL); } static inline void *surf_cpu_resource_by_name(const char *name) { @@ -358,28 +302,64 @@ static inline void *surf_storage_resource_by_name(const char *name){ return xbt_lib_get_elm_or_null(storage_lib, name); } -typedef struct surf_resource { - surf_model_t model; - char *name; - xbt_dict_t properties; -} s_surf_resource_t, *surf_resource_t; - -/** - * Resource which have a metric handled by a maxmin system - */ -typedef struct { - double scale; - double peak; - tmgr_trace_event_t event; -} s_surf_metric_t; - -typedef struct surf_resource_lmm { - s_surf_resource_t generic_resource; - lmm_constraint_t constraint; - e_surf_resource_state_t state_current; - tmgr_trace_event_t state_event; - s_surf_metric_t power; -} s_surf_resource_lmm_t, *surf_resource_lmm_t; +#ifdef __cplusplus +extern "C" { +#endif + +const char *surf_model_name(surf_model_t model); +xbt_swag_t surf_model_done_action_set(surf_model_t model); +xbt_swag_t surf_model_failed_action_set(surf_model_t model); +xbt_swag_t surf_model_ready_action_set(surf_model_t model); +xbt_swag_t surf_model_running_action_set(surf_model_t model); +surf_action_t surf_workstation_model_execute_parallel_task(surf_workstation_model_t model, + int workstation_nb, + void **workstation_list, + double *computation_amount, + double *communication_amount, + double rate); +surf_action_t surf_workstation_model_communicate(surf_workstation_model_t model, surf_workstation_CLM03_t src, surf_workstation_CLM03_t dst, double size, double rate); +xbt_dynar_t surf_workstation_model_get_route(surf_workstation_model_t model, surf_workstation_t src, surf_workstation_t dst); +surf_action_t surf_network_model_communicate(surf_network_model_t model, sg_routing_edge_t src, sg_routing_edge_t dst, double size, double rate); +const char *surf_resource_name(surf_resource_t resource); +xbt_dict_t surf_resource_get_properties(surf_resource_t resource); +e_surf_resource_state_t surf_resource_get_state(surf_resource_t resource); +double surf_workstation_get_speed(surf_workstation_t resource, double load); +double surf_workstation_get_available_speed(surf_workstation_t resource); +int surf_workstation_get_core(surf_workstation_t resource); +surf_action_t surf_workstation_execute(surf_workstation_t resource, double size); +surf_action_t surf_workstation_sleep(surf_workstation_t resource, double duration); +surf_action_t surf_workstation_communicate(surf_workstation_t workstation_src, surf_workstation_t workstation_dst, double size, double rate); +surf_action_t surf_workstation_open(surf_workstation_t workstation, const char* mount, const char* path); +surf_action_t surf_workstation_close(surf_workstation_t workstation, surf_file_t fd); +surf_action_t surf_cpu_execute(surf_cpu_t cpu, double size); +surf_action_t surf_cpu_sleep(surf_cpu_t cpu, double duration); +int surf_workstation_unlink(surf_workstation_t workstation, surf_file_t fd); +surf_action_t surf_workstation_ls(surf_workstation_t workstation, const char* mount, const char *path); +size_t surf_workstation_get_size(surf_workstation_t workstation, surf_file_t fd); +surf_action_t surf_workstation_read(surf_workstation_t resource, void *ptr, size_t size, surf_file_t fd); +surf_action_t surf_workstation_write(surf_workstation_t resource, const void *ptr, size_t size, surf_file_t fd); +int surf_network_link_is_shared(surf_network_link_t link); +double surf_network_link_get_bandwidth(surf_network_link_t link); +double surf_network_link_get_latency(surf_network_link_t link); +void *surf_action_get_data(surf_action_t action); +void surf_action_set_data(surf_action_t action, void *data); +void surf_action_unref(surf_action_t action); +double surf_action_get_start_time(surf_action_t action); +double surf_action_get_finish_time(surf_action_t action); +double surf_action_get_remains(surf_action_t action); +void surf_action_suspend(surf_action_t action); +void surf_action_resume(surf_action_t action); +void surf_action_cancel(surf_action_t action); +void surf_action_set_priority(surf_action_t action, double priority); +void surf_action_set_category(surf_action_t action, const char *category); +e_surf_action_state_t surf_action_get_state(surf_action_t action); +int surf_action_get_cost(surf_action_t action); +surf_file_t surf_storage_action_get_file(surf_storage_action_lmm_t action); +xbt_dict_t surf_storage_action_get_ls_dict(surf_storage_action_lmm_t action); + +#ifdef __cplusplus +} +#endif /**************************************/ /* Implementations of model object */ @@ -389,7 +369,7 @@ typedef struct surf_resource_lmm { /** \ingroup SURF_models * \brief The CPU model */ -XBT_PUBLIC_DATA(surf_model_t) surf_cpu_model; +XBT_PUBLIC_DATA(surf_cpu_model_t) surf_cpu_model; /** \ingroup SURF_models * \brief Initializes the CPU model with the model Cas01 @@ -434,7 +414,7 @@ XBT_PUBLIC_DATA(s_surf_model_description_t) surf_cpu_model_description[]; * model should be accessed because depending on the platform model, * the network model can be NULL. */ -XBT_PUBLIC_DATA(surf_model_t) surf_network_model; +XBT_PUBLIC_DATA(surf_network_model_t) surf_network_model; /** \ingroup SURF_models * \brief Same as network model 'LagrangeVelho', only with different correction factors. @@ -578,7 +558,7 @@ XBT_PUBLIC_DATA(s_surf_model_description_t) surf_storage_model_description[]; * because depending on the platform model, the network model and the CPU model * may not exist. */ -XBT_PUBLIC_DATA(surf_model_t) surf_workstation_model; +XBT_PUBLIC_DATA(surf_workstation_model_t) surf_workstation_model; /** \ingroup SURF_models * \brief Initializes the platform with a compound workstation model @@ -621,7 +601,9 @@ XBT_PUBLIC_DATA(s_surf_model_description_t) * TUTORIAL: New model */ XBT_PUBLIC(void) surf_new_model_init_default(void); + XBT_PUBLIC_DATA(s_surf_model_description_t) surf_new_model_description[]; + /*******************************************/ /** \ingroup SURF_models @@ -632,13 +614,20 @@ XBT_PUBLIC_DATA(xbt_dynar_t) model_list; /*******************************************/ /*** SURF Platform *************************/ /*******************************************/ -typedef struct s_as *AS_t; - +#ifdef __cplusplus +extern "C" { +#endif XBT_PUBLIC_DATA(AS_t) surf_AS_get_routing_root(void); XBT_PUBLIC_DATA(const char *) surf_AS_get_name(AS_t as); XBT_PUBLIC_DATA(xbt_dict_t) surf_AS_get_routing_sons(AS_t as); XBT_PUBLIC_DATA(const char *) surf_AS_get_model(AS_t as); XBT_PUBLIC_DATA(xbt_dynar_t) surf_AS_get_hosts(AS_t as); +XBT_PUBLIC_DATA(void) surf_AS_get_graph(AS_t as, xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges); +XBT_PUBLIC_DATA(AS_t) surf_platf_get_root(routing_platf_t platf); +XBT_PUBLIC_DATA(e_surf_network_element_type_t) surf_routing_edge_get_rc_type(sg_routing_edge_t edge); +#ifdef __cplusplus +} +#endif /*******************************************/ /*** SURF Globals **************************/ @@ -737,7 +726,7 @@ void instr_routing_define_callbacks (void); void instr_new_variable_type (const char *new_typename, const char *color); void instr_new_user_variable_type (const char *father_type, const char *new_typename, const char *color); void instr_new_user_state_type (const char *father_type, const char *new_typename); -void instr_new_value_for_user_state_type (const char *typename, const char *value, const char *color); +void instr_new_value_for_user_state_type (const char *_typename, const char *value, const char *color); int instr_platform_traced (void); xbt_graph_t instr_routing_platform_graph (void); void instr_routing_platform_graph_export_graphviz (xbt_graph_t g, const char *filename); diff --git a/src/include/surf/surf_resource.h b/src/include/surf/surf_resource.h index dc66869fdd..e9c78c0c9f 100644 --- a/src/include/surf/surf_resource.h +++ b/src/include/surf/surf_resource.h @@ -9,7 +9,7 @@ #ifndef SURF_RESOURCE_H #define SURF_RESOURCE_H -static XBT_INLINE +/*FIXME:DELETEstatic XBT_INLINE surf_resource_t surf_resource_new(size_t childsize, surf_model_t model, const char *name, xbt_dict_t props) @@ -37,6 +37,6 @@ static XBT_INLINE const char *surf_resource_name(const void *resource) static XBT_INLINE xbt_dict_t surf_resource_properties(const void *resource) { return ((surf_resource_t) resource)->properties; -} +}*/ #endif /* SURF_RESOURCE_H */ diff --git a/src/include/surf/trace_mgr.h b/src/include/surf/trace_mgr.h index 3394dec69d..37821371bd 100644 --- a/src/include/surf/trace_mgr.h +++ b/src/include/surf/trace_mgr.h @@ -9,7 +9,7 @@ #include "xbt/heap.h" #include "xbt/dynar.h" -#include "surf/solver.h" +#include "surf/maxmin.h" #include "surf/datatypes.h" #include "simgrid/platf_interface.h" diff --git a/src/instr/instr_interface.c b/src/instr/instr_interface.c index e18be1f617..aec098019f 100644 --- a/src/instr/instr_interface.c +++ b/src/instr/instr_interface.c @@ -8,7 +8,10 @@ #ifdef HAVE_TRACING #include "instr/instr_private.h" -#include "surf/network_private.h" +#include "surf/surf.h" +#include "surf/surf_private.h" + +//FIXME:#include "surf/network_private.h" typedef enum { INSTR_US_DECLARE, @@ -374,7 +377,7 @@ static void instr_user_srcdst_variable(double time, unsigned int i; void *link; xbt_dynar_foreach (route, i, link) { - char *link_name = ((link_CM02_t)link)->lmm_resource.generic_resource.name; + char *link_name = (char*)surf_resource_name(link); instr_user_variable (time, link_name, variable, father_type, value, what, NULL, user_link_variables); } } diff --git a/src/instr/instr_private.h b/src/instr/instr_private.h index 24f2af342d..d853fbaeb6 100644 --- a/src/instr/instr_private.h +++ b/src/instr/instr_private.h @@ -102,6 +102,10 @@ extern xbt_dict_t user_vm_variables; extern xbt_dict_t user_link_variables; extern double TRACE_last_timestamp_to_dump; +#ifdef __cplusplus +extern "C" { +#endif + /* instr_paje_header.c */ void TRACE_header(int basic); @@ -211,6 +215,10 @@ XBT_PUBLIC(val_t) PJ_value_get_or_new (const char *name, const char *color, typ XBT_PUBLIC(val_t) PJ_value_get (const char *name, const type_t father); void PJ_value_free (val_t value); +#ifdef __cplusplus +} +#endif + #endif /* HAVE_TRACING */ #ifdef HAVE_JEDULE diff --git a/src/msg/msg_private.h b/src/msg/msg_private.h index 4d8150077c..02af63d702 100644 --- a/src/msg/msg_private.h +++ b/src/msg/msg_private.h @@ -9,7 +9,6 @@ #include "msg/msg.h" #include "simgrid/simix.h" -#include "surf/solver.h" #include "surf/surf.h" #include "xbt/fifo.h" #include "xbt/dynar.h" diff --git a/src/simdag/private.h b/src/simdag/private.h index e0bb1e0e1f..e48de288e1 100644 --- a/src/simdag/private.h +++ b/src/simdag/private.h @@ -12,7 +12,6 @@ #include "xbt/fifo.h" #include "simdag/simdag.h" #include "simdag/datatypes.h" -#include "surf/solver.h" #include "surf/surf.h" #include "xbt/swag.h" #include "xbt/mallocator.h" diff --git a/src/simdag/sd_global.c b/src/simdag/sd_global.c index 896e758c06..e52086423b 100644 --- a/src/simdag/sd_global.c +++ b/src/simdag/sd_global.c @@ -286,11 +286,10 @@ xbt_swag_t SD_simulate_swag(double how_long) { /* let's see which tasks are done */ xbt_dynar_foreach(model_list, iter, model) { - while ((action = xbt_swag_extract(model->states.done_action_set))) { - task = action->data; - task->start_time = - surf_workstation_model-> - action_get_start_time(task->surf_action); + while ((action = xbt_swag_extract(surf_model_done_action_set(model)))) { + task = surf_action_get_data(action); + task->start_time = surf_action_get_start_time(task->surf_action); + task->finish_time = surf_get_clock(); XBT_VERB("Task '%s' done", SD_task_get_name(task)); XBT_DEBUG("Calling __SD_task_just_done"); @@ -354,15 +353,13 @@ xbt_swag_t SD_simulate_swag(double how_long) { } /* let's see which tasks have just failed */ - while ((action = xbt_swag_extract(model->states.failed_action_set))) { - task = action->data; - task->start_time = - surf_workstation_model-> - action_get_start_time(task->surf_action); + while ((action = xbt_swag_extract(surf_model_failed_action_set(model)))) { + task = surf_action_get_data(action); + task->start_time = surf_action_get_start_time(task->surf_action); task->finish_time = surf_get_clock(); XBT_VERB("Task '%s' failed", SD_task_get_name(task)); __SD_task_set_state(task, SD_FAILED); - surf_workstation_model->action_unref(action); + surf_action_unref(action); task->surf_action = NULL; xbt_swag_insert(task,sd_global->return_set); diff --git a/src/simdag/sd_link.c b/src/simdag/sd_link.c index da64d74cd9..65d15072c5 100644 --- a/src/simdag/sd_link.c +++ b/src/simdag/sd_link.c @@ -23,7 +23,7 @@ SD_link_t __SD_link_create(void *surf_link, void *data) link = xbt_new(s_SD_link_t, 1); link->surf_link = surf_link; link->data = data; /* user data */ - if (surf_workstation_model->extension.workstation.link_shared(surf_link)) + if (surf_network_link_is_shared(surf_link)) link->sharing_policy = SD_LINK_SHARED; else link->sharing_policy = SD_LINK_FATPIPE; @@ -118,8 +118,7 @@ const char *SD_link_get_name(SD_link_t link) */ double SD_link_get_current_bandwidth(SD_link_t link) { - return surf_workstation_model->extension.workstation. - get_link_bandwidth(link->surf_link); + return surf_network_link_get_bandwidth(link->surf_link); } /** @@ -130,8 +129,7 @@ double SD_link_get_current_bandwidth(SD_link_t link) */ double SD_link_get_current_latency(SD_link_t link) { - return surf_workstation_model->extension.workstation. - get_link_latency(link->surf_link); + return surf_network_link_get_latency(link->surf_link); } /** diff --git a/src/simdag/sd_task.c b/src/simdag/sd_task.c index af052fb289..c17bb71ca6 100644 --- a/src/simdag/sd_task.c +++ b/src/simdag/sd_task.c @@ -257,7 +257,7 @@ void SD_task_destroy(SD_task_t task) xbt_free(task->name); if (task->surf_action != NULL) - surf_workstation_model->action_unref(task->surf_action); + surf_action_unref(task->surf_action); xbt_free(task->workstation_list); xbt_free(task->communication_amount); @@ -358,13 +358,11 @@ void __SD_task_set_state(SD_task_t task, e_SD_task_state_t new_state) break; case SD_RUNNING: task->state_set = sd_global->running_task_set; - task->start_time = - surf_workstation_model->action_get_start_time(task->surf_action); + task->start_time = surf_action_get_start_time(task->surf_action); break; case SD_DONE: task->state_set = sd_global->done_task_set; - task->finish_time = - surf_workstation_model->action_get_finish_time(task->surf_action); + task->finish_time = surf_action_get_finish_time(task->surf_action); task->remains = 0; #ifdef HAVE_JEDULE jedule_log_sd_event(task); @@ -499,7 +497,7 @@ double SD_task_get_alpha(SD_task_t task) double SD_task_get_remaining_amount(SD_task_t task) { if (task->surf_action) - return surf_workstation_model->get_remains(task->surf_action); + return surf_action_get_remains(task->surf_action); else return task->remains; } @@ -1047,7 +1045,7 @@ void SD_task_unschedule(SD_task_t task) } if (__SD_task_is_running(task)) /* the task should become SD_FAILED */ - surf_workstation_model->action_cancel(task->surf_action); + surf_action_cancel(task->surf_action); else { if (task->unsatisfied_dependencies == 0) __SD_task_set_state(task, SD_SCHEDULABLE); @@ -1127,15 +1125,14 @@ void __SD_task_really_run(SD_task_t task) memcpy(communication_amount, task->communication_amount, sizeof(double) * workstation_nb * workstation_nb); - task->surf_action = - surf_workstation_model->extension. - workstation.execute_parallel_task(workstation_nb, - surf_workstations, - computation_amount, - communication_amount, - task->rate); + task->surf_action = surf_workstation_model_execute_parallel_task((surf_workstation_model_t)surf_workstation_model, + workstation_nb, + surf_workstations, + computation_amount, + communication_amount, + task->rate); - surf_workstation_model->action_data_set(task->surf_action, task); + surf_action_set_data(task->surf_action, task); XBT_DEBUG("surf_action = %p", task->surf_action); @@ -1224,7 +1221,7 @@ void __SD_task_just_done(SD_task_t task) candidates = xbt_new(SD_task_t, 8); __SD_task_set_state(task, SD_DONE); - surf_workstation_model->action_unref(task->surf_action); + surf_action_unref(task->surf_action); task->surf_action = NULL; XBT_DEBUG("Looking for candidates"); @@ -1382,8 +1379,7 @@ static void __SD_task_remove_dependencies(SD_task_t task) double SD_task_get_start_time(SD_task_t task) { if (task->surf_action) - return surf_workstation_model-> - action_get_start_time(task->surf_action); + return surf_action_get_start_time(task->surf_action); else return task->start_time; } @@ -1402,8 +1398,7 @@ double SD_task_get_start_time(SD_task_t task) double SD_task_get_finish_time(SD_task_t task) { if (task->surf_action) /* should never happen as actions are destroyed right after their completion */ - return surf_workstation_model-> - action_get_finish_time(task->surf_action); + return surf_action_get_finish_time(task->surf_action); else return task->finish_time; } diff --git a/src/simdag/sd_workstation.c b/src/simdag/sd_workstation.c index f961c7f12b..d73d59e93f 100644 --- a/src/simdag/sd_workstation.c +++ b/src/simdag/sd_workstation.c @@ -12,8 +12,6 @@ #include "surf/surf.h" #include "surf/surf_resource.h" - - XBT_LOG_NEW_DEFAULT_SUBCATEGORY(sd_workstation, sd, "Logging specific to SimDag (workstation)"); @@ -152,8 +150,7 @@ const char *SD_workstation_get_property_value(SD_workstation_t ws, */ xbt_dict_t SD_workstation_get_properties(SD_workstation_t workstation) { - return surf_workstation_model->extension. - workstation.get_properties(surf_workstation_resource_priv(workstation)); + return surf_resource_get_properties(surf_workstation_resource_priv(workstation)); } @@ -221,9 +218,9 @@ const SD_link_t *SD_route_get_list(SD_workstation_t src, surf_src = src; surf_dst = dst; - surf_route = - surf_workstation_model->extension.workstation.get_route(surf_src, - surf_dst); + + surf_route = surf_workstation_model_get_route((surf_workstation_model_t)surf_workstation_model, + surf_src, surf_dst); xbt_dynar_foreach(surf_route, cpt, surf_link) { link_name = surf_resource_name(surf_link); @@ -243,8 +240,8 @@ const SD_link_t *SD_route_get_list(SD_workstation_t src, */ int SD_route_get_size(SD_workstation_t src, SD_workstation_t dst) { - return xbt_dynar_length(surf_workstation_model->extension. - workstation.get_route(src, dst)); + return xbt_dynar_length(surf_workstation_model_get_route( + (surf_workstation_model_t)surf_workstation_model, src, dst)); } /** @@ -256,8 +253,7 @@ int SD_route_get_size(SD_workstation_t src, SD_workstation_t dst) */ double SD_workstation_get_power(SD_workstation_t workstation) { - return surf_workstation_model->extension.workstation. - get_speed(workstation, 1.0); + return surf_workstation_get_speed(workstation, 1.0); } /** @@ -269,8 +265,7 @@ double SD_workstation_get_power(SD_workstation_t workstation) */ double SD_workstation_get_available_power(SD_workstation_t workstation) { - return surf_workstation_model->extension. - workstation.get_available_speed(workstation); + return surf_workstation_get_available_speed(workstation); } /** diff --git a/src/simgrid/sg_config.c b/src/simgrid/sg_config.c index 0871374063..3022b610d4 100644 --- a/src/simgrid/sg_config.c +++ b/src/simgrid/sg_config.c @@ -13,9 +13,8 @@ #include "xbt/str.h" #include "xbt/lib.h" #include "xbt/sysdep.h" -#include "surf/solver.h" #include "surf/surf.h" -#include "surf/solver.h" +#include "surf/maxmin.h" #include "instr/instr_interface.h" #include "simgrid/simix.h" #include "simgrid/sg_config.h" diff --git a/src/simix/smx_global.c b/src/simix/smx_global.c index c578d5178e..1754afcff7 100644 --- a/src/simix/smx_global.c +++ b/src/simix/smx_global.c @@ -317,14 +317,15 @@ void SIMIX_run(void) ((void (*)(void*))timer->func)(timer->args); xbt_free(timer); } + /* Wake up all processes waiting for a Surf action to finish */ xbt_dynar_foreach(model_list, iter, model) { - set = model->states.failed_action_set; + set = surf_model_failed_action_set(model); while ((action = xbt_swag_extract(set))) - SIMIX_simcall_post((smx_action_t) action->data); - set = model->states.done_action_set; + SIMIX_simcall_post((smx_action_t) surf_action_get_data(action)); + set = surf_model_done_action_set(model); while ((action = xbt_swag_extract(set))) - SIMIX_simcall_post((smx_action_t) action->data); + SIMIX_simcall_post((smx_action_t) surf_action_get_data(action)); } /* Clean processes to destroy */ diff --git a/src/simix/smx_host.c b/src/simix/smx_host.c index 72da17a23c..bece28b362 100644 --- a/src/simix/smx_host.c +++ b/src/simix/smx_host.c @@ -135,7 +135,7 @@ xbt_dict_t SIMIX_pre_host_get_properties(smx_simcall_t simcall, smx_host_t host) xbt_dict_t SIMIX_host_get_properties(smx_host_t host){ xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); - return surf_workstation_model->extension.workstation.get_properties(host); + return surf_resource_get_properties(surf_workstation_resource_priv(host)); } double SIMIX_pre_host_get_speed(smx_simcall_t simcall, smx_host_t host){ @@ -143,9 +143,7 @@ double SIMIX_pre_host_get_speed(smx_simcall_t simcall, smx_host_t host){ } double SIMIX_host_get_speed(smx_host_t host){ xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); - - return surf_workstation_model->extension.workstation. - get_speed(host, 1.0); + return surf_workstation_get_speed(host, 1.0); } int SIMIX_pre_host_get_core(smx_simcall_t simcall, smx_host_t host){ @@ -154,8 +152,7 @@ int SIMIX_pre_host_get_core(smx_simcall_t simcall, smx_host_t host){ int SIMIX_host_get_core(smx_host_t host){ xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); - return surf_workstation_model->extension.workstation. - get_core(host); + return surf_workstation_get_core(host); } @@ -166,8 +163,7 @@ double SIMIX_pre_host_get_available_speed(smx_simcall_t simcall, smx_host_t host double SIMIX_host_get_available_speed(smx_host_t host){ xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); - return surf_workstation_model->extension.workstation. - get_available_speed(host); + return surf_workstation_get_available_speed(host); } int SIMIX_pre_host_get_state(smx_simcall_t simcall, smx_host_t host){ @@ -176,8 +172,7 @@ int SIMIX_pre_host_get_state(smx_simcall_t simcall, smx_host_t host){ int SIMIX_host_get_state(smx_host_t host){ xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)"); - return surf_workstation_model->extension.workstation. - get_state(host); + return surf_resource_get_state(surf_workstation_resource_priv(host)); } void* SIMIX_pre_host_self_get_data(smx_simcall_t simcall){ @@ -336,10 +331,9 @@ smx_action_t SIMIX_host_execute(const char *name, /* set surf's action */ if (!MC_is_active()) { action->execution.surf_exec = - surf_workstation_model->extension.workstation.execute(host, - computation_amount); - surf_workstation_model->action_data_set(action->execution.surf_exec, action); - surf_workstation_model->set_priority(action->execution.surf_exec, priority); + surf_workstation_execute(host, computation_amount); + surf_action_set_data(action->execution.surf_exec, action); + surf_action_set_priority(action->execution.surf_exec, priority); } XBT_DEBUG("Create execute action %p", action); @@ -381,11 +375,10 @@ smx_action_t SIMIX_host_parallel_execute(const char *name, /* set surf's action */ if (!MC_is_active()) { action->execution.surf_exec = - surf_workstation_model->extension.workstation. - execute_parallel_task(host_nb, workstation_list, computation_amount, - communication_amount, rate); + surf_workstation_model_execute_parallel_task((surf_workstation_model_t)surf_workstation_model, + host_nb, workstation_list, computation_amount, communication_amount, rate); - surf_workstation_model->action_data_set(action->execution.surf_exec, action); + surf_action_set_data(action->execution.surf_exec, action); } XBT_DEBUG("Create parallel execute action %p", action); @@ -399,7 +392,7 @@ void SIMIX_host_execution_destroy(smx_action_t action){ XBT_DEBUG("Destroy action %p", action); if (action->execution.surf_exec) { - surf_workstation_model->action_unref(action->execution.surf_exec); + surf_action_unref(action->execution.surf_exec); action->execution.surf_exec = NULL; } xbt_free(action->name); @@ -413,7 +406,7 @@ void SIMIX_host_execution_cancel(smx_action_t action){ XBT_DEBUG("Cancel action %p", action); if (action->execution.surf_exec) - surf_workstation_model->action_cancel(action->execution.surf_exec); + surf_action_cancel(action->execution.surf_exec); } double SIMIX_pre_host_execution_get_remains(smx_simcall_t simcall, smx_action_t action){ @@ -423,7 +416,7 @@ double SIMIX_host_execution_get_remains(smx_action_t action){ double result = 0.0; if (action->state == SIMIX_RUNNING) - result = surf_workstation_model->get_remains(action->execution.surf_exec); + result = surf_action_get_remains(action->execution.surf_exec); return result; } @@ -441,7 +434,7 @@ void SIMIX_pre_host_execution_set_priority(smx_simcall_t simcall, smx_action_t a } void SIMIX_host_execution_set_priority(smx_action_t action, double priority){ if(action->execution.surf_exec) - surf_workstation_model->set_priority(action->execution.surf_exec, priority); + surf_action_set_priority(action->execution.surf_exec, priority); } void SIMIX_pre_host_execution_wait(smx_simcall_t simcall, smx_action_t action){ @@ -467,13 +460,13 @@ void SIMIX_pre_host_execution_wait(smx_simcall_t simcall, smx_action_t action){ void SIMIX_host_execution_suspend(smx_action_t action) { if(action->execution.surf_exec) - surf_workstation_model->suspend(action->execution.surf_exec); + surf_action_suspend(action->execution.surf_exec); } void SIMIX_host_execution_resume(smx_action_t action) { if(action->execution.surf_exec) - surf_workstation_model->resume(action->execution.surf_exec); + surf_action_resume(action->execution.surf_exec); } void SIMIX_execution_finish(smx_action_t action) @@ -506,8 +499,8 @@ void SIMIX_execution_finish(smx_action_t action) (int)action->state); } /* check if the host is down */ - if (surf_workstation_model->extension. - workstation.get_state(simcall->issuer->smx_host) != SURF_RESOURCE_ON) { + + if (surf_resource_get_state((surf_resource_t)surf_workstation_resource_priv(simcall->issuer->smx_host)) != SURF_RESOURCE_ON) { simcall->issuer->context->iwannadie = 1; } @@ -524,11 +517,11 @@ void SIMIX_post_host_execute(smx_action_t action) { if (action->type == SIMIX_ACTION_EXECUTE && /* FIMXE: handle resource failure * for parallel tasks too */ - surf_workstation_model->extension.workstation.get_state(action->execution.host) == SURF_RESOURCE_OFF) { + surf_resource_get_state((surf_resource_t)surf_workstation_resource_priv(action->execution.host)) == SURF_RESOURCE_OFF) { /* If the host running the action failed, notice it so that the asking * process can be killed if it runs on that host itself */ action->state = SIMIX_FAILED; - } else if (surf_workstation_model->action_state_get(action->execution.surf_exec) == SURF_ACTION_FAILED) { + } else if (surf_action_get_state(action->execution.surf_exec) == SURF_ACTION_FAILED) { /* If the host running the action didn't fail, then the action was * canceled */ action->state = SIMIX_CANCELED; @@ -537,7 +530,7 @@ void SIMIX_post_host_execute(smx_action_t action) } if (action->execution.surf_exec) { - surf_workstation_model->action_unref(action->execution.surf_exec); + surf_action_unref(action->execution.surf_exec); action->execution.surf_exec = NULL; } @@ -557,9 +550,9 @@ void SIMIX_set_category(smx_action_t action, const char *category) { if (action->state != SIMIX_RUNNING) return; if (action->type == SIMIX_ACTION_EXECUTE){ - surf_workstation_model->set_category(action->execution.surf_exec, category); + surf_action_set_category(action->execution.surf_exec, category); }else if (action->type == SIMIX_ACTION_COMMUNICATE){ - surf_workstation_model->set_category(action->comm.surf_comm, category); + surf_action_set_category(action->comm.surf_comm, category); } } #endif diff --git a/src/simix/smx_host_private.h b/src/simix/smx_host_private.h index a47fe05661..8dfd9e448a 100644 --- a/src/simix/smx_host_private.h +++ b/src/simix/smx_host_private.h @@ -21,7 +21,9 @@ static inline smx_host_priv_t SIMIX_host_priv(smx_host_t host){ return (smx_host_priv_t) xbt_lib_get_level(host, SIMIX_HOST_LEVEL); } - +#ifdef __cplusplus +extern "C" { +#endif smx_host_t SIMIX_host_create(const char *name, void *workstation, void *data); void SIMIX_host_destroy(void *host); @@ -87,5 +89,9 @@ void SIMIX_pre_set_category(smx_simcall_t simcall, smx_action_t action, void SIMIX_set_category(smx_action_t action, const char *category); #endif +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/simix/smx_io.c b/src/simix/smx_io.c index 9f4f6dc876..9793490a17 100644 --- a/src/simix/smx_io.c +++ b/src/simix/smx_io.c @@ -31,8 +31,7 @@ smx_action_t SIMIX_file_read(smx_process_t process, void* ptr, size_t size, smx_host_t host = process->smx_host; /* check if the host is active */ - if (surf_workstation_model->extension. - workstation.get_state(host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) { THROWF(host_error, 0, "Host %s failed, you cannot call this function", sg_host_name(host)); } @@ -45,11 +44,9 @@ smx_action_t SIMIX_file_read(smx_process_t process, void* ptr, size_t size, #endif action->io.host = host; - action->io.surf_io = - surf_workstation_model->extension.workstation.read(host, ptr, size, - fd->surf_file); + action->io.surf_io = surf_workstation_read(host, ptr, size, fd->surf_file); - surf_workstation_model->action_data_set(action->io.surf_io, action); + surf_action_set_data(action->io.surf_io, action); XBT_DEBUG("Create io action %p", action); return action; @@ -71,8 +68,7 @@ smx_action_t SIMIX_file_write(smx_process_t process, const void* ptr, smx_host_t host = process->smx_host; /* check if the host is active */ - if (surf_workstation_model->extension. - workstation.get_state(host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) { THROWF(host_error, 0, "Host %s failed, you cannot call this function", sg_host_name(host)); } @@ -85,11 +81,9 @@ smx_action_t SIMIX_file_write(smx_process_t process, const void* ptr, #endif action->io.host = host; - action->io.surf_io = - surf_workstation_model->extension.workstation.write(host, ptr, size, - fd->surf_file); + action->io.surf_io = surf_workstation_write(host, ptr, size, fd->surf_file); - surf_workstation_model->action_data_set(action->io.surf_io, action); + surf_action_set_data(action->io.surf_io, action); XBT_DEBUG("Create io action %p", action); return action; @@ -111,8 +105,7 @@ smx_action_t SIMIX_file_open(smx_process_t process ,const char* mount, smx_host_t host = process->smx_host; /* check if the host is active */ - if (surf_workstation_model->extension. - workstation.get_state(host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) { THROWF(host_error, 0, "Host %s failed, you cannot call this function", sg_host_name(host)); } @@ -125,10 +118,9 @@ smx_action_t SIMIX_file_open(smx_process_t process ,const char* mount, #endif action->io.host = host; - action->io.surf_io = - surf_workstation_model->extension.workstation.open(host, mount, path); + action->io.surf_io = surf_workstation_open(host, mount, path); - surf_workstation_model->action_data_set(action->io.surf_io, action); + surf_action_set_data(action->io.surf_io, action); XBT_DEBUG("Create io action %p", action); return action; @@ -148,8 +140,7 @@ smx_action_t SIMIX_file_close(smx_process_t process, smx_file_t fd) smx_host_t host = process->smx_host; /* check if the host is active */ - if (surf_workstation_model->extension. - workstation.get_state(host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) { THROWF(host_error, 0, "Host %s failed, you cannot call this function", sg_host_name(host)); } @@ -162,9 +153,9 @@ smx_action_t SIMIX_file_close(smx_process_t process, smx_file_t fd) #endif action->io.host = host; - action->io.surf_io = surf_workstation_model->extension.workstation.close(host, fd->surf_file); + action->io.surf_io = surf_workstation_close(host, fd->surf_file); - surf_workstation_model->action_data_set(action->io.surf_io, action); + surf_action_set_data(action->io.surf_io, action); XBT_DEBUG("Create io action %p", action); return action; @@ -181,13 +172,12 @@ int SIMIX_file_unlink(smx_process_t process, smx_file_t fd) { smx_host_t host = process->smx_host; /* check if the host is active */ - if (surf_workstation_model->extension. - workstation.get_state(host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) { THROWF(host_error, 0, "Host %s failed, you cannot call this function", sg_host_name(host)); } - if (surf_workstation_model->extension.workstation.unlink(host, fd->surf_file)){ + if (surf_workstation_unlink(host, fd->surf_file)){ fd->surf_file = NULL; return 1; } else @@ -207,7 +197,7 @@ smx_action_t SIMIX_file_ls(smx_process_t process, const char* mount, const char smx_action_t action; smx_host_t host = process->smx_host; /* check if the host is active */ - if (surf_workstation_model->extension.workstation.get_state(host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) { THROWF(host_error, 0, "Host %s failed, you cannot call this function", sg_host_name(host)); } @@ -220,9 +210,9 @@ smx_action_t SIMIX_file_ls(smx_process_t process, const char* mount, const char #endif action->io.host = host; - action->io.surf_io = surf_workstation_model->extension.workstation.ls(host,mount,path); + action->io.surf_io = surf_workstation_ls(host,mount,path); - surf_workstation_model->action_data_set(action->io.surf_io, action); + surf_action_set_data(action->io.surf_io, action); XBT_DEBUG("Create io action %p", action); return action; } @@ -235,8 +225,7 @@ size_t SIMIX_pre_file_get_size(smx_simcall_t simcall, smx_file_t fd) size_t SIMIX_file_get_size(smx_process_t process, smx_file_t fd) { smx_host_t host = process->smx_host; - return surf_workstation_model->extension.workstation.get_size(host, - fd->surf_file); + return surf_workstation_get_size(host, fd->surf_file); } @@ -253,7 +242,7 @@ void SIMIX_post_io(smx_action_t action) switch (simcall->call) { case SIMCALL_FILE_OPEN:; smx_file_t tmp = xbt_new(s_smx_file_t,1); - tmp->surf_file = (action->io.surf_io)->file; + tmp->surf_file = surf_storage_action_get_file((surf_storage_action_lmm_t)action->io.surf_io); simcall_file_open__set__result(simcall, tmp); break; @@ -261,13 +250,12 @@ void SIMIX_post_io(smx_action_t action) xbt_free(simcall_file_close__get__fd(simcall)); simcall_file_close__set__result(simcall, 0); break; - case SIMCALL_FILE_WRITE: - simcall_file_write__set__result(simcall, (action->io.surf_io)->cost); + simcall_file_write__set__result(simcall, surf_action_get_cost(action->io.surf_io)); break; case SIMCALL_FILE_READ: - simcall_file_read__set__result(simcall, (action->io.surf_io)->cost); + simcall_file_read__set__result(simcall, surf_action_get_cost(action->io.surf_io)); break; case SIMCALL_FILE_LS: @@ -279,14 +267,14 @@ void SIMIX_post_io(smx_action_t action) // xbt_dict_set((action->io.surf_io)->ls_dict,key,dst,xbt_free); // } // } - simcall_file_ls__set__result(simcall, (action->io.surf_io)->ls_dict); + simcall_file_ls__set__result(simcall, surf_storage_action_get_ls_dict((surf_storage_action_lmm_t)action->io.surf_io)); break; default: break; } } - switch (surf_workstation_model->action_state_get(action->io.surf_io)) { + switch (surf_action_get_state(action->io.surf_io)) { case SURF_ACTION_FAILED: action->state = SIMIX_FAILED; @@ -308,7 +296,7 @@ void SIMIX_io_destroy(smx_action_t action) { XBT_DEBUG("Destroy action %p", action); if (action->io.surf_io) - action->io.surf_io->model_type->action_unref(action->io.surf_io); + surf_action_unref(action->io.surf_io); xbt_mallocator_release(simix_global->action_mallocator, action); } @@ -338,8 +326,7 @@ void SIMIX_io_finish(smx_action_t action) (int)action->state); } - if (surf_workstation_model->extension. - workstation.get_state(simcall->issuer->smx_host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(simcall->issuer->smx_host)) != SURF_RESOURCE_ON) { simcall->issuer->context->iwannadie = 1; } diff --git a/src/simix/smx_network.c b/src/simix/smx_network.c index 3be4eb5bec..53133ae297 100644 --- a/src/simix/smx_network.c +++ b/src/simix/smx_network.c @@ -340,17 +340,17 @@ void SIMIX_comm_destroy_internal_actions(smx_action_t action) #ifdef HAVE_LATENCY_BOUND_TRACKING action->latency_limited = SIMIX_comm_is_latency_bounded(action); #endif - action->comm.surf_comm->model_type->action_unref(action->comm.surf_comm); + surf_action_unref(action->comm.surf_comm); action->comm.surf_comm = NULL; } if (action->comm.src_timeout){ - action->comm.src_timeout->model_type->action_unref(action->comm.src_timeout); + surf_action_unref(action->comm.src_timeout); action->comm.src_timeout = NULL; } if (action->comm.dst_timeout){ - action->comm.dst_timeout->model_type->action_unref(action->comm.dst_timeout); + surf_action_unref(action->comm.dst_timeout); action->comm.dst_timeout = NULL; } } @@ -729,8 +729,8 @@ void SIMIX_pre_comm_wait(smx_simcall_t simcall, smx_action_t action, double time if (action->state != SIMIX_WAITING && action->state != SIMIX_RUNNING) { SIMIX_comm_finish(action); } else { /* if (timeout >= 0) { we need a surf sleep action even when there is no timeout, otherwise surf won't tell us when the host fails */ - sleep = surf_workstation_model->extension.workstation.sleep(simcall->issuer->smx_host, timeout); - surf_workstation_model->action_data_set(sleep, action); + sleep = surf_workstation_sleep(surf_workstation_resource_priv(simcall->issuer->smx_host), timeout); + surf_action_set_data(sleep, action); if (simcall->issuer == action->comm.src_proc) action->comm.src_timeout = sleep; @@ -846,15 +846,14 @@ XBT_INLINE void SIMIX_comm_start(smx_action_t action) XBT_DEBUG("Starting communication %p from '%s' to '%s'", action, SIMIX_host_get_name(sender), SIMIX_host_get_name(receiver)); - action->comm.surf_comm = surf_workstation_model->extension.workstation. - communicate(sender, receiver, action->comm.task_size, action->comm.rate); + action->comm.surf_comm = surf_workstation_communicate(sender, receiver, action->comm.task_size, action->comm.rate); - surf_workstation_model->action_data_set(action->comm.surf_comm, action); + surf_action_set_data(action->comm.surf_comm, action); action->state = SIMIX_RUNNING; /* If a link is failed, detect it immediately */ - if (surf_workstation_model->action_state_get(action->comm.surf_comm) == SURF_ACTION_FAILED) { + if (surf_action_get_state(action->comm.surf_comm) == SURF_ACTION_FAILED) { XBT_DEBUG("Communication from '%s' to '%s' failed to start because of a link failure", SIMIX_host_get_name(sender), SIMIX_host_get_name(receiver)); action->state = SIMIX_LINK_FAILURE; @@ -874,7 +873,7 @@ XBT_INLINE void SIMIX_comm_start(smx_action_t action) XBT_DEBUG("The communication is suspended on startup because dst (%s:%s) were suspended since it initiated the communication", SIMIX_host_get_name(action->comm.dst_proc->smx_host), action->comm.dst_proc->name); - surf_workstation_model->suspend(action->comm.surf_comm); + surf_action_suspend(action->comm.surf_comm); } } @@ -980,8 +979,7 @@ void SIMIX_comm_finish(smx_action_t action) } } - if (surf_workstation_model->extension. - workstation.get_state(simcall->issuer->smx_host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(simcall->issuer->smx_host)) != SURF_RESOURCE_ON) { simcall->issuer->context->iwannadie = 1; } @@ -1013,19 +1011,19 @@ void SIMIX_post_comm(smx_action_t action) { /* Update action state */ if (action->comm.src_timeout && - surf_workstation_model->action_state_get(action->comm.src_timeout) == SURF_ACTION_DONE) + surf_action_get_state(action->comm.src_timeout) == SURF_ACTION_DONE) action->state = SIMIX_SRC_TIMEOUT; else if (action->comm.dst_timeout && - surf_workstation_model->action_state_get(action->comm.dst_timeout) == SURF_ACTION_DONE) + surf_action_get_state(action->comm.dst_timeout) == SURF_ACTION_DONE) action->state = SIMIX_DST_TIMEOUT; else if (action->comm.src_timeout && - surf_workstation_model->action_state_get(action->comm.src_timeout) == SURF_ACTION_FAILED) + surf_action_get_state(action->comm.src_timeout) == SURF_ACTION_FAILED) action->state = SIMIX_SRC_HOST_FAILURE; else if (action->comm.dst_timeout && - surf_workstation_model->action_state_get(action->comm.dst_timeout) == SURF_ACTION_FAILED) + surf_action_get_state(action->comm.dst_timeout) == SURF_ACTION_FAILED) action->state = SIMIX_DST_HOST_FAILURE; else if (action->comm.surf_comm && - surf_workstation_model->action_state_get(action->comm.surf_comm) == SURF_ACTION_FAILED) { + surf_action_get_state(action->comm.surf_comm) == SURF_ACTION_FAILED) { XBT_DEBUG("Puta madre. Surf says that the link broke"); action->state = SIMIX_LINK_FAILURE; } else @@ -1066,7 +1064,7 @@ void SIMIX_comm_cancel(smx_action_t action) else if (!MC_is_active() /* when running the MC there are no surf actions */ && (action->state == SIMIX_READY || action->state == SIMIX_RUNNING)) { - surf_workstation_model->action_cancel(action->comm.surf_comm); + surf_action_cancel(action->comm.surf_comm); } } @@ -1074,7 +1072,7 @@ void SIMIX_comm_suspend(smx_action_t action) { /*FIXME: shall we suspend also the timeout actions? */ if (action->comm.surf_comm) - surf_workstation_model->suspend(action->comm.surf_comm); + surf_action_suspend(action->comm.surf_comm); /* in the other case, the action will be suspended on creation, in SIMIX_comm_start() */ } @@ -1082,7 +1080,7 @@ void SIMIX_comm_resume(smx_action_t action) { /*FIXME: check what happen with the timeouts */ if (action->comm.surf_comm) - surf_workstation_model->resume(action->comm.surf_comm); + surf_action_resume(action->comm.surf_comm); /* in the other case, the action were not really suspended yet, see SIMIX_comm_suspend() and SIMIX_comm_start() */ } @@ -1107,7 +1105,7 @@ double SIMIX_comm_get_remains(smx_action_t action) switch (action->state) { case SIMIX_RUNNING: - remains = surf_workstation_model->get_remains(action->comm.surf_comm); + remains = surf_action_get_remains(action->comm.surf_comm); break; case SIMIX_WAITING: diff --git a/src/simix/smx_new_api.c b/src/simix/smx_new_api.c index acafb0e3a9..f9a1146299 100644 --- a/src/simix/smx_new_api.c +++ b/src/simix/smx_new_api.c @@ -43,7 +43,7 @@ void SIMIX_post_new_api(smx_action_t action) } } - switch (surf_workstation_model->action_state_get(action->new_api.surf_new_api)) { + switch (surf_action_get_state(action->new_api.surf_new_api)) { case SURF_ACTION_FAILED: action->state = SIMIX_FAILED; @@ -67,8 +67,7 @@ smx_action_t SIMIX_new_api_fct(smx_process_t process, const char* param1, double smx_host_t host = process->smx_host; /* check if the host is active */ - if (surf_workstation_model->extension. - workstation.get_state(host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) { THROWF(host_error, 0, "Host %s failed, you cannot call this function", sg_host_name(host)); } @@ -81,9 +80,9 @@ smx_action_t SIMIX_new_api_fct(smx_process_t process, const char* param1, double #endif // Called the function from the new model - action->new_api.surf_new_api = surf_workstation_model->extension.new_model.fct(); + //FIXME:CHECK WHAT TO DO action->new_api.surf_new_api = surf_workstation_model->extension.new_model.fct(); - surf_workstation_model->action_data_set(action->new_api.surf_new_api, action); + surf_action_set_data(action->new_api.surf_new_api, action); XBT_DEBUG("Create NEW MODEL action %p", action); return action; @@ -93,7 +92,7 @@ void SIMIX_new_api_destroy(smx_action_t action) { XBT_DEBUG("Destroy action %p", action); if (action->new_api.surf_new_api) - action->new_api.surf_new_api->model_type->action_unref(action->new_api.surf_new_api); + surf_action_unref(action->new_api.surf_new_api); xbt_mallocator_release(simix_global->action_mallocator, action); } @@ -123,8 +122,7 @@ void SIMIX_new_api_finish(smx_action_t action) (int)action->state); } - if (surf_workstation_model->extension. - workstation.get_state(simcall->issuer->smx_host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(simcall->issuer->smx_host)) != SURF_RESOURCE_ON) { simcall->issuer->context->iwannadie = 1; } diff --git a/src/simix/smx_private.h b/src/simix/smx_private.h index f15d3c123b..1130ff9329 100644 --- a/src/simix/smx_private.h +++ b/src/simix/smx_private.h @@ -8,7 +8,6 @@ #define _SIMIX_PRIVATE_H #include "simgrid/simix.h" -#include "surf/solver.h" #include "surf/surf.h" #include "xbt/fifo.h" #include "xbt/swag.h" diff --git a/src/simix/smx_process.c b/src/simix/smx_process.c index 4899f9174d..da07fbaf2a 100644 --- a/src/simix/smx_process.c +++ b/src/simix/smx_process.c @@ -691,8 +691,7 @@ smx_action_t SIMIX_process_sleep(smx_process_t process, double duration) smx_host_t host = process->smx_host; /* check if the host is active */ - if (surf_workstation_model->extension. - workstation.get_state(host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(host)) != SURF_RESOURCE_ON) { THROWF(host_error, 0, "Host %s failed, you cannot call this function", sg_host_name(host)); } @@ -706,9 +705,9 @@ smx_action_t SIMIX_process_sleep(smx_process_t process, double duration) action->sleep.host = host; action->sleep.surf_sleep = - surf_workstation_model->extension.workstation.sleep(host, duration); + surf_workstation_sleep(host, duration); - surf_workstation_model->action_data_set(action->sleep.surf_sleep, action); + surf_action_set_data(action->sleep.surf_sleep, action); XBT_DEBUG("Create sleep action %p", action); return action; @@ -721,7 +720,7 @@ void SIMIX_post_process_sleep(smx_action_t action) while ((simcall = xbt_fifo_shift(action->simcalls))) { - switch(surf_workstation_model->action_state_get(action->sleep.surf_sleep)){ + switch(surf_action_get_state(action->sleep.surf_sleep)){ case SURF_ACTION_FAILED: simcall->issuer->context->iwannadie = 1; //SMX_EXCEPTION(simcall->issuer, host_error, 0, "Host failed"); @@ -736,8 +735,7 @@ void SIMIX_post_process_sleep(smx_action_t action) THROW_IMPOSSIBLE; break; } - if (surf_workstation_model->extension. - workstation.get_state(simcall->issuer->smx_host) != SURF_RESOURCE_ON) { + if (surf_resource_get_state(surf_workstation_resource_priv(simcall->issuer->smx_host)) != SURF_RESOURCE_ON) { simcall->issuer->context->iwannadie = 1; } simcall_process_sleep__set__result(simcall, state); @@ -752,18 +750,18 @@ void SIMIX_process_sleep_destroy(smx_action_t action) { XBT_DEBUG("Destroy action %p", action); if (action->sleep.surf_sleep) - action->sleep.surf_sleep->model_type->action_unref(action->sleep.surf_sleep); + surf_action_unref(action->sleep.surf_sleep); xbt_mallocator_release(simix_global->action_mallocator, action); } void SIMIX_process_sleep_suspend(smx_action_t action) { - surf_workstation_model->suspend(action->sleep.surf_sleep); + surf_action_suspend(action->sleep.surf_sleep); } void SIMIX_process_sleep_resume(smx_action_t action) { - surf_workstation_model->resume(action->sleep.surf_sleep); + surf_action_resume(action->sleep.surf_sleep); } /** diff --git a/src/simix/smx_smurf_private.h b/src/simix/smx_smurf_private.h index 34a0cd48a0..c5ed37165a 100644 --- a/src/simix/smx_smurf_private.h +++ b/src/simix/smx_smurf_private.h @@ -161,10 +161,10 @@ (name, type, __VA_ARGS__) #define SIMCALL_FUNC_SIMCALL(res) SIMCALL_FUNC_SIMCALL_ res -#define SIMCALL_WITH_FUNC_RETURN(name, type, field, cast) return self->simcall.result.field; +#define SIMCALL_WITH_FUNC_RETURN(name, type, field, ...) return self->simcall.result.field; #define SIMCALL_WITHOUT_FUNC_RETURN(name, type, field) #define SIMCALL_FUNC_RETURN_(name, type, ...)\ - MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_FUNC_RETURN, SIMCALL_WITHOUT_FUNC_RETURN, SIMCALL_WITHOUT_FUNC_RETURN)\ + MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_FUNC_RETURN, SIMCALL_WITH_FUNC_RETURN, SIMCALL_WITHOUT_FUNC_RETURN)\ (name, type, __VA_ARGS__) #define SIMCALL_FUNC_RETURN(res) SIMCALL_FUNC_RETURN_ res diff --git a/src/simix/smx_synchro.c b/src/simix/smx_synchro.c index aee4eebd65..27b372600c 100644 --- a/src/simix/smx_synchro.c +++ b/src/simix/smx_synchro.c @@ -28,9 +28,9 @@ static smx_action_t SIMIX_synchro_wait(smx_host_t smx_host, double timeout) action->type = SIMIX_ACTION_SYNCHRO; action->name = xbt_strdup("synchro"); action->synchro.sleep = - surf_workstation_model->extension.workstation.sleep(smx_host, timeout); + surf_workstation_sleep(smx_host, timeout); - surf_workstation_model->action_data_set(action->synchro.sleep, action); + surf_action_set_data(action->synchro.sleep, action); XBT_OUT(); return action; } @@ -70,7 +70,7 @@ void SIMIX_synchro_destroy(smx_action_t action) { XBT_IN("(%p)",action); XBT_DEBUG("Destroying synchro %p", action); - action->synchro.sleep->model_type->action_unref(action->synchro.sleep); + surf_action_unref(action->synchro.sleep); xbt_free(action->name); xbt_mallocator_release(simix_global->action_mallocator, action); XBT_OUT(); @@ -79,9 +79,9 @@ void SIMIX_synchro_destroy(smx_action_t action) void SIMIX_post_synchro(smx_action_t action) { XBT_IN("(%p)",action); - if (surf_workstation_model->action_state_get(action->synchro.sleep) == SURF_ACTION_FAILED) + if (surf_action_get_state(action->synchro.sleep) == SURF_ACTION_FAILED) action->state = SIMIX_FAILED; - else if(surf_workstation_model->action_state_get(action->synchro.sleep) == SURF_ACTION_DONE) + else if(surf_action_get_state(action->synchro.sleep) == SURF_ACTION_DONE) action->state = SIMIX_SRC_TIMEOUT; SIMIX_synchro_finish(action); diff --git a/src/surf/cpu.cpp b/src/surf/cpu.cpp index a1ac6ea6cb..5d870ef1c5 100644 --- a/src/surf/cpu.cpp +++ b/src/surf/cpu.cpp @@ -1,17 +1,11 @@ #include "cpu.hpp" -//TODO: resolve dependencies -static int TRACE_is_enabled(void) {return 0;} -static void TRACE_surf_host_set_utilization(const char *resource, - const char *category, - double value, - double now, - double delta){} -static double TRACE_last_timestamp_to_dump = 0; - -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surfpp_cpu, surfpp, +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu, surf, "Logging specific to the SURF cpu module"); +} +CpuModelPtr surf_cpu_model; /********* * Model * diff --git a/src/surf/cpu.hpp b/src/surf/cpu.hpp index c7779e2db6..c73473877b 100644 --- a/src/surf/cpu.hpp +++ b/src/surf/cpu.hpp @@ -41,14 +41,12 @@ class Cpu : virtual public Resource { public: Cpu(){}; Cpu(CpuModelPtr model, const char* name, xbt_dict_t properties) : Resource(model, name, properties) {}; - CpuActionPtr execute(double size); - CpuActionPtr sleep(double duration); - e_surf_resource_state_t getState(); + virtual CpuActionPtr execute(double size)=0; + virtual CpuActionPtr sleep(double duration)=0; int getCore(); double getSpeed(double load); double getAvailableSpeed(); void addTraces(void); - double m_powerPeak; /*< CPU power peak */ double m_powerScale; /*< Percentage of CPU disponible */ protected: diff --git a/src/surf/cpu_cas01.c b/src/surf/cpu_cas01.c index 53b1e30b64..f704612a5c 100644 --- a/src/surf/cpu_cas01.c +++ b/src/surf/cpu_cas01.c @@ -409,7 +409,7 @@ static void surf_cpu_model_init_internal() surf_action_lmm_update_index_heap); surf_cpu_model->model_private->modified_set = xbt_swag_new(xbt_swag_offset(comp, generic_lmm_action.action_list_hookup)); - //TOREPAIR: cpu_model->model_private->maxmin_system->m_keepTrack = cpu_model->model_private->modified_set; + surf_cpu_model->model_private->maxmin_system->keep_track = surf_cpu_model->model_private->modified_set; } } diff --git a/src/surf/cpu_cas01.cpp b/src/surf/cpu_cas01.cpp index 6eb404c545..68fba770c0 100644 --- a/src/surf/cpu_cas01.cpp +++ b/src/surf/cpu_cas01.cpp @@ -10,14 +10,10 @@ #include "maxmin_private.h" #include "simgrid/sg_config.h" -//TODO: resolve dependencies -static void TRACE_surf_host_set_power(double date, const char *resource, double power) {} - - -static ModelPtr surf_cpu_model = NULL; - -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surfpp_cpu_cas, surfpp, +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu_cas, surf, "Logging specific to the SURF CPU IMPROVED module"); +} static xbt_swag_t cpu_running_action_set_that_does_not_need_being_checked = NULL; @@ -141,7 +137,7 @@ CpuCas01LmmPtr CpuCas01Model::createResource(const char *name, double power_peak double CpuCas01Model::shareResourcesFull(double now) { CpuCas01ActionLmm action; - Model::shareResourcesFull(p_runningActionSet, + Model::shareResourcesMaxMin(p_runningActionSet, xbt_swag_offset(action, p_variable), p_maxminSystem, lmm_solve); return 0; diff --git a/src/surf/cpu_ti.cpp b/src/surf/cpu_ti.cpp index a9446205f5..3b5020a2c6 100644 --- a/src/surf/cpu_ti.cpp +++ b/src/surf/cpu_ti.cpp @@ -1,20 +1,19 @@ #include "cpu_ti.hpp" -//#include "solver.hpp" #include "trace_mgr_private.h" #include "xbt/heap.h" #ifndef SURF_MODEL_CPUTI_H_ #define SURF_MODEL_CPUTI_H_ -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surfpp_cpu_tii, surfpp, +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu_ti, surf, "Logging specific to the SURF CPU TRACE INTEGRATION module"); +} static xbt_swag_t cpu_ti_running_action_set_that_does_not_need_being_checked; static xbt_swag_t cpu_ti_modified_cpu; static xbt_heap_t cpu_ti_action_heap; -static CpuTiModelPtr surf_cpu_model = NULL; - static void cpu_ti_action_update_index_heap(void *action, int i); /********* @@ -805,9 +804,14 @@ void CpuTi::updateRemainingAmount(double now) } CpuActionPtr CpuTi::execute(double size) +{ + return execute(size); +} + +CpuTiActionPtr CpuTi::_execute(double size) { XBT_IN("(%s,%g)", m_name, size); - CpuTiActionPtr action = new CpuTiAction(surf_cpu_model, size, p_stateCurrent != SURF_RESOURCE_ON); + CpuTiActionPtr action = new CpuTiAction((CpuTiModelPtr) p_model, size, p_stateCurrent != SURF_RESOURCE_ON); action->p_cpu = this; action->m_indexHeap = -1; @@ -830,7 +834,7 @@ CpuActionPtr CpuTi::sleep(double duration) duration = MAX(duration, MAXMIN_PRECISION); XBT_IN("(%s,%g)", m_name, duration); - CpuActionPtr action = execute(1.0); + CpuTiActionPtr action = _execute(1.0); action->m_maxDuration = duration; action->m_suspended = 2; if (duration == NO_MAX_DURATION) { diff --git a/src/surf/cpu_ti.hpp b/src/surf/cpu_ti.hpp index d37cce4aab..01f66eb072 100644 --- a/src/surf/cpu_ti.hpp +++ b/src/surf/cpu_ti.hpp @@ -114,10 +114,11 @@ public: void updateState(tmgr_trace_event_t event_type, double value, double date); void updateActionFinishDate(double now); - bool isUsed(); + bool isUsed(); void printCpuTiModel(); CpuTiModelPtr getModel(); CpuActionPtr execute(double size); + CpuTiActionPtr _execute(double size); CpuActionPtr sleep(double duration); double getAvailableSpeed(); @@ -153,6 +154,6 @@ public: double getRemains(); CpuTiPtr p_cpu; int m_indexHeap; - + int m_suspended; private: }; diff --git a/src/surf/fair_bottleneck.c b/src/surf/fair_bottleneck.c new file mode 100644 index 0000000000..aa9c4fa634 --- /dev/null +++ b/src/surf/fair_bottleneck.c @@ -0,0 +1,181 @@ +/* Copyright (c) 2007, 2008, 2009, 2010. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + + +#include "xbt/sysdep.h" +#include "xbt/log.h" +#include "maxmin_private.h" +#include +#include + +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_maxmin); +#define SHOW_EXPR_G(expr) XBT_DEBUG(#expr " = %g",expr); +#define SHOW_EXPR_D(expr) XBT_DEBUG(#expr " = %d",expr); +#define SHOW_EXPR_P(expr) XBT_DEBUG(#expr " = %p",expr); + +void bottleneck_solve(lmm_system_t sys) +{ + lmm_variable_t var = NULL; + lmm_variable_t var_next = NULL; + lmm_constraint_t cnst = NULL; + s_lmm_constraint_t s_cnst; + lmm_constraint_t cnst_next = NULL; + lmm_element_t elem = NULL; + xbt_swag_t cnst_list = NULL; + xbt_swag_t var_list = NULL; + xbt_swag_t elem_list = NULL; + int i; + + static s_xbt_swag_t cnst_to_update; + + if (!(sys->modified)) + return; + + /* Init */ + xbt_swag_init(&(cnst_to_update), + xbt_swag_offset(s_cnst, saturated_constraint_set_hookup)); + + var_list = &(sys->variable_set); + XBT_DEBUG("Variable set : %d", xbt_swag_size(var_list)); + xbt_swag_foreach(var, var_list) { + int nb = 0; + var->value = 0.0; + XBT_DEBUG("Handling variable %p", var); + xbt_swag_insert(var, &(sys->saturated_variable_set)); + for (i = 0; i < var->cnsts_number; i++) { + if (var->cnsts[i].value == 0.0) + nb++; + } + if ((nb == var->cnsts_number) && (var->weight > 0.0)) { + XBT_DEBUG("Err, finally, there is no need to take care of variable %p", + var); + xbt_swag_remove(var, &(sys->saturated_variable_set)); + var->value = 1.0; + } + if (var->weight <= 0.0) { + XBT_DEBUG("Err, finally, there is no need to take care of variable %p", + var); + xbt_swag_remove(var, &(sys->saturated_variable_set)); + } + } + var_list = &(sys->saturated_variable_set); + + cnst_list = &(sys->active_constraint_set); + XBT_DEBUG("Active constraints : %d", xbt_swag_size(cnst_list)); + xbt_swag_foreach(cnst, cnst_list) { + xbt_swag_insert(cnst, &(sys->saturated_constraint_set)); + } + cnst_list = &(sys->saturated_constraint_set); + xbt_swag_foreach(cnst, cnst_list) { + cnst->remaining = cnst->bound; + cnst->usage = 0.0; + } + + XBT_DEBUG("Fair bottleneck Initialized"); + + /* + * Compute Usage and store the variables that reach the maximum. + */ + do { + if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) { + XBT_DEBUG("Fair bottleneck done"); + lmm_print(sys); + } + XBT_DEBUG("******* Constraints to process: %d *******", + xbt_swag_size(cnst_list)); + xbt_swag_foreach_safe(cnst, cnst_next, cnst_list) { + int nb = 0; + XBT_DEBUG("Processing cnst %p ", cnst); + elem_list = &(cnst->element_set); + cnst->usage = 0.0; + xbt_swag_foreach(elem, elem_list) { + if (elem->variable->weight <= 0) + break; + if ((elem->value > 0) + && xbt_swag_belongs(elem->variable, var_list)) + nb++; + } + XBT_DEBUG("\tThere are %d variables", nb); + if (nb > 0 && !cnst->shared) + nb = 1; + if (!nb) { + cnst->remaining = 0.0; + cnst->usage = cnst->remaining; + xbt_swag_remove(cnst, cnst_list); + continue; + } + cnst->usage = cnst->remaining / nb; + XBT_DEBUG("\tConstraint Usage %p : %f with %d variables", cnst, + cnst->usage, nb); + } + + xbt_swag_foreach_safe(var, var_next, var_list) { + double min_inc = + var->cnsts[0].constraint->usage / var->cnsts[0].value; + for (i = 1; i < var->cnsts_number; i++) { + lmm_element_t elm = &var->cnsts[i]; + min_inc = MIN(min_inc, elm->constraint->usage / elm->value); + } + if (var->bound > 0) + min_inc = MIN(min_inc, var->bound - var->value); + var->mu = min_inc; + XBT_DEBUG("Updating variable %p maximum increment: %g", var, var->mu); + var->value += var->mu; + if (var->value == var->bound) { + xbt_swag_remove(var, var_list); + } + } + + xbt_swag_foreach_safe(cnst, cnst_next, cnst_list) { + XBT_DEBUG("Updating cnst %p ", cnst); + elem_list = &(cnst->element_set); + xbt_swag_foreach(elem, elem_list) { + if (elem->variable->weight <= 0) + break; + if (cnst->shared) { + XBT_DEBUG("\tUpdate constraint %p (%g) with variable %p by %g", + cnst, cnst->remaining, elem->variable, + elem->variable->mu); + double_update(&(cnst->remaining), + elem->value * elem->variable->mu); + } else { + XBT_DEBUG + ("\tNon-Shared variable. Update constraint usage of %p (%g) with variable %p by %g", + cnst, cnst->usage, elem->variable, elem->variable->mu); + cnst->usage = MIN(cnst->usage, elem->value * elem->variable->mu); + } + } + if (!cnst->shared) { + XBT_DEBUG("\tUpdate constraint %p (%g) by %g", + cnst, cnst->remaining, cnst->usage); + + double_update(&(cnst->remaining), cnst->usage); + } + + XBT_DEBUG("\tRemaining for %p : %g", cnst, cnst->remaining); + if (cnst->remaining == 0.0) { + XBT_DEBUG("\tGet rid of constraint %p", cnst); + + xbt_swag_remove(cnst, cnst_list); + xbt_swag_foreach(elem, elem_list) { + if (elem->variable->weight <= 0) + break; + if (elem->value > 0) { + XBT_DEBUG("\t\tGet rid of variable %p", elem->variable); + xbt_swag_remove(elem->variable, var_list); + } + } + } + } + } while (xbt_swag_size(var_list)); + + xbt_swag_reset(cnst_list); + sys->modified = 0; + if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) { + XBT_DEBUG("Fair bottleneck done"); + lmm_print(sys); + } +} diff --git a/src/surf/instr_routing.c b/src/surf/instr_routing.c index 8aa9377763..884519caa4 100644 --- a/src/surf/instr_routing.c +++ b/src/surf/instr_routing.c @@ -9,7 +9,7 @@ #ifdef HAVE_TRACING #include "surf/surf_private.h" -#include "surf/network_private.h" +//FIXME:#include "surf/network_private.h" #include "xbt/graph.h" XBT_LOG_NEW_DEFAULT_SUBCATEGORY (instr_routing, instr, "Tracing platform hierarchy"); @@ -134,14 +134,14 @@ static void recursiveGraphExtraction (AS_t rc, container_t container, xbt_dict_t XBT_DEBUG("Graph extraction disabled by user."); return; } - XBT_DEBUG ("Graph extraction for routing_component = %s", rc->name); - if (!xbt_dict_is_empty(rc->routing_sons)){ + XBT_DEBUG ("Graph extraction for routing_component = %s", surf_AS_get_name(rc)); + if (!xbt_dict_is_empty(surf_AS_get_routing_sons(rc))){ xbt_dict_cursor_t cursor = NULL; AS_t rc_son; char *child_name; //bottom-up recursion - xbt_dict_foreach(rc->routing_sons, cursor, child_name, rc_son) { - container_t child_container = xbt_dict_get (container->children, rc_son->name); + xbt_dict_foreach(surf_AS_get_routing_sons(rc), cursor, child_name, rc_son) { + container_t child_container = xbt_dict_get (container->children, surf_AS_get_name(rc_son)); recursiveGraphExtraction (rc_son, child_container, filter); } } @@ -155,7 +155,7 @@ static void recursiveGraphExtraction (AS_t rc, container_t container, xbt_dict_t xbt_dict_cursor_t cursor = NULL; char *edge_name; - rc->get_graph(graph,nodes,edges,rc); + surf_AS_get_graph(rc, graph, nodes, edges); xbt_dict_foreach(edges,cursor,edge_name,edge) { linkContainers(PJ_container_get(edge->src->data), PJ_container_get(edge->dst->data), filter); } @@ -330,7 +330,7 @@ static void instr_routing_parse_end_platform () currentContainer = NULL; xbt_dict_t filter = xbt_dict_new_homogeneous(xbt_free); XBT_DEBUG ("Starting graph extraction."); - recursiveGraphExtraction (routing_platf->root, PJ_container_get_root(), filter); + recursiveGraphExtraction (surf_platf_get_root(routing_platf), PJ_container_get_root(), filter); XBT_DEBUG ("Graph extraction finished."); xbt_dict_free(&filter); platform_created = 1; @@ -450,18 +450,18 @@ int instr_platform_traced () static void recursiveXBTGraphExtraction (xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges, AS_t rc, container_t container) { - if (!xbt_dict_is_empty(rc->routing_sons)){ + if (!xbt_dict_is_empty(surf_AS_get_routing_sons(rc))){ xbt_dict_cursor_t cursor = NULL; AS_t rc_son; char *child_name; //bottom-up recursion - xbt_dict_foreach(rc->routing_sons, cursor, child_name, rc_son) { - container_t child_container = xbt_dict_get (container->children, rc_son->name); + xbt_dict_foreach(surf_AS_get_routing_sons(rc), cursor, child_name, rc_son) { + container_t child_container = xbt_dict_get (container->children, surf_AS_get_name(rc_son)); recursiveXBTGraphExtraction (graph, nodes, edges, rc_son, child_container); } } - rc->get_graph(graph,nodes,edges,rc); + surf_AS_get_graph(rc, graph, nodes, edges); } xbt_graph_t instr_routing_platform_graph (void) @@ -469,7 +469,7 @@ xbt_graph_t instr_routing_platform_graph (void) xbt_graph_t ret = xbt_graph_new_graph (0, NULL); xbt_dict_t nodes = xbt_dict_new_homogeneous(NULL); xbt_dict_t edges = xbt_dict_new_homogeneous(NULL); - recursiveXBTGraphExtraction (ret, nodes, edges, routing_platf->root, PJ_container_get_root()); + recursiveXBTGraphExtraction (ret, nodes, edges, surf_platf_get_root(routing_platf), PJ_container_get_root()); xbt_dict_free (&nodes); xbt_dict_free (&edges); return ret; diff --git a/src/surf/instr_surf.c b/src/surf/instr_surf.c index 9faf3a89fc..bf8339ead1 100644 --- a/src/surf/instr_surf.c +++ b/src/surf/instr_surf.c @@ -6,7 +6,7 @@ #include "instr/instr_private.h" #include "surf/surf_private.h" -#include "surf/network_gtnets_private.h" +//FIXME:#include "surf/network_gtnets_private.h" #ifdef HAVE_TRACING @@ -43,9 +43,9 @@ void TRACE_surf_link_set_bandwidth(double date, const char *resource, double ban /* to trace gtnets */ void TRACE_surf_gtnets_communicate(void *action, void *src, void *dst) { - surf_action_network_GTNETS_t gtnets_action = (surf_action_network_GTNETS_t)action; + /*FIXME:surf_action_network_GTNETS_t gtnets_action = (surf_action_network_GTNETS_t)action; gtnets_action->src = src; - gtnets_action->dst = dst; + gtnets_action->dst = dst;*/ } void TRACE_surf_action(surf_action_t surf_action, const char *category) @@ -57,6 +57,6 @@ void TRACE_surf_action(surf_action_t surf_action, const char *category) if (!category) return; - surf_action->category = xbt_strdup(category); + surf_action_set_category(surf_action, xbt_strdup(category)); } #endif /* HAVE_TRACING */ diff --git a/src/surf/lagrange.c b/src/surf/lagrange.c new file mode 100644 index 0000000000..0eec4fb677 --- /dev/null +++ b/src/surf/lagrange.c @@ -0,0 +1,656 @@ +/* Copyright (c) 2007, 2008, 2009, 2010. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +/* + * Modelling the proportional fairness using the Lagrange Optimization + * Approach. For a detailed description see: + * "ssh://username@scm.gforge.inria.fr/svn/memo/people/pvelho/lagrange/ppf.ps". + */ +#include "xbt/log.h" +#include "xbt/sysdep.h" +#include "maxmin_private.h" + +#include +#ifndef MATH +#include +#endif + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_lagrange, surf, + "Logging specific to SURF (lagrange)"); +XBT_LOG_NEW_SUBCATEGORY(surf_lagrange_dichotomy, surf_lagrange, + "Logging specific to SURF (lagrange dichotomy)"); + +#define SHOW_EXPR(expr) XBT_CDEBUG(surf_lagrange,#expr " = %g",expr); + +double (*func_f_def) (lmm_variable_t, double); +double (*func_fp_def) (lmm_variable_t, double); +double (*func_fpi_def) (lmm_variable_t, double); + +/* + * Local prototypes to implement the lagrangian optimization with optimal step, also called dichotomy. + */ +//solves the proportional fairness using a lagrange optimizition with dichotomy step +void lagrange_solve(lmm_system_t sys); +//computes the value of the dichotomy using a initial values, init, with a specific variable or constraint +static double dichotomy(double init, double diff(double, void *), + void *var_cnst, double min_error); +//computes the value of the differential of constraint param_cnst applied to lambda +static double partial_diff_lambda(double lambda, void *param_cnst); + +static int __check_feasible(xbt_swag_t cnst_list, xbt_swag_t var_list, + int warn) +{ + xbt_swag_t elem_list = NULL; + lmm_element_t elem = NULL; + lmm_constraint_t cnst = NULL; + lmm_variable_t var = NULL; + + double tmp; + + xbt_swag_foreach(cnst, cnst_list) { + tmp = 0; + elem_list = &(cnst->element_set); + xbt_swag_foreach(elem, elem_list) { + var = elem->variable; + if (var->weight <= 0) + continue; + tmp += var->value; + } + + if (double_positive(tmp - cnst->bound)) { + if (warn) + XBT_WARN + ("The link (%p) is over-used. Expected less than %f and got %f", + cnst, cnst->bound, tmp); + return 0; + } + XBT_DEBUG + ("Checking feasability for constraint (%p): sat = %f, lambda = %f ", + cnst, tmp - cnst->bound, cnst->lambda); + } + + xbt_swag_foreach(var, var_list) { + if (!var->weight) + break; + if (var->bound < 0) + continue; + XBT_DEBUG("Checking feasability for variable (%p): sat = %f mu = %f", var, + var->value - var->bound, var->mu); + + if (double_positive(var->value - var->bound)) { + if (warn) + XBT_WARN + ("The variable (%p) is too large. Expected less than %f and got %f", + var, var->bound, var->value); + return 0; + } + } + return 1; +} + +static double new_value(lmm_variable_t var) +{ + double tmp = 0; + int i; + + for (i = 0; i < var->cnsts_number; i++) { + tmp += (var->cnsts[i].constraint)->lambda; + } + if (var->bound > 0) + tmp += var->mu; + XBT_DEBUG("\t Working on var (%p). cost = %e; Weight = %e", var, tmp, + var->weight); + //uses the partial differential inverse function + return var->func_fpi(var, tmp); +} + +static double new_mu(lmm_variable_t var) +{ + double mu_i = 0.0; + double sigma_i = 0.0; + int j; + + for (j = 0; j < var->cnsts_number; j++) { + sigma_i += (var->cnsts[j].constraint)->lambda; + } + mu_i = var->func_fp(var, var->bound) - sigma_i; + if (mu_i < 0.0) + return 0.0; + return mu_i; +} + +static double dual_objective(xbt_swag_t var_list, xbt_swag_t cnst_list) +{ + lmm_constraint_t cnst = NULL; + lmm_variable_t var = NULL; + + double obj = 0.0; + + xbt_swag_foreach(var, var_list) { + double sigma_i = 0.0; + int j; + + if (!var->weight) + break; + + for (j = 0; j < var->cnsts_number; j++) + sigma_i += (var->cnsts[j].constraint)->lambda; + + if (var->bound > 0) + sigma_i += var->mu; + + XBT_DEBUG("var %p : sigma_i = %1.20f", var, sigma_i); + + obj += var->func_f(var, var->func_fpi(var, sigma_i)) - + sigma_i * var->func_fpi(var, sigma_i); + + if (var->bound > 0) + obj += var->mu * var->bound; + } + + xbt_swag_foreach(cnst, cnst_list) + obj += cnst->lambda * cnst->bound; + + return obj; +} + +void lagrange_solve(lmm_system_t sys) +{ + /* + * Lagrange Variables. + */ + int max_iterations = 100; + double epsilon_min_error = MAXMIN_PRECISION; + double dichotomy_min_error = 1e-14; + double overall_modification = 1; + + /* + * Variables to manipulate the data structure proposed to model the maxmin + * fairness. See docummentation for more details. + */ + xbt_swag_t cnst_list = NULL; + lmm_constraint_t cnst = NULL; + + xbt_swag_t var_list = NULL; + lmm_variable_t var = NULL; + + /* + * Auxiliar variables. + */ + int iteration = 0; + double tmp = 0; + int i; + double obj, new_obj; + + XBT_DEBUG("Iterative method configuration snapshot =====>"); + XBT_DEBUG("#### Maximum number of iterations : %d", max_iterations); + XBT_DEBUG("#### Minimum error tolerated : %e", + epsilon_min_error); + XBT_DEBUG("#### Minimum error tolerated (dichotomy) : %e", + dichotomy_min_error); + + if (XBT_LOG_ISENABLED(surf_lagrange, xbt_log_priority_debug)) { + lmm_print(sys); + } + + if (!(sys->modified)) + return; + + + /* + * Initialize lambda. + */ + cnst_list = &(sys->active_constraint_set); + xbt_swag_foreach(cnst, cnst_list) { + cnst->lambda = 1.0; + cnst->new_lambda = 2.0; + XBT_DEBUG("#### cnst(%p)->lambda : %e", cnst, cnst->lambda); + } + + /* + * Initialize the var list variable with only the active variables. + * Associate an index in the swag variables. Initialize mu. + */ + var_list = &(sys->variable_set); + i = 0; + xbt_swag_foreach(var, var_list) { + if (!var->weight) + var->value = 0.0; + else { + int nb = 0; + if (var->bound < 0.0) { + XBT_DEBUG("#### NOTE var(%d) is a boundless variable", i); + var->mu = -1.0; + var->value = new_value(var); + } else { + var->mu = 1.0; + var->new_mu = 2.0; + var->value = new_value(var); + } + XBT_DEBUG("#### var(%p) ->weight : %e", var, var->weight); + XBT_DEBUG("#### var(%p) ->mu : %e", var, var->mu); + XBT_DEBUG("#### var(%p) ->weight: %e", var, var->weight); + XBT_DEBUG("#### var(%p) ->bound: %e", var, var->bound); + for (i = 0; i < var->cnsts_number; i++) { + if (var->cnsts[i].value == 0.0) + nb++; + } + if (nb == var->cnsts_number) + var->value = 1.0; + } + } + + /* + * Compute dual objective. + */ + obj = dual_objective(var_list, cnst_list); + + /* + * While doesn't reach a minimun error or a number maximum of iterations. + */ + while (overall_modification > epsilon_min_error + && iteration < max_iterations) { +/* int dual_updated=0; */ + + iteration++; + XBT_DEBUG("************** ITERATION %d **************", iteration); + XBT_DEBUG("-------------- Gradient Descent ----------"); + + /* + * Improve the value of mu_i + */ + xbt_swag_foreach(var, var_list) { + if (!var->weight) + break; + if (var->bound >= 0) { + XBT_DEBUG("Working on var (%p)", var); + var->new_mu = new_mu(var); +/* dual_updated += (fabs(var->new_mu-var->mu)>dichotomy_min_error); */ +/* XBT_DEBUG("dual_updated (%d) : %1.20f",dual_updated,fabs(var->new_mu-var->mu)); */ + XBT_DEBUG("Updating mu : var->mu (%p) : %1.20f -> %1.20f", var, + var->mu, var->new_mu); + var->mu = var->new_mu; + + new_obj = dual_objective(var_list, cnst_list); + XBT_DEBUG("Improvement for Objective (%g -> %g) : %g", obj, new_obj, + obj - new_obj); + xbt_assert(obj - new_obj >= -epsilon_min_error, + "Our gradient sucks! (%1.20f)", obj - new_obj); + obj = new_obj; + } + } + + /* + * Improve the value of lambda_i + */ + xbt_swag_foreach(cnst, cnst_list) { + XBT_DEBUG("Working on cnst (%p)", cnst); + cnst->new_lambda = + dichotomy(cnst->lambda, partial_diff_lambda, cnst, + dichotomy_min_error); +/* dual_updated += (fabs(cnst->new_lambda-cnst->lambda)>dichotomy_min_error); */ +/* XBT_DEBUG("dual_updated (%d) : %1.20f",dual_updated,fabs(cnst->new_lambda-cnst->lambda)); */ + XBT_DEBUG("Updating lambda : cnst->lambda (%p) : %1.20f -> %1.20f", + cnst, cnst->lambda, cnst->new_lambda); + cnst->lambda = cnst->new_lambda; + + new_obj = dual_objective(var_list, cnst_list); + XBT_DEBUG("Improvement for Objective (%g -> %g) : %g", obj, new_obj, + obj - new_obj); + xbt_assert(obj - new_obj >= -epsilon_min_error, + "Our gradient sucks! (%1.20f)", obj - new_obj); + obj = new_obj; + } + + /* + * Now computes the values of each variable (\rho) based on + * the values of \lambda and \mu. + */ + XBT_DEBUG("-------------- Check convergence ----------"); + overall_modification = 0; + xbt_swag_foreach(var, var_list) { + if (var->weight <= 0) + var->value = 0.0; + else { + tmp = new_value(var); + + overall_modification = + MAX(overall_modification, fabs(var->value - tmp)); + + var->value = tmp; + XBT_DEBUG("New value of var (%p) = %e, overall_modification = %e", + var, var->value, overall_modification); + } + } + + XBT_DEBUG("-------------- Check feasability ----------"); + if (!__check_feasible(cnst_list, var_list, 0)) + overall_modification = 1.0; + XBT_DEBUG("Iteration %d: overall_modification : %f", iteration, + overall_modification); +/* if(!dual_updated) { */ +/* XBT_WARN("Could not improve the convergence at iteration %d. Drop it!",iteration); */ +/* break; */ +/* } */ + } + + __check_feasible(cnst_list, var_list, 1); + + if (overall_modification <= epsilon_min_error) { + XBT_DEBUG("The method converges in %d iterations.", iteration); + } + if (iteration >= max_iterations) { + XBT_DEBUG + ("Method reach %d iterations, which is the maximum number of iterations allowed.", + iteration); + } +/* XBT_INFO("Method converged after %d iterations", iteration); */ + + if (XBT_LOG_ISENABLED(surf_lagrange, xbt_log_priority_debug)) { + lmm_print(sys); + } +} + +/* + * Returns a double value corresponding to the result of a dichotomy proccess with + * respect to a given variable/constraint (\mu in the case of a variable or \lambda in + * case of a constraint) and a initial value init. + * + * @param init initial value for \mu or \lambda + * @param diff a function that computes the differential of with respect a \mu or \lambda + * @param var_cnst a pointer to a variable or constraint + * @param min_erro a minimun error tolerated + * + * @return a double correponding to the result of the dichotomyal process + */ +static double dichotomy(double init, double diff(double, void *), + void *var_cnst, double min_error) +{ + double min, max; + double overall_error; + double middle; + double min_diff, max_diff, middle_diff; + double diff_0 = 0.0; + min = max = init; + + XBT_IN(); + + if (init == 0.0) { + min = max = 0.5; + } + + min_diff = max_diff = middle_diff = 0.0; + overall_error = 1; + + if ((diff_0 = diff(1e-16, var_cnst)) >= 0) { + XBT_CDEBUG(surf_lagrange_dichotomy, "returning 0.0 (diff = %e)", diff_0); + XBT_OUT(); + return 0.0; + } + + min_diff = diff(min, var_cnst); + max_diff = diff(max, var_cnst); + + while (overall_error > min_error) { + XBT_CDEBUG(surf_lagrange_dichotomy, + "[min, max] = [%1.20f, %1.20f] || diffmin, diffmax = %1.20f, %1.20f", + min, max, min_diff, max_diff); + + if (min_diff > 0 && max_diff > 0) { + if (min == max) { + XBT_CDEBUG(surf_lagrange_dichotomy, "Decreasing min"); + min = min / 2.0; + min_diff = diff(min, var_cnst); + } else { + XBT_CDEBUG(surf_lagrange_dichotomy, "Decreasing max"); + max = min; + max_diff = min_diff; + } + } else if (min_diff < 0 && max_diff < 0) { + if (min == max) { + XBT_CDEBUG(surf_lagrange_dichotomy, "Increasing max"); + max = max * 2.0; + max_diff = diff(max, var_cnst); + } else { + XBT_CDEBUG(surf_lagrange_dichotomy, "Increasing min"); + min = max; + min_diff = max_diff; + } + } else if (min_diff < 0 && max_diff > 0) { + middle = (max + min) / 2.0; + XBT_CDEBUG(surf_lagrange_dichotomy, "Trying (max+min)/2 : %1.20f", + middle); + + if ((min == middle) || (max == middle)) { + XBT_CWARN(surf_lagrange_dichotomy, + "Cannot improve the convergence! min=max=middle=%1.20f, diff = %1.20f." + " Reaching the 'double' limits. Maybe scaling your function would help ([%1.20f,%1.20f]).", + min, max - min, min_diff, max_diff); + break; + } + middle_diff = diff(middle, var_cnst); + + if (middle_diff < 0) { + XBT_CDEBUG(surf_lagrange_dichotomy, "Increasing min"); + min = middle; + overall_error = max_diff - middle_diff; + min_diff = middle_diff; +/* SHOW_EXPR(overall_error); */ + } else if (middle_diff > 0) { + XBT_CDEBUG(surf_lagrange_dichotomy, "Decreasing max"); + max = middle; + overall_error = max_diff - middle_diff; + max_diff = middle_diff; +/* SHOW_EXPR(overall_error); */ + } else { + overall_error = 0; +/* SHOW_EXPR(overall_error); */ + } + } else if (min_diff == 0) { + max = min; + overall_error = 0; +/* SHOW_EXPR(overall_error); */ + } else if (max_diff == 0) { + min = max; + overall_error = 0; +/* SHOW_EXPR(overall_error); */ + } else if (min_diff > 0 && max_diff < 0) { + XBT_CWARN(surf_lagrange_dichotomy, + "The impossible happened, partial_diff(min) > 0 && partial_diff(max) < 0"); + xbt_abort(); + } else { + XBT_CWARN(surf_lagrange_dichotomy, + "diffmin (%1.20f) or diffmax (%1.20f) are something I don't know, taking no action.", + min_diff, max_diff); + xbt_abort(); + } + } + + XBT_CDEBUG(surf_lagrange_dichotomy, "returning %e", (min + max) / 2.0); + XBT_OUT(); + return ((min + max) / 2.0); +} + +static double partial_diff_lambda(double lambda, void *param_cnst) +{ + + int j; + xbt_swag_t elem_list = NULL; + lmm_element_t elem = NULL; + lmm_variable_t var = NULL; + lmm_constraint_t cnst = (lmm_constraint_t) param_cnst; + double diff = 0.0; + double sigma_i = 0.0; + + XBT_IN(); + elem_list = &(cnst->element_set); + + XBT_CDEBUG(surf_lagrange_dichotomy, "Computing diff of cnst (%p)", cnst); + + xbt_swag_foreach(elem, elem_list) { + var = elem->variable; + if (var->weight <= 0) + continue; + + XBT_CDEBUG(surf_lagrange_dichotomy, "Computing sigma_i for var (%p)", + var); + // Initialize the summation variable + sigma_i = 0.0; + + // Compute sigma_i + for (j = 0; j < var->cnsts_number; j++) { + sigma_i += (var->cnsts[j].constraint)->lambda; + } + + //add mu_i if this flow has a RTT constraint associated + if (var->bound > 0) + sigma_i += var->mu; + + //replace value of cnst->lambda by the value of parameter lambda + sigma_i = (sigma_i - cnst->lambda) + lambda; + + diff += -var->func_fpi(var, sigma_i); + } + + + diff += cnst->bound; + + XBT_CDEBUG(surf_lagrange_dichotomy, + "d D/d lambda for cnst (%p) at %1.20f = %1.20f", cnst, lambda, + diff); + XBT_OUT(); + return diff; +} + +/** \brief Attribute the value bound to var->bound. + * + * \param func_fpi inverse of the partial differential of f (f prime inverse, (f')^{-1}) + * + * Set default functions to the ones passed as parameters. This is a polimorfism in C pure, enjoy the roots of programming. + * + */ +void lmm_set_default_protocol_function(double (*func_f) + + + + + + + (lmm_variable_t var, double x), + double (*func_fp) (lmm_variable_t + var, double x), + double (*func_fpi) (lmm_variable_t + var, double x)) +{ + func_f_def = func_f; + func_fp_def = func_fp; + func_fpi_def = func_fpi; +} + + +/**************** Vegas and Reno functions *************************/ +/* + * NOTE for Reno: all functions consider the network + * coeficient (alpha) equal to 1. + */ + +/* + * For Vegas: $f(x) = \alpha D_f\ln(x)$ + * Therefore: $fp(x) = \frac{\alpha D_f}{x}$ + * Therefore: $fpi(x) = \frac{\alpha D_f}{x}$ + */ +#define VEGAS_SCALING 1000.0 + +double func_vegas_f(lmm_variable_t var, double x) +{ + xbt_assert(x > 0.0, "Don't call me with stupid values! (%1.20f)", x); + return VEGAS_SCALING * var->weight * log(x); +} + +double func_vegas_fp(lmm_variable_t var, double x) +{ + xbt_assert(x > 0.0, "Don't call me with stupid values! (%1.20f)", x); + return VEGAS_SCALING * var->weight / x; +} + +double func_vegas_fpi(lmm_variable_t var, double x) +{ + xbt_assert(x > 0.0, "Don't call me with stupid values! (%1.20f)", x); + return var->weight / (x / VEGAS_SCALING); +} + +/* + * For Reno: $f(x) = \frac{\sqrt{3/2}}{D_f} atan(\sqrt{3/2}D_f x)$ + * Therefore: $fp(x) = \frac{3}{3 D_f^2 x^2+2}$ + * Therefore: $fpi(x) = \sqrt{\frac{1}{{D_f}^2 x} - \frac{2}{3{D_f}^2}}$ + */ +#define RENO_SCALING 1.0 +double func_reno_f(lmm_variable_t var, double x) +{ + xbt_assert(var->weight > 0.0, "Don't call me with stupid values!"); + + return RENO_SCALING * sqrt(3.0 / 2.0) / var->weight * + atan(sqrt(3.0 / 2.0) * var->weight * x); +} + +double func_reno_fp(lmm_variable_t var, double x) +{ + return RENO_SCALING * 3.0 / (3.0 * var->weight * var->weight * x * x + + 2.0); +} + +double func_reno_fpi(lmm_variable_t var, double x) +{ + double res_fpi; + + xbt_assert(var->weight > 0.0, "Don't call me with stupid values!"); + xbt_assert(x > 0.0, "Don't call me with stupid values!"); + + res_fpi = + 1.0 / (var->weight * var->weight * (x / RENO_SCALING)) - + 2.0 / (3.0 * var->weight * var->weight); + if (res_fpi <= 0.0) + return 0.0; +/* xbt_assert(res_fpi>0.0,"Don't call me with stupid values!"); */ + return sqrt(res_fpi); +} + + +/* Implementing new Reno-2 + * For Reno-2: $f(x) = U_f(x_f) = \frac{{2}{D_f}}*ln(2+x*D_f)$ + * Therefore: $fp(x) = 2/(Weight*x + 2) + * Therefore: $fpi(x) = (2*Weight)/x - 4 + */ +#define RENO2_SCALING 1.0 +double func_reno2_f(lmm_variable_t var, double x) +{ + xbt_assert(var->weight > 0.0, "Don't call me with stupid values!"); + return RENO2_SCALING * (1.0 / var->weight) * log((x * var->weight) / + (2.0 * x * var->weight + + 3.0)); +} + +double func_reno2_fp(lmm_variable_t var, double x) +{ + return RENO2_SCALING * 3.0 / (var->weight * x * + (2.0 * var->weight * x + 3.0)); +} + +double func_reno2_fpi(lmm_variable_t var, double x) +{ + double res_fpi; + double tmp; + + xbt_assert(x > 0.0, "Don't call me with stupid values!"); + tmp = x * var->weight * var->weight; + res_fpi = tmp * (9.0 * x + 24.0); + + if (res_fpi <= 0.0) + return 0.0; + + res_fpi = RENO2_SCALING * (-3.0 * tmp + sqrt(res_fpi)) / (4.0 * tmp); + return res_fpi; +} diff --git a/src/surf/maxmin.c b/src/surf/maxmin.c new file mode 100644 index 0000000000..3d49f84d12 --- /dev/null +++ b/src/surf/maxmin.c @@ -0,0 +1,891 @@ +/* Copyright (c) 2004-2011. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + + +#include "xbt/sysdep.h" +#include "xbt/log.h" +#include "xbt/mallocator.h" +#include "maxmin_private.h" +#include +#include /* sprintf */ +#include +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_maxmin, surf, + "Logging specific to SURF (maxmin)"); + +typedef struct s_dyn_light { + int *data; + int pos; + int size; +} s_dyn_light_t, *dyn_light_t; + +XBT_EXPORT_NO_IMPORT(double) sg_maxmin_precision = 0.00001; + +static void *lmm_variable_mallocator_new_f(void); +static void lmm_variable_mallocator_free_f(void *var); +#define lmm_variable_mallocator_reset_f ((void_f_pvoid_t)NULL) +static void lmm_update_modified_set(lmm_system_t sys, + lmm_constraint_t cnst); +static void lmm_remove_all_modified_set(lmm_system_t sys); +static int Global_debug_id = 1; +static int Global_const_debug_id = 1; + +static void lmm_var_free(lmm_system_t sys, lmm_variable_t var); +static XBT_INLINE void lmm_cnst_free(lmm_system_t sys, + lmm_constraint_t cnst); + +lmm_system_t lmm_system_new(int selective_update) +{ + lmm_system_t l = NULL; + s_lmm_variable_t var; + s_lmm_constraint_t cnst; + + l = xbt_new0(s_lmm_system_t, 1); + + l->modified = 0; + l->selective_update_active = selective_update; + l->visited_counter = 1; + + XBT_DEBUG("Setting selective_update_active flag to %d\n", + l->selective_update_active); + + xbt_swag_init(&(l->variable_set), + xbt_swag_offset(var, variable_set_hookup)); + xbt_swag_init(&(l->constraint_set), + xbt_swag_offset(cnst, constraint_set_hookup)); + + xbt_swag_init(&(l->active_constraint_set), + xbt_swag_offset(cnst, active_constraint_set_hookup)); + + xbt_swag_init(&(l->modified_constraint_set), + xbt_swag_offset(cnst, modified_constraint_set_hookup)); + xbt_swag_init(&(l->saturated_variable_set), + xbt_swag_offset(var, saturated_variable_set_hookup)); + xbt_swag_init(&(l->saturated_constraint_set), + xbt_swag_offset(cnst, saturated_constraint_set_hookup)); + + l->variable_mallocator = xbt_mallocator_new(65536, + lmm_variable_mallocator_new_f, + lmm_variable_mallocator_free_f, + lmm_variable_mallocator_reset_f); + + return l; +} + +void lmm_system_free(lmm_system_t sys) +{ + lmm_variable_t var = NULL; + lmm_constraint_t cnst = NULL; + + while ((var = extract_variable(sys))) { + XBT_WARN + ("Variable %p (%d) still in LMM system when freing it: this may be a bug", + var, var->id_int); + lmm_var_free(sys, var); + } + + while ((cnst = extract_constraint(sys))) + lmm_cnst_free(sys, cnst); + + xbt_mallocator_free(sys->variable_mallocator); + free(sys); +} + +XBT_INLINE void lmm_variable_disable(lmm_system_t sys, lmm_variable_t var) +{ + int i; + int n; + + lmm_element_t elem = NULL; + + XBT_IN("(sys=%p, var=%p)", sys, var); + sys->modified = 1; + + n = 0; + for (i = 0; i < var->cnsts_number; i++) { + elem = &var->cnsts[i]; + xbt_swag_remove(elem, &(elem->constraint->element_set)); + xbt_swag_remove(elem, &(elem->constraint->active_element_set)); + if (!xbt_swag_size(&(elem->constraint->element_set))) + make_constraint_inactive(sys, elem->constraint); + else { + if (n < i) + var->cnsts[n].constraint = elem->constraint; + n++; + } + } + if (n) { + var->cnsts_number = n; + lmm_update_modified_set(sys, var->cnsts[0].constraint); + } + + var->cnsts_number = 0; + XBT_OUT(); +} + +static void lmm_var_free(lmm_system_t sys, lmm_variable_t var) +{ + + lmm_variable_disable(sys, var); + xbt_mallocator_release(sys->variable_mallocator, var); +} + +static XBT_INLINE void lmm_cnst_free(lmm_system_t sys, + lmm_constraint_t cnst) +{ +/* xbt_assert(xbt_swag_size(&(cnst->element_set)), */ +/* "This list should be empty!"); */ + make_constraint_inactive(sys, cnst); + free(cnst); +} + +lmm_constraint_t lmm_constraint_new(lmm_system_t sys, void *id, + double bound_value) +{ + lmm_constraint_t cnst = NULL; + s_lmm_element_t elem; + + cnst = xbt_new0(s_lmm_constraint_t, 1); + cnst->id = id; + cnst->id_int = Global_const_debug_id++; + xbt_swag_init(&(cnst->element_set), + xbt_swag_offset(elem, element_set_hookup)); + xbt_swag_init(&(cnst->active_element_set), + xbt_swag_offset(elem, active_element_set_hookup)); + + cnst->bound = bound_value; + cnst->usage = 0; + cnst->shared = 1; + insert_constraint(sys, cnst); + + return cnst; +} + +XBT_INLINE void lmm_constraint_shared(lmm_constraint_t cnst) +{ + cnst->shared = 0; +} + +XBT_INLINE int lmm_constraint_is_shared(lmm_constraint_t cnst) +{ + return (cnst->shared); +} + +XBT_INLINE void lmm_constraint_free(lmm_system_t sys, + lmm_constraint_t cnst) +{ + remove_constraint(sys, cnst); + lmm_cnst_free(sys, cnst); +} + +static void *lmm_variable_mallocator_new_f(void) +{ + lmm_variable_t var = xbt_new(s_lmm_variable_t, 1); + var->cnsts = NULL; /* will be created by realloc */ + return var; +} + +static void lmm_variable_mallocator_free_f(void *var) +{ + xbt_free(((lmm_variable_t) var)->cnsts); + xbt_free(var); +} + +lmm_variable_t lmm_variable_new(lmm_system_t sys, void *id, + double weight, + double bound, int number_of_constraints) +{ + lmm_variable_t var = NULL; + int i; + + XBT_IN("(sys=%p, id=%p, weight=%f, bound=%f, num_cons =%d)", + sys, id, weight, bound, number_of_constraints); + + var = xbt_mallocator_get(sys->variable_mallocator); + var->id = id; + var->id_int = Global_debug_id++; + var->cnsts = xbt_realloc(var->cnsts, number_of_constraints * sizeof(s_lmm_element_t)); + for (i = 0; i < number_of_constraints; i++) { + var->cnsts[i].element_set_hookup.next = NULL; + var->cnsts[i].element_set_hookup.prev = NULL; + var->cnsts[i].active_element_set_hookup.next = NULL; + var->cnsts[i].active_element_set_hookup.prev = NULL; + var->cnsts[i].constraint = NULL; + var->cnsts[i].variable = NULL; + var->cnsts[i].value = 0.0; + } + var->cnsts_size = number_of_constraints; + var->cnsts_number = 0; + var->weight = weight; + var->bound = bound; + var->value = 0.0; + var->visited = sys->visited_counter - 1; + var->mu = 0.0; + var->new_mu = 0.0; + var->func_f = func_f_def; + var->func_fp = func_fp_def; + var->func_fpi = func_fpi_def; + + var->variable_set_hookup.next = NULL; + var->variable_set_hookup.prev = NULL; + var->saturated_variable_set_hookup.next = NULL; + var->saturated_variable_set_hookup.prev = NULL; + + if (weight) + xbt_swag_insert_at_head(var, &(sys->variable_set)); + else + xbt_swag_insert_at_tail(var, &(sys->variable_set)); + + XBT_OUT(" returns %p", var); + return var; +} + +void lmm_variable_free(lmm_system_t sys, lmm_variable_t var) +{ + remove_variable(sys, var); + lmm_var_free(sys, var); +} + +XBT_INLINE double lmm_variable_getvalue(lmm_variable_t var) +{ + return (var->value); +} + +XBT_INLINE double lmm_variable_getbound(lmm_variable_t var) +{ + return (var->bound); +} + +void lmm_expand(lmm_system_t sys, lmm_constraint_t cnst, + lmm_variable_t var, double value) +{ + lmm_element_t elem = NULL; + + sys->modified = 1; + + xbt_assert(var->cnsts_number < var->cnsts_size, "Too much constraints"); + + elem = &(var->cnsts[var->cnsts_number++]); + + elem->value = value; + elem->constraint = cnst; + elem->variable = var; + + if (var->weight) + xbt_swag_insert_at_head(elem, &(elem->constraint->element_set)); + else + xbt_swag_insert_at_tail(elem, &(elem->constraint->element_set)); + if(!sys->selective_update_active) { + make_constraint_active(sys, cnst); + } else if(elem->value>0 || var->weight >0) { + make_constraint_active(sys, cnst); + lmm_update_modified_set(sys, cnst); + if (var->cnsts_number > 1) + lmm_update_modified_set(sys, var->cnsts[0].constraint); + } +} + +void lmm_expand_add(lmm_system_t sys, lmm_constraint_t cnst, + lmm_variable_t var, double value) +{ + int i; + sys->modified = 1; + + for (i = 0; i < var->cnsts_number; i++) + if (var->cnsts[i].constraint == cnst) + break; + + if (i < var->cnsts_number) { + if (cnst->shared) + var->cnsts[i].value += value; + else + var->cnsts[i].value = MAX(var->cnsts[i].value, value); + lmm_update_modified_set(sys, cnst); + } else + lmm_expand(sys, cnst, var, value); +} + +void lmm_elem_set_value(lmm_system_t sys, lmm_constraint_t cnst, + lmm_variable_t var, double value) +{ + int i; + + for (i = 0; i < var->cnsts_number; i++) + if (var->cnsts[i].constraint == cnst) + break; + + if (i < var->cnsts_number) { + var->cnsts[i].value = value; + sys->modified = 1; + lmm_update_modified_set(sys, cnst); + } else + DIE_IMPOSSIBLE; +} + +XBT_INLINE lmm_constraint_t lmm_get_cnst_from_var(lmm_system_t sys, + lmm_variable_t var, + int num) +{ + if (num < var->cnsts_number) + return (var->cnsts[num].constraint); + else + return NULL; +} + +XBT_INLINE double lmm_get_cnst_weight_from_var(lmm_system_t sys, + lmm_variable_t var, + int num) +{ + if (num < var->cnsts_number) + return (var->cnsts[num].value); + else + return 0.0; +} + +XBT_INLINE int lmm_get_number_of_cnst_from_var(lmm_system_t sys, + lmm_variable_t var) +{ + return (var->cnsts_number); +} + +lmm_variable_t lmm_get_var_from_cnst(lmm_system_t sys, + lmm_constraint_t cnst, + lmm_element_t * elem) +{ + if (!(*elem)) + *elem = xbt_swag_getFirst(&(cnst->element_set)); + else + *elem = xbt_swag_getNext(*elem, cnst->element_set.offset); + if (*elem) + return (*elem)->variable; + else + return NULL; +} + +XBT_INLINE void *lmm_constraint_id(lmm_constraint_t cnst) +{ + return cnst->id; +} + +XBT_INLINE void *lmm_variable_id(lmm_variable_t var) +{ + return var->id; +} + +static XBT_INLINE void saturated_constraint_set_update(double usage, + int cnst_light_num, + dyn_light_t saturated_constraint_set, + double *min_usage) +{ + xbt_assert(usage > 0,"Impossible"); + + if (*min_usage < 0 || *min_usage > usage) { + *min_usage = usage; + // XBT_HERE(" min_usage=%f (cnst->remaining / cnst->usage =%f)", *min_usage, usage); + saturated_constraint_set->data[0] = cnst_light_num; + saturated_constraint_set->pos = 1; + } else if (*min_usage == usage) { + if(saturated_constraint_set->pos == saturated_constraint_set->size) { // realloc the size + saturated_constraint_set->size *= 2; + saturated_constraint_set->data = xbt_realloc(saturated_constraint_set->data, (saturated_constraint_set->size) * sizeof(int)); + } + saturated_constraint_set->data[saturated_constraint_set->pos] = cnst_light_num; + saturated_constraint_set->pos++; + } +} + +static XBT_INLINE void saturated_variable_set_update( + s_lmm_constraint_light_t *cnst_light_tab, + dyn_light_t saturated_constraint_set, + lmm_system_t sys) +{ + lmm_constraint_light_t cnst = NULL; + lmm_element_t elem = NULL; + xbt_swag_t elem_list = NULL; + int i; + for(i = 0; i< saturated_constraint_set->pos; i++){ + cnst = &cnst_light_tab[saturated_constraint_set->data[i]]; + elem_list = &(cnst->cnst->active_element_set); + xbt_swag_foreach(elem, elem_list) { + if (elem->variable->weight <= 0) + break; + if ((elem->value > 0)) + xbt_swag_insert(elem->variable, &(sys->saturated_variable_set)); + } + } +} + +void lmm_print(lmm_system_t sys) +{ + lmm_constraint_t cnst = NULL; + lmm_element_t elem = NULL; + lmm_variable_t var = NULL; + xbt_swag_t cnst_list = NULL; + xbt_swag_t var_list = NULL; + xbt_swag_t elem_list = NULL; + char print_buf[1024]; + char *trace_buf = xbt_malloc0(sizeof(char)); + double sum = 0.0; + + /* Printing Objective */ + var_list = &(sys->variable_set); + sprintf(print_buf, "MAX-MIN ( "); + trace_buf = + xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1); + strcat(trace_buf, print_buf); + xbt_swag_foreach(var, var_list) { + sprintf(print_buf, "'%d'(%f) ", var->id_int, var->weight); + trace_buf = + xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1); + strcat(trace_buf, print_buf); + } + sprintf(print_buf, ")"); + trace_buf = + xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1); + strcat(trace_buf, print_buf); + XBT_DEBUG("%20s", trace_buf); + trace_buf[0] = '\000'; + + XBT_DEBUG("Constraints"); + /* Printing Constraints */ + cnst_list = &(sys->active_constraint_set); + xbt_swag_foreach(cnst, cnst_list) { + sum = 0.0; + elem_list = &(cnst->element_set); + sprintf(print_buf, "\t"); + trace_buf = + xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1); + strcat(trace_buf, print_buf); + sprintf(print_buf, "%s(",(cnst->shared)?"":"max"); + trace_buf = + xbt_realloc(trace_buf, + strlen(trace_buf) + strlen(print_buf) + 1); + strcat(trace_buf, print_buf); + xbt_swag_foreach(elem, elem_list) { + sprintf(print_buf, "%f.'%d'(%f) %s ", elem->value, + elem->variable->id_int, elem->variable->value,(cnst->shared)?"+":","); + trace_buf = + xbt_realloc(trace_buf, + strlen(trace_buf) + strlen(print_buf) + 1); + strcat(trace_buf, print_buf); + if(cnst->shared) + sum += elem->value * elem->variable->value; + else + sum = MAX(sum,elem->value * elem->variable->value); + } + sprintf(print_buf, "0) <= %f ('%d')", cnst->bound, cnst->id_int); + trace_buf = + xbt_realloc(trace_buf, strlen(trace_buf) + strlen(print_buf) + 1); + strcat(trace_buf, print_buf); + + if (!cnst->shared) { + sprintf(print_buf, " [MAX-Constraint]"); + trace_buf = + xbt_realloc(trace_buf, + strlen(trace_buf) + strlen(print_buf) + 1); + strcat(trace_buf, print_buf); + } + XBT_DEBUG("%s", trace_buf); + trace_buf[0] = '\000'; + xbt_assert(!double_positive(sum - cnst->bound), + "Incorrect value (%f is not smaller than %f): %g", + sum, cnst->bound, sum - cnst->bound); + } + + XBT_DEBUG("Variables"); + /* Printing Result */ + xbt_swag_foreach(var, var_list) { + if (var->bound > 0) { + XBT_DEBUG("'%d'(%f) : %f (<=%f)", var->id_int, var->weight, var->value, + var->bound); + xbt_assert(!double_positive(var->value - var->bound), + "Incorrect value (%f is not smaller than %f", + var->value, var->bound); + } else { + XBT_DEBUG("'%d'(%f) : %f", var->id_int, var->weight, var->value); + } + } + + free(trace_buf); +} + +void lmm_solve(lmm_system_t sys) +{ + lmm_variable_t var = NULL; + lmm_constraint_t cnst = NULL; + lmm_constraint_t cnst_next = NULL; + lmm_element_t elem = NULL; + xbt_swag_t cnst_list = NULL; + xbt_swag_t var_list = NULL; + xbt_swag_t elem_list = NULL; + double min_usage = -1; + double min_bound = -1; + + if (!(sys->modified)) + return; + + XBT_IN("(sys=%p)", sys); + + /* + * Compute Usage and store the variables that reach the maximum. + */ + cnst_list = + sys-> + selective_update_active ? &(sys->modified_constraint_set) : + &(sys->active_constraint_set); + + XBT_DEBUG("Active constraints : %d", xbt_swag_size(cnst_list)); + /* Init: Only modified code portions */ + xbt_swag_foreach(cnst, cnst_list) { + elem_list = &(cnst->element_set); + //XBT_DEBUG("Variable set : %d", xbt_swag_size(elem_list)); + xbt_swag_foreach(elem, elem_list) { + var = elem->variable; + if (var->weight <= 0.0) + break; + var->value = 0.0; + } + } + + s_lmm_constraint_light_t *cnst_light_tab = (s_lmm_constraint_light_t *)xbt_malloc0(xbt_swag_size(cnst_list)*sizeof(s_lmm_constraint_light_t)); + int cnst_light_num = 0; + dyn_light_t saturated_constraint_set = xbt_new0(s_dyn_light_t,1); + saturated_constraint_set->size = 5; + saturated_constraint_set->data = xbt_new0(int, saturated_constraint_set->size); + + xbt_swag_foreach_safe(cnst, cnst_next, cnst_list) { + /* INIT */ + cnst->remaining = cnst->bound; + if (cnst->remaining == 0) + continue; + cnst->usage = 0; + elem_list = &(cnst->element_set); + xbt_swag_foreach(elem, elem_list) { + /* 0-weighted elements (ie, sleep actions) are at the end of the swag and we don't want to consider them */ + if (elem->variable->weight <= 0) + break; + if ((elem->value > 0)) { + if (cnst->shared) + cnst->usage += elem->value / elem->variable->weight; + else if (cnst->usage < elem->value / elem->variable->weight) + cnst->usage = elem->value / elem->variable->weight; + + make_elem_active(elem); + if (sys->keep_track) + xbt_swag_insert(elem->variable->id, sys->keep_track); + } + } + XBT_DEBUG("Constraint Usage '%d' : %f", cnst->id_int, cnst->usage); + /* Saturated constraints update */ + + if(cnst->usage > 0) { + cnst_light_tab[cnst_light_num].cnst = cnst; + cnst->cnst_light = &(cnst_light_tab[cnst_light_num]); + cnst_light_tab[cnst_light_num].remaining_over_usage = cnst->remaining / cnst->usage; + saturated_constraint_set_update(cnst_light_tab[cnst_light_num].remaining_over_usage, + cnst_light_num, saturated_constraint_set, &min_usage); + cnst_light_num++; + } + } + + saturated_variable_set_update( cnst_light_tab, + saturated_constraint_set, + sys); + + /* Saturated variables update */ + + do { + /* Fix the variables that have to be */ + var_list = &(sys->saturated_variable_set); + + xbt_swag_foreach(var, var_list) { + if (var->weight <= 0.0) + DIE_IMPOSSIBLE; + /* First check if some of these variables have reach their upper + bound and update min_usage accordingly. */ + XBT_DEBUG + ("var=%d, var->bound=%f, var->weight=%f, min_usage=%f, var->bound*var->weight=%f", + var->id_int, var->bound, var->weight, min_usage, + var->bound * var->weight); + if ((var->bound > 0) && (var->bound * var->weight < min_usage)) { + if (min_bound < 0) + min_bound = var->bound; + else + min_bound = MIN(min_bound, var->bound); + XBT_DEBUG("Updated min_bound=%f", min_bound); + } + } + + + while ((var = xbt_swag_getFirst(var_list))) { + int i; + + if (min_bound < 0) { + var->value = min_usage / var->weight; + } else { + if (min_bound == var->bound) + var->value = var->bound; + else { + xbt_swag_remove(var, var_list); + continue; + } + } + XBT_DEBUG("Min usage: %f, Var(%d)->weight: %f, Var(%d)->value: %f ", + min_usage, var->id_int, var->weight, var->id_int, var->value); + + + /* Update usage */ + + for (i = 0; i < var->cnsts_number; i++) { + elem = &var->cnsts[i]; + cnst = elem->constraint; + if (cnst->shared) { + double_update(&(cnst->remaining), elem->value * var->value); + double_update(&(cnst->usage), elem->value / var->weight); + if(cnst->usage<=0 || cnst->remaining<=0) { + if (cnst->cnst_light) { + int index = (cnst->cnst_light-cnst_light_tab); + XBT_DEBUG("index: %d \t cnst_light_num: %d \t || \t cnst: %p \t cnst->cnst_light: %p \t cnst_light_tab: %p ", + index,cnst_light_num, cnst, cnst->cnst_light, cnst_light_tab); + cnst_light_tab[index]=cnst_light_tab[cnst_light_num-1]; + cnst_light_tab[index].cnst->cnst_light = &cnst_light_tab[index]; + cnst_light_num--; + cnst->cnst_light = NULL; + } + } else { + cnst->cnst_light->remaining_over_usage = cnst->remaining / cnst->usage; + } + make_elem_inactive(elem); + } else { + cnst->usage = 0.0; + make_elem_inactive(elem); + elem_list = &(cnst->element_set); + xbt_swag_foreach(elem, elem_list) { + if (elem->variable->weight <= 0 || elem->variable->value > 0) + break; + if (elem->value > 0) + cnst->usage = MAX(cnst->usage, elem->value / elem->variable->weight); + } + if (cnst->usage<=0 || cnst->remaining<=0) { + if(cnst->cnst_light) { + int index = (cnst->cnst_light-cnst_light_tab); + XBT_DEBUG("index: %d \t cnst_light_num: %d \t || \t cnst: %p \t cnst->cnst_light: %p \t cnst_light_tab: %p ", + index,cnst_light_num, cnst, cnst->cnst_light, cnst_light_tab); + cnst_light_tab[index]=cnst_light_tab[cnst_light_num-1]; + cnst_light_tab[index].cnst->cnst_light = &cnst_light_tab[index]; + cnst_light_num--; + cnst->cnst_light = NULL; + } + } else { + cnst->cnst_light->remaining_over_usage = cnst->remaining / cnst->usage; + } + } + } + xbt_swag_remove(var, var_list); + } + + /* Find out which variables reach the maximum */ + min_usage = -1; + min_bound = -1; + saturated_constraint_set->pos = 0; + int pos; + for(pos=0; pos 0); + + sys->modified = 0; + if (sys->selective_update_active) + lmm_remove_all_modified_set(sys); + + if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) { + lmm_print(sys); + } + + xbt_free(saturated_constraint_set->data); + xbt_free(saturated_constraint_set); + xbt_free(cnst_light_tab); + XBT_OUT(); +} + +/* Not a O(1) function */ + +void lmm_update(lmm_system_t sys, lmm_constraint_t cnst, + lmm_variable_t var, double value) +{ + int i; + + for (i = 0; i < var->cnsts_number; i++) + if (var->cnsts[i].constraint == cnst) { + var->cnsts[i].value = value; + sys->modified = 1; + lmm_update_modified_set(sys, cnst); + return; + } +} + +/** \brief Attribute the value bound to var->bound. + * + * \param sys the lmm_system_t + * \param var the lmm_variable_t + * \param bound the new bound to associate with var + * + * Makes var->bound equal to bound. Whenever this function is called + * a change is signed in the system. To + * avoid false system changing detection it is a good idea to test + * (bound != 0) before calling it. + * + */ +void lmm_update_variable_bound(lmm_system_t sys, lmm_variable_t var, + double bound) +{ + sys->modified = 1; + var->bound = bound; + + if (var->cnsts_number) + lmm_update_modified_set(sys, var->cnsts[0].constraint); +} + + +void lmm_update_variable_weight(lmm_system_t sys, lmm_variable_t var, + double weight) +{ + int i; + lmm_element_t elem; + + if (weight == var->weight) + return; + XBT_IN("(sys=%p, var=%p, weight=%f)", sys, var, weight); + sys->modified = 1; + var->weight = weight; + xbt_swag_remove(var, &(sys->variable_set)); + if (weight) + xbt_swag_insert_at_head(var, &(sys->variable_set)); + else + xbt_swag_insert_at_tail(var, &(sys->variable_set)); + + for (i = 0; i < var->cnsts_number; i++) { + elem = &var->cnsts[i]; + xbt_swag_remove(elem, &(elem->constraint->element_set)); + if (weight) + xbt_swag_insert_at_head(elem, &(elem->constraint->element_set)); + else + xbt_swag_insert_at_tail(elem, &(elem->constraint->element_set)); + + if (i == 0) + lmm_update_modified_set(sys, elem->constraint); + } + if (!weight) + var->value = 0.0; + + XBT_OUT(); +} + +XBT_INLINE double lmm_get_variable_weight(lmm_variable_t var) +{ + return var->weight; +} + +XBT_INLINE void lmm_update_constraint_bound(lmm_system_t sys, + lmm_constraint_t cnst, + double bound) +{ + sys->modified = 1; + lmm_update_modified_set(sys, cnst); + cnst->bound = bound; +} + +XBT_INLINE int lmm_constraint_used(lmm_system_t sys, lmm_constraint_t cnst) +{ + return xbt_swag_belongs(cnst, &(sys->active_constraint_set)); +} + +XBT_INLINE lmm_constraint_t lmm_get_first_active_constraint(lmm_system_t + sys) +{ + return xbt_swag_getFirst(&(sys->active_constraint_set)); +} + +XBT_INLINE lmm_constraint_t lmm_get_next_active_constraint(lmm_system_t + sys, + lmm_constraint_t + cnst) +{ + return xbt_swag_getNext(cnst, (sys->active_constraint_set).offset); +} + +#ifdef HAVE_LATENCY_BOUND_TRACKING +XBT_INLINE int lmm_is_variable_limited_by_latency(lmm_variable_t var) +{ + return (double_equals(var->bound, var->value)); +} +#endif + + +/** \brief Update the constraint set propagating recursively to + * other constraints so the system should not be entirely computed. + * + * \param sys the lmm_system_t + * \param cnst the lmm_constraint_t affected by the change + * + * A recursive algorithm to optimize the system recalculation selecting only + * constraints that have changed. Each constraint change is propagated + * to the list of constraints for each variable. + */ +static void lmm_update_modified_set_rec(lmm_system_t sys, + lmm_constraint_t cnst) +{ + lmm_element_t elem; + + xbt_swag_foreach(elem, &cnst->element_set) { + lmm_variable_t var = elem->variable; + s_lmm_element_t *cnsts = var->cnsts; + int i; + for (i = 0; var->visited != sys->visited_counter + && i < var->cnsts_number ; i++) { + if (cnsts[i].constraint != cnst + && !xbt_swag_belongs(cnsts[i].constraint, + &sys->modified_constraint_set)) { + xbt_swag_insert(cnsts[i].constraint, &sys->modified_constraint_set); + lmm_update_modified_set_rec(sys, cnsts[i].constraint); + } + } + var->visited = sys->visited_counter; + } +} + +static void lmm_update_modified_set(lmm_system_t sys, + lmm_constraint_t cnst) +{ + /* nothing to do if selective update isn't active */ + if (sys->selective_update_active + && !xbt_swag_belongs(cnst, &sys->modified_constraint_set)) { + xbt_swag_insert(cnst, &sys->modified_constraint_set); + lmm_update_modified_set_rec(sys, cnst); + } +} + +/** \brief Remove all constraints of the modified_constraint_set. + * + * \param sys the lmm_system_t + */ +static void lmm_remove_all_modified_set(lmm_system_t sys) +{ + if (++sys->visited_counter == 1) { + /* the counter wrapped around, reset each variable->visited */ + lmm_variable_t var; + xbt_swag_foreach(var, &sys->variable_set) + var->visited = 0; + } + xbt_swag_reset(&sys->modified_constraint_set); +} diff --git a/src/surf/maxmin_private.h b/src/surf/maxmin_private.h index f14d003320..2239cd2b3e 100644 --- a/src/surf/maxmin_private.h +++ b/src/surf/maxmin_private.h @@ -7,8 +7,7 @@ #ifndef _SURF_MAXMIN_PRIVATE_H #define _SURF_MAXMIN_PRIVATE_H -//#include "surf/maxmin.h" -#include "surf/solver.h" +#include "surf/maxmin.h" #include "xbt/swag.h" #include "xbt/mallocator.h" diff --git a/src/surf/maxmin_private_.h b/src/surf/maxmin_private_.h new file mode 100644 index 0000000000..bdf6fc4459 --- /dev/null +++ b/src/surf/maxmin_private_.h @@ -0,0 +1,112 @@ +/* Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#ifndef _SURF_MAXMIN_PRIVATE_H +#define _SURF_MAXMIN_PRIVATE_H + +#include "surf/maxmin_.h" +#include "xbt/swag.h" +#include "xbt/mallocator.h" + + + +typedef struct lmm_element { + /* hookup to constraint */ + s_xbt_swag_hookup_t element_set_hookup; + s_xbt_swag_hookup_t active_element_set_hookup; + + lmm_constraint_t constraint; + lmm_variable_t variable; + double value; +} s_lmm_element_t; +#define make_elem_active(elem) xbt_swag_insert_at_head(elem,&(elem->constraint->active_element_set)) +#define make_elem_inactive(elem) xbt_swag_remove(elem,&(elem->constraint->active_element_set)) + +typedef struct lmm_constraint_light { + double remaining_over_usage; + lmm_constraint_t cnst; +} s_lmm_constraint_light_t; + +typedef struct lmm_constraint { + /* hookup to system */ + s_xbt_swag_hookup_t constraint_set_hookup; + s_xbt_swag_hookup_t active_constraint_set_hookup; + s_xbt_swag_hookup_t modified_constraint_set_hookup; + s_xbt_swag_hookup_t saturated_constraint_set_hookup; + + s_xbt_swag_t element_set; /* a list of lmm_element_t */ + s_xbt_swag_t active_element_set; /* a list of lmm_element_t */ + double remaining; + double usage; + double bound; + int shared; + void *id; + int id_int; + double lambda; + double new_lambda; + lmm_constraint_light_t cnst_light; +} s_lmm_constraint_t; + +typedef struct lmm_variable { + /* hookup to system */ + s_xbt_swag_hookup_t variable_set_hookup; + s_xbt_swag_hookup_t saturated_variable_set_hookup; + + s_lmm_element_t *cnsts; + int cnsts_size; + int cnsts_number; + double weight; + double bound; + double value; + void *id; + int id_int; + unsigned visited; /* used by lmm_update_modified_set */ + /* \begin{For Lagrange only} */ + double mu; + double new_mu; + double (*func_f) (struct lmm_variable * var, double x); /* (f) */ + double (*func_fp) (struct lmm_variable * var, double x); /* (f') */ + double (*func_fpi) (struct lmm_variable * var, double x); /* (f')^{-1} */ + /* \end{For Lagrange only} */ +} s_lmm_variable_t; + +typedef struct lmm_system { + int modified; + int selective_update_active; /* flag to update partially the system only selecting changed portions */ + unsigned visited_counter; /* used by lmm_update_modified_set */ + s_xbt_swag_t variable_set; /* a list of lmm_variable_t */ + s_xbt_swag_t constraint_set; /* a list of lmm_constraint_t */ + + s_xbt_swag_t active_constraint_set; /* a list of lmm_constraint_t */ + s_xbt_swag_t modified_constraint_set; /* a list of modified lmm_constraint_t */ + + s_xbt_swag_t saturated_variable_set; /* a list of lmm_variable_t */ + s_xbt_swag_t saturated_constraint_set; /* a list of lmm_constraint_t_t */ + + xbt_swag_t keep_track; + + xbt_mallocator_t variable_mallocator; +} s_lmm_system_t; + +#define extract_variable(sys) xbt_swag_extract(&(sys->variable_set)) +#define extract_constraint(sys) xbt_swag_extract(&(sys->constraint_set)) +#define insert_constraint(sys,cnst) xbt_swag_insert(cnst,&(sys->constraint_set)) +#define remove_variable(sys,var) do {xbt_swag_remove(var,&(sys->variable_set));\ + xbt_swag_remove(var,&(sys->saturated_variable_set));} while(0) +#define remove_constraint(sys,cnst) do {xbt_swag_remove(cnst,&(sys->constraint_set));\ + xbt_swag_remove(cnst,&(sys->saturated_constraint_set));} while(0) +#define make_constraint_active(sys,cnst) xbt_swag_insert(cnst,&(sys->active_constraint_set)) +#define make_constraint_inactive(sys,cnst) \ + do { xbt_swag_remove(cnst, &sys->active_constraint_set); \ + xbt_swag_remove(cnst, &sys->modified_constraint_set); } while (0) + +void lmm_print(lmm_system_t sys); + +extern double (*func_f_def) (lmm_variable_t, double); +extern double (*func_fp_def) (lmm_variable_t, double); +extern double (*func_fpi_def) (lmm_variable_t, double); + +#endif /* _SURF_MAXMIN_PRIVATE_H */ diff --git a/src/surf/network.c b/src/surf/network.c index 9133c1ab8b..04c576314d 100644 --- a/src/surf/network.c +++ b/src/surf/network.c @@ -820,7 +820,7 @@ static void surf_network_model_init_internal(void) surf_action_lmm_update_index_heap); surf_network_model->model_private->modified_set = xbt_swag_new(xbt_swag_offset(comm, generic_lmm_action.action_list_hookup)); - //TOREPAIR: surf_network_model->model_private->maxmin_system->keep_track = surf_network_model->model_private->modified_set; + surf_network_model->model_private->maxmin_system->keep_track = surf_network_model->model_private->modified_set; } surf_network_model->gap_remove = NULL; diff --git a/src/surf/network.cpp b/src/surf/network.cpp index ea5060a573..ab8d902aab 100644 --- a/src/surf/network.cpp +++ b/src/surf/network.cpp @@ -1,33 +1,211 @@ #include "network.hpp" +#include "maxmin_private.h" +#include "simgrid/sg_config.h" -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surfpp_network, surfpp, +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network, surf, "Logging specific to the SURF network module"); +} -//TODO: resolve dependencies -static int TRACE_is_enabled(void) {return 0;} -static void TRACE_surf_host_set_utilization(const char *resource, - const char *category, - double value, - double now, - double delta){} -static void TRACE_surf_link_set_utilization(const char *resource, - const char *category, - double value, - double now, - double delta){} -static double TRACE_last_timestamp_to_dump = 0; +NetworkCm02ModelPtr surf_network_model = NULL; -/********* - * Utils * - *********/ +double sg_sender_gap = 0.0; +double sg_latency_factor = 1.0; /* default value; can be set by model or from command line */ +double sg_bandwidth_factor = 1.0; /* default value; can be set by model or from command line */ +double sg_weight_S_parameter = 0.0; /* default value; can be set by model or from command line */ -static xbt_dict_t gap_lookup = NULL;//TODO: remove static +double sg_tcp_gamma = 0.0; +int sg_network_crosstraffic = 0; /********* * Model * *********/ -void NetworkModel::updateActionsStateLazy(double now, double delta) +/************************************************************************/ +/* New model based on optimizations discussed during Pedro Velho's thesis*/ +/************************************************************************/ +/* @techreport{VELHO:2011:HAL-00646896:1, */ +/* url = {http://hal.inria.fr/hal-00646896/en/}, */ +/* title = {{Flow-level network models: have we reached the limits?}}, */ +/* author = {Velho, Pedro and Schnorr, Lucas and Casanova, Henri and Legrand, Arnaud}, */ +/* type = {Rapport de recherche}, */ +/* institution = {INRIA}, */ +/* number = {RR-7821}, */ +/* year = {2011}, */ +/* month = Nov, */ +/* pdf = {http://hal.inria.fr/hal-00646896/PDF/rr-validity.pdf}, */ +/* } */ +void surf_network_model_init_LegrandVelho(void) +{ + if (surf_network_model) + return; + + surf_network_model = new NetworkCm02Model(); + xbt_dynar_push(model_list, &surf_network_model); + + xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor", + 13.01); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor", + 0.97); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 20537); +} + +/***************************************************************************/ +/* The nice TCP sharing model designed by Loris Marchal and Henri Casanova */ +/***************************************************************************/ +/* @TechReport{ rr-lip2002-40, */ +/* author = {Henri Casanova and Loris Marchal}, */ +/* institution = {LIP}, */ +/* title = {A Network Model for Simulation of Grid Application}, */ +/* number = {2002-40}, */ +/* month = {oct}, */ +/* year = {2002} */ +/* } */ +void surf_network_model_init_CM02(void) +{ + + if (surf_network_model) + return; + + surf_network_model = new NetworkCm02Model(); + xbt_dynar_push(model_list, &surf_network_model); + + xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor", 1.0); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor", + 1.0); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 0.0); +} + +/***************************************************************************/ +/* The models from Steven H. Low */ +/***************************************************************************/ +/* @article{Low03, */ +/* author={Steven H. Low}, */ +/* title={A Duality Model of {TCP} and Queue Management Algorithms}, */ +/* year={2003}, */ +/* journal={{IEEE/ACM} Transactions on Networking}, */ +/* volume={11}, number={4}, */ +/* } */ +void surf_network_model_init_Reno(void) +{ + if (surf_network_model) + return; + + surf_network_model = new NetworkCm02Model(); + xbt_dynar_push(model_list, &surf_network_model); + lmm_set_default_protocol_function(func_reno_f, func_reno_fp, + func_reno_fpi); + surf_network_model->f_networkSolve = lagrange_solve; + + xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor", 10.4); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor", + 0.92); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 8775); +} + + +void surf_network_model_init_Reno2(void) +{ + if (surf_network_model) + return; + + surf_network_model = new NetworkCm02Model(); + xbt_dynar_push(model_list, &surf_network_model); + lmm_set_default_protocol_function(func_reno2_f, func_reno2_fp, + func_reno2_fpi); + surf_network_model->f_networkSolve = lagrange_solve; + + xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor", 10.4); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor", + 0.92); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S_parameter", + 8775); +} + +void surf_network_model_init_Vegas(void) +{ + if (surf_network_model) + return; + + surf_network_model = new NetworkCm02Model(); + xbt_dynar_push(model_list, &surf_network_model); + lmm_set_default_protocol_function(func_vegas_f, func_vegas_fp, + func_vegas_fpi); + surf_network_model->f_networkSolve = lagrange_solve; + + xbt_cfg_setdefault_double(_sg_cfg_set, "network/latency_factor", 10.4); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/bandwidth_factor", + 0.92); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 8775); +} + +NetworkCm02Model::NetworkCm02Model() : NetworkCm02Model("network"){ +} + +NetworkCm02Model::NetworkCm02Model(string name) : Model(name){ + NetworkCm02ActionLmmPtr comm; + + char *optim = xbt_cfg_get_string(_sg_cfg_set, "network/optim"); + int select = + xbt_cfg_get_boolean(_sg_cfg_set, "network/maxmin_selective_update"); + + if (!strcmp(optim, "Full")) { + p_updateMechanism = UM_FULL; + m_selectiveUpdate = select; + } else if (!strcmp(optim, "Lazy")) { + p_updateMechanism = UM_LAZY; + m_selectiveUpdate = 1; + xbt_assert((select == 1) + || + (xbt_cfg_is_default_value + (_sg_cfg_set, "network/maxmin_selective_update")), + "Disabling selective update while using the lazy update mechanism is dumb!"); + } else { + xbt_die("Unsupported optimization (%s) for this model", optim); + } + + if (!p_maxminSystem) + p_maxminSystem = lmm_system_new(m_selectiveUpdate); + + routing_model_create(createResource("__loopback__", + 498000000, NULL, 0.000015, NULL, + SURF_RESOURCE_ON, NULL, + SURF_LINK_FATPIPE, NULL)); + + if (p_updateMechanism == UM_LAZY) { + p_actionHeap = xbt_heap_new(8, NULL); + xbt_heap_set_update_callback(p_actionHeap, surf_action_lmm_update_index_heap); + p_modifiedSet = xbt_swag_new(xbt_swag_offset((*comm), p_actionListHookup)); + p_maxminSystem->keep_track = p_modifiedSet; + } +} + +NetworkCm02LinkLmmPtr NetworkCm02Model::createResource(const char *name, + double bw_initial, + tmgr_trace_t bw_trace, + double lat_initial, + tmgr_trace_t lat_trace, + e_surf_resource_state_t state_initial, + tmgr_trace_t state_trace, + e_surf_link_sharing_policy_t policy, + xbt_dict_t properties) +{ + xbt_assert(!xbt_lib_get_or_null(link_lib, name, SURF_LINK_LEVEL), + "Link '%s' declared several times in the platform file.", + name); + + NetworkCm02LinkLmmPtr nw_link = + new NetworkCm02LinkLmm(this, name, properties, p_maxminSystem, sg_bandwidth_factor * bw_initial, history, + state_initial, state_trace, bw_initial, bw_trace, lat_initial, lat_trace, policy); + + + xbt_lib_set(link_lib, name, SURF_LINK_LEVEL, nw_link); + XBT_DEBUG("Create link '%s'",name); + + return nw_link; +} + +void NetworkCm02Model::updateActionsStateLazy(double now, double delta) { NetworkCm02ActionLmmPtr action; while ((xbt_heap_size(p_actionHeap) > 0) @@ -74,39 +252,288 @@ void NetworkModel::updateActionsStateLazy(double now, double delta) action->setState(SURF_ACTION_DONE); action->heapRemove(p_actionHeap); - gapRemove(action); + action->gapRemove(); } } return; } -void NetworkModel::gapRemove(ActionLmmPtr lmm_action) -{ - xbt_fifo_t fifo; - size_t size; - NetworkCm02ActionLmmPtr action = (NetworkCm02ActionLmmPtr)lmm_action; - - if (sg_sender_gap > 0.0 && action->p_senderLinkName - && action->p_senderFifoItem) { - fifo = - (xbt_fifo_t) xbt_dict_get_or_null(gap_lookup, - action->p_senderLinkName); - xbt_fifo_remove_item(fifo, action->p_senderFifoItem); - size = xbt_fifo_size(fifo); - if (size == 0) { - xbt_fifo_free(fifo); - xbt_dict_remove(gap_lookup, action->p_senderLinkName); - size = xbt_dict_length(gap_lookup); - if (size == 0) { - xbt_dict_free(&gap_lookup); +xbt_dynar_t NetworkCm02Model::getRoute(RoutingEdgePtr src, RoutingEdgePtr dst) +{ + xbt_dynar_t route = NULL; + routing_platf->getRouteAndLatency(src, dst, &route, NULL); + return route; +} + +NetworkCm02ActionPtr NetworkCm02Model::communicate(RoutingEdgePtr src, RoutingEdgePtr dst, + double size, double rate) +{ + unsigned int i; + NetworkCm02LinkLmmPtr link; + int failed = 0; + NetworkCm02ActionLmmPtr action = NULL; + double bandwidth_bound; + double latency = 0.0; + xbt_dynar_t back_route = NULL; + int constraints_per_variable = 0; + + xbt_dynar_t route = xbt_dynar_new(sizeof(RoutingEdgePtr), NULL); + + XBT_IN("(%s,%s,%g,%g)", src->p_name, dst->p_name, size, rate); + + routing_platf->getRouteAndLatency(src, dst, &route, &latency); + xbt_assert(!xbt_dynar_is_empty(route) || latency, + "You're trying to send data from %s to %s but there is no connection at all between these two hosts.", + src->p_name, dst->p_name); + + xbt_dynar_foreach(route, i, link) { + if (link->p_stateCurrent == SURF_RESOURCE_OFF) { + failed = 1; + break; + } + } + if (sg_network_crosstraffic == 1) { + routing_platf->getRouteAndLatency(dst, src, &back_route, NULL); + xbt_dynar_foreach(back_route, i, link) { + if (link->p_stateCurrent == SURF_RESOURCE_OFF) { + failed = 1; + break; } } } + + action = new NetworkCm02ActionLmm(this, size, failed); + +#ifdef HAVE_LATENCY_BOUND_TRACKING + action->m_latencyLimited = 0; +#endif + action->m_weight = action->m_latency = latency; + + xbt_swag_insert(action, action->p_stateSet); + action->m_rate = rate; + if (p_updateMechanism == UM_LAZY) { + action->m_indexHeap = -1; + action->m_lastUpdate = surf_get_clock(); + } + + bandwidth_bound = -1.0; + if (sg_weight_S_parameter > 0) { + xbt_dynar_foreach(route, i, link) { + action->m_weight += + sg_weight_S_parameter / + (link->p_power.peak * link->p_power.scale); + } + } + xbt_dynar_foreach(route, i, link) { + double bb = bandwidthFactor(size) * + (link->p_power.peak * link->p_power.scale); + bandwidth_bound = + (bandwidth_bound < 0.0) ? bb : min(bandwidth_bound, bb); + } + + action->m_latCurrent = action->m_latency; + action->m_latency *= latencyFactor(size); + action->m_rate = bandwidthConstraint(action->m_rate, bandwidth_bound, size); + if (m_haveGap) { + xbt_assert(!xbt_dynar_is_empty(route), + "Using a model with a gap (e.g., SMPI) with a platform without links (e.g. vivaldi)!!!"); + + link = *(NetworkCm02LinkLmmPtr *) xbt_dynar_get_ptr(route, 0); + gapAppend(size, link, action); + XBT_DEBUG("Comm %p: %s -> %s gap=%f (lat=%f)", + action, src->p_name, dst->p_name, action->m_senderGap, + action->m_latency); + } + + constraints_per_variable = xbt_dynar_length(route); + if (back_route != NULL) + constraints_per_variable += xbt_dynar_length(back_route); + + if (action->m_latency > 0) { + action->p_variable = lmm_variable_new(p_maxminSystem, action, 0.0, -1.0, + constraints_per_variable); + if (p_updateMechanism == UM_LAZY) { + // add to the heap the event when the latency is payed + XBT_DEBUG("Added action (%p) one latency event at date %f", action, + action->m_latency + action->m_lastUpdate); + action->heapInsert(p_actionHeap, action->m_latency + action->m_lastUpdate, xbt_dynar_is_empty(route) ? NORMAL : LATENCY); + } + } else + action->p_variable = lmm_variable_new(p_maxminSystem, action, 1.0, -1.0, constraints_per_variable); + + if (action->m_rate < 0) { + lmm_update_variable_bound(p_maxminSystem, action->p_variable, (action->m_latCurrent > 0) ? sg_tcp_gamma / (2.0 * action->m_latCurrent) : -1.0); + } else { + lmm_update_variable_bound(p_maxminSystem, action->p_variable, (action->m_latCurrent > 0) ? min(action->m_rate, sg_tcp_gamma / (2.0 * action->m_latCurrent)) : action->m_rate); + } + + xbt_dynar_foreach(route, i, link) { + lmm_expand(p_maxminSystem, link->p_constraint, action->p_variable, 1.0); + } + + if (sg_network_crosstraffic == 1) { + XBT_DEBUG("Fullduplex active adding backward flow using 5%%"); + xbt_dynar_foreach(back_route, i, link) { + lmm_expand(p_maxminSystem, link->p_constraint, action->p_variable, .05); + } + } + + xbt_dynar_free(&route); + XBT_OUT(); + + return action; +} + +double NetworkCm02Model::latencyFactor(double size) { + return sg_latency_factor; +} + +double NetworkCm02Model::bandwidthFactor(double size) { + return sg_bandwidth_factor; +} + +double NetworkCm02Model::bandwidthConstraint(double rate, double bound, double size) { + return rate; } /************ * Resource * ************/ +NetworkCm02LinkLmm::NetworkCm02LinkLmm(NetworkCm02ModelPtr model, const char *name, xbt_dict_t props, + lmm_system_t system, + double constraint_value, + tmgr_history_t history, + e_surf_resource_state_t state_init, + tmgr_trace_t state_trace, + double metric_peak, + tmgr_trace_t metric_trace, + double lat_initial, + tmgr_trace_t lat_trace, + e_surf_link_sharing_policy_t policy) +: ResourceLmm(model, name, props, system, constraint_value, history, state_init, state_trace, metric_peak, metric_trace) +{ + m_latCurrent = lat_initial; + if (lat_trace) + p_latEvent = tmgr_history_add_trace(history, lat_trace, 0.0, 0, this); + + if (policy == SURF_LINK_FATPIPE) + lmm_constraint_shared(p_constraint); +} + +bool NetworkCm02LinkLmm::isUsed() +{ + return lmm_constraint_used(p_model->p_maxminSystem, p_constraint); +} + +double NetworkCm02Link::getLatency() +{ + return m_latCurrent; +} + +double NetworkCm02LinkLmm::getBandwidth() +{ + return p_power.peak * p_power.scale; +} + +bool NetworkCm02LinkLmm::isShared() +{ + return lmm_constraint_is_shared(p_constraint); +} + +void NetworkCm02LinkLmm::updateState(tmgr_trace_event_t event_type, + double value, double date) +{ + /* printf("[" "%lg" "] Asking to update network card \"%s\" with value " */ + /* "%lg" " for event %p\n", surf_get_clock(), nw_link->name, */ + /* value, event_type); */ + + if (event_type == p_power.event) { + double delta = + sg_weight_S_parameter / value - sg_weight_S_parameter / + (p_power.peak * p_power.scale); + lmm_variable_t var = NULL; + lmm_element_t elem = NULL; + NetworkCm02ActionLmmPtr action = NULL; + + p_power.peak = value; + lmm_update_constraint_bound(p_model->p_maxminSystem, + p_constraint, + sg_bandwidth_factor * + (p_power.peak * p_power.scale)); +#ifdef HAVE_TRACING + TRACE_surf_link_set_bandwidth(date, m_name, sg_bandwidth_factor * p_power.peak * p_power.scale); +#endif + if (sg_weight_S_parameter > 0) { + while ((var = lmm_get_var_from_cnst(p_model->p_maxminSystem, p_constraint, &elem))) { + action = (NetworkCm02ActionLmmPtr) lmm_variable_id(var); + action->m_weight += delta; + if (!action->m_suspended) + lmm_update_variable_weight(p_model->p_maxminSystem, action->p_variable, action->m_weight); + } + } + if (tmgr_trace_event_free(event_type)) + p_power.event = NULL; + } else if (event_type == p_latEvent) { + double delta = value - m_latCurrent; + lmm_variable_t var = NULL; + lmm_element_t elem = NULL; + NetworkCm02ActionLmmPtr action = NULL; + + m_latCurrent = value; + while ((var = lmm_get_var_from_cnst(p_model->p_maxminSystem, p_constraint, &elem))) { + action = (NetworkCm02ActionLmmPtr) lmm_variable_id(var); + action->m_latCurrent += delta; + action->m_weight += delta; + if (action->m_rate < 0) + lmm_update_variable_bound(p_model->p_maxminSystem, action->p_variable, sg_tcp_gamma / (2.0 * action->m_latCurrent)); + else { + lmm_update_variable_bound(p_model->p_maxminSystem, action->p_variable, + min(action->m_rate, sg_tcp_gamma / (2.0 * action->m_latCurrent))); + + if (action->m_rate < sg_tcp_gamma / (2.0 * action->m_latCurrent)) { + XBT_INFO("Flow is limited BYBANDWIDTH"); + } else { + XBT_INFO("Flow is limited BYLATENCY, latency of flow is %f", + action->m_latCurrent); + } + } + if (!action->m_suspended) + lmm_update_variable_weight(p_model->p_maxminSystem, action->p_variable, action->m_weight); + + } + if (tmgr_trace_event_free(event_type)) + p_latEvent = NULL; + } else if (event_type == p_stateEvent) { + if (value > 0) + p_stateCurrent = SURF_RESOURCE_ON; + else { + lmm_constraint_t cnst = p_constraint; + lmm_variable_t var = NULL; + lmm_element_t elem = NULL; + + p_stateCurrent = SURF_RESOURCE_OFF; + while ((var = lmm_get_var_from_cnst(p_model->p_maxminSystem, cnst, &elem))) { + ActionPtr action = (ActionPtr) lmm_variable_id(var); + + if (action->getState() == SURF_ACTION_RUNNING || + action->getState() == SURF_ACTION_READY) { + action->m_finish = date; + action->setState(SURF_ACTION_FAILED); + } + } + } + if (tmgr_trace_event_free(event_type)) + p_stateEvent = NULL; + } else { + XBT_CRITICAL("Unknown event ! \n"); + xbt_abort(); + } + + XBT_DEBUG + ("There were a resource state event, need to update actions related to the constraint (%p)", + p_constraint); + return; +} /********** * Action * @@ -146,4 +573,8 @@ void NetworkCm02ActionLmm::updateRemainingLazy(double now) m_lastUpdate = now; m_lastValue = lmm_variable_getvalue(p_variable); } +void NetworkCm02ActionLmm::recycle() +{ + return; +} diff --git a/src/surf/network.hpp b/src/surf/network.hpp index aa21a7efe1..32fbdaa45e 100644 --- a/src/surf/network.hpp +++ b/src/surf/network.hpp @@ -1,5 +1,7 @@ #include "surf.hpp" #include "xbt/fifo.h" +#include "xbt/graph.h" +#include "surf_routing.hpp" #ifndef SURF_MODEL_NETWORK_H_ #define SURF_MODEL_NETWORK_H_ @@ -7,45 +9,96 @@ /*********** * Classes * ***********/ -class NetworkModel; -typedef NetworkModel *NetworkModelPtr; +class NetworkCm02Model; +typedef NetworkCm02Model *NetworkCm02ModelPtr; class NetworkCm02Link; typedef NetworkCm02Link *NetworkCm02LinkPtr; +class NetworkCm02LinkLmm; +typedef NetworkCm02LinkLmm *NetworkCm02LinkLmmPtr; + class NetworkCm02Action; typedef NetworkCm02Action *NetworkCm02ActionPtr; class NetworkCm02ActionLmm; typedef NetworkCm02ActionLmm *NetworkCm02ActionLmmPtr; +/********* + * Tools * + *********/ +extern NetworkCm02ModelPtr surf_network_model; + + + /********* * Model * *********/ -class NetworkModel : public Model { +class NetworkCm02Model : public Model { public: - NetworkModel(string name) : Model(name) {}; - NetworkCm02LinkPtr createResource(string name); + NetworkCm02Model(string name); + NetworkCm02Model(); + //FIXME:NetworkCm02LinkPtr createResource(string name); + NetworkCm02LinkLmmPtr createResource(const char *name, + double bw_initial, + tmgr_trace_t bw_trace, + double lat_initial, + tmgr_trace_t lat_trace, + e_surf_resource_state_t state_initial, + tmgr_trace_t state_trace, + e_surf_link_sharing_policy_t policy, + xbt_dict_t properties); void updateActionsStateLazy(double now, double delta); - void updateActionsStateFull(double now, double delta); - void gapRemove(ActionLmmPtr action); - - virtual void addTraces() =0; + void updateActionsStateFull(double now, double delta); + virtual void gapAppend(double size, const NetworkCm02LinkLmmPtr link, NetworkCm02ActionLmmPtr action) {}; + NetworkCm02ActionPtr communicate(RoutingEdgePtr src, RoutingEdgePtr dst, + double size, double rate); + xbt_dynar_t getRoute(RoutingEdgePtr src, RoutingEdgePtr dst); //FIXME: kill field? That is done by the routing nowadays + //FIXME: virtual void addTraces() =0; + void (*f_networkSolve)(lmm_system_t) = lmm_solve; + double latencyFactor(double size); + double bandwidthFactor(double size); + double bandwidthConstraint(double rate, double bound, double size); + bool m_haveGap = false; }; /************ * Resource * ************/ -class NetworkCm02Link : public Resource { -public: - NetworkCm02Link(NetworkModelPtr model, const char* name, xbt_dict_t properties) : Resource(model, name, properties) {}; +class NetworkCm02Link : virtual public Resource { +public: + NetworkCm02Link(){}; + NetworkCm02Link(NetworkCm02ModelPtr model, const char* name, xbt_dict_t properties) : Resource(model, name, properties) {}; + virtual double getBandwidth()=0; + double getLatency(); + virtual bool isShared()=0; /* Using this object with the public part of model does not make sense */ - double lat_current; - tmgr_trace_event_t lat_event; + double m_latCurrent; + tmgr_trace_event_t p_latEvent; }; +class NetworkCm02LinkLmm : public ResourceLmm, public NetworkCm02Link { +public: + NetworkCm02LinkLmm(NetworkCm02ModelPtr model, const char *name, xbt_dict_t props, + lmm_system_t system, + double constraint_value, + tmgr_history_t history, + e_surf_resource_state_t state_init, + tmgr_trace_t state_trace, + double metric_peak, + tmgr_trace_t metric_trace, + double lat_initial, + tmgr_trace_t lat_trace, + e_surf_link_sharing_policy_t policy); + bool isShared(); + bool isUsed(); + double getBandwidth(); + void updateState(tmgr_trace_event_t event_type, double value, double date); +}; + + /********** * Action * **********/ @@ -70,6 +123,7 @@ class NetworkCm02ActionLmm : public ActionLmm, public NetworkCm02Action { public: NetworkCm02ActionLmm(ModelPtr model, double cost, bool failed): ActionLmm(model, cost, failed), NetworkCm02Action(model, cost, failed) {}; void updateRemainingLazy(double now); + void recycle(); }; #endif /* SURF_MODEL_NETWORK_H_ */ diff --git a/src/surf/network_constant.cpp b/src/surf/network_constant.cpp new file mode 100644 index 0000000000..fc4babc90d --- /dev/null +++ b/src/surf/network_constant.cpp @@ -0,0 +1,171 @@ +#include "network_constant.hpp" +#include "surf/random_mgr.h" + +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_network); +static random_data_t random_latency = NULL; +static int host_number_int = 0; + +static void netcste_count_hosts(sg_platf_host_cbarg_t h) { + host_number_int++; +} + +/********* + * Model * + *********/ +void surf_network_model_init_Constant() +{ + xbt_assert(surf_network_model == NULL); + surf_network_model = new NetworkConstantModel(); + + if (!random_latency) + random_latency = random_new(RAND, 100, 0.0, 1.0, .125, .034); + + //FIXME:sg_platf_host_add_cb(netcste_count_hosts); + + xbt_dynar_push(model_list, &surf_network_model); + + //FIXME:routing_model_create(NULL); +} + +double NetworkConstantModel::shareResources(double now) +{ + void *_action = NULL; + NetworkConstantActionLmmPtr action = NULL; + double min = -1.0; + + xbt_swag_foreach(_action, p_runningActionSet) { + action = (NetworkConstantActionLmmPtr) _action; + if (action->m_latency > 0) { + if (min < 0) + min = action->m_latency; + else if (action->m_latency < min) + min = action->m_latency; + } + } + + return min; +} + +void NetworkConstantModel::updateActionsState(double now, double delta) +{ + void *_action, *_next_action; + NetworkConstantActionLmmPtr action = NULL; + + xbt_swag_foreach_safe(_action, _next_action, p_runningActionSet) { + action = (NetworkConstantActionLmmPtr) _action; + if (action->m_latency > 0) { + if (action->m_latency > delta) { + double_update(&(action->m_latency), delta); + } else { + action->m_latency = 0.0; + } + } + double_update(&(action->m_remains), + action->m_cost * delta / action->m_latInit); + if (action->m_maxDuration != NO_MAX_DURATION) + double_update(&(action->m_maxDuration), delta); + + if (action->m_remains <= 0) { + action->m_finish = surf_get_clock(); + action->setState(SURF_ACTION_DONE); + } else if ((action->m_maxDuration != NO_MAX_DURATION) + && (action->m_maxDuration <= 0)) { + action->m_finish = surf_get_clock(); + action->setState(SURF_ACTION_DONE); + } + } +} + +NetworkCm02ActionLmmPtr NetworkConstantModel::communicate(RoutingEdgePtr src, RoutingEdgePtr dst, + double size, double rate) +{ + char *src_name = src->p_name; + char *dst_name = dst->p_name; + + XBT_IN("(%s,%s,%g,%g)", src_name, dst_name, size, rate); + NetworkConstantActionLmmPtr action = new NetworkConstantActionLmm(this, sg_latency_factor); + XBT_OUT(); + + return action; +} + +/************ + * Resource * + ************/ +bool NetworkConstantLinkLmm::isUsed() +{ + return 0; +} + +void NetworkConstantLinkLmm::updateState(tmgr_trace_event_t event_type, + double value, double time) +{ + DIE_IMPOSSIBLE; +} + +double NetworkConstantLinkLmm::getBandwidth() +{ + DIE_IMPOSSIBLE; + return -1.0; /* useless since DIE actually abort(), but eclipse prefer to have a useless and harmless return */ +} + +double NetworkConstantLinkLmm::getLatency() +{ + DIE_IMPOSSIBLE; + return -1.0; /* useless since DIE actually abort(), but eclipse prefer to have a useless and harmless return */ +} + +bool NetworkConstantLinkLmm::isShared() +{ + DIE_IMPOSSIBLE; + return -1; /* useless since DIE actually abort(), but eclipse prefer to have a useless and harmless return */ +} + +/********** + * Action * + **********/ + +int NetworkConstantActionLmm::unref() +{ + m_refcount--; + if (!m_refcount) { + xbt_swag_remove(this, p_stateSet); + delete this; + return 1; + } + return 0; +} + +void NetworkConstantActionLmm::cancel() +{ + return; +} + +#ifdef HAVE_TRACING +void NetworkConstantActionLmm::setCategory(const char *category) +{ + //ignore completely the categories in constant model, they are not traced +} +#endif + +void NetworkConstantActionLmm::suspend() +{ + m_suspended = true; +} + +void NetworkConstantActionLmm::resume() +{ + if (m_suspended) + m_suspended = false; +} + +void NetworkConstantActionLmm::recycle() +{ + return; +} + +bool NetworkConstantActionLmm::isSuspended() +{ + return m_suspended; +} + diff --git a/src/surf/network_constant.hpp b/src/surf/network_constant.hpp new file mode 100644 index 0000000000..38736beac4 --- /dev/null +++ b/src/surf/network_constant.hpp @@ -0,0 +1,70 @@ +#include "network.hpp" + +#ifndef NETWORK_CONSTANT_HPP_ +#define NETWORK_CONSTANT_HPP_ + +/*********** + * Classes * + ***********/ +class NetworkConstantModel; +typedef NetworkConstantModel *NetworkConstantModelPtr; + +class NetworkConstantLinkLmm; +typedef NetworkConstantLinkLmm *NetworkConstantLinkLmmPtr; + +class NetworkConstantActionLmm; +typedef NetworkConstantActionLmm *NetworkConstantActionLmmPtr; + +/********* + * Model * + *********/ +class NetworkConstantModel : public NetworkCm02Model { +public: + NetworkConstantModel() : NetworkCm02Model("constant time network") {}; + NetworkCm02LinkLmmPtr createResource(string name); + double shareResources(double now); + void updateActionsState(double now, double delta); + NetworkCm02ActionLmmPtr communicate(RoutingEdgePtr src, RoutingEdgePtr dst, + double size, double rate); + void gapRemove(ActionLmmPtr action); + //FIXME:virtual void addTraces() =0; +}; + +/************ + * Resource * + ************/ +class NetworkConstantLinkLmm : public NetworkCm02LinkLmm { +public: + NetworkConstantLinkLmm(NetworkCm02ModelPtr model, const char* name, xbt_dict_t properties); + bool isUsed(); + void updateState(tmgr_trace_event_t event_type, double value, double date); + double getBandwidth(); + double getLatency(); + bool isShared(); +}; + +/********** + * Action * + **********/ +class NetworkConstantActionLmm : public NetworkCm02ActionLmm { +public: + NetworkConstantActionLmm(NetworkConstantModelPtr model, double latency): + NetworkCm02ActionLmm(model, 0, false), m_latInit(latency) { + m_latency = latency; + if (m_latency <= 0.0) { + p_stateSet = p_model->p_doneActionSet; + xbt_swag_insert(this, p_stateSet); + } + }; + int unref(); + void recycle(); + void cancel(); + void setCategory(const char *category); + void suspend(); + void resume(); + bool isSuspended(); + double m_latInit; + int m_suspended; +}; + +#endif /* NETWORK_CONSTANT_HPP_ */ diff --git a/src/surf/network_gtnets.cpp b/src/surf/network_gtnets.cpp new file mode 100644 index 0000000000..5570c20440 --- /dev/null +++ b/src/surf/network_gtnets.cpp @@ -0,0 +1,108 @@ +#include "network_gtnets.hpp" + +static double time_to_next_flow_completion = -1; + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network_gtnets, surf, + "Logging specific to the SURF network GTNetS module"); + +extern routing_platf_t routing_platf; + +double sg_gtnets_jitter = 0.0; +int sg_gtnets_jitter_seed = 10; + +/********* + * Model * + *********/ + +void newRoute(int src_id, int dst_id, + xbt_dynar_t links, int nb_link) +{ + void *_link; + NetworkGTNetsLinkPtr link; + unsigned int cursor; + int i = 0; + int *gtnets_links; + + XBT_IN("(src_id=%d, dst_id=%d, links=%p, nb_link=%d)", + src_id, dst_id, links, nb_link); + + /* Build the list of gtnets link IDs */ + gtnets_links = xbt_new0(int, nb_link); + i = 0; + xbt_dynar_foreach(links, cursor, _link) { + link = (NetworkGTNetsLinkPtr) _link; + gtnets_links[i++] = link->m_id; + } + + if (gtnets_add_route(src_id, dst_id, gtnets_links, nb_link)) { + xbt_die("Cannot create GTNetS route"); + } + XBT_OUT(); +} + +void newRouteOnehop(int src_id, int dst_id, + NetworkGTNetsLinkPtr link) +{ + if (gtnets_add_onehop_route(src_id, dst_id, link->m_id)) { + xbt_die("Cannot create GTNetS route"); + } +} + +int NetworkGTNetsModel::addLink(ind id, double bandwidth, double latency) +{ + double bw = bandwidth * 8; //Bandwidth in bits (used in GTNETS). + + map::iterator iter = p_links.find(id); + xbt_assert((iter == p_links.end()), "Link %d already exists", id); + + if(iter == p_links.end()) { + GTNETS_Link* link= new GTNETS_Link(id); + p_links[id] = link; + } + + XBT_DEBUG("Creating a new P2P, linkid %d, bandwidth %gl, latency %gl", id, bandwidth, latency); + p_gtnetsLinks_[id] = new Linkp2p(bw, latency); + if(jitter_ > 0){ + XBT_DEBUG("Using jitter %f, and seed %u", jitter_, jitter_seed_); + double min = -1*jitter_*latency; + double max = jitter_*latency; + uniform_jitter_generator_[id] = new Uniform(min,max); + gtnets_links_[id]->Jitter((const Random &) *(uniform_jitter_generator_[id])); + } + + return 0; +} + +/************ + * Resource * + ************/ +NetworkGTNetsLink::NetworkGTNetsLink(NetworkGTNetsModelPtr model, const char* name, double bw, double lat, xbt_dict_t properties) + :NetworkCm02Link(model, name, properties), m_bwCurrent(bw), m_latCurrent(lat) +{ + + static int link_count = -1; + + if (xbt_lib_get_or_null(link_lib, name, SURF_LINK_LEVEL)) { + return; + } + + XBT_DEBUG("Scanning link name %s", name); + + link_count++; + + XBT_DEBUG("Adding new link, linkid %d, name %s, latency %g, bandwidth %g", + link_count, name, lat, bw); + + + + if (gtnets_add_link(link_count, bw, lat)) { + xbt_die("Cannot create GTNetS link"); + } + m_id = link_count; + + xbt_lib_set(link_lib, name, SURF_LINK_LEVEL, this); +} + +/********** + * Action * + **********/ diff --git a/src/surf/network_gtnets.hpp b/src/surf/network_gtnets.hpp new file mode 100644 index 0000000000..a2af26dade --- /dev/null +++ b/src/surf/network_gtnets.hpp @@ -0,0 +1,124 @@ +#include "network.hpp" + +#ifndef NETWORK_GTNETS_HPP_ +#define NETWORK_GTNETS_HPP_ + +#include "simulator.h" // Definitions for the Simulator Object +#include "node.h" // Definitions for the Node Object +#include "linkp2p.h" // Definitions for point-to-point link objects +#include "ratetimeparse.h" // Definitions for Rate and Time objects +#include "application-tcpserver.h" // Definitions for TCPServer application +#include "application-tcpsend.h" // Definitions for TCP Sending application +#include "tcp-tahoe.h" // Definitions for TCP Tahoe +#include "tcp-reno.h" +#include "tcp-newreno.h" +#include "event.h" +#include "routing-manual.h" +#include "red.h" + +xbt_dict_t network_card_ids; + +/*********** + * Classes * + ***********/ +class NetworkGTNetsModel; +typedef NetworkGTNetsModel *NetworkGTNetsModelPtr; + +class NetworkGTNetsLink; +typedef NetworkGTNetsLink *NetworkGTNetsLinkPtr; + +class NetworkGTNetsAction; +typedef NetworkGTNetsAction *NetworkGTNetsActionPtr; + +class NetworkGTNetsActionLmm; +typedef NetworkGTNetsActionLmm *NetworkGTNetsActionLmmPtr; + +/********* + * Model * + *********/ +class NetworkGTNetsModel : public NetworkCm02Model { +public: + NetworkGTNetsModel() : NetworkCm02Model("constant time network") {}; + int addLink(int id, double bandwidth, double latency); + int addOnehop_route(int src, int dst, int link); + int addRoute(int src, int dst, int *links, int nlink); + int addRouter(int id); + int createFlow(int src, int dst, long datasize, void *metadata); + double getTimeToNextFlowCompletion(); + int runUntilNextFlowCompletion(void ***metadata, + int *number_of_flows); + int run(double deltat); + // returns the total received by the TCPServer peer of the given action + double gtNetsGetFlowRx(void *metadata); + void createGTNetsTopology(); + void printTopology(); + void setJitter(double); + void setJitterSeed(int); +private: + void addNodes(); + void nodeConnect(); + + bool nodeInclude(int); + bool linkInclude(int); + Simulator *p_sim; + GTNETS_Topology *p_topo; + RoutingManual *p_rm; + REDQueue *p_redQueue; + int m_nnode; + int m_isTopology; + int m_nflow; + double m_jitter; + int m_jitterSeed; + map p_uniformJitterGenerator; + + map p_gtnetsServers; + map p_gtnetsClients; + map p_gtnetsLinks_; + map p_gtnetsNodes; + map p_gtnetsActionToFlow; + + map p_gtnetsMetadata; + + // From Topology + int m_nodeID; + map p_links; + vector p_nodes; + map p_hosts; //hostid->nodeid + set p_routers; +}; + +/************ + * Resource * + ************/ +class NetworkGTNetsLink : public NetworkCm02Link { +public: + NetworkGTNetsLink(NetworkGTNetsModelPtr model, const char* name, double bw, double lat, xbt_dict_t properties); + /* Using this object with the public part of + model does not make sense */ + double m_bwCurrent; + double m_latCurrent; + int m_id; +}; + +/********** + * Action * + **********/ +class NetworkGTNetsAction : public NetworkCm02Action { +public: + NetworkGTNetsAction(NetworkGTNetsModelPtr model, double latency){}; + + double m_latency; + double m_latCurrent; +#ifdef HAVE_TRACING + int m_lastRemains; +#endif + lmm_variable_t p_variable; + double m_rate; + int m_suspended; +#ifdef HAVE_TRACING + RoutingEdgePtr src; + RoutingEdgePtr dst; +#endif //HAVE_TRACING +}; + +#endif /* NETWORK_GTNETS_HPP_ */ diff --git a/src/surf/network_ns3.c b/src/surf/network_ns3.c index 9e0707dabe..e180da04f3 100644 --- a/src/surf/network_ns3.c +++ b/src/surf/network_ns3.c @@ -5,8 +5,7 @@ * under the terms of the license (GNU LGPL) which comes with this package. */ #include "surf_private.h" -//#include "surf/maxmin.h" -#include "surf/solver.h" +#include "surf/maxmin.h" #include "surf/ns3/ns3_interface.h" #include "xbt/lib.h" #include "surf/network_ns3_private.h" diff --git a/src/surf/network_smpi.cpp b/src/surf/network_smpi.cpp new file mode 100644 index 0000000000..10d2e6247b --- /dev/null +++ b/src/surf/network_smpi.cpp @@ -0,0 +1,196 @@ +#include "network_smpi.hpp" +#include "simgrid/sg_config.h" + +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_network); + +xbt_dynar_t smpi_bw_factor = NULL; +xbt_dynar_t smpi_lat_factor = NULL; + +typedef struct s_smpi_factor *smpi_factor_t; +typedef struct s_smpi_factor { + long factor; + double value; +} s_smpi_factor_t; + +xbt_dict_t gap_lookup = NULL; + +static int factor_cmp(const void *pa, const void *pb) +{ + return (((s_smpi_factor_t*)pa)->factor > ((s_smpi_factor_t*)pb)->factor); +} + + +static xbt_dynar_t parse_factor(const char *smpi_coef_string) +{ + char *value = NULL; + unsigned int iter = 0; + s_smpi_factor_t fact; + xbt_dynar_t smpi_factor, radical_elements, radical_elements2 = NULL; + + smpi_factor = xbt_dynar_new(sizeof(s_smpi_factor_t), NULL); + radical_elements = xbt_str_split(smpi_coef_string, ";"); + xbt_dynar_foreach(radical_elements, iter, value) { + + radical_elements2 = xbt_str_split(value, ":"); + if (xbt_dynar_length(radical_elements2) != 2) + xbt_die("Malformed radical for smpi factor!"); + fact.factor = atol(xbt_dynar_get_as(radical_elements2, 0, char *)); + fact.value = atof(xbt_dynar_get_as(radical_elements2, 1, char *)); + xbt_dynar_push_as(smpi_factor, s_smpi_factor_t, fact); + XBT_DEBUG("smpi_factor:\t%ld : %f", fact.factor, fact.value); + xbt_dynar_free(&radical_elements2); + } + xbt_dynar_free(&radical_elements); + iter=0; + xbt_dynar_sort(smpi_factor, &factor_cmp); + xbt_dynar_foreach(smpi_factor, iter, fact) { + XBT_DEBUG("ordered smpi_factor:\t%ld : %f", fact.factor, fact.value); + + } + return smpi_factor; +} + +/********* + * Model * + *********/ + +/************************************************************************/ +/* New model based on LV08 and experimental results of MPI ping-pongs */ +/************************************************************************/ +/* @Inproceedings{smpi_ipdps, */ +/* author={Pierre-Nicolas Clauss and Mark Stillwell and Stéphane Genaud and Frédéric Suter and Henri Casanova and Martin Quinson}, */ +/* title={Single Node On-Line Simulation of {MPI} Applications with SMPI}, */ +/* booktitle={25th IEEE International Parallel and Distributed Processing Symposium (IPDPS'11)}, */ +/* address={Anchorage (Alaska) USA}, */ +/* month=may, */ +/* year={2011} */ +/* } */ +void surf_network_model_init_SMPI(void) +{ + + if (surf_network_model) + return; + surf_network_model = new NetworkSmpiModel(); + + xbt_dynar_push(model_list, &surf_network_model); + + xbt_cfg_setdefault_double(_sg_cfg_set, "network/sender_gap", 10e-6); + xbt_cfg_setdefault_double(_sg_cfg_set, "network/weight_S", 8775); +} + +void NetworkSmpiModel::gapAppend(double size, const NetworkCm02LinkLmmPtr link, NetworkCm02ActionLmmPtr action) +{ + const char *src = link->m_name; + xbt_fifo_t fifo; + //surf_action_network_CM02_t last_action; + //double bw; + + if (sg_sender_gap > 0.0) { + if (!gap_lookup) { + gap_lookup = xbt_dict_new(); + } + fifo = (xbt_fifo_t) xbt_dict_get_or_null(gap_lookup, src); + action->m_senderGap = 0.0; + if (fifo && xbt_fifo_size(fifo) > 0) { + /* Compute gap from last send */ + /*last_action = + (surf_action_network_CM02_t) + xbt_fifo_get_item_content(xbt_fifo_get_last_item(fifo));*/ + // bw = net_get_link_bandwidth(link); + action->m_senderGap = sg_sender_gap; + /* max(sg_sender_gap,last_action->sender.size / bw);*/ + action->m_latency += action->m_senderGap; + } + /* Append action as last send */ + /*action->sender.link_name = link->lmm_resource.generic_resource.name; + fifo = + (xbt_fifo_t) xbt_dict_get_or_null(gap_lookup, + action->sender.link_name); + if (!fifo) { + fifo = xbt_fifo_new(); + xbt_dict_set(gap_lookup, action->sender.link_name, fifo, NULL); + } + action->sender.fifo_item = xbt_fifo_push(fifo, action);*/ + action->m_senderSize = size; + } +} + +void NetworkSmpiModel::gapRemove(ActionLmmPtr lmm_action) +{ + xbt_fifo_t fifo; + size_t size; + NetworkCm02ActionLmmPtr action = (NetworkCm02ActionLmmPtr)(lmm_action); + + if (sg_sender_gap > 0.0 && action->p_senderLinkName + && action->p_senderFifoItem) { + fifo = + (xbt_fifo_t) xbt_dict_get_or_null(gap_lookup, + action->p_senderLinkName); + xbt_fifo_remove_item(fifo, action->p_senderFifoItem); + size = xbt_fifo_size(fifo); + if (size == 0) { + xbt_fifo_free(fifo); + xbt_dict_remove(gap_lookup, action->p_senderLinkName); + size = xbt_dict_length(gap_lookup); + if (size == 0) { + xbt_dict_free(&gap_lookup); + } + } + } +} + +double NetworkSmpiModel::latencyFactor(double size) +{ + if (!smpi_bw_factor) + smpi_bw_factor = + parse_factor(sg_cfg_get_string("smpi/bw_factor")); + + unsigned int iter = 0; + s_smpi_factor_t fact; + double current=1.0; + xbt_dynar_foreach(smpi_bw_factor, iter, fact) { + if (size <= fact.factor) { + XBT_DEBUG("%lf <= %ld return %f", size, fact.factor, current); + return current; + }else + current=fact.value; + } + XBT_DEBUG("%lf > %ld return %f", size, fact.factor, current); + + return current; +} +double NetworkSmpiModel::bandwidthFactor(double size) +{ + if (!smpi_lat_factor) + smpi_lat_factor = + parse_factor(sg_cfg_get_string("smpi/lat_factor")); + + unsigned int iter = 0; + s_smpi_factor_t fact; + double current=1.0; + xbt_dynar_foreach(smpi_lat_factor, iter, fact) { + if (size <= fact.factor) { + XBT_DEBUG("%lf <= %ld return %f", size, fact.factor, current); + return current; + }else + current=fact.value; + } + XBT_DEBUG("%lf > %ld return %f", size, fact.factor, current); + + return current; +} + +double NetworkSmpiModel::bandwidthConstraint(double rate, double bound, double size) +{ + return rate < 0 ? bound : min(bound, rate * bandwidthFactor(size)); +} + +/************ + * Resource * + ************/ + + + +/********** + * Action * + **********/ diff --git a/src/surf/network_smpi.hpp b/src/surf/network_smpi.hpp new file mode 100644 index 0000000000..beae8e2286 --- /dev/null +++ b/src/surf/network_smpi.hpp @@ -0,0 +1,71 @@ +#include "network.hpp" + +/*********** + * Classes * + ***********/ + +class NetworkSmpiModel; +typedef NetworkSmpiModel *NetworkSmpiModelPtr; + +class NetworkSmpiLink; +typedef NetworkSmpiLink *NetworkSmpiLinkPtr; + +class NetworkSmpiLinkLmm; +typedef NetworkSmpiLinkLmm *NetworkSmpiLinkLmmPtr; + +class NetworkSmpiAction; +typedef NetworkSmpiAction *NetworkSmpiActionPtr; + +class NetworkSmpiActionLmm; +typedef NetworkSmpiActionLmm *NetworkSmpiActionLmmPtr; + +/********* + * Tools * + *********/ + +/********* + * Model * + *********/ + +class NetworkSmpiModel : public NetworkCm02Model { +public: + NetworkSmpiModel(){}; + void gapAppend(double size, const NetworkCm02LinkLmmPtr link, NetworkCm02ActionLmmPtr action); + void gapRemove(ActionLmmPtr action); + double latencyFactor(double size); + double bandwidthFactor(double size); + double bandwidthConstraint(double rate, double bound, double size); + void communicateCallBack() {}; +}; + + +/************ + * Resource * + ************/ + +class NetworkSmpiLinkLmm : public NetworkCm02LinkLmm { +public: + NetworkSmpiLinkLmm(NetworkSmpiModelPtr model, const char *name, xbt_dict_t props, + lmm_system_t system, + double constraint_value, + tmgr_history_t history, + e_surf_resource_state_t state_init, + tmgr_trace_t state_trace, + double metric_peak, + tmgr_trace_t metric_trace, + double lat_initial, + tmgr_trace_t lat_trace, + e_surf_link_sharing_policy_t policy); +}; + + +/********** + * Action * + **********/ + +class NetworkSmpiActionLmm : public NetworkCm02ActionLmm { +public: + NetworkSmpiActionLmm(ModelPtr model, double cost, bool failed); +}; + + diff --git a/src/surf/new_model.c b/src/surf/new_model.c index 35e725ec34..3881a7458a 100644 --- a/src/surf/new_model.c +++ b/src/surf/new_model.c @@ -20,13 +20,19 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_new_model, surf, surf_model_t surf_new_model = NULL; lmm_system_t new_model_maxmin_system = NULL; +/*FIXME: static int new_model_selective_update = 0; static xbt_swag_t new_model_running_action_set_that_does_not_need_being_checked = NULL; +*/ #define GENERIC_LMM_ACTION(action) action->generic_lmm_action #define GENERIC_ACTION(action) GENERIC_LMM_ACTION(action).generic_action +void surf_new_model_init_default(void){} + +//FIXME:UPDATE FOR SURF++ +#ifdef UPDATE_FOR_SURFPP static void new_model_action_state_set(surf_action_t action, e_surf_action_state_t state); static surf_action_t new_model_action_execute () @@ -179,3 +185,5 @@ void surf_new_model_init_default(void) xbt_dynar_push(model_list, &surf_new_model); } + +#endif diff --git a/src/surf/storage.cpp b/src/surf/storage.cpp new file mode 100644 index 0000000000..771091be39 --- /dev/null +++ b/src/surf/storage.cpp @@ -0,0 +1,639 @@ +#include "storage.hpp" +#include "surf_private.h" + +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_storage, surf, + "Logging specific to the SURF storage module"); +} + +xbt_lib_t storage_lib; +int ROUTING_STORAGE_LEVEL; //Routing for storagelevel +int ROUTING_STORAGE_HOST_LEVEL; +int SURF_STORAGE_LEVEL; +xbt_lib_t storage_type_lib; +int ROUTING_STORAGE_TYPE_LEVEL; //Routing for storage_type level + +static xbt_dynar_t storage_list; + +xbt_dynar_t mount_list = NULL; /* temporary store of current mount storage */ +StorageModelPtr surf_storage_model = NULL; + +lmm_system_t storage_maxmin_system = NULL; +static int storage_selective_update = 0; +static xbt_swag_t storage_running_action_set_that_does_not_need_being_checked = NULL; + +void storage_register_callbacks() { + + /*FIXME:ROUTING_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,xbt_free); + ROUTING_STORAGE_HOST_LEVEL = xbt_lib_add_level(storage_lib,routing_storage_host_free); + ROUTING_STORAGE_TYPE_LEVEL = xbt_lib_add_level(storage_type_lib,routing_storage_type_free); + SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_storage_resource_free); + + sg_platf_storage_add_cb(storage_parse_storage); + sg_platf_mstorage_add_cb(storage_parse_mstorage); + sg_platf_storage_type_add_cb(storage_parse_storage_type); + sg_platf_mount_add_cb(storage_parse_mount);*/ +} + +/*********** + * PARSING * + ***********/ + +static void parse_storage_init(sg_platf_storage_cbarg_t storage) +{ + void* stype = xbt_lib_get_or_null(storage_type_lib, + storage->type_id, + ROUTING_STORAGE_TYPE_LEVEL); + if(!stype) xbt_die("No storage type '%s'",storage->type_id); + + // if storage content is not specified use the content of storage_type if exist + if(!strcmp(storage->content,"") && strcmp(((storage_type_t) stype)->content,"")){ + storage->content = ((storage_type_t) stype)->content; + XBT_DEBUG("For disk '%s' content is empty, use the content of storage type '%s'",storage->id,((storage_type_t) stype)->type_id); + } + + XBT_DEBUG("SURF storage create resource\n\t\tid '%s'\n\t\ttype '%s' \n\t\tmodel '%s' \n\t\tcontent '%s'\n\t\tproperties '%p'\n", + storage->id, + ((storage_type_t) stype)->model, + ((storage_type_t) stype)->type_id, + storage->content, + ((storage_type_t) stype)->properties); + + surf_storage_model->createResource(storage->id, ((storage_type_t) stype)->model, + ((storage_type_t) stype)->type_id, + storage->content); +} + +static void parse_mstorage_init(sg_platf_mstorage_cbarg_t mstorage) +{ + XBT_DEBUG("parse_mstorage_init"); +} + +static void parse_storage_type_init(sg_platf_storage_type_cbarg_t storagetype_) +{ + XBT_DEBUG("parse_storage_type_init"); +} + +static void parse_mount_init(sg_platf_mount_cbarg_t mount) +{ + XBT_DEBUG("parse_mount_init"); +} + +static void storage_parse_storage(sg_platf_storage_cbarg_t storage) +{ + xbt_assert(!xbt_lib_get_or_null(storage_lib, storage->id,ROUTING_STORAGE_LEVEL), + "Reading a storage, processing unit \"%s\" already exists", storage->id); + + // Verification of an existing type_id +#ifndef NDEBUG + void* storage_type = xbt_lib_get_or_null(storage_type_lib, storage->type_id,ROUTING_STORAGE_TYPE_LEVEL); +#endif + xbt_assert(storage_type,"Reading a storage, type id \"%s\" does not exists", storage->type_id); + + XBT_DEBUG("ROUTING Create a storage name '%s' with type_id '%s' and content '%s'", + storage->id, + storage->type_id, + storage->content); + + xbt_lib_set(storage_lib, + storage->id, + ROUTING_STORAGE_LEVEL, + (void *) xbt_strdup(storage->type_id)); +} + +static xbt_dict_t parse_storage_content(char *filename, size_t *used_size) +{ + *used_size = 0; + if ((!filename) || (strcmp(filename, "") == 0)) + return NULL; + + xbt_dict_t parse_content = xbt_dict_new_homogeneous(NULL); + FILE *file = NULL; + + file = surf_fopen(filename, "r"); + xbt_assert(file != NULL, "Cannot open file '%s' (path=%s)", filename, + xbt_str_join(surf_path, ":")); + + char *line = NULL; + size_t len = 0; + ssize_t read; + char path[1024]; + size_t size; + + + while ((read = xbt_getline(&line, &len, file)) != -1) { + if (read){ + if(sscanf(line,"%s %zu",path, &size)==2) { + *used_size += size; + xbt_dict_set(parse_content,path,(void*) size,NULL); + } else { + xbt_die("Be sure of passing a good format for content file.\n"); + } + } + } + free(line); + fclose(file); + return parse_content; +} + +static void storage_parse_storage_type(sg_platf_storage_type_cbarg_t storage_type) +{ + xbt_assert(!xbt_lib_get_or_null(storage_type_lib, storage_type->id,ROUTING_STORAGE_TYPE_LEVEL), + "Reading a storage type, processing unit \"%s\" already exists", storage_type->id); + + storage_type_t stype = xbt_new0(s_storage_type_t, 1); + stype->model = xbt_strdup(storage_type->model); + stype->properties = storage_type->properties; + stype->content = xbt_strdup(storage_type->content); + stype->type_id = xbt_strdup(storage_type->id); + stype->size = storage_type->size * 1000000000; /* storage_type->size is in Gbytes and stype->sizeis in bytes */ + + XBT_DEBUG("ROUTING Create a storage type id '%s' with model '%s' content '%s'", + stype->type_id, + stype->model, + storage_type->content); + + xbt_lib_set(storage_type_lib, + stype->type_id, + ROUTING_STORAGE_TYPE_LEVEL, + (void *) stype); +} +static void storage_parse_mstorage(sg_platf_mstorage_cbarg_t mstorage) +{ + THROW_UNIMPLEMENTED; +// mount_t mnt = xbt_new0(s_mount_t, 1); +// mnt->id = xbt_strdup(mstorage->type_id); +// mnt->name = xbt_strdup(mstorage->name); +// +// if(!mount_list){ +// XBT_DEBUG("Creata a Mount list for %s",A_surfxml_host_id); +// mount_list = xbt_dynar_new(sizeof(char *), NULL); +// } +// xbt_dynar_push(mount_list,(void *) mnt); +// free(mnt->id); +// free(mnt->name); +// xbt_free(mnt); +// XBT_DEBUG("ROUTING Mount a storage name '%s' with type_id '%s'",mstorage->name, mstorage->id); +} + +static void mount_free(void *p) +{ + mount_t mnt = (mount_t) p; + xbt_free(mnt->name); +} + +static void storage_parse_mount(sg_platf_mount_cbarg_t mount) +{ + // Verification of an existing storage +#ifndef NDEBUG + void* storage = xbt_lib_get_or_null(storage_lib, mount->id,ROUTING_STORAGE_LEVEL); +#endif + xbt_assert(storage,"Disk id \"%s\" does not exists", mount->id); + + XBT_DEBUG("ROUTING Mount '%s' on '%s'",mount->id, mount->name); + + s_mount_t mnt; + mnt.id = surf_storage_resource_priv(surf_storage_resource_by_name(mount->id)); + mnt.name = xbt_strdup(mount->name); + + if(!mount_list){ + //FIXME:XBT_DEBUG("Create a Mount list for %s",A_surfxml_host_id); + mount_list = xbt_dynar_new(sizeof(s_mount_t), mount_free); + } + xbt_dynar_push(mount_list,&mnt); +} + +static XBT_INLINE void routing_storage_type_free(void *r) +{ + storage_type_t stype = (storage_type_t) r; + free(stype->model); + free(stype->type_id); + free(stype->content); + xbt_dict_free(&(stype->properties)); + free(stype); +} + +static XBT_INLINE void surf_storage_resource_free(void *r) +{ + // specific to storage + StoragePtr storage = (StoragePtr) r; + xbt_dict_free(&storage->p_content); + xbt_dynar_free(&storage->p_writeActions); + // generic resource + delete storage; +} + +static XBT_INLINE void routing_storage_host_free(void *r) +{ + xbt_dynar_t dyn = (xbt_dynar_t) r; + xbt_dynar_free(&dyn); +} + +/********* + * Model * + *********/ + +void surf_storage_model_init_default(void) +{ + new StorageModel(); +} + +StorageModel::StorageModel() : Model("Storage"){ + StorageActionLmm action; + storage_running_action_set_that_does_not_need_being_checked = + xbt_swag_new(xbt_swag_offset(action, p_stateHookup)); + + if (!storage_maxmin_system) { + storage_maxmin_system = lmm_system_new(storage_selective_update); + } + xbt_dynar_push(model_list, this); + + sg_platf_storage_add_cb(parse_storage_init); + sg_platf_storage_type_add_cb(parse_storage_type_init); + sg_platf_mstorage_add_cb(parse_mstorage_init); + sg_platf_mount_add_cb(parse_mount_init); + + ROUTING_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,xbt_free); + ROUTING_STORAGE_HOST_LEVEL = xbt_lib_add_level(storage_lib,routing_storage_host_free); + ROUTING_STORAGE_TYPE_LEVEL = xbt_lib_add_level(storage_type_lib,routing_storage_type_free); + SURF_STORAGE_LEVEL = xbt_lib_add_level(storage_lib,surf_storage_resource_free); + + sg_platf_storage_add_cb(storage_parse_storage); + sg_platf_mstorage_add_cb(storage_parse_mstorage); + sg_platf_storage_type_add_cb(storage_parse_storage_type); + sg_platf_mount_add_cb(storage_parse_mount); +} + + +StorageModel::~StorageModel(){ + lmm_system_free(storage_maxmin_system); + storage_maxmin_system = NULL; + + surf_storage_model = NULL; + + xbt_dynar_free(&storage_list); + + xbt_swag_free(storage_running_action_set_that_does_not_need_being_checked); + storage_running_action_set_that_does_not_need_being_checked = NULL; +} + +StoragePtr StorageModel::createResource(const char* id, const char* model, const char* type_id, const char* content_name) +{ + + xbt_assert(!surf_storage_resource_priv(surf_storage_resource_by_name(id)), + "Storage '%s' declared several times in the platform file", + id); + + StoragePtr storage ;//= new Storage(); + + storage_type_t storage_type = (storage_type_t) xbt_lib_get_or_null(storage_type_lib, type_id,ROUTING_STORAGE_TYPE_LEVEL); + double Bread = atof((char*)xbt_dict_get(storage_type->properties, "Bread")); + double Bwrite = atof((char*)xbt_dict_get(storage_type->properties, "Bwrite")); + double Bconnection = atof((char*)xbt_dict_get(storage_type->properties, "Bconnection")); + XBT_DEBUG("Create resource with Bconnection '%f' Bread '%f' Bwrite '%f' and Size '%lu'", Bconnection, Bread, Bwrite, (unsigned long)storage_type->size); + storage->p_constraint = lmm_constraint_new(storage_maxmin_system, storage, Bconnection); + /* TOREPAIR: storage->constraint = lmm_constraint_new(storage_maxmin_system, storage, Bconnection); + storage->constraint_read = lmm_constraint_new(storage_maxmin_system, storage, Bread); + storage->constraint_write = lmm_constraint_new(storage_maxmin_system, storage, Bwrite);*/ + storage->p_content = parseContent((char*)content_name, &(storage->m_usedSize)); + storage->m_size = storage_type->size; + + xbt_lib_set(storage_lib, id, SURF_STORAGE_LEVEL, storage); + + XBT_DEBUG("SURF storage create resource\n\t\tid '%s'\n\t\ttype '%s' \n\t\tmodel '%s' \n\t\tproperties '%p'\n\t\tBread '%f'\n", + id, + model, + type_id, + storage_type->properties, + Bread); + + if(!storage_list) storage_list=xbt_dynar_new(sizeof(char *),NULL); + xbt_dynar_push(storage_list, &storage); + + return storage; +} + +double StorageModel::shareResources(double now) +{ + XBT_DEBUG("storage_share_resources %f", now); + StorageActionLmm action; + unsigned int i, j; + StoragePtr storage; + StorageActionLmmPtr write_action; + + double min_completion = shareResourcesMaxMin(p_runningActionSet, + xbt_swag_offset(action, p_variable), + storage_maxmin_system, lmm_solve); + + double rate; + // Foreach disk + xbt_dynar_foreach(storage_list,i,storage) + { + rate = 0; + // Foreach write action on disk + xbt_dynar_foreach(storage->p_writeActions, j, write_action) + { + rate += lmm_variable_getvalue(write_action->p_variable); + } + if(rate > 0) + min_completion = MIN(min_completion, (storage->m_size-storage->m_usedSize)/rate); + } + + return min_completion; +} + +void StorageModel::updateActionsState(double now, double delta) +{ + void *_action, *_next_action; + StorageActionLmmPtr action = NULL; + + // Update the disk usage + // Update the file size + // For each action of type write + xbt_swag_foreach_safe(_action, _next_action, p_runningActionSet) { + action = (StorageActionLmmPtr) _action; + if(action->m_type == WRITE) + { + double rate = lmm_variable_getvalue(action->p_variable); + /* Hack to avoid rounding differences between x86 and x86_64 + * (note that the next sizes are of type size_t). */ + long incr = delta * rate + MAXMIN_PRECISION; + action->p_storage->m_usedSize += incr; // disk usage + action->p_file->size += incr; // file size + } + } + + xbt_swag_foreach_safe(_action, _next_action, p_runningActionSet) { + action = (StorageActionLmmPtr) _action; + + double_update(&action->m_remains, + lmm_variable_getvalue(action->p_variable) * delta); + + if (action->m_maxDuration != NO_MAX_DURATION) + double_update(&action->m_maxDuration, delta); + + if(action->m_remains > 0 && + lmm_get_variable_weight(action->p_variable) > 0 && + action->p_storage->m_usedSize == action->p_storage->m_size) + { + action->m_finish = surf_get_clock(); + action->setState(SURF_ACTION_FAILED); + } else if ((action->m_remains <= 0) && + (lmm_get_variable_weight(action->p_variable) > 0)) + { + action->m_finish = surf_get_clock(); + action->setState(SURF_ACTION_DONE); + } else if ((action->m_maxDuration != NO_MAX_DURATION) && + (action->m_maxDuration <= 0)) + { + action->m_finish = surf_get_clock(); + action->setState(SURF_ACTION_DONE); + } + } + + return; +} + +xbt_dict_t StorageModel::parseContent(char *filename, size_t *used_size) +{ + *used_size = 0; + if ((!filename) || (strcmp(filename, "") == 0)) + return NULL; + + xbt_dict_t parse_content = xbt_dict_new_homogeneous(NULL); + FILE *file = NULL; + + file = surf_fopen(filename, "r"); + xbt_assert(file != NULL, "Cannot open file '%s' (path=%s)", filename, + xbt_str_join(surf_path, ":")); + + char *line = NULL; + size_t len = 0; + ssize_t read; + char path[1024]; + size_t size; + + + while ((read = xbt_getline(&line, &len, file)) != -1) { + if (read){ + if(sscanf(line,"%s %zu",path, &size)==2) { + *used_size += size; + xbt_dict_set(parse_content,path,(void*) size,NULL); + } else { + xbt_die("Be sure of passing a good format for content file.\n"); + } + } + } + free(line); + fclose(file); + return parse_content; +} + +/************ + * Resource * + ************/ + +Storage::Storage(StorageModelPtr model, const char* name, xbt_dict_t properties) { + p_writeActions = xbt_dynar_new(sizeof(char *),NULL); +} + +bool Storage::isUsed() +{ + THROW_UNIMPLEMENTED; + return false; +} + +void Storage::updateState(tmgr_trace_event_t event_type, double value, double date) +{ + THROW_UNIMPLEMENTED; +} + +StorageActionLmmPtr Storage::ls(const char* path) +{ + StorageActionLmmPtr action = new StorageActionLmm(p_model, 0, m_stateCurrent != SURF_RESOURCE_ON, this, LS); + + action->p_lsDict = NULL; + xbt_dict_t ls_dict = xbt_dict_new(); + + char* key; + size_t size = 0; + xbt_dict_cursor_t cursor = NULL; + + xbt_dynar_t dyn = NULL; + char* file = NULL; + + // for each file in the storage content + xbt_dict_foreach(p_content,cursor,key,size){ + // Search if file start with the prefix 'path' + if(xbt_str_start_with(key,path)){ + file = &key[strlen(path)]; + + // Split file with '/' + dyn = xbt_str_split(file,"/"); + file = xbt_dynar_get_as(dyn,0,char*); + + // file + if(xbt_dynar_length(dyn) == 1){ + xbt_dict_set(ls_dict,file,&size,NULL); + } + // Directory + else + { + // if directory does not exist yet in the dictionary + if(!xbt_dict_get_or_null(ls_dict,file)) + xbt_dict_set(ls_dict,file,NULL,NULL); + } + xbt_dynar_free(&dyn); + } + } + + action->p_lsDict = ls_dict; + return action; +} + +StorageActionLmmPtr Storage::open(const char* mount, const char* path) +{ + XBT_DEBUG("\tOpen file '%s'",path); + size_t size = (size_t) xbt_dict_get_or_null(p_content, path); + // if file does not exist create an empty file + if(!size){ + xbt_dict_set(p_content, path, &size, NULL); + XBT_DEBUG("File '%s' was not found, file created.",path); + } + surf_file_t file = xbt_new0(s_surf_file_t,1); + file->name = xbt_strdup(path); + file->size = size; + file->storage = xbt_strdup(mount); + + StorageActionLmmPtr action = new StorageActionLmm(p_model, 0, m_stateCurrent != SURF_RESOURCE_ON, this, OPEN); + action->p_file = file; + return action; +} + +StorageActionLmmPtr Storage::close(surf_file_t fd) +{ + char *filename = fd->name; + XBT_DEBUG("\tClose file '%s' size '%zu'", filename, fd->size); + // unref write actions from storage + StorageActionLmmPtr write_action; + unsigned int i; + xbt_dynar_foreach(p_writeActions, i, write_action) { + if ((write_action->p_file) == fd) { + xbt_dynar_cursor_rm(p_writeActions, &i); + write_action->unref(); + } + } + free(fd->name); + free(fd->storage); + xbt_free(fd); + StorageActionLmmPtr action = new StorageActionLmm(p_model, 0, m_stateCurrent != SURF_RESOURCE_ON, this, CLOSE); + return action; +} + +StorageActionLmmPtr Storage::read(void* ptr, size_t size, surf_file_t fd) +{ + if(size > fd->size) + size = fd->size; + StorageActionLmmPtr action = new StorageActionLmm(p_model, 0, m_stateCurrent != SURF_RESOURCE_ON, this, READ); + return action; +} + +StorageActionLmmPtr Storage::write(const void* ptr, size_t size, surf_file_t fd) +{ + char *filename = fd->name; + XBT_DEBUG("\tWrite file '%s' size '%zu/%zu'",filename,size,fd->size); + + StorageActionLmmPtr action = new StorageActionLmm(p_model, 0, m_stateCurrent != SURF_RESOURCE_ON, this, WRITE); + action->p_file = fd; + + // If the storage is full + if(m_usedSize==m_size) { + action->setState(SURF_ACTION_FAILED); + } + return action; +} + +/********** + * Action * + **********/ + +StorageActionLmm::StorageActionLmm(ModelPtr model, double cost, bool failed, StoragePtr storage, e_surf_action_storage_type_t type) + : ActionLmm(model, cost, failed), p_storage(storage), m_type(type) { + XBT_IN("(%s,%zu", storage->m_name, cost); + // Must be less than the max bandwidth for all actions + lmm_expand(storage_maxmin_system, storage->p_constraint, p_variable, 1.0); + switch(type) { + case OPEN: + case CLOSE: + case STAT: + case LS: + break; + case READ: + lmm_expand(storage_maxmin_system, storage->p_constraintRead, + p_variable, 1.0); + break; + case WRITE: + lmm_expand(storage_maxmin_system, storage->p_constraintWrite, + p_variable, 1.0); + xbt_dynar_push(storage->p_writeActions,this); + break; + } + XBT_OUT(); +} + +int StorageActionLmm::unref() +{ + m_refcount--; + if (!m_refcount) { + xbt_swag_remove(this, p_stateSet); + if (p_variable) + lmm_variable_free(storage_maxmin_system, p_variable); +#ifdef HAVE_TRACING + xbt_free(p_category); +#endif + delete this; + return 1; + } + return 0; +} + +void StorageActionLmm::cancel() +{ + setState(SURF_ACTION_FAILED); + return; +} + + + +void StorageActionLmm::suspend() +{ + XBT_IN("(%p)", this); + if (m_suspended != 2) { + lmm_update_variable_weight(storage_maxmin_system, + p_variable, + 0.0); + m_suspended = 1; + } + XBT_OUT(); +} + +void StorageActionLmm::resume() +{ + THROW_UNIMPLEMENTED; +} + +bool StorageActionLmm::isSuspended() +{ + return m_suspended == 1; +} + +void StorageActionLmm::setMaxDuration(double duration) +{ + THROW_UNIMPLEMENTED; +} + +void StorageActionLmm::setPriority(double priority) +{ + THROW_UNIMPLEMENTED; +} + diff --git a/src/surf/storage.hpp b/src/surf/storage.hpp new file mode 100644 index 0000000000..7e929d6e1e --- /dev/null +++ b/src/surf/storage.hpp @@ -0,0 +1,110 @@ +#include "surf.hpp" + +#ifndef STORAGE_HPP_ +#define STORAGE_HPP_ + +/*********** + * Classes * + ***********/ + +class StorageModel; +typedef StorageModel *StorageModelPtr; + +class Storage; +typedef Storage *StoragePtr; + +class StorageActionLmm; +typedef StorageActionLmm *StorageActionLmmPtr; + +/********* + * Model * + *********/ +class StorageModel : Model { +public: + StorageModel(); + ~StorageModel(); + StoragePtr createResource(const char* id, const char* model, const char* type_id, const char* content_name); + double shareResources(double now); + void updateActionsState(double now, double delta); + + xbt_dict_t parseContent(char *filename, size_t *used_size); +}; + +/************ + * Resource * + ************/ + +class Storage : public ResourceLmm { +public: + Storage(StorageModelPtr model, const char* name, xbt_dict_t properties); + + bool isUsed(); + void updateState(tmgr_trace_event_t event_type, double value, double date); + + lmm_constraint_t p_constraintWrite; /* Constraint for maximum write bandwidth*/ + lmm_constraint_t p_constraintRead; /* Constraint for maximum write bandwidth*/ + xbt_dict_t p_content; /* char * -> s_surf_file_t */ + + StorageActionLmmPtr open(const char* mount, const char* path); + StorageActionLmmPtr close(surf_file_t fd); + StorageActionLmmPtr unlink(surf_file_t fd); + StorageActionLmmPtr ls(const char *path); + size_t getSize(surf_file_t fd); + StorageActionLmmPtr read(void* ptr, size_t size, surf_file_t fd);//FIXME:why we have a useless param ptr ?? + StorageActionLmmPtr write(const void* ptr, size_t size, surf_file_t fd);//FIXME:why we have a useless param ptr ?? + + size_t m_size; + size_t m_usedSize; + xbt_dynar_t p_writeActions; +}; + +/********** + * Action * + **********/ + +typedef enum { + READ=0, WRITE, STAT, OPEN, CLOSE, LS +} e_surf_action_storage_type_t; + +class StorageActionLmm : public ActionLmm { +public: + StorageActionLmm(){}; + StorageActionLmm(ModelPtr model, double cost, bool failed, StoragePtr storage, e_surf_action_storage_type_t type); + + int unref(); + void cancel(); + //FIXME:??void recycle(); + void suspend(); + void resume(); + bool isSuspended(); + void setMaxDuration(double duration); + void setPriority(double priority); + + e_surf_action_storage_type_t m_type; + StoragePtr p_storage; + surf_file_t p_file; + xbt_dict_t p_lsDict; +}; + + +typedef struct s_storage_type { + char *model; + char *content; + char *type_id; + xbt_dict_t properties; + size_t size; +} s_storage_type_t, *storage_type_t; + +typedef struct s_mount { + void *id; + char *name; +} s_mount_t, *mount_t; + +typedef struct surf_file { + char *name; + char *storage; + size_t size; +} s_surf_file_t; + + +#endif /* STORAGE_HPP_ */ diff --git a/src/surf/storage_private.h b/src/surf/storage_private.h index 1d896f5bac..dccf6f3966 100644 --- a/src/surf/storage_private.h +++ b/src/surf/storage_private.h @@ -27,7 +27,7 @@ typedef struct surf_file { } s_surf_file_t; typedef struct storage { - s_surf_resource_t generic_resource; /*< Structure with generic data. Needed at begin to interact with SURF */ + //FIXME:s_surf_resource_t generic_resource; /*< Structure with generic data. Needed at begin to interact with SURF */ e_surf_resource_state_t state_current; /*< STORAGE current state (ON or OFF) */ lmm_constraint_t constraint; /* Constraint for maximum bandwidth from connection */ lmm_constraint_t constraint_write; /* Constraint for maximum write bandwidth*/ @@ -43,7 +43,7 @@ typedef enum { } e_surf_action_storage_type_t; typedef struct surf_action_storage { - s_surf_action_lmm_t generic_lmm_action; + //FIXME:s_surf_action_lmm_t generic_lmm_action; e_surf_action_storage_type_t type; void *storage; } s_surf_action_storage_t, *surf_action_storage_t; diff --git a/src/surf/surf.cpp b/src/surf/surf.cpp index 6508e38abd..54355f624e 100644 --- a/src/surf/surf.cpp +++ b/src/surf/surf.cpp @@ -1,22 +1,21 @@ +#include "surf_private.h" #include "surf.hpp" #include "cpu.hpp" #include "simix/smx_host_private.h" +#include "surf_routing.hpp" +#include "simgrid/sg_config.h" +#include "mc/mc.h" -XBT_LOG_NEW_CATEGORY(surfpp, "All SURF categories"); -XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surfpp_kernel, surfpp, +extern "C" { +XBT_LOG_NEW_CATEGORY(surf, "All SURF categories"); +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf, "Logging specific to SURF (kernel)"); +} /********* * Utils * *********/ -double NOWW = 0; - -XBT_INLINE double surf_get_clock(void) -{ - return NOWW; -} - /* This function is a pimple that we ought to fix. But it won't be easy. * * The surf_solve() function does properly return the set of actions that changed. @@ -50,6 +49,134 @@ static void remove_watched_host(void *key) xbt_dict_remove(watched_hosts_lib, *(char**)key); } +void surf_watched_hosts(void) +{ + char *key; + void *host; + xbt_dict_cursor_t cursor; + xbt_dynar_t hosts = xbt_dynar_new(sizeof(char*), NULL); + + XBT_DEBUG("Check for host SURF_RESOURCE_ON on watched_hosts_lib"); + xbt_dict_foreach(watched_hosts_lib, cursor, key, host) + { + if(SIMIX_host_get_state((smx_host_t)host) == SURF_RESOURCE_ON){ + XBT_INFO("Restart processes on host: %s", SIMIX_host_get_name((smx_host_t)host)); + SIMIX_host_autorestart((smx_host_t)host); + xbt_dynar_push_as(hosts, char*, key); + } + else + XBT_DEBUG("See SURF_RESOURCE_OFF on host: %s",key); + } + xbt_dynar_map(hosts, remove_watched_host); + xbt_dynar_free(&hosts); +} + + +xbt_dynar_t model_list = NULL; +tmgr_history_t history = NULL; +lmm_system_t maxmin_system = NULL; +xbt_dynar_t surf_path = NULL; + +/* Don't forget to update the option description in smx_config when you change this */ +s_surf_model_description_t surf_network_model_description[] = { + {"LV08", + "Realistic network analytic model (slow-start modeled by multiplying latency by 10.4, bandwidth by .92; bottleneck sharing uses a payload of S=8775 for evaluating RTT). ", + surf_network_model_init_LegrandVelho}, + {"Constant", + "Simplistic network model where all communication take a constant time (one second). This model provides the lowest realism, but is (marginally) faster.", + surf_network_model_init_Constant}, + {"SMPI", + "Realistic network model specifically tailored for HPC settings (accurate modeling of slow start with correction factors on three intervals: < 1KiB, < 64 KiB, >= 64 KiB)", + surf_network_model_init_SMPI}, + {"CM02", + "Legacy network analytic model (Very similar to LV08, but without corrective factors. The timings of small messages are thus poorly modeled).", + surf_network_model_init_CM02}, +#ifdef HAVE_GTNETS + {"GTNets", + "Network pseudo-model using the GTNets simulator instead of an analytic model", + surf_network_model_init_GTNETS}, +#endif +#ifdef HAVE_NS3 + {"NS3", + "Network pseudo-model using the NS3 tcp model instead of an analytic model", + surf_network_model_init_NS3}, +#endif + {"Reno", + "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).", + surf_network_model_init_Reno}, + {"Reno2", + "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).", + surf_network_model_init_Reno2}, + {"Vegas", + "Model from Steven H. Low using lagrange_solve instead of lmm_solve (experts only; check the code for more info).", + surf_network_model_init_Vegas}, + {NULL, NULL, NULL} /* this array must be NULL terminated */ +}; + +s_surf_model_description_t surf_cpu_model_description[] = { + {"Cas01", + "Simplistic CPU model (time=size/power).", + surf_cpu_model_init_Cas01}, + {NULL, NULL, NULL} /* this array must be NULL terminated */ +}; + +s_surf_model_description_t surf_workstation_model_description[] = { + {"default", + "Default workstation model. Currently, CPU:Cas01 and network:LV08 (with cross traffic enabled)", + surf_workstation_model_init_current_default}, + {"compound", + "Workstation model that is automatically chosen if you change the network and CPU models", + surf_workstation_model_init_compound}, + {"ptask_L07", "Workstation model somehow similar to Cas01+CM02 but allowing parallel tasks", + surf_workstation_model_init_ptask_L07}, + {NULL, NULL, NULL} /* this array must be NULL terminated */ +}; + +s_surf_model_description_t surf_optimization_mode_description[] = { + {"Lazy", + "Lazy action management (partial invalidation in lmm + heap in action remaining).", + NULL}, + {"TI", + "Trace integration. Highly optimized mode when using availability traces (only available for the Cas01 CPU model for now).", + NULL}, + {"Full", + "Full update of remaining and variables. Slow but may be useful when debugging.", + NULL}, + {NULL, NULL, NULL} /* this array must be NULL terminated */ +}; + +s_surf_model_description_t surf_storage_model_description[] = { + {"default", + "Simplistic storage model.", + surf_storage_model_init_default}, + {NULL, NULL, NULL} /* this array must be NULL terminated */ +}; + +/* ********************************************************************* */ +/* TUTORIAL: New model */ +s_surf_model_description_t surf_new_model_description[] = { + {"default", + "Tutorial model.", + surf_new_model_init_default}, + {NULL, NULL, NULL} /* this array must be NULL terminated */ +}; +/* ********************************************************************* */ + +#ifdef CONTEXT_THREADS +static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */ +#endif + +static double *surf_mins = NULL; /* return value of share_resources for each model */ +static int surf_min_index; /* current index in surf_mins */ +static double min; /* duration determined by surf_solve */ + +double NOW = 0; + +XBT_INLINE double surf_get_clock(void) +{ + return NOW; +} + /*TODO: keepit void surf_watched_hosts(void) { char *key; @@ -74,10 +201,254 @@ static void remove_watched_host(void *key) xbt_dynar_free(&hosts); }*/ +#ifdef _XBT_WIN32 +# define FILE_DELIM "\\" +#else +# define FILE_DELIM "/" /* FIXME: move to better location */ +#endif + +FILE *surf_fopen(const char *name, const char *mode) +{ + unsigned int cpt; + char *path_elm = NULL; + char *buff; + FILE *file = NULL; + + xbt_assert(name); + + if (__surf_is_absolute_file_path(name)) /* don't mess with absolute file names */ + return fopen(name, mode); + + /* search relative files in the path */ + xbt_dynar_foreach(surf_path, cpt, path_elm) { + buff = bprintf("%s" FILE_DELIM "%s", path_elm, name); + file = fopen(buff, mode); + free(buff); + + if (file) + return file; + } + return NULL; +} + +/* + * Returns the initial path. On Windows the initial path is + * the current directory for the current process in the other + * case the function returns "./" that represents the current + * directory on Unix/Linux platforms. + */ + +const char *__surf_get_initial_path(void) +{ + +#ifdef _XBT_WIN32 + unsigned i; + char current_directory[MAX_PATH + 1] = { 0 }; + unsigned int len = GetCurrentDirectory(MAX_PATH + 1, current_directory); + char root[4] = { 0 }; + + if (!len) + return NULL; + + strncpy(root, current_directory, 3); + + for (i = 0; i < MAX_DRIVE; i++) { + if (toupper(root[0]) == disk_drives_letter_table[i][0]) + return disk_drives_letter_table[i]; + } + + return NULL; +#else + return "./"; +#endif +} + +/* The __surf_is_absolute_file_path() returns 1 if + * file_path is a absolute file path, in the other + * case the function returns 0. + */ +int __surf_is_absolute_file_path(const char *file_path) +{ +#ifdef _XBT_WIN32 + WIN32_FIND_DATA wfd = { 0 }; + HANDLE hFile = FindFirstFile(file_path, &wfd); + + if (INVALID_HANDLE_VALUE == hFile) + return 0; + + FindClose(hFile); + return 1; +#else + return (file_path[0] == '/'); +#endif +} + +/** Displays the long description of all registered models, and quit */ +void model_help(const char *category, s_surf_model_description_t * table) +{ + int i; + printf("Long description of the %s models accepted by this simulator:\n", + category); + for (i = 0; table[i].name; i++) + printf(" %s: %s\n", table[i].name, table[i].description); +} + +int find_model_description(s_surf_model_description_t * table, + const char *name) +{ + int i; + char *name_list = NULL; + + for (i = 0; table[i].name; i++) + if (!strcmp(name, table[i].name)) { + return i; + } + name_list = strdup(table[0].name); + for (i = 1; table[i].name; i++) { + name_list = (char *) xbt_realloc(name_list, strlen(name_list) + strlen(table[i].name) + 3); + strcat(name_list, ", "); + strcat(name_list, table[i].name); + } + xbt_die("Model '%s' is invalid! Valid models are: %s.", name, name_list); + return -1; +} + +static XBT_INLINE void routing_asr_host_free(void *p) +{ + delete ((RoutingEdgePtr) p); +} + +static XBT_INLINE void routing_asr_prop_free(void *p) +{ + xbt_dict_t elm = (xbt_dict_t) p; + xbt_dict_free(&elm); +} + +static XBT_INLINE void surf_resource_free(void *r) +{ + ResourcePtr resource = (ResourcePtr) r; + delete resource; +} + +void sg_version(int *ver_major,int *ver_minor,int *ver_patch) { + *ver_major = SIMGRID_VERSION_MAJOR; + *ver_minor = SIMGRID_VERSION_MINOR; + *ver_patch = SIMGRID_VERSION_PATCH; +} + +void surf_init(int *argc, char **argv) +{ + XBT_DEBUG("Create all Libs"); + host_lib = xbt_lib_new(); + link_lib = xbt_lib_new(); + as_router_lib = xbt_lib_new(); + storage_lib = xbt_lib_new(); + storage_type_lib = xbt_lib_new(); + watched_hosts_lib = xbt_dict_new(); + + XBT_DEBUG("Add routing levels"); + ROUTING_HOST_LEVEL = xbt_lib_add_level(host_lib,routing_asr_host_free); + ROUTING_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_host_free); + ROUTING_PROP_ASR_LEVEL = xbt_lib_add_level(as_router_lib,routing_asr_prop_free); + + XBT_DEBUG("Add SURF levels"); + SURF_CPU_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free); + SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_resource_free); + SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_resource_free); + + xbt_init(argc, argv); + if (!model_list) + model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL); + if (!history) + history = tmgr_history_new(); + +#ifdef HAVE_TRACING + TRACE_add_start_function(TRACE_surf_alloc); + TRACE_add_end_function(TRACE_surf_release); +#endif + + sg_config_init(argc, argv); + + surf_action_init(); + if (MC_is_active()) + MC_memory_init(); +} + +void surf_exit(void) +{ + unsigned int iter; + ModelPtr model = NULL; + + sg_config_finalize(); + + xbt_dynar_foreach(model_list, iter, model) + delete model; + xbt_dynar_free(&model_list); + routing_exit(); + + if (maxmin_system) { + lmm_system_free(maxmin_system); + maxmin_system = NULL; + } + if (history) { + tmgr_history_free(history); + history = NULL; + } + surf_action_exit(); + +#ifdef CONTEXT_THREADS + xbt_parmap_destroy(surf_parmap); + xbt_free(surf_mins); + surf_mins = NULL; +#endif + + xbt_dynar_free(&surf_path); + + xbt_lib_free(&host_lib); + xbt_lib_free(&link_lib); + xbt_lib_free(&as_router_lib); + xbt_lib_free(&storage_lib); + xbt_lib_free(&storage_type_lib); + + xbt_dict_free(&watched_hosts_lib); + + tmgr_finalize(); + surf_parse_lex_destroy(); + surf_parse_free_callbacks(); + + NOW = 0; /* Just in case the user plans to restart the simulation afterward */ +} /********* * Model * *********/ +Model::Model(string name) + : m_name(name), m_resOnCB(0), m_resOffCB(0), m_actSuspendCB(0), m_actCancelCB(0), m_actResumeCB(0) +{ + ActionPtr action; + p_readyActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup)); + p_runningActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup)); + p_failedActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup)); + p_doneActionSet = xbt_swag_new(xbt_swag_offset(*action, p_stateHookup)); + + p_modifiedSet = NULL; + p_actionHeap = NULL; + p_updateMechanism = UM_UNDEFINED; + m_selectiveUpdate = 0; +} + +Model::~Model(){ +xbt_swag_free(p_readyActionSet); +xbt_swag_free(p_runningActionSet); +xbt_swag_free(p_failedActionSet); +xbt_swag_free(p_doneActionSet); +} + +double Model::shareResources(double now) +{ + //FIXME: to implement +} + double Model::shareResourcesLazy(double now) { ActionLmmPtr action = NULL; @@ -150,7 +521,7 @@ double Model::shareResourcesLazy(double now) return min; } -double Model::shareResourcesFull(xbt_swag_t running_actions, +double Model::shareResourcesMaxMin(xbt_swag_t running_actions, size_t offset, lmm_system_t sys, void (*solve) (lmm_system_t)) @@ -209,8 +580,15 @@ double Model::shareResourcesFull(xbt_swag_t running_actions, return min; } -void Model::gapRemove(ActionLmmPtr action) {} - +void Model::updateActionsState(double now, double delta) +{ + if (p_updateMechanism == UM_FULL) + updateActionsStateFull(now, delta); + else if (p_updateMechanism == UM_LAZY) + updateActionsStateLazy(now, delta); + else + xbt_die("Invalid cpu update mechanism!"); +} void Model::updateActionsStateLazy(double now, double delta) { @@ -278,10 +656,25 @@ void Model::notifyActionSuspend(ActionPtr a) * Resource * ************/ -string Resource::getName() { +Resource::Resource(surf_model_t model, const char *name, xbt_dict_t props) + : m_name(xbt_strdup(name)), m_running(true), p_model(model), m_properties(props) +{} + +Resource::Resource(){ + //FIXME:free(m_name); + xbt_dict_free(&m_properties); +} + +const char *Resource::getName() +{ return m_name; } +xbt_dict_t Resource::getProperties() +{ + return m_properties; +} + e_surf_resource_state_t Resource::getState() { return m_stateCurrent; @@ -308,27 +701,90 @@ void Resource::turnOff() } } +ResourceLmm::ResourceLmm(surf_model_t model, const char *name, xbt_dict_t props, + lmm_system_t system, + double constraint_value, + tmgr_history_t history, + e_surf_resource_state_t state_init, + tmgr_trace_t state_trace, + double metric_peak, + tmgr_trace_t metric_trace) + : Resource(model, name, props) +{ + p_constraint = lmm_constraint_new(system, this, constraint_value); + p_stateCurrent = state_init; + if (state_trace) + p_stateEvent = tmgr_history_add_trace(history, state_trace, 0.0, 0, this); + p_power.scale = 1.0; + p_power.peak = metric_peak; + if (metric_trace) + p_power.event = tmgr_history_add_trace(history, metric_trace, 0.0, 0, this); +} + /********** * Action * **********/ -/* added to manage the communication action's heap */ -void surf_action_lmm_update_index_heap(void *action, int i) { - ((ActionLmmPtr)action)->updateIndexHeap(i); -} -void ActionLmm::updateIndexHeap(int i) -{ - m_indexHeap = i; -} - -/*TODO/const char *surf_action_state_names[6] = { +const char *surf_action_state_names[6] = { "SURF_ACTION_READY", "SURF_ACTION_RUNNING", "SURF_ACTION_FAILED", "SURF_ACTION_DONE", "SURF_ACTION_TO_FREE", "SURF_ACTION_NOT_IN_THE_SYSTEM" -};*/ +}; + +/** + * \brief Initializes the action module of Surf. + */ +void surf_action_init(void) { + + /* the action mallocator will always provide actions of the following size, + * so this size should be set to the maximum size of the surf action structures + */ + /*FIXME:action_mallocator_allocated_size = sizeof(s_surf_action_network_CM02_t); + action_mallocator = xbt_mallocator_new(65536, surf_action_mallocator_new_f, + surf_action_mallocator_free_f, surf_action_mallocator_reset_f);*/ +} + +/** + * \brief Uninitializes the action module of Surf. + */ +void surf_action_exit(void) { + //FIXME:xbt_mallocator_free(action_mallocator); +} + +Action::Action(){} + +Action::Action(ModelPtr model, double cost, bool failed): + m_cost(cost), p_model(model), m_failed(failed), m_remains(cost), + m_refcount(1), m_priority(1.0), m_maxDuration(NO_MAX_DURATION), + m_start(surf_get_clock()), m_finish(-1.0) +{ + #ifdef HAVE_TRACING + p_category = NULL; + #endif + if (failed) + p_stateSet = p_model->p_failedActionSet; + else + p_stateSet = p_model->p_runningActionSet; + + xbt_swag_insert(this, p_stateSet); +} + +Action::~Action() {} + +int Action::unref(){ + DIE_IMPOSSIBLE; +} + +void Action::cancel(){ + DIE_IMPOSSIBLE; +} + +void Action::recycle(){ + DIE_IMPOSSIBLE; +} e_surf_action_state_t Action::getState() { @@ -390,6 +846,88 @@ void Action::setCategory(const char *category) } #endif +void Action::ref(){ + m_refcount++; +} + +void ActionLmm::setMaxDuration(double duration) +{ + XBT_IN("(%p,%g)", this, duration); + m_maxDuration = duration; + if (p_model->p_updateMechanism == UM_LAZY) // remove action from the heap + heapRemove(p_model->p_actionHeap); + XBT_OUT(); +} + +void ActionLmm::gapRemove() {} + +void ActionLmm::setPriority(double priority) +{ + XBT_IN("(%p,%g)", this, priority); + m_priority = priority; + lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, priority); + + if (p_model->p_updateMechanism == UM_LAZY) + heapRemove(p_model->p_actionHeap); + XBT_OUT(); +} + +void ActionLmm::cancel(){ + setState(SURF_ACTION_FAILED); + if (p_model->p_updateMechanism == UM_LAZY) { + xbt_swag_remove(this, p_model->p_modifiedSet); + heapRemove(p_model->p_actionHeap); + } +} + +int ActionLmm::unref(){ + m_refcount--; + if (!m_refcount) { + xbt_swag_remove(this, p_stateSet); + if (p_variable) + lmm_variable_free(p_model->p_maxminSystem, p_variable); + if (p_model->p_updateMechanism == UM_LAZY) { + /* remove from heap */ + heapRemove(p_model->p_actionHeap); + xbt_swag_remove(this, p_model->p_modifiedSet); + } +#ifdef HAVE_TRACING + xbt_free(p_category); +#endif + delete this; + return 1; + } + return 0; +} + +void ActionLmm::suspend() +{ + XBT_IN("(%p)", this); + if (m_suspended != 2) { + lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, 0.0); + m_suspended = 1; + if (p_model->p_updateMechanism == UM_LAZY) + heapRemove(p_model->p_actionHeap); + } + XBT_OUT(); +} + +void ActionLmm::resume() +{ + XBT_IN("(%p)", this); + if (m_suspended != 2) { + lmm_update_variable_weight(p_model->p_maxminSystem, p_variable, m_priority); + m_suspended = 0; + if (p_model->p_updateMechanism == UM_LAZY) + heapRemove(p_model->p_actionHeap); + } + XBT_OUT(); +} + +bool ActionLmm::isSuspended() +{ + return m_suspended == 1; +} /* insert action on heap using a given key and a hat (heap_action_type) * a hat can be of three types for communications: * @@ -411,6 +949,16 @@ void ActionLmm::heapRemove(xbt_heap_t heap) } } +/* added to manage the communication action's heap */ +void surf_action_lmm_update_index_heap(void *action, int i) { + ((ActionLmmPtr)action)->updateIndexHeap(i); +} + +void ActionLmm::updateIndexHeap(int i) { + m_indexHeap = i; +} + + double ActionLmm::getRemains() { XBT_IN("(%p)", this); diff --git a/src/surf/surf.hpp b/src/surf/surf.hpp index 6deea66080..996aa47825 100644 --- a/src/surf/surf.hpp +++ b/src/surf/surf.hpp @@ -15,15 +15,14 @@ #include "xbt/lib.h" #include "surf/surf_routing.h" #include "simgrid/platf_interface.h" +#include "surf/surf.h" +#include "surf/surf_private.h" extern tmgr_history_t history; #define NO_MAX_DURATION -1.0 using namespace std; -// TODO: put in surf_private.hpp -extern xbt_dict_t watched_hosts_lib; - /** \ingroup SURF_simulation * \brief Return the current time * @@ -34,6 +33,19 @@ extern xbt_dict_t watched_hosts_lib; * Utils * *********/ +/* user-visible parameters */ +extern double sg_tcp_gamma; +extern double sg_sender_gap; +extern double sg_latency_factor; +extern double sg_bandwidth_factor; +extern double sg_weight_S_parameter; +extern int sg_network_crosstraffic; +#ifdef HAVE_GTNETS +extern double sg_gtnets_jitter; +extern int sg_gtnets_jitter_seed; +#endif +extern xbt_dynar_t surf_path; + #ifdef __cplusplus extern "C" { #endif @@ -46,21 +58,23 @@ XBT_PUBLIC(void) surf_watched_hosts(void); extern double sg_sender_gap; XBT_PUBLIC(int) SURF_CPU_LEVEL; //Surf cpu level +int __surf_is_absolute_file_path(const char *file_path); + /*********** * Classes * ***********/ -class Model; +//class Model; typedef Model* ModelPtr; -class Resource; +//class Resource; typedef Resource* ResourcePtr; typedef boost::function ResourceCallback; -class Action; +//class Action; typedef Action* ActionPtr; typedef boost::function ActionCallback; -class ActionLmm; +//class ActionLmm; typedef ActionLmm* ActionLmmPtr; enum heap_action_type{ @@ -70,12 +84,6 @@ enum heap_action_type{ NOTSET }; -typedef enum { - UM_FULL, - UM_LAZY, - UM_UNDEFINED -} e_UM_t; - /********* * Trace * *********/ @@ -95,31 +103,23 @@ XBT_PUBLIC_DATA(xbt_dynar_t) model_list; class Model { public: - Model(string name) { - m_name = name; - m_resOnCB = m_resOffCB= 0; - m_actSuspendCB = m_actCancelCB = m_actResumeCB = 0; - } - virtual ~Model() { - xbt_swag_free(p_readyActionSet); - xbt_swag_free(p_runningActionSet); - xbt_swag_free(p_failedActionSet); - xbt_swag_free(p_doneActionSet); - } + Model(string name); + virtual ~Model(); + ResourcePtr createResource(string name); ActionPtr createAction(double _cost, bool _failed); - double (Model::*shareResources)(double now); + virtual double shareResources(double now); double shareResourcesLazy(double now); - double shareResourcesFull(xbt_swag_t running_actions, + //double shareResourcesFull(double now); + double shareResourcesMaxMin(xbt_swag_t running_actions, size_t offset, lmm_system_t sys, void (*solve) (lmm_system_t)); - void (Model::*updateActionsState)(double now, double delta); + void updateActionsState(double now, double delta); void updateActionsStateLazy(double now, double delta); void updateActionsStateFull(double now, double delta); string getName() {return m_name;}; - void gapRemove(ActionLmmPtr action); void addTurnedOnCallback(ResourceCallback rc); void notifyResourceTurnedOn(ResourcePtr r); @@ -144,12 +144,12 @@ public: xbt_swag_t p_runningActionSet; /**< Actions in state SURF_ACTION_RUNNING */ xbt_swag_t p_failedActionSet; /**< Actions in state SURF_ACTION_FAILED */ xbt_swag_t p_doneActionSet; /**< Actions in state SURF_ACTION_DONE */ + string m_name; protected: std::vector m_failedActions, m_runningActions; private: - string m_name; ResourceCallback m_resOnCB, m_resOffCB; ActionCallback m_actCancelCB, m_actSuspendCB, m_actResumeCB; }; @@ -169,15 +169,14 @@ typedef struct { class Resource { public: - Resource() {}; - Resource(ModelPtr model, const char *name, xbt_dict_t properties): - m_name(name),m_running(true),p_model(model),m_properties(properties) {}; + Resource(); + Resource(ModelPtr model, const char *name, xbt_dict_t properties); virtual ~Resource() {}; - void updateState(tmgr_trace_event_t event_type, double value, double date); + virtual void updateState(tmgr_trace_event_t event_type, double value, double date)=0; //private - bool isUsed(); + virtual bool isUsed()=0; //TODOupdateActionState(); //TODOupdateResourceState(); //TODOfinilize(); @@ -186,17 +185,19 @@ public: void turnOn(); void turnOff(); void setName(string name); - string getName(); + const char *getName(); + xbt_dict_t getProperties(); + ModelPtr getModel() {return p_model;}; e_surf_resource_state_t getState(); void printModel() { std::cout << p_model->getName() << "<start; -} +}*/ double surf_action_get_finish_time(surf_action_t action) { diff --git a/src/surf/surf_interface.cpp b/src/surf/surf_interface.cpp new file mode 100644 index 0000000000..6cc7d33110 --- /dev/null +++ b/src/surf/surf_interface.cpp @@ -0,0 +1,374 @@ +#include "surf.hpp" +#include "workstation.hpp" +#include "network.hpp" +#include "instr/instr_private.h" + +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_kernel); + +/********* + * TOOLS * + *********/ +extern double NOW; + +#ifdef CONTEXT_THREADS +static xbt_parmap_t surf_parmap = NULL; /* parallel map on models */ +#endif + +static double *surf_mins = NULL; /* return value of share_resources for each model */ +static int surf_min_index; /* current index in surf_mins */ +static double surf_min; /* duration determined by surf_solve */ + +void surf_presolve(void) +{ + double next_event_date = -1.0; + tmgr_trace_event_t event = NULL; + double value = -1.0; + surf_resource_t resource = NULL; + surf_model_t model = NULL; + unsigned int iter; + + XBT_DEBUG + ("First Run! Let's \"purge\" events and put models in the right state"); + while ((next_event_date = tmgr_history_next_date(history)) != -1.0) { + if (next_event_date > NOW) + break; + while ((event = + tmgr_history_get_next_event_leq(history, next_event_date, + &value, + (void **) &resource))) { + if (value >= 0){ + resource->updateState(event, value, NOW); + } + } + } + xbt_dynar_foreach(model_list, iter, model) + model->updateActionsState(NOW, 0.0); +} + +static void surf_share_resources(surf_model_t model) +{ + double next_action_end = -1.0; + int i = __sync_fetch_and_add(&surf_min_index, 1); + if (strcmp(model->m_name.c_str(), "network NS3")) { + XBT_DEBUG("Running for Resource [%s]", model->m_name.c_str()); + next_action_end = model->shareResources(NOW); + XBT_DEBUG("Resource [%s] : next action end = %f", + model->m_name.c_str(), next_action_end); + } + surf_mins[i] = next_action_end; +} + +static void surf_update_actions_state(surf_model_t model) +{ + model->updateActionsState(NOW, surf_min); +} + +double surf_solve(double max_date) +{ + surf_min = -1.0; /* duration */ + double next_event_date = -1.0; + double model_next_action_end = -1.0; + double value = -1.0; + surf_resource_t resource = NULL; + surf_model_t model = NULL; + tmgr_trace_event_t event = NULL; + unsigned int iter; + + if (max_date != -1.0 && max_date != NOW) { + surf_min = max_date - NOW; + } + + XBT_DEBUG("Looking for next action end for all models except NS3"); + + if (surf_mins == NULL) { + surf_mins = xbt_new(double, xbt_dynar_length(model_list)); + } + surf_min_index = 0; + + /* sequential version */ + xbt_dynar_foreach(model_list, iter, model) { + surf_share_resources(model); + } + + unsigned i; + for (i = 0; i < xbt_dynar_length(model_list); i++) { + if ((surf_min < 0.0 || surf_mins[i] < surf_min) + && surf_mins[i] >= 0.0) { + surf_min = surf_mins[i]; + } + } + + XBT_DEBUG("Min for resources (remember that NS3 don't update that value) : %f", surf_min); + + XBT_DEBUG("Looking for next trace event"); + + do { + XBT_DEBUG("Next TRACE event : %f", next_event_date); + + next_event_date = tmgr_history_next_date(history); + + if(!strcmp(surf_network_model->m_name.c_str(), "network NS3")){//FIXME: add surf_network_model->m_name && + if(next_event_date!=-1.0 && surf_min!=-1.0) { + surf_min = MIN(next_event_date - NOW, surf_min); + } else{ + surf_min = MAX(next_event_date - NOW, surf_min); + } + + XBT_DEBUG("Run for network at most %f", surf_min); + // run until min or next flow + model_next_action_end = surf_network_model->shareResources(surf_min); + + XBT_DEBUG("Min for network : %f", model_next_action_end); + if(model_next_action_end>=0.0) + surf_min = model_next_action_end; + } + + if (next_event_date < 0.0) { + XBT_DEBUG("no next TRACE event. Stop searching for it"); + break; + } + + if ((surf_min == -1.0) || (next_event_date > NOW + surf_min)) break; + + XBT_DEBUG("Updating models (min = %g, NOW = %g, next_event_date = %g)", surf_min, NOW, next_event_date); + while ((event = + tmgr_history_get_next_event_leq(history, next_event_date, + &value, + (void **) &resource))) { + if (resource->isUsed()) { + surf_min = next_event_date - NOW; + XBT_DEBUG + ("This event will modify model state. Next event set to %f", + surf_min); + } + /* update state of model_obj according to new value. Does not touch lmm. + It will be modified if needed when updating actions */ + XBT_DEBUG("Calling update_resource_state for resource %s with min %lf", + resource->p_model->m_name.c_str(), surf_min); + resource->updateState(event, value, next_event_date); + } + } while (1); + + /* FIXME: Moved this test to here to avoid stopping simulation if there are actions running on cpus and all cpus are with availability = 0. + * This may cause an infinite loop if one cpu has a trace with periodicity = 0 and the other a trace with periodicity > 0. + * The options are: all traces with same periodicity(0 or >0) or we need to change the way how the events are managed */ + if (surf_min == -1.0) { + XBT_DEBUG("No next event at all. Bail out now."); + return -1.0; + } + + XBT_DEBUG("Duration set to %f", surf_min); + + NOW = NOW + surf_min; + + /* sequential version */ + xbt_dynar_foreach(model_list, iter, model) { + surf_update_actions_state(model); + } + +#ifdef HAVE_TRACING + TRACE_paje_dump_buffer (0); +#endif + + return surf_min; +} + +XBT_INLINE double surf_get_clock(void) +{ + return NOW; +} + +void routing_get_route_and_latency(sg_routing_edge_t src, sg_routing_edge_t dst, + xbt_dynar_t * route, double *latency){ + routing_platf->getRouteAndLatency(src, dst, route, latency); +} + +/********* + * MODEL * + *********/ + +const char *surf_model_name(surf_model_t model){ + return model->m_name.c_str(); +} + +xbt_swag_t surf_model_done_action_set(surf_model_t model){ + return model->p_doneActionSet; +} + +xbt_swag_t surf_model_failed_action_set(surf_model_t model){ + return model->p_failedActionSet; +} + +xbt_swag_t surf_model_ready_action_set(surf_model_t model){ + return model->p_readyActionSet; +} + +xbt_swag_t surf_model_running_action_set(surf_model_t model){ + return model->p_runningActionSet; +} + +surf_action_t surf_workstation_model_execute_parallel_task(surf_workstation_model_t model, + int workstation_nb, + void **workstation_list, + double *computation_amount, + double *communication_amount, + double rate){ + return model->executeParallelTask(workstation_nb, workstation_list, computation_amount, communication_amount, rate); +} + +surf_action_t surf_workstation_model_communicate(surf_workstation_model_t model, surf_workstation_CLM03_t src, surf_workstation_CLM03_t dst, double size, double rate){ + model->communicate(src, dst, size, rate); +} + +xbt_dynar_t surf_workstation_model_get_route(surf_workstation_model_t model, + surf_workstation_t src, surf_workstation_t dst){ + return model->getRoute((WorkstationCLM03Ptr)surf_workstation_resource_priv(src),(WorkstationCLM03Ptr)surf_workstation_resource_priv(dst)); +} + +surf_action_t surf_network_model_communicate(surf_network_model_t model, sg_routing_edge_t src, sg_routing_edge_t dst, double size, double rate){ + model->communicate(src, dst, size, rate); +} + +const char *surf_resource_name(surf_resource_t resource){ + return resource->m_name; +} + +xbt_dict_t surf_resource_get_properties(surf_resource_t resource){ + return resource->m_properties; +} + +e_surf_resource_state_t surf_resource_get_state(surf_resource_t resource){ + return resource->getState(); +} + +surf_action_t surf_workstation_sleep(surf_workstation_t resource, double duration){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(resource))->sleep(duration); +} + +double surf_workstation_get_speed(surf_workstation_t resource, double load){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(resource))->getSpeed(load); +} + +double surf_workstation_get_available_speed(surf_workstation_t resource){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(resource))->getAvailableSpeed(); +} + +int surf_workstation_get_core(surf_workstation_t resource){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(resource))->getCore(); +} + +surf_action_t surf_workstation_execute(surf_workstation_t resource, double size){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(resource))->execute(size); +} + +surf_action_t surf_workstation_communicate(surf_workstation_t workstation_src, surf_workstation_t workstation_dst, double size, double rate){ + return surf_workstation_model->communicate((surf_workstation_CLM03_t)surf_workstation_resource_priv(workstation_src),(surf_workstation_CLM03_t)surf_workstation_resource_priv(workstation_dst), size, rate); +} + +surf_action_t surf_workstation_open(surf_workstation_t workstation, const char* mount, const char* path){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(workstation))->open(mount, path); +} + +surf_action_t surf_workstation_close(surf_workstation_t workstation, surf_file_t fd){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(workstation))->close(fd); +} + +int surf_workstation_unlink(surf_workstation_t workstation, surf_file_t fd){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(workstation))->unlink(fd); +} + +surf_action_t surf_workstation_ls(surf_workstation_t workstation, const char* mount, const char *path){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(workstation))->ls(mount, path); +} + +size_t surf_workstation_get_size(surf_workstation_t workstation, surf_file_t fd){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(workstation))->getSize(fd); +} + +surf_action_t surf_workstation_read(surf_workstation_t resource, void *ptr, size_t size, surf_file_t fd){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(resource))->read(ptr, size, fd); +} + +surf_action_t surf_workstation_write(surf_workstation_t resource, const void *ptr, size_t size, surf_file_t fd){ + return ((surf_workstation_CLM03_t)surf_workstation_resource_priv(resource))->write(ptr, size, fd); +} + +int surf_network_link_is_shared(surf_network_link_t link){ + return link->isShared(); +} + +double surf_network_link_get_bandwidth(surf_network_link_t link){ + return link->getBandwidth(); +} + +double surf_network_link_get_latency(surf_network_link_t link){ + return link->getLatency(); +} + +surf_action_t surf_cpu_execute(surf_cpu_t cpu, double size){ + return cpu->execute(size); +} + +surf_action_t surf_cpu_sleep(surf_cpu_t cpu, double duration){ + return cpu->sleep(duration); +} + +double surf_action_get_start_time(surf_action_t action){ + return action->m_start; +} + +double surf_action_get_finish_time(surf_action_t action){ + return action->m_finish; +} + +double surf_action_get_remains(surf_action_t action){ + return action->m_remains; +} + +void surf_action_unref(surf_action_t action){ + action->unref(); +} + +void surf_action_suspend(surf_action_t action){ + action->suspend(); +} + +void surf_action_resume(surf_action_t action){ + action->suspend(); +} + +void surf_action_cancel(surf_action_t action){ + action->cancel(); +} + +void surf_action_set_priority(surf_action_t action, double priority){ + action->setPriority(priority); +} + +void surf_action_set_category(surf_action_t action, const char *category){ + action->setCategory(category); +} + +void *surf_action_get_data(surf_action_t action){ + return action->p_data; +} + +void surf_action_set_data(surf_action_t action, void *data){ + action->p_data = data; +} + +e_surf_action_state_t surf_action_get_state(surf_action_t action){ + return action->getState(); +} + +int surf_action_get_cost(surf_action_t action){ + return action->m_cost; +} + +surf_file_t surf_storage_action_get_file(surf_storage_action_lmm_t action){ + return action->p_file; +} + +xbt_dict_t surf_storage_action_get_ls_dict(surf_storage_action_lmm_t action){ + return action->p_lsDict; +} diff --git a/src/surf/surf_private.h b/src/surf/surf_private.h index b6152bd44e..2153f8c643 100644 --- a/src/surf/surf_private.h +++ b/src/surf/surf_private.h @@ -6,8 +6,8 @@ #ifndef _SURF_SURF_PRIVATE_H #define _SURF_SURF_PRIVATE_H -#include "surf/solver.h" #include "surf/surf.h" +#include "surf/maxmin.h" #include "surf/trace_mgr.h" #include "xbt/log.h" #include "surf/surfxml_parse.h" @@ -17,6 +17,10 @@ #define NO_MAX_DURATION -1.0 +#ifdef __cplusplus +extern "C" { +#endif + extern xbt_dict_t watched_hosts_lib; extern const char *surf_action_state_names[6]; @@ -46,30 +50,30 @@ typedef struct surf_model_private { } s_surf_model_private_t; -double generic_maxmin_share_resources(xbt_swag_t running_actions, +/*FIXME:REMOVEdouble generic_maxmin_share_resources(xbt_swag_t running_actions, size_t offset, lmm_system_t sys, - void (*solve) (lmm_system_t)); + void (*solve) (lmm_system_t));*/ double generic_share_resources_lazy(double now, surf_model_t model); /* Generic functions common to all models */ void surf_action_init(void); void surf_action_exit(void); e_surf_action_state_t surf_action_state_get(surf_action_t action); /* cannot declare inline since we use a pointer to it */ -double surf_action_get_start_time(surf_action_t action); /* cannot declare inline since we use a pointer to it */ +//FIXME:DELETEdouble surf_action_get_start_time(surf_action_t action); /* cannot declare inline since we use a pointer to it */ double surf_action_get_finish_time(surf_action_t action); /* cannot declare inline since we use a pointer to it */ void surf_action_free(surf_action_t * action); -void surf_action_state_set(surf_action_t action, - e_surf_action_state_t state); -void surf_action_data_set(surf_action_t action, void *data); /* cannot declare inline since we use a pointer to it */ +/*FIXME:void surf_action_state_set(surf_action_t action, + e_surf_action_state_t state);*/ +//FIXME:void surf_action_data_set(surf_action_t action, void *data); /* cannot declare inline since we use a pointer to it */ void surf_action_lmm_update_index_heap(void *action, int i); /* callback for heap management shared by cpu and net models */ -void surf_action_lmm_heap_insert(xbt_heap_t heap, surf_action_lmm_t action, - double key, enum heap_action_type hat); +/*FIXME:void surf_action_lmm_heap_insert(xbt_heap_t heap, surf_action_lmm_t action, + double key, enum heap_action_type hat);*/ void surf_action_lmm_heap_remove(xbt_heap_t heap,surf_action_lmm_t action); void surf_action_cancel(surf_action_t action); -int surf_action_unref(surf_action_t action); +//FIXME:removeint surf_action_unref(surf_action_t action); void surf_action_suspend(surf_action_t action); void surf_action_resume(surf_action_t action); int surf_action_is_suspended(surf_action_t action); @@ -195,8 +199,8 @@ XBT_PUBLIC(void) generic_get_graph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict /** * Resource protected methods */ -XBT_PUBLIC(void) surfxml_bufferstack_push(int new); -XBT_PUBLIC(void) surfxml_bufferstack_pop(int new); +XBT_PUBLIC(void) surfxml_bufferstack_push(int _new); +XBT_PUBLIC(void) surfxml_bufferstack_pop(int _new); XBT_PUBLIC_DATA(int) surfxml_bufferstack_size; @@ -205,5 +209,8 @@ XBT_PUBLIC_DATA(int) surfxml_bufferstack_size; void TRACE_surf_host_set_power(double date, const char *resource, double power); void TRACE_surf_link_set_bandwidth(double date, const char *resource, double bandwidth); +#ifdef __cplusplus +} +#endif #endif /* _SURF_SURF_PRIVATE_H */ diff --git a/src/surf/surf_private.hpp b/src/surf/surf_private.hpp new file mode 100644 index 0000000000..1b540c6499 --- /dev/null +++ b/src/surf/surf_private.hpp @@ -0,0 +1,14 @@ + +#ifndef SURF_PRIVATE_HPP_ +#define SURF_PRIVATE_HPP_ + +#ifdef __cplusplus +extern "C" { +#endif +FILE *surf_fopen(const char *name, const char *mode); +#ifdef __cplusplus +} +#endif + + +#endif /* SURF_PRIVATE_HPP_ */ diff --git a/src/surf/surf_routing.cpp b/src/surf/surf_routing.cpp new file mode 100644 index 0000000000..545b75f4b7 --- /dev/null +++ b/src/surf/surf_routing.cpp @@ -0,0 +1,1267 @@ +#include "surf_routing.hpp" +#include "surf_routing_private.hpp" +#include "surf/surfxml_parse_values.h" +#include "surf/random_mgr.h" + +/** + * @ingroup SURF_build_api + * @brief A library containing all known workstations + */ +xbt_lib_t host_lib; + +int ROUTING_HOST_LEVEL; //Routing level +int SURF_CPU_LEVEL; //Surf cpu level +int SURF_WKS_LEVEL; //Surf workstation level +int SIMIX_HOST_LEVEL; //Simix level +int MSG_HOST_LEVEL; //Msg level +int SD_HOST_LEVEL; //Simdag level +int COORD_HOST_LEVEL=0; //Coordinates level +int NS3_HOST_LEVEL; //host node for ns3 + +xbt_dict_t watched_hosts_lib; + +/** + * @ingroup SURF_build_api + * @brief A library containing all known links + */ +xbt_lib_t link_lib; +int SD_LINK_LEVEL; //Simdag level +int SURF_LINK_LEVEL; //Surf level +int NS3_LINK_LEVEL; //link for ns3 + +xbt_lib_t as_router_lib; +int ROUTING_ASR_LEVEL; //Routing level +int COORD_ASR_LEVEL; //Coordinates level +int NS3_ASR_LEVEL; //host node for ns3 +int ROUTING_PROP_ASR_LEVEL; //Where the properties are stored + +static xbt_dict_t random_value = NULL; + + +/** @brief Retrieve a routing edge from its name + * + * Routing edges are either CPU/workstation and routers, whatever + */ +RoutingEdgePtr sg_routing_edge_by_name_or_null(const char *name) { + RoutingEdgePtr net_elm = (RoutingEdgePtr) xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL); + if (!net_elm) + net_elm = (RoutingEdgePtr) xbt_lib_get_or_null(as_router_lib, name, ROUTING_ASR_LEVEL); + return net_elm; +} + +/* Global vars */ +RoutingPlatfPtr routing_platf = NULL; +AsPtr current_routing = NULL; + +/* global parse functions */ +extern xbt_dynar_t mount_list; + +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route, surf, "Routing part of surf"); +} + +static void routing_parse_peer(sg_platf_peer_cbarg_t peer); /* peer bypass */ +static void routing_parse_Srandom(void); /* random bypass */ + +static void routing_parse_postparse(void); + +/* this lines are only for replace use like index in the model table */ +typedef enum { + SURF_MODEL_FULL = 0, + SURF_MODEL_FLOYD, + SURF_MODEL_DIJKSTRA, + SURF_MODEL_DIJKSTRACACHE, + SURF_MODEL_NONE, + SURF_MODEL_VIVALDI, + SURF_MODEL_CLUSTER +} e_routing_types; + +struct s_model_type routing_models[] = { + {"Full", + "Full routing data (fast, large memory requirements, fully expressive)", + model_full_create, model_full_end}, + {"Floyd", + "Floyd routing data (slow initialization, fast lookup, lesser memory requirements, shortest path routing only)", + model_floyd_create, model_floyd_end}, + {"Dijkstra", + "Dijkstra routing data (fast initialization, slow lookup, small memory requirements, shortest path routing only)", + model_dijkstra_create, model_dijkstra_both_end}, + {"DijkstraCache", + "Dijkstra routing data (fast initialization, fast lookup, small memory requirements, shortest path routing only)", + model_dijkstracache_create, model_dijkstra_both_end}, + {"none", "No routing (Unless you know what you are doing, avoid using this mode in combination with a non Constant network model).", + model_none_create, NULL}, + {"Vivaldi", "Vivaldi routing", + model_vivaldi_create, NULL}, + {"Cluster", "Cluster routing", + model_cluster_create, NULL}, + {NULL, NULL, NULL, NULL} +}; + +/** + * \brief Add a "host_link" to the network element list + */ +static void parse_S_host_link(sg_platf_host_link_cbarg_t host) +{ + RoutingEdgePtr info = (RoutingEdgePtr) xbt_lib_get_or_null(host_lib, host->id, ROUTING_HOST_LEVEL); + xbt_assert(info, "Host '%s' not found!", host->id); + xbt_assert(current_routing->p_modelDesc == &routing_models[SURF_MODEL_CLUSTER] || + current_routing->p_modelDesc == &routing_models[SURF_MODEL_VIVALDI], + "You have to be in model Cluster to use tag host_link!"); + + s_surf_parsing_link_up_down_t link_up_down; + link_up_down.link_up = xbt_lib_get_or_null(link_lib, host->link_up, SURF_LINK_LEVEL); + link_up_down.link_down = xbt_lib_get_or_null(link_lib, host->link_down, SURF_LINK_LEVEL); + link_up_down.limiter_link = NULL; + link_up_down.loopback_link = NULL; + + xbt_assert(link_up_down.link_up, "Link '%s' not found!",host->link_up); + xbt_assert(link_up_down.link_down, "Link '%s' not found!",host->link_down); + + if(!current_routing->p_linkUpDownList) + current_routing->p_linkUpDownList = xbt_dynar_new(sizeof(s_surf_parsing_link_up_down_t),NULL); + + // If dynar is is greater than edge id and if the host_link is already defined + if(xbt_dynar_length(current_routing->p_linkUpDownList) > info->m_id && + xbt_dynar_get_as(current_routing->p_linkUpDownList, info->m_id, void*)) + xbt_die("Host_link for '%s' is already defined!",host->id); + + XBT_DEBUG("Push Host_link for host '%s' to position %d", info->p_name, info->m_id); + xbt_dynar_set_as(current_routing->p_linkUpDownList, info->m_id, s_surf_parsing_link_up_down_t, link_up_down); +} + +/** + * \brief Add a "host" to the network element list + */ +static void parse_S_host(sg_platf_host_cbarg_t host) +{ + if (current_routing->p_hierarchy == SURF_ROUTING_NULL) + current_routing->p_hierarchy = SURF_ROUTING_BASE; + xbt_assert(!xbt_lib_get_or_null(host_lib, host->id, ROUTING_HOST_LEVEL), + "Reading a host, processing unit \"%s\" already exists", host->id); + + RoutingEdgePtr info = new RoutingEdge(); + info->p_rcComponent = current_routing; + info->p_rcType = SURF_NETWORK_ELEMENT_HOST; + info->p_name = xbt_strdup(host->id); + info->m_id = current_routing->parsePU(info); + xbt_lib_set(host_lib, host->id, ROUTING_HOST_LEVEL, (void *) info); + XBT_DEBUG("Having set name '%s' id '%d'", host->id, info->m_id); + + if(mount_list){ + xbt_lib_set(storage_lib, host->id, ROUTING_STORAGE_HOST_LEVEL, (void *) mount_list); + mount_list = NULL; + } + + if (host->coord && strcmp(host->coord, "")) { + unsigned int cursor; + char*str; + + if (!COORD_HOST_LEVEL) + xbt_die ("To use host coordinates, please add --cfg=network/coordinates:yes to your command line"); + /* Pre-parse the host coordinates -- FIXME factorize with routers by overloading the routing->parse_PU function*/ + xbt_dynar_t ctn_str = xbt_str_split_str(host->coord, " "); + xbt_dynar_t ctn = xbt_dynar_new(sizeof(double),NULL); + xbt_dynar_foreach(ctn_str,cursor, str) { + double val = atof(str); + xbt_dynar_push(ctn,&val); + } + xbt_dynar_shrink(ctn, 0); + xbt_dynar_free(&ctn_str); + xbt_lib_set(host_lib, host->id, COORD_HOST_LEVEL, (void *) ctn); + XBT_DEBUG("Having set host coordinates for '%s'",host->id); + } +} + +/** + * \brief Add a "router" to the network element list + */ +static void parse_S_router(sg_platf_router_cbarg_t router) +{ + if (current_routing->p_hierarchy == SURF_ROUTING_NULL) + current_routing->p_hierarchy = SURF_ROUTING_BASE; + xbt_assert(!xbt_lib_get_or_null(as_router_lib, router->id, ROUTING_ASR_LEVEL), + "Reading a router, processing unit \"%s\" already exists", + router->id); + + RoutingEdgePtr info = new RoutingEdge(); + info->p_rcComponent = current_routing; + info->p_rcType = SURF_NETWORK_ELEMENT_ROUTER; + info->p_name = xbt_strdup(router->id); + info->m_id = current_routing->parsePU(info); + xbt_lib_set(as_router_lib, router->id, ROUTING_ASR_LEVEL, (void *) info); + XBT_DEBUG("Having set name '%s' id '%d'", router->id, info->m_id); + + if (router->coord && strcmp(router->coord, "")) { + unsigned int cursor; + char*str; + + if (!COORD_ASR_LEVEL) + xbt_die ("To use host coordinates, please add --cfg=network/coordinates:yes to your command line"); + /* Pre-parse the host coordinates */ + xbt_dynar_t ctn_str = xbt_str_split_str(router->coord, " "); + xbt_dynar_t ctn = xbt_dynar_new(sizeof(double),NULL); + xbt_dynar_foreach(ctn_str,cursor, str) { + double val = atof(str); + xbt_dynar_push(ctn,&val); + } + xbt_dynar_shrink(ctn, 0); + xbt_dynar_free(&ctn_str); + xbt_lib_set(as_router_lib, router->id, COORD_ASR_LEVEL, (void *) ctn); + XBT_DEBUG("Having set router coordinates for '%s'",router->id); + } +} + +/** + * \brief Store the route by calling the set_route function of the current routing component + */ +static void parse_E_route(sg_platf_route_cbarg_t route) +{ + /*FIXME:REMOVE:xbt_assert(current_routing->parse_route, + "no defined method \"set_route\" in \"%s\"", + current_routing->name);*/ + + current_routing->parseRoute(route); +} + +/** + * \brief Store the ASroute by calling the set_ASroute function of the current routing component + */ +static void parse_E_ASroute(sg_platf_route_cbarg_t ASroute) +{ + /*FIXME:REMOVE:xbt_assert(current_routing->parse_ASroute, + "no defined method \"set_ASroute\" in \"%s\"", + current_routing->name);*/ + current_routing->parseASroute(ASroute); +} + +/** + * \brief Store the bypass route by calling the set_bypassroute function of the current routing component + */ +static void parse_E_bypassRoute(sg_platf_route_cbarg_t route) +{ + /*FIXME:REMOVE:xbt_assert(current_routing->parse_bypassroute, + "Bypassing mechanism not implemented by routing '%s'", + current_routing->name);*/ + + current_routing->parseBypassroute(route); +} + +/** + * \brief Store the bypass route by calling the set_bypassroute function of the current routing component + */ +static void parse_E_bypassASroute(sg_platf_route_cbarg_t ASroute) +{ + /*FIXME:REMOVE:xbt_assert(current_routing->parse_bypassroute, + "Bypassing mechanism not implemented by routing '%s'", + current_routing->name);*/ + current_routing->parseBypassroute(ASroute); +} + +static void routing_parse_trace(sg_platf_trace_cbarg_t trace) +{ + tmgr_trace_t tmgr_trace; + if (!trace->file || strcmp(trace->file, "") != 0) { + tmgr_trace = tmgr_trace_new_from_file(trace->file); + } else if (strcmp(trace->pc_data, "") == 0) { + tmgr_trace = NULL; + } else { + tmgr_trace = + tmgr_trace_new_from_string(trace->id, trace->pc_data, + trace->periodicity); + } + xbt_dict_set(traces_set_list, trace->id, (void *) tmgr_trace, NULL); +} + +static void routing_parse_trace_connect(sg_platf_trace_connect_cbarg_t trace_connect) +{ + xbt_assert(xbt_dict_get_or_null + (traces_set_list, trace_connect->trace), + "Cannot connect trace %s to %s: trace unknown", + trace_connect->trace, + trace_connect->element); + + switch (trace_connect->kind) { + case SURF_TRACE_CONNECT_KIND_HOST_AVAIL: + xbt_dict_set(trace_connect_list_host_avail, + trace_connect->trace, + xbt_strdup(trace_connect->element), NULL); + break; + case SURF_TRACE_CONNECT_KIND_POWER: + xbt_dict_set(trace_connect_list_power, trace_connect->trace, + xbt_strdup(trace_connect->element), NULL); + break; + case SURF_TRACE_CONNECT_KIND_LINK_AVAIL: + xbt_dict_set(trace_connect_list_link_avail, + trace_connect->trace, + xbt_strdup(trace_connect->element), NULL); + break; + case SURF_TRACE_CONNECT_KIND_BANDWIDTH: + xbt_dict_set(trace_connect_list_bandwidth, + trace_connect->trace, + xbt_strdup(trace_connect->element), NULL); + break; + case SURF_TRACE_CONNECT_KIND_LATENCY: + xbt_dict_set(trace_connect_list_latency, trace_connect->trace, + xbt_strdup(trace_connect->element), NULL); + break; + default: + xbt_die("Cannot connect trace %s to %s: kind of trace unknown", + trace_connect->trace, trace_connect->element); + break; + } +} + +extern int _sg_init_status; /* yay, this is an horrible hack */ + +/** + * \brief Make a new routing component to the platform + * + * Add a new autonomous system to the platform. Any elements (such as host, + * router or sub-AS) added after this call and before the corresponding call + * to sg_platf_new_AS_close() will be added to this AS. + * + * Once this function was called, the configuration concerning the used + * models cannot be changed anymore. + * + * @param AS_id name of this autonomous system. Must be unique in the platform + * @param wanted_routing_type one of Full, Floyd, Dijkstra or similar. Full list in the variable routing_models, in src/surf/surf_routing.c + */ +void routing_AS_begin(sg_platf_AS_cbarg_t AS) +{ + XBT_DEBUG("routing_AS_begin"); + routing_model_description_t model = NULL; + + xbt_assert(!xbt_lib_get_or_null + (as_router_lib, AS->id, ROUTING_ASR_LEVEL), + "The AS \"%s\" already exists", AS->id); + + _sg_init_status = 2; /* horrible hack: direct access to the global controlling the level of configuration to prevent any further config */ + + /* search the routing model */ + switch(AS->routing){ + case A_surfxml_AS_routing_Cluster: model = &routing_models[SURF_MODEL_CLUSTER];break; + case A_surfxml_AS_routing_Dijkstra: model = &routing_models[SURF_MODEL_DIJKSTRA];break; + case A_surfxml_AS_routing_DijkstraCache: model = &routing_models[SURF_MODEL_DIJKSTRACACHE];break; + case A_surfxml_AS_routing_Floyd: model = &routing_models[SURF_MODEL_FLOYD];break; + case A_surfxml_AS_routing_Full: model = &routing_models[SURF_MODEL_FULL];break; + case A_surfxml_AS_routing_None: model = &routing_models[SURF_MODEL_NONE];break; + case A_surfxml_AS_routing_Vivaldi: model = &routing_models[SURF_MODEL_VIVALDI];break; + default: xbt_die("Not a valid model!!!"); + break; + } + + /* make a new routing component */ + AsPtr new_as = model->create(); + + new_as->p_modelDesc = model; + new_as->p_hierarchy = SURF_ROUTING_NULL; + new_as->p_name = xbt_strdup(AS->id); + + RoutingEdgePtr info = new RoutingEdge(); + + if (current_routing == NULL && routing_platf->p_root == NULL) { + + /* it is the first one */ + new_as->p_routingFather = NULL; + routing_platf->p_root = new_as; + info->m_id = -1; + } else if (current_routing != NULL && routing_platf->p_root != NULL) { + + xbt_assert(!xbt_dict_get_or_null + (current_routing->p_routingSons, AS->id), + "The AS \"%s\" already exists", AS->id); + /* it is a part of the tree */ + new_as->p_routingFather = current_routing; + /* set the father behavior */ + if (current_routing->p_hierarchy == SURF_ROUTING_NULL) + current_routing->p_hierarchy = SURF_ROUTING_RECURSIVE; + /* add to the sons dictionary */ + xbt_dict_set(current_routing->p_routingSons, AS->id, + (void *) new_as, NULL); + /* add to the father element list */ + info->m_id = current_routing->parseAS(info); + } else { + THROWF(arg_error, 0, "All defined components must be belong to a AS"); + } + + info->p_rcComponent = new_as->p_routingFather; + info->p_rcType = SURF_NETWORK_ELEMENT_AS; + info->p_name = new_as->p_name; + + xbt_lib_set(as_router_lib, info->p_name, ROUTING_ASR_LEVEL, + (void *) info); + XBT_DEBUG("Having set name '%s' id '%d'", new_as->p_name, info->m_id); + + /* set the new current component of the tree */ + current_routing = new_as; + current_routing->p_netElem = info; + +} + +/** + * \brief Specify that the current description of AS is finished + * + * Once you've declared all the content of your AS, you have to close + * it with this call. Your AS is not usable until you call this function. + * + * @fixme: this call is not as robust as wanted: bad things WILL happen + * if you call it twice for the same AS, or if you forget calling it, or + * even if you add stuff to a closed AS + * + */ +void routing_AS_end(sg_platf_AS_cbarg_t AS) +{ + + if (current_routing == NULL) { + THROWF(arg_error, 0, "Close an AS, but none was under construction"); + } else { + if (current_routing->p_modelDesc->end) + current_routing->p_modelDesc->end(current_routing); + current_routing = current_routing->p_routingFather; + } +} + +/* Aux Business methods */ + +/** + * \brief Get the AS father and the first elements of the chain + * + * \param src the source host name + * \param dst the destination host name + * + * Get the common father of the to processing units, and the first different + * father in the chain + */ +static void elements_father(sg_routing_edge_t src, sg_routing_edge_t dst, + AS_t * res_father, + AS_t * res_src, + AS_t * res_dst) +{ + xbt_assert(src && dst, "bad parameters for \"elements_father\" method"); +#define ELEMENTS_FATHER_MAXDEPTH 16 /* increase if it is not enough */ + AS_t src_as, dst_as; + AS_t path_src[ELEMENTS_FATHER_MAXDEPTH]; + AS_t path_dst[ELEMENTS_FATHER_MAXDEPTH]; + int index_src = 0; + int index_dst = 0; + AS_t current; + AS_t current_src; + AS_t current_dst; + AS_t father; + + /* (1) find the as where the src and dst are located */ + sg_routing_edge_t src_data = src; + sg_routing_edge_t dst_data = dst; + src_as = src_data->p_rcComponent; + dst_as = dst_data->p_rcComponent; +#ifndef NDEBUG + char* src_name = src_data->p_name; + char* dst_name = dst_data->p_name; +#endif + + xbt_assert(src_as && dst_as, + "Ask for route \"from\"(%s) or \"to\"(%s) no found", src_name, dst_name); + + /* (2) find the path to the root routing component */ + for (current = src_as; current != NULL; current = current->p_routingFather) { + if (index_src >= ELEMENTS_FATHER_MAXDEPTH) + xbt_die("ELEMENTS_FATHER_MAXDEPTH should be increased for path_src"); + path_src[index_src++] = current; + } + for (current = dst_as; current != NULL; current = current->p_routingFather) { + if (index_dst >= ELEMENTS_FATHER_MAXDEPTH) + xbt_die("ELEMENTS_FATHER_MAXDEPTH should be increased for path_dst"); + path_dst[index_dst++] = current; + } + + /* (3) find the common father */ + do { + current_src = path_src[--index_src]; + current_dst = path_dst[--index_dst]; + } while (index_src > 0 && index_dst > 0 && current_src == current_dst); + + /* (4) they are not in the same routing component, make the path */ + if (current_src == current_dst) + father = current_src; + else + father = path_src[index_src + 1]; + + /* (5) result generation */ + *res_father = father; /* first the common father of src and dst */ + *res_src = current_src; /* second the first different father of src */ + *res_dst = current_dst; /* three the first different father of dst */ + +#undef ELEMENTS_FATHER_MAXDEPTH +} + +/* Global Business methods */ + +/** + * \brief Recursive function for get_route_latency + * + * \param src the source host name + * \param dst the destination host name + * \param *route the route where the links are stored. It is either NULL or a ready to use dynar + * \param *latency the latency, if needed + * + * This function is called by "get_route" and "get_latency". It allows to walk + * recursively through the ASes tree. + */ +static void _get_route_and_latency(RoutingEdgePtr src, RoutingEdgePtr dst, + xbt_dynar_t * links, double *latency) +{ + s_sg_platf_route_cbarg_t route; + memset(&route,0,sizeof(route)); + + xbt_assert(src && dst, "bad parameters for \"_get_route_latency\" method"); + XBT_DEBUG("Solve route/latency \"%s\" to \"%s\"", src->p_name, dst->p_name); + + /* Find how src and dst are interconnected */ + AsPtr common_father, src_father, dst_father; + elements_father(src, dst, &common_father, &src_father, &dst_father); + XBT_DEBUG("elements_father: common father '%s' src_father '%s' dst_father '%s'", + common_father->p_name, src_father->p_name, dst_father->p_name); + + /* Check whether a direct bypass is defined */ + sg_platf_route_cbarg_t e_route_bypass = NULL; + //FIXME:REMOVE:if (common_father->get_bypass_route) + e_route_bypass = common_father->getBypassRoute(src, dst, latency); + + /* Common ancestor is kind enough to declare a bypass route from src to dst -- use it and bail out */ + if (e_route_bypass) { + xbt_dynar_merge(links, &e_route_bypass->link_list); + //FIXME:generic_free_route(e_route_bypass); + return; + } + + /* If src and dst are in the same AS, life is good */ + if (src_father == dst_father) { /* SURF_ROUTING_BASE */ + route.link_list = *links; + common_father->getRouteAndLatency(src, dst, &route, latency); + // if vivaldi latency+=vivaldi(src,dst) + return; + } + + /* Not in the same AS, no bypass. We'll have to find our path between the ASes recursively*/ + + route.link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL); + // Find the net_card corresponding to father + RoutingEdgePtr src_father_net_elm = src_father->p_netElem; + RoutingEdgePtr dst_father_net_elm = dst_father->p_netElem; + + common_father->getRouteAndLatency(src_father_net_elm, dst_father_net_elm, + &route, latency); + + xbt_assert((route.gw_src != NULL) && (route.gw_dst != NULL), + "bad gateways for route from \"%s\" to \"%s\"", src->p_name, dst->p_name); + + sg_routing_edge_t src_gateway_net_elm = route.gw_src; + sg_routing_edge_t dst_gateway_net_elm = route.gw_dst; + + /* If source gateway is not our source, we have to recursively find our way up to this point */ + if (src != src_gateway_net_elm) + _get_route_and_latency(src, src_gateway_net_elm, links, latency); + xbt_dynar_merge(links, &route.link_list); + + /* If dest gateway is not our destination, we have to recursively find our way from this point */ + if (dst_gateway_net_elm != dst) + _get_route_and_latency(dst_gateway_net_elm, dst, links, latency); + + // if vivaldi latency+=vivaldi(src_gateway,dst_gateway) +} + +AS_t surf_platf_get_root(routing_platf_t platf){ + return platf->p_root; +} + +e_surf_network_element_type_t surf_routing_edge_get_rc_type(sg_routing_edge_t edge){ + return edge->p_rcType; +} + + +/** + * \brief Find a route between hosts + * + * \param src the network_element_t for src host + * \param dst the network_element_t for dst host + * \param route where to store the list of links. + * If *route=NULL, create a short lived dynar. Else, fill the provided dynar + * \param latency where to store the latency experienced on the path (or NULL if not interested) + * It is the caller responsability to initialize latency to 0 (we add to provided route) + * \pre route!=NULL + * + * walk through the routing components tree and find a route between hosts + * by calling the differents "get_route" functions in each routing component. + */ +void RoutingPlatf::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, + xbt_dynar_t* route, double *latency) +{ + XBT_DEBUG("routing_get_route_and_latency from %s to %s", src->p_name, dst->p_name); + if (!*route) { + xbt_dynar_reset(routing_platf->p_lastRoute); + *route = routing_platf->p_lastRoute; + } + + _get_route_and_latency(src, dst, route, latency); + + xbt_assert(!latency || *latency >= 0.0, + "negative latency on route between \"%s\" and \"%s\"", src->p_name, dst->p_name); +} + +static xbt_dynar_t recursive_get_onelink_routes(AsPtr rc) +{ + xbt_dynar_t ret = xbt_dynar_new(sizeof(OnelinkPtr), xbt_free); + + //adding my one link routes + xbt_dynar_t onelink_mine = rc->getOneLinkRoutes(); + if (onelink_mine) + xbt_dynar_merge(&ret,&onelink_mine); + + //recursing + char *key; + xbt_dict_cursor_t cursor = NULL; + AS_t rc_child; + xbt_dict_foreach(rc->p_routingSons, cursor, key, rc_child) { + xbt_dynar_t onelink_child = recursive_get_onelink_routes(rc_child); + if (onelink_child) + xbt_dynar_merge(&ret,&onelink_child); + } + return ret; +} + +static xbt_dynar_t get_onelink_routes(void) +{ + return recursive_get_onelink_routes(routing_platf->p_root); +} + +e_surf_network_element_type_t routing_get_network_element_type(const char *name) +{ + RoutingEdgePtr rc = sg_routing_edge_by_name_or_null(name); + if (rc) + return rc->p_rcType; + + return SURF_NETWORK_ELEMENT_NULL; +} + +/** + * \brief Generic method: create the global routing schema + * + * Make a global routing structure and set all the parsing functions. + */ +void routing_model_create( void *loopback) +{ + /* config the uniq global routing */ + routing_platf = new RoutingPlatf(); + routing_platf->p_root = NULL; + //FIXME:routing_platf->get_onelink_routes = get_onelink_routes; + //FIXME:routing_platf->loopback = loopback; + routing_platf->p_lastRoute = xbt_dynar_new(sizeof(sg_routing_link_t),NULL); + /* no current routing at moment */ + current_routing = NULL; +} + + +/* ************************************************** */ +/* ********** PATERN FOR NEW ROUTING **************** */ + +/* The minimal configuration of a new routing model need the next functions, + * also you need to set at the start of the file, the new model in the model + * list. Remember keep the null ending of the list. + */ +/*** Routing model structure ***/ +// typedef struct { +// s_routing_component_t generic_routing; +// /* things that your routing model need */ +// } s_routing_component_NEW_t,*routing_component_NEW_t; + +/*** Parse routing model functions ***/ +// static void model_NEW_set_processing_unit(routing_component_t rc, const char* name) {} +// static void model_NEW_set_autonomous_system(routing_component_t rc, const char* name) {} +// static void model_NEW_set_route(routing_component_t rc, const char* src, const char* dst, route_t route) {} +// static void model_NEW_set_ASroute(routing_component_t rc, const char* src, const char* dst, route_extended_t route) {} +// static void model_NEW_set_bypassroute(routing_component_t rc, const char* src, const char* dst, route_extended_t e_route) {} + +/*** Business methods ***/ +// static route_extended_t NEW_get_route(routing_component_t rc, const char* src,const char* dst) {return NULL;} +// static route_extended_t NEW_get_bypass_route(routing_component_t rc, const char* src,const char* dst) {return NULL;} +// static void NEW_finalize(routing_component_t rc) { xbt_free(rc);} + +/*** Creation routing model functions ***/ +// static void* model_NEW_create(void) { +// routing_component_NEW_t new_component = xbt_new0(s_routing_component_NEW_t,1); +// new_component->generic_routing.set_processing_unit = model_NEW_set_processing_unit; +// new_component->generic_routing.set_autonomous_system = model_NEW_set_autonomous_system; +// new_component->generic_routing.set_route = model_NEW_set_route; +// new_component->generic_routing.set_ASroute = model_NEW_set_ASroute; +// new_component->generic_routing.set_bypassroute = model_NEW_set_bypassroute; +// new_component->generic_routing.get_route = NEW_get_route; +// new_component->generic_routing.get_bypass_route = NEW_get_bypass_route; +// new_component->generic_routing.finalize = NEW_finalize; +// /* initialization of internal structures */ +// return new_component; +// } /* mandatory */ +// static void model_NEW_load(void) {} /* mandatory */ +// static void model_NEW_unload(void) {} /* mandatory */ +// static void model_NEW_end(void) {} /* mandatory */ + +/* ************************************************************************** */ +/* ************************* GENERIC PARSE FUNCTIONS ************************ */ + +void routing_cluster_add_backbone(void* bb) { + xbt_assert(current_routing->p_modelDesc == &routing_models[SURF_MODEL_CLUSTER], + "You have to be in model Cluster to use tag backbone!"); + /*FIXME:xbt_assert(!((as_cluster_t)current_routing)->p_backbone, "The backbone link is already defined!"); + ((as_cluster_t)current_routing)->p_backbone = bb;*/ + XBT_DEBUG("Add a backbone to AS '%s'",current_routing->p_name); +} + +static void routing_parse_cabinet(sg_platf_cabinet_cbarg_t cabinet) +{ + int start, end, i; + char *groups , *host_id , *link_id = NULL; + unsigned int iter; + xbt_dynar_t radical_elements; + xbt_dynar_t radical_ends; + + //Make all hosts + radical_elements = xbt_str_split(cabinet->radical, ","); + xbt_dynar_foreach(radical_elements, iter, groups) { + + radical_ends = xbt_str_split(groups, "-"); + start = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 0, char *)); + + switch (xbt_dynar_length(radical_ends)) { + case 1: + end = start; + break; + case 2: + end = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 1, char *)); + break; + default: + surf_parse_error("Malformed radical"); + break; + } + s_sg_platf_host_cbarg_t host; + memset(&host, 0, sizeof(host)); + host.initial_state = SURF_RESOURCE_ON; + host.power_peak = cabinet->power; + host.power_scale = 1.0; + host.core_amount = 1; + + s_sg_platf_link_cbarg_t link; + memset(&link, 0, sizeof(link)); + link.state = SURF_RESOURCE_ON; + link.policy = SURF_LINK_FULLDUPLEX; + link.latency = cabinet->lat; + link.bandwidth = cabinet->bw; + + s_sg_platf_host_link_cbarg_t host_link; + memset(&host_link, 0, sizeof(host_link)); + + for (i = start; i <= end; i++) { + host_id = bprintf("%s%d%s",cabinet->prefix,i,cabinet->suffix); + link_id = bprintf("link_%s%d%s",cabinet->prefix,i,cabinet->suffix); + host.id = host_id; + link.id = link_id; + sg_platf_new_host(&host); + sg_platf_new_link(&link); + + char* link_up = bprintf("%s_UP",link_id); + char* link_down = bprintf("%s_DOWN",link_id); + host_link.id = host_id; + host_link.link_up = link_up; + host_link.link_down= link_down; + sg_platf_new_host_link(&host_link); + + free(host_id); + free(link_id); + free(link_up); + free(link_down); + } + + xbt_dynar_free(&radical_ends); + } + xbt_dynar_free(&radical_elements); +} + +static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster) +{ + char *host_id, *groups, *link_id = NULL; + xbt_dict_t patterns = NULL; + + s_sg_platf_host_cbarg_t host; + s_sg_platf_link_cbarg_t link; + + unsigned int iter; + int start, end, i; + xbt_dynar_t radical_elements; + xbt_dynar_t radical_ends; + + if ((cluster->availability_trace && strcmp(cluster->availability_trace, "")) + || (cluster->state_trace && strcmp(cluster->state_trace, ""))) { + patterns = xbt_dict_new_homogeneous(xbt_free_f); + xbt_dict_set(patterns, "id", xbt_strdup(cluster->id), NULL); + xbt_dict_set(patterns, "prefix", xbt_strdup(cluster->prefix), NULL); + xbt_dict_set(patterns, "suffix", xbt_strdup(cluster->suffix), NULL); + } + + XBT_DEBUG("", cluster->id); + s_sg_platf_AS_cbarg_t AS = SG_PLATF_AS_INITIALIZER; + AS.id = cluster->id; + AS.routing = A_surfxml_AS_routing_Cluster; + sg_platf_new_AS_begin(&AS); + + current_routing->p_linkUpDownList + = xbt_dynar_new(sizeof(s_surf_parsing_link_up_down_t),NULL); + + //Make all hosts + radical_elements = xbt_str_split(cluster->radical, ","); + xbt_dynar_foreach(radical_elements, iter, groups) { + + radical_ends = xbt_str_split(groups, "-"); + start = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 0, char *)); + + switch (xbt_dynar_length(radical_ends)) { + case 1: + end = start; + break; + case 2: + end = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 1, char *)); + break; + default: + surf_parse_error("Malformed radical"); + break; + } + for (i = start; i <= end; i++) { + host_id = + bprintf("%s%d%s", cluster->prefix, i, cluster->suffix); + link_id = bprintf("%s_link_%d", cluster->id, i); + + XBT_DEBUG("", host_id, cluster->power); + + memset(&host, 0, sizeof(host)); + host.id = host_id; + if (cluster->availability_trace && strcmp(cluster->availability_trace, "")) { + xbt_dict_set(patterns, "radical", bprintf("%d", i), NULL); + char *avail_file = xbt_str_varsubst(cluster->availability_trace, patterns); + XBT_DEBUG("\tavailability_file=\"%s\"", avail_file); + host.power_trace = tmgr_trace_new_from_file(avail_file); + xbt_free(avail_file); + } else { + XBT_DEBUG("\tavailability_file=\"\""); + } + + if (cluster->state_trace && strcmp(cluster->state_trace, "")) { + char *avail_file = xbt_str_varsubst(cluster->state_trace, patterns); + XBT_DEBUG("\tstate_file=\"%s\"", avail_file); + host.state_trace = tmgr_trace_new_from_file(avail_file); + xbt_free(avail_file); + } else { + XBT_DEBUG("\tstate_file=\"\""); + } + + host.power_peak = cluster->power; + host.power_scale = 1.0; + host.core_amount = cluster->core_amount; + host.initial_state = SURF_RESOURCE_ON; + host.coord = ""; + sg_platf_new_host(&host); + XBT_DEBUG(""); + + XBT_DEBUG("", link_id, + cluster->bw, cluster->lat); + + memset(&link, 0, sizeof(link)); + link.id = link_id; + link.bandwidth = cluster->bw; + link.latency = cluster->lat; + link.state = SURF_RESOURCE_ON; + link.policy = cluster->sharing_policy; + sg_platf_new_link(&link); + + s_surf_parsing_link_up_down_t info; + + if (link.policy == SURF_LINK_FULLDUPLEX) { + char *tmp_link = bprintf("%s_UP", link_id); + info.link_up = + xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL); + free(tmp_link); + tmp_link = bprintf("%s_DOWN", link_id); + info.link_down = + xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL); + free(tmp_link); + } else { + info.link_up = xbt_lib_get_or_null(link_lib, link_id, SURF_LINK_LEVEL); + info.link_down = info.link_up; + } + + if(cluster->limiter_link!=0){ + char *tmp_link = bprintf("%s_limiter", link_id); + XBT_DEBUG("", tmp_link, + cluster->limiter_link); + + + memset(&link, 0, sizeof(link)); + link.id = tmp_link; + link.bandwidth = cluster->limiter_link; + link.latency = 0; + link.state = SURF_RESOURCE_ON; + link.policy = SURF_LINK_SHARED; + sg_platf_new_link(&link); + info.limiter_link = + xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL); + free(tmp_link); + }else{ + info.limiter_link =NULL; + } + + if(cluster->loopback_bw!=0 || cluster->loopback_lat!=0){ + char *tmp_link = bprintf("%s_loopback", link_id); + XBT_DEBUG("", tmp_link, + cluster->limiter_link); + + + memset(&link, 0, sizeof(link)); + link.id = tmp_link; + link.bandwidth = cluster->loopback_bw; + link.latency = cluster->loopback_lat; + link.state = SURF_RESOURCE_ON; + link.policy = SURF_LINK_FATPIPE; + sg_platf_new_link(&link); + info.loopback_link = + xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL); + free(tmp_link); + }else{ + info.loopback_link =NULL; + } + + xbt_dynar_push(current_routing->p_linkUpDownList, &info); + xbt_free(link_id); + xbt_free(host_id); + } + + xbt_dynar_free(&radical_ends); + } + xbt_dynar_free(&radical_elements); + + // Add a router. It is magically used thanks to the way in which surf_routing_cluster is written, + // and it's very useful to connect clusters together + XBT_DEBUG(" "); + XBT_DEBUG("", cluster->router_id); + char *newid = NULL; + s_sg_platf_router_cbarg_t router; + memset(&router, 0, sizeof(router)); + router.id = cluster->router_id; + router.coord = ""; + if (!router.id || !strcmp(router.id, "")) + router.id = newid = + bprintf("%s%s_router%s", cluster->prefix, cluster->id, + cluster->suffix); + sg_platf_new_router(&router); + ((AsClusterPtr)current_routing)->p_router = (RoutingEdgePtr) xbt_lib_get_or_null(as_router_lib, router.id, ROUTING_ASR_LEVEL); + free(newid); + + //Make the backbone + if ((cluster->bb_bw != 0) || (cluster->bb_lat != 0)) { + char *link_backbone = bprintf("%s_backbone", cluster->id); + XBT_DEBUG("", link_backbone, + cluster->bb_bw, cluster->bb_lat); + + memset(&link, 0, sizeof(link)); + link.id = link_backbone; + link.bandwidth = cluster->bb_bw; + link.latency = cluster->bb_lat; + link.state = SURF_RESOURCE_ON; + link.policy = cluster->bb_sharing_policy; + + sg_platf_new_link(&link); + + routing_cluster_add_backbone(xbt_lib_get_or_null(link_lib, link_backbone, SURF_LINK_LEVEL)); + + free(link_backbone); + } + + XBT_DEBUG(""); + sg_platf_new_AS_end(); + XBT_DEBUG(" "); + xbt_dict_free(&patterns); // no op if it were never set +} + +static void routing_parse_postparse(void) { + xbt_dict_free(&random_value); +} + +static void routing_parse_peer(sg_platf_peer_cbarg_t peer) +{ + char *host_id = NULL; + char *link_id; + + XBT_DEBUG(" "); + host_id = HOST_PEER(peer->id); + link_id = LINK_PEER(peer->id); + + XBT_DEBUG("", host_id, peer->power); + s_sg_platf_host_cbarg_t host; + memset(&host, 0, sizeof(host)); + host.initial_state = SURF_RESOURCE_ON; + host.id = host_id; + host.power_peak = peer->power; + host.power_scale = 1.0; + host.power_trace = peer->availability_trace; + host.state_trace = peer->state_trace; + host.core_amount = 1; + host.coord = peer->coord; + sg_platf_new_host(&host); + + s_sg_platf_link_cbarg_t link; + memset(&link, 0, sizeof(link)); + link.state = SURF_RESOURCE_ON; + link.policy = SURF_LINK_SHARED; + link.latency = peer->lat; + + char* link_up = bprintf("%s_UP",link_id); + XBT_DEBUG("", link_up, + peer->bw_out, peer->lat); + link.id = link_up; + link.bandwidth = peer->bw_out; + sg_platf_new_link(&link); + + char* link_down = bprintf("%s_DOWN",link_id); + XBT_DEBUG("", link_down, + peer->bw_in, peer->lat); + link.id = link_down; + link.bandwidth = peer->bw_in; + sg_platf_new_link(&link); + + XBT_DEBUG("", host_id,link_up,link_down); + s_sg_platf_host_link_cbarg_t host_link; + memset(&host_link, 0, sizeof(host_link)); + host_link.id = host_id; + host_link.link_up = link_up; + host_link.link_down= link_down; + sg_platf_new_host_link(&host_link); + + XBT_DEBUG(" "); + + //xbt_dynar_free(&tab_elements_num); + free(host_id); + free(link_id); + free(link_up); + free(link_down); +} + +static void routing_parse_Srandom(void) +{ + double mean, std, min, max, seed; + char *random_id = A_surfxml_random_id; + char *random_radical = A_surfxml_random_radical; + char *rd_name = NULL; + char *rd_value; + mean = surf_parse_get_double(A_surfxml_random_mean); + std = surf_parse_get_double(A_surfxml_random_std___deviation); + min = surf_parse_get_double(A_surfxml_random_min); + max = surf_parse_get_double(A_surfxml_random_max); + seed = surf_parse_get_double(A_surfxml_random_seed); + + double res = 0; + int i = 0; + random_data_t random = xbt_new0(s_random_data_t, 1); + char *tmpbuf; + + xbt_dynar_t radical_elements; + unsigned int iter; + char *groups; + int start, end; + xbt_dynar_t radical_ends; + + switch (A_surfxml_random_generator) { + case AU_surfxml_random_generator: + case A_surfxml_random_generator_NONE: + random->generator = NONE; + break; + case A_surfxml_random_generator_DRAND48: + random->generator = DRAND48; + break; + case A_surfxml_random_generator_RAND: + random->generator = RAND; + break; + case A_surfxml_random_generator_RNGSTREAM: + random->generator = RNGSTREAM; + break; + default: + surf_parse_error("Invalid random generator"); + break; + } + random->seed = seed; + random->min = min; + random->max = max; + + /* Check user stupidities */ + if (max < min) + THROWF(arg_error, 0, "random->max < random->min (%f < %f)", max, min); + if (mean < min) + THROWF(arg_error, 0, "random->mean < random->min (%f < %f)", mean, min); + if (mean > max) + THROWF(arg_error, 0, "random->mean > random->max (%f > %f)", mean, max); + + /* normalize the mean and standard deviation before storing */ + random->mean = (mean - min) / (max - min); + random->std = std / (max - min); + + if (random->mean * (1 - random->mean) < random->std * random->std) + THROWF(arg_error, 0, "Invalid mean and standard deviation (%f and %f)", + random->mean, random->std); + + XBT_DEBUG + ("id = '%s' min = '%f' max = '%f' mean = '%f' std_deviatinon = '%f' generator = '%d' seed = '%ld' radical = '%s'", + random_id, random->min, random->max, random->mean, random->std, + (int)random->generator, random->seed, random_radical); + + if (!random_value) + random_value = xbt_dict_new_homogeneous(free); + + if (!strcmp(random_radical, "")) { + res = random_generate(random); + rd_value = bprintf("%f", res); + xbt_dict_set(random_value, random_id, rd_value, NULL); + } else { + radical_elements = xbt_str_split(random_radical, ","); + xbt_dynar_foreach(radical_elements, iter, groups) { + radical_ends = xbt_str_split(groups, "-"); + switch (xbt_dynar_length(radical_ends)) { + case 1: + xbt_assert(!xbt_dict_get_or_null(random_value, random_id), + "Custom Random '%s' already exists !", random_id); + res = random_generate(random); + tmpbuf = + bprintf("%s%d", random_id, + atoi(xbt_dynar_getfirst_as(radical_ends, char *))); + xbt_dict_set(random_value, tmpbuf, bprintf("%f", res), NULL); + xbt_free(tmpbuf); + break; + + case 2: + start = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 0, char *)); + end = surf_parse_get_int(xbt_dynar_get_as(radical_ends, 1, char *)); + for (i = start; i <= end; i++) { + xbt_assert(!xbt_dict_get_or_null(random_value, random_id), + "Custom Random '%s' already exists !", bprintf("%s%d", + random_id, + i)); + res = random_generate(random); + tmpbuf = bprintf("%s%d", random_id, i); + xbt_dict_set(random_value, tmpbuf, bprintf("%f", res), NULL); + xbt_free(tmpbuf); + } + break; + default: + XBT_CRITICAL("Malformed radical"); + break; + } + res = random_generate(random); + rd_name = bprintf("%s_router", random_id); + rd_value = bprintf("%f", res); + xbt_dict_set(random_value, rd_name, rd_value, NULL); + + xbt_dynar_free(&radical_ends); + } + free(rd_name); + xbt_dynar_free(&radical_elements); + } +} + +void routing_register_callbacks() +{ + sg_platf_host_add_cb(parse_S_host); + sg_platf_router_add_cb(parse_S_router); + sg_platf_host_link_add_cb(parse_S_host_link); + sg_platf_route_add_cb(parse_E_route); + sg_platf_ASroute_add_cb(parse_E_ASroute); + sg_platf_bypassRoute_add_cb(parse_E_bypassRoute); + sg_platf_bypassASroute_add_cb(parse_E_bypassASroute); + + sg_platf_cluster_add_cb(routing_parse_cluster); + sg_platf_cabinet_add_cb(routing_parse_cabinet); + + sg_platf_peer_add_cb(routing_parse_peer); + sg_platf_postparse_add_cb(routing_parse_postparse); + + /* we care about the ASes while parsing the platf. Incredible, isnt it? */ + sg_platf_AS_end_add_cb(routing_AS_end); + sg_platf_AS_begin_add_cb(routing_AS_begin); + + sg_platf_trace_add_cb(routing_parse_trace); + sg_platf_trace_connect_add_cb(routing_parse_trace_connect); + +#ifdef HAVE_TRACING + instr_routing_define_callbacks(); +#endif +} + +/** + * \brief Recursive function for finalize + * + * \param rc the source host name + * + * This fuction is call by "finalize". It allow to finalize the + * AS or routing components. It delete all the structures. + */ +static void finalize_rec(AsPtr as) { + xbt_dict_cursor_t cursor = NULL; + char *key; + AS_t elem; + + xbt_dict_foreach(as->p_routingSons, cursor, key, elem) { + finalize_rec(elem); + } + + delete as;; +} + +/** \brief Frees all memory allocated by the routing module */ +void routing_exit(void) { + if (!routing_platf) + return; + xbt_dynar_free(&routing_platf->p_lastRoute); + finalize_rec(routing_platf->p_root); + xbt_free(routing_platf); +} + +AS_t surf_AS_get_routing_root() { + return routing_platf->p_root; +} + +const char *surf_AS_get_name(AsPtr as) { + return as->p_name; +} + +xbt_dict_t surf_AS_get_routing_sons(AsPtr as) { + return as->p_routingSons; +} + +const char *surf_AS_get_model(AsPtr as) { + return as->p_modelDesc->name; +} + +xbt_dynar_t surf_AS_get_hosts(AsPtr as) { + xbt_dynar_t elms = as->p_indexNetworkElm; + sg_routing_edge_t relm; + xbt_dictelm_t delm; + int index; + int count = xbt_dynar_length(elms); + xbt_dynar_t res = xbt_dynar_new(sizeof(xbt_dictelm_t), NULL); + for (index = 0; index < count; index++) { + relm = xbt_dynar_get_as(elms, index, RoutingEdgePtr); + delm = xbt_lib_get_elm_or_null(host_lib, relm->p_name); + if (delm!=NULL) { + xbt_dynar_push(res, &delm); + } + } + return res; +} + +void surf_AS_get_graph(AS_t as, xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges) { + as->getGraph(graph, nodes, edges); +} + diff --git a/src/surf/surf_routing.hpp b/src/surf/surf_routing.hpp new file mode 100644 index 0000000000..960314f2bc --- /dev/null +++ b/src/surf/surf_routing.hpp @@ -0,0 +1,91 @@ +#include "surf.hpp" + +#ifndef NETWORK_ROUTING_HPP_ +#define NETWORK_ROUTING_HPP_ + +void routing_model_create( void *loopback); + +/*********** + * Classes * + ***********/ +class As; +typedef As *AsPtr; + +class RoutingModelDescription; +typedef RoutingModelDescription *RoutingModelDescriptionPtr; + +class RoutingEdge; +typedef RoutingEdge *RoutingEdgePtr; + +class Onelink; +typedef Onelink *OnelinkPtr; + +class RoutingPlatf; +typedef RoutingPlatf *RoutingPlatfPtr; + + +/*FIXME:class RoutingModelDescription { + const char *p_name; + const char *p_desc; + AsPtr create(); + void end(AsPtr as); +};*/ + +class As { +public: + xbt_dynar_t p_indexNetworkElm; + xbt_dict_t p_bypassRoutes; /* store bypass routes */ + routing_model_description_t p_modelDesc; + e_surf_routing_hierarchy_t p_hierarchy; + char *p_name; + AsPtr p_routingFather; + xbt_dict_t p_routingSons; + RoutingEdgePtr p_netElem; + xbt_dynar_t p_linkUpDownList; + + As(){}; + ~As(){}; + virtual void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency)=0; + virtual xbt_dynar_t getOneLinkRoutes()=0; + virtual void getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges)=0; + virtual sg_platf_route_cbarg_t getBypassRoute(RoutingEdgePtr src, RoutingEdgePtr dst, double *lat)=0; + + /* The parser calls the following functions to inform the routing models + * that a new element is added to the AS currently built. + * + * Of course, only the routing model of this AS is informed, not every ones */ + virtual int parsePU(RoutingEdgePtr elm)=0; /* A host or a router, whatever */ + virtual int parseAS( RoutingEdgePtr elm)=0; + virtual void parseRoute(sg_platf_route_cbarg_t route)=0; + virtual void parseASroute(sg_platf_route_cbarg_t route)=0; + virtual void parseBypassroute(sg_platf_route_cbarg_t e_route)=0; +}; + +class RoutingEdge { +public: + AsPtr p_rcComponent; + e_surf_network_element_type_t p_rcType; + int m_id; + char *p_name; +}; + +/* + * Link of lenght 1, alongside with its source and destination. This is mainly usefull in the bindings to gtnets and ns3 + */ +class Onelink { +public: + RoutingEdgePtr p_src; + RoutingEdgePtr p_dst; + void *p_linkPtr; +}; + +class RoutingPlatf { +public: + AsPtr p_root; + void *p_loopback; + xbt_dynar_t p_lastRoute; + xbt_dynar_t getOneLinkRoutes(void); + void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, xbt_dynar_t * links, double *latency); +}; + +#endif /* NETWORK_ROUTING_HPP_ */ diff --git a/src/surf/surf_routing_cluster.cpp b/src/surf/surf_routing_cluster.cpp new file mode 100644 index 0000000000..9358cd3496 --- /dev/null +++ b/src/surf/surf_routing_cluster.cpp @@ -0,0 +1,10 @@ +#include "surf_routing_private.h" + +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_cluster, surf, "Routing part of surf"); +} + +AS_t model_cluster_create(void) +{ +//FIXME: +} diff --git a/src/surf/surf_routing_dijkstra.cpp b/src/surf/surf_routing_dijkstra.cpp new file mode 100644 index 0000000000..70c084f8c5 --- /dev/null +++ b/src/surf/surf_routing_dijkstra.cpp @@ -0,0 +1,501 @@ +/* Copyright (c) 2009, 2010, 2011. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "surf_routing_dijkstra.hpp" +#include "surf_routing_private.h" +#include "network.hpp" + +/* Global vars */ +extern routing_platf_t routing_platf; + +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_dijkstra, surf, "Routing part of surf -- dijkstra routing logic"); +} + +AS_t model_dijkstra_create(void){ + return new AsDijkstra(0); +} + +AS_t model_dijkstracache_create(void){ + return new AsDijkstra(1); +} + +void model_dijkstra_both_end(AS_t as) +{ + delete as; +} + +/* Free functions */ + +static void route_cache_elem_free(void *e) +{ + route_cache_element_t elm = (route_cache_element_t) e; + if (elm) { + xbt_free(elm->pred_arr); + xbt_free(elm); + } +} + +static void graph_node_map_elem_free(void *e) +{ + graph_node_map_element_t elm = (graph_node_map_element_t) e; + xbt_free(elm); +} + +static void graph_edge_data_free(void *e) // FIXME: useless code duplication +{ + sg_platf_route_cbarg_t e_route = (sg_platf_route_cbarg_t) e; + if (e_route) { + xbt_dynar_free(&(e_route->link_list)); + xbt_free(e_route); + } +} + +/* Utility functions */ + +xbt_node_t AsDijkstra::routeGraphNewNode(int id, int graph_id) +{ + xbt_node_t node = NULL; + graph_node_data_t data = NULL; + graph_node_map_element_t elm = NULL; + + data = xbt_new0(struct graph_node_data, 1); + data->id = id; + data->graph_id = graph_id; + node = xbt_graph_new_node(p_routeGraph, data); + + elm = xbt_new0(struct graph_node_map_element, 1); + elm->node = node; + xbt_dict_set_ext(p_graphNodeMap, (char *) (&id), sizeof(int), + (xbt_set_elm_t) elm, NULL); + + return node; +} + +graph_node_map_element_t AsDijkstra::nodeMapSearch(int id) +{ + graph_node_map_element_t elm = (graph_node_map_element_t) + xbt_dict_get_or_null_ext(p_graphNodeMap, + (char *) (&id), + sizeof(int)); + return elm; +} + +/* Parsing */ + +void AsDijkstra::newRoute(int src_id, int dst_id, sg_platf_route_cbarg_t e_route) +{ + XBT_DEBUG("Load Route from \"%d\" to \"%d\"", src_id, dst_id); + xbt_node_t src = NULL; + xbt_node_t dst = NULL; + + graph_node_map_element_t src_elm = (graph_node_map_element_t) + xbt_dict_get_or_null_ext(p_graphNodeMap, + (char *) (&src_id), + sizeof(int)); + graph_node_map_element_t dst_elm = (graph_node_map_element_t) + xbt_dict_get_or_null_ext(p_graphNodeMap, + (char *) (&dst_id), + sizeof(int)); + + + if (src_elm) + src = src_elm->node; + + if (dst_elm) + dst = dst_elm->node; + + /* add nodes if they don't exist in the graph */ + if (src_id == dst_id && src == NULL && dst == NULL) { + src = this->routeGraphNewNode(src_id, -1); + dst = src; + } else { + if (src == NULL) { + src = this->routeGraphNewNode(src_id, -1); + } + if (dst == NULL) { + dst = this->routeGraphNewNode(dst_id, -1); + } + } + + /* add link as edge to graph */ + xbt_graph_new_edge(p_routeGraph, src, dst, e_route); +} + +void AsDijkstra::addLoopback() { + xbt_dynar_t nodes = xbt_graph_get_nodes(p_routeGraph); + + xbt_node_t node = NULL; + unsigned int cursor2; + xbt_dynar_foreach(nodes, cursor2, node) { + xbt_dynar_t out_edges = xbt_graph_node_get_outedges(node); + xbt_edge_t edge = NULL; + unsigned int cursor; + + int found = 0; + xbt_dynar_foreach(out_edges, cursor, edge) { + xbt_node_t other_node = xbt_graph_edge_get_target(edge); + if (other_node == node) { + found = 1; + break; + } + } + + if (!found) { + sg_platf_route_cbarg_t e_route = xbt_new0(s_sg_platf_route_cbarg_t, 1); + e_route->link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL); + xbt_dynar_push(e_route->link_list, &routing_platf->p_loopback); + xbt_graph_new_edge(p_routeGraph, node, node, e_route); + } + } +} + +xbt_dynar_t AsDijkstra::getOnelinkRoutes() +{ + xbt_dynar_t ret = xbt_dynar_new(sizeof(OnelinkPtr), xbt_free); + sg_platf_route_cbarg_t route = xbt_new0(s_sg_platf_route_cbarg_t,1); + route->link_list = xbt_dynar_new(sizeof(sg_routing_link_t),NULL); + + int src,dst; + RoutingEdgePtr src_elm, dst_elm; + size_t table_size = xbt_dynar_length(p_indexNetworkElm); + for(src=0; src < table_size; src++) { + for(dst=0; dst< table_size; dst++) { + xbt_dynar_reset(route->link_list); + src_elm = xbt_dynar_get_as(p_indexNetworkElm, src, RoutingEdgePtr); + dst_elm = xbt_dynar_get_as(p_indexNetworkElm, dst, RoutingEdgePtr); + this->getRouteAndLatency(src_elm, dst_elm,route, NULL); + + if (xbt_dynar_length(route->link_list) == 1) { + void *link = *(void **) xbt_dynar_get_ptr(route->link_list, 0); + OnelinkPtr onelink = new Onelink(); + onelink->p_linkPtr = link; + if (p_hierarchy == SURF_ROUTING_BASE) { + onelink->p_src = src_elm; + onelink->p_dst = dst_elm; + } else if (p_hierarchy == SURF_ROUTING_RECURSIVE) { + onelink->p_src = route->gw_src; + onelink->p_dst = route->gw_dst; + } + xbt_dynar_push(ret, &onelink); + } + } + } + return ret; +} + +void AsDijkstra::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t route, double *lat) +{ + + /* set utils vars */ + + srcDstCheck(src, dst); + int *src_id = &(src->m_id); + int *dst_id = &(dst->m_id); + + if (!src_id || !dst_id) + THROWF(arg_error,0,"No route from '%s' to '%s'",src->p_name,dst->p_name); + + int *pred_arr = NULL; + int src_node_id = 0; + int dst_node_id = 0; + int *nodeid = NULL; + int v; + sg_platf_route_cbarg_t e_route; + int size = 0; + unsigned int cpt; + NetworkCm02LinkPtr link; + xbt_dynar_t links = NULL; + route_cache_element_t elm = NULL; + xbt_dynar_t nodes = xbt_graph_get_nodes(p_routeGraph); + + /* Use the graph_node id mapping set to quickly find the nodes */ + graph_node_map_element_t src_elm = nodeMapSearch(*src_id); + graph_node_map_element_t dst_elm = nodeMapSearch(*dst_id); + + src_node_id = ((graph_node_data_t) + xbt_graph_node_get_data(src_elm->node))->graph_id; + dst_node_id = ((graph_node_data_t) + xbt_graph_node_get_data(dst_elm->node))->graph_id; + + /* if the src and dst are the same */ + if (src_node_id == dst_node_id) { + + xbt_node_t node_s_v = xbt_dynar_get_as(nodes, src_node_id, xbt_node_t); + xbt_node_t node_e_v = xbt_dynar_get_as(nodes, dst_node_id, xbt_node_t); + xbt_edge_t edge = xbt_graph_get_edge(p_routeGraph, node_s_v, node_e_v); + + if (edge == NULL) + THROWF(arg_error, 0, "No route from '%s' to '%s'", src->p_name, dst->p_name); + + e_route = (sg_platf_route_cbarg_t) xbt_graph_edge_get_data(edge); + + links = e_route->link_list; + xbt_dynar_foreach(links, cpt, link) { + xbt_dynar_unshift(route->link_list, &link); + if (lat) + *lat += link->getLatency(); + } + + } + + if (m_cached) { + /*check if there is a cached predecessor list avail */ + elm = (route_cache_element_t) + xbt_dict_get_or_null_ext(p_routeCache, (char *) (&src_id), + sizeof(int)); + } + + if (elm) { /* cached mode and cache hit */ + pred_arr = elm->pred_arr; + } else { /* not cached mode or cache miss */ + double *cost_arr = NULL; + xbt_heap_t pqueue = NULL; + int i = 0; + + int nr_nodes = xbt_dynar_length(nodes); + cost_arr = xbt_new0(double, nr_nodes); /* link cost from src to other hosts */ + pred_arr = xbt_new0(int, nr_nodes); /* predecessors in path from src */ + pqueue = xbt_heap_new(nr_nodes, xbt_free); + + /* initialize */ + cost_arr[src_node_id] = 0.0; + + for (i = 0; i < nr_nodes; i++) { + if (i != src_node_id) { + cost_arr[i] = DBL_MAX; + } + + pred_arr[i] = 0; + + /* initialize priority queue */ + nodeid = xbt_new0(int, 1); + *nodeid = i; + xbt_heap_push(pqueue, nodeid, cost_arr[i]); + + } + + /* apply dijkstra using the indexes from the graph's node array */ + while (xbt_heap_size(pqueue) > 0) { + int *v_id = (int *) xbt_heap_pop(pqueue); + xbt_node_t v_node = xbt_dynar_get_as(nodes, *v_id, xbt_node_t); + xbt_dynar_t out_edges = xbt_graph_node_get_outedges(v_node); + xbt_edge_t edge = NULL; + unsigned int cursor; + + xbt_dynar_foreach(out_edges, cursor, edge) { + xbt_node_t u_node = xbt_graph_edge_get_target(edge); + graph_node_data_t data = (graph_node_data_t) xbt_graph_node_get_data(u_node); + int u_id = data->graph_id; + sg_platf_route_cbarg_t tmp_e_route = (sg_platf_route_cbarg_t) xbt_graph_edge_get_data(edge); + int cost_v_u = (tmp_e_route->link_list)->used; /* count of links, old model assume 1 */ + + if (cost_v_u + cost_arr[*v_id] < cost_arr[u_id]) { + pred_arr[u_id] = *v_id; + cost_arr[u_id] = cost_v_u + cost_arr[*v_id]; + nodeid = xbt_new0(int, 1); + *nodeid = u_id; + xbt_heap_push(pqueue, nodeid, cost_arr[u_id]); + } + } + + /* free item popped from pqueue */ + xbt_free(v_id); + } + + xbt_free(cost_arr); + xbt_heap_free(pqueue); + } + + /* compose route path with links */ + RoutingEdgePtr gw_src = NULL, gw_dst, prev_gw_src, first_gw = NULL; + RoutingEdgePtr gw_dst_net_elm = NULL, prev_gw_src_net_elm = NULL; + + for (v = dst_node_id; v != src_node_id; v = pred_arr[v]) { + xbt_node_t node_pred_v = + xbt_dynar_get_as(nodes, pred_arr[v], xbt_node_t); + xbt_node_t node_v = xbt_dynar_get_as(nodes, v, xbt_node_t); + xbt_edge_t edge = + xbt_graph_get_edge(p_routeGraph, node_pred_v, node_v); + + if (edge == NULL) + THROWF(arg_error, 0, "No route from '%s' to '%s'", src->p_name, dst->p_name); + + prev_gw_src = gw_src; + + e_route = (sg_platf_route_cbarg_t) xbt_graph_edge_get_data(edge); + gw_src = e_route->gw_src; + gw_dst = e_route->gw_dst; + + if (v == dst_node_id) + first_gw = gw_dst; + + if (p_hierarchy == SURF_ROUTING_RECURSIVE && v != dst_node_id + && strcmp(gw_dst->p_name, prev_gw_src->p_name)) { + xbt_dynar_t e_route_as_to_as=NULL; + + routing_platf->getRouteAndLatency(gw_dst_net_elm, prev_gw_src_net_elm, &e_route_as_to_as, NULL); + if (edge == NULL) + THROWF(arg_error,0,"No route from '%s' to '%s'", src->p_name, dst->p_name); + links = e_route_as_to_as; + int pos = 0; + xbt_dynar_foreach(links, cpt, link) { + xbt_dynar_insert_at(route->link_list, pos, &link); + if (lat) + *lat += link->getLatency(); + pos++; + } + } + + links = e_route->link_list; + xbt_dynar_foreach(links, cpt, link) { + xbt_dynar_unshift(route->link_list, &link); + if (lat) + *lat += link->getLatency(); + } + size++; + } + + if (p_hierarchy == SURF_ROUTING_RECURSIVE) { + route->gw_src = gw_src; + route->gw_dst = first_gw; + } + + if (m_cached && elm == NULL) { + /* add to predecessor list of the current src-host to cache */ + elm = xbt_new0(struct route_cache_element, 1); + elm->pred_arr = pred_arr; + elm->size = size; + xbt_dict_set_ext(p_routeCache, (char *) (&src_id), sizeof(int), + (xbt_set_elm_t) elm, NULL); + } + + if (!m_cached) + xbt_free(pred_arr); +} + +AsDijkstra::~AsDijkstra() +{ + xbt_graph_free_graph(p_routeGraph, &xbt_free, + &graph_edge_data_free, &xbt_free); + xbt_dict_free(&p_graphNodeMap); + if (m_cached) + xbt_dict_free(&p_routeCache); +} + +/* Creation routing model functions */ + +AsDijkstra::AsDijkstra() : AsGeneric(), m_cached(0) {} + +AsDijkstra::AsDijkstra(int cached) : AsGeneric(), m_cached(cached) +{ + /*new_component->generic_routing.parse_route = model_dijkstra_both_parse_route; + new_component->generic_routing.parse_ASroute = model_dijkstra_both_parse_route; + new_component->generic_routing.get_route_and_latency = dijkstra_get_route_and_latency; + new_component->generic_routing.get_onelink_routes = + dijkstra_get_onelink_routes; + new_component->generic_routing.get_graph = generic_get_graph; + new_component->generic_routing.finalize = dijkstra_finalize; + new_component->cached = cached;*/ +} + +void AsDijkstra::end() +{ + xbt_node_t node = NULL; + unsigned int cursor2; + xbt_dynar_t nodes = NULL; + + /* Create the topology graph */ + if(!p_routeGraph) + p_routeGraph = xbt_graph_new_graph(1, NULL); + if(!p_graphNodeMap) + p_graphNodeMap = xbt_dict_new_homogeneous(&graph_node_map_elem_free); + + if (m_cached && p_routeCache) + p_routeCache = xbt_dict_new_homogeneous(&route_cache_elem_free); + + /* Add the loopback if needed */ + if (routing_platf->p_loopback && p_hierarchy == SURF_ROUTING_BASE) + addLoopback(); + + /* initialize graph indexes in nodes after graph has been built */ + nodes = xbt_graph_get_nodes(p_routeGraph); + + xbt_dynar_foreach(nodes, cursor2, node) { + graph_node_data_t data = (graph_node_data_t) xbt_graph_node_get_data(node); + data->graph_id = cursor2; + } + +} +void AsDijkstra::parseRoute(sg_platf_route_cbarg_t route) +{ + char *src = (char*)(route->src); + char *dst = (char*)(route->dst); + + int as_route = 0; + if(!route->gw_dst && !route->gw_src) + XBT_DEBUG("Load Route from \"%s\" to \"%s\"", src, dst); + else{ + XBT_DEBUG("Load ASroute from \"%s(%s)\" to \"%s(%s)\"", src, + route->gw_src->p_name, dst, route->gw_dst->p_name); + as_route = 1; + if(route->gw_dst->p_rcType == SURF_NETWORK_ELEMENT_NULL) + xbt_die("The gw_dst '%s' does not exist!",route->gw_dst->p_name); + if(route->gw_src->p_rcType == SURF_NETWORK_ELEMENT_NULL) + xbt_die("The gw_src '%s' does not exist!",route->gw_src->p_name); + } + + RoutingEdgePtr src_net_elm, dst_net_elm; + + src_net_elm = sg_routing_edge_by_name_or_null(src); + dst_net_elm = sg_routing_edge_by_name_or_null(dst); + + xbt_assert(src_net_elm, "Network elements %s not found", src); + xbt_assert(dst_net_elm, "Network elements %s not found", dst); + + /* Create the topology graph */ + if(!p_routeGraph) + p_routeGraph = xbt_graph_new_graph(1, NULL); + if(!p_graphNodeMap) + p_graphNodeMap = xbt_dict_new_homogeneous(&graph_node_map_elem_free); + + if (m_cached && !p_routeCache) + p_routeCache = xbt_dict_new_homogeneous(&route_cache_elem_free); + + sg_platf_route_cbarg_t e_route = newExtendedRoute(p_hierarchy, route, 1); + newRoute(src_net_elm->m_id, dst_net_elm->m_id, e_route); + + // Symmetrical YES + if ( (route->symmetrical == TRUE && as_route == 0) + || (route->symmetrical == TRUE && as_route == 1) + ) + { + if(!route->gw_dst && !route->gw_src) + XBT_DEBUG("Load Route from \"%s\" to \"%s\"", dst, src); + else + XBT_DEBUG("Load ASroute from \"%s(%s)\" to \"%s(%s)\"", dst, + route->gw_dst->p_name, src, route->gw_src->p_name); + + xbt_dynar_t nodes = xbt_graph_get_nodes(p_routeGraph); + xbt_node_t node_s_v = xbt_dynar_get_as(nodes, src_net_elm->m_id, xbt_node_t); + xbt_node_t node_e_v = xbt_dynar_get_as(nodes, dst_net_elm->m_id, xbt_node_t); + xbt_edge_t edge = + xbt_graph_get_edge(p_routeGraph, node_e_v, node_s_v); + + if (edge) + THROWF(arg_error,0,"(AS)Route from '%s' to '%s' already exists",src,dst); + + if (route->gw_dst && route->gw_src) { + RoutingEdgePtr gw_tmp; + gw_tmp = route->gw_src; + route->gw_src = route->gw_dst; + route->gw_dst = gw_tmp; + } + sg_platf_route_cbarg_t link_route_back = newExtendedRoute(p_hierarchy, route, 0); + newRoute(dst_net_elm->m_id, src_net_elm->m_id, link_route_back); + } + xbt_dynar_free(&route->link_list); +} diff --git a/src/surf/surf_routing_dijkstra.hpp b/src/surf/surf_routing_dijkstra.hpp new file mode 100644 index 0000000000..621d248cef --- /dev/null +++ b/src/surf/surf_routing_dijkstra.hpp @@ -0,0 +1,41 @@ +#include "surf_routing_generic.hpp" + +#ifndef SURF_ROUTING_DIJKSTRA_HPP_ +#define SURF_ROUTING_DIJKSTRA_HPP_ + +typedef struct graph_node_data { + int id; + int graph_id; /* used for caching internal graph id's */ +} s_graph_node_data_t, *graph_node_data_t; + +typedef struct graph_node_map_element { + xbt_node_t node; +} s_graph_node_map_element_t, *graph_node_map_element_t; + +typedef struct route_cache_element { + int *pred_arr; + int size; +} s_route_cache_element_t, *route_cache_element_t; + +class AsDijkstra : public AsGeneric { +public: + AsDijkstra(); + AsDijkstra(int cached); + ~AsDijkstra(); + xbt_node_t routeGraphNewNode(int id, int graph_id); + graph_node_map_element_t nodeMapSearch(int id); + void newRoute(int src_id, int dst_id, sg_platf_route_cbarg_t e_route); + void addLoopback(); + void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t route, double *lat); + xbt_dynar_t getOnelinkRoutes(); + void getRouteAndLatency(sg_platf_route_cbarg_t route, double *lat); + void parseRoute(sg_platf_route_cbarg_t route); + void end(); + + xbt_graph_t p_routeGraph; /* xbt_graph */ + xbt_dict_t p_graphNodeMap; /* map */ + xbt_dict_t p_routeCache; /* use in cache mode */ + int m_cached; +}; + +#endif /* SURF_ROUTING_DIJKSTRA_HPP_ */ diff --git a/src/surf/surf_routing_floyd.cpp b/src/surf/surf_routing_floyd.cpp new file mode 100644 index 0000000000..28d759635c --- /dev/null +++ b/src/surf/surf_routing_floyd.cpp @@ -0,0 +1,14 @@ +#include "surf_routing_private.h" + +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_floyd, surf, "Routing part of surf"); +} + +AS_t model_floyd_create(void) +{//FIXME: +} + +void model_floyd_end(AS_t current_routing) +{ +//FIXME: +} diff --git a/src/surf/surf_routing_full.cpp b/src/surf/surf_routing_full.cpp new file mode 100644 index 0000000000..0058aeb84b --- /dev/null +++ b/src/surf/surf_routing_full.cpp @@ -0,0 +1,12 @@ +#include "surf_routing_private.h" + +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_full, surf, "Routing part of surf"); +} + +AS_t model_full_create(void) +{//FIXME: +} + +void model_full_end(AS_t current_routing) +{} diff --git a/src/surf/surf_routing_generic.cpp b/src/surf/surf_routing_generic.cpp new file mode 100644 index 0000000000..fd8e37b243 --- /dev/null +++ b/src/surf/surf_routing_generic.cpp @@ -0,0 +1,476 @@ +/* Copyright (c) 2009, 2010, 2011. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "simgrid/platf_interface.h" // platform creation API internal interface + +#include "surf_routing_generic.hpp" +#include "network.hpp" +#include "xbt/graph.h" + +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_routing_generic, surf_route, "Generic implementation of the surf routing"); +} + +static int no_bypassroute_declared = 1; + +void generic_free_route(sg_platf_route_cbarg_t route) +{ + if (route) { + xbt_dynar_free(&route->link_list); + xbt_free(route); + } +} + +void AsGeneric::parseRoute(sg_platf_route_cbarg_t route){ + THROW_IMPOSSIBLE; +} + +void AsGeneric::parseASroute(sg_platf_route_cbarg_t route){ + THROW_IMPOSSIBLE; +} + +void AsGeneric::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency){ + THROW_IMPOSSIBLE; +} + +xbt_dynar_t AsGeneric::getOneLinkRoutes(){ + THROW_IMPOSSIBLE; +} + +AsGeneric::AsGeneric() { + p_bypassRoutes = xbt_dict_new_homogeneous((void (*)(void *)) generic_free_route); +} + +AsGeneric::~AsGeneric() { + xbt_dict_free(&p_bypassRoutes); +} + +int AsGeneric::parsePU(RoutingEdgePtr elm) +{ + XBT_DEBUG("Load process unit \"%s\"", elm->p_name); + xbt_dynar_push_as(p_indexNetworkElm, RoutingEdgePtr, elm); + return xbt_dynar_length(p_indexNetworkElm)-1; +} + +int AsGeneric::parseAS(RoutingEdgePtr elm) +{ + XBT_DEBUG("Load Autonomous system \"%s\"", elm->p_name); + xbt_dynar_push_as(p_indexNetworkElm, RoutingEdgePtr, elm); + return xbt_dynar_length(p_indexNetworkElm)-1; +} + +void AsGeneric::parseBypassroute(sg_platf_route_cbarg_t e_route) +{ + char *src = (char*)(e_route->src); + char *dst = (char*)(e_route->dst); + + if(e_route->gw_dst) + XBT_DEBUG("Load bypassASroute from \"%s\" to \"%s\"", src, dst); + else + XBT_DEBUG("Load bypassRoute from \"%s\" to \"%s\"", src, dst); + xbt_dict_t dict_bypassRoutes = p_bypassRoutes; + char *route_name; + + route_name = bprintf("%s#%s", src, dst); + xbt_assert(!xbt_dynar_is_empty(e_route->link_list), + "Invalid count of links, must be greater than zero (%s,%s)", + src, dst); + xbt_assert(!xbt_dict_get_or_null(dict_bypassRoutes, route_name), + "The bypass route between \"%s\"(\"%s\") and \"%s\"(\"%s\") already exists", + src, e_route->gw_src->p_name, dst, e_route->gw_dst->p_name); + + sg_platf_route_cbarg_t new_e_route = NULL; + if(e_route->gw_dst) + new_e_route = newExtendedRoute(SURF_ROUTING_RECURSIVE, e_route, 1); + else + new_e_route = newExtendedRoute(SURF_ROUTING_BASE, e_route, 1); + + xbt_dynar_free(&(e_route->link_list)); + + xbt_dict_set(dict_bypassRoutes, route_name, new_e_route, NULL); + no_bypassroute_declared = 0; + xbt_free(route_name); +} + +/* ************************************************************************** */ +/* *********************** GENERIC BUSINESS METHODS ************************* */ + +xbt_dynar_t AsGeneric::getOnelinkRoutes() { // FIXME: kill that stub + xbt_die("\"generic_get_onelink_routes\" not implemented yet"); + return NULL; +} + +static const char *instr_node_name(xbt_node_t node) +{ + void *data = xbt_graph_node_get_data(node); + char *str = (char *) data; + return str; +} + +xbt_node_t new_xbt_graph_node(xbt_graph_t graph, const char *name, + xbt_dict_t nodes) +{ + xbt_node_t ret = (xbt_node_t) xbt_dict_get_or_null(nodes, name); + if (ret) + return ret; + + ret = xbt_graph_new_node(graph, xbt_strdup(name)); + xbt_dict_set(nodes, name, ret, NULL); + return ret; +} + +xbt_edge_t new_xbt_graph_edge(xbt_graph_t graph, xbt_node_t s, xbt_node_t d, + xbt_dict_t edges) +{ + xbt_edge_t ret; + + const char *sn = instr_node_name(s); + const char *dn = instr_node_name(d); + int len = strlen(sn) + strlen(dn) + 1; + char *name = (char *) xbt_malloc(len * sizeof(char)); + + + snprintf(name, len, "%s%s", sn, dn); + ret = (xbt_edge_t) xbt_dict_get_or_null(edges, name); + if (ret == NULL) { + snprintf(name, len, "%s%s", dn, sn); + ret = (xbt_edge_t) xbt_dict_get_or_null(edges, name); + } + + if (ret == NULL) { + ret = xbt_graph_new_edge(graph, s, d, NULL); + xbt_dict_set(edges, name, ret, NULL); + } + free(name); + return ret; +} + +void AsGeneric::getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges) +{ + int src, dst; + int table_size = xbt_dynar_length(p_indexNetworkElm); + + + for (src = 0; src < table_size; src++) { + RoutingEdgePtr my_src = + xbt_dynar_get_as(p_indexNetworkElm, src, RoutingEdgePtr); + for (dst = 0; dst < table_size; dst++) { + if (src == dst) + continue; + RoutingEdgePtr my_dst = + xbt_dynar_get_as(p_indexNetworkElm, dst, RoutingEdgePtr); + + sg_platf_route_cbarg_t route = xbt_new0(s_sg_platf_route_cbarg_t, 1); + route->link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL); + + getRouteAndLatency(my_src, my_dst, route, NULL); + + XBT_DEBUG ("get_route_and_latency %s -> %s", my_src->p_name, my_dst->p_name); + + unsigned int cpt; + void *link; + + xbt_node_t current, previous; + const char *previous_name, *current_name; + + if (route->gw_src) { + previous = new_xbt_graph_node(graph, route->gw_src->p_name, nodes); + previous_name = route->gw_src->p_name; + } else { + previous = new_xbt_graph_node(graph, my_src->p_name, nodes); + previous_name = my_src->p_name; + } + + xbt_dynar_foreach(route->link_list, cpt, link) { + const char *link_name = ((ResourcePtr) link)->m_name; + current = new_xbt_graph_node(graph, link_name, nodes); + current_name = link_name; + new_xbt_graph_edge(graph, previous, current, edges); + XBT_DEBUG (" %s -> %s", previous_name, current_name); + previous = current; + previous_name = current_name; + } + + if (route->gw_dst) { + current = new_xbt_graph_node(graph, route->gw_dst->p_name, nodes); + current_name = route->gw_dst->p_name; + } else { + current = new_xbt_graph_node(graph, my_dst->p_name, nodes); + current_name = my_dst->p_name; + } + new_xbt_graph_edge(graph, previous, current, edges); + XBT_DEBUG (" %s -> %s", previous_name, current_name); + + xbt_dynar_free (&(route->link_list)); + xbt_free (route); + } + } +} + +sg_platf_route_cbarg_t AsGeneric::getBypassRoute(RoutingEdgePtr src, + RoutingEdgePtr dst, + double *lat) +{ + // If never set a bypass route return NULL without any further computations + XBT_DEBUG("generic_get_bypassroute from %s to %s", src->p_name, dst->p_name); + if (no_bypassroute_declared) + return NULL; + + sg_platf_route_cbarg_t e_route_bypass = NULL; + xbt_dict_t dict_bypassRoutes = p_bypassRoutes; + + if(dst->p_rcComponent == this && src->p_rcComponent == this ){ + char *route_name = bprintf("%s#%s", src->p_name, dst->p_name); + e_route_bypass = (sg_platf_route_cbarg_t) xbt_dict_get_or_null(dict_bypassRoutes, route_name); + if(e_route_bypass) + XBT_DEBUG("Find bypass route with %ld links",xbt_dynar_length(e_route_bypass->link_list)); + free(route_name); + } + else{ + AsPtr src_as, dst_as; + int index_src, index_dst; + xbt_dynar_t path_src = NULL; + xbt_dynar_t path_dst = NULL; + AsPtr current = NULL; + AsPtr *current_src = NULL; + AsPtr *current_dst = NULL; + + if (src == NULL || dst == NULL) + xbt_die("Ask for route \"from\"(%s) or \"to\"(%s) no found at AS \"%s\"", + src->p_name, dst->p_name, p_name); + + src_as = src->p_rcComponent; + dst_as = dst->p_rcComponent; + + /* (2) find the path to the root routing component */ + path_src = xbt_dynar_new(sizeof(AsPtr), NULL); + current = src_as; + while (current != NULL) { + xbt_dynar_push(path_src, ¤t); + current = current->p_routingFather; + } + path_dst = xbt_dynar_new(sizeof(AsPtr), NULL); + current = dst_as; + while (current != NULL) { + xbt_dynar_push(path_dst, ¤t); + current = current->p_routingFather; + } + + /* (3) find the common father */ + index_src = path_src->used - 1; + index_dst = path_dst->used - 1; + current_src = (AsPtr *) xbt_dynar_get_ptr(path_src, index_src); + current_dst = (AsPtr *) xbt_dynar_get_ptr(path_dst, index_dst); + while (index_src >= 0 && index_dst >= 0 && *current_src == *current_dst) { + xbt_dynar_pop_ptr(path_src); + xbt_dynar_pop_ptr(path_dst); + index_src--; + index_dst--; + current_src = (AsPtr *) xbt_dynar_get_ptr(path_src, index_src); + current_dst = (AsPtr *) xbt_dynar_get_ptr(path_dst, index_dst); + } + + int max_index_src = path_src->used - 1; + int max_index_dst = path_dst->used - 1; + + int max_index = max(max_index_src, max_index_dst); + int i, max; + + for (max = 0; max <= max_index; max++) { + for (i = 0; i < max; i++) { + if (i <= max_index_src && max <= max_index_dst) { + char *route_name = bprintf("%s#%s", + (*(AsPtr *) + (xbt_dynar_get_ptr(path_src, i)))->p_name, + (*(AsPtr *) + (xbt_dynar_get_ptr(path_dst, max)))->p_name); + e_route_bypass = (sg_platf_route_cbarg_t) xbt_dict_get_or_null(dict_bypassRoutes, route_name); + xbt_free(route_name); + } + if (e_route_bypass) + break; + if (max <= max_index_src && i <= max_index_dst) { + char *route_name = bprintf("%s#%s", + (*(AsPtr *) + (xbt_dynar_get_ptr(path_src, max)))->p_name, + (*(AsPtr *) + (xbt_dynar_get_ptr(path_dst, i)))->p_name); + e_route_bypass = (sg_platf_route_cbarg_t) xbt_dict_get_or_null(dict_bypassRoutes, route_name); + xbt_free(route_name); + } + if (e_route_bypass) + break; + } + + if (e_route_bypass) + break; + + if (max <= max_index_src && max <= max_index_dst) { + char *route_name = bprintf("%s#%s", + (*(AsPtr *) + (xbt_dynar_get_ptr(path_src, max)))->p_name, + (*(AsPtr *) + (xbt_dynar_get_ptr(path_dst, max)))->p_name); + e_route_bypass = (sg_platf_route_cbarg_t) xbt_dict_get_or_null(dict_bypassRoutes, route_name); + xbt_free(route_name); + } + if (e_route_bypass) + break; + } + + xbt_dynar_free(&path_src); + xbt_dynar_free(&path_dst); + } + + sg_platf_route_cbarg_t new_e_route = NULL; + if (e_route_bypass) { + NetworkCm02LinkPtr link; + unsigned int cpt = 0; + new_e_route = xbt_new0(s_sg_platf_route_cbarg_t, 1); + new_e_route->gw_src = e_route_bypass->gw_src; + new_e_route->gw_dst = e_route_bypass->gw_dst; + new_e_route->link_list = + xbt_dynar_new(sizeof(sg_routing_link_t), NULL); + xbt_dynar_foreach(e_route_bypass->link_list, cpt, link) { + xbt_dynar_push(new_e_route->link_list, &link); + if (lat) + *lat += link->getLatency(); + } + } + + return new_e_route; +} + +/* ************************************************************************** */ +/* ************************* GENERIC AUX FUNCTIONS ************************** */ +/* change a route containing link names into a route containing link entities */ +sg_platf_route_cbarg_t AsGeneric::newExtendedRoute(e_surf_routing_hierarchy_t hierarchy, + sg_platf_route_cbarg_t routearg, int change_order) { + + sg_platf_route_cbarg_t result; + char *link_name; + unsigned int cpt; + + result = xbt_new0(s_sg_platf_route_cbarg_t, 1); + result->link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL); + + xbt_assert(hierarchy == SURF_ROUTING_BASE + || hierarchy == SURF_ROUTING_RECURSIVE, + "The hierarchy of this AS is neither BASIC nor RECURSIVE, I'm lost here."); + + if (hierarchy == SURF_ROUTING_RECURSIVE) { + + xbt_assert(routearg->gw_src && routearg->gw_dst, + "NULL is obviously a bad gateway"); + + /* remeber not erase the gateway names */ + result->gw_src = routearg->gw_src; + result->gw_dst = routearg->gw_dst; + } + + xbt_dynar_foreach(routearg->link_list, cpt, link_name) { + + void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL); + if (link) { + if (change_order) + xbt_dynar_push(result->link_list, &link); + else + xbt_dynar_unshift(result->link_list, &link); + } else + THROWF(mismatch_error, 0, "Link %s not found", link_name); + } + + return result; +} + + + +AsPtr AsGeneric::asExist(AsPtr to_find) +{ + //return to_find; // FIXME: BYPASSERROR OF FOREACH WITH BREAK + xbt_dict_cursor_t cursor = NULL; + char *key; + int found = 0; + AsGenericPtr elem; + xbt_dict_foreach(p_routingSons, cursor, key, elem) { + if (to_find == elem || elem->asExist(to_find)) { + found = 1; + break; + } + } + if (found) + return to_find; + return NULL; +} + +AsPtr AsGeneric::autonomousSystemExist(char *element) +{ + //return rc; // FIXME: BYPASSERROR OF FOREACH WITH BREAK + AsPtr element_as, result, elem; + xbt_dict_cursor_t cursor = NULL; + char *key; + element_as = ((RoutingEdgePtr) + xbt_lib_get_or_null(as_router_lib, element, + ROUTING_ASR_LEVEL))->p_rcComponent; + result = ((AsPtr) - 1); + if (element_as != this) + result = asExist(element_as); + + int found = 0; + if (result) { + xbt_dict_foreach(element_as->p_routingSons, cursor, key, elem) { + found = !strcmp(elem->p_name, element); + if (found) + break; + } + if (found) + return element_as; + } + return NULL; +} + +AsPtr AsGeneric::processingUnitsExist(char *element) +{ + AsPtr element_as; + element_as = ((RoutingEdgePtr) + xbt_lib_get_or_null(host_lib, + element, ROUTING_HOST_LEVEL))->p_rcComponent; + if (element_as == this) + return element_as; + return asExist(element_as); +} + +void AsGeneric::srcDstCheck(RoutingEdgePtr src, RoutingEdgePtr dst) +{ + + RoutingEdgePtr src_data = src; + RoutingEdgePtr dst_data = dst; + + if (src_data == NULL || dst_data == NULL) + xbt_die("Ask for route \"from\"(%s) or \"to\"(%s) no found at AS \"%s\"", + src->p_name, + dst->p_name, + p_name); + + AsPtr src_as = + (src_data)->p_rcComponent; + AsPtr dst_as = + (dst_data)->p_rcComponent; + + if (src_as != dst_as) + xbt_die("The src(%s in %s) and dst(%s in %s) are in differents AS", + src->p_name, src_as->p_name, + dst->p_name, dst_as->p_name); + + if (this != dst_as) + xbt_die + ("The routing component of src'%s' and dst'%s' is not the same as the network elements belong (%s?=%s?=%s)", + src->p_name, + dst->p_name, + src_as->p_name, + dst_as->p_name, + p_name); +} diff --git a/src/surf/surf_routing_generic.hpp b/src/surf/surf_routing_generic.hpp new file mode 100644 index 0000000000..ecf6975e06 --- /dev/null +++ b/src/surf/surf_routing_generic.hpp @@ -0,0 +1,38 @@ +#include "surf_routing_none.hpp" + +#ifndef SURF_ROUTING_GENERIC_HPP_ +#define SURF_ROUTING_GENERIC_HPP_ + +class AsGeneric; +typedef AsGeneric *AsGenericPtr; + +class AsGeneric : public AsNone { +public: + AsGeneric(); + ~AsGeneric(); + void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency); + xbt_dynar_t getOneLinkRoutes(); + void getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges); + sg_platf_route_cbarg_t getBypassRoute(RoutingEdgePtr src, RoutingEdgePtr dst, double *lat); + void finalize(); + + /* The parser calls the following functions to inform the routing models + * that a new element is added to the AS currently built. + * + * Of course, only the routing model of this AS is informed, not every ones */ + int parsePU(RoutingEdgePtr elm); /* A host or a router, whatever */ + int parseAS( RoutingEdgePtr elm); + void parseRoute(sg_platf_route_cbarg_t route); + void parseASroute(sg_platf_route_cbarg_t route); + void parseBypassroute(sg_platf_route_cbarg_t e_route); + + xbt_dynar_t getOnelinkRoutes(); + sg_platf_route_cbarg_t getBypassroute(RoutingEdgePtr src, RoutingEdgePtr dst, double *lat); + sg_platf_route_cbarg_t newExtendedRoute(e_surf_routing_hierarchy_t hierarchy, sg_platf_route_cbarg_t routearg, int change_order); + AsPtr asExist(AsPtr to_find); + AsPtr autonomousSystemExist(char *element); + AsPtr processingUnitsExist(char *element); + void srcDstCheck(RoutingEdgePtr src, RoutingEdgePtr dst); +}; + +#endif /* SURF_ROUTING_GENERIC_HPP_ */ diff --git a/src/surf/surf_routing_none.c b/src/surf/surf_routing_none.c index d312a29797..1379bb7733 100644 --- a/src/surf/surf_routing_none.c +++ b/src/surf/surf_routing_none.c @@ -6,7 +6,9 @@ #include "surf_routing_private.h" +extern "C" { XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_none, surf, "Routing part of surf"); +} static xbt_dynar_t none_get_onelink_routes(AS_t rc) { return NULL; diff --git a/src/surf/surf_routing_none.cpp b/src/surf/surf_routing_none.cpp new file mode 100644 index 0000000000..07c059aa9a --- /dev/null +++ b/src/surf/surf_routing_none.cpp @@ -0,0 +1,73 @@ +/* Copyright (c) 2009, 2010, 2011. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "surf_routing_none.hpp" +#include "surf_routing_private.h" + +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_none, surf, "Routing part of surf"); +} + +AS_t model_none_create(void) +{//FIXME: +} + +xbt_dynar_t AsNone::getOneLinkRoutes() { + return NULL; +} + +void AsNone::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, + sg_platf_route_cbarg_t res, double *lat) +{ + *lat = 0.0; +} + +void AsNone::getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges) +{ + XBT_INFO("No routing no graph"); +} + +sg_platf_route_cbarg_t AsNone::getBypassRoute(RoutingEdgePtr src, RoutingEdgePtr dst, double *lat) { + return NULL; +} + +int AsNone::parsePU(RoutingEdgePtr elm) { + XBT_DEBUG("Load process unit \"%s\"", elm->p_name); + xbt_dynar_push_as(p_indexNetworkElm, RoutingEdgePtr, elm); + /* don't care about PUs */ + return -1; +} + +int AsNone::parseAS(RoutingEdgePtr elm) { + XBT_DEBUG("Load Autonomous system \"%s\"", elm->p_name); + xbt_dynar_push_as(p_indexNetworkElm, RoutingEdgePtr, elm); + /* even don't care about sub-ASes -- I'm as nihilist as an old punk*/ + return -1; +} + +void AsNone::parseRoute(sg_platf_route_cbarg_t route){ + THROW_IMPOSSIBLE; +} + +void AsNone::parseASroute(sg_platf_route_cbarg_t route){ + THROW_IMPOSSIBLE; +} +void AsNone::parseBypassroute(sg_platf_route_cbarg_t e_route){ + THROW_IMPOSSIBLE; +} + +/* Creation routing model functions */ +AsNone::AsNone() { + p_routingSons = xbt_dict_new_homogeneous(NULL); + p_indexNetworkElm = xbt_dynar_new(sizeof(char*),NULL); +} + +AsNone::~AsNone() { + xbt_dict_free(&p_routingSons); + xbt_dynar_free(&p_indexNetworkElm); + xbt_dynar_free(&p_linkUpDownList); +} + diff --git a/src/surf/surf_routing_none.hpp b/src/surf/surf_routing_none.hpp new file mode 100644 index 0000000000..7a56e25b83 --- /dev/null +++ b/src/surf/surf_routing_none.hpp @@ -0,0 +1,28 @@ +#include "surf_routing.hpp" + +#ifndef SURF_ROUTING_NONE_HPP_ +#define SURF_ROUTING_NONE_HPP_ + +class AsNone : public As { +public: + AsNone(); + ~AsNone(); + void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency); + xbt_dynar_t getOneLinkRoutes(); + void getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges); + sg_platf_route_cbarg_t getBypassRoute(RoutingEdgePtr src, RoutingEdgePtr dst, double *lat); + void finalize(); + + /* The parser calls the following functions to inform the routing models + * that a new element is added to the AS currently built. + * + * Of course, only the routing model of this AS is informed, not every ones */ + int parsePU(RoutingEdgePtr elm); /* A host or a router, whatever */ + int parseAS( RoutingEdgePtr elm); + void parseRoute(sg_platf_route_cbarg_t route); + void parseASroute(sg_platf_route_cbarg_t route); + void parseBypassroute(sg_platf_route_cbarg_t e_route); +}; + + +#endif /* SURF_ROUTING_NONE_HPP_ */ diff --git a/src/surf/surf_routing_private.h b/src/surf/surf_routing_private.h index 99f54ddfc8..59ae1e623d 100644 --- a/src/surf/surf_routing_private.h +++ b/src/surf/surf_routing_private.h @@ -10,36 +10,37 @@ #include #include "internal_config.h" -#include "surf_private.h" +//#include "surf_private.h" #include "xbt/dynar.h" #include "xbt/str.h" #include "xbt/config.h" #include "xbt/graph.h" #include "xbt/set.h" #include "surf/surfxml_parse.h" +#include "surf_routing.hpp" /* ************************************************************************** */ /* ******************************* NO ROUTING ******************************* */ /* Only save the AS tree, and forward calls to child ASes */ -AS_t model_none_create(void); -AS_t model_none_create_sized(size_t childsize); -void model_none_finalize(AS_t as); +AsPtr model_none_create(void); +AsPtr model_none_create_sized(size_t childsize); +void model_none_finalize(AsPtr as); /* ************************************************************************** */ /* ***************** GENERIC PARSE FUNCTIONS (declarations) ***************** */ -AS_t model_generic_create_sized(size_t childsize); -void model_generic_finalize(AS_t as); +AsPtr model_generic_create_sized(size_t childsize); +void model_generic_finalize(AsPtr as); -int generic_parse_PU(AS_t rc, sg_routing_edge_t elm); -int generic_parse_AS(AS_t rc, sg_routing_edge_t elm); -void generic_parse_bypassroute(AS_t rc, sg_platf_route_cbarg_t e_route); +int generic_parse_PU(AsPtr rc, RoutingEdgePtr elm); +int generic_parse_AS(AsPtr rc, RoutingEdgePtr elm); +void generic_parse_bypassroute(AsPtr rc, sg_platf_route_cbarg_t e_route); /* ************************************************************************** */ /* *************** GENERIC BUSINESS METHODS (declarations) ****************** */ -xbt_dynar_t generic_get_onelink_routes(AS_t rc); -sg_platf_route_cbarg_t generic_get_bypassroute(AS_t rc, - sg_routing_edge_t src, - sg_routing_edge_t dst, +xbt_dynar_t generic_get_onelink_routes(AsPtr rc); +sg_platf_route_cbarg_t generic_get_bypassroute(AsPtr rc, + RoutingEdgePtr src, + RoutingEdgePtr dst, double *lat); /* ************************************************************************** */ @@ -50,51 +51,50 @@ sg_platf_route_cbarg_t generic_get_bypassroute(AS_t rc, * produced route */ sg_platf_route_cbarg_t generic_new_extended_route(e_surf_routing_hierarchy_t hierarchy, sg_platf_route_cbarg_t data, int preserve_order); -AS_t -generic_autonomous_system_exist(AS_t rc, char *element); -AS_t -generic_processing_units_exist(AS_t rc, char *element); -void generic_src_dst_check(AS_t rc, sg_routing_edge_t src, - sg_routing_edge_t dst); +AsPtr +generic_autonomous_system_exist(AsPtr rc, char *element); +AsPtr +generic_processing_units_exist(AsPtr rc, char *element); +void generic_src_dst_check(AsPtr rc, RoutingEdgePtr src, + RoutingEdgePtr dst); /* ************************************************************************** */ /* *************************** FLOYD ROUTING ******************************** */ -AS_t model_floyd_create(void); /* create structures for floyd routing model */ -void model_floyd_end(AS_t as); /* finalize the creation of floyd routing model */ -void model_floyd_parse_route(AS_t rc, sg_platf_route_cbarg_t route); +AsPtr model_floyd_create(void); /* create structures for floyd routing model */ +void model_floyd_end(AsPtr as); /* finalize the creation of floyd routing model */ +void model_floyd_parse_route(AsPtr rc, sg_platf_route_cbarg_t route); /* ************************************************** */ /* ************** Cluster ROUTING **************** */ -typedef struct { - s_as_t generic_routing; - void *backbone; - void *loopback; - sg_routing_edge_t router; -} s_as_cluster_t, *as_cluster_t; +class AsCluster : public As { + void *p_backbone; + void *p_loopback; + RoutingEdgePtr router; +}; -AS_t model_cluster_create(void); /* create structures for cluster routing model */ +AsPtr model_cluster_create(void); /* create structures for cluster routing model */ /* ************************************************** */ /* ************** Vivaldi ROUTING **************** */ -AS_t model_vivaldi_create(void); /* create structures for vivaldi routing model */ +AsPtr model_vivaldi_create(void); /* create structures for vivaldi routing model */ #define HOST_PEER(peername) bprintf("peer_%s", peername) #define ROUTER_PEER(peername) bprintf("router_%s", peername) #define LINK_PEER(peername) bprintf("link_%s", peername) /* ************************************************************************** */ /* ********** Dijkstra & Dijkstra Cached ROUTING **************************** */ -AS_t model_dijkstra_both_create(int cached); /* create by calling dijkstra or dijkstracache */ -AS_t model_dijkstra_create(void); /* create structures for dijkstra routing model */ -AS_t model_dijkstracache_create(void); /* create structures for dijkstracache routing model */ -void model_dijkstra_both_end(AS_t as); /* finalize the creation of dijkstra routing model */ -void model_dijkstra_both_parse_route (AS_t rc, sg_platf_route_cbarg_t route); +AsPtr model_dijkstra_both_create(int cached); /* create by calling dijkstra or dijkstracache */ +AsPtr model_dijkstra_create(void); /* create structures for dijkstra routing model */ +AsPtr model_dijkstracache_create(void); /* create structures for dijkstracache routing model */ +void model_dijkstra_both_end(AsPtr as); /* finalize the creation of dijkstra routing model */ +void model_dijkstra_both_parse_route (AsPtr rc, sg_platf_route_cbarg_t route); /* ************************************************************************** */ /* *************************** FULL ROUTING ********************************* */ -AS_t model_full_create(void); /* create structures for full routing model */ -void model_full_end(AS_t as); /* finalize the creation of full routing model */ +AsPtr model_full_create(void); /* create structures for full routing model */ +void model_full_end(AsPtr as); /* finalize the creation of full routing model */ void model_full_set_route( /* Set the route and ASroute between src and dst */ - AS_t rc, sg_platf_route_cbarg_t route); + AsPtr rc, sg_platf_route_cbarg_t route); /* ************************************************************************** */ /* ************************* GRAPH EXPORTING FUNCTIONS ********************** */ xbt_node_t new_xbt_graph_node (xbt_graph_t graph, const char *name, xbt_dict_t nodes); diff --git a/src/surf/surf_routing_private.hpp b/src/surf/surf_routing_private.hpp new file mode 100644 index 0000000000..e3d718b1a8 --- /dev/null +++ b/src/surf/surf_routing_private.hpp @@ -0,0 +1,106 @@ +/* Copyright (c) 2009, 2010, 2011. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#ifndef _SURF_SURF_ROUTING_PRIVATE_H +#define _SURF_SURF_ROUTING_PRIVATE_H + +#include +#include "internal_config.h" + +#include "surf.hpp" +#include "xbt/dynar.h" +#include "xbt/str.h" +#include "xbt/config.h" +#include "xbt/graph.h" +#include "xbt/set.h" +#include "surf/surfxml_parse.h" + +/* ************************************************************************** */ +/* ******************************* NO ROUTING ******************************* */ +/* Only save the AS tree, and forward calls to child ASes */ +AS_t model_none_create(void); +AS_t model_none_create_sized(size_t childsize); +void model_none_finalize(AS_t as); +/* ************************************************************************** */ +/* ***************** GENERIC PARSE FUNCTIONS (declarations) ***************** */ +AS_t model_generic_create_sized(size_t childsize); +void model_generic_finalize(AS_t as); + +int generic_parse_PU(AS_t rc, sg_routing_edge_t elm); +int generic_parse_AS(AS_t rc, sg_routing_edge_t elm); +void generic_parse_bypassroute(AS_t rc, sg_platf_route_cbarg_t e_route); + +/* ************************************************************************** */ +/* *************** GENERIC BUSINESS METHODS (declarations) ****************** */ + +xbt_dynar_t generic_get_onelink_routes(AS_t rc); +sg_platf_route_cbarg_t generic_get_bypassroute(AS_t rc, + sg_routing_edge_t src, + sg_routing_edge_t dst, + double *lat); + +/* ************************************************************************** */ +/* ****************** GENERIC AUX FUNCTIONS (declarations) ****************** */ + +/* change a route containing link names into a route containing link entities. + * If change_order is true, the links are put in reverse order in the + * produced route */ +sg_platf_route_cbarg_t generic_new_extended_route(e_surf_routing_hierarchy_t hierarchy, + sg_platf_route_cbarg_t data, int preserve_order); +AS_t +generic_autonomous_system_exist(AS_t rc, char *element); +AS_t +generic_processing_units_exist(AS_t rc, char *element); +void generic_src_dst_check(AS_t rc, sg_routing_edge_t src, + sg_routing_edge_t dst); + +/* ************************************************************************** */ +/* *************************** FLOYD ROUTING ******************************** */ +AS_t model_floyd_create(void); /* create structures for floyd routing model */ +void model_floyd_end(AS_t as); /* finalize the creation of floyd routing model */ +void model_floyd_parse_route(AS_t rc, sg_platf_route_cbarg_t route); + +/* ************************************************** */ +/* ************** Cluster ROUTING **************** */ +class AsCluster : public As { +public: + void *backbone; + void *loopback; + RoutingEdgePtr p_router; +}; +typedef AsCluster *AsClusterPtr; +//FIXME:remove} s_as_cluster_t, *as_cluster_t; + +AsPtr model_cluster_create(void); /* create structures for cluster routing model */ + +/* ************************************************** */ +/* ************** Vivaldi ROUTING **************** */ +AS_t model_vivaldi_create(void); /* create structures for vivaldi routing model */ +#define HOST_PEER(peername) bprintf("peer_%s", peername) +#define ROUTER_PEER(peername) bprintf("router_%s", peername) +#define LINK_PEER(peername) bprintf("link_%s", peername) + +/* ************************************************************************** */ +/* ********** Dijkstra & Dijkstra Cached ROUTING **************************** */ +AS_t model_dijkstra_both_create(int cached); /* create by calling dijkstra or dijkstracache */ +AS_t model_dijkstra_create(void); /* create structures for dijkstra routing model */ +AS_t model_dijkstracache_create(void); /* create structures for dijkstracache routing model */ +void model_dijkstra_both_end(AS_t as); /* finalize the creation of dijkstra routing model */ +void model_dijkstra_both_parse_route (AS_t rc, sg_platf_route_cbarg_t route); + +/* ************************************************************************** */ +/* *************************** FULL ROUTING ********************************* */ +AS_t model_full_create(void); /* create structures for full routing model */ +void model_full_end(AS_t as); /* finalize the creation of full routing model */ +void model_full_set_route( /* Set the route and ASroute between src and dst */ + AS_t rc, sg_platf_route_cbarg_t route); +/* ************************************************************************** */ +/* ************************* GRAPH EXPORTING FUNCTIONS ********************** */ +xbt_node_t new_xbt_graph_node (xbt_graph_t graph, const char *name, xbt_dict_t nodes); +xbt_edge_t new_xbt_graph_edge (xbt_graph_t graph, xbt_node_t s, xbt_node_t d, xbt_dict_t edges); + + +#endif /* _SURF_SURF_ROUTING_PRIVATE_H */ diff --git a/src/surf/surf_routing_vivaldi.cpp b/src/surf/surf_routing_vivaldi.cpp new file mode 100644 index 0000000000..b36798f0d3 --- /dev/null +++ b/src/surf/surf_routing_vivaldi.cpp @@ -0,0 +1,10 @@ +#include "surf_routing_private.h" + +extern "C" { + XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_vivaldi, surf, "Routing part of surf"); +} + + +AS_t model_vivaldi_create(void) +{//FIXME: +} diff --git a/src/surf/surfxml_parse.c b/src/surf/surfxml_parse.c index a8016911e4..ba782bbc1a 100644 --- a/src/surf/surfxml_parse.c +++ b/src/surf/surfxml_parse.c @@ -14,6 +14,7 @@ #include "xbt/dict.h" #include "surf/surfxml_parse.h" #include "surf/surf_private.h" +#include "surf/random_mgr.h" #include "simgrid/sg_config.h" XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_parse, surf, diff --git a/src/surf/workstation.cpp b/src/surf/workstation.cpp new file mode 100644 index 0000000000..a8a4ec183d --- /dev/null +++ b/src/surf/workstation.cpp @@ -0,0 +1,244 @@ +#include "workstation.hpp" +#include "simgrid/sg_config.h" + +extern "C" { +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_workstation, surf, + "Logging specific to the SURF workstation module"); +} + +WorkstationModelPtr surf_workstation_model = NULL; + +//FIXME:Faire hériter ou composer de cup et network + +/********* + * Model * + *********/ + +void surf_workstation_model_init_current_default(void) +{ + surf_workstation_model = new WorkstationModel(); + xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", xbt_strdup("yes")); + surf_cpu_model_init_Cas01(); + surf_network_model_init_LegrandVelho(); + + xbt_dynar_push(model_list, &surf_workstation_model); + //FIXME:sg_platf_host_add_cb(workstation_new); +} + +void surf_workstation_model_init_compound() +{ + + xbt_assert(surf_cpu_model, "No CPU model defined yet!"); + xbt_assert(surf_network_model, "No network model defined yet!"); + surf_workstation_model = new WorkstationModel(); + xbt_dynar_push(model_list, &surf_workstation_model); + //FIXME:sg_platf_host_add_cb(workstation_new); +} + +WorkstationModel::WorkstationModel() : Model("Workstation") { + //FIXME:xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", xbt_strdup("yes")); + //FIXME:surf_cpu_model_init_Cas01(); + //FIXME:surf_network_model_init_LegrandVelho(); + + xbt_dynar_push(model_list, this); + //FIXME:sg_platf_host_add_cb(workstation_new); +} + + +void WorkstationModel::parseInit(sg_platf_host_cbarg_t host){ + createResource(host->id); +} + +WorkstationCLM03Ptr WorkstationModel::createResource(string name){ + + WorkstationCLM03Ptr workstation = new WorkstationCLM03(surf_workstation_model, name.c_str(), NULL, + (xbt_dynar_t)xbt_lib_get_or_null(storage_lib, name.c_str(), ROUTING_STORAGE_HOST_LEVEL), + (RoutingEdgePtr)xbt_lib_get_or_null(host_lib, name.c_str(), ROUTING_HOST_LEVEL), + (CpuPtr)xbt_lib_get_or_null(host_lib, name.c_str(), SURF_CPU_LEVEL)); + XBT_DEBUG("Create workstation %s with %ld mounted disks", name.c_str(), xbt_dynar_length(workstation->p_storage)); + xbt_lib_set(host_lib, name.c_str(), SURF_WKS_LEVEL, workstation); + return workstation; +} + +double WorkstationModel::shareResources(double now){ + return -1.0; +} + +void WorkstationModel::updateActionsState(double now, double delta){ + return; +} + +ActionPtr WorkstationModel::executeParallelTask(int workstation_nb, + void **workstation_list, + double *computation_amount, + double *communication_amount, + double rate){ +#define cost_or_zero(array,pos) ((array)?(array)[pos]:0.0) + if ((workstation_nb == 1) + && (cost_or_zero(communication_amount, 0) == 0.0)) + return ((WorkstationCLM03Ptr)workstation_list[0])->execute(computation_amount[0]); + else if ((workstation_nb == 1) + && (cost_or_zero(computation_amount, 0) == 0.0)) + return communicate((WorkstationCLM03Ptr)workstation_list[0], (WorkstationCLM03Ptr)workstation_list[0],communication_amount[0], rate); + else if ((workstation_nb == 2) + && (cost_or_zero(computation_amount, 0) == 0.0) + && (cost_or_zero(computation_amount, 1) == 0.0)) { + int i,nb = 0; + double value = 0.0; + + for (i = 0; i < workstation_nb * workstation_nb; i++) { + if (cost_or_zero(communication_amount, i) > 0.0) { + nb++; + value = cost_or_zero(communication_amount, i); + } + } + if (nb == 1) + return communicate((WorkstationCLM03Ptr)workstation_list[0], (WorkstationCLM03Ptr)workstation_list[1],value, rate); + } +#undef cost_or_zero + + THROW_UNIMPLEMENTED; /* This model does not implement parallel tasks */ + return NULL; +} + +/* returns an array of network_link_CM02_t */ +xbt_dynar_t WorkstationModel::getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst) +{ + XBT_DEBUG("ws_get_route"); + return surf_network_model->getRoute(src->p_netElm, dst->p_netElm); +} + +ActionPtr WorkstationModel::communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst, double size, double rate){ + surf_network_model->communicate(src->p_netElm, dst->p_netElm, size, rate); +} + + + +/************ + * Resource * + ************/ +WorkstationCLM03::WorkstationCLM03(WorkstationModelPtr model, const char* name, xbt_dict_t properties, xbt_dynar_t storage, RoutingEdgePtr netElm, CpuPtr cpu) + : Resource(model, name, properties), p_storage(storage), p_netElm(netElm), p_cpu(cpu) {} + +bool WorkstationCLM03::isUsed(){ + THROW_IMPOSSIBLE; /* This model does not implement parallel tasks */ + return -1; +} + +void WorkstationCLM03::updateState(tmgr_trace_event_t event_type, double value, double date){ + THROW_IMPOSSIBLE; /* This model does not implement parallel tasks */ +} + +ActionPtr WorkstationCLM03::execute(double size) { + return p_cpu->execute(size); +} + +ActionPtr WorkstationCLM03::sleep(double duration) { + return p_cpu->sleep(duration); +} + +e_surf_resource_state_t WorkstationCLM03::getState() { + return p_cpu->getState(); +} + +int WorkstationCLM03::getCore(){ + return p_cpu->getCore(); +} + +double WorkstationCLM03::getSpeed(double load){ + return p_cpu->getSpeed(load); +} + +double WorkstationCLM03::getAvailableSpeed(){ + return p_cpu->getAvailableSpeed(); +} + +xbt_dict_t WorkstationCLM03::getProperties() +{ + return p_cpu->m_properties; +} + + +StoragePtr WorkstationCLM03::findStorageOnMountList(const char* storage) +{ + StoragePtr st = NULL; + s_mount_t mnt; + unsigned int cursor; + + XBT_DEBUG("Search for storage name '%s' on '%s'",storage,m_name); + xbt_dynar_foreach(p_storage,cursor,mnt) + { + XBT_DEBUG("See '%s'",mnt.name); + if(!strcmp(storage,mnt.name)){ + st = (StoragePtr)mnt.id; + break; + } + } + if(!st) xbt_die("Can't find mount '%s' for '%s'",storage,m_name); + return st; +} + +ActionPtr WorkstationCLM03::open(const char* mount, const char* path) { + StoragePtr st = findStorageOnMountList(mount); + XBT_DEBUG("OPEN on disk '%s'", st->m_name); + return st->open(mount, path); +} + +ActionPtr WorkstationCLM03::close(surf_file_t fd) { + StoragePtr st = findStorageOnMountList(fd->storage); + XBT_DEBUG("CLOSE on disk '%s'",st->m_name); + return st->close(fd); +} + +ActionPtr WorkstationCLM03::read(void* ptr, size_t size, surf_file_t fd) { + StoragePtr st = findStorageOnMountList(fd->storage); + XBT_DEBUG("READ on disk '%s'",st->m_name); + return st->read(ptr, size, fd); +} + +ActionPtr WorkstationCLM03::write(const void* ptr, size_t size, surf_file_t fd) { + StoragePtr st = findStorageOnMountList(fd->storage); + XBT_DEBUG("WRITE on disk '%s'",st->m_name); + return st->write(ptr, size, fd); +} + +int WorkstationCLM03::unlink(surf_file_t fd) { + if (!fd){ + XBT_WARN("No such file descriptor. Impossible to unlink"); + return 0; + } else { +// XBT_INFO("%s %zu", fd->storage, fd->size); + StoragePtr st = findStorageOnMountList(fd->storage); + /* Check if the file is on this storage */ + if (!xbt_dict_get_or_null(st->p_content, fd->name)){ + XBT_WARN("File %s is not on disk %s. Impossible to unlink", fd->name, + st->m_name); + return 0; + } else { + XBT_DEBUG("UNLINK on disk '%s'",st->m_name); + st->m_usedSize -= fd->size; + + // Remove the file from storage + xbt_dict_remove(st->p_content, fd->name); + + free(fd->name); + free(fd->storage); + xbt_free(fd); + return 1; + } + } +} + +ActionPtr WorkstationCLM03::ls(const char* mount, const char *path){ + XBT_DEBUG("LS on mount '%s' and file '%s'", mount, path); + StoragePtr st = findStorageOnMountList(mount); + return st->ls(path); +} + +size_t WorkstationCLM03::getSize(surf_file_t fd){ + return fd->size; +} + +/********** + * Action * + **********/ diff --git a/src/surf/workstation.hpp b/src/surf/workstation.hpp new file mode 100644 index 0000000000..db068ed63c --- /dev/null +++ b/src/surf/workstation.hpp @@ -0,0 +1,106 @@ +#include "surf.hpp" +#include "storage.hpp" +#include "cpu.hpp" +#include "network.hpp" + +#ifndef WORKSTATION_HPP_ +#define WORKSTATION_HPP_ + +/*********** + * Classes * + ***********/ + +class WorkstationModel; +typedef WorkstationModel *WorkstationModelPtr; + +class WorkstationCLM03; +typedef WorkstationCLM03 *WorkstationCLM03Ptr; + +class WorkstationAction; +typedef WorkstationAction *WorkstationActionPtr; + +/*FIXME:class WorkstationActionLmm; +typedef WorkstationActionLmm *WorkstationActionLmmPtr;*/ + +/********* + * Tools * + *********/ +extern WorkstationModelPtr surf_workstation_model; + +/********* + * Model * + *********/ +class WorkstationModel : public Model { +public: + WorkstationModel(string name): Model(name) {}; + WorkstationModel(); + void parseInit(sg_platf_host_cbarg_t host); + WorkstationCLM03Ptr createResource(string name); + double shareResources(double now); + void updateActionsState(double now, double delta); + + ActionPtr executeParallelTask(int workstation_nb, + void **workstation_list, + double *computation_amount, + double *communication_amount, + double rate); + xbt_dynar_t getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst); + ActionPtr communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst, double size, double rate); +}; + +/************ + * Resource * + ************/ + +class WorkstationCLM03 : virtual public Resource { +public: + WorkstationCLM03(WorkstationModelPtr model, const char* name, xbt_dict_t properties, xbt_dynar_t storage, RoutingEdgePtr netElm, CpuPtr cpu); + + void updateState(tmgr_trace_event_t event_type, double value, double date); + + ActionPtr execute(double size); + ActionPtr sleep(double duration); + e_surf_resource_state_t getState(); + + int getCore(); + double getSpeed(double load); + double getAvailableSpeed(); + + xbt_dict_t getProperties(); + + StoragePtr findStorageOnMountList(const char* storage); + ActionPtr open(const char* mount, const char* path); + ActionPtr close(surf_file_t fd); + int unlink(surf_file_t fd); + ActionPtr ls(const char* mount, const char *path); + size_t getSize(surf_file_t fd); + ActionPtr read(void* ptr, size_t size, surf_file_t fd); + ActionPtr write(const void* ptr, size_t size, surf_file_t fd); + bool isUsed(); + //bool isShared(); + xbt_dynar_t p_storage; + RoutingEdgePtr p_netElm; + CpuPtr p_cpu; + NetworkCm02LinkPtr p_network; +}; + +class WorkstationCLM03Lmm : public WorkstationCLM03, public ResourceLmm { +public: + WorkstationCLM03Lmm(WorkstationModelPtr model, const char* name, xbt_dict_t props): WorkstationCLM03(model, name, props, NULL, NULL, NULL){}; +}; + +/********** + * Action * + **********/ +class WorkstationAction : virtual public Action { +public: + WorkstationAction(ModelPtr model, double cost, bool failed): Action(model, cost, failed) {}; +}; + +class WorkstationActionLmm : public ActionLmm, public WorkstationAction { +public: + WorkstationActionLmm(ModelPtr model, double cost, bool failed): ActionLmm(model, cost, failed), WorkstationAction(model, cost, failed) {}; +}; + + +#endif /* WORKSTATION_HPP_ */ diff --git a/src/surf/workstation_ptask_L07.cpp b/src/surf/workstation_ptask_L07.cpp new file mode 100644 index 0000000000..cf8134f14a --- /dev/null +++ b/src/surf/workstation_ptask_L07.cpp @@ -0,0 +1,752 @@ +/* Copyright (c) 2007, 2008, 2009, 2010. The SimGrid Team. + * All rights reserved. */ + +/* This program is free software; you can redistribute it and/or modify it + * under the terms of the license (GNU LGPL) which comes with this package. */ + +#include "workstation_ptask_L07.hpp" +#include "cpu.hpp" +#include "surf_routing.hpp" + +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_workstation); + +static int ptask_host_count = 0; +static xbt_dict_t ptask_parallel_task_link_set = NULL; +lmm_system_t ptask_maxmin_system = NULL; + +WorkstationL07Model::WorkstationL07Model() : WorkstationModel("Workstation ptask_L07") { + if (!ptask_maxmin_system) + ptask_maxmin_system = lmm_system_new(1); + routing_model_create(createLinkResource("__loopback__", + 498000000, NULL, + 0.000015, NULL, + SURF_RESOURCE_ON, NULL, + SURF_LINK_FATPIPE, NULL)); + + surf_network_model = new NetworkL07Model(); +} + +double WorkstationL07Model::shareResources(double now) +{ + void *_action; + WorkstationL07ActionLmmPtr action; + + xbt_swag_t running_actions = surf_workstation_model->p_runningActionSet; + double min = this->shareResourcesMaxMin(running_actions, + xbt_swag_offset((*action), + p_variable), + ptask_maxmin_system, + bottleneck_solve); + + xbt_swag_foreach(_action, running_actions) { + action = (WorkstationL07ActionLmmPtr) _action; + if (action->m_latency > 0) { + if (min < 0) { + min = action->m_latency; + XBT_DEBUG("Updating min (value) with %p (start %f): %f", action, + action->m_start, min); + } else if (action->m_latency < min) { + min = action->m_latency; + XBT_DEBUG("Updating min (latency) with %p (start %f): %f", action, + action->m_start, min); + } + } + } + + XBT_DEBUG("min value : %f", min); + + return min; +} + +void WorkstationL07Model::updateActionsState(double now, double delta) +{ + double deltap = 0.0; + void *_action, *_next_action; + WorkstationL07ActionLmmPtr action; + xbt_swag_t running_actions = + surf_workstation_model->p_runningActionSet; + + xbt_swag_foreach_safe(_action, _next_action, running_actions) { + action = (WorkstationL07ActionLmmPtr) _action; + deltap = delta; + if (action->m_latency > 0) { + if (action->m_latency > deltap) { + double_update(&(action->m_latency), deltap); + deltap = 0.0; + } else { + double_update(&(deltap), action->m_latency); + action->m_latency = 0.0; + } + if ((action->m_latency == 0.0) && (action->m_suspended == 0)) { + action->updateBound(); + lmm_update_variable_weight(ptask_maxmin_system, action->p_variable, 1.0); + } + } + XBT_DEBUG("Action (%p) : remains (%g) updated by %g.", + action, action->m_remains, lmm_variable_getvalue(action->p_variable) * delta); + double_update(&(action->m_remains), lmm_variable_getvalue(action->p_variable) * delta); + + if (action->m_maxDuration != NO_MAX_DURATION) + double_update(&(action->m_maxDuration), delta); + + XBT_DEBUG("Action (%p) : remains (%g).", + action, action->m_remains); + if ((action->m_remains <= 0) && + (lmm_get_variable_weight(action->p_variable) > 0)) { + action->m_finish = surf_get_clock(); + action->setState(SURF_ACTION_DONE); + } else if ((action->m_maxDuration != NO_MAX_DURATION) && + (action->m_maxDuration <= 0)) { + action->m_finish = surf_get_clock(); + action->setState(SURF_ACTION_DONE); + } else { + /* Need to check that none of the model has failed */ + lmm_constraint_t cnst = NULL; + int i = 0; + void *constraint_id = NULL; + + while ((cnst = lmm_get_cnst_from_var(ptask_maxmin_system, action->p_variable, + i++))) { + constraint_id = lmm_constraint_id(cnst); + + if (((WorkstationCLM03Ptr)constraint_id)->m_stateCurrent == SURF_RESOURCE_OFF) { + XBT_DEBUG("Action (%p) Failed!!", action); + action->m_finish = surf_get_clock(); + action->setState(SURF_ACTION_FAILED); + break; + } + } + } + } + return; +} + +ActionPtr WorkstationL07Model::executeParallelTask(int workstation_nb, + void **workstation_list, + double + *computation_amount, double + *communication_amount, + double rate) +{ + WorkstationL07ActionLmmPtr action; + int i, j; + unsigned int cpt; + int nb_link = 0; + int nb_host = 0; + double latency = 0.0; + + if (ptask_parallel_task_link_set == NULL) + ptask_parallel_task_link_set = xbt_dict_new_homogeneous(NULL); + + xbt_dict_reset(ptask_parallel_task_link_set); + + /* Compute the number of affected resources... */ + for (i = 0; i < workstation_nb; i++) { + for (j = 0; j < workstation_nb; j++) { + xbt_dynar_t route=NULL; + + if (communication_amount[i * workstation_nb + j] > 0) { + double lat=0.0; + unsigned int cpt; + LinkL07Ptr link; + + routing_platf->getRouteAndLatency(((CpuL07Ptr)workstation_list[i])->p_info, ((CpuL07Ptr)workstation_list[j])->p_info, &route,&lat); + latency = MAX(latency, lat); + + xbt_dynar_foreach(route, cpt, link) { + xbt_dict_set(ptask_parallel_task_link_set,link->m_name,link,NULL); + } + } + } + } + + nb_link = xbt_dict_length(ptask_parallel_task_link_set); + xbt_dict_reset(ptask_parallel_task_link_set); + + for (i = 0; i < workstation_nb; i++) + if (computation_amount[i] > 0) + nb_host++; + + action = new WorkstationL07ActionLmm(this, 1, 0); + XBT_DEBUG("Creating a parallel task (%p) with %d cpus and %d links.", + action, workstation_nb, nb_link); + action->m_suspended = 0; /* Should be useless because of the + calloc but it seems to help valgrind... */ + action->m_workstationNb = workstation_nb; + action->p_workstationList = (WorkstationCLM03Ptr *) workstation_list; + action->p_computationAmount = computation_amount; + action->p_communicationAmount = communication_amount; + action->m_latency = latency; + action->m_rate = rate; + + action->p_variable = lmm_variable_new(ptask_maxmin_system, action, 1.0, + (action->m_rate > 0) ? action->m_rate : -1.0, + workstation_nb + nb_link); + + if (action->m_latency > 0) + lmm_update_variable_weight(ptask_maxmin_system, action->p_variable, 0.0); + + for (i = 0; i < workstation_nb; i++) + lmm_expand(ptask_maxmin_system, ((CpuL07Ptr)workstation_list[i])->p_constraint, + action->p_variable, computation_amount[i]); + + for (i = 0; i < workstation_nb; i++) { + for (j = 0; j < workstation_nb; j++) { + LinkL07Ptr link; + xbt_dynar_t route=NULL; + if (communication_amount[i * workstation_nb + j] == 0.0) + continue; + + routing_platf->getRouteAndLatency(((CpuL07Ptr)workstation_list[i])->p_info, ((CpuL07Ptr)workstation_list[j])->p_info, &route,NULL); + + xbt_dynar_foreach(route, cpt, link) { + lmm_expand_add(ptask_maxmin_system, link->p_constraint, + action->p_variable, + communication_amount[i * workstation_nb + j]); + } + } + } + + if (nb_link + nb_host == 0) { + action->m_cost = 1.0; + action->m_remains = 0.0; + } + + return (surf_action_t) action; +} + +ActionPtr WorkstationL07Model::communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst, + double size, double rate) +{ + void **workstation_list = xbt_new0(void *, 2); + double *computation_amount = xbt_new0(double, 2); + double *communication_amount = xbt_new0(double, 4); + ActionPtr res = NULL; + + workstation_list[0] = src; + workstation_list[1] = dst; + communication_amount[1] = size; + + res = executeParallelTask(2, workstation_list, + computation_amount, + communication_amount, rate); + + return res; +} + +xbt_dynar_t WorkstationL07Model::getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst) +{ + xbt_dynar_t route=NULL; + routing_platf->getRouteAndLatency(((CpuL07Ptr)src)->p_info, ((CpuL07Ptr)dst)->p_info, &route,NULL); + return route; +} + +WorkstationCLM03Ptr WorkstationL07Model::createCpuResource(const char *name, double power_scale, + double power_initial, + tmgr_trace_t power_trace, + e_surf_resource_state_t state_initial, + tmgr_trace_t state_trace, + xbt_dict_t cpu_properties) +{ + CpuL07Ptr cpu = NULL; + xbt_assert(!surf_workstation_resource_priv(surf_workstation_resource_by_name(name)), + "Host '%s' declared several times in the platform file.", + name); + + cpu = new CpuL07(this, name, cpu_properties); + + cpu->p_info = (RoutingEdgePtr) xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL); + if(!(cpu->p_info)) xbt_die("Don't find ROUTING_HOST_LEVEL for '%s'",name); + + cpu->p_power.scale = power_scale; + xbt_assert(cpu->p_power.scale > 0, "Power has to be >0"); + + cpu->m_powerCurrent = power_initial; + if (power_trace) + cpu->p_power.event = + tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu); + + cpu->m_stateCurrent = state_initial; + if (state_trace) + cpu->p_stateEvent = + tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu); + + cpu->p_constraint = + lmm_constraint_new(ptask_maxmin_system, cpu, + cpu->m_powerCurrent * cpu->p_power.scale); + + xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, cpu); + + return cpu;//FIXME:xbt_lib_get_elm_or_null(host_lib, name); +} + +WorkstationCLM03Ptr WorkstationL07Model::createLinkResource(const char *name, + double bw_initial, + tmgr_trace_t bw_trace, + double lat_initial, + tmgr_trace_t lat_trace, + e_surf_resource_state_t + state_initial, + tmgr_trace_t state_trace, + e_surf_link_sharing_policy_t + policy, xbt_dict_t properties) +{ + LinkL07Ptr nw_link = new LinkL07(this, xbt_strdup(name), properties); + xbt_assert(!xbt_lib_get_or_null(link_lib, name, SURF_LINK_LEVEL), + "Link '%s' declared several times in the platform file.", + name); + + nw_link->m_bwCurrent = bw_initial; + if (bw_trace) + nw_link->p_bwEvent = + tmgr_history_add_trace(history, bw_trace, 0.0, 0, nw_link); + nw_link->p_stateCurrent = state_initial; + nw_link->m_latCurrent = lat_initial; + if (lat_trace) + nw_link->p_latEvent = + tmgr_history_add_trace(history, lat_trace, 0.0, 0, nw_link); + if (state_trace) + nw_link->p_stateEvent = + tmgr_history_add_trace(history, state_trace, 0.0, 0, nw_link); + + nw_link->p_constraint = + lmm_constraint_new(ptask_maxmin_system, nw_link, + nw_link->m_bwCurrent); + + if (policy == SURF_LINK_FATPIPE) + lmm_constraint_shared(nw_link->p_constraint); + + xbt_lib_set(link_lib, name, SURF_LINK_LEVEL, nw_link); + return nw_link; +} + +void WorkstationL07Model::addTraces() +{ + xbt_dict_cursor_t cursor = NULL; + char *trace_name, *elm; + + if (!trace_connect_list_host_avail) + return; + + /* Connect traces relative to cpu */ + xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) { + tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name); + CpuL07Ptr host = (CpuL07Ptr) surf_workstation_resource_priv(surf_workstation_resource_by_name(elm)); + + xbt_assert(host, "Host %s undefined", elm); + xbt_assert(trace, "Trace %s undefined", trace_name); + + host->p_stateEvent = tmgr_history_add_trace(history, trace, 0.0, 0, host); + } + + xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) { + tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name); + CpuL07Ptr host = (CpuL07Ptr) surf_workstation_resource_priv(surf_workstation_resource_by_name(elm)); + + xbt_assert(host, "Host %s undefined", elm); + xbt_assert(trace, "Trace %s undefined", trace_name); + + host->p_power.event = tmgr_history_add_trace(history, trace, 0.0, 0, host); + } + + /* Connect traces relative to network */ + xbt_dict_foreach(trace_connect_list_link_avail, cursor, trace_name, elm) { + tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name); + LinkL07Ptr link = (LinkL07Ptr) xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL); + + xbt_assert(link, "Link %s undefined", elm); + xbt_assert(trace, "Trace %s undefined", trace_name); + + link->p_stateEvent = tmgr_history_add_trace(history, trace, 0.0, 0, link); + } + + xbt_dict_foreach(trace_connect_list_bandwidth, cursor, trace_name, elm) { + tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name); + LinkL07Ptr link = (LinkL07Ptr) xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL); + + xbt_assert(link, "Link %s undefined", elm); + xbt_assert(trace, "Trace %s undefined", trace_name); + + link->p_bwEvent = tmgr_history_add_trace(history, trace, 0.0, 0, link); + } + + xbt_dict_foreach(trace_connect_list_latency, cursor, trace_name, elm) { + tmgr_trace_t trace = (tmgr_trace_t) xbt_dict_get_or_null(traces_set_list, trace_name); + LinkL07Ptr link = (LinkL07Ptr) xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL); + + xbt_assert(link, "Link %s undefined", elm); + xbt_assert(trace, "Trace %s undefined", trace_name); + + link->p_latEvent = tmgr_history_add_trace(history, trace, 0.0, 0, link); + } +} + +/************ + * Resource * + ************/ + +CpuL07::CpuL07(WorkstationL07ModelPtr model, const char* name, xbt_dict_t props) : WorkstationCLM03Lmm(model, name, props) { + +} + +LinkL07::LinkL07(WorkstationL07ModelPtr model, const char* name, xbt_dict_t props) : WorkstationCLM03Lmm(model, name, props) { + +} + +bool CpuL07::isUsed(){ + return lmm_constraint_used(ptask_maxmin_system, p_constraint); +} + +bool LinkL07::isUsed(){ + return lmm_constraint_used(ptask_maxmin_system, p_constraint); +} + +void CpuL07::updateState(tmgr_trace_event_t event_type, double value, double date){ + XBT_DEBUG("Updating cpu %s (%p) with value %g", m_name, this, value); + if (event_type == p_power.event) { + m_powerCurrent = value; + lmm_update_constraint_bound(ptask_maxmin_system, p_constraint, m_powerCurrent * p_power.scale); + if (tmgr_trace_event_free(event_type)) + p_power.event = NULL; + } else if (event_type == p_stateEvent) { + if (value > 0) + p_stateCurrent = SURF_RESOURCE_ON; + else + p_stateCurrent = SURF_RESOURCE_OFF; + if (tmgr_trace_event_free(event_type)) + p_stateEvent = NULL; + } else { + XBT_CRITICAL("Unknown event ! \n"); + xbt_abort(); + } + return; +} + +void LinkL07::updateState(tmgr_trace_event_t event_type, double value, double date){ + XBT_DEBUG("Updating link %s (%p) with value=%f for date=%g", m_name, this, value, date); + if (event_type == p_bwEvent) { + m_bwCurrent = value; + lmm_update_constraint_bound(ptask_maxmin_system, p_constraint, m_bwCurrent); + if (tmgr_trace_event_free(event_type)) + p_bwEvent = NULL; + } else if (event_type == p_latEvent) { + lmm_variable_t var = NULL; + WorkstationL07ActionLmmPtr action; + lmm_element_t elem = NULL; + + m_latCurrent = value; + while ((var = lmm_get_var_from_cnst(ptask_maxmin_system, p_constraint, &elem))) { + action = (WorkstationL07ActionLmmPtr) lmm_variable_id(var); + action->updateBound(); + } + if (tmgr_trace_event_free(event_type)) + p_latEvent = NULL; + } else if (event_type == p_stateEvent) { + if (value > 0) + p_stateCurrent = SURF_RESOURCE_ON; + else + p_stateCurrent = SURF_RESOURCE_OFF; + if (tmgr_trace_event_free(event_type)) + p_stateEvent = NULL; + } else { + XBT_CRITICAL("Unknown event ! \n"); + xbt_abort(); + } + return; +} + + +e_surf_resource_state_t CpuL07::getState() +{ + return p_stateCurrent; +} + +double CpuL07::getSpeed(double load) +{ + return load * p_power.scale; +} + +double CpuL07::getAvailableSpeed() +{ + return m_powerCurrent; +} + +ActionPtr CpuL07::execute(double size) +{ + void **workstation_list = xbt_new0(void *, 1); + double *computation_amount = xbt_new0(double, 1); + double *communication_amount = xbt_new0(double, 1); + + workstation_list[0] = this; + communication_amount[0] = 0.0; + computation_amount[0] = size; + + return ((WorkstationL07ModelPtr)p_model)->executeParallelTask(1, workstation_list, + computation_amount, + communication_amount, -1); +} + +ActionPtr CpuL07::sleep(double duration) +{ + WorkstationL07ActionLmmPtr action = NULL; + + XBT_IN("(%s,%g)", m_name, duration); + + action = dynamic_cast(execute(1.0)); + action->m_maxDuration = duration; + action->m_suspended = 2; + lmm_update_variable_weight(ptask_maxmin_system, action->p_variable, 0.0); + + XBT_OUT(); + return action; +} + +double LinkL07::getBandwidth() +{ + return m_bwCurrent; +} + +double LinkL07::getLatency() +{ + return m_latCurrent; +} + +bool LinkL07::isShared() +{ + return lmm_constraint_is_shared(p_constraint); +} + +/********** + * Action * + **********/ + +WorkstationL07ActionLmm::~WorkstationL07ActionLmm(){ + free(p_workstationList); + free(p_communicationAmount); + free(p_computationAmount); +#ifdef HAVE_TRACING + xbt_free(p_category); +#endif +} + +void WorkstationL07ActionLmm::updateBound() +{ + double lat_current = 0.0; + double lat_bound = -1.0; + int i, j; + + for (i = 0; i < m_workstationNb; i++) { + for (j = 0; j < m_workstationNb; j++) { + xbt_dynar_t route=NULL; + + if (p_communicationAmount[i * m_workstationNb + j] > 0) { + double lat = 0.0; + routing_platf->getRouteAndLatency(((CpuL07Ptr) p_workstationList[i])->p_info, ((CpuL07Ptr)p_workstationList[j])->p_info, &route, &lat); + + lat_current = MAX(lat_current, lat * p_communicationAmount[i * m_workstationNb + j]); + } + } + } + lat_bound = sg_tcp_gamma / (2.0 * lat_current); + XBT_DEBUG("action (%p) : lat_bound = %g", this, lat_bound); + if ((m_latency == 0.0) && (m_suspended == 0)) { + if (m_rate < 0) + lmm_update_variable_bound(ptask_maxmin_system, p_variable, lat_bound); + else + lmm_update_variable_bound(ptask_maxmin_system, p_variable, min(m_rate, lat_bound)); + } +} + +int WorkstationL07ActionLmm::unref() +{ + m_refcount--; + if (!m_refcount) { + xbt_swag_remove(this, p_stateSet); + if (p_variable) + lmm_variable_free(ptask_maxmin_system, p_variable); + delete this; + return 1; + } + return 0; +} + +void WorkstationL07ActionLmm::cancel() +{ + setState(SURF_ACTION_FAILED); + return; +} + +void WorkstationL07ActionLmm::suspend() +{ + XBT_IN("(%p))", this); + if (m_suspended != 2) { + m_suspended = 1; + lmm_update_variable_weight(ptask_maxmin_system, p_variable, 0.0); + } + XBT_OUT(); +} + +void WorkstationL07ActionLmm::resume() +{ + XBT_IN("(%p)", this); + if (m_suspended != 2) { + lmm_update_variable_weight(ptask_maxmin_system, p_variable, 1.0); + m_suspended = 0; + } + XBT_OUT(); +} + +bool WorkstationL07ActionLmm::isSuspended() +{ + return m_suspended == 1; +} + +void WorkstationL07ActionLmm::setMaxDuration(double duration) +{ /* FIXME: should inherit */ + XBT_IN("(%p,%g)", this, duration); + m_maxDuration = duration; + XBT_OUT(); +} + +void WorkstationL07ActionLmm::setPriority(double priority) +{ /* FIXME: should inherit */ + XBT_IN("(%p,%g)", this, priority); + m_priority = priority; + XBT_OUT(); +} + +double WorkstationL07ActionLmm::getRemains() +{ + XBT_IN("(%p)", this); + XBT_OUT(); + return m_remains; +} + + + + + + + + + +static void ptask_finalize(void) +{ + xbt_dict_free(&ptask_parallel_task_link_set); + + delete surf_workstation_model; + surf_workstation_model = NULL; + delete surf_network_model; + surf_network_model = NULL; + + ptask_host_count = 0; + + if (ptask_maxmin_system) { + lmm_system_free(ptask_maxmin_system); + ptask_maxmin_system = NULL; + } +} + +/**************************************/ +/******* Resource Private **********/ +/**************************************/ + + + + + + + + + + + + + + + + +/**************************************/ +/*** Resource Creation & Destruction **/ +/**************************************/ + + + +static void ptask_parse_cpu_init(sg_platf_host_cbarg_t host) +{ + ((WorkstationL07ModelPtr)surf_workstation_model)->createCpuResource( + host->id, + host->power_peak, + host->power_scale, + host->power_trace, + host->initial_state, + host->state_trace, + host->properties); +} + + + +static void ptask_parse_link_init(sg_platf_link_cbarg_t link) +{ + if (link->policy == SURF_LINK_FULLDUPLEX) { + char *link_id; + link_id = bprintf("%s_UP", link->id); + ((WorkstationL07ModelPtr)surf_workstation_model)->createLinkResource(link_id, + link->bandwidth, + link->bandwidth_trace, + link->latency, + link->latency_trace, + link->state, + link->state_trace, + link->policy, + link->properties); + xbt_free(link_id); + link_id = bprintf("%s_DOWN", link->id); + ((WorkstationL07ModelPtr)surf_workstation_model)->createLinkResource(link_id, + link->bandwidth, + link->bandwidth_trace, + link->latency, + link->latency_trace, + link->state, + link->state_trace, + link->policy, + NULL); /* FIXME: We need to deep copy the + * properties or we won't be able to free + * it */ + xbt_free(link_id); + } else { + ((WorkstationL07ModelPtr)surf_workstation_model)->createLinkResource(link->id, + link->bandwidth, + link->bandwidth_trace, + link->latency, + link->latency_trace, + link->state, + link->state_trace, + link->policy, + link->properties); + } + + current_property_set = NULL; +} + + + +static void ptask_define_callbacks() +{ + sg_platf_host_add_cb(ptask_parse_cpu_init); + sg_platf_link_add_cb(ptask_parse_link_init); + //FIXME:sg_platf_postparse_add_cb(ptask_add_traces); +} + +/**************************************/ +/*************** Generic **************/ +/**************************************/ +void surf_workstation_model_init_ptask_L07(void) +{ + XBT_INFO("surf_workstation_model_init_ptask_L07"); + xbt_assert(!surf_cpu_model, "CPU model type already defined"); + xbt_assert(!surf_network_model, "network model type already defined"); + ptask_define_callbacks(); + new WorkstationL07Model(); + xbt_dynar_push(model_list, &surf_workstation_model); +} diff --git a/src/surf/workstation_ptask_L07.hpp b/src/surf/workstation_ptask_L07.hpp new file mode 100644 index 0000000000..38a6e9e498 --- /dev/null +++ b/src/surf/workstation_ptask_L07.hpp @@ -0,0 +1,134 @@ +#include "workstation.hpp" + +#ifndef WORKSTATION_L07_HPP_ +#define WORKSTATION_L07_HPP_ + +/*********** + * Classes * + ***********/ + +class WorkstationL07Model; +typedef WorkstationL07Model *WorkstationL07ModelPtr; + +class CpuL07; +typedef CpuL07 *CpuL07Ptr; + +class LinkL07; +typedef LinkL07 *LinkL07Ptr; + +class WorkstationL07ActionLmm; +typedef WorkstationL07ActionLmm *WorkstationL07ActionLmmPtr; + +/*FIXME:class WorkstationActionLmm; +typedef WorkstationActionLmm *WorkstationActionLmmPtr;*/ + +/********* + * Tools * + *********/ + +/********* + * Model * + *********/ +class WorkstationL07Model : public WorkstationModel { +public: + WorkstationL07Model(); + void parseInit(sg_platf_host_cbarg_t host); + WorkstationCLM03Ptr createCpuResource(const char *name, double power_scale, + double power_initial, + tmgr_trace_t power_trace, + e_surf_resource_state_t state_initial, + tmgr_trace_t state_trace, + xbt_dict_t cpu_properties); + WorkstationCLM03Ptr createLinkResource(const char *name, + double bw_initial, + tmgr_trace_t bw_trace, + double lat_initial, + tmgr_trace_t lat_trace, + e_surf_resource_state_t + state_initial, + tmgr_trace_t state_trace, + e_surf_link_sharing_policy_t + policy, xbt_dict_t properties); + double shareResources(double now); + void updateActionsState(double now, double delta); + void addTraces(); + + ActionPtr executeParallelTask(int workstation_nb, + void **workstation_list, + double *computation_amount, + double *communication_amount, + double rate); + xbt_dynar_t getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst); + ActionPtr communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst, double size, double rate); +}; + +class NetworkL07Model : public NetworkCm02Model { +public: + NetworkL07Model(): NetworkCm02Model() {}; + xbt_dynar_t getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst) {DIE_IMPOSSIBLE;}; + ActionPtr communicate(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst, double size, double rate) {DIE_IMPOSSIBLE;}; + void addTraces() {DIE_IMPOSSIBLE;}; +}; + +/************ + * Resource * + ************/ + +class CpuL07 : public WorkstationCLM03Lmm { +public: + CpuL07(WorkstationL07ModelPtr model, const char* name, xbt_dict_t properties); + bool isUsed(); + void updateState(tmgr_trace_event_t event_type, double value, double date); + e_surf_resource_state_t getState(); + double getSpeed(double load); + double getAvailableSpeed(); + ActionPtr execute(double size); + ActionPtr sleep(double duration); + + double m_powerCurrent; + RoutingEdgePtr p_info; +}; + +class LinkL07 : public WorkstationCLM03Lmm { +public: + LinkL07(WorkstationL07ModelPtr model, const char* name, xbt_dict_t props); + bool isUsed(); + void updateState(tmgr_trace_event_t event_type, double value, double date); + double getBandwidth(); + double getLatency(); + bool isShared(); + + double m_latCurrent; + tmgr_trace_event_t p_latEvent; + double m_bwCurrent; + tmgr_trace_event_t p_bwEvent; +}; + +/********** + * Action * + **********/ +class WorkstationL07ActionLmm : public WorkstationActionLmm { +public: + WorkstationL07ActionLmm(ModelPtr model, double cost, bool failed): WorkstationActionLmm(model, cost, failed) {}; + ~WorkstationL07ActionLmm(); + + void updateBound(); + + int unref(); + void cancel(); + void suspend(); + void resume(); + bool isSuspended(); + void setMaxDuration(double duration); + void setPriority(double priority); + double getRemains(); + + int m_workstationNb; + WorkstationCLM03Ptr *p_workstationList; + double *p_computationAmount; + double *p_communicationAmount; + double m_latency; + double m_rate; +}; + +#endif /* WORKSTATION_L07_HPP_ */ diff --git a/teshsuite/simdag/platforms/flatifier.c b/teshsuite/simdag/platforms/flatifier.c index 0fcec51730..e2bd77ce07 100644 --- a/teshsuite/simdag/platforms/flatifier.c +++ b/teshsuite/simdag/platforms/flatifier.c @@ -155,8 +155,8 @@ int main(int argc, char **argv) // Routers xbt_lib_foreach(as_router_lib, cursor_src, key, value1) { - if(((sg_routing_edge_t)xbt_lib_get_or_null(as_router_lib, key, - ROUTING_ASR_LEVEL))->rc_type == SURF_NETWORK_ELEMENT_ROUTER) + if(surf_routing_edge_get_rc_type(xbt_lib_get_or_null(as_router_lib, key, + ROUTING_ASR_LEVEL)) == SURF_NETWORK_ELEMENT_ROUTER) { printf(" \n",key); } @@ -198,7 +198,7 @@ int main(int argc, char **argv) { void *link = xbt_dynar_get_as(route,i,void *); - char *link_name = xbt_strdup(((surf_resource_t)link)->name); + char *link_name = xbt_strdup(surf_resource_name(link)); printf("<%s id=\"%s\"/>",link_ctn,link_name); free(link_name); } @@ -217,7 +217,7 @@ int main(int argc, char **argv) { void *link = xbt_dynar_get_as(route,i,void *); - char *link_name = xbt_strdup(((surf_resource_t)link)->name); + char *link_name = xbt_strdup(surf_resource_name(link)); printf("<%s id=\"%s\"/>",link_ctn,link_name); free(link_name); } @@ -243,7 +243,7 @@ int main(int argc, char **argv) { void *link = xbt_dynar_get_as(route,i,void *); - char *link_name = xbt_strdup(((surf_resource_t)link)->name); + char *link_name = xbt_strdup(surf_resource_name(link)); printf("<%s id=\"%s\"/>",link_ctn,link_name); free(link_name); } @@ -261,7 +261,7 @@ int main(int argc, char **argv) { void *link = xbt_dynar_get_as(route,i,void *); - char *link_name = xbt_strdup(((surf_resource_t)link)->name); + char *link_name = xbt_strdup(surf_resource_name(link)); printf("<%s id=\"%s\"/>",link_ctn,link_name); free(link_name); } diff --git a/testsuite/surf/lmm_usage.c b/testsuite/surf/lmm_usage.c index 9b6bd023ca..37bb41e52b 100644 --- a/testsuite/surf/lmm_usage.c +++ b/testsuite/surf/lmm_usage.c @@ -11,7 +11,7 @@ #endif #include "xbt/sysdep.h" -#include "surf/solver.h" +#include "surf/maxmin.h" #include "xbt/log.h" #include "xbt/module.h" #include diff --git a/testsuite/surf/maxmin_bench.c b/testsuite/surf/maxmin_bench.c index 8aaca95e66..0d46aa5a81 100644 --- a/testsuite/surf/maxmin_bench.c +++ b/testsuite/surf/maxmin_bench.c @@ -11,7 +11,7 @@ #endif -#include "surf/solver.h" +#include "surf/maxmin.h" #include "xbt/module.h" #include "xbt/xbt_os_time.h" #include "xbt/sysdep.h" /* time manipulation for benchmarking */ diff --git a/testsuite/surf/surf_usage.c b/testsuite/surf/surf_usage.c index 1224959352..a57a3996f8 100644 --- a/testsuite/surf/surf_usage.c +++ b/testsuite/surf/surf_usage.c @@ -67,14 +67,14 @@ void test(char *platform) XBT_DEBUG("%s : %p", surf_resource_name(cpuB), cpuB); /* Let's do something on it */ - actionA = surf_cpu_model->extension.cpu.execute(cpuA, 1000.0); - actionB = surf_cpu_model->extension.cpu.execute(cpuB, 1000.0); - actionC = surf_cpu_model->extension.cpu.sleep(cpuB, 7.32); + actionA = surf_cpu_execute(cpuA, 1000.0); + actionB = surf_cpu_execute(cpuB, 1000.0); + actionC = surf_cpu_sleep(cpuB, 7.32); /* Use whatever calling style you want... */ - stateActionA = surf_cpu_model->action_state_get(actionA); /* When you know actionA model type */ - stateActionB = actionB->model_type->action_state_get(actionB); /* If you're unsure about it's model type */ - stateActionC = surf_cpu_model->action_state_get(actionC); /* When you know actionA model type */ + stateActionA = surf_action_get_state(actionA); /* When you know actionA model type */ + stateActionB = surf_action_get_state(actionB); /* If you're unsure about it's model type */ + stateActionC = surf_action_get_state(actionC); /* When you know actionA model type */ /* And just look at the state of these tasks */ XBT_DEBUG("actionA : %p (%s)", actionA, string_action(stateActionA)); @@ -91,8 +91,7 @@ void test(char *platform) XBT_DEBUG("%s : %p", surf_resource_name(cardB), cardB); /* Let's do something on it */ - surf_network_model->extension.network.communicate(cardA, cardB, - 150.0, -1.0); + surf_network_model_communicate(surf_network_model, cardA, cardB, 150.0, -1.0); surf_solve(-1.0); /* Takes traces into account. Returns 0.0 */ do { @@ -101,31 +100,29 @@ void test(char *platform) XBT_DEBUG("Next Event : %g", now); XBT_DEBUG("\t CPU actions"); while ((action = - xbt_swag_extract(surf_cpu_model->states.failed_action_set))) { + xbt_swag_extract(surf_model_failed_action_set((surf_model_t)surf_cpu_model)))) { XBT_DEBUG("\t * Failed : %p", action); - action->model_type->action_unref(action); + surf_action_unref(action); } while ((action = - xbt_swag_extract(surf_cpu_model->states.done_action_set))) { + xbt_swag_extract(surf_model_done_action_set((surf_model_t)surf_cpu_model)))) { XBT_DEBUG("\t * Done : %p", action); - action->model_type->action_unref(action); + surf_action_unref(action); } XBT_DEBUG("\t Network actions"); while ((action = - xbt_swag_extract(surf_network_model->states. - failed_action_set))) { + xbt_swag_extract(surf_model_failed_action_set((surf_model_t)surf_network_model)))) { XBT_DEBUG("\t * Failed : %p", action); - action->model_type->action_unref(action); + surf_action_unref(action); } while ((action = - xbt_swag_extract(surf_network_model->states. - done_action_set))) { + xbt_swag_extract(surf_model_done_action_set((surf_model_t)surf_network_model)))) { XBT_DEBUG("\t * Done : %p", action); - action->model_type->action_unref(action); + surf_action_unref(action); } - } while ((xbt_swag_size(surf_network_model->states.running_action_set) || - xbt_swag_size(surf_cpu_model->states.running_action_set)) && + } while ((xbt_swag_size(surf_model_running_action_set((surf_model_t)surf_network_model)) || + xbt_swag_size(surf_model_running_action_set((surf_model_t)surf_cpu_model))) && surf_solve(-1.0) >= 0.0); XBT_DEBUG("Simulation Terminated"); diff --git a/testsuite/surf/surf_usage2.c b/testsuite/surf/surf_usage2.c index 4c92bea7a8..9ff6cb8ebb 100644 --- a/testsuite/surf/surf_usage2.c +++ b/testsuite/surf/surf_usage2.c @@ -62,12 +62,11 @@ void test(char *platform) XBT_DEBUG("%s : %p", surf_resource_name(workstationB), workstationB); /* Let's do something on it */ - surf_workstation_model->extension.workstation.execute(workstationA, 1000.0); - surf_workstation_model->extension.workstation.execute(workstationB, 1000.0); - surf_workstation_model->extension.workstation.sleep(workstationB, 7.32); + surf_workstation_execute(workstationA, 1000.0); + surf_workstation_execute(workstationB, 1000.0); + surf_workstation_sleep(workstationB, 7.32); - surf_workstation_model->extension.workstation. - communicate(workstationA, workstationB, 150.0, -1.0); + surf_workstation_model_communicate(surf_workstation_model, workstationA, workstationB, 150.0, -1.0); surf_solve(-1.0); /* Takes traces into account. Returns 0.0 */ do { @@ -80,17 +79,17 @@ void test(char *platform) XBT_DEBUG("Next Event : %g", now); xbt_dynar_foreach(model_list, iter, model) { - XBT_DEBUG("\t %s actions", model->name); - while ((action = xbt_swag_extract(model->states.failed_action_set))) { + XBT_DEBUG("\t %s actions", surf_model_name(model)); + while ((action = xbt_swag_extract(surf_model_failed_action_set((surf_model_t)model)))) { XBT_DEBUG("\t * Failed : %p", action); - model->action_unref(action); + surf_action_unref(action); } - while ((action = xbt_swag_extract(model->states.done_action_set))) { + while ((action = xbt_swag_extract(surf_model_done_action_set((surf_model_t)model)))) { XBT_DEBUG("\t * Done : %p", action); - model->action_unref(action); + surf_action_unref(action); } - if (xbt_swag_size(model->states.running_action_set)) { - XBT_DEBUG("running %s", model->name); + if (xbt_swag_size(surf_model_running_action_set((surf_model_t)model))) { + XBT_DEBUG("running %s", surf_model_name(model)); running = 1; } }