Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'surf++'
authorPaul Bédaride <paul.bedaride@gmail.com>
Fri, 15 Nov 2013 14:27:48 +0000 (15:27 +0100)
committerPaul Bédaride <paul.bedaride@gmail.com>
Fri, 15 Nov 2013 14:27:48 +0000 (15:27 +0100)
Conflicts:
src/include/surf/surf.h
src/instr/instr_private.h
src/simix/smx_smurf_private.h
src/smpi/smpi_bench.c
src/surf/workstation.c

156 files changed:
.cproject
.project
CMakeLists.txt
buildtools/Cmake/DefinePackages.cmake
buildtools/Cmake/Flags.cmake
doc/doxygen/platform.doc
examples/java/cloud/Cloud.java
examples/java/cloud/Master.java
examples/java/cloud/Slave.java
examples/msg/cloud/CMakeLists.txt
examples/msg/cloud/bound.c [new file with mode: 0644]
examples/msg/cloud/masterslave_virtual_machines.c
examples/msg/cloud/migrate_vm.c [new file with mode: 0644]
examples/msg/cloud/multicore.c [new file with mode: 0644]
examples/msg/cloud/multicore_plat.xml [new file with mode: 0644]
examples/msg/cloud/scale.c [new file with mode: 0644]
examples/msg/cloud/simple_plat.xml [new file with mode: 0644]
examples/msg/cloud/simple_vm.c [new file with mode: 0644]
include/msg/datatypes.h
include/msg/msg.h
include/simgrid/platf.h
include/simgrid/simix.h
include/surf/surf_routing.h
include/xbt/automaton.h
include/xbt/ex.h
include/xbt/heap.h
include/xbt/lib.h
include/xbt/module.h
src/bindings/java/jmsg_host.c
src/bindings/java/jmsg_host.h
src/bindings/java/jmsg_task.c
src/bindings/java/jmsg_task.h
src/bindings/java/jmsg_vm.c
src/bindings/java/jmsg_vm.h
src/bindings/java/org/simgrid/msg/Host.java
src/bindings/java/org/simgrid/msg/Task.java
src/bindings/java/org/simgrid/msg/VM.java
src/bindings/java/smx_context_java.c
src/bindings/lua/lua_host.c
src/include/instr/instr_interface.h
src/include/simgrid/platf_interface.h
src/include/simgrid/sg_config.h
src/include/surf/datatypes.h
src/include/surf/maxmin.h
src/include/surf/surf.h
src/include/surf/surf_resource.h
src/include/surf/surf_resource_lmm.h
src/include/surf/trace_mgr.h
src/instr/instr_interface.c
src/instr/instr_private.h
src/msg/instr_msg_vm.c
src/msg/msg_global.c
src/msg/msg_gos.c
src/msg/msg_host.c
src/msg/msg_private.h
src/msg/msg_process.c
src/msg/msg_task.c
src/msg/msg_vm.c
src/simdag/sd_global.c
src/simdag/sd_link.c
src/simdag/sd_task.c
src/simdag/sd_workstation.c
src/simgrid/sg_config.c
src/simix/smx_deployment.c
src/simix/smx_global.c
src/simix/smx_host.c
src/simix/smx_host_private.h
src/simix/smx_io.c
src/simix/smx_network.c
src/simix/smx_new_api.c
src/simix/smx_process.c
src/simix/smx_smurf.c
src/simix/smx_smurf_private.h
src/simix/smx_synchro.c
src/simix/smx_user.c
src/simix/smx_vm.c [new file with mode: 0644]
src/smpi/smpi_bench.c
src/surf/cpu.cpp [new file with mode: 0644]
src/surf/cpu.hpp [new file with mode: 0644]
src/surf/cpu_cas01.c [deleted file]
src/surf/cpu_cas01.cpp [new file with mode: 0644]
src/surf/cpu_cas01.hpp [new file with mode: 0644]
src/surf/cpu_cas01_private.h
src/surf/cpu_ti.c [deleted file]
src/surf/cpu_ti.cpp [new file with mode: 0644]
src/surf/cpu_ti.hpp [new file with mode: 0644]
src/surf/cpu_ti_private.h [deleted file]
src/surf/fair_bottleneck.cpp [new file with mode: 0644]
src/surf/instr_routing.c
src/surf/instr_surf.c
src/surf/lagrange.cpp [new file with mode: 0644]
src/surf/maxmin.c
src/surf/maxmin_private_.h [new file with mode: 0644]
src/surf/network.c
src/surf/network.cpp [new file with mode: 0644]
src/surf/network.hpp [new file with mode: 0644]
src/surf/network_constant.c
src/surf/network_constant.cpp [new file with mode: 0644]
src/surf/network_constant.hpp [new file with mode: 0644]
src/surf/network_gtnets.c
src/surf/network_gtnets.cpp [new file with mode: 0644]
src/surf/network_gtnets.hpp [new file with mode: 0644]
src/surf/network_ns3.c
src/surf/network_private.h [deleted file]
src/surf/network_smpi.cpp [new file with mode: 0644]
src/surf/network_smpi.hpp [new file with mode: 0644]
src/surf/new_model.c
src/surf/new_model_private.h [deleted file]
src/surf/storage.c
src/surf/storage.cpp [new file with mode: 0644]
src/surf/storage.hpp [new file with mode: 0644]
src/surf/storage_private.h [deleted file]
src/surf/surf.c
src/surf/surf.cpp [new file with mode: 0644]
src/surf/surf.hpp [new file with mode: 0644]
src/surf/surf_action.c
src/surf/surf_interface.cpp [new file with mode: 0644]
src/surf/surf_model.c [deleted file]
src/surf/surf_private.h
src/surf/surf_routing.cpp [moved from src/surf/surf_routing.c with 82% similarity]
src/surf/surf_routing.hpp [new file with mode: 0644]
src/surf/surf_routing_cluster.c [deleted file]
src/surf/surf_routing_cluster.cpp [new file with mode: 0644]
src/surf/surf_routing_cluster.hpp [new file with mode: 0644]
src/surf/surf_routing_dijkstra.cpp [moved from src/surf/surf_routing_dijkstra.c with 56% similarity]
src/surf/surf_routing_dijkstra.hpp [new file with mode: 0644]
src/surf/surf_routing_floyd.cpp [moved from src/surf/surf_routing_floyd.c with 54% similarity]
src/surf/surf_routing_floyd.hpp [new file with mode: 0644]
src/surf/surf_routing_full.cpp [moved from src/surf/surf_routing_full.c with 57% similarity]
src/surf/surf_routing_full.hpp [new file with mode: 0644]
src/surf/surf_routing_generic.cpp [moved from src/surf/surf_routing_generic.c with 57% similarity]
src/surf/surf_routing_generic.hpp [new file with mode: 0644]
src/surf/surf_routing_none.c [deleted file]
src/surf/surf_routing_none.cpp [new file with mode: 0644]
src/surf/surf_routing_none.hpp [new file with mode: 0644]
src/surf/surf_routing_private.hpp [moved from src/surf/surf_routing_private.h with 93% similarity]
src/surf/surf_routing_vivaldi.c [deleted file]
src/surf/surf_routing_vivaldi.cpp [new file with mode: 0644]
src/surf/surf_routing_vivaldi.hpp [new file with mode: 0644]
src/surf/surfxml_parse.c
src/surf/vm_workstation.c [new file with mode: 0644]
src/surf/vm_workstation_private.h [new file with mode: 0644]
src/surf/workstation.c
src/surf/workstation.cpp [new file with mode: 0644]
src/surf/workstation.hpp [new file with mode: 0644]
src/surf/workstation_private.h [new file with mode: 0644]
src/surf/workstation_ptask_L07.c
src/surf/workstation_ptask_L07.cpp [new file with mode: 0644]
src/surf/workstation_ptask_L07.hpp [new file with mode: 0644]
src/xbt/ex.c
src/xbt/lib.c
src/xbt/log.c
src/xbt/swag.c
teshsuite/simdag/platforms/flatifier.c
testsuite/surf/surf_usage.c
testsuite/surf/surf_usage2.c

index 2d167a8..70f5e1a 100644 (file)
--- a/.cproject
+++ b/.cproject
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?fileVersion 5.0.0?>
-
-<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage2">
+<?fileVersion 5.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage2">
        <storageModule moduleId="org.eclipse.cdt.core.settings">
-               <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1353180652">
-                       <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1353180652_org.eclipse.cdt.core.settings" id="cdt.managedbuild.toolchain.gnu.base.1353180652" name="Default"/>
-                       <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1353180652_cdtBuildSystem" version="4.0.0"/>
-                       <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1353180652_org.eclipse.cdt.core.externalSettings"/>
+               <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1053321950">
+                       <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1053321950_org.eclipse.cdt.core.settings" id="cdt.managedbuild.toolchain.gnu.base.1053321950" name="Default"/>
+                       <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1053321950_cdtBuildSystem" version="4.0.0"/>
+                       <storageModule externalCElementFile="cdt.managedbuild.toolchain.gnu.base.1053321950_org.eclipse.cdt.core.externalSettings"/>
                </cconfiguration>
        </storageModule>
-       <storageModule moduleId="org.eclipse.cdt.core.pathentry">
-               <pathentry kind="mac" name="main" path="" value="smpi_simulated_main"/>
-               <pathentry include="/usr/include/lua5.1" kind="inc" path="" system="true"/>
-               <pathentry include="/usr/include" kind="inc" path="" system="true"/>
-               <pathentry base-path="simgrid" include="include" kind="inc" path="" system="true"/>
-               <pathentry base-path="simgrid" include="src/include" kind="inc" path="" system="true"/>
-               <pathentry base-path="simgrid" include="src" kind="inc" path="" system="true"/>
-               <pathentry excluding="**/CMakeFiles/" kind="out" path=""/>
-               <pathentry kind="src" path=""/>
-       </storageModule>
        <storageModule moduleId="cdtBuildSystem" version="4.0.0">
-               <project id="simgrid.null.697056024" name="simgrid"/>
+               <project id="simgrid.null.1652888656" name="simgrid"/>
+       </storageModule>
+       <storageModule moduleId="scannerConfiguration">
+               <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
        </storageModule>
+       <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
        <storageModule moduleId="refreshScope" versionNumber="2">
                <configuration configurationName="Default">
                        <resource resourceType="PROJECT" workspacePath="/simgrid"/>
                </configuration>
        </storageModule>
-       <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
-       <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
-       <storageModule moduleId="scannerConfiguration">
-               <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
-               <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
-                       <buildOutputProvider>
-                               <openAction enabled="true" filePath=""/>
-                               <parser enabled="true"/>
-                       </buildOutputProvider>
-                       <scannerInfoProvider id="specsFile">
-                               <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="/usr/bin/gcc" useDefault="true"/>
-                               <parser enabled="true"/>
-                       </scannerInfoProvider>
-               </profile>
-               <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
-                       <buildOutputProvider>
-                               <openAction enabled="true" filePath=""/>
-                               <parser enabled="true"/>
-                       </buildOutputProvider>
-                       <scannerInfoProvider id="makefileGenerator">
-                               <runAction arguments="-f ${project_name}_scd.mk" command="/usr/bin/make" useDefault="true"/>
-                               <parser enabled="true"/>
-                       </scannerInfoProvider>
-               </profile>
-               <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1353180652;cdt.managedbuild.toolchain.gnu.base.1353180652.1797514135;cdt.managedbuild.tool.gnu.c.compiler.base.2037544368;cdt.managedbuild.tool.gnu.c.compiler.input.1851803849">
-                       <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
-                       <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
-                               <buildOutputProvider>
-                                       <openAction enabled="true" filePath=""/>
-                                       <parser enabled="true"/>
-                               </buildOutputProvider>
-                               <scannerInfoProvider id="specsFile">
-                                       <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="/usr/bin/gcc" useDefault="true"/>
-                                       <parser enabled="true"/>
-                               </scannerInfoProvider>
-                       </profile>
-                       <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
-                               <buildOutputProvider>
-                                       <openAction enabled="true" filePath=""/>
-                                       <parser enabled="true"/>
-                               </buildOutputProvider>
-                               <scannerInfoProvider id="makefileGenerator">
-                                       <runAction arguments="-f ${project_name}_scd.mk" command="/usr/bin/make" useDefault="true"/>
-                                       <parser enabled="true"/>
-                               </scannerInfoProvider>
-                       </profile>
-               </scannerConfigBuildInfo>
-               <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1353180652;cdt.managedbuild.toolchain.gnu.base.1353180652.1797514135;cdt.managedbuild.tool.gnu.cpp.compiler.base.1129818443;cdt.managedbuild.tool.gnu.cpp.compiler.input.500761747">
-                       <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
-                       <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
-                               <buildOutputProvider>
-                                       <openAction enabled="true" filePath=""/>
-                                       <parser enabled="true"/>
-                               </buildOutputProvider>
-                               <scannerInfoProvider id="specsFile">
-                                       <runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="/usr/bin/gcc" useDefault="true"/>
-                                       <parser enabled="true"/>
-                               </scannerInfoProvider>
-                       </profile>
-                       <profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
-                               <buildOutputProvider>
-                                       <openAction enabled="true" filePath=""/>
-                                       <parser enabled="true"/>
-                               </buildOutputProvider>
-                               <scannerInfoProvider id="makefileGenerator">
-                                       <runAction arguments="-f ${project_name}_scd.mk" command="/usr/bin/make" useDefault="true"/>
-                                       <parser enabled="true"/>
-                               </scannerInfoProvider>
-                       </profile>
-               </scannerConfigBuildInfo>
-       </storageModule>
 </cproject>
index d935a7a..a3b80ff 100644 (file)
--- a/.project
+++ b/.project
@@ -1,91 +1,27 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-  <name>simgrid</name>
-  <comment></comment>
-  <projects>
-  </projects>
-  <buildSpec>
-    <buildCommand>
-      <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
-      <triggers>clean,full,incremental,</triggers>
-      <arguments>
-        <dictionary>
-          <key>?name?</key>
-          <value></value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.append_environment</key>
-          <value>true</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.autoBuildTarget</key>
-          <value>all</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.buildArguments</key>
-          <value></value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.buildCommand</key>
-          <value>make</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
-          <value>clean</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.contents</key>
-          <value>org.eclipse.cdt.make.core.activeConfigSettings</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.enableAutoBuild</key>
-          <value>false</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.enableCleanBuild</key>
-          <value>true</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.enableFullBuild</key>
-          <value>true</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.fullBuildTarget</key>
-          <value>all</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.stopOnError</key>
-          <value>true</value>
-        </dictionary>
-        <dictionary>
-          <key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
-          <value>true</value>
-        </dictionary>
-      </arguments>
-    </buildCommand>
-    <buildCommand>
-      <name>org.rubypeople.rdt.core.rubybuilder</name>
-      <arguments>
-      </arguments>
-    </buildCommand>
-    <buildCommand>
-      <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
-      <triggers>full,incremental,</triggers>
-      <arguments>
-      </arguments>
-    </buildCommand>
-    <buildCommand>
-      <name>org.eclipse.jdt.core.javabuilder</name>
-      <arguments>
-      </arguments>
-    </buildCommand>
-  </buildSpec>
-  <natures>
-    <nature>org.eclipse.cdt.core.ccnature</nature>
-    <nature>org.eclipse.cdt.core.cnature</nature>
-    <nature>org.rubypeople.rdt.core.rubynature</nature>
-    <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
-    <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
-    <nature>org.eclipse.jdt.core.javanature</nature>
-  </natures>
+       <name>simgrid</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+                       <triggers>clean,full,incremental,</triggers>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+                       <triggers>full,incremental,</triggers>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.cdt.core.cnature</nature>
+               <nature>org.eclipse.cdt.core.ccnature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+       </natures>
 </projectDescription>
index a00593a..ff6cbe1 100644 (file)
@@ -7,6 +7,9 @@ project(SimGrid C)
 if (enable_gtnets OR enable_ns3)
   enable_language(CXX)
 endif()
+
+enable_language(CXX)
+
 if (NOT DEFINED enable_smpi OR enable_smpi) # smpi is enabled by default
   # Call enable_language(Fortran) in order to load the build rules for
   # this language, needed by teshsuite/smpi/mpich-test/.  Use
@@ -32,7 +35,7 @@ if (NOT DEFINED enable_smpi OR enable_smpi) # smpi is enabled by default
 endif()
 
 set(CMAKE_C_FLAGS "" CACHE TYPE INTERNAL FORCE)
-set(CMAKE_CXX_FLAGS "" CACHE TYPE INTERNAL FORCE)
+set(CMAKE_CXX_FLAGS " -std=c++11 " CACHE TYPE INTERNAL FORCE)
 set(CMAKE_EXE_LINKER_FLAGS "" CACHE TYPE INTERNAL FORCE)
 set(CMAKE_C_LINK_FLAGS "" CACHE TYPE INTERNAL FORCE)
 set(CMAKE_Fortran_FLAGS "" CACHE TYPE INTERNAL FORCE)
index 701ffe4..615ca4d 100644 (file)
@@ -35,20 +35,26 @@ set(EXTRA_DIST
   src/simix/smx_smurf_private.h
   src/simix/smx_synchro_private.h
   src/smpi/README
+  src/smpi/colls/COPYRIGHTS
   src/smpi/colls/colls.h
   src/smpi/colls/colls_private.h
   src/smpi/colls/coll_tuned_topo.h
   src/smpi/private.h
   src/smpi/smpi_mpi_dt_private.h
-  src/surf/cpu_cas01_private.h
+  src/surf/cpu.hpp
+  src/surf/cpu_ti.hpp
+  src/surf/cpu_cas01.hpp
   src/surf/cpu_ti_private.h
   src/surf/gtnets/gtnets_interface.h
   src/surf/gtnets/gtnets_simulator.h
   src/surf/gtnets/gtnets_topology.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_smpi.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
@@ -56,11 +62,24 @@ set(EXTRA_DIST
   src/surf/platf_generator_private.h
   src/surf/simgrid.dtd
   src/surf/simgrid_dtd.c
+  src/surf/storage.hpp
   src/surf/storage_private.h
+  src/surf/surf.hpp
   src/surf/surf_private.h
   src/surf/surf_routing_private.h
+  src/surf/surf_routing_private.hpp
+  src/surf/surf_routing.hpp
+  src/surf/surf_routing_cluster.hpp
+  src/surf/surf_routing_dijkstra.hpp
+  src/surf/surf_routing_floyd.hpp
+  src/surf/surf_routing_full.hpp
+  src/surf/surf_routing_generic.hpp
+  src/surf/surf_routing_none.hpp
+  src/surf/surf_routing_vivaldi.hpp
   src/surf/surfxml_parse.c
   src/surf/trace_mgr_private.h
+  src/surf/workstation.hpp
+  src/surf/workstation_ptask_L07.hpp
   src/win32/config.h
   src/xbt/automaton/automaton_lexer.yy.c
   src/xbt/automaton/parserPromela.lex
@@ -268,7 +287,7 @@ set(GTNETS_SRC
   src/surf/gtnets/gtnets_interface.cc
   src/surf/gtnets/gtnets_simulator.cc
   src/surf/gtnets/gtnets_topology.cc
-  src/surf/network_gtnets.c
+  src/surf/network_gtnets.cpp
   )
 
 set(NS3_SRC
@@ -280,35 +299,37 @@ set(NS3_SRC
   )
 
 set(SURF_SRC
-  src/surf/cpu_cas01.c
-  src/surf/cpu_ti.c
+  src/surf/cpu.cpp
+  src/surf/cpu_ti.cpp
+  src/surf/cpu_cas01.cpp
   src/surf/fair_bottleneck.c
   src/surf/instr_routing.c
   src/surf/instr_surf.c
   src/surf/lagrange.c
   src/surf/maxmin.c
-  src/surf/network.c
-  src/surf/network_constant.c
+  src/surf/network.cpp
+  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/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/storage.cpp
+  src/surf/surf.cpp
+  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/surf/vm_workstation.cpp
   src/xbt/xbt_sg_stubs.c
   )
 
@@ -326,6 +347,7 @@ set(SIMIX_SRC
   src/simix/smx_smurf.c
   src/simix/smx_synchro.c
   src/simix/smx_user.c
+  src/simix/smx_vm.c
   )
 
 set(SIMGRID_SRC
@@ -367,19 +389,6 @@ set(SIMIX_SRC
 )
 #* ****************************************************************************************** *#
 
-#* ****************************************************************************************** *#
-#* TUTORIAL: New Model                                                                        *#
-
-set(SURF_SRC
-  ${SURF_SRC}
-  src/surf/new_model.c
-  )
-set(EXTRA_DIST
-  ${EXTRA_DIST}
-  src/surf/new_model_private.h
-  )
-#* ****************************************************************************************** *#
-
 set(SIMDAG_SRC
   src/simdag/instr_sd_task.c
   src/simdag/sd_daxloader.c
index 058ea2d..9c37da3 100644 (file)
@@ -69,9 +69,10 @@ set(TESH_OPTION "")
 if(enable_coverage)
   find_program(GCOV_PATH gcov)
   if(GCOV_PATH)
-    SET(COVERAGE_COMMAND "${GCOV_PATH}" CACHE TYPE FILEPATH FORCE)
+    set(COVERAGE_COMMAND "${GCOV_PATH}" CACHE TYPE FILEPATH FORCE)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCOVERAGE")
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
     set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fprofile-arcs -ftest-coverage")
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
     set(TESH_OPTION --enable-coverage)
index 1101198..c2712b6 100644 (file)
@@ -372,14 +372,17 @@ router_name = prefix + clusterId + router_ + suffix;
 
 <b>cluster example</b>
 \verbatim
-<cluster id="my_cluster_1" prefix="" suffix=""
-               radical="0-262144"      power="1000000000"    bw="125000000"     lat="5E-5"/>
-<cluster id="my_cluster_1" prefix="c-" suffix=".me"
-               radical="0-99"  power="1000000000"    bw="125000000"     lat="5E-5"
-        bb_bw="2250000000" bb_lat="5E-4"/>
+<cluster id="my_cluster_1" prefix="" suffix="" radical="0-262144"
+         power="1e9" bw="125e6" lat="5E-5"/>
+
+<cluster id="my_cluster_1" prefix="c-" suffix=".me" radical="0-99"
+         power="1e9" bw="125e6" lat="5E-5"
+         bb_bw="2.25e9" bb_lat="5E-4"/>
 \endverbatim
-The second examples creates 100 machines, which names are the following:
+The second examples creates one router and 100 machines, which names 
+are the following:
 \verbatim
+c-my_cluster_1_router.me
 c-0.my_cluster_1.me
 c-1.my_cluster_1.me
 c-2.my_cluster_1.me
index 3e64460..333a905 100644 (file)
@@ -17,7 +17,7 @@ import org.simgrid.msg.MsgException;
 public class Cloud {
        public static final double task_comp_size = 10;
        public static final double task_comm_size = 10;
-
+       public static final int hostNB = 500 ; 
        public static void main(String[] args) throws MsgException {       
            Msg.init(args); 
            
@@ -28,15 +28,15 @@ public class Cloud {
            }
            /* Construct the platform */
                Msg.createEnvironment(args[0]);
-                 /* Retrieve the 10 first hosts of the platform file */
                Host[] hosts = Host.all();
-               if (hosts.length < 10) {
-                       Msg.info("I need at least 10 hosts in the platform file, but " + args[0] + " contains only " + hosts.length + " hosts");
+               if (hosts.length < hostNB+1) {
+                       Msg.info("I need at least "+ (hostNB+1) +"  hosts in the platform file, but " + args[0] + " contains only " + hosts.length + " hosts");
                        System.exit(42);
                }
+               Msg.info("Start"+ hostNB +"  hosts");
                new Master(hosts[0],"Master",hosts).start();
                /* Execute the simulation */
                Msg.run();
                
     }
-}
\ No newline at end of file
+}
index 8710bfb..1a2f095 100644 (file)
@@ -24,31 +24,36 @@ public class Master extends Process {
                this.hosts = hosts;
        }
        public void main(String[] args) throws MsgException {
-               int slavesCount = 10;
+               int slavesCount = Cloud.hostNB;
                
                ArrayList<VM> vms = new ArrayList<VM>();
                
+               // Create one VM per host and bind a process inside each one. 
                for (int i = 0; i < slavesCount; i++) {
-                       Slave slave = new Slave(hosts[i],i);
-                       slave.start();
-                       VM vm = new VM(hosts[i],hosts[i]+"_"+i,1);
-                       vm.bind(slave);
+                       Msg.info("create VM0"+i);       
+                       VM vm = new VM(hosts[i+1],"VM0"+i);
+                       vm.start();
                        vms.add(vm);
+                       Slave slave = new Slave(vm,i);
+                       Msg.info("Put Worker "+slave.msgName()+ " on "+vm.getName());
+                       slave.start();
+       
                }
                Msg.info("Launched " + vms.size() + " VMs");
                
                Msg.info("Send a first batch of work to everyone");
                workBatch(slavesCount);
                
-               Msg.info("Now suspend all VMs, just for fun");
+               Msg.info("Suspend all VMs");
                for (int i = 0; i < vms.size(); i++) {
+                       Msg.info("Suspend "+vms.get(i).getName());
                        vms.get(i).suspend();
                }
                
                Msg.info("Wait a while");
                waitFor(2);
                
-               Msg.info("Enough. Let's resume everybody.");
+               Msg.info("Resume all VMs.");
                for (int i = 0; i < vms.size(); i++) {
                        vms.get(i).resume();
                }
@@ -59,39 +64,44 @@ public class Master extends Process {
                Msg.info("Add one more process per VM.");
                for (int i = 0; i < vms.size(); i++) {
                        VM vm = vms.get(i);
-                       Slave slave = new Slave(hosts[i],i + vms.size());
+                       Slave slave = new Slave(vm,i + vms.size());
                        slave.start();
-                       vm.bind(slave);
                }
+       
+               workBatch(slavesCount * 2);
                
-               Msg.info("Migrate everyone to the second host.");
+               Msg.info("Migrate everyone to "+hosts[2].getName());
                for (int i = 0; i < vms.size(); i++) {
-                       vms.get(i).migrate(hosts[1]);
+                       vms.get(i).migrate(hosts[2]);
                }
                
-               Msg.info("Suspend everyone, move them to the third host, and resume them.");
+//             Msg.info("Suspend everyone, move them to the third host, and resume them.");
+               Msg.info("Migrate everyone to the third host (please note that cold migration is not yet available");
+               
+
                for (int i = 0; i < vms.size(); i++) {
                        VM vm = vms.get(i);
-                       vm.suspend();
-                       vm.migrate(hosts[2]);
-                       vm.resume();
+       //              vm.suspend();
+                       vm.migrate(hosts[3]);
+               //      vm.resume();
                }
                
-               workBatch(slavesCount * 2);
+       
                
                Msg.info("Let's shut down the simulation and kill everyone.");
                
                for (int i = 0; i < vms.size(); i++) {
                        vms.get(i).shutdown();
+                       vms.get(i).destroy();
                }                               
                Msg.info("Master done.");
        }
        
        public void workBatch(int slavesCount) throws MsgException {
                for (int i = 0; i < slavesCount; i++) {
-                       Task task = new Task("Task_" + i, Cloud.task_comp_size, Cloud.task_comm_size);
-                       Msg.info("Sending to " + i);
-                       task.send("slave_" + i);
+                       Task task = new Task("Task0" + i, Cloud.task_comp_size, Cloud.task_comm_size);
+                       Msg.info("Sending to WRK0" + i);
+                       task.send("MBOX:WRK0" + i);
                }
        }
 }
index 4d9963e..000d1d2 100644 (file)
@@ -16,15 +16,15 @@ import org.simgrid.msg.Task;
 public class Slave extends Process {
        private int number;
        public Slave(Host host, int number) {
-               super(host,"Slave " + number,null);
+               super(host,"WRK0" + number,null);
                this.number = number;
        }
        public void main(String[] args) throws MsgException {
+               Msg.info(this.msgName() +" is listenning on MBOX:WRK0"+ number);
                while(true) {                   
-                       Msg.info("Receiving on " + "slave_" + number);
                        Task task;
                         try {
-                                task = Task.receive("slave_"+number);
+                                task = Task.receive("MBOX:WRK0"+number);
                         } catch (MsgException e) {
                                 Msg.debug("Received failed. I'm done. See you!");
                                 break;
@@ -39,9 +39,9 @@ public class Slave extends Process {
                        } catch (MsgException e) {
 
                        }
-                       Msg.info("\"" + task.getName() + "\" done ");
+                       Msg.info(this.msgName() +" executed task (" + task.getName()+")");
                }
 
                
        }
-}
\ No newline at end of file
+}
index 534992d..60f12b8 100644 (file)
@@ -3,13 +3,19 @@ cmake_minimum_required(VERSION 2.6)
 set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")
 
 add_executable(masterslave_virtual_machines "masterslave_virtual_machines.c")
+add_executable(simple_vm "simple_vm.c")
+add_executable(migrate_vm "migrate_vm.c")
+add_executable(bound "bound.c")
+add_executable(scale "scale.c")
+add_executable(multicore "multicore.c")
 
 ### Add definitions for compile
-if(WIN32)
-  target_link_libraries(masterslave_virtual_machines simgrid )
-else()
-  target_link_libraries(masterslave_virtual_machines simgrid)
-endif()
+target_link_libraries(masterslave_virtual_machines simgrid)
+target_link_libraries(simple_vm simgrid)
+target_link_libraries(migrate_vm simgrid)
+target_link_libraries(bound simgrid)
+target_link_libraries(scale simgrid)
+target_link_libraries(multicore simgrid)
 
 set(tesh_files
   ${tesh_files}
@@ -19,11 +25,18 @@ set(tesh_files
 set(xml_files
   ${xml_files}
   ${CMAKE_CURRENT_SOURCE_DIR}/masterslave_virtual_machines.xml
+  ${CMAKE_CURRENT_SOURCE_DIR}/simple_plat.xml
+  ${CMAKE_CURRENT_SOURCE_DIR}/multicore_plat.xml
   PARENT_SCOPE
   )
 set(examples_src
   ${examples_src}
   ${CMAKE_CURRENT_SOURCE_DIR}/masterslave_virtual_machines.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/simple_vm.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/migrate_vm.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/bound.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/scale.c
+  ${CMAKE_CURRENT_SOURCE_DIR}/multicore.c
   PARENT_SCOPE
   )
 set(bin_files
diff --git a/examples/msg/cloud/bound.c b/examples/msg/cloud/bound.c
new file mode 100644 (file)
index 0000000..ec22eef
--- /dev/null
@@ -0,0 +1,380 @@
+/* Copyright (c) 2007-2013. 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 <stdio.h>
+#include "msg/msg.h"            /* Yeah! If you want to use msg, you need to include msg/msg.h */
+#include "xbt/sysdep.h"         /* calloc, printf */
+
+/* Create a log channel to have nice outputs. */
+#include "xbt/log.h"
+#include "xbt/asserts.h"
+XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,
+                             "Messages specific for this msg example");
+
+/** @addtogroup MSG_examples
+ *
+ * - <b>priority/priority.c</b>: Demonstrates the use of @ref
+ *   MSG_task_set_bound to change the computation priority of a
+ *   given task.
+ *
+ */
+
+static int worker_main(int argc, char *argv[])
+{
+  double computation_amount = atof(argv[1]);
+  int use_bound = atoi(argv[2]);
+  double bound = atof(argv[3]);
+
+  {
+    double clock_sta = MSG_get_clock();
+
+    msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL);
+    if (use_bound)
+      MSG_task_set_bound(task, bound);
+    MSG_task_execute(task);
+    MSG_task_destroy(task);
+
+    double clock_end = MSG_get_clock();
+    double duration = clock_end - clock_sta;
+    double flops_per_sec = computation_amount / duration;
+
+    if (use_bound)
+      XBT_INFO("bound to %f => duration %f (%f flops/s)", bound, duration, flops_per_sec);
+    else
+      XBT_INFO("not bound => duration %f (%f flops/s)", duration, flops_per_sec);
+  }
+
+  return 0;
+}
+
+static void launch_worker(msg_host_t host, const char *pr_name, double computation_amount, int use_bound, double bound)
+{
+  char **argv = xbt_new(char *, 5);
+  argv[0] = xbt_strdup(pr_name);
+  argv[1] = bprintf("%lf", computation_amount);
+  argv[2] = bprintf("%d", use_bound);
+  argv[3] = bprintf("%lf", bound);
+  argv[4] = NULL;
+
+  MSG_process_create_with_arguments(pr_name, worker_main, NULL, host, 4, argv);
+}
+
+
+
+static int worker_busy_loop_main(int argc, char *argv[])
+{
+  msg_task_t *task = MSG_process_get_data(MSG_process_self());
+  for (;;)
+    MSG_task_execute(*task);
+
+  return 0;
+}
+
+/* FIXME: */
+#define DOUBLE_MAX 100000000000L
+
+static void test_dynamic_change(void)
+{
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+
+  msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
+  msg_host_t vm1 = MSG_vm_create_core(pm0, "VM1");
+  MSG_vm_start(vm0);
+  MSG_vm_start(vm1);
+
+  msg_task_t task0 = MSG_task_create("Task0", DOUBLE_MAX, 0, NULL);
+  msg_task_t task1 = MSG_task_create("Task1", DOUBLE_MAX, 0, NULL);
+  msg_process_t pr0 = MSG_process_create("worker0", worker_busy_loop_main, &task0, vm0);
+  msg_process_t pr1 = MSG_process_create("worker1", worker_busy_loop_main, &task1, vm1);
+
+
+  double task0_remain_prev = MSG_task_get_remaining_computation(task0);
+  double task1_remain_prev = MSG_task_get_remaining_computation(task1);
+
+  {
+    const double cpu_speed = MSG_get_host_speed(pm0);
+    int i = 0;
+    for (i = 0; i < 10; i++) {
+      double new_bound = (cpu_speed / 10) * i;
+      XBT_INFO("set bound of VM1 to %f", new_bound);
+      MSG_vm_set_bound(vm1, new_bound);
+      MSG_process_sleep(100);
+
+      double task0_remain_now = MSG_task_get_remaining_computation(task0);
+      double task1_remain_now = MSG_task_get_remaining_computation(task1);
+
+      double task0_flops_per_sec = task0_remain_prev - task0_remain_now;
+      double task1_flops_per_sec = task1_remain_prev - task1_remain_now;
+
+      XBT_INFO("Task0@VM0: %f flops/s", task0_flops_per_sec / 100);
+      XBT_INFO("Task1@VM1: %f flops/s", task1_flops_per_sec / 100);
+
+      task0_remain_prev = task0_remain_now;
+      task1_remain_prev = task1_remain_now;
+    }
+  }
+
+  MSG_process_kill(pr0);
+  MSG_process_kill(pr1);
+  
+  MSG_vm_destroy(vm0);
+  MSG_vm_destroy(vm1);
+}
+
+
+
+static void test_one_task(msg_host_t hostA)
+{
+  const double cpu_speed = MSG_get_host_speed(hostA);
+  const double computation_amount = cpu_speed * 10;
+  const char *hostA_name = MSG_host_get_name(hostA);
+
+  XBT_INFO("### Test: with/without MSG_task_set_bound");
+
+#if 0
+  /* Easy-to-understand code (without calling MSG_task_set_bound) */
+  {
+    double clock_sta = MSG_get_clock();
+
+    msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL);
+    MSG_task_execute(task);
+    MSG_task_destroy(task);
+
+    double clock_end = MSG_get_clock();
+    double duration = clock_end - clock_sta;
+    double flops_per_sec = computation_amount / duration;
+
+    XBT_INFO("not bound => duration %f (%f flops/s)", duration, flops_per_sec);
+  }
+
+  /* Easy-to-understand code (with calling MSG_task_set_bound) */
+  {
+    double clock_sta = MSG_get_clock();
+
+    msg_task_t task = MSG_task_create("Task", computation_amount, 0, NULL);
+    MSG_task_set_bound(task, cpu_speed / 2);
+    MSG_task_execute(task);
+    MSG_task_destroy(task);
+
+    double clock_end = MSG_get_clock();
+    double duration = clock_end - clock_sta;
+    double flops_per_sec = computation_amount / duration;
+
+    XBT_INFO("bound to 0.5 => duration %f (%f flops/s)", duration, flops_per_sec);
+  }
+#endif
+
+  {
+    XBT_INFO("### Test: no bound for Task1@%s", hostA_name);
+    launch_worker(hostA, "worker0", computation_amount, 0, 0);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: 50%% for Task1@%s", hostA_name);
+    launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: 33%% for Task1@%s", hostA_name);
+    launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 3);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: zero for Task1@%s (i.e., unlimited)", hostA_name);
+    launch_worker(hostA, "worker0", computation_amount, 1, 0);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: 200%% for Task1@%s (i.e., meaningless)", hostA_name);
+    launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 2);
+  }
+
+  MSG_process_sleep(1000);
+}
+
+
+static void test_two_tasks(msg_host_t hostA, msg_host_t hostB)
+{
+  const double cpu_speed = MSG_get_host_speed(hostA);
+  xbt_assert(cpu_speed == MSG_get_host_speed(hostB));
+  const double computation_amount = cpu_speed * 10;
+  const char *hostA_name = MSG_host_get_name(hostA);
+  const char *hostB_name = MSG_host_get_name(hostB);
+
+  {
+    XBT_INFO("### Test: no bound for Task1@%s, no bound for Task2@%s", hostA_name, hostB_name);
+    launch_worker(hostA, "worker0", computation_amount, 0, 0);
+    launch_worker(hostB, "worker1", computation_amount, 0, 0);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: 0 for Task1@%s, 0 for Task2@%s (i.e., unlimited)", hostA_name, hostB_name);
+    launch_worker(hostA, "worker0", computation_amount, 1, 0);
+    launch_worker(hostB, "worker1", computation_amount, 1, 0);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: 50%% for Task1@%s, 50%% for Task2@%s", hostA_name, hostB_name);
+    launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 2);
+    launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 2);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: 25%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
+    launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed / 4);
+    launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: 75%% for Task1@%s, 100%% for Task2@%s", hostA_name, hostB_name);
+    launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
+    launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: no bound for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
+    launch_worker(hostA, "worker0", computation_amount, 0, 0);
+    launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
+  }
+
+  MSG_process_sleep(1000);
+
+  {
+    XBT_INFO("### Test: 75%% for Task1@%s, 25%% for Task2@%s", hostA_name, hostB_name);
+    launch_worker(hostA, "worker0", computation_amount, 1, cpu_speed * 0.75);
+    launch_worker(hostB, "worker1", computation_amount, 1, cpu_speed / 4);
+  }
+
+  MSG_process_sleep(1000);
+}
+
+static int master_main(int argc, char *argv[])
+{
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+
+
+  {
+    XBT_INFO("# 1. Put a single task on a PM. ");
+    test_one_task(pm0);
+    XBT_INFO(" ");
+
+
+    XBT_INFO("# 2. Put two tasks on a PM.");
+    test_two_tasks(pm0, pm0);
+    XBT_INFO(" ");
+  }
+
+
+  {
+    msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
+    MSG_vm_start(vm0);
+
+    XBT_INFO("# 3. Put a single task on a VM. ");
+    test_one_task(vm0);
+    XBT_INFO(" ");
+
+    XBT_INFO("# 4. Put two tasks on a VM.");
+    test_two_tasks(vm0, vm0);
+    XBT_INFO(" ");
+
+
+    MSG_vm_destroy(vm0);
+  }
+
+
+  {
+    msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
+    MSG_vm_start(vm0);
+
+    XBT_INFO("# 6. Put a task on a PM and a task on a VM.");
+    test_two_tasks(pm0, vm0);
+    XBT_INFO(" ");
+
+
+    MSG_vm_destroy(vm0);
+  }
+
+
+  {
+    msg_host_t vm0 = MSG_vm_create_core(pm0, "VM0");
+    const double cpu_speed = MSG_get_host_speed(pm0);
+    MSG_vm_set_bound(vm0, cpu_speed / 10);
+    MSG_vm_start(vm0);
+
+    XBT_INFO("# 7. Put a single task on the VM capped by 10%%.");
+    test_one_task(vm0);
+    XBT_INFO(" ");
+
+    XBT_INFO("# 8. Put two tasks on the VM capped by 10%%.");
+    test_two_tasks(vm0, vm0);
+    XBT_INFO(" ");
+
+    XBT_INFO("# 9. Put a task on a PM and a task on the VM capped by 10%%.");
+    test_two_tasks(pm0, vm0);
+    XBT_INFO(" ");
+
+    MSG_vm_destroy(vm0);
+  }
+
+
+  XBT_INFO("# 10. Change a bound dynamically.");
+  test_dynamic_change();
+
+  return 0;
+}
+
+static void launch_master(msg_host_t host)
+{
+  const char *pr_name = "master_";
+  char **argv = xbt_new(char *, 2);
+  argv[0] = xbt_strdup(pr_name);
+  argv[1] = NULL;
+
+  MSG_process_create_with_arguments(pr_name, master_main, NULL, host, 1, argv);
+}
+
+int main(int argc, char *argv[])
+{
+  /* Get the arguments */
+  MSG_init(&argc, argv);
+
+  /* load the platform file */
+  if (argc != 2) {
+    printf("Usage: %s example/msg/cloud/simple_plat.xml\n", argv[0]);
+    return 1;
+  }
+
+  MSG_create_environment(argv[1]);
+
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+  launch_master(pm0);
+
+  int res = MSG_main();
+  XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
+
+
+  return !(res == MSG_OK);
+}
index 33513a0..5725935 100644 (file)
@@ -5,7 +5,7 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include <stdio.h>
-#include "msg/msg.h"            /* Yeah! If you want to use msg, you need to include msg/msg.h */
+#include "msg/msg.h"
 #include "xbt/sysdep.h"         /* calloc, printf */
 
 /* Create a log channel to have nice outputs. */
@@ -16,217 +16,246 @@ XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,
 
 /** @addtogroup MSG_examples
  * 
- *  - <b>cloud/masterslave_virtual_machines.c: Master/slaves
- *    example, à la cloud</b>. The classical example revisited to demonstrate the use of virtual machines.
+ *  - <b>cloud/masterslave_virtual_machines.c: Master/workers
+ *    example on a cloud</b>. The classical example revisited to demonstrate the use of virtual machines.
  */
 
-double task_comp_size = 10000000;
-double task_comm_size = 10000000;
+const double task_comp_size = 10000000;
+const double task_comm_size = 10000000;
 
 
-int master(int argc, char *argv[]);
-int slave_fun(int argc, char *argv[]);
+int master_fun(int argc, char *argv[]);
+int worker_fun(int argc, char *argv[]);
 
-static void work_batch(int slaves_count) {
+
+static void work_batch(int workers_count)
+{
   int i;
-  for (i = 0; i < slaves_count; i++) {
-    char taskname_buffer[64];
-    char mailbox_buffer[64];
+  for (i = 0; i < workers_count; i++) {
+    char *tname = bprintf("Task%02d", i);
+    char *mbox =  bprintf("MBOX:WRK%02d", i);
+
+    msg_task_t task = MSG_task_create(tname, task_comp_size, task_comm_size, NULL);
 
-    sprintf(taskname_buffer, "Task_%d", i);
-    sprintf(mailbox_buffer,"Slave_%d",i);
+    XBT_INFO("send task(%s) to mailbox(%s)", tname, mbox);
+    MSG_task_send(task, mbox);
 
-    XBT_INFO("Sending \"%s\" to \"%s\"",taskname_buffer,mailbox_buffer);
-    MSG_task_send(MSG_task_create(taskname_buffer, task_comp_size, task_comm_size,NULL),
-        mailbox_buffer);
+    free(tname);
+    free(mbox);
   }
 }
 
-int master(int argc, char *argv[]) {
-  int slaves_count = 10;
-  msg_host_t *slaves = xbt_new(msg_host_t,10);
-
+int master_fun(int argc, char *argv[])
+{
   msg_vm_t vm;
   unsigned int i;
+  int workers_count = argc - 1;
 
-  /* Retrive the hostnames constituting our playground today */
-  for (i = 1; i < argc; i++) {
-    slaves[i - 1] = MSG_get_host_by_name(argv[i]);
-    xbt_assert(slaves[i - 1] != NULL, "Cannot use inexistent host %s", argv[i]);
-  }
+  msg_host_t *pms = xbt_new(msg_host_t, workers_count);
+  xbt_dynar_t vms = xbt_dynar_new(sizeof(msg_vm_t), NULL);
 
-  /* Launch the sub processes: one VM per host, with one process inside each */
+  /* Retrieve the PMs that will launch worker processes. */
+  for (i = 1; i < argc; i++)
+    pms[i - 1] = MSG_get_host_by_name(argv[i]);
 
-  for (i=0;i<slaves_count;i++) {
-    char slavename[64];
-    sprintf(slavename,"Slave %d",i);
-    char**argv=xbt_new(char*,3);
-    argv[0] = xbt_strdup(slavename);
-    argv[1] = bprintf("%d",i);
-    argv[2] = NULL;
 
-    char vmName[64];
-    snprintf(vmName, 64, "vm_%d", i);
+  /* Launch VMs and worker processes. One VM per PM, and one worker process per VM. */
 
-    msg_vm_t vm = MSG_vm_start(slaves[i],vmName,2);
-    MSG_vm_bind(vm, MSG_process_create_with_arguments(slavename,slave_fun,NULL,slaves[i],2,argv));
-  }
+  XBT_INFO("Launch %d VMs", workers_count);
+  for (i=0; i< workers_count; i++) {
+    char *vm_name = bprintf("VM%02d", i);
+    char *pr_name = bprintf("WRK%02d", i);
+    char *mbox = bprintf("MBOX:WRK%02d", i);
 
+    char **wrk_argv = xbt_new(char*, 3);
+    wrk_argv[0] = pr_name;
+    wrk_argv[1] = mbox;
+    wrk_argv[2] = NULL;
 
-  xbt_dynar_t vms = MSG_vms_as_dynar();
-  XBT_INFO("Launched %ld VMs", xbt_dynar_length(vms));
+    XBT_INFO("create %s", vm_name);
+    msg_vm_t vm = MSG_vm_create_core(pms[i], vm_name);
+
+    s_ws_params_t params;
+    memset(&params, 0, sizeof(params));
+    params.ramsize = 1L * 1024 * 1024 * 1024; // 1Gbytes
+    MSG_host_set_params(vm, &params);
+
+    MSG_vm_start(vm);
+    xbt_dynar_push(vms, &vm);
+
+    XBT_INFO("put %s on %s", pr_name, vm_name);
+    MSG_process_create_with_arguments(pr_name, worker_fun, NULL, vm, 2, wrk_argv);
+  }
 
-  /* Send a bunch of work to every one */
-  XBT_INFO("Send a first batch of work to every one");
-  work_batch(slaves_count);
 
-  XBT_INFO("Now suspend all VMs, just for fun");
+  /* Send a bunch of work to every one */
+  XBT_INFO("Send a task to %d worker process", workers_count);
+  work_batch(workers_count);
 
-  xbt_dynar_foreach(vms,i,vm) {
+  XBT_INFO("Suspend all VMs");
+  xbt_dynar_foreach(vms, i, vm) {
+    const char *vm_name = MSG_host_get_name(vm);
+    XBT_INFO("suspend %s", vm_name);
     MSG_vm_suspend(vm);
   }
 
   XBT_INFO("Wait a while");
   MSG_process_sleep(2);
 
-  XBT_INFO("Enough. Let's resume everybody.");
-  xbt_dynar_foreach(vms,i,vm) {
+  XBT_INFO("Resume all VMs");
+  xbt_dynar_foreach(vms, i, vm) {
     MSG_vm_resume(vm);
   }
+
+
   XBT_INFO("Sleep long enough for everyone to be done with previous batch of work");
-  MSG_process_sleep(1000-MSG_get_clock());
+  MSG_process_sleep(1000 - MSG_get_clock());
 
   XBT_INFO("Add one more process per VM");
-  xbt_dynar_foreach(vms,i,vm) {
-    msg_vm_t vm = xbt_dynar_get_as(vms,i,msg_vm_t);
-    char slavename[64];
-    sprintf(slavename,"Slave %ld",i+xbt_dynar_length(vms));
-    char**argv=xbt_new(char*,3);
-    argv[0] = xbt_strdup(slavename);
-    argv[1] = bprintf("%ld",i+xbt_dynar_length(vms));
-    argv[2] = NULL;
-    MSG_vm_bind(vm, MSG_process_create_with_arguments(slavename,slave_fun,NULL,slaves[i],2,argv));
+  xbt_dynar_foreach(vms, i, vm) {
+    unsigned int index = i + xbt_dynar_length(vms);
+    char *vm_name = bprintf("VM%02d", i);
+    char *pr_name = bprintf("WRK%02d", index);
+    char *mbox = bprintf("MBOX:WRK%02d", index);
+
+    char **wrk_argv = xbt_new(char*, 3);
+    wrk_argv[0] = pr_name;
+    wrk_argv[1] = mbox;
+    wrk_argv[2] = NULL;
+
+    XBT_INFO("put %s on %s", pr_name, vm_name);
+    MSG_process_create_with_arguments(pr_name, worker_fun, NULL, vm, 2, wrk_argv);
   }
 
-  XBT_INFO("Reboot all the VMs");
-  xbt_dynar_foreach(vms,i,vm) {
-    MSG_vm_reboot(vm);
-  }
-
-  work_batch(slaves_count*2);
+  XBT_INFO("Send a task to %d worker process", workers_count * 2);
+  work_batch(workers_count * 2);
 
-  XBT_INFO("Migrate everyone to the second host.");
-  xbt_dynar_foreach(vms,i,vm) {
-    MSG_vm_migrate(vm,slaves[1]);
+  XBT_INFO("Migrate all VMs to PM(%s)", MSG_host_get_name(pms[1]));
+  xbt_dynar_foreach(vms, i, vm) {
+    MSG_vm_migrate(vm, pms[1]);
   }
-  XBT_INFO("Suspend everyone, move them to the third host, and resume them.");
-  xbt_dynar_foreach(vms,i,vm) {
-    MSG_vm_suspend(vm);
-    MSG_vm_migrate(vm,slaves[2]);
-    MSG_vm_resume(vm);
+
+  /* Migration with default policy is called (i.e. live migration with pre-copy strategy) */
+  /* If you want to use other policy such as post-copy or cold migration, you should add a third parameter that defines the policy */
+  XBT_INFO("Migrate all VMs to PM(%s)", MSG_host_get_name(pms[2]));
+  xbt_dynar_foreach(vms, i, vm) {
+    // MSG_vm_suspend(vm);
+    MSG_vm_migrate(vm, pms[2]);
+    // MSG_vm_resume(vm);
   }
 
 
-  XBT_INFO("Let's shut down the simulation. 10 first processes will be shut down cleanly while the second half will forcefully get killed");
-  for (i = 0; i < slaves_count; i++) {
-    char mailbox_buffer[64];
-    sprintf(mailbox_buffer,"Slave_%d",i);
+  XBT_INFO("Shutdown the half of worker processes gracefuly. The remaining half will be forcibly killed");
+  for (i = 0; i < workers_count; i++) {
+    char mbox[64];
+    sprintf(mbox, "MBOX:WRK%02d", i);
     msg_task_t finalize = MSG_task_create("finalize", 0, 0, 0);
-    MSG_task_send(finalize, mailbox_buffer);
+    MSG_task_send(finalize, mbox);
   }
 
   XBT_INFO("Wait a while before effective shutdown.");
   MSG_process_sleep(2);
 
-  xbt_dynar_foreach(vms,i,vm) {
+
+  XBT_INFO("Shutdown and destroy all the VMs. The remaining worker processes will be forcibly killed.");
+  xbt_dynar_foreach(vms, i, vm) {
+    XBT_INFO("shutdown %s", MSG_host_get_name(vm));
     MSG_vm_shutdown(vm);
+    XBT_INFO("destroy %s", MSG_host_get_name(vm));
     MSG_vm_destroy(vm);
   }
 
   XBT_INFO("Goodbye now!");
-  free(slaves);
+  free(pms);
   xbt_dynar_free(&vms);
+
   return 0;
-}                               /* end_of_master */
+}
 
 /** Receiver function  */
-int slave_fun(int argc, char *argv[])
+int worker_fun(int argc, char *argv[])
 {
-  char mailbox_name[128];
-  msg_task_t task = NULL;
-  _XBT_GNUC_UNUSED int res;
-  /* since the slaves will move around, use slave_%d as mailbox names instead of hostnames */
-  xbt_assert(argc>=2, "slave processes need to be given their rank as parameter");
-  sprintf(mailbox_name,"Slave_%s",argv[1]);
-  XBT_INFO("Slave listenning on %s",argv[1]);
-  while (1) {
-    res = MSG_task_receive(&(task),mailbox_name);
-    xbt_assert(res == MSG_OK, "MSG_task_get failed");
-
-    XBT_INFO("Received \"%s\" from mailbox %s", MSG_task_get_name(task),mailbox_name);
+  xbt_assert(argc == 2, "need mbox in arguments");
+
+  char *mbox = argv[1];
+  const char *pr_name = MSG_process_get_name(MSG_process_self());
+  XBT_INFO("%s is listenning on mailbox(%s)", pr_name, mbox);
+
+  for (;;) {
+    msg_task_t task = NULL;
+
+    msg_error_t res = MSG_task_receive(&task, mbox);
+    if (res != MSG_OK) {
+      XBT_CRITICAL("MSG_task_get failed");
+      DIE_IMPOSSIBLE;
+    }
+
+    XBT_INFO("%s received task(%s) from mailbox(%s)",
+        pr_name, MSG_task_get_name(task), mbox);
+
     if (!strcmp(MSG_task_get_name(task), "finalize")) {
       MSG_task_destroy(task);
       break;
     }
 
     MSG_task_execute(task);
-    XBT_INFO("\"%s\" done", MSG_task_get_name(task));
+    XBT_INFO("%s executed task(%s)", pr_name, MSG_task_get_name(task));
     MSG_task_destroy(task);
-    task = NULL;
   }
 
   return 0;
-}                               /* end_of_slave */
+}
+
 
 /** Main function */
 int main(int argc, char *argv[])
 {
-  msg_error_t res = MSG_OK;
-  xbt_dynar_t hosts_dynar;
-  msg_host_t*hosts= xbt_new(msg_host_t,10);
-  char**hostnames= xbt_new(char*,10);
-  char**masterargv=xbt_new(char*,12);
-  int i;
+  const int nb_hosts = 3;
 
-  /* Get the arguments */
   MSG_init(&argc, argv);
-  if (argc < 2) {
-    printf("Usage: %s platform_file\n", argv[0]);
-    printf("example: %s msg_platform.xml\n", argv[0]);
-    exit(1);
-  } if (argc>2) {
-    printf("Usage: %s platform_file\n", argv[0]);
-    printf("Other parameters (such as the deployment file) are ignored.");
+  if (argc != 2) {
+    printf("Usage: %s example/msg/msg_platform.xml\n", argv[0]);
+    return 1;
   }
 
-  /* load the platform file */
+  /* Load the platform file */
   MSG_create_environment(argv[1]);
-  /* Retrieve the 10 first hosts of the platform file */
-  hosts_dynar = MSG_hosts_as_dynar();
-  xbt_assert(xbt_dynar_length(hosts_dynar)>10,
-      "I need at least 10 hosts in the platform file, but %s contains only %ld hosts_dynar.",
-      argv[1],xbt_dynar_length(hosts_dynar));
-  for (i=0;i<10;i++) {
-    hosts[i] = xbt_dynar_get_as(hosts_dynar,i,msg_host_t);
-    hostnames[i] = xbt_strdup(MSG_host_get_name(hosts[i]));
+
+  /* Retrieve hosts from the platform file */
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+
+  if (xbt_dynar_length(hosts_dynar) <= nb_hosts) {
+    XBT_CRITICAL("need %d hosts", nb_hosts);
+    return 1;
   }
-  masterargv[0]=xbt_strdup("master");
-  for (i=1;i<11;i++) {
-    masterargv[i] = xbt_strdup(MSG_host_get_name(hosts[i-1]));
+
+  msg_host_t master_pm = NULL;
+  char **master_argv = xbt_new(char *, 12);
+  master_argv[0] = xbt_strdup("master");
+  master_argv[11] = NULL;
+
+  unsigned int i;
+  msg_host_t host;
+  xbt_dynar_foreach(hosts_dynar, i, host) {
+    if (i == 0) {
+      master_pm = host;
+      continue;
+    }
+
+    master_argv[i] = xbt_strdup(MSG_host_get_name(host));
+
+    if (i == nb_hosts)
+      break;
+  }
+
+  msg_error_t res = 1;
+  if (master_pm!=NULL){
+    MSG_process_create_with_arguments("master", master_fun, NULL, master_pm, nb_hosts + 1, master_argv);
+
+    res = MSG_main();
+    XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
   }
-  masterargv[11]=NULL;
-  MSG_process_create_with_arguments("master",master,NULL,hosts[0],11,masterargv);
-  res = MSG_main();
-  XBT_INFO("Simulation time %g", MSG_get_clock());
-
-  free(hosts);
-  for (i=0;i<10;i++) 
-     free(hostnames[i]);
-  free(hostnames);
   xbt_dynar_free(&hosts_dynar);
 
-  if (res == MSG_OK)
-    return 0;
-  else
-    return 1;
-}                               /* end_of_main */
+  return !(res == MSG_OK);
+}
diff --git a/examples/msg/cloud/migrate_vm.c b/examples/msg/cloud/migrate_vm.c
new file mode 100644 (file)
index 0000000..46a8725
--- /dev/null
@@ -0,0 +1,163 @@
+/* Copyright (c) 2007-2012. 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 <stdio.h>
+#include "msg/msg.h"
+#include "xbt/sysdep.h"         /* calloc, printf */
+
+/* Create a log channel to have nice outputs. */
+#include "xbt/log.h"
+#include "xbt/asserts.h"
+XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,
+                             "Messages specific for this msg example");
+
+
+static void vm_migrate(msg_vm_t vm, msg_host_t dst_pm)
+{
+  msg_host_t src_pm = MSG_vm_get_pm(vm);
+  double mig_sta = MSG_get_clock();
+  MSG_vm_migrate(vm, dst_pm);
+  double mig_end = MSG_get_clock();
+
+  XBT_INFO("%s migrated: %s->%s in %g s", MSG_vm_get_name(vm),
+                 MSG_host_get_name(src_pm), MSG_host_get_name(dst_pm),
+                 mig_end - mig_sta);
+}
+
+static int migration_worker_main(int argc, char *argv[])
+{
+  xbt_assert(argc == 3);
+  char *vm_name = argv[1];
+  char *dst_pm_name = argv[2];
+
+  msg_vm_t vm = MSG_get_host_by_name(vm_name);
+  msg_host_t dst_pm = MSG_get_host_by_name(dst_pm_name);
+
+  vm_migrate(vm, dst_pm);
+
+  return 0;
+}
+
+static void vm_migrate_async(msg_vm_t vm, msg_host_t dst_pm)
+{
+  const char *vm_name = MSG_vm_get_name(vm);
+  const char *dst_pm_name = MSG_host_get_name(dst_pm);
+  msg_host_t host = MSG_host_self();
+
+  const char *pr_name = "mig_wrk";
+  char **argv = xbt_new(char *, 4);
+  argv[0] = xbt_strdup(pr_name);
+  argv[1] = xbt_strdup(vm_name);
+  argv[2] = xbt_strdup(dst_pm_name);
+  argv[3] = NULL;
+
+  MSG_process_create_with_arguments(pr_name, migration_worker_main, NULL, host, 3, argv);
+}
+
+static int master_main(int argc, char *argv[])
+{
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+  msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t);
+  msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t);
+  msg_vm_t vm0, vm1;
+  s_ws_params_t params;
+  memset(&params, 0, sizeof(params));
+
+
+
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  params.ramsize = 1L * 1000 * 1000 * 1000; // 1Gbytes
+  MSG_host_set_params(vm0, &params);
+  MSG_vm_start(vm0);
+
+  XBT_INFO("Test: Migrate a VM with %ld Mbytes RAM", params.ramsize / 1000 / 1000);
+  vm_migrate(vm0, pm1);
+
+  MSG_vm_destroy(vm0);
+
+
+
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  params.ramsize = 1L * 1000 * 1000 * 100; // 100Mbytes
+  MSG_host_set_params(vm0, &params);
+  MSG_vm_start(vm0);
+
+  XBT_INFO("Test: Migrate a VM with %ld Mbytes RAM", params.ramsize / 1000 / 1000);
+  vm_migrate(vm0, pm1);
+
+  MSG_vm_destroy(vm0);
+
+
+
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  vm1 = MSG_vm_create_core(pm0, "VM1");
+
+  params.ramsize = 1L * 1000 * 1000 * 1000; // 1Gbytes
+  MSG_host_set_params(vm0, &params);
+  MSG_host_set_params(vm1, &params);
+  MSG_vm_start(vm0);
+  MSG_vm_start(vm1);
+
+  XBT_INFO("Test: Migrate two VMs at once from PM0 to PM1");
+  vm_migrate_async(vm0, pm1);
+  vm_migrate_async(vm1, pm1);
+  MSG_process_sleep(10000);
+
+  MSG_vm_destroy(vm0);
+  MSG_vm_destroy(vm1);
+
+
+
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  vm1 = MSG_vm_create_core(pm0, "VM1");
+
+  params.ramsize = 1L * 1000 * 1000 * 1000; // 1Gbytes
+  MSG_host_set_params(vm0, &params);
+  MSG_host_set_params(vm1, &params);
+  MSG_vm_start(vm0);
+  MSG_vm_start(vm1);
+
+  XBT_INFO("Test: Migrate two VMs at once to different PMs");
+  vm_migrate_async(vm0, pm1);
+  vm_migrate_async(vm1, pm2);
+  MSG_process_sleep(10000);
+
+  MSG_vm_destroy(vm0);
+  MSG_vm_destroy(vm1);
+
+
+  return 0;
+}
+
+static void launch_master(msg_host_t host)
+{
+  const char *pr_name = "master_";
+  char **argv = xbt_new(char *, 2);
+  argv[0] = xbt_strdup(pr_name);
+  argv[1] = NULL;
+
+  MSG_process_create_with_arguments(pr_name, master_main, NULL, host, 1, argv);
+}
+
+
+int main(int argc, char *argv[])
+{
+  /* Get the arguments */
+  MSG_init(&argc, argv);
+
+  /* load the platform file */
+  MSG_create_environment(argv[1]);
+
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+  launch_master(pm0);
+
+  int res = MSG_main();
+  XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
+
+
+  return !(res == MSG_OK);
+}
diff --git a/examples/msg/cloud/multicore.c b/examples/msg/cloud/multicore.c
new file mode 100644 (file)
index 0000000..1247695
--- /dev/null
@@ -0,0 +1,388 @@
+/* Copyright (c) 2007-2013. 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 <stdio.h>
+#include "msg/msg.h"
+#include "xbt/sysdep.h"         /* calloc, printf */
+
+/* Create a log channel to have nice outputs. */
+#include "xbt/log.h"
+#include "xbt/asserts.h"
+XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test, "Messages specific for this msg example");
+
+
+
+
+
+static int worker_main(int argc, char *argv[])
+{
+  msg_task_t task = MSG_process_get_data(MSG_process_self());
+  MSG_task_execute(task);
+
+  XBT_INFO("task %p bye", task);
+
+  return 0;
+}
+
+
+struct task_data {
+       msg_task_t task;
+       double prev_computation_amount;
+       double prev_clock;
+};
+
+
+static void task_data_init_clock(struct task_data *t)
+{
+  t->prev_computation_amount = MSG_task_get_remaining_computation(t->task);
+  t->prev_clock = MSG_get_clock();
+}
+
+
+static void task_data_get_clock(struct task_data *t)
+{
+  double now_computation_amount = MSG_task_get_remaining_computation(t->task);
+  double now_clock = MSG_get_clock();
+
+  double done = t->prev_computation_amount - now_computation_amount;
+  double duration = now_clock - t->prev_clock;
+
+  XBT_INFO("%s: %f fops/s", MSG_task_get_name(t->task), done / duration);
+
+  t->prev_computation_amount = now_computation_amount;
+  t->prev_clock = now_clock;
+}
+
+
+static void test_pm_pin(void)
+{
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+  msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t);
+  msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t);
+
+
+  struct task_data t1;
+  struct task_data t2;
+  struct task_data t3;
+  struct task_data t4;
+
+  t1.task = MSG_task_create("Task1", 10000000000000000UL, 0, NULL);
+  t2.task = MSG_task_create("Task2", 10000000000000000UL, 0, NULL);
+  t3.task = MSG_task_create("Task3", 10000000000000000UL, 0, NULL);
+  t4.task = MSG_task_create("Task4", 10000000000000000UL, 0, NULL);
+
+  MSG_process_create("worker1", worker_main, t1.task, pm1);
+  MSG_process_create("worker2", worker_main, t2.task, pm1);
+  MSG_process_create("worker3", worker_main, t3.task, pm1);
+  MSG_process_create("worker4", worker_main, t4.task, pm1);
+
+
+  XBT_INFO("## 1. start 4 tasks on PM1 (2 cores)");
+  task_data_init_clock(&t1);
+  task_data_init_clock(&t2);
+  task_data_init_clock(&t3);
+  task_data_init_clock(&t4);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+  task_data_get_clock(&t4);
+
+
+  XBT_INFO("## 2. pin all tasks to CPU0");
+  MSG_task_set_affinity(t1.task, pm1, 0x01);
+  MSG_task_set_affinity(t2.task, pm1, 0x01);
+  MSG_task_set_affinity(t3.task, pm1, 0x01);
+  MSG_task_set_affinity(t4.task, pm1, 0x01);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+  task_data_get_clock(&t4);
+
+
+  XBT_INFO("## 3. clear the affinity of task4");
+  MSG_task_set_affinity(t4.task, pm1, 0);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+  task_data_get_clock(&t4);
+
+
+  XBT_INFO("## 4. clear the affinity of task3");
+  MSG_task_set_affinity(t3.task, pm1, 0);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+  task_data_get_clock(&t4);
+
+
+  XBT_INFO("## 5. clear the affinity of task2");
+  MSG_task_set_affinity(t2.task, pm1, 0);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+  task_data_get_clock(&t4);
+
+
+  XBT_INFO("## 6. pin all tasks to CPU0 of another PM (no effect now)");
+  MSG_task_set_affinity(t1.task, pm0, 0);
+  MSG_task_set_affinity(t2.task, pm0, 0);
+  MSG_task_set_affinity(t3.task, pm2, 0);
+  MSG_task_set_affinity(t4.task, pm2, 0);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+  task_data_get_clock(&t4);
+
+
+
+  MSG_task_cancel(t1.task);
+  MSG_task_cancel(t2.task);
+  MSG_task_cancel(t3.task);
+  MSG_task_cancel(t4.task);
+  MSG_process_sleep(10);
+  MSG_task_destroy(t1.task);
+  MSG_task_destroy(t2.task);
+  MSG_task_destroy(t3.task);
+  MSG_task_destroy(t4.task);
+}
+
+
+static void test_vm_pin(void)
+{
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t); // 1 cores
+  msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t); // 2 cores
+  msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t); // 4 cores
+
+
+  /* set up VMs on PM2 (4 cores) */
+  msg_vm_t vm0 = MSG_vm_create_core(pm2, "VM0");
+  msg_vm_t vm1 = MSG_vm_create_core(pm2, "VM1");
+  msg_vm_t vm2 = MSG_vm_create_core(pm2, "VM2");
+  msg_vm_t vm3 = MSG_vm_create_core(pm2, "VM3");
+
+  s_ws_params_t params;
+  memset(&params, 0, sizeof(params));
+  params.ramsize = 1L * 1024 * 1024;
+  params.skip_stage1 = 1;
+  params.skip_stage2 = 1;
+  //params.mig_speed = 1L * 1024 * 1024;
+  MSG_host_set_params(vm0, &params);
+  MSG_host_set_params(vm1, &params);
+  MSG_host_set_params(vm2, &params);
+  MSG_host_set_params(vm3, &params);
+
+  MSG_vm_start(vm0);
+  MSG_vm_start(vm1);
+  MSG_vm_start(vm2);
+  MSG_vm_start(vm3);
+
+
+  /* set up tasks and processes */
+  struct task_data t0;
+  struct task_data t1;
+  struct task_data t2;
+  struct task_data t3;
+
+  t0.task = MSG_task_create("Task0", 10000000000000000UL, 0, NULL);
+  t1.task = MSG_task_create("Task1", 10000000000000000UL, 0, NULL);
+  t2.task = MSG_task_create("Task2", 10000000000000000UL, 0, NULL);
+  t3.task = MSG_task_create("Task3", 10000000000000000UL, 0, NULL);
+
+  MSG_process_create("worker0", worker_main, t0.task, vm0);
+  MSG_process_create("worker1", worker_main, t1.task, vm1);
+  MSG_process_create("worker2", worker_main, t2.task, vm2);
+  MSG_process_create("worker3", worker_main, t3.task, vm3);
+
+
+  /* start experiments */
+  XBT_INFO("## 1. start 4 VMs on PM2 (4 cores)");
+  task_data_init_clock(&t0);
+  task_data_init_clock(&t1);
+  task_data_init_clock(&t2);
+  task_data_init_clock(&t3);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+
+  XBT_INFO("## 2. pin all VMs to CPU0 of PM2");
+  MSG_vm_set_affinity(vm0, pm2, 0x01);
+  MSG_vm_set_affinity(vm1, pm2, 0x01);
+  MSG_vm_set_affinity(vm2, pm2, 0x01);
+  MSG_vm_set_affinity(vm3, pm2, 0x01);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+
+  XBT_INFO("## 3. pin all VMs to CPU0 of PM1 (no effect at now)");
+  /* Because VMs are on PM2, the below operations do not effect computation now. */
+  MSG_vm_set_affinity(vm0, pm1, 0x01);
+  MSG_vm_set_affinity(vm1, pm1, 0x01);
+  MSG_vm_set_affinity(vm2, pm1, 0x01);
+  MSG_vm_set_affinity(vm3, pm1, 0x01);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+
+  XBT_INFO("## 4. unpin VM0, and pin VM2 and VM3 to CPU1 of PM2");
+  MSG_vm_set_affinity(vm0, pm2, 0x00);
+  MSG_vm_set_affinity(vm2, pm2, 0x02);
+  MSG_vm_set_affinity(vm3, pm2, 0x02);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+
+  XBT_INFO("## 5. migrate all VMs to PM0 (only 1 CPU core)");
+  MSG_vm_migrate(vm0, pm0);
+  MSG_vm_migrate(vm1, pm0);
+  MSG_vm_migrate(vm2, pm0);
+  MSG_vm_migrate(vm3, pm0);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+
+  XBT_INFO("## 6. migrate all VMs to PM1 (2 CPU cores, with affinity settings)");
+  MSG_vm_migrate(vm0, pm1);
+  MSG_vm_migrate(vm1, pm1);
+  MSG_vm_migrate(vm2, pm1);
+  MSG_vm_migrate(vm3, pm1);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+
+  XBT_INFO("## 7. clear affinity settings on PM1");
+  MSG_vm_set_affinity(vm0, pm1, 0);
+  MSG_vm_set_affinity(vm1, pm1, 0);
+  MSG_vm_set_affinity(vm2, pm1, 0);
+  MSG_vm_set_affinity(vm3, pm1, 0);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+  MSG_process_sleep(10);
+  task_data_get_clock(&t0);
+  task_data_get_clock(&t1);
+  task_data_get_clock(&t2);
+  task_data_get_clock(&t3);
+
+
+  /* clean up everything */
+  MSG_task_cancel(t0.task);
+  MSG_task_cancel(t1.task);
+  MSG_task_cancel(t2.task);
+  MSG_task_cancel(t3.task);
+  MSG_process_sleep(10);
+  MSG_task_destroy(t0.task);
+  MSG_task_destroy(t1.task);
+  MSG_task_destroy(t2.task);
+  MSG_task_destroy(t3.task);
+
+  MSG_vm_destroy(vm0);
+  MSG_vm_destroy(vm1);
+  MSG_vm_destroy(vm2);
+  MSG_vm_destroy(vm3);
+}
+
+
+static int master_main(int argc, char *argv[])
+{
+  XBT_INFO("=== Test PM (set affinity) ===");
+  test_pm_pin();
+
+  XBT_INFO("=== Test VM (set affinity) ===");
+  test_vm_pin();
+
+  return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+  /* Get the arguments */
+  MSG_init(&argc, argv);
+
+  /* load the platform file */
+  if (argc != 2) {
+    printf("Usage: %s examples/msg/cloud/multicore_plat.xml\n", argv[0]);
+    return 1;
+  }
+
+  MSG_create_environment(argv[1]);
+
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+  msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t);
+  msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t);
+
+
+  XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm0), MSG_host_get_core_number(pm0), MSG_get_host_speed(pm0));
+  XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm1), MSG_host_get_core_number(pm1), MSG_get_host_speed(pm1));
+  XBT_INFO("%s: %d core(s), %f flops/s per each", MSG_host_get_name(pm2), MSG_host_get_core_number(pm2), MSG_get_host_speed(pm2));
+
+
+
+  MSG_process_create("master", master_main, NULL, pm0);
+
+
+
+
+  int res = MSG_main();
+  XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
+
+
+  return !(res == MSG_OK);
+}
diff --git a/examples/msg/cloud/multicore_plat.xml b/examples/msg/cloud/multicore_plat.xml
new file mode 100644 (file)
index 0000000..3a1b616
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version='1.0'?>
+<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
+<platform version="3">
+       <AS id="siteA" routing="Full">
+               <host id="PM0" power="1E8" core="1"/>
+               <host id="PM1" power="1E8" core="2"/>
+               <host id="PM2" power="1E8" core="4"/>
+
+               <!-- <link id="link1" bandwidth="1E6" latency="1E-2" /> -->
+               <link id="link1" bandwidth="12500000" latency="1E-2" />
+
+               <route src="PM0" dst="PM1">
+                       <link_ctn id="link1"/>
+               </route>
+
+               <route src="PM0" dst="PM2">
+                       <link_ctn id="link1"/>
+               </route>
+
+               <route src="PM1" dst="PM2">
+                       <link_ctn id="link1"/>
+               </route>
+       </AS>
+</platform>
diff --git a/examples/msg/cloud/scale.c b/examples/msg/cloud/scale.c
new file mode 100644 (file)
index 0000000..e113d2c
--- /dev/null
@@ -0,0 +1,216 @@
+/* Copyright (c) 2007-2012. 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 <stdio.h>
+#include <sys/time.h>
+#include "msg/msg.h"
+#include "xbt/sysdep.h"         /* calloc, printf */
+
+/* Create a log channel to have nice outputs. */
+#include "xbt/log.h"
+#include "xbt/asserts.h"
+XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,
+                             "Messages specific for this msg example");
+
+/*
+ * Usage:
+ * ./examples/msg/cloud/scale ../examples/platforms/g5k.xml
+ *
+ * 1. valgrind --tool=callgrind ./examples/msg/cloud/scale ../examples/platforms/g5k.xml
+ * 2. kcachegrind
+ **/
+
+static double time_precise(void)
+{
+       struct timeval tv;
+       int ret = gettimeofday(&tv, NULL);
+  if (ret < 0)
+    xbt_die("gettimeofday");
+
+       double now = (double) tv.tv_sec + tv.tv_usec * 0.001 * 0.001;
+
+       return now;
+}
+
+static int computation_fun(int argc, char *argv[])
+{
+  for (;;) {
+    // double clock_sta = time_precise();
+
+    msg_task_t task = MSG_task_create("Task", 10000000, 0, NULL);
+    MSG_task_execute(task);
+    MSG_task_destroy(task);
+
+    // double clock_end = time_precise();
+
+    // XBT_INFO("%f", clock_end - clock_sta);
+  }
+
+
+  return 0;
+}
+
+static void launch_computation_worker(msg_host_t host)
+{
+  MSG_process_create("compute", computation_fun, NULL, host);
+}
+
+#if 0
+struct task_priv {
+  msg_host_t tx_host;
+  msg_process_t tx_proc;
+  double clock_sta;
+};
+
+static int communication_tx_fun(int argc, char *argv[])
+{
+  xbt_assert(argc == 2);
+  const char *mbox = argv[1];
+
+  msg_task_t task = MSG_task_create("Task", 1000000, 1000000, NULL);
+
+  struct task_priv *priv = xbt_new(struct task_priv, 1);
+  priv->tx_proc = MSG_process_self();
+  priv->tx_host = MSG_host_self();
+  priv->clock_sta = MSG_get_clock();
+
+  MSG_task_set_data(task, priv);
+
+  MSG_task_send(task, mbox);
+
+  return 0;
+}
+
+static int communication_rx_fun(int argc, char *argv[])
+{
+  const char *pr_name = MSG_process_get_name(MSG_process_self());
+  const char *host_name = MSG_host_get_name(MSG_host_self());
+  xbt_assert(argc == 2);
+  const char *mbox = argv[1];
+
+  msg_task_t task = NULL;
+  MSG_task_recv(&task, mbox);
+
+  struct task_priv *priv = MSG_task_get_data(task);
+  double clock_end = MSG_get_clock();
+
+  XBT_INFO("%s:%s to %s:%s => %g sec",
+      MSG_host_get_name(priv->tx_host),
+      MSG_process_get_name(priv->tx_proc),
+      host_name, pr_name, clock_end - priv->clock_sta);
+
+  MSG_task_destroy(task);
+
+  return 0;
+}
+
+static void launch_communication_worker(msg_host_t tx_host, msg_host_t rx_host)
+{
+  char *mbox = bprintf("MBOX:%s-%s",
+      MSG_host_get_name(tx_host),
+      MSG_host_get_name(rx_host));
+  char **argv = NULL;
+  
+  const char *pr_name_tx =  "comm_tx";
+  argv = xbt_new(char *, 3);
+  argv[0] = xbt_strdup(pr_name_tx);
+  argv[1] = xbt_strdup(mbox);
+  argv[2] = NULL;
+
+  MSG_process_create_with_arguments(pr_name_tx, communication_tx_fun, NULL, tx_host, 2, argv);
+
+  const char *pr_name_rx =  "comm_rx";  
+  argv = xbt_new(char *, 3);
+  argv[0] = xbt_strdup(pr_name_rx);
+  argv[1] = xbt_strdup(mbox);
+  argv[2] = NULL;
+
+  MSG_process_create_with_arguments(pr_name_rx, communication_rx_fun, NULL, rx_host, 2, argv);
+
+  xbt_free(mbox);
+}
+#endif
+
+
+
+
+
+
+static int master_main(int argc, char *argv[])
+{
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+
+  int npm = 10;
+  int nvm = 1000;
+
+  msg_host_t *pm = xbt_new(msg_host_t, npm);
+  msg_vm_t   *vm = xbt_new(msg_vm_t, nvm);
+
+  int i = 0;
+  for (i = 0; i < npm; i++) {
+         pm[i] = xbt_dynar_get_as(hosts_dynar, i, msg_host_t);
+  }
+
+  for (i = 0; i < nvm; i++) {
+         int pm_index = i % npm;
+         char *vm_name = bprintf("vm%d", i);
+         vm[i] = MSG_vm_create_core(pm[pm_index], vm_name);
+         MSG_vm_start(vm[i]);
+
+    launch_computation_worker(vm[i]);
+
+         xbt_free(vm_name);
+  }
+
+
+  XBT_INFO("## Test (start)");
+
+  for (i = 0; i < 10; i++) {
+         double clock_sta = time_precise();
+         MSG_process_sleep(1);
+         double clock_end = time_precise();
+         XBT_INFO("duration %f", clock_end - clock_sta);
+  }
+
+
+  for (i = 0; i < nvm; i++) {
+         MSG_vm_destroy(vm[i]);
+  }
+
+  XBT_INFO("## Test (ended)");
+  
+  return 0;
+}
+
+static void launch_master(msg_host_t host)
+{
+  const char *pr_name = "master_";
+  char **argv = xbt_new(char *, 2);
+  argv[0] = xbt_strdup(pr_name);
+  argv[1] = NULL;
+
+  MSG_process_create_with_arguments(pr_name, master_main, NULL, host, 1, argv);
+}
+
+
+int main(int argc, char *argv[])
+{
+  /* Get the arguments */
+  MSG_init(&argc, argv);
+
+  /* load the platform file */
+  xbt_assert(argc == 2);
+  MSG_create_environment(argv[1]);
+
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+  launch_master(pm0);
+
+  int res = MSG_main();
+  XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
+
+
+  return !(res == MSG_OK);
+}
diff --git a/examples/msg/cloud/simple_plat.xml b/examples/msg/cloud/simple_plat.xml
new file mode 100644 (file)
index 0000000..9bc4478
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version='1.0'?>
+<!DOCTYPE platform SYSTEM "http://simgrid.gforge.inria.fr/simgrid.dtd">
+<platform version="3">
+       <AS id="siteA" routing="Full">
+               <host id="PM0" power="1E8"/>
+               <host id="PM1" power="1E8"/>
+               <host id="PM2" power="1E8"/>
+
+               <!-- <link id="link1" bandwidth="1E6" latency="1E-2" /> -->
+               <link id="link1" bandwidth="12500000" latency="1E-2" />
+
+               <route src="PM0" dst="PM1">
+                       <link_ctn id="link1"/>
+               </route>
+
+               <route src="PM0" dst="PM2">
+                       <link_ctn id="link1"/>
+               </route>
+
+               <route src="PM1" dst="PM2">
+                       <link_ctn id="link1"/>
+               </route>
+       </AS>
+</platform>
diff --git a/examples/msg/cloud/simple_vm.c b/examples/msg/cloud/simple_vm.c
new file mode 100644 (file)
index 0000000..e61c01c
--- /dev/null
@@ -0,0 +1,297 @@
+/* Copyright (c) 2007-2012. 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 <stdio.h>
+#include "msg/msg.h"
+#include "xbt/sysdep.h"         /* calloc, printf */
+
+/* Create a log channel to have nice outputs. */
+#include "xbt/log.h"
+#include "xbt/asserts.h"
+XBT_LOG_NEW_DEFAULT_CATEGORY(msg_test,
+                             "Messages specific for this msg example");
+
+
+static int computation_fun(int argc, char *argv[])
+{
+  const char *pr_name = MSG_process_get_name(MSG_process_self());
+  const char *host_name = MSG_host_get_name(MSG_host_self());
+
+  msg_task_t task = MSG_task_create("Task", 1000000, 1000000, NULL);
+
+  double clock_sta = MSG_get_clock();
+  MSG_task_execute(task);
+  double clock_end = MSG_get_clock();
+
+  XBT_INFO("%s:%s task executed %g", host_name, pr_name, clock_end - clock_sta);
+
+  MSG_task_destroy(task);
+
+  return 0;
+}
+
+static void launch_computation_worker(msg_host_t host)
+{
+  const char *pr_name = "compute";
+  char **argv = xbt_new(char *, 2);
+  argv[0] = xbt_strdup(pr_name);
+  argv[1] = NULL;
+
+  MSG_process_create_with_arguments(pr_name, computation_fun, NULL, host, 1, argv);
+}
+
+struct task_priv {
+  msg_host_t tx_host;
+  msg_process_t tx_proc;
+  double clock_sta;
+};
+
+static int communication_tx_fun(int argc, char *argv[])
+{
+  xbt_assert(argc == 2);
+  const char *mbox = argv[1];
+
+  msg_task_t task = MSG_task_create("Task", 1000000, 1000000, NULL);
+
+  struct task_priv *priv = xbt_new(struct task_priv, 1);
+  priv->tx_proc = MSG_process_self();
+  priv->tx_host = MSG_host_self();
+  priv->clock_sta = MSG_get_clock();
+
+  MSG_task_set_data(task, priv);
+
+  MSG_task_send(task, mbox);
+
+  return 0;
+}
+
+static int communication_rx_fun(int argc, char *argv[])
+{
+  const char *pr_name = MSG_process_get_name(MSG_process_self());
+  const char *host_name = MSG_host_get_name(MSG_host_self());
+  xbt_assert(argc == 2);
+  const char *mbox = argv[1];
+
+  msg_task_t task = NULL;
+  MSG_task_recv(&task, mbox);
+
+  struct task_priv *priv = MSG_task_get_data(task);
+  double clock_end = MSG_get_clock();
+
+  XBT_INFO("%s:%s to %s:%s => %g sec",
+      MSG_host_get_name(priv->tx_host),
+      MSG_process_get_name(priv->tx_proc),
+      host_name, pr_name, clock_end - priv->clock_sta);
+
+  MSG_task_destroy(task);
+
+  return 0;
+}
+
+static void launch_communication_worker(msg_host_t tx_host, msg_host_t rx_host)
+{
+  char *mbox = bprintf("MBOX:%s-%s",
+      MSG_host_get_name(tx_host),
+      MSG_host_get_name(rx_host));
+  char **argv = NULL;
+  
+  const char *pr_name_tx =  "comm_tx";
+  argv = xbt_new(char *, 3);
+  argv[0] = xbt_strdup(pr_name_tx);
+  argv[1] = xbt_strdup(mbox);
+  argv[2] = NULL;
+
+  MSG_process_create_with_arguments(pr_name_tx, communication_tx_fun, NULL, tx_host, 2, argv);
+
+  const char *pr_name_rx =  "comm_rx";  
+  argv = xbt_new(char *, 3);
+  argv[0] = xbt_strdup(pr_name_rx);
+  argv[1] = xbt_strdup(mbox);
+  argv[2] = NULL;
+
+  MSG_process_create_with_arguments(pr_name_rx, communication_rx_fun, NULL, rx_host, 2, argv);
+
+  xbt_free(mbox);
+}
+
+
+static int master_main(int argc, char *argv[])
+{
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+  msg_host_t pm1 = xbt_dynar_get_as(hosts_dynar, 1, msg_host_t);
+  msg_host_t pm2 = xbt_dynar_get_as(hosts_dynar, 2, msg_host_t);
+  msg_vm_t vm0, vm1;
+
+
+  XBT_INFO("## Test 1 (started): check computation on normal PMs");
+
+  XBT_INFO("### Put a task on a PM");
+  launch_computation_worker(pm0);
+  MSG_process_sleep(2);
+
+  XBT_INFO("### Put two tasks on a PM");
+  launch_computation_worker(pm0);
+  launch_computation_worker(pm0);
+  MSG_process_sleep(2);
+
+  XBT_INFO("### Put a task on each PM");
+  launch_computation_worker(pm0);
+  launch_computation_worker(pm1);
+  MSG_process_sleep(2);
+
+  XBT_INFO("## Test 1 (ended)");
+
+
+  XBT_INFO("## Test 2 (started): check impact of running a task inside a VM (there is no degradation for the moment)");
+
+  XBT_INFO("### Put a VM on a PM, and put a task to the VM");
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  MSG_vm_start(vm0);
+  launch_computation_worker(vm0);
+  MSG_process_sleep(2);
+  MSG_vm_destroy(vm0);
+
+  XBT_INFO("## Test 2 (ended)");
+
+  
+  XBT_INFO("## Test 3 (started): check impact of running a task collocated with a VM (there is no VM noise for the moment)");
+
+  XBT_INFO("### Put a VM on a PM, and put a task to the PM");
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  MSG_vm_start(vm0);
+  launch_computation_worker(pm0);
+  MSG_process_sleep(2);
+  MSG_vm_destroy(vm0);
+
+  XBT_INFO("## Test 3 (ended)");
+
+
+  XBT_INFO("## Test 4 (started): compare the cost of running two tasks inside two different VMs collocated or not (for the moment, there is no degradation for the VMs. Hence, the time should be equals to the time of test 1");
+
+  XBT_INFO("### Put two VMs on a PM, and put a task to each VM");
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  vm1 = MSG_vm_create_core(pm0, "VM1");
+  MSG_vm_start(vm0);
+  MSG_vm_start(vm1);
+  launch_computation_worker(vm0);
+  launch_computation_worker(vm1);
+  MSG_process_sleep(2);
+  MSG_vm_destroy(vm0);
+  MSG_vm_destroy(vm1);
+
+  XBT_INFO("### Put a VM on each PM, and put a task to each VM");
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  vm1 = MSG_vm_create_core(pm1, "VM1");
+  MSG_vm_start(vm0);
+  MSG_vm_start(vm1);
+  launch_computation_worker(vm0);
+  launch_computation_worker(vm1);
+  MSG_process_sleep(2);
+  MSG_vm_destroy(vm0);
+  MSG_vm_destroy(vm1);
+  XBT_INFO("## Test 4 (ended)");
+
+  
+  XBT_INFO("## Test 5  (started): Analyse network impact");
+  XBT_INFO("### Make a connection between PM0 and PM1");
+  launch_communication_worker(pm0, pm1);
+  MSG_process_sleep(5);
+
+  XBT_INFO("### Make two connection between PM0 and PM1");
+  launch_communication_worker(pm0, pm1);
+  launch_communication_worker(pm0, pm1);
+  MSG_process_sleep(5);
+
+  XBT_INFO("### Make a connection between PM0 and VM0@PM0");
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  MSG_vm_start(vm0);
+  launch_communication_worker(pm0, vm0);
+  MSG_process_sleep(5);
+  MSG_vm_destroy(vm0);
+
+  XBT_INFO("### Make a connection between PM0 and VM0@PM1");
+  vm0 = MSG_vm_create_core(pm1, "VM0");
+  MSG_vm_start(vm0);
+  launch_communication_worker(pm0, vm0);
+  MSG_process_sleep(5);
+  MSG_vm_destroy(vm0);
+
+  XBT_INFO("### Make two connections between PM0 and VM0@PM1");
+  vm0 = MSG_vm_create_core(pm1, "VM0");
+  MSG_vm_start(vm0);
+  launch_communication_worker(pm0, vm0);
+  launch_communication_worker(pm0, vm0);
+  MSG_process_sleep(5);
+  MSG_vm_destroy(vm0);
+
+  XBT_INFO("### Make a connection between PM0 and VM0@PM1, and also make a connection between PM0 and PM1");
+  vm0 = MSG_vm_create_core(pm1, "VM0");
+  MSG_vm_start(vm0);
+  launch_communication_worker(pm0, vm0);
+  launch_communication_worker(pm0, pm1);
+  MSG_process_sleep(5);
+  MSG_vm_destroy(vm0);
+
+  XBT_INFO("### Make a connection between VM0@PM0 and PM1@PM1, and also make a connection between VM0@PM0 and VM1@PM1");
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  vm1 = MSG_vm_create_core(pm1, "VM1");
+  MSG_vm_start(vm0);
+  MSG_vm_start(vm1);
+  launch_communication_worker(vm0, vm1);
+  launch_communication_worker(vm0, vm1);
+  MSG_process_sleep(5);
+  MSG_vm_destroy(vm0);
+  MSG_vm_destroy(vm1);
+
+  XBT_INFO("## Test 5 (ended)");
+
+
+  XBT_INFO("## Test 6 (started): Check migration impact (not yet implemented neither on the CPU resource nor on the network one");
+  XBT_INFO("### Relocate VM0 between PM0 and PM1");
+  vm0 = MSG_vm_create_core(pm0, "VM0");
+  MSG_vm_start(vm0);
+  launch_communication_worker(vm0, pm2);
+  MSG_process_sleep(0.01);
+  MSG_vm_migrate(vm0, pm1);
+  MSG_process_sleep(0.01);
+  MSG_vm_migrate(vm0, pm0);
+  MSG_process_sleep(5);
+  MSG_vm_destroy(vm0);
+  XBT_INFO("## Test 6 (ended)");
+  
+  return 0;
+}
+
+static void launch_master(msg_host_t host)
+{
+  const char *pr_name = "master_";
+  char **argv = xbt_new(char *, 2);
+  argv[0] = xbt_strdup(pr_name);
+  argv[1] = NULL;
+
+  MSG_process_create_with_arguments(pr_name, master_main, NULL, host, 1, argv);
+}
+
+
+int main(int argc, char *argv[])
+{
+  /* Get the arguments */
+  MSG_init(&argc, argv);
+
+  /* load the platform file */
+  xbt_assert(argc == 2);
+  MSG_create_environment(argv[1]);
+
+  xbt_dynar_t hosts_dynar = MSG_hosts_as_dynar();
+  msg_host_t pm0 = xbt_dynar_get_as(hosts_dynar, 0, msg_host_t);
+  launch_master(pm0);
+
+  int res = MSG_main();
+  XBT_INFO("Bye (simulation time %g)", MSG_get_clock());
+
+
+  return !(res == MSG_OK);
+}
index efee4e6..0f5bf3b 100644 (file)
@@ -28,7 +28,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 ************************************ */
 
@@ -48,7 +48,12 @@ typedef xbt_dictelm_t msg_host_t;
 typedef s_xbt_dictelm_t s_msg_host_t;
 
 typedef struct msg_host_priv {
-  xbt_swag_t vms;
+  int        dp_enabled;
+  xbt_dict_t dp_objs;
+  double     dp_updated_by_deleted_tasks;
+
+  xbt_dict_t affinity_mask_db;
+
 #ifdef MSG_USE_DEPRECATED
   msg_mailbox_t *mailboxes;     /**< the channels  */
 #endif
@@ -83,22 +88,13 @@ typedef struct msg_task {
  */
 typedef struct msg_task *msg_task_t;
 
-/* ********************************  VM ************************************* */
-typedef struct msg_vm *msg_vm_t;
-
-typedef enum {
-  msg_vm_state_suspended, msg_vm_state_running, msg_vm_state_migrating
-} e_msg_vm_state_t;
-
-typedef struct msg_vm {
-  char *name;
-  s_xbt_swag_hookup_t all_vms_hookup;
-  s_xbt_swag_hookup_t host_vms_hookup;
-  xbt_dynar_t processes;
-  e_msg_vm_state_t state;
-  msg_host_t location;
-  int coreAmount;
-} s_msg_vm_t;
+/* ******************************** VM ************************************* */
+typedef msg_host_t msg_vm_t;
+typedef msg_host_priv_t msg_vm_priv_t;
+
+static inline msg_vm_priv_t MSG_vm_priv(msg_vm_t vm){
+  return (msg_vm_priv_t) xbt_lib_get_level(vm, MSG_HOST_LEVEL);
+}
 
 /* ******************************** File ************************************ */
 typedef struct simdata_file *simdata_file_t;
index 4a845f3..8b55e68 100644 (file)
@@ -118,6 +118,8 @@ XBT_PUBLIC(void) MSG_as_router_set_property_value(const char* asr, const char *n
 XBT_PUBLIC(msg_error_t) MSG_host_set_data(msg_host_t host, void *data);
 XBT_PUBLIC(void *) MSG_host_get_data(msg_host_t host);
 XBT_PUBLIC(const char *) MSG_host_get_name(msg_host_t host);
+XBT_PUBLIC(void) MSG_host_on(msg_host_t host);
+XBT_PUBLIC(void) MSG_host_off(msg_host_t host);
 XBT_PUBLIC(msg_host_t) MSG_host_self(void);
 XBT_PUBLIC(int) MSG_get_host_msgload(msg_host_t host);
 /* int MSG_get_msgload(void); This function lacks specification; discard it */
@@ -125,7 +127,8 @@ XBT_PUBLIC(double) MSG_get_host_speed(msg_host_t h);
 XBT_PUBLIC(int) MSG_host_get_core_number(msg_host_t h);
 XBT_PUBLIC(xbt_swag_t) MSG_host_get_process_list(msg_host_t h);
 XBT_PUBLIC(int) MSG_host_is_avail(msg_host_t h);
-XBT_PUBLIC(void) __MSG_host_destroy(msg_host_priv_t host);
+XBT_PUBLIC(void) __MSG_host_priv_free(msg_host_priv_t priv);
+XBT_PUBLIC(void) __MSG_host_destroy(msg_host_t host);
 
 XBT_PUBLIC(double) MSG_get_host_power_peak_at(msg_host_t h, int pstate_index);
 XBT_PUBLIC(double) MSG_get_host_current_power_peak(msg_host_t h);
@@ -147,6 +150,8 @@ XBT_PUBLIC(void) MSG_create_environment(const char *file);
 XBT_PUBLIC(msg_host_t) MSG_get_host_by_name(const char *name);
 XBT_PUBLIC(xbt_dynar_t) MSG_hosts_as_dynar(void);
 XBT_PUBLIC(int) MSG_get_host_number(void);
+XBT_PUBLIC(void) MSG_host_get_params(msg_host_t ind_pm, ws_params_t params);
+XBT_PUBLIC(void) MSG_host_set_params(msg_host_t ind_pm, ws_params_t params);
 XBT_PUBLIC(xbt_dict_t) MSG_host_get_storage_list(msg_host_t host);
 XBT_PUBLIC(xbt_dict_t) MSG_host_get_storage_content(msg_host_t host);
 /************************** Process handling *********************************/
@@ -238,6 +243,8 @@ XBT_PUBLIC(msg_error_t) MSG_task_receive_from_host_bounded(msg_task_t * task, co
 XBT_PUBLIC(msg_error_t) MSG_task_execute(msg_task_t task);
 XBT_PUBLIC(msg_error_t) MSG_parallel_task_execute(msg_task_t task);
 XBT_PUBLIC(void) MSG_task_set_priority(msg_task_t task, double priority);
+XBT_PUBLIC(void) MSG_task_set_bound(msg_task_t task, double bound);
+XBT_PUBLIC(void) MSG_task_set_affinity(msg_task_t task, msg_host_t host, unsigned long mask);
 
 XBT_PUBLIC(msg_error_t) MSG_process_sleep(double nb_sec);
 
@@ -411,30 +418,47 @@ XBT_PUBLIC(int) MSG_sem_would_block(msg_sem_t sem);
  * Usual lack of guaranty of any kind applies here, and is even increased.
  *
  */
-/* This function should not be called directly, but rather from MSG_vm_start_from_template that does not exist yet*/
-XBT_PUBLIC(msg_vm_t) MSG_vm_start(msg_host_t location, const char *name, int coreAmount);
 
-XBT_PUBLIC(int) MSG_vm_is_suspended(msg_vm_t);
+XBT_PUBLIC(int) MSG_vm_is_created(msg_vm_t);
 XBT_PUBLIC(int) MSG_vm_is_running(msg_vm_t);
+XBT_PUBLIC(int) MSG_vm_is_migrating(msg_vm_t);
 
-XBT_PUBLIC(void) MSG_vm_bind(msg_vm_t vm, msg_process_t process);
-XBT_PUBLIC(void) MSG_vm_unbind(msg_vm_t vm, msg_process_t process); // simple wrapper over process_kill
+XBT_PUBLIC(int) MSG_vm_is_suspended(msg_vm_t);
+XBT_PUBLIC(int) MSG_vm_is_saving(msg_vm_t);
+XBT_PUBLIC(int) MSG_vm_is_saved(msg_vm_t);
+XBT_PUBLIC(int) MSG_vm_is_restoring(msg_vm_t);
 
-XBT_PUBLIC(void) MSG_vm_migrate(msg_vm_t vm, msg_host_t destination);
 
-XBT_PUBLIC(void) MSG_vm_suspend(msg_vm_t vm);
-  // \forall p in VM, MSG_process_suspend(p) // Freeze the processes
+XBT_PUBLIC(const char*) MSG_vm_get_name(msg_vm_t);
 
-XBT_PUBLIC(void) MSG_vm_resume(msg_vm_t vm);  // Simulate the fact of reading the processes from disk and resuming them
-  // \forall p in VM, MSG_process_resume(p) // unfreeze them
+// TODO add VDI later
+XBT_PUBLIC(msg_vm_t) MSG_vm_create_core(msg_host_t location, const char *name);
+XBT_PUBLIC(msg_vm_t) MSG_vm_create(msg_host_t ind_pm, const char *name,
+    int core_nb, int mem_cap, int net_cap, char *disk_path, int disk_size, int mig_netspeed, int dp_intensity);
 
-XBT_PUBLIC(void) MSG_vm_shutdown(msg_vm_t vm); // killall
+XBT_PUBLIC(void) MSG_vm_destroy(msg_vm_t vm);
 
-XBT_PUBLIC(void) MSG_vm_reboot(msg_vm_t vm);
+XBT_PUBLIC(void) MSG_vm_start(msg_vm_t);
 
-XBT_PUBLIC(void) MSG_vm_destroy(msg_vm_t vm);
+/* Shutdown the guest operating system. */
+XBT_PUBLIC(void) MSG_vm_shutdown(msg_vm_t vm);
+
+XBT_PUBLIC(void) MSG_vm_migrate(msg_vm_t vm, msg_host_t destination);
+
+/* Suspend the execution of the VM, but keep its state on memory. */
+XBT_PUBLIC(void) MSG_vm_suspend(msg_vm_t vm);
+XBT_PUBLIC(void) MSG_vm_resume(msg_vm_t vm);
+
+/* Save the VM state to a disk. */
+XBT_PUBLIC(void) MSG_vm_save(msg_vm_t vm);
+XBT_PUBLIC(void) MSG_vm_restore(msg_vm_t vm);
+
+XBT_PUBLIC(msg_host_t) MSG_vm_get_pm(msg_vm_t vm);
+XBT_PUBLIC(void) MSG_vm_set_bound(msg_vm_t vm, double bound);
+XBT_PUBLIC(void) MSG_vm_set_affinity(msg_vm_t vm, msg_host_t pm, unsigned long mask);
 
-XBT_PUBLIC(xbt_dynar_t) MSG_vms_as_dynar(void);
+/* TODO: do we need this? */
+// XBT_PUBLIC(xbt_dynar_t) MSG_vms_as_dynar(void);
 
 /*
 void* MSG_process_get_property(msg_process_t, char* key)
index ff9095d..b888225 100644 (file)
 
 #include <xbt.h>
 
-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 void *sg_routing_link_t; /* FIXME:The actual type is model-dependent so use void* instead*/
+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 {
@@ -47,6 +53,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,
@@ -71,6 +80,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;
@@ -319,6 +332,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
 
@@ -368,5 +385,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 */
index 07b4052..8e9db8c 100644 (file)
@@ -14,6 +14,7 @@
 #include "xbt/parmap.h"
 #include "xbt/swag.h"
 #include "simgrid/platf.h"
+#include "surf/surf.h"
 
 SG_BEGIN_DECL()
 
@@ -260,6 +261,8 @@ XBT_PUBLIC(smx_host_t) SIMIX_host_get_by_name(const char *name);
 XBT_PUBLIC(smx_host_t) SIMIX_host_self(void);
 XBT_PUBLIC(const char*) SIMIX_host_self_get_name(void);
 XBT_PUBLIC(const char*) SIMIX_host_get_name(smx_host_t host); /* FIXME: make private: only the name of SIMIX_host_self() should be public without request */
+XBT_PUBLIC(void) SIMIX_host_on(smx_host_t host);
+XBT_PUBLIC(void) SIMIX_host_off(smx_host_t host, smx_process_t issuer);
 XBT_PUBLIC(void) SIMIX_host_self_set_data(void *data);
 XBT_PUBLIC(void*) SIMIX_host_self_get_data(void);
 XBT_PUBLIC(void*) SIMIX_host_get_data(smx_host_t host);
@@ -303,6 +306,8 @@ XBT_PUBLIC(void) SIMIX_file_set_data(smx_file_t fd, void *data);
 XBT_PUBLIC(smx_host_t) simcall_host_get_by_name(const char *name);
 XBT_PUBLIC(const char *) simcall_host_get_name(smx_host_t host);
 XBT_PUBLIC(xbt_dict_t) simcall_host_get_properties(smx_host_t host);
+XBT_PUBLIC(void) simcall_host_on(smx_host_t host);
+XBT_PUBLIC(void) simcall_host_off(smx_host_t host);
 XBT_PUBLIC(int) simcall_host_get_core(smx_host_t host);
 XBT_PUBLIC(xbt_swag_t) simcall_host_get_process_list(smx_host_t host);
 XBT_PUBLIC(double) simcall_host_get_speed(smx_host_t host);
@@ -321,7 +326,7 @@ XBT_PUBLIC(double) simcall_host_get_consumed_energy(smx_host_t host);
 
 XBT_PUBLIC(smx_action_t) simcall_host_execute(const char *name, smx_host_t host,
                                                 double computation_amount,
-                                                double priority);
+                                                double priority, double bound, unsigned long affinity_mask);
 XBT_PUBLIC(smx_action_t) simcall_host_parallel_execute(const char *name,
                                                      int host_nb,
                                                      smx_host_t *host_list,
@@ -334,8 +339,28 @@ XBT_PUBLIC(void) simcall_host_execution_cancel(smx_action_t execution);
 XBT_PUBLIC(double) simcall_host_execution_get_remains(smx_action_t execution);
 XBT_PUBLIC(e_smx_state_t) simcall_host_execution_get_state(smx_action_t execution);
 XBT_PUBLIC(void) simcall_host_execution_set_priority(smx_action_t execution, double priority);
+XBT_PUBLIC(void) simcall_host_execution_set_bound(smx_action_t execution, double bound);
+XBT_PUBLIC(void) simcall_host_execution_set_affinity(smx_action_t execution, smx_host_t host, unsigned long mask);
 XBT_PUBLIC(e_smx_state_t) simcall_host_execution_wait(smx_action_t execution);
 XBT_PUBLIC(xbt_dict_t) simcall_host_get_storage_list(smx_host_t host);
+XBT_PUBLIC(void) simcall_host_get_params(smx_host_t vm, ws_params_t param);
+XBT_PUBLIC(void) simcall_host_set_params(smx_host_t vm, ws_params_t param);
+
+/******************************* VM simcalls ********************************/
+// Create the vm_workstation at the SURF level
+XBT_PUBLIC(void*) simcall_vm_create(const char *name, smx_host_t host);
+XBT_PUBLIC(int) simcall_vm_get_state(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_start(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_migrate(smx_host_t vm, smx_host_t dst_pm);
+XBT_PUBLIC(void *) simcall_vm_get_pm(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_set_bound(smx_host_t vm, double bound);
+XBT_PUBLIC(void) simcall_vm_set_affinity(smx_host_t vm, smx_host_t pm, unsigned long mask);
+XBT_PUBLIC(void) simcall_vm_resume(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_save(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_restore(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_suspend(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_destroy(smx_host_t vm);
+XBT_PUBLIC(void) simcall_vm_shutdown(smx_host_t vm);
 
 /**************************** Process simcalls ********************************/
 /* Constructor and Destructor */
index d9e91ef..3c2e36a 100644 (file)
 #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
@@ -47,4 +51,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 */
index 0cdf31f..0994be3 100644 (file)
@@ -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;
index e57f166..5e2905f 100644 (file)
@@ -262,7 +262,8 @@ typedef enum {
   thread_error,                 /**< error while [un]locking */
   host_error,                   /**< host failed */
   tracing_error,                /**< error during the simulation tracing */
-  io_error                      /**< disk or file error */
+  io_error,                      /**< disk or file error */
+  vm_error                      /**< vm  error */
 } xbt_errcat_t;
 
 XBT_PUBLIC(const char *) xbt_ex_catname(xbt_errcat_t cat);
index 29a9149..cc50c02 100644 (file)
@@ -16,6 +16,9 @@
  *  @{
  */
 /* @brief heap datatype */
+#ifdef __cplusplus
+extern "C" {
+#endif
 typedef struct xbt_heap *xbt_heap_t;
 
 XBT_PUBLIC(xbt_heap_t) xbt_heap_new(int init_size,
@@ -33,6 +36,8 @@ XBT_PUBLIC(void) xbt_heap_set_update_callback(xbt_heap_t H,
                                                                        *,
                                                                        int));
 XBT_PUBLIC(void *) xbt_heap_remove(xbt_heap_t H, int i);
-
+#ifdef __cplusplus
+}
+#endif
 /* @} */
 #endif                          /* _XBT_HEAP_H */
index 5139ff8..c087513 100644 (file)
@@ -26,10 +26,12 @@ XBT_PUBLIC(void) xbt_lib_free(xbt_lib_t * lib);
 XBT_PUBLIC(int) xbt_lib_add_level(xbt_lib_t lib, void_f_pvoid_t free_f);
 XBT_PUBLIC(void) xbt_lib_set(xbt_lib_t lib, const char *name, int level,
                              void *obj);
+XBT_PUBLIC(void) xbt_lib_unset(xbt_lib_t lib, const char *key, int level, int invoke_callback);
 XBT_PUBLIC(void *) xbt_lib_get_or_null(xbt_lib_t lib, const char *name,
                                        int level);
 XBT_PUBLIC(xbt_dictelm_t) xbt_lib_get_elm_or_null(xbt_lib_t lib, const char *key);
 XBT_PUBLIC(void *) xbt_lib_get_level(xbt_dictelm_t elm, int level);
+XBT_PUBLIC(void) xbt_lib_remove(xbt_lib_t lib, const char *key);
 
 #define xbt_lib_length(lib) xbt_dict_length((lib)->dict)
 
index b5b9a82..29cad1b 100644 (file)
 
 #include <xbt/misc.h>           /* 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 */
index 9a3a1ff..1384125 100644 (file)
@@ -154,6 +154,19 @@ Java_org_simgrid_msg_Host_currentHost(JNIEnv * env, jclass cls) {
 
   return jhost;
 }
+
+JNIEXPORT void JNICALL
+Java_org_simgrid_msg_Host_on(JNIEnv *env, jobject jhost) {
+  msg_host_t host = jhost_get_native(env, jhost);
+  MSG_host_on(host);
+}
+
+JNIEXPORT void JNICALL
+Java_org_simgrid_msg_Host_off(JNIEnv *env, jobject jhost) {
+  msg_host_t host = jhost_get_native(env, jhost);
+  MSG_host_off(host);
+}
+
 JNIEXPORT jint JNICALL
 Java_org_simgrid_msg_Host_getCount(JNIEnv * env, jclass cls) {
   xbt_dynar_t hosts =  MSG_hosts_as_dynar();
index 5eff534..92f1989 100644 (file)
@@ -112,6 +112,24 @@ Java_org_simgrid_msg_Host_nativeInit(JNIEnv *env, jclass cls);
 JNIEXPORT jobject JNICALL Java_org_simgrid_msg_Host_getByName
     (JNIEnv *, jclass, jstring);
 
+/**
+ * This function start the host if it is off
+ *
+ * @param jhost                        The host to test the validity.
+ * @param env                  The environment of the current thread
+ *
+ */
+JNIEXPORT void JNICALL Java_org_simgrid_msg_Host_on(JNIEnv *env, jobject jhost);
+
+/**
+ * This function stop the host if it is on
+ *
+ * @param jhost                        The host to test the validity.
+ * @param env                  The environment of the current thread
+ *
+ */
+JNIEXPORT void JNICALL Java_org_simgrid_msg_Host_off(JNIEnv *env, jobject jhost);
+
 /*
  * Class               org_simgrid_msg_Host
  * Method              currentHost
index 01c30ce..4be2266 100644 (file)
@@ -225,6 +225,18 @@ Java_org_simgrid_msg_Task_execute(JNIEnv * env, jobject jtask)
   }
 }
 
+JNIEXPORT void JNICALL
+Java_org_simgrid_msg_Task_setBound(JNIEnv * env, jobject jtask, jdouble load)
+{
+  msg_task_t task = jtask_to_native_task(jtask, env);
+
+  if (!task) {
+    jxbt_throw_notbound(env, "task", jtask);
+    return;
+  }
+  MSG_task_set_bound(task, load);
+}
+
 JNIEXPORT jstring JNICALL
 Java_org_simgrid_msg_Task_getName(JNIEnv * env,
                                        jobject jtask) {
index 197d86a..eec3647 100644 (file)
@@ -124,6 +124,14 @@ JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_cancel
 JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_execute
     (JNIEnv *, jobject);
 
+/*
+ * Class               org_simgrid_msg_Task
+ * Method              setBound
+ * Signature   ()V
+ */
+JNIEXPORT void JNICALL Java_org_simgrid_msg_Task_setBound
+    (JNIEnv *, jobject, jdouble);
+
 /*
  * Class               org_simgrid_msg_Task
  * Method              getName
index 5c54c1f..2df6a93 100644 (file)
@@ -29,100 +29,161 @@ Java_org_simgrid_msg_VM_nativeInit(JNIEnv *env, jclass cls) {
     jxbt_throw_native(env,bprintf("Can't find some fields in Java class. You should report this bug."));
   }
 }
+
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isCreated(JNIEnv * env, jobject jvm) {
+  msg_vm_t vm = jvm_get_native(env,jvm);
+  return (jint) MSG_vm_is_created(vm);
+}
+
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isRunning(JNIEnv * env, jobject jvm) {
+  msg_vm_t vm = jvm_get_native(env,jvm);
+  return (jint) MSG_vm_is_running(vm);
+}
+
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isMigrating(JNIEnv * env, jobject jvm) {
+  msg_vm_t vm = jvm_get_native(env,jvm);
+  return (jint) MSG_vm_is_migrating(vm);
+}
+
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isSuspended(JNIEnv * env, jobject jvm) {
+  msg_vm_t vm = jvm_get_native(env,jvm);
+  return (jint) MSG_vm_is_suspended(vm);
+}
+
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isSaving(JNIEnv * env, jobject jvm) {
+  msg_vm_t vm = jvm_get_native(env,jvm);
+  return (jint) MSG_vm_is_saving(vm);
+}
+
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isSaved(JNIEnv * env, jobject jvm) {
+  msg_vm_t vm = jvm_get_native(env,jvm);
+  return (jint) MSG_vm_is_saved(vm);
+}
+
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isRestoring(JNIEnv * env, jobject jvm) {
+  msg_vm_t vm = jvm_get_native(env,jvm);
+  return (jint) MSG_vm_is_restoring(vm);
+}
+
+JNIEXPORT void JNICALL
+Java_org_simgrid_msg_VM_setBound(JNIEnv *env, jobject jvm, jint load) { 
+
+       msg_vm_t vm = jvm_get_native(env,jvm);
+       double bound = MSG_get_host_speed(vm) * load / 100;
+       MSG_vm_set_bound(vm, bound); 
+}
+
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_start(JNIEnv *env, jobject jvm, jobject jhost, jstring jname, jint jcoreamount) {
+Java_org_simgrid_msg_VM_create(JNIEnv *env, jobject jvm, jobject jhost, jstring jname,
+                              jint jncore, jint jramsize, jint jnetcap, jstring jdiskpath, jint jdisksize, jint jmig_netspeed, jint jdp_intensity) {
+
   msg_host_t host = jhost_get_native(env, jhost);
 
   const char *name;
   name = (*env)->GetStringUTFChars(env, jname, 0);
   name = xbt_strdup(name);
-  
-  msg_vm_t vm = MSG_vm_start(host, name, (int)jcoreamount);
+
+  // TODO disk concerns are not taken into account yet
+  // const char *diskpath;
+  // disk_path = (*env)->GetStringUTFChars(env, jdiskpath, 0);
+  // disk_path = xbt_strdup(disk_path);
+
+  msg_vm_t vm = MSG_vm_create(host, name, (int) jncore, (int) jramsize,
+                 (int) jnetcap, NULL, (int) jdisksize, (int) jmig_netspeed, (int) jdp_intensity);
 
   jvm_bind(env,jvm,vm);
 }
+
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_VM_destroy(JNIEnv *env, jobject jvm) {
   msg_vm_t vm = jvm_get_native(env,jvm);
   MSG_vm_destroy(vm);
 }
-JNIEXPORT jboolean JNICALL
-Java_org_simgrid_msg_VM_isSuspended(JNIEnv *env, jobject jvm) {
-  msg_vm_t vm = jvm_get_native(env,jvm);
 
-  return MSG_vm_is_suspended(vm) ? JNI_TRUE : JNI_FALSE;
-}
-JNIEXPORT jboolean JNICALL
-Java_org_simgrid_msg_VM_isRunning(JNIEnv *env, jobject jvm) {
-  msg_vm_t vm = jvm_get_native(env,jvm);
-
-  return MSG_vm_is_running(vm) ? JNI_TRUE : JNI_FALSE;
-}
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_bind(JNIEnv *env, jobject jvm, jobject jprocess) {
+Java_org_simgrid_msg_VM_start(JNIEnv *env, jobject jvm) {
   msg_vm_t vm = jvm_get_native(env,jvm);
-  msg_process_t process = jprocess_to_native_process(jprocess,env);
-
-  xbt_assert((vm != NULL), "VM object is not bound");
-  xbt_assert((process != NULL), "Process object is not bound.");
-
-  MSG_vm_bind(vm,process);
+  MSG_vm_start(vm);
 }
+
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_unbind(JNIEnv *env, jobject jvm, jobject jprocess) {
+Java_org_simgrid_msg_VM_shutdown(JNIEnv *env, jobject jvm) {
   msg_vm_t vm = jvm_get_native(env,jvm);
-  msg_process_t process = jprocess_to_native_process(jprocess,env);
-
-  MSG_vm_unbind(vm,process);
+  MSG_vm_shutdown(vm);
 }
+
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_migrate(JNIEnv *env, jobject jvm, jobject jhost) {
+Java_org_simgrid_msg_VM_internalmig(JNIEnv *env, jobject jvm, jobject jhost) {
   msg_vm_t vm = jvm_get_native(env,jvm);
   msg_host_t host = jhost_get_native(env, jhost);
-
   MSG_vm_migrate(vm,host);
 }
+
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_VM_suspend(JNIEnv *env, jobject jvm) {
   msg_vm_t vm = jvm_get_native(env,jvm);
-  xbt_ex_t e;
-  TRY {
-    MSG_vm_suspend(vm);
-  }
-  CATCH(e) {
-    xbt_ex_free(e);
-  }
+  MSG_vm_suspend(vm);
 }
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_VM_resume(JNIEnv *env, jobject jvm) {
   msg_vm_t vm = jvm_get_native(env,jvm);
-  xbt_ex_t e;
-  TRY {
-    MSG_vm_resume(vm);
-  }
-  CATCH(e) {
-    xbt_ex_free(e);
-  }
+  MSG_vm_resume(vm);
 }
+
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_shutdown(JNIEnv *env, jobject jvm) {
+Java_org_simgrid_msg_VM_save(JNIEnv *env, jobject jvm) {
   msg_vm_t vm = jvm_get_native(env,jvm);
-  xbt_ex_t e;
-  TRY {
-    MSG_vm_shutdown(vm);
-  }
-  CATCH(e) {
-    xbt_ex_free(e);
-  }
+  MSG_vm_save(vm);
 }
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_reboot(JNIEnv *env, jobject jvm) {
+Java_org_simgrid_msg_VM_restore(JNIEnv *env, jobject jvm) {
   msg_vm_t vm = jvm_get_native(env,jvm);
-  xbt_ex_t e;
-  TRY {
-    MSG_vm_reboot(vm);
-  }
-  CATCH(e) {
-    xbt_ex_free(e);
+  MSG_vm_restore(vm);
+}
+
+
+
+JNIEXPORT jobject JNICALL
+Java_org_simgrid_msg_VM_get_pm(JNIEnv *env, jobject jvm) {
+  jobject jhost;
+  msg_vm_t vm = jvm_get_native(env,jvm);
+  msg_host_t host = MSG_vm_get_pm(vm);
+
+  if (!MSG_host_get_data(host)) {
+    /* the native host not yet associated with the java host instance */
+
+    /* instanciate a new java host instance */
+    jhost = jhost_new_instance(env);
+
+    if (!jhost) {
+      jxbt_throw_jni(env, "java host instantiation failed");
+      return NULL;
+    }
+
+    /* get a global reference to the newly created host */
+    jhost = jhost_ref(env, jhost);
+
+    if (!jhost) {
+      jxbt_throw_jni(env, "global ref allocation failed");
+      return NULL;
+    }
+    /* Sets the host name */
+    const char *name = MSG_host_get_name(host);
+    jobject jname = (*env)->NewStringUTF(env,name);
+    (*env)->SetObjectField(env, jhost, jxbt_get_jfield(env, (*env)->FindClass(env, "org/simgrid/msg/Host"), "name", "Ljava/lang/String;"), jname);
+    /* Bind & store it */
+    jhost_bind(jhost, host, env);
+    MSG_host_set_data(host, (void *) jhost);
+  } else {
+    jhost = (jobject) MSG_host_get_data(host);
   }
+
+  return jhost;
 }
index 6bf4284..5892e2f 100644 (file)
@@ -22,55 +22,101 @@ msg_vm_t jvm_get_native(JNIEnv *env, jobject jvm);
  */
 JNIEXPORT void JNICALL
 Java_org_simgrid_msg_VM_nativeInit(JNIEnv *env, jclass);
+
 /**
  * Class                       org_simgrid_msg_VM
- * Method                      start
- * Signature   (I)V
+ * Method                      isCreated
+ * Signature   ()B
  */
-JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_start(JNIEnv *env, jobject jvm, jobject jhost, jstring jname, jint jcoreamount);
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isCreated(JNIEnv *env, jobject jvm);
 /**
- * Class            org_simgrid_msg_VM
- * Method           destroy
- * Signature    ()V
+ * Class                       org_simgrid_msg_VM
+ * Method                      isRunning
+ * Signature   ()B
  */
-JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_destroy(JNIEnv *env, jobject jvm);
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isRunning(JNIEnv *env, jobject jvm);
+/**
+ * Class                       org_simgrid_msg_VM
+ * Method                      isMigrating
+ * Signature   ()B
+ */
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isMigrating(JNIEnv *env, jobject jvm);
 /**
  * Class                       org_simgrid_msg_VM
  * Method                      isSuspended
  * Signature   ()B
  */
-JNIEXPORT jboolean JNICALL
+JNIEXPORT jint JNICALL
 Java_org_simgrid_msg_VM_isSuspended(JNIEnv *env, jobject jvm);
 /**
  * Class                       org_simgrid_msg_VM
- * Method                      isRunning
+ * Method                      isResuming
  * Signature   ()B
  */
-JNIEXPORT jboolean JNICALL
-Java_org_simgrid_msg_VM_isRunning(JNIEnv *env, jobject jvm);
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isResuming(JNIEnv *env, jobject jvm);
+/**
+ * Class                       org_simgrid_msg_VM
+ * Method                      isSuspended
+ * Signature   ()B
+ */
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isSaving(JNIEnv *env, jobject jvm);
 /**
  * Class                       org_simgrid_msg_VM
- * Method                      bind
- * Signature   (Lorg/simgrid/msg/Process;)V
+ * Method                      isSave
+ * Signature   ()B
+ */
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isSaved(JNIEnv *env, jobject jvm);
+/**
+ * Class                       org_simgrid_msg_VM
+ * Method                      isResuming
+ * Signature   ()B
+ */
+JNIEXPORT jint JNICALL
+Java_org_simgrid_msg_VM_isRestoring(JNIEnv *env, jobject jvm);
+/**
+ * Class                       org_simgrid_msg_VM
+ * Method                      setBound
+ * Signature   ()B
+ */
+JNIEXPORT void JNICALL
+Java_org_simgrid_msg_VM_setBound(JNIEnv *env, jobject jvm, jint load); 
+
+/**
+ * Class            org_simgrid_msg_VM
+ * Method           create
+ * Signature    ()V
  */
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_bind(JNIEnv *env, jobject jvm, jobject jprocess);
+Java_org_simgrid_msg_VM_create(JNIEnv *env, jobject jvm, jobject jhost, jstring jname,
+                              jint jncore, jint jramsize, jint jnetcap, jstring jdiskpath, jint jdisksize, jint dprate, jint mig_netspeed);
+
+/**
+ * Class            org_simgrid_msg_VM
+ * Method           destroy
+ * Signature    ()V
+ */
+JNIEXPORT void JNICALL
+Java_org_simgrid_msg_VM_destroy(JNIEnv *env, jobject jvm);
 /**
  * Class                       org_simgrid_msg_VM
- * Method                      unbind
- * Signature   (Lorg/simgrid/msg/Process;)V
+ * Method                      start
+ * Signature   (I)V
  */
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_unbind(JNIEnv *env, jobject jvm, jobject jprocess);
+Java_org_simgrid_msg_VM_start(JNIEnv *env, jobject jvm);
 /**
  * Class                       org_simgrid_msg_VM
- * Method                      migrate
+ * Method                      nativeMigrate
  * Signature   (Lorg/simgrid/msg/Host;)V
  */
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_migrate(JNIEnv *env, jobject jvm, jobject jhost);
+Java_org_simgrid_msg_VM_internalmig(JNIEnv *env, jobject jvm, jobject jhost);
 /**
  * Class                       org_simgrid_msg_VM
  * Method                      suspend
@@ -94,11 +140,18 @@ JNIEXPORT void JNICALL
 Java_org_simgrid_msg_VM_shutdown(JNIEnv *env, jobject jvm);
 /**
  * Class            org_simgrid_msg_VM
- * Method           reboot
+ * Method           save
+ * Signature    ()V
+ */
+JNIEXPORT void JNICALL
+Java_org_simgrid_msg_VM_save(JNIEnv *env, jobject jvm);
+/**
+ * Class            org_simgrid_msg_VM
+ * Method           save
  * Signature    ()V
  */
 JNIEXPORT void JNICALL
-Java_org_simgrid_msg_VM_reboot(JNIEnv *env, jobject jvm);
+Java_org_simgrid_msg_VM_restore(JNIEnv *env, jobject jvm);
 
 JNIEXPORT jobject JNICALL
 Java_org_simgrid_msg_VM_get_pm(JNIEnv *env, jobject jvm);
index fc48cba..c629598 100644 (file)
@@ -53,7 +53,7 @@ public class Host {
        /**
         * Host name
         */
-       private String name;
+       protected String name;
 
        /**
         * User data.
@@ -66,6 +66,11 @@ public class Host {
                this.bind = 0;
                this.data = null;
        };
+       
+       public String toString (){
+               return this.name; 
+               
+       }
 
        /**
         * This static method gets an host instance associated with a native
@@ -123,6 +128,7 @@ public class Host {
        public String getName() {
                return name;
        }
+
        /**
         * Sets the data of the host.
      * @param data
@@ -148,6 +154,17 @@ public class Host {
                return null != this.data;
        }
 
+       /**
+        * This method start the host if it is off
+        */ 
+       public native void on();
+
+       /**
+        * This method stop the host if it is on
+        */ 
+       public native void off();
+
+
        /**
         * This method returns the number of tasks currently running on a host.
         * The external load is not taken in account.
@@ -177,11 +194,13 @@ public class Host {
         * Returns the value of a given host property. 
         */
        public native String getProperty(String name);
+       
        /**
         * Change the value of a given host property. 
         */
        public native void setProperty(String name, String value);
-    /** This method tests if a host is available.
+    
+       /** This method tests if a host is available.
      * @return True if the host is available.
      */
        public native boolean isAvail();
index 319aee6..11784df 100644 (file)
@@ -168,6 +168,11 @@ public class Task {
      * @throws TaskCancelledException
      */
        public native void execute() throws HostFailureException,TaskCancelledException;
+       /**
+        * Bound a computation to a certain load
+        *
+        */
+       public native void setBound(double load); 
        /**
         * Cancels a task.
         *
index 5c9c8e3..7b73404 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * JNI interface to Cloud interface in Simgrid
+ * JNI interface to virtual machine in Simgrid
  * 
  * Copyright (c) 2006-2013. The SimGrid Team.
  * All right reserved. 
@@ -13,61 +13,154 @@ package org.simgrid.msg;
 import org.simgrid.msg.Host;
 import org.simgrid.msg.Process;
 
-public class VM {
-       /**
-        * This attribute represents a bind between a java task object and
-        * a native task. Even if this attribute is public you must never
-        * access to it. It is set automatically during the build of the object.
-        */
-       private long bind = 0;
+public class VM extends Host{
+       // Please note that we are not declaring a new bind variable 
+       //(the bind variable has been inherited from the super class Host)
+       
+       /* Static functions */ 
+       // GetByName is inherited from the super class Host
        
-       private int coreAmount;
 
-        private String name;
+        private static VM[] vms=null;    
+    private Host currentHost; 
+
+       /* Constructors / destructors */
+    /**
+        * Create a `basic' VM (i.e. 1 core, 1GB of RAM, other values are not taken into account).
+        */
+       public VM(Host host, String name) {
+               this(host,name,1,1024, -1, null, -1,0 , 0);
+       }
+
        /**
-        * Create a new empty VM.
-        * NOTE: it is expected that in the future, the coreAmount parameter will be used
-        * to add extra constraints on the execution, but the argument is ignored for now.
+        * Create a  VM
+        * @param host, Host node
+        * @param name, name of the machine
+        * @param nCore, number of core
+        * @param ramSize, size of the RAM that should be allocated (in MBytes) 
+        * @param netCap (not used for the moment)
+        * @param diskPath (not used for the moment)
+        * @param diskSize (not used for the moment)
+        * @param migNetSpeed (network bandwith allocated for migrations in MB/s, if you don't know put zero ;))
+        * @param dpIntensity (dirty page percentage according to migNetSpeed, [0-100], if you don't know put zero ;))
         */
-       public VM(Host host, String name, int coreAmount) {
-               this.coreAmount = coreAmount;
-               this.name = name;
-               start(host,name,coreAmount);
+       
+       public VM(Host host, String name, int nCore,  int ramSize, 
+                       int netCap, String diskPath, int diskSize, int migNetSpeed, int dpIntensity){
+               super();
+               super.name = name; 
+               this.currentHost = host; 
+               create(host, name, nCore, ramSize, netCap, diskPath, diskSize, migNetSpeed, dpIntensity);
+               VM.addVM(this);
+       }
+
+       private static void addVM(VM vm){
+               VM[] vmsN=null; 
+               int i=0;
+               if(VM.vms == null)
+                       vmsN = new VM[1]; 
+               else
+                       vmsN = new VM[vms.length+1]; 
+               
+               for (i=0; i<vmsN.length-1 ; i ++){
+                       vmsN[i]=vms[i]; 
+               } 
+               vmsN[i]=vm;
+               vms=vmsN;
+       }
+   public static VM[] all(){
+               return vms;
+       }
+       public static VM getVMByName(String name){
+               for (int i=0 ; i < vms.length ; i++){
+                         if (vms[i].getName().equals(name))
+                                       return vms[i];          
+               }
+               return null; 
        }
        protected void finalize() {
                destroy();
        }
-       /**
-        * Destroy the VM
-        */
-       protected native void destroy();
-       /**
-        * Natively implemented method starting the VM.
-        * @param coreAmount
-        */
-       private native void start(Host host, String name, int coreAmount);
-               
+       
+
+       /* JNI / Native code */
+
+       /* get/set property methods are inherited from the Host class. */
+       
        /** Returns whether the given VM is currently suspended
         */     
-       public native boolean isSuspended();
+       public native int isCreated();
+       
        /** Returns whether the given VM is currently running
         */
-       public native boolean isRunning();
-       /** Add the given process into the VM.
-        * Afterward, when the VM is migrated or suspended or whatever, the process will have the corresponding handling, too.
-        */     
-       public native void bind(Process process);
-       /** Removes the given process from the given VM, and kill it
-        *  Will raise a ProcessNotFound exception if the process were not bound to that VM
+       public native int isRunning();
+
+       /** Returns whether the given VM is currently running
+        */
+       public native int isMigrating();
+       
+       /** Returns whether the given VM is currently suspended
         */     
-       public native void unbind(Process process);
-       /** Immediately change the host on which all processes are running
-        *
-        * No migration cost occurs. If you want to simulate this too, you want to use a
-        * Task.send() before or after, depending on whether you want to do cold or hot
-        * migration.
+       public native int isSuspended();
+               
+       /** Returns whether the given VM is currently saving
+        */
+       public native int isSaving();
+       
+       /** Returns whether the given VM is currently saved
+        */
+       public native int isSaved();
+
+       /** Returns whether the given VM is currently restoring its state
+        */
+       public native boolean isRestoring();
+       
+       /**
+        * Natively implemented method create the VM.
+        * @param nCore, number of core
+        * @param ramSize, size of the RAM that should be allocated (in MB) 
+        * @param netCap (not used for the moment)
+        * @param diskPath (not used for the moment)
+        * @param diskSize (not used for the moment)
+        * @param migNetSpeed (network bandwith allocated for migrations in MB/s, if you don't know put zero ;))
+        * @param dpIntensity (dirty page intensity, a percentage of migNetSpeed [0-100],  if you don't know put zero ;))
+        */
+       private native void create(Host host, String name, int nCore, int ramSize, 
+                        int netCap, String diskPath, int diskSize, int migNetSpeed, int dpIntensity);
+
+
+       /**
+        * Bound the VM to a certain % of its vcpu capability (e.g. 75% of vm.getSpeed())
+        * @param load, percentage (between [0,100]
+        */
+       public native void setBound(int load);
+
+       /**
+        * start the VM
+        */
+       public native void start();
+
+       
+       /**
+        * Immediately kills all processes within the given VM. Any memory that they allocated will be leaked.
+        * No extra delay occurs. If you want to simulate this too, you want to use a MSG_process_sleep() or something
+        */
+       public native void shutdown();
+       
+       /**  
+        * Invoke native migration routine
+       */
+       public native void internalmig(Host destination);
+
+       
+       /** Change the host on which all processes are running
+        * (pre-copy is implemented)
         */     
-       public native void migrate(Host destination);
+       public void migrate(Host destination){
+               this.internalmig(destination);
+               this.currentHost = destination; 
+       }
+       
        /** Immediately suspend the execution of all processes within the given VM
         *
         * No suspension cost occurs. If you want to simulate this too, you want to
@@ -75,6 +168,7 @@ public class VM {
         * of VM suspend to you.
         */     
        public native void suspend();
+       
        /** Immediately resumes the execution of all processes within the given VM
         *
         * No resume cost occurs. If you want to simulate this too, you want to
@@ -82,19 +176,33 @@ public class VM {
         * of VM resume to you.
         */
        public native void resume();
-       /**
-        * Immediately kills all processes within the given VM. Any memory that they allocated will be leaked.
-        * No extra delay occurs. If you want to simulate this too, you want to use a MSG_process_sleep() or something
+       
+       /** Immediately suspend the execution of all processes within the given VM 
+        *  and save its state on the persistent HDD
+        *  Not yet implemented (for the moment it behaves like suspend)
+        *  No suspension cost occurs. If you want to simulate this too, you want to
+        *  use a \ref File.write() before or after, depending on the exact semantic
+        *  of VM suspend to you.
+        */     
+       public native void save();
+       
+       /** Immediately resumes the execution of all processes previously saved 
+        * within the given VM
+        *  Not yet implemented (for the moment it behaves like resume)
+        *
+        * No resume cost occurs. If you want to simulate this too, you want to
+        * use a \ref File.read() before or after, depending on the exact semantic
+        * of VM resume to you.
         */
-       public native void shutdown();
+       public native void restore();
+       
+
        /**
-        * Reboot the VM, restarting all the processes in it.
+        * Destroy the VM
         */
-       public native void reboot();
+       public native void destroy();
 
-       public String getName() {
-               return name;
-       }               
+       
 
        /**
         * Class initializer, to initialize various JNI stuff
index 6d4e75c..9071f64 100644 (file)
@@ -111,18 +111,23 @@ static void* smx_ctx_java_thread_run(void *data) {
     (*env)->SetLongField(env, context->jprocess, jprocess_field_Process_bind,
                          (intptr_t)process);
   }
-  xbt_assert((context->jprocess != NULL), "Process not created...");
-  //wait for the process to be able to begin
-  //TODO: Cache it
+
+  // Adrien, ugly path, just to bypass creation of context at low levels
+  // (i.e such as for the VM migration for instance)
+  if(context->jprocess != NULL){
+       xbt_assert((context->jprocess != NULL), "Process not created...");
+       //wait for the process to be able to begin
+       //TODO: Cache it
        jfieldID jprocess_field_Process_startTime = jxbt_get_sfield(env, "org/simgrid/msg/Process", "startTime", "D");
-  jdouble startTime =  (*env)->GetDoubleField(env, context->jprocess, jprocess_field_Process_startTime);
-  if (startTime > MSG_get_clock()) {
-       MSG_process_sleep(startTime - MSG_get_clock());
+       jdouble startTime =  (*env)->GetDoubleField(env, context->jprocess, jprocess_field_Process_startTime);
+       if (startTime > MSG_get_clock()) {
+               MSG_process_sleep(startTime - MSG_get_clock());
+       }
+       //Execution of the "run" method.
+       jmethodID id = jxbt_get_smethod(env, "org/simgrid/msg/Process", "run", "()V");
+       xbt_assert( (id != NULL), "Method not found...");
+       (*env)->CallVoidMethod(env, context->jprocess, id);
   }
-  //Execution of the "run" method.
-  jmethodID id = jxbt_get_smethod(env, "org/simgrid/msg/Process", "run", "()V");
-  xbt_assert( (id != NULL), "Method not found...");
-  (*env)->CallVoidMethod(env, context->jprocess, id);
   smx_ctx_java_stop((smx_context_t)context);
 
   return NULL;
index 9e33f3c..f0184b1 100644 (file)
@@ -184,7 +184,7 @@ static int l_host_sleep(lua_State *L)
 static int l_host_destroy(lua_State *L)
 {
   msg_host_t ht = sglua_check_host(L, 1);
-  __MSG_host_destroy(MSG_host_priv(ht));
+  __MSG_host_priv_free(MSG_host_priv(ht));
   return 0;
 }
 
index 52664c7..0f5c429 100644 (file)
@@ -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
index 2ecc52a..7091f04 100644 (file)
@@ -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 <config>s, if any, and before <AS> or friends such as <cluster>)
index e4142a9..3d01e63 100644 (file)
@@ -9,6 +9,11 @@
 /*******************************************/
 /*** Config Globals **************************/
 /*******************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 XBT_PUBLIC_DATA(xbt_cfg_t) _sg_cfg_set;
 XBT_PUBLIC_DATA(int) _sg_cfg_init_status;
 XBT_PUBLIC_DATA(int) _sg_cfg_exit_asap;
@@ -21,3 +26,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
index 31375cd..3dd00e0 100644 (file)
@@ -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,8 +21,8 @@ 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_storage *surf_storage_t;
 typedef struct surf_stat *surf_stat_t;
 
index acd57fb..e4e67c5 100644 (file)
@@ -31,6 +31,10 @@ 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);
 
@@ -51,6 +55,8 @@ 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_shrink(lmm_system_t sys, lmm_constraint_t cnst,
+                            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,
@@ -127,5 +133,8 @@ 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 */
index e59ba76..97bdd57 100644 (file)
@@ -35,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 */
@@ -43,6 +42,82 @@ typedef enum {
   SURF_NETWORK_ELEMENT_AS       /* AS type */
 } e_surf_network_element_type_t;
 
+#ifdef __cplusplus
+class Model;
+class CpuModel;
+class WorkstationModel;
+class WorkstationVMModel;
+class NetworkCm02Model;
+class StorageModel;
+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 WorkstationVMModel WorkstationVMModel;
+typedef struct NetworkCm02Model NetworkCm02Model;
+typedef struct StorageModel StorageModel;
+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 WorkstationVMModel *surf_vm_workstation_model_t;
+
+typedef NetworkCm02Model *surf_network_model_t;
+typedef StorageModel *surf_storage_model_t;
+
+typedef xbt_dictelm_t surf_resource_t;
+typedef Resource *surf_cpp_resource_t;
+typedef WorkstationCLM03 *surf_workstation_CLM03_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);
 
@@ -72,58 +147,6 @@ 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
  *
@@ -131,6 +154,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      */
@@ -141,228 +165,60 @@ 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;
-XBT_PUBLIC_DATA(routing_platf_t) routing_platf;
-
-/*******************************************
- *  TUTORIAL: New model
- *  New model extension public
- *  Public functions specific to a New model.
- */
-typedef struct surf_new_model_extension_public {
-  surf_action_t(*fct) ();
-  void* (*create_resource) ();
-} s_surf_model_extension_new_model_t;
-/*******************************************/
+/* FIXME: Where should the VM state be defined? */
+typedef enum {
+  /* created, but not yet started */
+  SURF_VM_STATE_CREATED,
 
-/** \ingroup SURF_models
- *  \brief Private data available on all models
- */
-typedef struct surf_model_private *surf_model_private_t;
-
-     /* Cpu model */
-
-     /** \ingroup SURF_models
-      *  \brief CPU model extension public
-      *
-      *  Public functions specific to the CPU model.
-      */
-typedef struct surf_cpu_model_extension_public {
-  surf_action_t(*execute) (void *cpu, double size);
-  surf_action_t(*sleep) (void *cpu, double duration);
-  e_surf_resource_state_t(*get_state) (void *cpu);
-  int (*get_core) (void *cpu);
-  double (*get_speed) (void *cpu, double load);
-  double (*get_available_speed) (void *cpu);
-  double (*get_current_power_peak) (void *cpu);
-  double (*get_power_peak_at) (void *cpu, int pstate_index);
-  int (*get_nb_pstates) (void *cpu);
-  void (*set_power_peak_at) (void *cpu, int pstate_index);
-  double (*get_consumed_energy) (void *cpu);
-  void (*add_traces) (void);
-} s_surf_model_extension_cpu_t;
-
-     /* Network model */
-
-     /** \ingroup SURF_models
-      *  \brief Network model extension public
-      *
-      *  Public functions specific to the network model
-      */
-typedef struct surf_network_model_extension_public {
-  surf_action_t (*communicate) (sg_routing_edge_t src,
-                                sg_routing_edge_t dst,
-                                double size, double rate);
-  xbt_dynar_t(*get_route) (void *src, void *dst); //FIXME: kill field? That is done by the routing nowadays
-  double (*get_link_bandwidth) (const void *link);
-  double (*get_link_latency) (const void *link);
-  int (*link_shared) (const void *link);
-  void (*add_traces) (void);
-} s_surf_model_extension_network_t;
-
-/* Storage model */
+  SURF_VM_STATE_RUNNING,
+  SURF_VM_STATE_MIGRATING,
 
-/** \ingroup SURF_models
- *  \brief Storage model extension public
- *
- *  Public functions specific to the Storage model.
- */
-
-typedef struct surf_storage_model_extension_public {
-  surf_action_t(*open) (void *storage, const char* mount, const char* path);
-  surf_action_t(*close) (void *storage, surf_file_t fd);
-  surf_action_t(*read) (void *storage, surf_file_t fd, sg_storage_size_t size);
-  surf_action_t(*write) (void *storage, surf_file_t fd, sg_storage_size_t size);
-  surf_action_t(*stat) (void *storage, surf_file_t fd);
-  surf_action_t(*ls) (void *storage, const char *path);
-  xbt_dict_t(*get_properties) (const void *storage);
-  void (*rename) (void *storage, const char *src, const char *dest);
-  xbt_dict_t(*get_content) (void *storage);
-  sg_storage_size_t(*get_size) (void *storage);
-} s_surf_model_extension_storage_t;
-
-     /** \ingroup SURF_models
-      *  \brief Workstation model extension public
-      *
-      *  Public functions specific to the workstation model.
-      */
-typedef struct surf_workstation_model_extension_public {
-  surf_action_t(*execute) (void *workstation, double size);                                /**< Execute a computation amount on a workstation
-                                      and create the corresponding action */
-  surf_action_t(*sleep) (void *workstation, double duration);                              /**< Make a workstation sleep during a given duration */
-  e_surf_resource_state_t(*get_state) (void *workstation);                                      /**< Return the CPU state of a workstation */
-
-  int (*get_core) (void *workstation); 
-  double (*get_speed) (void *workstation, double load);                                    /**< Return the speed of a workstation */
-  double (*get_available_speed) (void *workstation);                                       /**< Return tha available speed of a workstation */
-
-  double (*get_current_power_peak) (void *workstation);                                          /**< Return the current CPU speed of a workstation */
-  double (*get_power_peak_at) (void *workstation, int pstate_index);                     /**< Return the speed of a workstation for a specific pstate,
-                                                                                                (where higher pstate values represent lower processor speeds) */
-  int (*get_nb_pstates) (void *workstation);                                             /**< Return the number of pstates defined for a workstation (default is 1) */
-  void (*set_power_peak_at) (void *workstation, int pstate_index);                       /**< Set the processor speed of a workstation to the speed associated with the pstate_index pstate */
-  double (*get_consumed_energy) (void *workstation);                                     /**< Return the total energy consumed by a workstation */
-
-   surf_action_t(*communicate) (void *workstation_src,                                     /**< Execute a communication amount between two workstations */
-                                void *workstation_dst, double size,
-                                double max_rate);
-   // FIXME: kill next field, which duplicates the routing
-   xbt_dynar_t(*get_route) (void *workstation_src, void *workstation_dst);                 /**< Get the list of links between two ws */
-
-   surf_action_t(*execute_parallel_task) (int workstation_nb,                              /**< Execute a parallel task on several workstations */
-                                          void **workstation_list,
-                                          double *computation_amount,
-                                          double *communication_amount,
-                                          double rate);
-  double (*get_link_bandwidth) (const void *link);                                         /**< Return the current bandwidth of a network link */
-  double (*get_link_latency) (const void *link);                                           /**< Return the current latency of a network link */
-  surf_action_t(*open) (void *workstation, const char* storage,
-                        const char* path);
-  surf_action_t(*close) (void *workstation, surf_file_t fd);
-  surf_action_t(*read) (void *workstation, surf_file_t fd, sg_storage_size_t size);
-  surf_action_t(*write) (void *workstation, surf_file_t fd, sg_storage_size_t size);
-  surf_action_t(*stat) (void *workstation, surf_file_t fd);
-  int(*unlink) (void *workstation, surf_file_t fd);
-  surf_action_t(*ls) (void *workstation, const char* mount, const char *path);
-  sg_storage_size_t (*get_size) (void *workstation, surf_file_t fd);
-  xbt_dynar_t (*get_info) (void *workstation, surf_file_t fd);
-  int (*link_shared) (const void *link);
-  xbt_dict_t(*get_properties) (const void *resource);
-  void (*add_traces) (void);
-
-  sg_storage_size_t (*get_free_size) (void *workstation,const char* name);
-  sg_storage_size_t (*get_used_size) (void *workstation,const char* name);
-  xbt_dict_t (*get_storage_list) (void *workstation);
-
-} s_surf_model_extension_workstation_t;
+  /* Suspend/resume does not involve disk I/O, so we assume there is no transition states. */
+  SURF_VM_STATE_SUSPENDED,
 
+  /* Save/restore involves disk I/O, so there should be transition states. */
+  SURF_VM_STATE_SAVING,
+  SURF_VM_STATE_SAVED,
+  SURF_VM_STATE_RESTORING,
 
+} e_surf_vm_state_t;
 
+typedef struct ws_params {
+  int ncpus;
+  long ramsize;
+  int overcommit;
 
-/** \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
+  /* The size of other states than memory pages, which is out-of-scope of dirty
+   * page tracking. */
+  long devsize;
+  int skip_stage1;
+  int skip_stage2;
+  double max_downtime;
 
-  void (*gap_remove) (surf_action_lmm_t action);
+  double dp_rate;
+  double dp_cap; /* bytes per 1 flop execution */
 
-  surf_model_private_t model_private;
+  double xfer_cpu_overhead;
+  double dpt_cpu_overhead;
 
-  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;
+  /* set migration speed */
+  double mig_speed;
+} s_ws_params_t, *ws_params_t;
 
-surf_model_t surf_model_init(void);
-void surf_model_exit(surf_model_t model);
+/***************************/
+/* Generic model object */
+/***************************/
+//FIXME:REMOVE typedef struct s_routing_platf s_routing_platf_t, *routing_platf_t;
+XBT_PUBLIC_DATA(routing_platf_t) routing_platf;
 
 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 *storage){
-  return xbt_lib_get_level((void *)storage, SURF_STORAGE_LEVEL);
+  return (void*)xbt_lib_get_level((xbt_dictelm_t)storage, SURF_STORAGE_LEVEL);
 }
 
 static inline void *surf_cpu_resource_by_name(const char *name) {
@@ -375,29 +231,93 @@ 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;
-  void_f_pvoid_t free_f;
-} 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
+char *surf_routing_edge_name(sg_routing_edge_t edge);
+void *surf_as_cluster_get_backbone(AS_t as);
+void surf_as_cluster_set_backbone(AS_t as, void* backbone);
+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_resource_t src, surf_resource_t dst, double size, double rate);
+xbt_dynar_t surf_workstation_model_get_route(surf_workstation_model_t model, surf_resource_t src, surf_resource_t dst);
+void surf_vm_workstation_model_create(const char *name, surf_resource_t ind_phys_host);
+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_cpp_resource_t resource);
+xbt_dict_t surf_resource_get_properties(surf_cpp_resource_t resource);
+e_surf_resource_state_t surf_resource_get_state(surf_cpp_resource_t resource);
+void surf_resource_set_state(surf_cpp_resource_t resource, e_surf_resource_state_t state);
+double surf_workstation_get_speed(surf_resource_t resource, double load);
+double surf_workstation_get_available_speed(surf_resource_t resource);
+int surf_workstation_get_core(surf_resource_t resource);
+surf_action_t surf_workstation_execute(surf_resource_t resource, double size);
+surf_action_t surf_workstation_sleep(surf_resource_t resource, double duration);
+surf_action_t surf_workstation_open(surf_resource_t workstation, const char* mount, const char* path);
+surf_action_t surf_workstation_close(surf_resource_t workstation, surf_file_t fd);
+surf_action_t surf_workstation_read(surf_resource_t resource, surf_file_t fd, sg_storage_size_t size);
+surf_action_t surf_workstation_write(surf_resource_t resource, surf_file_t fd, sg_storage_size_t size);
+xbt_dynar_t surf_workstation_get_info(surf_resource_t resource, surf_file_t fd);
+sg_storage_size_t surf_workstation_get_free_size(surf_resource_t resource, const char* name);
+sg_storage_size_t surf_workstation_get_used_size(surf_resource_t resource, const char* name);
+xbt_dynar_t surf_workstation_get_vms(surf_resource_t resource);
+void surf_workstation_get_params(surf_resource_t resource, ws_params_t params);
+void surf_workstation_set_params(surf_resource_t resource, ws_params_t params);
+void surf_vm_workstation_destroy(surf_resource_t resource);
+void surf_vm_workstation_suspend(surf_resource_t resource);
+void surf_vm_workstation_resume(surf_resource_t resource);
+void surf_vm_workstation_save(surf_resource_t resource);
+void surf_vm_workstation_restore(surf_resource_t resource);
+void surf_vm_workstation_migrate(surf_resource_t resource, surf_resource_t ind_vm_ws_dest);
+surf_resource_t surf_vm_workstation_get_pm(surf_resource_t resource);
+void surf_vm_workstation_set_bound(surf_resource_t resource, double bound);
+void surf_vm_workstation_set_affinity(surf_resource_t resource, surf_resource_t cpu, unsigned long mask);
+surf_action_t surf_cpu_execute(surf_resource_t cpu, double size);
+surf_action_t surf_cpu_sleep(surf_resource_t cpu, double duration);
+double surf_workstation_get_current_power_peak(surf_resource_t host);
+double surf_workstation_get_power_peak_at(surf_resource_t host, int pstate_index);
+int surf_workstation_get_nb_pstates(surf_resource_t host);
+void surf_workstation_set_power_peak_at(surf_resource_t host, int pstate_index);
+double surf_workstation_get_consumed_energy(surf_resource_t host);
+xbt_dict_t surf_workstation_get_storage_list(surf_resource_t workstation);
+int surf_workstation_unlink(surf_resource_t workstation, surf_file_t fd);
+surf_action_t surf_workstation_ls(surf_resource_t workstation, const char* mount, const char *path);
+size_t surf_workstation_get_size(surf_resource_t workstation, surf_file_t fd);
+int surf_network_link_is_shared(surf_cpp_resource_t link);
+double surf_network_link_get_bandwidth(surf_cpp_resource_t link);
+double surf_network_link_get_latency(surf_cpp_resource_t link);
+xbt_dict_t surf_storage_get_content(surf_resource_t resource);
+sg_storage_size_t surf_storage_get_size(surf_resource_t resource);
+void surf_storage_rename(surf_resource_t resource, const char* src, const char* dest);
+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);
+void surf_cpu_action_set_affinity(surf_action_t action, surf_resource_t cpu, unsigned long mask);
+void surf_cpu_action_set_bound(surf_action_t action, double bound);
+surf_file_t surf_storage_action_get_file(surf_action_t action);
+xbt_dict_t surf_storage_action_get_ls_dict(surf_action_t action);
+surf_model_t surf_resource_model(const void *host, int level);
+#ifdef __cplusplus
+}
+#endif
 
 /**************************************/
 /* Implementations of model object */
@@ -405,9 +325,15 @@ typedef struct surf_resource_lmm {
 
 
 /** \ingroup SURF_models
- *  \brief The CPU model
+ *  \brief The CPU model object for the physical machine layer
+ */
+XBT_PUBLIC_DATA(surf_cpu_model_t) surf_cpu_model_pm;
+
+/** \ingroup SURF_models
+ *  \brief The CPU model object for the virtual machine layer
  */
-XBT_PUBLIC_DATA(surf_model_t) surf_cpu_model;
+XBT_PUBLIC_DATA(surf_cpu_model_t) surf_cpu_model_vm;
+
 
 /** \ingroup SURF_models
  *  \brief Initializes the CPU model with the model Cas01
@@ -452,7 +378,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.
@@ -588,7 +514,7 @@ XBT_PUBLIC(void) surf_storage_model_init_default(void);
  */
 XBT_PUBLIC_DATA(s_surf_model_description_t) surf_storage_model_description[];
 
-XBT_PUBLIC_DATA(surf_model_t) surf_storage_model;
+XBT_PUBLIC_DATA(surf_storage_model_t) surf_storage_model;
 
 /** \ingroup SURF_models
  *  \brief The workstation model
@@ -598,7 +524,17 @@ XBT_PUBLIC_DATA(surf_model_t) surf_storage_model;
  *  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 The vm_workstation model
+ *
+ *  Note that when you create an API on top of SURF,
+ *  the vm_workstation model should be the only one you use
+ *  because depending on the platform model, the network model and the CPU model
+ *  may not exist.
+ */
+XBT_PUBLIC_DATA(surf_vm_workstation_model_t) surf_vm_workstation_model;
 
 /** \ingroup SURF_models
  *  \brief Initializes the platform with a compound workstation model
@@ -637,17 +573,31 @@ XBT_PUBLIC(void) surf_workstation_model_init_ptask_L07(void);
 XBT_PUBLIC_DATA(s_surf_model_description_t)
     surf_workstation_model_description[];
 
-/*******************************************
- *  TUTORIAL: New model
+/** \ingroup SURF_models
+ *  \brief Initializes the platform with the current best network and cpu models at hand
+ *
+ *  This platform model seperates the workstation model and the network model.
+ *  The workstation model will be initialized with the model compound, the network
+ *  model with the model LV08 (with cross traffic support) and the CPU model with
+ *  the model Cas01.
+ *  Such model is subject to modification with warning in the ChangeLog so monitor it!
+ *
+ */
+XBT_PUBLIC(void) surf_vm_workstation_model_init_current_default(void);
+
+/** \ingroup SURF_models
+ *  \brief The list of all available vm workstation model models
  */
-XBT_PUBLIC(void) surf_new_model_init_default(void);
-XBT_PUBLIC_DATA(s_surf_model_description_t) surf_new_model_description[];
+XBT_PUBLIC_DATA(s_surf_model_description_t)
+    surf_vm_workstation_model_description[];
+
 /*******************************************/
 
 /** \ingroup SURF_models
  *  \brief List of initialized models
  */
 XBT_PUBLIC_DATA(xbt_dynar_t) model_list;
+XBT_PUBLIC_DATA(xbt_dynar_t) model_list_invoke;
 
 /** \ingroup SURF_simulation
  *  \brief List of hosts that have juste restarted and whose autorestart process should be restarted.
@@ -662,13 +612,20 @@ XBT_PUBLIC(xbt_dict_t) watched_hosts_lib;
 /*******************************************/
 /*** 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 **************************/
@@ -765,7 +722,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);
index 963fdff..fdc1eb6 100644 (file)
@@ -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, void_f_pvoid_t free_f)
@@ -40,6 +40,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 */
index 44bfeaf..4be9408 100644 (file)
@@ -11,7 +11,7 @@
 #include "surf/trace_mgr.h"
 #include "surf/surf_resource.h"
 
-
+#ifdef TOMATO
 static XBT_INLINE
     surf_resource_lmm_t surf_resource_lmm_new(size_t childsize,
                                               /* for superclass */
@@ -43,7 +43,7 @@ static XBT_INLINE
         tmgr_history_add_trace(history, metric_trace, 0.0, 0, res);
   return res;
 }
-
+#endif
 
 static XBT_INLINE e_surf_resource_state_t surf_resource_lmm_get_state(void
                                                                       *r)
index 85c80a6..3343492 100644 (file)
 #include "surf/datatypes.h"
 #include "simgrid/platf_interface.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Creation functions */
 XBT_PUBLIC(tmgr_history_t) tmgr_history_new(void);
 XBT_PUBLIC(void) tmgr_history_free(tmgr_history_t history);
@@ -43,4 +47,8 @@ XBT_PUBLIC(tmgr_trace_event_t)
 
 XBT_PUBLIC(void) tmgr_finalize(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif                          /* _SURF_TMGR_H */
index 052144c..170ebb1 100644 (file)
@@ -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);
   }
 }
index 2c0fc4b..84e81c2 100644 (file)
@@ -230,6 +230,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, int size);
 
@@ -345,7 +349,6 @@ 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);
 
-
 void print_pajeDefineContainerType(paje_event_t event);
 void print_pajeDefineVariableType(paje_event_t event);
 void print_pajeDefineStateType(paje_event_t event);
@@ -458,6 +461,11 @@ typedef struct s_instr_extra_data {
   int num_processes;
 } s_instr_extra_data_t;
 
+#ifdef __cplusplus
+}
+#endif
+
+
 #endif /* HAVE_TRACING */
 
 #ifdef HAVE_JEDULE
index c72cbfc..d048549 100644 (file)
@@ -13,7 +13,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY (instr_msg_vm, instr, "MSG VM");
 
 char *instr_vm_id (msg_vm_t vm, char *str, int len)
 {
-  return instr_vm_id_2 (vm->name, str, len);
+       return instr_vm_id_2 (MSG_vm_get_name(vm), str, len);
 }
 
 char *instr_vm_id_2 (const char *vm_name, char *str, int len)
@@ -55,7 +55,7 @@ void TRACE_msg_vm_change_host(msg_vm_t vm, msg_host_t old_host, msg_host_t new_h
   }
 }
 
-void TRACE_msg_vm_create (const char *vm_name, msg_host_t host)
+void TRACE_msg_vm_create(const char *vm_name, msg_host_t host)
 {
   if (TRACE_msg_vm_is_enabled()){
     int len = INSTR_DEFAULT_STR_SIZE;
@@ -66,6 +66,20 @@ void TRACE_msg_vm_create (const char *vm_name, msg_host_t host)
   }
 }
 
+void TRACE_msg_vm_start(msg_vm_t vm)
+{
+  if (TRACE_msg_vm_is_enabled()){
+    int len = INSTR_DEFAULT_STR_SIZE;
+    char str[INSTR_DEFAULT_STR_SIZE];
+
+    container_t vm_container = PJ_container_get (instr_vm_id(vm, str, len));
+    type_t type = PJ_type_get ("MSG_VM_STATE", vm_container->type);
+    val_t value = PJ_value_get ("start", type);
+    new_pajePushState (MSG_get_clock(), vm_container, type, value);
+  }
+
+}
+
 void TRACE_msg_vm_kill(msg_vm_t vm) {
   if (TRACE_msg_vm_is_enabled()) {
     int len = INSTR_DEFAULT_STR_SIZE;
@@ -103,7 +117,7 @@ void TRACE_msg_vm_resume(msg_vm_t vm)
   }
 }
 
-void TRACE_msg_vm_sleep_in(msg_vm_t vm)
+void TRACE_msg_vm_save(msg_vm_t vm)
 {
   if (TRACE_msg_vm_is_enabled()){
     int len = INSTR_DEFAULT_STR_SIZE;
@@ -111,12 +125,12 @@ void TRACE_msg_vm_sleep_in(msg_vm_t vm)
 
     container_t vm_container = PJ_container_get (instr_vm_id(vm, str, len));
     type_t type = PJ_type_get ("MSG_VM_STATE", vm_container->type);
-    val_t value = PJ_value_get ("sleep", type);
+    val_t value = PJ_value_get ("save", type);
     new_pajePushState (MSG_get_clock(), vm_container, type, value);
   }
 }
 
-void TRACE_msg_vm_sleep_out(msg_vm_t vm)
+void TRACE_msg_vm_restore(msg_vm_t vm)
 {
   if (TRACE_msg_vm_is_enabled()){
     int len = INSTR_DEFAULT_STR_SIZE;
index d98766c..77ce1e0 100644 (file)
@@ -38,7 +38,6 @@ void MSG_init_nocheck(int *argc, char **argv) {
 
   xbt_getpid = MSG_process_self_PID;
   if (!msg_global) {
-    s_msg_vm_t vm; // to compute the offset
 
     SIMIX_global_init(argc, argv);
     
@@ -50,7 +49,6 @@ void MSG_init_nocheck(int *argc, char **argv) {
     msg_global->sent_msg = 0;
     msg_global->task_copy_callback = NULL;
     msg_global->process_data_cleanup = NULL;
-    msg_global->vms = xbt_swag_new(xbt_swag_offset(vm,all_vms_hookup));
 
     /* initialization of the action module */
     _MSG_action_init();
@@ -71,7 +69,7 @@ void MSG_init_nocheck(int *argc, char **argv) {
 #endif
 
   XBT_DEBUG("ADD MSG LEVELS");
-  MSG_HOST_LEVEL = xbt_lib_add_level(host_lib, (void_f_pvoid_t) __MSG_host_destroy);
+  MSG_HOST_LEVEL = xbt_lib_add_level(host_lib, (void_f_pvoid_t) __MSG_host_priv_free);
   MSG_STORAGE_LEVEL = xbt_lib_add_level(storage_lib, (void_f_pvoid_t) __MSG_storage_destroy);
 
   if(sg_cfg_get_boolean("clean_atexit")) atexit(MSG_exit);
@@ -177,7 +175,6 @@ static void MSG_exit(void) {
   TRACE_end();
 #endif
 
-  xbt_swag_free(msg_global->vms);
   free(msg_global);
   msg_global = NULL;
 }
index 3bdc8d8..fd25739 100644 (file)
@@ -24,7 +24,15 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_gos, msg,
  */
 msg_error_t MSG_task_execute(msg_task_t task)
 {
-  return MSG_parallel_task_execute(task);
+  /* TODO: add this to other locations */
+  msg_host_t host = MSG_process_get_host(MSG_process_self());
+  MSG_host_add_task(host, task);
+
+  msg_error_t ret = MSG_parallel_task_execute(task);
+
+  MSG_host_del_task(host, task);
+
+  return ret;
 }
 
 /** \ingroup msg_task_usage
@@ -75,10 +83,16 @@ msg_error_t MSG_parallel_task_execute(msg_task_t task)
                                                        1.0, -1.0);
       XBT_DEBUG("Parallel execution action created: %p", simdata->compute);
     } else {
+      unsigned long affinity_mask = (unsigned long) xbt_dict_get_or_null_ext(simdata->affinity_mask_db, (char *) p_simdata->m_host, sizeof(msg_host_t));
+      XBT_DEBUG("execute %s@%s with affinity(0x%04lx)", MSG_task_get_name(task), MSG_host_get_name(p_simdata->m_host), affinity_mask);
+
       simdata->compute = simcall_host_execute(task->name,
                                               p_simdata->m_host,
                                               simdata->computation_amount,
-                                              simdata->priority);
+                                              simdata->priority,
+                                              simdata->bound,
+                                              affinity_mask
+                                              );
 
     }
 #ifdef HAVE_TRACING
index 2b797aa..9e45fce 100644 (file)
@@ -29,28 +29,32 @@ XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(msg);
 msg_host_t __MSG_host_create(smx_host_t workstation)
 {
   const char *name = SIMIX_host_get_name(workstation);
-  msg_host_priv_t host = xbt_new0(s_msg_host_priv_t, 1);
-  s_msg_vm_t vm; // simply to compute the offset
-
-  host->vms = xbt_swag_new(xbt_swag_offset(vm,host_vms_hookup));
+  msg_host_priv_t priv = xbt_new0(s_msg_host_priv_t, 1);
 
 #ifdef MSG_USE_DEPRECATED
   int i;
   char alias[MAX_ALIAS_NAME + 1] = { 0 };       /* buffer used to build the key of the mailbox */
 
   if (msg_global->max_channel > 0)
-    host->mailboxes = xbt_new0(msg_mailbox_t, msg_global->max_channel);
+    priv->mailboxes = xbt_new0(msg_mailbox_t, msg_global->max_channel);
 
   for (i = 0; i < msg_global->max_channel; i++) {
     sprintf(alias, "%s:%d", name, i);
 
     /* the key of the mailbox (in this case) is build from the name of the host and the channel number */
-    host->mailboxes[i] = MSG_mailbox_new(alias);
+    priv->mailboxes[i] = MSG_mailbox_new(alias);
     memset(alias, 0, MAX_ALIAS_NAME + 1);
   }
 #endif
 
-  xbt_lib_set(host_lib,name,MSG_HOST_LEVEL,host);
+
+  priv->dp_objs = xbt_dict_new();
+  priv->dp_enabled = 0;
+  priv->dp_updated_by_deleted_tasks = 0;
+
+  priv->affinity_mask_db = xbt_dict_new_homogeneous(NULL);
+
+  xbt_lib_set(host_lib, name, MSG_HOST_LEVEL, priv);
   
   return xbt_lib_get_elm_or_null(host_lib, name);
 }
@@ -114,20 +118,54 @@ msg_host_t MSG_host_self(void)
   return MSG_process_get_host(NULL);
 }
 
+
 /*
- * \brief Destroys a host (internal call only)
+ * \brief Start the host if it is off
+ */
+void MSG_host_on(msg_host_t host)
+{
+  simcall_host_on(host);
+}
+
+/*
+ * \brief Stop the host if it is on
+ */
+void MSG_host_off(msg_host_t host)
+{
+  simcall_host_off(host);
+}
+
+/*
+ * \brief Frees private data of a host (internal call only)
  */
-void __MSG_host_destroy(msg_host_priv_t host) {
+void __MSG_host_priv_free(msg_host_priv_t priv)
+{
+  unsigned int size = xbt_dict_size(priv->dp_objs);
+  if (size > 0)
+    XBT_WARN("dp_objs: %u pending task?", size);
+  xbt_dict_free(&priv->dp_objs);
+  xbt_dict_free(&priv->affinity_mask_db);
 
 #ifdef MSG_USE_DEPRECATED
   if (msg_global->max_channel > 0)
-    free(host->mailboxes);
+    free(priv->mailboxes);
 #endif
-  if (xbt_swag_size(host->vms) > 0 ) {
-    XBT_VERB("Host shut down, but it still hosts %d VMs. They will be leaked.",xbt_swag_size(host->vms));
-  }
-  xbt_swag_free(host->vms);
-  free(host);
+
+  free(priv);
+}
+
+/*
+ * \brief Destroys a host (internal call only)
+ */
+void __MSG_host_destroy(msg_host_t host)
+{
+  const char *name = MSG_host_get_name(host);
+  /* TODO:
+   * What happens if VMs still remain on this host?
+   * Revisit here after the surf layer gets stable.
+   **/
+
+  xbt_lib_unset(host_lib, name, MSG_HOST_LEVEL, 1);
 }
 
 /** \ingroup m_host_management
@@ -280,6 +318,27 @@ int MSG_host_is_avail(msg_host_t host)
   xbt_assert((host != NULL), "Invalid parameters (host is NULL)");
   return (simcall_host_get_state(host));
 }
+/** \ingroup m_host_management
+ * \brief Set the parameters of a given host
+ *
+ * \param host a host
+ * \param params a prameter object
+ */
+void MSG_host_set_params(msg_host_t ind_pm, ws_params_t params)
+{
+  simcall_host_set_params(ind_pm, params);
+}
+
+/** \ingroup m_host_management
+ * \brief Get the parameters of a given host
+ *
+ * \param host a host
+ * \param params a prameter object
+ */
+void MSG_host_get_params(msg_host_t ind_pm, ws_params_t params)
+{
+  simcall_host_get_params(ind_pm, params);
+}
 
 /** \ingroup m_host_management
  * \brief Return the speed of the processor (in flop/s) at a given pstate
index f3e1b89..950c507 100644 (file)
@@ -31,7 +31,12 @@ typedef struct simdata_task {
   msg_process_t receiver;
   msg_host_t source;
   double priority;
-  double rate;
+  double bound; /* Capping for CPU resource */
+  double rate;  /* Capping for network resource */
+
+  /* CPU affinity database of this task */
+  xbt_dict_t affinity_mask_db; /* smx_host_t host => unsigned long mask */
+
   int isused;  /* Indicates whether the task is used in SIMIX currently */
   int host_nb;                  /* ==0 if sequential task; parallel task if not */
   /*******  Parallel Tasks Only !!!! *******/
@@ -73,8 +78,6 @@ typedef struct simdata_process {
   int argc;                     /* arguments number if any */
   msg_error_t last_errno;       /* the last value returned by a MSG_function */
 
-  msg_vm_t vm;                 /* virtual machine the process is in */
-
   void* data;                   /* user data */
 } s_simdata_process_t, *simdata_process_t;
 
@@ -94,21 +97,21 @@ typedef struct msg_comm {
   msg_task_t *task_received;      /* where the task will be received (NULL for the sender) */
   msg_error_t status;           /* status of the communication once finished */
 } s_msg_comm_t;
-/*
-typedef enum {
-  msg_vm_state_suspended, msg_vm_state_running, msg_vm_state_migrating
-} e_msg_vm_state_t;
 
-typedef struct msg_vm {
-  const char *name;
-  s_xbt_swag_hookup_t all_vms_hookup;
-  s_xbt_swag_hookup_t host_vms_hookup;
-  xbt_dynar_t processes;
-  e_msg_vm_state_t state;
-  msg_host_t location;
-  int coreAmount;
-} s_msg_vm_t;
-*/
+
+/******************************* VM *************************************/
+typedef struct dirty_page {
+  double prev_clock;
+  double prev_remaining;
+  msg_task_t task;
+} s_dirty_page, *dirty_page_t;
+
+XBT_PUBLIC_DATA(const char*) MSG_vm_get_property_value(msg_vm_t vm, const char *name);
+XBT_PUBLIC_DATA(xbt_dict_t) MSG_vm_get_properties(msg_vm_t vm);
+XBT_PUBLIC_DATA(void) MSG_vm_set_property_value(msg_vm_t vm, const char *name, void *value, void_f_pvoid_t free_ctn);
+XBT_PUBLIC_DATA(msg_vm_t) MSG_vm_get_by_name(const char *name);
+XBT_PUBLIC_DATA(const char*) MSG_vm_get_name(msg_vm_t vm);
+
 /************************** Global variables ********************************/
 typedef struct MSG_Global {
   xbt_fifo_t host;
@@ -119,7 +122,6 @@ typedef struct MSG_Global {
   unsigned long int sent_msg;   /* Total amount of messages sent during the simulation */
   void (*task_copy_callback) (msg_task_t task, msg_process_t src, msg_process_t dst);
   void_f_pvoid_t process_data_cleanup;
-  xbt_swag_t vms;
 } s_MSG_Global_t, *MSG_Global_t;
 
 /*extern MSG_Global_t msg_global;*/
@@ -142,7 +144,7 @@ XBT_PUBLIC_DATA(MSG_Global_t) msg_global;
 
 msg_host_t __MSG_host_create(smx_host_t workstation);
 msg_storage_t __MSG_storage_create(smx_storage_t storage);
-void __MSG_host_destroy(msg_host_priv_t host);
+void __MSG_host_destroy(msg_host_t host);
 void __MSG_storage_destroy(msg_storage_priv_t host);
 
 void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc);
@@ -157,6 +159,13 @@ void _MSG_action_exit(void);
 
 void MSG_post_create_environment(void);
 
+static inline void *msg_host_resource_priv(const void *host) {
+  return xbt_lib_get_level((void *)host, MSG_HOST_LEVEL);
+}
+
+void MSG_host_add_task(msg_host_t host, msg_task_t task);
+void MSG_host_del_task(msg_host_t host, msg_task_t task);
+
 /********** Tracing **********/
 /* declaration of instrumentation functions from msg_task_instr.c */
 void TRACE_msg_set_task_category(msg_task_t task, const char *category);
@@ -184,16 +193,17 @@ void TRACE_msg_process_sleep_out(msg_process_t process);
 void TRACE_msg_process_end(msg_process_t process);
 
 /* declaration of instrumentation functions from instr_msg_vm.c */
-char *instr_vm_id (msg_vm_t vm, char *str, int len);
-char *instr_vm_id_2 (const char *vm_name, char *str, int len);
+char *instr_vm_id(msg_vm_t vm, char *str, int len);
+char *instr_vm_id_2(const char *vm_name, char *str, int len);
 void TRACE_msg_vm_change_host(msg_vm_t vm, msg_host_t old_host,
                                    msg_host_t new_host);
-void TRACE_msg_vm_create (const char *vm_name, msg_host_t host);
+void TRACE_msg_vm_start(msg_vm_t vm);
+void TRACE_msg_vm_create(const char *vm_name, msg_host_t host);
 void TRACE_msg_vm_kill(msg_vm_t process);
 void TRACE_msg_vm_suspend(msg_vm_t vm);
 void TRACE_msg_vm_resume(msg_vm_t vm);
-void TRACE_msg_vm_sleep_in(msg_vm_t vm);
-void TRACE_msg_vm_sleep_out(msg_vm_t vm);
+void TRACE_msg_vm_save(msg_vm_t vm);
+void TRACE_msg_vm_restore(msg_vm_t vm);
 void TRACE_msg_vm_end(msg_vm_t vm);
 
 SG_END_DECL()
index 2cefbc7..259fb7d 100644 (file)
@@ -50,12 +50,6 @@ void MSG_process_cleanup_from_SIMIX(smx_process_t smx_proc)
     msg_global->process_data_cleanup(msg_proc->data);
   }
 
-  // remove the process from its virtual machine
-  if (msg_proc && msg_proc->vm) {
-    int pos = xbt_dynar_search(msg_proc->vm->processes,&smx_proc);
-    xbt_dynar_remove_at(msg_proc->vm->processes,pos, NULL);
-  }
-
   // free the MSG process
   xbt_free(msg_proc);
 }
index f104387..aee793c 100644 (file)
@@ -5,6 +5,7 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include "msg_private.h"
+#include "simix/smx_private.h"
 #include "xbt/sysdep.h"
 #include "xbt/log.h"
 
@@ -62,6 +63,8 @@ msg_task_t MSG_task_create(const char *name, double compute_duration,
   simdata->receiver = NULL;
   simdata->source = NULL;
   simdata->priority = 1.0;
+  simdata->bound = 0;
+  simdata->affinity_mask_db = xbt_dict_new_homogeneous(NULL);
   simdata->rate = -1.0;
   simdata->isused = 0;
 
@@ -283,6 +286,8 @@ msg_error_t MSG_task_destroy(msg_task_t task)
   /* parallel tasks only */
   xbt_free(task->simdata->host_list);
 
+  xbt_dict_free(&task->simdata->affinity_mask_db);
+
   /* free main structures */
   xbt_free(task->simdata);
   xbt_free(task);
@@ -438,3 +443,111 @@ void MSG_task_set_priority(msg_task_t task, double priority)
     simcall_host_execution_set_priority(task->simdata->compute,
                                       task->simdata->priority);
 }
+
+
+/** \ingroup m_task_management
+ * \brief Changes the maximum CPU utilization of a computation task.
+ *        Unit is flops/s.
+ *
+ * For VMs, there is a pitfall. Please see MSG_vm_set_bound().
+ */
+void MSG_task_set_bound(msg_task_t task, double bound)
+{
+  xbt_assert(task, "Invalid parameter");
+  xbt_assert(task->simdata, "Invalid parameter");
+
+  if (bound == 0)
+    XBT_INFO("bound == 0 means no capping (i.e., unlimited).");
+
+  task->simdata->bound = bound;
+  if (task->simdata->compute)
+    simcall_host_execution_set_bound(task->simdata->compute,
+                                      task->simdata->bound);
+}
+
+
+/** \ingroup m_task_management
+ * \brief Changes the CPU affinity of a computation task.
+ *
+ * When pinning the given task to the first CPU core of the given host, use
+ * 0x01 for the mask value. Each bit of the mask value corresponds to each CPU
+ * core. See taskset(1) on Linux.
+ *
+ * \param task a target task
+ * \param host the host having a multi-core CPU
+ * \param mask the bit mask of a new CPU affinity setting for the task
+ *
+ *
+ * Usage:
+ * 0. Define a host with multiple cores.
+ *    <host id="PM0" power="1E8" core="2"/>
+ *
+ * 1. Pin a given task to the first CPU core of a host.
+ *   MSG_task_set_affinity(task, pm0, 0x01);
+ *
+ * 2. Pin a given task to the third CPU core of a host. Turn on the third bit of the mask.
+ *   MSG_task_set_affinity(task, pm0, 0x04); // 0x04 == 100B
+ *
+ * 3. Pin a given VM to the first CPU core of a host.
+ *   MSG_vm_set_affinity(vm, pm0, 0x01);
+ *
+ * See examples/msg/cloud/multicore.c for more information.
+ *
+ *
+ * Note:
+ * 1. The current code does not allow an affinity of a task to multiple cores.
+ * The mask value 0x03 (i.e., a given task will be executed on the first core
+ * or the second core) is not allowed. The mask value 0x01 or 0x02 works. See
+ * cpu_cas01.c for details.
+ *
+ * 2. It is recommended to first compare simulation results in both the Lazy
+ * and Full calculation modes (using --cfg=cpu/optim:Full or not). Fix
+ * cpu_cas01.c if you find wrong results in the Lazy mode.
+ *
+ */
+void MSG_task_set_affinity(msg_task_t task, msg_host_t host, unsigned long mask)
+{
+  xbt_assert(task, "Invalid parameter");
+  xbt_assert(task->simdata, "Invalid parameter");
+
+  if (mask == 0) {
+    /* 0 means clear */
+    {
+      /* We need remove_ext() not throwing exception. */
+      void *ret = xbt_dict_get_or_null_ext(task->simdata->affinity_mask_db, (char *) host, sizeof(msg_host_t));
+      if (ret != NULL)
+        xbt_dict_remove_ext(task->simdata->affinity_mask_db, (char *) host, sizeof(host));
+    }
+  } else
+    xbt_dict_set_ext(task->simdata->affinity_mask_db, (char *) host, sizeof(host), (void *) mask, NULL);
+
+  /* We set affinity data of this task. If the task is being executed, we
+   * actually change the affinity setting of the task. Otherwise, this change
+   * will be applied when the task is executed. */
+
+  if (!task->simdata->compute) {
+    /* task is not yet executed */
+    XBT_INFO("set affinity(0x%04lx@%s) for %s (not active now)", mask, MSG_host_get_name(host), MSG_task_get_name(task));
+    return;
+  }
+
+  {
+    smx_action_t compute = task->simdata->compute;
+    msg_host_t host_now = compute->execution.host;  // simix_private.h is necessary
+    if (host_now != host) {
+      /* task is not yet executed on this host */
+      XBT_INFO("set affinity(0x%04lx@%s) for %s (not active now)", mask, MSG_host_get_name(host), MSG_task_get_name(task));
+      return;
+    }
+
+    /* task is being executed on this host. so change the affinity now */
+    {
+      /* check it works. remove me if it works. */
+      unsigned long affinity_mask = (unsigned long) xbt_dict_get_or_null_ext(task->simdata->affinity_mask_db, (char *) host, sizeof(msg_host_t));
+      xbt_assert(affinity_mask == mask);
+    }
+
+    XBT_INFO("set affinity(0x%04lx@%s) for %s", mask, MSG_host_get_name(host), MSG_task_get_name(task));
+    simcall_host_execution_set_affinity(task->simdata->compute, host, mask);
+  }
+}
index d5bff35..2f773b2 100644 (file)
@@ -4,6 +4,20 @@
 /* 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. */
 
+// QUESTIONS:
+// 1./ check how and where a new VM is added to the list of the hosts
+// 2./ Diff between SIMIX_Actions and SURF_Actions
+// => SIMIX_actions : point synchro entre processus de niveau (theoretically speaking I do not have to create such SIMIX_ACTION
+// =>  Surf_Actions
+
+// TODO
+//     MSG_TRACE can be revisited in order to use  the host
+//     To implement a mixed model between workstation and vm_workstation,
+//     please give a look at surf_model_private_t model_private at SURF Level and to the share resource functions
+//     double (*share_resources) (double now);
+//     For the action into the vm workstation model, we should be able to leverage the usual one (and if needed, look at
+//             the workstation model.
+
 #include "msg_private.h"
 #include "xbt/sysdep.h"
 #include "xbt/log.h"
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(msg_vm, msg,
                                 "Cloud-oriented parts of the MSG API");
 
-/** @brief Create a new (empty) VMs.
- *  @ingroup msg_VMs
+
+/* **** ******** GENERAL ********* **** */
+
+/** \ingroup m_vm_management
+ * \brief Returns the value of a given vm property
  *
- *  @bug it is expected that in the future, the coreAmount parameter will be used
- *  to add extra constraints on the execution, but the argument is ignored for now.
+ * \param vm a vm
+ * \param name a property name
+ * \return value of a property (or NULL if property not set)
  */
 
-msg_vm_t MSG_vm_start(msg_host_t location, const char *name, int coreAmount) {
-  msg_vm_t res = xbt_new0(s_msg_vm_t,1);
-  res->all_vms_hookup.prev = NULL;
-  res->host_vms_hookup.prev = NULL;
-  res->state = msg_vm_state_running;
-  res->location = location;
-  res->coreAmount = coreAmount;
-  res->name = xbt_strdup(name);
-  res->processes = xbt_dynar_new(sizeof(msg_process_t),NULL);
+const char *MSG_vm_get_property_value(msg_vm_t vm, const char *name)
+{
+  return MSG_host_get_property_value(vm, name);
+}
 
-  xbt_swag_insert(res,msg_global->vms);
-  xbt_swag_insert(res, MSG_host_priv(location)->vms);
+/** \ingroup m_vm_management
+ * \brief Returns a xbt_dict_t consisting of the list of properties assigned to this host
+ *
+ * \param vm a vm
+ * \return a dict containing the properties
+ */
+xbt_dict_t MSG_vm_get_properties(msg_vm_t vm)
+{
+  xbt_assert((vm != NULL), "Invalid parameters (vm is NULL)");
 
-  #ifdef HAVE_TRACING
-  TRACE_msg_vm_create(name, location);
-  #endif
+  return (simcall_host_get_properties(vm));
+}
+
+/** \ingroup m_host_management
+ * \brief Change the value of a given host property
+ *
+ * \param host a host
+ * \param name a property name
+ * \param value what to change the property to
+ * \param free_ctn the freeing function to use to kill the value on need
+ */
+void MSG_vm_set_property_value(msg_vm_t vm, const char *name, void *value, void_f_pvoid_t free_ctn)
+{
+  xbt_dict_set(MSG_host_get_properties(vm), name, value, free_ctn);
+}
 
+/** \ingroup msg_vm_management
+ * \brief Finds a msg_vm_t using its name.
+ *
+ * This is a name directory service
+ * \param name the name of a vm.
+ * \return the corresponding vm
+ *
+ * Please note that a VM is a specific host. Hence, you should give a different name
+ * for each VM/PM.
+ */
 
-  return res;
+msg_vm_t MSG_vm_get_by_name(const char *name)
+{
+       return MSG_get_host_by_name(name);
 }
-/** @brief Returns a newly constructed dynar containing all existing VMs in the system.
- *  @ingroup msg_VMs
+
+/** \ingroup m_vm_management
+ *
+ * \brief Return the name of the #msg_host_t.
  *
- * Don't forget to free the dynar after use.
+ * This functions checks whether \a host is a valid pointer or not and return
+   its name.
  */
-xbt_dynar_t MSG_vms_as_dynar(void) {
-  xbt_dynar_t res = xbt_dynar_new(sizeof(msg_vm_t),NULL);
-  msg_vm_t vm;
-  xbt_swag_foreach(vm,msg_global->vms) {
-    xbt_dynar_push(res,&vm);
-  }
-  return res;
+const char *MSG_vm_get_name(msg_vm_t vm)
+{
+  return MSG_host_get_name(vm);
 }
 
-/** @brief Returns whether the given VM is currently suspended
+
+/* **** Check state of a VM **** */
+static inline int __MSG_vm_is_state(msg_vm_t vm, e_surf_vm_state_t state)
+{
+  return simcall_vm_get_state(vm) == state;
+}
+
+/** @brief Returns whether the given VM has just reated, not running.
  *  @ingroup msg_VMs
  */
-int MSG_vm_is_suspended(msg_vm_t vm) {
-  return vm->state == msg_vm_state_suspended;
+int MSG_vm_is_created(msg_vm_t vm)
+{
+  return __MSG_vm_is_state(vm, SURF_VM_STATE_CREATED);
 }
+
 /** @brief Returns whether the given VM is currently running
  *  @ingroup msg_VMs
  */
-int MSG_vm_is_running(msg_vm_t vm) {
-  return vm->state == msg_vm_state_running;
+int MSG_vm_is_running(msg_vm_t vm)
+{
+  return __MSG_vm_is_state(vm, SURF_VM_STATE_RUNNING);
 }
-/** @brief Add the given process into the VM.
+
+/** @brief Returns whether the given VM is currently migrating
  *  @ingroup msg_VMs
- *
- * Afterward, when the VM is migrated or suspended or whatever, the process will have the corresponding handling, too.
- *
  */
-void MSG_vm_bind(msg_vm_t vm, msg_process_t process) {
-  /* check if the process is already in a VM */
-  simdata_process_t simdata = simcall_process_get_data(process);
-  if (simdata->vm) {
-    msg_vm_t old_vm = simdata->vm;
-    int pos = xbt_dynar_search(old_vm->processes,&process);
-    xbt_dynar_remove_at(old_vm->processes,pos, NULL);
-  }
-  /* check if the host is in the right host */
-  if (simdata->m_host != vm->location) {
-    MSG_process_migrate(process,vm->location);
-  }
-  simdata->vm = vm;
+int MSG_vm_is_migrating(msg_vm_t vm)
+{
+  return __MSG_vm_is_state(vm, SURF_VM_STATE_MIGRATING);
+}
 
-  XBT_DEBUG("binding Process %s to %p",MSG_process_get_name(process),vm);
+/** @brief Returns whether the given VM is currently suspended, not running.
+ *  @ingroup msg_VMs
+ */
+int MSG_vm_is_suspended(msg_vm_t vm)
+{
+  return __MSG_vm_is_state(vm, SURF_VM_STATE_SUSPENDED);
+}
 
-  xbt_dynar_push_as(vm->processes,msg_process_t,process);
+/** @brief Returns whether the given VM is being saved (FIXME: live saving or not?).
+ *  @ingroup msg_VMs
+ */
+int MSG_vm_is_saving(msg_vm_t vm)
+{
+  return __MSG_vm_is_state(vm, SURF_VM_STATE_SAVING);
 }
-/** @brief Removes the given process from the given VM, and kill it
+
+/** @brief Returns whether the given VM has been saved, not running.
  *  @ingroup msg_VMs
- *
- *  Will raise a not_found exception if the process were not bound to that VM
  */
-void MSG_vm_unbind(msg_vm_t vm, msg_process_t process) {
-  int pos = xbt_dynar_search(vm->processes,process);
-  xbt_dynar_remove_at(vm->processes,pos, NULL);
-  MSG_process_kill(process);
+int MSG_vm_is_saved(msg_vm_t vm)
+{
+  return __MSG_vm_is_state(vm, SURF_VM_STATE_SAVED);
 }
 
-/** @brief Immediately change the host on which all processes are running.
+/** @brief Returns whether the given VM is being restored, not running.
  *  @ingroup msg_VMs
+ */
+int MSG_vm_is_restoring(msg_vm_t vm)
+{
+  return __MSG_vm_is_state(vm, SURF_VM_STATE_RESTORING);
+}
+
+
+
+/* ------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+
+/* **** ******** MSG vm actions ********* **** */
+
+/** @brief Create a new VM with specified parameters.
+ *  @ingroup msg_VMs*
+ *  All parameters are in MBytes
  *
- * No migration cost occurs. If you want to simulate this too, you want to use a
- * MSG_task_send() before or after, depending on whether you want to do cold or hot
- * migration.
  */
-void MSG_vm_migrate(msg_vm_t vm, msg_host_t destination) {
-  unsigned int cpt;
-  msg_process_t process;
-  xbt_dynar_foreach(vm->processes,cpt,process) {
-    MSG_process_migrate(process,destination);
+msg_vm_t MSG_vm_create(msg_host_t ind_pm, const char *name, int ncpus, int ramsize,
+                                            int net_cap, char *disk_path, int disksize,
+                                                int mig_netspeed, int dp_intensity)
+{
+       /* For the moment, intensity_rate is the percentage against the migration bandwidth */
+       double host_speed = MSG_get_host_speed(ind_pm);
+       double update_speed = ((double)dp_intensity/100) * mig_netspeed;
+       
+       msg_vm_t vm = MSG_vm_create_core(ind_pm, name);
+       s_ws_params_t params;
+       memset(&params, 0, sizeof(params));
+       params.ramsize = 1L * 1024 * 1024 * ramsize;
+       //params.overcommit = 0;
+       params.devsize = 0;
+       params.skip_stage2 = 0;
+       params.max_downtime = 0.03;
+       params.dp_rate = (update_speed * 1L * 1024 * 1024 ) / host_speed; 
+       params.dp_cap = params.ramsize / 0.9; // working set memory is 90%
+       params.mig_speed = 1L * 1024 * 1024 * mig_netspeed; // mig_speed
+
+   //XBT_INFO("dp rate %f migspeed : %f intensity mem : %d, updatespeed %f, hostspeed %f",params.dp_rate, params.mig_speed, dp_intensity, update_speed, host_speed);
+       simcall_host_set_params(vm, &params);
+
+       return vm;
+}
+
+
+/** @brief Create a new VM object. The VM is not yet started. The resource of the VM is allocated upon MSG_vm_start().
+ *  @ingroup msg_VMs*
+ *
+ * A VM is treated as a host. The name of the VM must be unique among all hosts.
+ */
+msg_vm_t MSG_vm_create_core(msg_host_t ind_pm, const char *name)
+{
+  /* make sure the VM of the same name does not exit */
+  {
+    void *ind_host_tmp = xbt_lib_get_elm_or_null(host_lib, name);
+    if (ind_host_tmp) {
+      XBT_ERROR("host %s already exits", name);
+      return NULL;
+    }
   }
-  xbt_swag_remove(vm, MSG_host_priv(vm->location)->vms);
-  xbt_swag_insert_at_tail(vm, MSG_host_priv(destination)->vms);
-  
+
+  /* Note: ind_vm and vm_workstation point to the same elm object. */
+  msg_vm_t ind_vm = NULL;
+  void *ind_vm_workstation =  NULL;
+
+  /* Ask the SIMIX layer to create the surf vm resource */
+  ind_vm_workstation = simcall_vm_create(name, ind_pm);
+  ind_vm = (msg_vm_t) __MSG_host_create(ind_vm_workstation);
+
+  XBT_DEBUG("A new VM (%s) has been created", name);
+
   #ifdef HAVE_TRACING
-  TRACE_msg_vm_change_host(vm,vm->location,destination);
+  TRACE_msg_vm_create(name, ind_pm);
   #endif
 
-  vm->location = destination;
+  return ind_vm;
 }
 
-/** @brief Immediately suspend the execution of all processes within the given VM.
+/** @brief Destroy a VM. Destroy the VM object from the simulation.
  *  @ingroup msg_VMs
- *
- * No suspension cost occurs. If you want to simulate this too, you want to
- * use a \ref MSG_file_write() before or after, depending on the exact semantic
- * of VM suspend to you.
  */
-void MSG_vm_suspend(msg_vm_t vm) {
-  unsigned int cpt;
-  msg_process_t process;
-  xbt_dynar_foreach(vm->processes,cpt,process) {
-    XBT_DEBUG("suspend process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
-    MSG_process_suspend(process);
+void MSG_vm_destroy(msg_vm_t vm)
+{
+  /* First, terminate all processes on the VM if necessary */
+  if (MSG_vm_is_running(vm))
+      simcall_vm_shutdown(vm);
+
+  if (!MSG_vm_is_created(vm)) {
+    XBT_CRITICAL("shutdown the given VM before destroying it");
+    DIE_IMPOSSIBLE;
   }
 
+  /* Then, destroy the VM object */
+  simcall_vm_destroy(vm);
+
+  __MSG_host_destroy(vm);
+
   #ifdef HAVE_TRACING
-  TRACE_msg_vm_suspend(vm);
+  TRACE_msg_vm_end(vm);
   #endif
 }
 
-/** @brief Immediately resumes the execution of all processes within the given VM.
+
+/** @brief Start a vm (i.e., boot the guest operating system)
  *  @ingroup msg_VMs
  *
- * No resume cost occurs. If you want to simulate this too, you want to
- * use a \ref MSG_file_read() before or after, depending on the exact semantic
- * of VM resume to you.
+ *  If the VM cannot be started, an exception is generated.
+ *
  */
-void MSG_vm_resume(msg_vm_t vm) {
-  unsigned int cpt;
-  msg_process_t process;
-  xbt_dynar_foreach(vm->processes,cpt,process) {
-    XBT_DEBUG("resume process %s of host %s",MSG_process_get_name(process),MSG_host_get_name(MSG_process_get_host(process)));
-    MSG_process_resume(process);
-  }
+void MSG_vm_start(msg_vm_t vm)
+{
+  simcall_vm_start(vm);
 
   #ifdef HAVE_TRACING
-  TRACE_msg_vm_resume(vm);
+  TRACE_msg_vm_start(vm);
   #endif
 }
 
+
+
 /** @brief Immediately kills all processes within the given VM. Any memory that they allocated will be leaked.
  *  @ingroup msg_VMs
  *
- * No extra delay occurs. If you want to simulate this too, you want to
+ * FIXME: No extra delay occurs. If you want to simulate this too, you want to
  * use a #MSG_process_sleep() or something. I'm not quite sure.
  */
 void MSG_vm_shutdown(msg_vm_t vm)
 {
-  msg_process_t process;
-  XBT_DEBUG("%lu processes in the VM", xbt_dynar_length(vm->processes));
-  while (!xbt_dynar_is_empty(vm->processes)) {
-    process = xbt_dynar_get_as(vm->processes,0,msg_process_t);
-    MSG_process_kill(process);
+  /* msg_vm_t equals to msg_host_t */
+  simcall_vm_shutdown(vm);
+
+  // #ifdef HAVE_TRACING
+  // TRACE_msg_vm_(vm);
+  // #endif
+}
+
+
+
+/* We have two mailboxes. mbox is used to transfer migration data between
+ * source and destiantion PMs. mbox_ctl is used to detect the completion of a
+ * migration. The names of these mailboxes must not conflict with others. */
+static inline char *get_mig_mbox_src_dst(const char *vm_name, const char *src_pm_name, const char *dst_pm_name)
+{
+  return bprintf("__mbox_mig_src_dst:%s(%s-%s)", vm_name, src_pm_name, dst_pm_name);
+}
+
+static inline char *get_mig_mbox_ctl(const char *vm_name, const char *src_pm_name, const char *dst_pm_name)
+{
+  return bprintf("__mbox_mig_ctl:%s(%s-%s)", vm_name, src_pm_name, dst_pm_name);
+}
+
+static inline char *get_mig_process_tx_name(const char *vm_name, const char *src_pm_name, const char *dst_pm_name)
+{
+  return bprintf("__pr_mig_tx:%s(%s-%s)", vm_name, src_pm_name, dst_pm_name);
+}
+
+static inline char *get_mig_process_rx_name(const char *vm_name, const char *src_pm_name, const char *dst_pm_name)
+{
+  return bprintf("__pr_mig_rx:%s(%s-%s)", vm_name, src_pm_name, dst_pm_name);
+}
+
+static inline char *get_mig_task_name(const char *vm_name, const char *src_pm_name, const char *dst_pm_name, int stage)
+{
+  return bprintf("__task_mig_stage%d:%s(%s-%s)", stage, vm_name, src_pm_name, dst_pm_name);
+}
+
+static void launch_deferred_exec_process(msg_host_t host, double computation, double prio);
+
+static int migration_rx_fun(int argc, char *argv[])
+{
+  XBT_DEBUG("mig: rx_start");
+
+  xbt_assert(argc == 4);
+  const char *vm_name = argv[1];
+  const char *src_pm_name  = argv[2];
+  const char *dst_pm_name  = argv[3];
+  msg_vm_t vm = MSG_get_host_by_name(vm_name);
+  msg_host_t src_pm = MSG_get_host_by_name(src_pm_name);
+  msg_host_t dst_pm = MSG_get_host_by_name(dst_pm_name);
+
+
+  s_ws_params_t params;
+  simcall_host_get_params(vm, &params);
+  const double xfer_cpu_overhead = params.xfer_cpu_overhead;
+
+
+  int need_exit = 0;
+
+  char *mbox = get_mig_mbox_src_dst(vm_name, src_pm_name, dst_pm_name);
+  char *mbox_ctl = get_mig_mbox_ctl(vm_name, src_pm_name, dst_pm_name);
+  char *finalize_task_name = get_mig_task_name(vm_name, src_pm_name, dst_pm_name, 3);
+
+  for (;;) {
+    msg_task_t task = NULL;
+    MSG_task_recv(&task, mbox);
+    {
+      double received = MSG_task_get_data_size(task);
+      /* TODO: clean up */
+      // const double alpha = 0.22L * 1.0E8 / (80L * 1024 * 1024);
+      launch_deferred_exec_process(vm, received * xfer_cpu_overhead, 1);
+    }
+
+    if (strcmp(task->name, finalize_task_name) == 0)
+      need_exit = 1;
+
+    MSG_task_destroy(task);
+
+    if (need_exit)
+      break;
+  }
+
+
+  /* deinstall the current affinity setting */
+  simcall_vm_set_affinity(vm, src_pm, 0);
+
+  simcall_vm_migrate(vm, dst_pm);
+  simcall_vm_resume(vm);
+
+  /* install the affinity setting of the VM on the destination pm */
+  {
+    msg_host_priv_t priv = msg_host_resource_priv(vm);
+
+    unsigned long affinity_mask = (unsigned long) xbt_dict_get_or_null_ext(priv->affinity_mask_db, (char *) dst_pm, sizeof(msg_host_t));
+    simcall_vm_set_affinity(vm, dst_pm, affinity_mask);
+    XBT_INFO("set affinity(0x%04lx@%s) for %s", affinity_mask, MSG_host_get_name(dst_pm), MSG_host_get_name(vm));
+  }
+
+  {
+    char *task_name = get_mig_task_name(vm_name, src_pm_name, dst_pm_name, 4);
+
+    msg_task_t task = MSG_task_create(task_name, 0, 0, NULL);
+    msg_error_t ret = MSG_task_send(task, mbox_ctl);
+    xbt_assert(ret == MSG_OK);
+
+    xbt_free(task_name);
+  }
+
+
+  xbt_free(mbox);
+  xbt_free(mbox_ctl);
+  xbt_free(finalize_task_name);
+
+  XBT_DEBUG("mig: rx_done");
+
+  return 0;
+}
+
+static void reset_dirty_pages(msg_vm_t vm)
+{
+  msg_host_priv_t priv = msg_host_resource_priv(vm);
+
+  char *key = NULL;
+  xbt_dict_cursor_t cursor = NULL;
+  dirty_page_t dp = NULL;
+  xbt_dict_foreach(priv->dp_objs, cursor, key, dp) {
+    double remaining = MSG_task_get_remaining_computation(dp->task);
+    dp->prev_clock = MSG_get_clock();
+    dp->prev_remaining = remaining;
+
+    // XBT_INFO("%s@%s remaining %f", key, sg_host_name(vm), remaining);
+  }
+}
+
+static void start_dirty_page_tracking(msg_vm_t vm)
+{
+  msg_host_priv_t priv = msg_host_resource_priv(vm);
+  priv->dp_enabled = 1;
+
+  reset_dirty_pages(vm);
+}
+
+static void stop_dirty_page_tracking(msg_vm_t vm)
+{
+  msg_host_priv_t priv = msg_host_resource_priv(vm);
+  priv->dp_enabled = 0;
+}
+
+#if 0
+/* It might be natural that we define dp_rate for each task. But, we will also
+ * have to care about how each task behavior affects the memory update behavior
+ * at the operating system level. It may not be easy to model it with a simple algorithm. */
+double calc_updated_pages(char *key, msg_vm_t vm, dirty_page_t dp, double remaining, double clock)
+{
+    double computed = dp->prev_remaining - remaining;
+    double duration = clock - dp->prev_clock;
+    double updated = dp->task->dp_rate * computed;
+
+    XBT_INFO("%s@%s: computated %f ops (remaining %f -> %f) in %f secs (%f -> %f)",
+        key, sg_host_name(vm), computed, dp->prev_remaining, remaining, duration, dp->prev_clock, clock);
+    XBT_INFO("%s@%s: updated %f bytes, %f Mbytes/s",
+        key, sg_host_name(vm), updated, updated / duration / 1000 / 1000);
+
+    return updated;
+}
+#endif
+
+static double get_computed(char *key, msg_vm_t vm, dirty_page_t dp, double remaining, double clock)
+{
+  double computed = dp->prev_remaining - remaining;
+  double duration = clock - dp->prev_clock;
+
+  XBT_DEBUG("%s@%s: computated %f ops (remaining %f -> %f) in %f secs (%f -> %f)",
+      key, sg_host_name(vm), computed, dp->prev_remaining, remaining, duration, dp->prev_clock, clock);
+
+  return computed;
+}
+
+static double lookup_computed_flop_counts(msg_vm_t vm, int stage_for_fancy_debug, int stage2_round_for_fancy_debug)
+{
+  msg_host_priv_t priv = msg_host_resource_priv(vm);
+  double total = 0;
+
+  char *key = NULL;
+  xbt_dict_cursor_t cursor = NULL;
+  dirty_page_t dp = NULL;
+  xbt_dict_foreach(priv->dp_objs, cursor, key, dp) {
+    double remaining = MSG_task_get_remaining_computation(dp->task);
+   
+        double clock = MSG_get_clock();
+
+    // total += calc_updated_pages(key, vm, dp, remaining, clock);
+    total += get_computed(key, vm, dp, remaining, clock);
+
+    dp->prev_remaining = remaining;
+    dp->prev_clock = clock;
+  }
+
+  total += priv->dp_updated_by_deleted_tasks;
+
+  XBT_DEBUG("mig-stage%d.%d: computed %f flop_counts (including %f by deleted tasks)",
+      stage_for_fancy_debug,
+      stage2_round_for_fancy_debug,
+      total, priv->dp_updated_by_deleted_tasks);
+
+
+
+  priv->dp_updated_by_deleted_tasks = 0;
+
+
+  return total;
+}
+
+// TODO Is this code redundant with the information provided by
+// msg_process_t MSG_process_create(const char *name, xbt_main_func_t code, void *data, msg_host_t host)
+void MSG_host_add_task(msg_host_t host, msg_task_t task)
+{
+  msg_host_priv_t priv = msg_host_resource_priv(host);
+  double remaining = MSG_task_get_remaining_computation(task);
+  char *key = bprintf("%s-%lld", task->name, task->counter);
+
+  dirty_page_t dp = xbt_new0(s_dirty_page, 1);
+  dp->task = task;
+
+  /* It should be okay that we add a task onto a migrating VM. */
+  if (priv->dp_enabled) {
+    dp->prev_clock = MSG_get_clock();
+    dp->prev_remaining = remaining;
+  }
+
+  xbt_assert(xbt_dict_get_or_null(priv->dp_objs, key) == NULL);
+  xbt_dict_set(priv->dp_objs, key, dp, NULL);
+  XBT_DEBUG("add %s on %s (remaining %f, dp_enabled %d)", key, sg_host_name(host), remaining, priv->dp_enabled);
+
+  xbt_free(key);
+}
+
+void MSG_host_del_task(msg_host_t host, msg_task_t task)
+{
+  msg_host_priv_t priv = msg_host_resource_priv(host);
+
+  char *key = bprintf("%s-%lld", task->name, task->counter);
+
+  dirty_page_t dp = xbt_dict_get_or_null(priv->dp_objs, key);
+  xbt_assert(dp->task == task);
+
+  /* If we are in the middle of dirty page tracking, we record how much
+   * computaion has been done until now, and keep the information for the
+   * lookup_() function that will called soon. */
+  if (priv->dp_enabled) {
+    double remaining = MSG_task_get_remaining_computation(task);
+    double clock = MSG_get_clock();
+    // double updated = calc_updated_pages(key, host, dp, remaining, clock);
+    double updated = get_computed(key, host, dp, remaining, clock);
+
+    priv->dp_updated_by_deleted_tasks += updated;
+  }
+
+  xbt_dict_remove(priv->dp_objs, key);
+  xbt_free(dp);
+
+  XBT_DEBUG("del %s on %s", key, sg_host_name(host));
+
+  xbt_free(key);
+}
+
+
+static int deferred_exec_fun(int argc, char *argv[])
+{
+  xbt_assert(argc == 3);
+  const char *comp_str = argv[1];
+  double computaion = atof(comp_str);
+  const char *prio_str = argv[2];
+  double prio = atof(prio_str);
+
+  msg_task_t task = MSG_task_create("__task_deferred", computaion, 0, NULL);
+  // XBT_INFO("exec deferred %f", computaion);
+
+  /* dpt is the results of the VM activity */
+  MSG_task_set_priority(task, prio);
+  MSG_task_execute(task);
+
+
+
+  MSG_task_destroy(task);
+
+  return 0;
+}
+
+static void launch_deferred_exec_process(msg_host_t host, double computation, double prio)
+{
+  char *pr_name = bprintf("__pr_deferred_exec_%s", MSG_host_get_name(host));
+
+  int nargvs = 4;
+  char **argv = xbt_new(char *, nargvs);
+  argv[0] = xbt_strdup(pr_name);
+  argv[1] = bprintf("%lf", computation);
+  argv[2] = bprintf("%lf", prio);
+  argv[3] = NULL;
+
+  MSG_process_create_with_arguments(pr_name, deferred_exec_fun, NULL, host, nargvs - 1, argv);
+
+  xbt_free(pr_name);
+}
+
+
+static int task_tx_overhead_fun(int argc, char *argv[])
+{
+  xbt_assert(argc == 2);
+  const char *mbox = argv[1];
+
+  int need_exit = 0;
+
+  // XBT_INFO("start %s", mbox);
+
+  for (;;) {
+    msg_task_t task = NULL;
+    MSG_task_recv(&task, mbox);
+
+    // XBT_INFO("task->name %s", task->name);
+
+    if (strcmp(task->name, "finalize_making_overhead") == 0)
+      need_exit = 1;
+
+    // XBT_INFO("exec");
+    // MSG_task_set_priority(task, 1000000);
+    MSG_task_execute(task);
+    MSG_task_destroy(task);
+
+    if (need_exit)
+      break;
+  }
+
+  // XBT_INFO("bye");
+
+  return 0;
+}
+
+static void start_overhead_process(msg_task_t comm_task)
+{
+  char *pr_name = bprintf("__pr_task_tx_overhead_%s", MSG_task_get_name(comm_task));
+  char *mbox    = bprintf("__mb_task_tx_overhead_%s", MSG_task_get_name(comm_task));
+
+  int nargvs = 3;
+  char **argv = xbt_new(char *, nargvs);
+  argv[0] = xbt_strdup(pr_name);
+  argv[1] = xbt_strdup(mbox);
+  argv[2] = NULL;
+
+  // XBT_INFO("micro start: mbox %s", mbox);
+  MSG_process_create_with_arguments(pr_name, task_tx_overhead_fun, NULL, MSG_host_self(), nargvs - 1, argv);
+
+  xbt_free(pr_name);
+  xbt_free(mbox);
+}
+
+static void shutdown_overhead_process(msg_task_t comm_task)
+{
+  char *mbox = bprintf("__mb_task_tx_overhead_%s", MSG_task_get_name(comm_task));
+
+  msg_task_t task = MSG_task_create("finalize_making_overhead", 0, 0, NULL);
+
+  // XBT_INFO("micro shutdown: mbox %s", mbox);
+  msg_error_t ret = MSG_task_send(task, mbox);
+  xbt_assert(ret == MSG_OK);
+
+  xbt_free(mbox);
+  // XBT_INFO("shutdown done");
+}
+
+static void request_overhead(msg_task_t comm_task, double computation)
+{
+  char *mbox = bprintf("__mb_task_tx_overhead_%s", MSG_task_get_name(comm_task));
+
+  msg_task_t task = MSG_task_create("micro", computation, 0, NULL);
+
+  // XBT_INFO("req overhead");
+  msg_error_t ret = MSG_task_send(task, mbox);
+  xbt_assert(ret == MSG_OK);
+
+  xbt_free(mbox);
+}
+
+/* alpha is (floating_operations / bytes).
+ *
+ * When actual migration traffic was 32 mbytes/s, we observed the CPU
+ * utilization of the main thread of the Qemu process was 10 %. 
+ *   alpha = 0.1 * C / (32 * 1024 * 1024)
+ * where the CPU capacity of the PM is C flops/s.
+ *
+ * */
+static void task_send_bounded_with_cpu_overhead(msg_task_t comm_task, char *mbox, double mig_speed, double alpha)
+{
+  const double chunk_size = 1024 * 1024 * 10;
+  double remaining = MSG_task_get_data_size(comm_task);
+
+  start_overhead_process(comm_task);
+
+
+  while (remaining > 0) {
+    double data_size = chunk_size;
+    if (remaining < chunk_size)
+      data_size = remaining;
+
+    remaining -= data_size;
+
+    // XBT_INFO("remaining %f bytes", remaining);
+
+
+    double clock_sta = MSG_get_clock();
+
+    /* create a micro task */
+    {
+      char *mtask_name = bprintf("__micro_%s", MSG_task_get_name(comm_task));
+      msg_task_t mtask = MSG_task_create(mtask_name, 0, data_size, NULL);
+
+      request_overhead(comm_task, data_size * alpha);
+
+      msg_error_t ret = MSG_task_send(mtask, mbox);
+      xbt_assert(ret == MSG_OK);
+
+      xbt_free(mtask_name);
+    }
+
+#if 0
+    {
+      /* In the real world, sending data involves small CPU computation. */
+      char *mtask_name = bprintf("__micro_%s", MSG_task_get_name(comm_task));
+      msg_task_t mtask = MSG_task_create(mtask_name, data_size * alpha, data_size, NULL);
+      MSG_task_execute(mtask);
+      MSG_task_destroy(mtask);
+      xbt_free(mtask_name);
+    }
+#endif
+   
+    /* TODO */
+
+    double clock_end = MSG_get_clock();
+
+
+    if (mig_speed > 0) {
+      /*
+       * (max bandwidth) > data_size / ((elapsed time) + time_to_sleep)
+       *
+       * Thus, we get
+       *   time_to_sleep > data_size / (max bandwidth) - (elapsed time)
+       *
+       * If time_to_sleep is smaller than zero, the elapsed time was too big. We
+       * do not need a micro sleep.
+       **/
+      double time_to_sleep = data_size / mig_speed - (clock_end - clock_sta);
+      if (time_to_sleep > 0)
+        MSG_process_sleep(time_to_sleep);
+
+
+      //XBT_INFO("duration %f", clock_end - clock_sta);
+      //XBT_INFO("time_to_sleep %f", time_to_sleep);
+    }
+  }
+
+  // XBT_INFO("%s", MSG_task_get_name(comm_task));
+  shutdown_overhead_process(comm_task);
+
+}
+
+
+#if 0
+static void make_cpu_overhead_of_data_transfer(msg_task_t comm_task, double init_comm_size)
+{
+  double prev_remaining = init_comm_size;
+
+  for (;;) {
+    double remaining = MSG_task_get_remaining_communication(comm_task);
+    if (remaining == 0)
+      need_exit = 1;
+
+    double sent = prev_remaining - remaining;
+    double comp_size = sent * overhead;
+
+
+    char *comp_task_name = bprintf("__sender_overhead%s", MSG_task_get_name(comm_task));
+    msg_task_t comp_task = MSG_task_create(comp_task_name, comp_size, 0, NULL);
+    MSG_task_execute(comp_task);
+    MSG_task_destroy(comp_task);
+
+    if (need_exit)
+      break;
+
+    prev_remaining = remaining;
+
+  }
+
+  xbt_free(comp_task_name);
+}
+#endif
+
+// #define USE_MICRO_TASK 1
+
+#if 0
+// const double alpha = 0.1L * 1.0E8 / (32L * 1024 * 1024);
+// const double alpha = 0.25L * 1.0E8 / (85L * 1024 * 1024);
+// const double alpha = 0.20L * 1.0E8 / (85L * 1024 * 1024);
+// const double alpha = 0.25L * 1.0E8 / (85L * 1024 * 1024);
+// const double alpha = 0.32L * 1.0E8 / (24L * 1024 * 1024);   // makes super good values for 32 mbytes/s
+//const double alpha = 0.32L * 1.0E8 / (32L * 1024 * 1024);
+// const double alpha = 0.56L * 1.0E8 / (80L * 1024 * 1024);
+////const double alpha = 0.20L * 1.0E8 / (80L * 1024 * 1024);
+// const double alpha = 0.56L * 1.0E8 / (90L * 1024 * 1024);
+// const double alpha = 0.66L * 1.0E8 / (90L * 1024 * 1024);
+// const double alpha = 0.20L * 1.0E8 / (80L * 1024 * 1024);
+
+/* CPU 22% when 80Mbyte/s */
+const double alpha = 0.22L * 1.0E8 / (80L * 1024 * 1024);
+#endif
+
+
+static void send_migration_data(const char *vm_name, const char *src_pm_name, const char *dst_pm_name,
+    double size, char *mbox, int stage, int stage2_round, double mig_speed, double xfer_cpu_overhead)
+{
+  char *task_name = get_mig_task_name(vm_name, src_pm_name, dst_pm_name, stage);
+  msg_task_t task = MSG_task_create(task_name, 0, size, NULL);
+
+  /* TODO: clean up */
+
+  double clock_sta = MSG_get_clock();
+
+#ifdef USE_MICRO_TASK
+
+  task_send_bounded_with_cpu_overhead(task, mbox, mig_speed, xfer_cpu_overhead);
+
+#else
+  msg_error_t ret;
+  if (mig_speed > 0)
+    ret = MSG_task_send_bounded(task, mbox, mig_speed);
+  else
+    ret = MSG_task_send(task, mbox);
+  xbt_assert(ret == MSG_OK);
+#endif
+
+  double clock_end = MSG_get_clock();
+  double duration = clock_end - clock_sta;
+  double actual_speed = size / duration;
+#ifdef USE_MICRO_TASK
+  double cpu_utilization = size * xfer_cpu_overhead / duration / 1.0E8;
+#else
+  double cpu_utilization = 0;
+#endif
+
+
+
+
+  if (stage == 2){
+    XBT_DEBUG("mig-stage%d.%d: sent %f duration %f actual_speed %f (target %f) cpu %f", stage, stage2_round, size, duration, actual_speed, mig_speed, cpu_utilization);}
+  else{
+    XBT_DEBUG("mig-stage%d: sent %f duration %f actual_speed %f (target %f) cpu %f", stage, size, duration, actual_speed, mig_speed, cpu_utilization);
+  }
+
+  xbt_free(task_name);
+
+
+
+#ifdef USE_MICRO_TASK
+  /* The name of a micro task starts with __micro, which does not match the
+   * special name that finalizes the receiver loop. Thus, we send the special task.
+   **/
+  {
+    if (stage == 3) {
+      char *task_name = get_mig_task_name(vm_name, src_pm_name, dst_pm_name, stage);
+      msg_task_t task = MSG_task_create(task_name, 0, 0, NULL);
+      msg_error_t ret = MSG_task_send(task, mbox);
+      xbt_assert(ret == MSG_OK);
+      xbt_free(task_name);
+    }
+  }
+#endif
+}
+
+static double get_updated_size(double computed, double dp_rate, double dp_cap)
+{
+  double updated_size = computed * dp_rate;
+  XBT_DEBUG("updated_size %f dp_rate %f", updated_size, dp_rate);
+  if (updated_size > dp_cap) {
+    // XBT_INFO("mig-stage2.%d: %f bytes updated, but cap it with the working set size %f", stage2_round, updated_size, dp_cap);
+    updated_size = dp_cap;
+  }
+
+  return updated_size;
+}
+
+static double send_stage1(msg_host_t vm, const char *src_pm_name, const char *dst_pm_name,
+    long ramsize, double mig_speed, double xfer_cpu_overhead, double dp_rate, double dp_cap, double dpt_cpu_overhead)
+{
+  const char *vm_name = MSG_host_get_name(vm);
+  char *mbox = get_mig_mbox_src_dst(vm_name, src_pm_name, dst_pm_name);
+
+  // const long chunksize = 1024 * 1024 * 100;
+  const long chunksize = 1024L * 1024 * 100000;
+  long remaining = ramsize;
+  double computed_total = 0;
+
+  while (remaining > 0) {
+    long datasize = chunksize;
+    if (remaining < chunksize)
+      datasize = remaining;
+
+    remaining -= datasize;
+
+    send_migration_data(vm_name, src_pm_name, dst_pm_name, datasize, mbox, 1, 0, mig_speed, xfer_cpu_overhead);
+
+    double computed = lookup_computed_flop_counts(vm, 1, 0);
+    computed_total += computed;
+
+    // {
+    //   double updated_size = get_updated_size(computed, dp_rate, dp_cap);
+
+    //   double overhead = dpt_cpu_overhead * updated_size;
+    //   launch_deferred_exec_process(vm, overhead, 10000);
+    // }
   }
 
+  return computed_total;
+}
+
+
+
+static double get_threshold_value(double bandwidth, double max_downtime)
+{
+  /* This value assumes the network link is 1Gbps. */
+  // double threshold = max_downtime * 125 * 1024 * 1024;
+  double threshold = max_downtime * bandwidth;
+
+  return threshold;
+}
+
+static int migration_tx_fun(int argc, char *argv[])
+{
+  XBT_DEBUG("mig: tx_start");
+
+  xbt_assert(argc == 4);
+  const char *vm_name = argv[1];
+  const char *src_pm_name  = argv[2];
+  const char *dst_pm_name  = argv[3];
+  msg_vm_t vm = MSG_get_host_by_name(vm_name);
+
+
+  s_ws_params_t params;
+  simcall_host_get_params(vm, &params);
+  const long ramsize        = params.ramsize;
+  const long devsize        = params.devsize;
+  const int skip_stage1     = params.skip_stage1;
+  const int skip_stage2     = params.skip_stage2;
+  const double dp_rate      = params.dp_rate;
+  const double dp_cap       = params.dp_cap;
+  const double mig_speed    = params.mig_speed;
+  const double xfer_cpu_overhead = params.xfer_cpu_overhead;
+  const double dpt_cpu_overhead = params.dpt_cpu_overhead;
+
+  double remaining_size = ramsize + devsize;
+
+  double max_downtime = params.max_downtime;
+  if (max_downtime == 0) {
+    XBT_WARN("use the default max_downtime value 30ms");
+    max_downtime = 0.03;
+  }
+
+  double threshold = 0.00001; /* TODO: cleanup */
+
+  /* setting up parameters has done */
+
+
+  if (ramsize == 0)
+    XBT_WARN("migrate a VM, but ramsize is zero");
+
+  char *mbox = get_mig_mbox_src_dst(vm_name, src_pm_name, dst_pm_name);
+
+  XBT_INFO("mig-stage1: remaining_size %f", remaining_size);
+
+  /* Stage1: send all memory pages to the destination. */
+  start_dirty_page_tracking(vm);
+
+  double computed_during_stage1 = 0;
+  if (!skip_stage1) {
+    // send_migration_data(vm_name, src_pm_name, dst_pm_name, ramsize, mbox, 1, 0, mig_speed, xfer_cpu_overhead);
+
+    /* send ramsize, but split it */
+    double clock_prev_send = MSG_get_clock();
+
+    computed_during_stage1 = send_stage1(vm, src_pm_name, dst_pm_name, ramsize, mig_speed, xfer_cpu_overhead, dp_rate, dp_cap, dpt_cpu_overhead);
+    remaining_size -= ramsize;
+
+    double clock_post_send = MSG_get_clock();
+    double bandwidth = ramsize / (clock_post_send - clock_prev_send);
+    threshold = get_threshold_value(bandwidth, max_downtime);
+    XBT_INFO("actual banwdidth %f, threshold %f", bandwidth / 1024 / 1024, threshold);
+  }
+
+
+  /* Stage2: send update pages iteratively until the size of remaining states
+   * becomes smaller than the threshold value. */
+  if (skip_stage2)
+    goto stage3;
+  if (max_downtime == 0) {
+    XBT_WARN("no max_downtime parameter, skip stage2");
+    goto stage3;
+  }
+
+
+  int stage2_round = 0;
+  for (;;) {
+
+    double updated_size = 0;
+    if (stage2_round == 0)  {
+      /* just after stage1, nothing has been updated. But, we have to send the data updated during stage1 */
+      updated_size = get_updated_size(computed_during_stage1, dp_rate, dp_cap);
+    } else {
+      double computed = lookup_computed_flop_counts(vm, 2, stage2_round);
+      updated_size = get_updated_size(computed, dp_rate, dp_cap);
+    }
+
+    XBT_INFO("mig-stage 2:%d updated_size %f computed_during_stage1 %f dp_rate %f dp_cap %f",
+        stage2_round, updated_size, computed_during_stage1, dp_rate, dp_cap);
+
+
+    // if (stage2_round != 0) {
+    //   /* during stage1, we have already created overhead tasks */
+    //   double overhead = dpt_cpu_overhead * updated_size;
+    //   XBT_DEBUG("updated %f overhead %f", updated_size, overhead);
+    //   launch_deferred_exec_process(vm, overhead, 10000);
+    // }
+
+
+    {
+      remaining_size += updated_size;
+
+      XBT_INFO("mig-stage2.%d: remaining_size %f (%s threshold %f)", stage2_round,
+          remaining_size, (remaining_size < threshold) ? "<" : ">", threshold);
+
+      if (remaining_size < threshold)
+        break;
+    }
+
+    double clock_prev_send = MSG_get_clock();
+
+    send_migration_data(vm_name, src_pm_name, dst_pm_name, updated_size, mbox, 2, stage2_round, mig_speed, xfer_cpu_overhead);
+
+    double clock_post_send = MSG_get_clock();
+
+    double bandwidth = updated_size / (clock_post_send - clock_prev_send);
+    threshold = get_threshold_value(bandwidth, max_downtime);
+    XBT_INFO("actual banwdidth %f, threshold %f", bandwidth / 1024 / 1024, threshold);
+
+
+
+
+
+
+
+    remaining_size -= updated_size;
+    stage2_round += 1;
+  }
+
+
+stage3:
+  /* Stage3: stop the VM and copy the rest of states. */
+  XBT_INFO("mig-stage3: remaining_size %f", remaining_size);
+  simcall_vm_suspend(vm);
+  stop_dirty_page_tracking(vm);
+
+  send_migration_data(vm_name, src_pm_name, dst_pm_name, remaining_size, mbox, 3, 0, mig_speed, xfer_cpu_overhead);
+
+  xbt_free(mbox);
+
+  XBT_DEBUG("mig: tx_done");
+
+  return 0;
+}
+
+
+
+static void do_migration(msg_vm_t vm, msg_host_t src_pm, msg_host_t dst_pm)
+{
+  char *mbox_ctl = get_mig_mbox_ctl(sg_host_name(vm), sg_host_name(src_pm), sg_host_name(dst_pm));
+
+  {
+    char *pr_name = get_mig_process_rx_name(sg_host_name(vm), sg_host_name(src_pm), sg_host_name(dst_pm));
+    int nargvs = 5;
+    char **argv = xbt_new(char *, nargvs);
+    argv[0] = xbt_strdup(pr_name);
+    argv[1] = xbt_strdup(sg_host_name(vm));
+    argv[2] = xbt_strdup(sg_host_name(src_pm));
+    argv[3] = xbt_strdup(sg_host_name(dst_pm));
+    argv[4] = NULL;
+
+    MSG_process_create_with_arguments(pr_name, migration_rx_fun, NULL, dst_pm, nargvs - 1, argv);
+
+    xbt_free(pr_name);
+  }
+
+  {
+    char *pr_name = get_mig_process_tx_name(sg_host_name(vm), sg_host_name(src_pm), sg_host_name(dst_pm));
+    int nargvs = 5;
+    char **argv = xbt_new(char *, nargvs);
+    argv[0] = xbt_strdup(pr_name);
+    argv[1] = xbt_strdup(sg_host_name(vm));
+    argv[2] = xbt_strdup(sg_host_name(src_pm));
+    argv[3] = xbt_strdup(sg_host_name(dst_pm));
+    argv[4] = NULL;
+    MSG_process_create_with_arguments(pr_name, migration_tx_fun, NULL, src_pm, nargvs - 1, argv);
+
+    xbt_free(pr_name);
+  }
+
+  /* wait until the migration have finished */
+  {
+    msg_task_t task = NULL;
+    msg_error_t ret = MSG_task_recv(&task, mbox_ctl);
+    xbt_assert(ret == MSG_OK);
+
+    char *expected_task_name = get_mig_task_name(sg_host_name(vm), sg_host_name(src_pm), sg_host_name(dst_pm), 4);
+    xbt_assert(strcmp(task->name, expected_task_name) == 0);
+    xbt_free(expected_task_name);
+  }
+
+  xbt_free(mbox_ctl);
+}
+
+
+/** @brief Migrate the VM to the given host.
+ *  @ingroup msg_VMs
+ *
+ * FIXME: No migration cost occurs. If you want to simulate this too, you want to use a
+ * MSG_task_send() before or after, depending on whether you want to do cold or hot
+ * migration.
+ */
+void MSG_vm_migrate(msg_vm_t vm, msg_host_t new_pm)
+{
+  /* some thoughts:
+   * - One approach is ...
+   *   We first create a new VM (i.e., destination VM) on the destination
+   *   physical host. The destination VM will receive the state of the source
+   *   VM over network. We will finally destroy the source VM.
+   *   - This behavior is similar to the way of migration in the real world.
+   *     Even before a migration is completed, we will see a destination VM,
+   *     consuming resources.
+   *   - We have to relocate all processes. The existing process migraion code
+   *     will work for this?
+   *   - The name of the VM is a somewhat unique ID in the code. It is tricky
+   *     for the destination VM?
+   *
+   * - Another one is ...
+   *   We update the information of the given VM to place it to the destination
+   *   physical host.
+   *
+   * The second one would be easier.
+   *   
+   */
+
+  msg_host_t old_pm = simcall_vm_get_pm(vm);
+
+  if (simcall_vm_get_state(vm) != SURF_VM_STATE_RUNNING)
+    THROWF(vm_error, 0, "VM(%s) is not running", sg_host_name(vm));
+
+  do_migration(vm, old_pm, new_pm);
+
+
+
+  XBT_DEBUG("VM(%s) moved from PM(%s) to PM(%s)", vm->key, old_pm->key, new_pm->key);
+
   #ifdef HAVE_TRACING
-  TRACE_msg_vm_kill(vm);
+  TRACE_msg_vm_change_host(vm, old_pm, new_pm);
   #endif
+}
 
+
+/** @brief Immediately suspend the execution of all processes within the given VM.
+ *  @ingroup msg_VMs
+ *
+ * This function stops the exection of the VM. All the processes on this VM
+ * will pause. The state of the VM is perserved. We can later resume it again.
+ *
+ * No suspension cost occurs.
+ */
+void MSG_vm_suspend(msg_vm_t vm)
+{
+  simcall_vm_suspend(vm);
+
+  XBT_DEBUG("vm_suspend done");
+
+  #ifdef HAVE_TRACING
+  TRACE_msg_vm_suspend(vm);
+  #endif
 }
 
-/**
- * \ingroup msg_VMs
- * \brief Reboot the VM, restarting all the processes in it.
+
+/** @brief Resume the execution of the VM. All processes on the VM run again.
+ *  @ingroup msg_VMs
+ *
+ * No resume cost occurs.
  */
-void MSG_vm_reboot(msg_vm_t vm)
+void MSG_vm_resume(msg_vm_t vm)
 {
-  xbt_dynar_t process_list = xbt_dynar_new(sizeof(msg_process_t), NULL);
-  msg_process_t process;
-  unsigned int cpt;
+  simcall_vm_resume(vm);
 
-  xbt_dynar_foreach(vm->processes, cpt, process) {
-    xbt_dynar_push_as(process_list, msg_process_t, process);
-  }
+  #ifdef HAVE_TRACING
+  TRACE_msg_vm_resume(vm);
+  #endif
+}
 
-  xbt_dynar_foreach(process_list, cpt, process) {
-    msg_process_t new_process = MSG_process_restart(process);
-    MSG_vm_bind(vm, new_process);
-  }
 
-  xbt_dynar_free(&process_list);
+/** @brief Immediately save the execution of all processes within the given VM.
+ *  @ingroup msg_VMs
+ *
+ * This function stops the exection of the VM. All the processes on this VM
+ * will pause. The state of the VM is perserved. We can later resume it again.
+ *
+ * FIXME: No suspension cost occurs. If you want to simulate this too, you want to
+ * use a \ref MSG_file_write() before or after, depending on the exact semantic
+ * of VM save to you.
+ */
+void MSG_vm_save(msg_vm_t vm)
+{
+  simcall_vm_save(vm);
+  #ifdef HAVE_TRACING
+  TRACE_msg_vm_save(vm);
+  #endif
 }
 
-/** @brief Destroy a msg_vm_t.
+/** @brief Restore the execution of the VM. All processes on the VM run again.
  *  @ingroup msg_VMs
+ *
+ * FIXME: No restore cost occurs. If you want to simulate this too, you want to
+ * use a \ref MSG_file_read() before or after, depending on the exact semantic
+ * of VM restore to you.
  */
-void MSG_vm_destroy(msg_vm_t vm) {
-  unsigned int cpt;
-  msg_process_t process;
-  xbt_dynar_foreach(vm->processes,cpt,process) {
-    //FIXME: Slow ?
-    simdata_process_t simdata = simcall_process_get_data(process);
-    simdata->vm = NULL;
-  }
+void MSG_vm_restore(msg_vm_t vm)
+{
+  simcall_vm_restore(vm);
 
   #ifdef HAVE_TRACING
-  TRACE_msg_vm_end(vm);
+  TRACE_msg_vm_restore(vm);
   #endif
+}
+
+
+/** @brief Get the physical host of a given VM.
+ *  @ingroup msg_VMs
+ */
+msg_host_t MSG_vm_get_pm(msg_vm_t vm)
+{
+  return simcall_vm_get_pm(vm);
+}
+
+
+/** @brief Set a CPU bound for a given VM.
+ *  @ingroup msg_VMs
+ *
+ * 1.
+ * Note that in some cases MSG_task_set_bound() may not intuitively work for VMs.
+ *
+ * For example,
+ *  On PM0, there are Task1 and VM0.
+ *  On VM0, there is Task2.
+ * Now we bound 75% to Task1@PM0 and bound 25% to Task2@VM0.
+ * Then, 
+ *  Task1@PM0 gets 50%.
+ *  Task2@VM0 gets 25%.
+ * This is NOT 75% for Task1@PM0 and 25% for Task2@VM0, respectively.
+ *
+ * This is because a VM has the dummy CPU action in the PM layer. Putting a
+ * task on the VM does not affect the bound of the dummy CPU action. The bound
+ * of the dummy CPU action is unlimited.
+ *
+ * There are some solutions for this problem. One option is to update the bound
+ * of the dummy CPU action automatically. It should be the sum of all tasks on
+ * the VM. But, this solution might be costy, because we have to scan all tasks
+ * on the VM in share_resource() or we have to trap both the start and end of
+ * task execution.
+ *
+ * The current solution is to use MSG_vm_set_bound(), which allows us to
+ * directly set the bound of the dummy CPU action.
+ *
+ *
+ * 2.
+ * Note that bound == 0 means no bound (i.e., unlimited). But, if a host has
+ * multiple CPU cores, the CPU share of a computation task (or a VM) never
+ * exceeds the capacity of a CPU core.
+ */
+void MSG_vm_set_bound(msg_vm_t vm, double bound)
+{
+       return simcall_vm_set_bound(vm, bound);
+}
+
+
+/** @brief Set the CPU affinity of a given VM.
+ *  @ingroup msg_VMs
+ *
+ * This function changes the CPU affinity of a given VM. Usage is the same as
+ * MSG_task_set_affinity(). See the MSG_task_set_affinity() for details.
+ */
+void MSG_vm_set_affinity(msg_vm_t vm, msg_host_t pm, unsigned long mask)
+{
+  msg_host_priv_t priv = msg_host_resource_priv(vm);
+
+  if (mask == 0)
+    xbt_dict_remove_ext(priv->affinity_mask_db, (char *) pm, sizeof(pm));
+  else
+    xbt_dict_set_ext(priv->affinity_mask_db, (char *) pm, sizeof(pm), (void *) mask, NULL);
 
-  xbt_free(vm->name);
-  xbt_dynar_free(&vm->processes);
-  xbt_free(vm);
+  msg_host_t pm_now = MSG_vm_get_pm(vm);
+  if (pm_now == pm) {
+    XBT_INFO("set affinity(0x%04lx@%s) for %s", mask, MSG_host_get_name(pm), MSG_host_get_name(vm));
+    simcall_vm_set_affinity(vm, pm, mask);
+  } else
+    XBT_INFO("set affinity(0x%04lx@%s) for %s (not active now)", mask, MSG_host_get_name(pm), MSG_host_get_name(vm));
 }
index 54feb2d..c34f3d9 100644 (file)
@@ -310,13 +310,13 @@ xbt_swag_t SD_simulate_swag(double how_long) {
     if (elapsed_time > 0.0)
       total_time += elapsed_time;
 
+    /* FIXME: shoud look at model_list or model_list_invoke? */
     /* 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");
@@ -380,15 +380,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);
index e147c42..f5e993d 100644 (file)
@@ -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);
 }
 
 /**
index c098fd1..ea42489 100644 (file)
@@ -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);
@@ -519,7 +517,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;
 }
@@ -1067,7 +1065,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);
@@ -1134,7 +1132,7 @@ void __SD_task_really_run(SD_task_t task)
   surf_workstations = xbt_new(void *, workstation_nb);
 
   for (i = 0; i < workstation_nb; i++)
-    surf_workstations[i] = task->workstation_list[i];
+    surf_workstations[i] =  surf_workstation_resource_priv(task->workstation_list[i]);
 
   double *computation_amount = xbt_new0(double, workstation_nb);
   double *communication_amount = xbt_new0(double, workstation_nb * workstation_nb);
@@ -1147,15 +1145,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);
 
@@ -1244,7 +1241,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");
@@ -1402,8 +1399,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;
 }
@@ -1422,8 +1418,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;
 }
index 14a0c70..f868b59 100644 (file)
@@ -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)");
 
@@ -178,8 +176,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));
 }
 
 
@@ -247,9 +244,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);
@@ -269,8 +266,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));
 }
 
 /**
@@ -282,8 +279,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);
 }
 
 /**
@@ -295,8 +291,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);
 }
 
 /**
@@ -482,7 +477,7 @@ void SD_workstation_set_access_mode(SD_workstation_t workstation,
  * \return a dynar containing all mounted storages on the workstation
  */
 xbt_dict_t SD_workstation_get_storage_list(SD_workstation_t workstation){
-  return surf_workstation_model->extension.workstation.get_storage_list(workstation);
+  return surf_workstation_get_storage_list(workstation);
 }
 
 /* Returns whether a task can start now on a workstation*/
index b812c87..11cf929 100644 (file)
@@ -130,6 +130,25 @@ static void _sg_cfg_cb__workstation_model(const char *name, int pos)
   find_model_description(surf_workstation_model_description, val);
 }
 
+/* callback of the vm_workstation/model variable */
+static void _sg_cfg_cb__vm_workstation_model(const char *name, int pos)
+{
+  char *val;
+
+  xbt_assert(_sg_cfg_init_status < 2,
+              "Cannot change the model after the initialization");
+
+  val = xbt_cfg_get_string(_sg_cfg_set, name);
+
+  if (!strcmp(val, "help")) {
+    model_help("vm_workstation", surf_vm_workstation_model_description);
+    sg_cfg_exit_early();
+  }
+
+  /* Make sure that the model exists */
+  find_model_description(surf_vm_workstation_model_description, val);
+}
+
 /* callback of the cpu/model variable */
 static void _sg_cfg_cb__cpu_model(const char *name, int pos)
 {
@@ -452,22 +471,6 @@ void sg_config_init(int *argc, char **argv)
                      xbt_cfgelm_string, 1, 1, &_sg_cfg_cb__storage_mode, NULL);
     xbt_cfg_setdefault_string(_sg_cfg_set, "storage/model", "default");
 
-    /* ********************************************************************* */
-    /* TUTORIAL: New model                                                   */
-    sprintf(description,
-            "The model to use for the New model. Possible values: ");
-    p = description;
-    while (*(++p) != '\0');
-    for (i = 0; surf_new_model_description[i].name; i++)
-      p += sprintf(p, "%s%s", (i == 0 ? "" : ", "),
-                   surf_new_model_description[i].name);
-    sprintf(p,
-            ".\n       (use 'help' as a value to see the long description of each model)");
-    xbt_cfg_register(&_sg_cfg_set, "new_model/model", description,
-                     xbt_cfgelm_string, 1, 1, &_sg_cfg_cb__storage_mode, NULL);
-    xbt_cfg_setdefault_string(_sg_cfg_set, "new_model/model", "default");
-    /* ********************************************************************* */
-
     sprintf(description,
             "The model to use for the network. Possible values: ");
     p = description;
@@ -507,6 +510,10 @@ void sg_config_init(int *argc, char **argv)
                      xbt_cfgelm_string, 1, 1, &_sg_cfg_cb__workstation_model, NULL);
     xbt_cfg_setdefault_string(_sg_cfg_set, "workstation/model", "default");
 
+    xbt_cfg_register(&_sg_cfg_set, "vm_workstation/model", description,
+                     xbt_cfgelm_string, 1, 1, &_sg_cfg_cb__vm_workstation_model, NULL);
+    xbt_cfg_setdefault_string(_sg_cfg_set, "vm_workstation/model", "default");
+
     xbt_cfg_register(&_sg_cfg_set, "network/TCP_gamma",
                      "Size of the biggest TCP window (cat /proc/sys/net/ipv4/tcp_[rw]mem for recv/send window; Use the last given value, which is the max window size)",
                      xbt_cfgelm_double, 1, 1, _sg_cfg_cb__tcp_gamma, NULL);
@@ -841,7 +848,9 @@ void sg_config_finalize(void)
 void surf_config_models_setup()
 {
   const char *workstation_model_name;
+  const char *vm_workstation_model_name;
   int workstation_id = -1;
+  int vm_workstation_id = -1;
   char *network_model_name = NULL;
   char *cpu_model_name = NULL;
   int storage_id = -1;
@@ -849,6 +858,8 @@ void surf_config_models_setup()
 
   workstation_model_name =
       xbt_cfg_get_string(_sg_cfg_set, "workstation/model");
+  vm_workstation_model_name =
+      xbt_cfg_get_string(_sg_cfg_set, "vm_workstation/model");
   network_model_name = xbt_cfg_get_string(_sg_cfg_set, "network/model");
   cpu_model_name = xbt_cfg_get_string(_sg_cfg_set, "cpu/model");
   storage_model_name = xbt_cfg_get_string(_sg_cfg_set, "storage/model");
@@ -893,19 +904,15 @@ void surf_config_models_setup()
   XBT_DEBUG("Call workstation_model_init");
   surf_workstation_model_description[workstation_id].model_init_preparse();
 
+  XBT_DEBUG("Call vm_workstation_model_init");
+  vm_workstation_id = find_model_description(surf_vm_workstation_model_description,
+                                          vm_workstation_model_name);
+  surf_vm_workstation_model_description[vm_workstation_id].model_init_preparse();
+
   XBT_DEBUG("Call storage_model_init");
   storage_id = find_model_description(surf_storage_model_description, storage_model_name);
   surf_storage_model_description[storage_id].model_init_preparse();
 
-  /* ********************************************************************* */
-  /* TUTORIAL: New model                                                   */
-  int new_model_id = -1;
-  char *new_model_name = NULL;
-  new_model_name = xbt_cfg_get_string(_sg_cfg_set, "new_model/model");
-  XBT_DEBUG("Call new model_init");
-  new_model_id = find_model_description(surf_new_model_description, new_model_name);
-  surf_new_model_description[new_model_id].model_init_preparse();
-  /* ********************************************************************* */
 }
 
 int sg_cfg_get_int(const char* name)
index 3b53ec8..50b4588 100644 (file)
@@ -36,6 +36,23 @@ static void parse_process(sg_platf_process_cbarg_t process)
   smx_process_arg_t arg = NULL;
   smx_process_t process_created = NULL;
 
+  arg = xbt_new0(s_smx_process_arg_t, 1);
+  arg->code = parse_code;
+  arg->data = NULL;
+  arg->hostname = sg_host_name(host);
+  arg->argc = process->argc;
+  arg->argv = xbt_new(char *,process->argc);
+  int i;
+  for (i=0; i<process->argc; i++)
+    arg->argv[i] = xbt_strdup(process->argv[i]);
+  arg->name = xbt_strdup(arg->argv[0]);
+  arg->kill_time = kill_time;
+  arg->properties = current_property_set;
+  if (!SIMIX_host_priv(host)->boot_processes) {
+    SIMIX_host_priv(host)->boot_processes = xbt_dynar_new(sizeof(smx_process_arg_t), _SIMIX_host_free_process_arg);
+  }
+  xbt_dynar_push_as(SIMIX_host_priv(host)->boot_processes,smx_process_arg_t,arg);
+
   if (start_time > SIMIX_get_clock()) {
     arg = xbt_new0(s_smx_process_arg_t, 1);
     arg->name = (char*)(process->argv)[0];
@@ -67,7 +84,7 @@ static void parse_process(sg_platf_process_cbarg_t process)
     else
       simcall_process_create(&process_created, (char*)(process->argv)[0], parse_code, NULL, sg_host_name(host), kill_time, process->argc,
           (char**)process->argv, current_property_set,auto_restart);
-
+    
     /* verify if process has been created (won't be the case if the host is currently dead, but that's fine) */
     if (!process_created) {
       return;
index 48127cb..e1f793e 100644 (file)
@@ -324,14 +324,20 @@ 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;
-      while ((action = xbt_swag_extract(set)))
-        SIMIX_simcall_post((smx_action_t) action->data);
-      set = model->states.done_action_set;
+      set = surf_model_failed_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));
+      set = surf_model_done_action_set(model);
+
+      while ((action = xbt_swag_extract(set))) 
+        if (surf_action_get_data(action) == NULL)
+          XBT_DEBUG("probably vcpu's action %p, skip", action);
+        else
+          SIMIX_simcall_post((smx_action_t) surf_action_get_data(action));
     }
 
     /* Autorestart all process */
@@ -347,6 +353,11 @@ void SIMIX_run(void)
     /* Clean processes to destroy */
     SIMIX_process_empty_trash();
 
+
+    XBT_DEBUG("### time %f, empty %d", time, xbt_dynar_is_empty(simix_global->process_to_run));
+    // !(time == -1.0 && xbt_dynar_is_empty()) 
+
+
   } while (time != -1.0 || !xbt_dynar_is_empty(simix_global->process_to_run));
 
   if (xbt_swag_size(simix_global->process_list) != 0) {
index 2480bbd..5b42062 100644 (file)
@@ -38,6 +38,86 @@ smx_host_t SIMIX_host_create(const char *name,
   return xbt_lib_get_or_null(host_lib, name, SIMIX_HOST_LEVEL);
 }
 
+void SIMIX_pre_host_on(smx_simcall_t simcall, smx_host_t h)
+{
+  SIMIX_host_on(h);
+}
+
+/**
+ * \brief Start the host if it is off
+ *
+ */
+void SIMIX_host_on(smx_host_t h)
+{
+  smx_host_priv_t host = SIMIX_host_priv(h);
+
+  xbt_assert((host != NULL), "Invalid parameters");
+
+  if (surf_resource_get_state(surf_workstation_resource_priv(h))==SURF_RESOURCE_OFF) {
+       surf_resource_set_state(surf_workstation_resource_priv(h), SURF_RESOURCE_ON);
+    unsigned int cpt;
+    smx_process_arg_t arg;
+    xbt_dynar_foreach(host->boot_processes,cpt,arg) {
+      smx_process_t process;
+
+      XBT_DEBUG("Booting Process %s(%s) right now", arg->argv[0], arg->hostname);
+      if (simix_global->create_process_function) {
+        simix_global->create_process_function(&process,
+                                              arg->argv[0],
+                                              arg->code,
+                                              NULL,
+                                              arg->hostname,
+                                              arg->kill_time,
+                                              arg->argc,
+                                              arg->argv,
+                                              arg->properties,
+                                              arg->auto_restart);
+      }
+      else {
+        simcall_process_create(&process,
+                                              arg->argv[0],
+                                              arg->code,
+                                              NULL,
+                                              arg->hostname,
+                                              arg->kill_time,
+                                              arg->argc,
+                                              arg->argv,
+                                              arg->properties,
+                                              arg->auto_restart);
+      }
+    }
+  }
+}
+
+void SIMIX_pre_host_off(smx_simcall_t simcall, smx_host_t h)
+{
+  SIMIX_host_off(h, simcall->issuer);
+}
+
+/**
+ * \brief Stop the host if it is on
+ *
+ */
+void SIMIX_host_off(smx_host_t h, smx_process_t issuer)
+{
+  smx_host_priv_t host = SIMIX_host_priv(h);
+
+  xbt_assert((host != NULL), "Invalid parameters");
+  
+  if (surf_resource_get_state(surf_workstation_resource_priv(h))==SURF_RESOURCE_OFF) {
+       surf_resource_set_state(surf_workstation_resource_priv(h), SURF_RESOURCE_ON);
+
+    /* Clean Simulator data */
+    if (xbt_swag_size(host->process_list) != 0) {
+      smx_process_t process = NULL;
+      xbt_swag_foreach(process, host->process_list) {
+        SIMIX_process_kill(process, issuer);
+       XBT_DEBUG("Killing %s on %s by %s", process->name,  sg_host_name(process->smx_host), issuer->name);
+      }
+    }
+  }
+}
+
 /**
  * \brief Internal function to destroy a SIMIX host.
  *
@@ -64,6 +144,7 @@ void SIMIX_host_destroy(void *h)
     THROWF(arg_error, 0, "%s", msg);
   }
   xbt_dynar_free(&host->auto_restart_processes);
+  xbt_dynar_free(&host->boot_processes);
   xbt_swag_free(host->process_list);
 
   /* Clean host structure */
@@ -135,7 +216,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 +224,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 +233,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);
 }
 
 xbt_swag_t SIMIX_pre_host_get_process_list(smx_simcall_t simcall, smx_host_t host){
@@ -176,8 +254,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);
 }
 
 double SIMIX_pre_host_get_current_power_peak(smx_simcall_t simcall, smx_host_t host){
@@ -185,8 +262,7 @@ double SIMIX_pre_host_get_current_power_peak(smx_simcall_t simcall, smx_host_t h
 }
 double SIMIX_host_get_current_power_peak(smx_host_t host) {
          xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
-         return surf_workstation_model->extension.workstation.
-                     get_current_power_peak(host);
+         return surf_workstation_get_current_power_peak(host);
 }
 
 double SIMIX_pre_host_get_power_peak_at(smx_simcall_t simcall, smx_host_t host, int pstate_index){
@@ -195,8 +271,7 @@ double SIMIX_pre_host_get_power_peak_at(smx_simcall_t simcall, smx_host_t host,
 double SIMIX_host_get_power_peak_at(smx_host_t host, int pstate_index) {
          xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
 
-         return surf_workstation_model->extension.workstation.
-             get_power_peak_at(host, pstate_index);
+         return surf_workstation_get_power_peak_at(host, pstate_index);
 }
 
 int SIMIX_pre_host_get_nb_pstates(smx_simcall_t simcall, smx_host_t host){
@@ -205,8 +280,7 @@ int SIMIX_pre_host_get_nb_pstates(smx_simcall_t simcall, smx_host_t host){
 int SIMIX_host_get_nb_pstates(smx_host_t host) {
          xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
 
-         return surf_workstation_model->extension.workstation.
-             get_nb_pstates(host);
+         return surf_workstation_get_nb_pstates(host);
 }
 
 
@@ -216,8 +290,7 @@ void SIMIX_pre_host_set_power_peak_at(smx_simcall_t simcall, smx_host_t host, in
 void SIMIX_host_set_power_peak_at(smx_host_t host, int pstate_index) {
          xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
 
-         surf_workstation_model->extension.workstation.
-             set_power_peak_at(host, pstate_index);
+         surf_workstation_set_power_peak_at(host, pstate_index);
 }
 
 double SIMIX_pre_host_get_consumed_energy(smx_simcall_t simcall, smx_host_t host){
@@ -225,8 +298,7 @@ double SIMIX_pre_host_get_consumed_energy(smx_simcall_t simcall, smx_host_t host
 }
 double SIMIX_host_get_consumed_energy(smx_host_t host) {
          xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
-         return surf_workstation_model->extension.workstation.
-                     get_consumed_energy(host);
+         return surf_workstation_get_consumed_energy(host);
 }
 
 int SIMIX_pre_host_get_state(smx_simcall_t simcall, smx_host_t host){
@@ -235,8 +307,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){
@@ -263,7 +334,7 @@ void* SIMIX_host_get_data(smx_host_t host){
   return SIMIX_host_priv(host)->data;
 }
 
-static void _SIMIX_host_free_process_arg(void *data)
+void _SIMIX_host_free_process_arg(void *data)
 {
   smx_process_arg_t arg = *(void**)data;
   int i;
@@ -387,11 +458,11 @@ void SIMIX_host_set_data(smx_host_t host, void *data){
 }
 
 smx_action_t SIMIX_pre_host_execute(smx_simcall_t simcall,const char *name,
-    smx_host_t host, double computation_amount, double priority){
-  return SIMIX_host_execute(name, host, computation_amount, priority);
+    smx_host_t host, double computation_amount, double priority, double bound, unsigned long affinity_mask){
+  return SIMIX_host_execute(name, host, computation_amount, priority, bound, affinity_mask);
 }
 smx_action_t SIMIX_host_execute(const char *name,
-    smx_host_t host, double computation_amount, double priority){
+    smx_host_t host, double computation_amount, double priority, double bound, unsigned long affinity_mask){
 
   /* alloc structures and initialize */
   smx_action_t action = xbt_mallocator_get(simix_global->action_mallocator);
@@ -406,11 +477,24 @@ 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);
+
+    action->execution.surf_exec = surf_workstation_execute(host, computation_amount);
+    surf_action_set_data(action->execution.surf_exec, action);
+    surf_action_set_priority(action->execution.surf_exec, priority);
+
+    /* Note (hypervisor): for multicore, the bound value being passed to the
+     * surf layer should not be zero (i.e., unlimited). It should be the
+     * capacity of a CPU core. */
+    if (bound == 0)
+      surf_cpu_action_set_bound(action->execution.surf_exec, SIMIX_host_get_speed(host));
+    else
+      surf_cpu_action_set_bound(action->execution.surf_exec, bound);
+
+    if (affinity_mask != 0) {
+      /* just a double check to confirm that this host is the host where this task is running. */
+      xbt_assert(action->execution.host == host);
+      surf_cpu_action_set_affinity(action->execution.surf_exec, host, affinity_mask);
+    }
   }
 
   XBT_DEBUG("Create execute action %p", action);
@@ -447,22 +531,43 @@ smx_action_t SIMIX_host_parallel_execute(const char *name,
   /* set surf's action */
   workstation_list = xbt_new0(void *, host_nb);
   for (i = 0; i < host_nb; i++)
-    workstation_list[i] = host_list[i];
+    workstation_list[i] = surf_workstation_resource_priv(host_list[i]);
+
+
+  /* FIXME: what happens if host_list contains VMs and PMs. If
+   * execute_parallel_task() does not change the state of the model, we can mix
+   * them. */
+  surf_model_t ws_model = surf_resource_model(host_list[0], SURF_WKS_LEVEL);
+  for (i = 1; i < host_nb; i++) {
+    surf_model_t ws_model_tmp = surf_resource_model(host_list[i], SURF_WKS_LEVEL);
+    if (ws_model_tmp != ws_model) {
+      XBT_CRITICAL("mixing VMs and PMs is not supported");
+      DIE_IMPOSSIBLE;
+    }
+  }
 
   /* 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);
 
   return action;
 }
 
+//FIXME: REMOVE not used
+static surf_model_t get_ws_model_from_action(smx_action_t action)
+{
+  xbt_assert(action->type == SIMIX_ACTION_EXECUTE);
+  smx_host_t host = action->execution.host;
+  surf_model_t model = surf_resource_model(host, SURF_WKS_LEVEL);
+  return model;
+}
+
 void SIMIX_pre_host_execution_destroy(smx_simcall_t simcall, smx_action_t action){
   SIMIX_host_execution_destroy(action);
 }
@@ -470,7 +575,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);
@@ -484,7 +589,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){
@@ -494,7 +599,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;
 }
@@ -508,11 +613,36 @@ e_smx_state_t SIMIX_host_execution_get_state(smx_action_t action){
 
 void SIMIX_pre_host_execution_set_priority(smx_simcall_t simcall, smx_action_t action,
                                        double priority){
-  return SIMIX_host_execution_set_priority(action, priority);
+  SIMIX_host_execution_set_priority(action, priority);
 }
 void SIMIX_host_execution_set_priority(smx_action_t action, double priority){
+
+  if(action->execution.surf_exec)
+       surf_action_set_priority(action->execution.surf_exec, priority);
+}
+
+void SIMIX_pre_host_execution_set_bound(smx_simcall_t simcall, smx_action_t action,
+                                       double bound){
+  SIMIX_host_execution_set_bound(action, bound);
+}
+void SIMIX_host_execution_set_bound(smx_action_t action, double bound){
+
   if(action->execution.surf_exec)
-    surf_workstation_model->set_priority(action->execution.surf_exec, priority);
+       surf_cpu_action_set_bound(action->execution.surf_exec, bound);
+}
+
+void SIMIX_pre_host_execution_set_affinity(smx_simcall_t simcall,
+    smx_action_t action, smx_host_t host, unsigned long mask){
+  SIMIX_host_execution_set_affinity(action, host, mask);
+}
+void SIMIX_host_execution_set_affinity(smx_action_t action, smx_host_t host, unsigned long mask){
+  xbt_assert(action->type == SIMIX_ACTION_EXECUTE);
+
+  if (action->execution.surf_exec) {
+    /* just a double check to confirm that this host is the host where this task is running. */
+    xbt_assert(action->execution.host == host);
+    surf_cpu_action_set_affinity(action->execution.surf_exec, host, mask);
+  }
 }
 
 void SIMIX_pre_host_execution_wait(smx_simcall_t simcall, smx_action_t action){
@@ -538,13 +668,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)
@@ -577,8 +707,7 @@ 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_workstation_resource_priv(simcall->issuer->smx_host)) != SURF_RESOURCE_ON) {
       simcall->issuer->context->iwannadie = 1;
     }
 
@@ -591,15 +720,16 @@ void SIMIX_execution_finish(smx_action_t action)
   SIMIX_host_execution_destroy(action);
 }
 
+
 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_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;
@@ -608,7 +738,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;
   }
 
@@ -628,18 +758,47 @@ 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
 
+/**
+ * \brief Function to get the parameters of the given the SIMIX host.
+ *
+ * \param host the host to get_phys_host (a smx_host_t)
+ * \param param the parameter object space to be overwritten (a ws_params_t)
+ */
+void SIMIX_host_get_params(smx_host_t ind_vm, ws_params_t params)
+{
+  /* jump to ws_get_params(). */
+  surf_workstation_get_params(ind_vm, params);
+}
+
+void SIMIX_pre_host_get_params(smx_simcall_t simcall, smx_host_t ind_vm, ws_params_t params)
+{
+  SIMIX_host_get_params(ind_vm, params);
+}
+
+void SIMIX_host_set_params(smx_host_t ind_vm, ws_params_t params)
+{
+  /* jump to ws_set_params(). */
+  surf_workstation_set_params(ind_vm, params);
+}
+
+void SIMIX_pre_host_set_params(smx_simcall_t simcall, smx_host_t ind_vm, ws_params_t params)
+{
+  SIMIX_host_set_params(ind_vm, params);
+}
+
 xbt_dict_t SIMIX_pre_host_get_storage_list(smx_simcall_t simcall, smx_host_t host){
   return SIMIX_host_get_storage_list(host);
 }
+
 xbt_dict_t SIMIX_host_get_storage_list(smx_host_t host){
   xbt_assert((host != NULL), "Invalid parameters (simix host is NULL)");
 
-  return surf_workstation_model->extension.workstation.get_storage_list(host);
+  return surf_workstation_get_storage_list(host);
 }
index f91d19d..614ce1f 100644 (file)
 typedef struct s_smx_host_priv {
   xbt_swag_t process_list;
   xbt_dynar_t auto_restart_processes;
+  xbt_dynar_t boot_processes; 
   void *data;              /**< @brief user data */
 } s_smx_host_priv_t;
 
 static inline smx_host_priv_t SIMIX_host_priv(smx_host_t host){
-  return xbt_lib_get_level(host, SIMIX_HOST_LEVEL);
+  return (smx_host_priv_t) xbt_lib_get_level(host, SIMIX_HOST_LEVEL);
 }
 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+void _SIMIX_host_free_process_arg(void *);
 smx_host_t SIMIX_host_create(const char *name, void *workstation, void *data);
 void SIMIX_host_destroy(void *host);
 
@@ -43,13 +48,15 @@ xbt_swag_t SIMIX_host_get_process_list(smx_host_t host);
 double SIMIX_host_get_speed(smx_host_t host);
 double SIMIX_host_get_available_speed(smx_host_t host);
 int SIMIX_host_get_state(smx_host_t host);
+void SIMIX_host_on(smx_host_t host);
+void SIMIX_host_off(smx_host_t host, smx_process_t issuer);
 double SIMIX_host_get_current_power_peak(smx_host_t host);
 double SIMIX_host_get_power_peak_at(smx_host_t host, int pstate_index);
 int SIMIX_host_get_nb_pstates(smx_host_t host);
 double SIMIX_host_get_consumed_energy(smx_host_t host);
 void SIMIX_host_set_power_peak_at(smx_host_t host, int pstate_index);
 smx_action_t SIMIX_host_execute(const char *name,
-    smx_host_t host, double computation_amount, double priority);
+    smx_host_t host, double computation_amount, double priority, double bound, unsigned long affinity_mask);
 smx_action_t SIMIX_host_parallel_execute(const char *name,
     int host_nb, smx_host_t *host_list,
     double *computation_amount, double *communication_amount,
@@ -59,6 +66,8 @@ void SIMIX_host_execution_cancel(smx_action_t action);
 double SIMIX_host_execution_get_remains(smx_action_t action);
 e_smx_state_t SIMIX_host_execution_get_state(smx_action_t action);
 void SIMIX_host_execution_set_priority(smx_action_t action, double priority);
+void SIMIX_host_execution_set_bound(smx_action_t action, double bound);
+void SIMIX_host_execution_set_affinity(smx_action_t action, smx_host_t host, unsigned long mask);
 void SIMIX_pre_host_execution_wait(smx_simcall_t simcall, smx_action_t action);
 xbt_dict_t SIMIX_host_get_storage_list(smx_host_t host);
 
@@ -66,6 +75,8 @@ xbt_dict_t SIMIX_host_get_storage_list(smx_host_t host);
 smx_host_t SIMIX_pre_host_get_by_name(smx_simcall_t, const char*);
 const char* SIMIX_pre_host_self_get_name(smx_simcall_t);
 const char* SIMIX_pre_host_get_name(smx_simcall_t, smx_host_t);
+void SIMIX_pre_host_on(smx_simcall_t, smx_host_t host);
+void SIMIX_pre_host_off(smx_simcall_t, smx_host_t host);
 xbt_dict_t SIMIX_pre_host_get_properties(smx_simcall_t, smx_host_t);
 int SIMIX_pre_host_get_core(smx_simcall_t, smx_host_t);
 xbt_swag_t SIMIX_pre_host_get_process_list(smx_simcall_t, smx_host_t host);
@@ -80,7 +91,7 @@ double SIMIX_pre_host_get_consumed_energy(smx_simcall_t, smx_host_t);
 void* SIMIX_pre_host_self_get_data(smx_simcall_t);
 void* SIMIX_pre_host_get_data(smx_simcall_t, smx_host_t);
 void SIMIX_pre_host_set_data(smx_simcall_t, smx_host_t, void*);
-smx_action_t SIMIX_pre_host_execute(smx_simcall_t, const char*, smx_host_t, double, double);
+smx_action_t SIMIX_pre_host_execute(smx_simcall_t, const char*, smx_host_t, double, double, double, unsigned long);
 smx_action_t SIMIX_pre_host_parallel_execute(smx_simcall_t, const char*, int, smx_host_t*,
                                              double*, double*, double, double);
 void SIMIX_pre_host_execution_destroy(smx_simcall_t, smx_action_t);
@@ -88,6 +99,8 @@ void SIMIX_pre_host_execution_cancel(smx_simcall_t, smx_action_t);
 double SIMIX_pre_host_execution_get_remains(smx_simcall_t, smx_action_t);
 e_smx_state_t SIMIX_pre_host_execution_get_state(smx_simcall_t, smx_action_t);
 void SIMIX_pre_host_execution_set_priority(smx_simcall_t, smx_action_t, double);
+void SIMIX_pre_host_execution_set_bound(smx_simcall_t simcall, smx_action_t action, double bound);
+void SIMIX_pre_host_execution_set_affinity(smx_simcall_t simcall, smx_action_t action, smx_host_t host, unsigned long mask);
 
 void SIMIX_host_execution_suspend(smx_action_t action);
 void SIMIX_host_execution_resume(smx_action_t action);
@@ -99,6 +112,57 @@ void SIMIX_pre_set_category(smx_simcall_t simcall, smx_action_t action,
                            const char *category);
 void SIMIX_set_category(smx_action_t action, const char *category);
 #endif
+/* vm related stuff */
+smx_host_t SIMIX_vm_create(const char *name, smx_host_t ind_phys_host);
+smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host);
+
+void SIMIX_vm_destroy(smx_host_t ind_vm);
+void SIMIX_pre_vm_destroy(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_resume(smx_host_t ind_vm, smx_process_t issuer);
+void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm);
+
+void SIMIX_vm_suspend(smx_host_t ind_vm, smx_process_t issuer);
+void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_save(smx_host_t ind_vm, smx_process_t issuer);
+void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm);
+
+void SIMIX_vm_restore(smx_host_t ind_vm, smx_process_t issuer);
+void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_start(smx_host_t ind_vm);
+void SIMIX_pre_vm_start(smx_simcall_t simcall, smx_host_t ind_vm);
+
+void SIMIX_vm_shutdown(smx_host_t ind_vm, smx_process_t issuer);
+void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_set_state(smx_host_t ind_vm, int state);
+void SIMIX_pre_vm_set_state(smx_simcall_t simcall, smx_host_t ind_vm, int state);
+
+int SIMIX_vm_get_state(smx_host_t ind_vm);
+int SIMIX_pre_vm_get_state(smx_simcall_t simcall, smx_host_t ind_vm);
+// --
+void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm);
+void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm);
+
+void *SIMIX_vm_get_pm(smx_host_t ind_vm);
+void *SIMIX_pre_vm_get_pm(smx_simcall_t simcall, smx_host_t ind_vm);
+
+void SIMIX_vm_set_bound(smx_host_t ind_vm, double bound);
+void SIMIX_pre_vm_set_bound(smx_simcall_t simcall, smx_host_t ind_vm, double bound);
+
+void SIMIX_vm_set_affinity(smx_host_t ind_vm, smx_host_t ind_pm, unsigned long mask);
+void SIMIX_pre_vm_set_affinity(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_pm, unsigned long mask);
+
+void SIMIX_host_get_params(smx_host_t ind_vm, ws_params_t params);
+void SIMIX_pre_host_get_params(smx_simcall_t simcall, smx_host_t ind_vm, ws_params_t params);
+
+void SIMIX_host_set_params(smx_host_t ind_vm, ws_params_t params);
+void SIMIX_pre_host_set_params(smx_simcall_t simcall, smx_host_t ind_vm, ws_params_t params);
+#ifdef __cplusplus
+}
+#endif
 
 #endif
 
index ee36fa4..f3ba022 100644 (file)
@@ -5,7 +5,7 @@
  * under the terms of the license (GNU LGPL) which comes with this package. */
 
 #include "smx_private.h"
-#include "surf/storage_private.h"
+//#include "surf/storage_private.h"
 #include "xbt/sysdep.h"
 #include "xbt/log.h"
 #include "xbt/dict.h"
@@ -84,8 +84,7 @@ smx_action_t SIMIX_file_read(smx_process_t process, smx_file_t fd, sg_storage_si
   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));
   }
@@ -98,10 +97,9 @@ smx_action_t SIMIX_file_read(smx_process_t process, smx_file_t fd, sg_storage_si
 #endif
 
   action->io.host = host;
-  action->io.surf_io =
-      surf_workstation_model->extension.workstation.read(host, fd->surf_file, size);
+  action->io.surf_io = surf_workstation_read(host, fd->surf_file, size);
 
-  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;
@@ -121,8 +119,7 @@ smx_action_t SIMIX_file_write(smx_process_t process, smx_file_t fd, sg_storage_s
   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));
   }
@@ -135,10 +132,9 @@ smx_action_t SIMIX_file_write(smx_process_t process, smx_file_t fd, sg_storage_s
 #endif
 
   action->io.host = host;
-  action->io.surf_io =
-      surf_workstation_model->extension.workstation.write(host, fd->surf_file, size);
+  action->io.surf_io = surf_workstation_write(host, fd->surf_file, size);
 
-  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;
@@ -160,8 +156,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));
   }
@@ -174,10 +169,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;
@@ -197,8 +191,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));
   }
@@ -211,9 +204,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;
@@ -230,13 +223,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)){
     xbt_free(fd);
     return 1;
   } else
@@ -256,7 +248,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));
   }
@@ -269,9 +261,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;
 }
@@ -284,8 +276,7 @@ sg_storage_size_t SIMIX_pre_file_get_size(smx_simcall_t simcall, smx_file_t fd)
 sg_storage_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);
 }
 
 xbt_dynar_t SIMIX_pre_file_get_info(smx_simcall_t simcall, smx_file_t fd)
@@ -296,8 +287,7 @@ xbt_dynar_t SIMIX_pre_file_get_info(smx_simcall_t simcall, smx_file_t fd)
 xbt_dynar_t SIMIX_file_get_info(smx_process_t process, smx_file_t fd)
 {
   smx_host_t host = process->smx_host;
-  return  surf_workstation_model->extension.workstation.get_info(host,
-      fd->surf_file);
+  return  surf_workstation_get_info(host, fd->surf_file);
 }
 
 void SIMIX_pre_storage_file_rename(smx_simcall_t simcall, smx_storage_t storage, const char* src, const char* dest)
@@ -307,7 +297,7 @@ void SIMIX_pre_storage_file_rename(smx_simcall_t simcall, smx_storage_t storage,
 
 void SIMIX_storage_file_rename(smx_process_t process, smx_storage_t storage, const char* src, const char* dest)
 {
-  return  surf_storage_model->extension.storage.rename(storage, src, dest);
+  return  surf_storage_rename(storage, src, dest);
 }
 
 sg_storage_size_t SIMIX_pre_storage_get_free_size(smx_simcall_t simcall, const char* name)
@@ -318,7 +308,7 @@ sg_storage_size_t SIMIX_pre_storage_get_free_size(smx_simcall_t simcall, const c
 sg_storage_size_t SIMIX_storage_get_free_size(smx_process_t process, const char* name)
 {
   smx_host_t host = process->smx_host;
-  return  surf_workstation_model->extension.workstation.get_free_size(host,name);
+  return  surf_workstation_get_free_size(host, name);
 }
 
 sg_storage_size_t SIMIX_pre_storage_get_used_size(smx_simcall_t simcall, const char* name)
@@ -329,7 +319,7 @@ sg_storage_size_t SIMIX_pre_storage_get_used_size(smx_simcall_t simcall, const c
 sg_storage_size_t SIMIX_storage_get_used_size(smx_process_t process, const char* name)
 {
   smx_host_t host = process->smx_host;
-  return  surf_workstation_model->extension.workstation.get_used_size(host,name);
+  return  surf_workstation_get_used_size(host, name);
 }
 
 xbt_dict_t SIMIX_pre_storage_get_properties(smx_simcall_t simcall, smx_storage_t storage){
@@ -337,7 +327,7 @@ xbt_dict_t SIMIX_pre_storage_get_properties(smx_simcall_t simcall, smx_storage_t
 }
 xbt_dict_t SIMIX_storage_get_properties(smx_storage_t storage){
   xbt_assert((storage != NULL), "Invalid parameters (simix storage is NULL)");
-  return surf_storage_model->extension.storage.get_properties(storage);
+  return surf_resource_get_properties(surf_workstation_resource_priv(storage));
 }
 
 const char* SIMIX_pre_storage_get_name(smx_simcall_t simcall, smx_storage_t storage){
@@ -375,12 +365,12 @@ xbt_dict_t SIMIX_pre_storage_get_content(smx_simcall_t simcall, smx_storage_t st
 
 xbt_dict_t SIMIX_storage_get_content(smx_storage_t storage){
   xbt_assert((storage != NULL), "Invalid parameters (simix storage is NULL)");
-  return surf_storage_model->extension.storage.get_content(storage);
+  return surf_storage_get_content(storage);
 }
 
 sg_storage_size_t SIMIX_storage_get_size(smx_storage_t storage){
   xbt_assert((storage != NULL), "Invalid parameters (simix storage is NULL)");
-  return surf_storage_model->extension.storage.get_size(storage);
+  return surf_storage_get_size(storage);
 }
 
 void SIMIX_post_io(smx_action_t action)
@@ -396,7 +386,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(action->io.surf_io);
       simcall_file_open__set__result(simcall, tmp);
       break;
 
@@ -404,13 +394,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:
@@ -422,14 +411,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(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;
@@ -451,7 +440,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);
 }
 
@@ -481,8 +470,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;
     }
 
index 7f9689a..6188ec6 100644 (file)
@@ -341,17 +341,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;
   }
 }
@@ -730,8 +730,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(simcall->issuer->smx_host, timeout);
+    surf_action_set_data(sleep, action);
 
     if (simcall->issuer == action->comm.src_proc)
       action->comm.src_timeout = sleep;
@@ -847,15 +847,16 @@ static 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_model_communicate(surf_workstation_model,
+                                                                   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;
@@ -875,7 +876,7 @@ static 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);
 
     }
   }
@@ -981,8 +982,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;
     }
 
@@ -1014,19 +1014,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
@@ -1067,7 +1067,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);
   }
 }
 
@@ -1075,7 +1075,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() */
 }
 
@@ -1083,7 +1083,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() */
 }
 
@@ -1108,7 +1108,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:
index eb0a9f1..01c3b5a 100644 (file)
@@ -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;
     }
 
index bc5c087..0ac19c0 100644 (file)
@@ -491,7 +491,8 @@ smx_action_t SIMIX_process_suspend(smx_process_t process, smx_process_t issuer)
       return NULL;
     }
   } else {
-    return SIMIX_host_execute("suspend", process->smx_host, 0.0, 1.0);
+    /* FIXME: computation size is zero. Is it okay that bound is zero ? */
+    return SIMIX_host_execute("suspend", process->smx_host, 0.0, 1.0, 0.0, 0);
   }
 }
 
@@ -695,8 +696,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));
   }
@@ -710,9 +710,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;
@@ -723,9 +723,11 @@ void SIMIX_post_process_sleep(smx_action_t action)
   smx_simcall_t simcall;
   e_smx_state_t state;
 
+  xbt_assert(action->type == SIMIX_ACTION_SLEEP);
+
   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");
@@ -740,8 +742,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);
@@ -755,19 +756,23 @@ void SIMIX_post_process_sleep(smx_action_t action)
 void SIMIX_process_sleep_destroy(smx_action_t action)
 {
   XBT_DEBUG("Destroy action %p", action);
+  xbt_assert(action->type == SIMIX_ACTION_SLEEP);
+
   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);
+  xbt_assert(action->type == SIMIX_ACTION_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);
+  xbt_assert(action->type == SIMIX_ACTION_SLEEP);
+  surf_action_resume(action->sleep.surf_sleep);
 }
 
 /** 
index aec3439..a5a3e27 100644 (file)
@@ -49,6 +49,8 @@ void SIMIX_simcall_pre(smx_simcall_t simcall, int value)
 {
   XBT_DEBUG("Handling simcall %p: %s", simcall, SIMIX_simcall_name(simcall->call));
   simcall->mc_value = value;
+  if (simcall->issuer->context->iwannadie && simcall->call != SIMCALL_PROCESS_CLEANUP)
+    return;
   switch (simcall->call) {
 SIMCALL_LIST(SIMCALL_CASE, SIMCALL_SEP_NOTHING)
     case NUM_SIMCALLS:;
index 6f7f8a4..89b6d68 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007-2010, 2012-2013. The SimGrid Team.
+ /* Copyright (c) 2007-2010, 2012-2013. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
 #define TULONG(n) (n, unsigned long, ul)
 #define TFLOAT(n) (n, float, f)
 #define TDOUBLE(n) (n, double, d)
-#define TPTR(n) (n, void*, p)
+#define TDPTR(n) (n, void*, dp, void*)
+#define TFPTR(n) (n, FPtr, fp, FPtr)
 #define TCPTR(n) (n, const void*, cp)
 #define TSIZE(n) (n, size_t, si)
 #define TSGSTSIZE(n) (n, sg_storage_size_t, sgstsi)
 #define TVOID(n) (n, void)
-#define TSPEC(n,t) (n, t, p)
+#define TDSPEC(n,t) (n, t, dp, void*)
+#define TFSPEC(n,t) (n, t, fp, FPtr)
 
 /* use comma or nothing to separate elements*/
 #define SIMCALL_SEP_COMMA ,
 #define SIMCALL_SEP_NOTHING
 
 /* get the name of the parameter */
-#define SIMCALL_NAME_(name, type, field) name
+#define SIMCALL_NAME_(name, type, field, ...) name
 #define SIMCALL_NAME(i, v) SIMCALL_NAME_ v
 
+/* get the cast of the parameter */
+#define SIMCALL_CASTTYPE_(name, type, field, cast) (cast)
+#define SIMCALL_NOCASTTYPE_(name, type, field) 
+#define SIMCALL_CASTTYPE(...) MAYBE5(,##__VA_ARGS__, SIMCALL_CASTTYPE_, SIMCALL_NOCASTTYPE_) (__VA_ARGS__)
+
+/* get the uncast of the parameter */
+#define SIMCALL_UNCASTTYPE_(name, type, field, cast) (type)
+#define SIMCALL_NOUNCASTTYPE_(name, type, field) 
+#define SIMCALL_UNCASTTYPE(...) MAYBE5(,##__VA_ARGS__, SIMCALL_UNCASTTYPE_, SIMCALL_NOUNCASTTYPE_) (__VA_ARGS__)
+
 /* get the %s format code of the parameter */
-#define SIMCALL_FORMAT_(name, type, field) %field
+#define SIMCALL_FORMAT_(name, type, field, ...) %field
 #define SIMCALL_FORMAT(i, v) SIMCALL_FORMAT_ v
 
 /* get the field of the parameter */
-#define SIMCALL_FIELD_(name, type, field) field
+#define SIMCALL_FIELD_(name, type, field, ...) field
 #define SIMCALL_FIELD(i, v) SIMCALL_FIELD_ v
 
 /* get the parameter declaration */
-#define SIMCALL_ARG_(name, type, field) type name
+#define SIMCALL_ARG_(name, type, field, ...) type name
 #define SIMCALL_ARG(i, v) SIMCALL_ARG_ v
 
 /* get the parameter initialisation field */
-#define SIMCALL_INIT_FIELD_(name, type, field) .field = name
+#define SIMCALL_INIT_FIELD_(name, type, field, ...) .field = SIMCALL_CASTTYPE(name, type, field,##__VA_ARGS__) name
 #define SIMCALL_INIT_FIELD(i, d, v) self->simcall.args[i]SIMCALL_INIT_FIELD_ v;
 
 /* get the case of the parameter */
-#define SIMCALL_CASE_PARAM_(name, type, field) field
-#define SIMCALL_CASE_PARAM(i, v) simcall->args[i].SIMCALL_CASE_PARAM_ v
+#define SIMCALL_CASE_PARAM_(name, type, field, ...) field
+#define SIMCALL_CASE_PARAM(i, v) SIMCALL_UNCASTTYPE v simcall->args[i].SIMCALL_CASE_PARAM_ v
 
 /* generate some code for SIMCALL_CASE if the simcall has an answer */
+#define MAYBE5(_0, _1, _2, _3, _4, func, ...) func
+#define MAYBE3(_0, _1, _2, func, ...) func
 #define MAYBE2(_0, _1, func, ...) func
 
-#define SIMCALL_WITH_RESULT_BEGIN(name, type, field) simcall->result.field =
+#define SIMCALL_WITH_RESULT_BEGIN(name, type, field, ...) simcall->result.field =
 #define SIMCALL_WITHOUT_RESULT_BEGIN(name, type, field)
 #define SIMCALL_RESULT_BEGIN_(name, type, ...)\
-        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_RESULT_BEGIN, SIMCALL_WITHOUT_RESULT_BEGIN)\
+        MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_RESULT_BEGIN, SIMCALL_WITH_RESULT_BEGIN, SIMCALL_WITHOUT_RESULT_BEGIN)\
        (name, type, __VA_ARGS__)
 #define SIMCALL_RESULT_BEGIN(answer, res) answer(SIMCALL_RESULT_BEGIN_ res)
 
 #define SIMCALL_WITH_FUNC_SIMCALL(name, type, field) smx_simcall_t simcall = 
 #define SIMCALL_WITHOUT_FUNC_SIMCALL(name, type, field)
 #define SIMCALL_FUNC_SIMCALL_(name, type, ...)\
-        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_FUNC_SIMCALL, SIMCALL_WITHOUT_FUNC_SIMCALL)\
+        MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_FUNC_SIMCALL, SIMCALL_WITH_FUNC_SIMCALL, SIMCALL_WITHOUT_FUNC_SIMCALL)\
        (name, type, __VA_ARGS__)
 #define SIMCALL_FUNC_SIMCALL(res) SIMCALL_FUNC_SIMCALL_ res
 
-#define SIMCALL_WITH_FUNC_RETURN(name, type, field) 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, ...)\
-        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_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
 
 /* generate the simcalls args getter/setter */
 #define SIMCALL_ARG_GETSET_(i, name, v) \
   static inline SIMCALL_FUNC_RETURN_TYPE(v) SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME(name), get, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall){\
-    return simcall->args[i].SIMCALL_FIELD_ v ;\
+    return (SIMCALL_FUNC_RETURN_TYPE(v)) simcall->args[i].SIMCALL_FIELD_ v ;\
   }\
   static inline void SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME(name), set, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall, SIMCALL_ARG_ v){\
-    simcall->args[i].SIMCALL_FIELD_ v = SIMCALL_NAME_ v ;\
+    simcall->args[i].SIMCALL_FIELD_ v = SIMCALL_CASTTYPE v SIMCALL_NAME_ v ;\
   }
 
 #define SIMCALL_ARG_GETSET(type, name, answer, res, ...)\
 /* generate the simcalls result getter/setter */
 #define SIMCALL_WITH_RES_GETSET(name, v) \
   static inline SIMCALL_FUNC_RETURN_TYPE(v) SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME((name)), get, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall){\
-    return simcall->result.SIMCALL_FIELD_ v ;\
+    return (SIMCALL_FUNC_RETURN_TYPE(v)) simcall->result.SIMCALL_FIELD_ v ;\
   }\
   static inline void SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME((name)), set, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall, SIMCALL_ARG_ v){\
     simcall->result.SIMCALL_FIELD_ v = SIMCALL_NAME_ v ;\
   }
 #define SIMCALL_WITHOUT_RES_GETSET(name, v)
 #define SIMCALL_RES_GETSET__(name, type, ...)\
-        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_RES_GETSET, SIMCALL_WITHOUT_RES_GETSET)
+        MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_RES_GETSET, SIMCALL_WITH_RES_GETSET, SIMCALL_WITHOUT_RES_GETSET)
 #define SIMCALL_RES_GETSET_(scname, v)\
         SIMCALL_RES_GETSET__ v (scname, v)
 #define SIMCALL_RES_GETSET(type, name, answer, res, ...)\
   inline void SIMCALL_GS_FUNC(SIMCALL_GS_SC_NAME((name)), set, SIMCALL_GS_ARG_NAME(v))(smx_simcall_t simcall, SIMCALL_ARG_ v);
 #define SIMCALL_WITHOUT_RES_GETSET_PROTO(name, v)
 #define SIMCALL_RES_GETSET_PROTO__(name, type, ...)\
-        MAYBE2(,##__VA_ARGS__, SIMCALL_WITH_RES_GETSET_PROTO, SIMCALL_WITHOUT_RES_GETSET_PROTO)
+        MAYBE3(,##__VA_ARGS__, SIMCALL_WITH_RES_GETSET_PROTO, SIMCALL_WITHOUT_RES_GETSET_PROTO, SIMCALL_WITHOUT_RES_GETSET_PROTO)
 #define SIMCALL_RES_GETSET_PROTO_(scname, v)\
         SIMCALL_RES_GETSET_PROTO__ v (scname, v)
 #define SIMCALL_RES_GETSET_PROTO(type, name, answer, res, ...)\
 
 /* the list of simcalls definitions */
 #define SIMCALL_LIST1(ACTION, sep) \
-ACTION(SIMCALL_HOST_GET_BY_NAME, host_get_by_name, WITH_ANSWER, TSPEC(result, smx_host_t), TSTRING(name)) sep \
-ACTION(SIMCALL_HOST_GET_NAME, host_get_name, WITH_ANSWER, TSTRING(result), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_GET_PROPERTIES, host_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_GET_CORE, host_get_core, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_GET_PROCESS_LIST, host_get_process_list, WITH_ANSWER, TSPEC(result, xbt_swag_t), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_GET_SPEED, host_get_speed, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_GET_AVAILABLE_SPEED, host_get_available_speed, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_GET_STATE, host_get_state, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_GET_DATA, host_get_data, WITH_ANSWER, TPTR(result), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_SET_DATA, host_set_data, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t), TPTR(data)) sep \
-ACTION(SIMCALL_HOST_GET_CURRENT_POWER_PEAK, host_get_current_power_peak, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_GET_POWER_PEAK_AT, host_get_power_peak_at, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t), TINT(pstate_index)) sep \
-ACTION(SIMCALL_HOST_GET_NB_PSTATES, host_get_nb_pstates, WITH_ANSWER, TINT(result), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_SET_POWER_PEAK_AT, host_set_power_peak_at, WITH_ANSWER, TVOID(result), TSPEC(host, smx_host_t), TINT(pstate_index)) sep \
-ACTION(SIMCALL_HOST_GET_CONSUMED_ENERGY, host_get_consumed_energy, WITH_ANSWER, TDOUBLE(result), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_HOST_EXECUTE, host_execute, WITH_ANSWER, TSPEC(result, smx_action_t), TSTRING(name), TSPEC(host, smx_host_t), TDOUBLE(computation_amount), TDOUBLE(priority)) sep \
-ACTION(SIMCALL_HOST_PARALLEL_EXECUTE, host_parallel_execute, WITH_ANSWER, TSPEC(result, smx_action_t), TSTRING(name), TINT(host_nb), TSPEC(host_list, smx_host_t*), TSPEC(computation_amount, double*), TSPEC(communication_amount, double*), TDOUBLE(amount), TDOUBLE(rate)) sep \
-ACTION(SIMCALL_HOST_EXECUTION_DESTROY, host_execution_destroy, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t)) sep \
-ACTION(SIMCALL_HOST_EXECUTION_CANCEL, host_execution_cancel, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t)) sep \
-ACTION(SIMCALL_HOST_EXECUTION_GET_REMAINS, host_execution_get_remains, WITH_ANSWER, TDOUBLE(result), TSPEC(execution, smx_action_t)) sep \
-ACTION(SIMCALL_HOST_EXECUTION_GET_STATE, host_execution_get_state, WITH_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
-ACTION(SIMCALL_HOST_EXECUTION_SET_PRIORITY, host_execution_set_priority, WITH_ANSWER, TVOID(result), TSPEC(execution, smx_action_t), TDOUBLE(priority)) sep \
-ACTION(SIMCALL_HOST_EXECUTION_WAIT, host_execution_wait, WITHOUT_ANSWER, TINT(result), TSPEC(execution, smx_action_t)) sep \
-ACTION(SIMCALL_HOST_GET_STORAGE_LIST, host_get_storage_list, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_PROCESS_CREATE, process_create, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t*), TSTRING(name), TSPEC(code, xbt_main_func_t), TPTR(data), TSTRING(hostname), TDOUBLE(kill_time), TINT(argc), TSPEC(argv, char**), TSPEC(properties, xbt_dict_t), TINT(auto_restart)) sep \
-ACTION(SIMCALL_PROCESS_KILL, process_kill, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_HOST_GET_BY_NAME, host_get_by_name, WITH_ANSWER, TDSPEC(result, smx_host_t), TSTRING(name)) sep \
+ACTION(SIMCALL_HOST_GET_NAME, host_get_name, WITH_ANSWER, TSTRING(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_ON, host_on, WITH_ANSWER, TVOID(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_OFF, host_off, WITH_ANSWER, TVOID(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_GET_PROPERTIES, host_get_properties, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_GET_CORE, host_get_core, WITH_ANSWER, TINT(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_GET_PROCESS_LIST, host_get_process_list, WITH_ANSWER, TDSPEC(result, xbt_swag_t), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_GET_SPEED, host_get_speed, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_GET_AVAILABLE_SPEED, host_get_available_speed, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_GET_STATE, host_get_state, WITH_ANSWER, TINT(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_GET_DATA, host_get_data, WITH_ANSWER, TDPTR(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_SET_DATA, host_set_data, WITH_ANSWER, TVOID(result), TDSPEC(host, smx_host_t), TDPTR(data)) sep \
+ACTION(SIMCALL_HOST_GET_CURRENT_POWER_PEAK, host_get_current_power_peak, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_GET_POWER_PEAK_AT, host_get_power_peak_at, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t), TINT(pstate_index)) sep \
+ACTION(SIMCALL_HOST_GET_NB_PSTATES, host_get_nb_pstates, WITH_ANSWER, TINT(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_SET_POWER_PEAK_AT, host_set_power_peak_at, WITH_ANSWER, TVOID(result), TDSPEC(host, smx_host_t), TINT(pstate_index)) sep \
+ACTION(SIMCALL_HOST_GET_CONSUMED_ENERGY, host_get_consumed_energy, WITH_ANSWER, TDOUBLE(result), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_EXECUTE, host_execute, WITH_ANSWER, TDSPEC(result, smx_action_t), TSTRING(name), TDSPEC(host, smx_host_t), TDOUBLE(computation_amount), TDOUBLE(priority), TDOUBLE(bound), TULONG(affinity_mask)) sep \
+ACTION(SIMCALL_HOST_PARALLEL_EXECUTE, host_parallel_execute, WITH_ANSWER, TDSPEC(result, smx_action_t), TSTRING(name), TINT(host_nb), TDSPEC(host_list, smx_host_t*), TDSPEC(computation_amount, double*), TDSPEC(communication_amount, double*), TDOUBLE(amount), TDOUBLE(rate)) sep \
+ACTION(SIMCALL_HOST_EXECUTION_DESTROY, host_execution_destroy, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t)) sep \
+ACTION(SIMCALL_HOST_EXECUTION_CANCEL, host_execution_cancel, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t)) sep \
+ACTION(SIMCALL_HOST_EXECUTION_GET_REMAINS, host_execution_get_remains, WITH_ANSWER, TDOUBLE(result), TDSPEC(execution, smx_action_t)) sep \
+ACTION(SIMCALL_HOST_EXECUTION_GET_STATE, host_execution_get_state, WITH_ANSWER, TINT(result), TDSPEC(execution, smx_action_t)) sep \
+ACTION(SIMCALL_HOST_EXECUTION_SET_PRIORITY, host_execution_set_priority, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t), TDOUBLE(priority)) sep \
+ACTION(SIMCALL_HOST_EXECUTION_SET_BOUND, host_execution_set_bound, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t), TDOUBLE(bound)) sep \
+ACTION(SIMCALL_HOST_EXECUTION_SET_AFFINITY, host_execution_set_affinity, WITH_ANSWER, TVOID(result), TDSPEC(execution, smx_action_t), TDSPEC(ws, smx_host_t), TULONG(mask)) sep \
+ACTION(SIMCALL_HOST_EXECUTION_WAIT, host_execution_wait, WITHOUT_ANSWER, TINT(result), TDSPEC(execution, smx_action_t)) sep \
+ACTION(SIMCALL_HOST_GET_STORAGE_LIST, host_get_storage_list, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_HOST_GET_PARAMS, host_get_params, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDSPEC(params, ws_params_t)) sep \
+ACTION(SIMCALL_HOST_SET_PARAMS, host_set_params, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDSPEC(params, ws_params_t)) sep \
+ACTION(SIMCALL_VM_CREATE, vm_create, WITH_ANSWER, TDPTR(result), TSTRING(name), TDSPEC(ind_pm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_START, vm_start, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SET_STATE, vm_set_state, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TINT(state)) sep \
+ACTION(SIMCALL_VM_GET_STATE, vm_get_state, WITH_ANSWER, TINT(result), TDSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_MIGRATE, vm_migrate, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDSPEC(ind_dst_pm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_GET_PM, vm_get_pm, WITH_ANSWER,    TDPTR(result),  TDSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SET_BOUND,    vm_set_bound,    WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDOUBLE(bound)) sep \
+ACTION(SIMCALL_VM_SET_AFFINITY, vm_set_affinity, WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t), TDSPEC(ind_pm, smx_host_t), TULONG(mask)) sep \
+ACTION(SIMCALL_VM_DESTROY,   vm_destroy,   WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SUSPEND,   vm_suspend,   WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_RESUME,    vm_resume,    WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SHUTDOWN,  vm_shutdown,  WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_SAVE,      vm_save,      WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_VM_RESTORE,   vm_restore,   WITH_ANSWER, TVOID(result), TDSPEC(ind_vm, smx_host_t)) sep \
+ACTION(SIMCALL_PROCESS_CREATE, process_create, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t*), TSTRING(name), TFSPEC(code, xbt_main_func_t), TDPTR(data), TSTRING(hostname), TDOUBLE(kill_time), TINT(argc), TDSPEC(argv, char**), TDSPEC(properties, xbt_dict_t), TINT(auto_restart)) sep \
+ACTION(SIMCALL_PROCESS_KILL, process_kill, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t)) sep \
 ACTION(SIMCALL_PROCESS_KILLALL, process_killall, WITH_ANSWER, TVOID(result), TINT(reset_pid)) sep \
-ACTION(SIMCALL_PROCESS_CLEANUP, process_cleanup, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
-ACTION(SIMCALL_PROCESS_CHANGE_HOST, process_change_host, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TSPEC(dest, smx_host_t)) sep \
-ACTION(SIMCALL_PROCESS_SUSPEND, process_suspend, WITHOUT_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
-ACTION(SIMCALL_PROCESS_RESUME, process_resume, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_PROCESS_CLEANUP, process_cleanup, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_PROCESS_CHANGE_HOST, process_change_host, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t), TDSPEC(dest, smx_host_t)) sep \
+ACTION(SIMCALL_PROCESS_SUSPEND, process_suspend, WITHOUT_ANSWER, TVOID(result), TDSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_PROCESS_RESUME, process_resume, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t)) sep \
 ACTION(SIMCALL_PROCESS_COUNT, process_count, WITH_ANSWER, TINT(result)) sep \
-ACTION(SIMCALL_PROCESS_GET_PID, process_get_PID, WITH_ANSWER, TINT(result), TSPEC(process, smx_process_t)) sep  \
-ACTION(SIMCALL_PROCESS_GET_PPID, process_get_PPID, WITH_ANSWER, TINT(result), TSPEC(process, smx_process_t)) sep  \
-ACTION(SIMCALL_PROCESS_GET_DATA, process_get_data, WITH_ANSWER, TPTR(result), TSPEC(process, smx_process_t)) sep \
-ACTION(SIMCALL_PROCESS_SET_DATA, process_set_data, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TPTR(data)) sep \
-ACTION(SIMCALL_PROCESS_GET_HOST, process_get_host, WITH_ANSWER, TSPEC(result, smx_host_t), TSPEC(process, smx_process_t)) sep \
-ACTION(SIMCALL_PROCESS_GET_NAME, process_get_name, WITH_ANSWER, TSTRING(result), TSPEC(process, smx_process_t)) sep \
-ACTION(SIMCALL_PROCESS_IS_SUSPENDED, process_is_suspended, WITH_ANSWER, TINT(result), TSPEC(process, smx_process_t)) sep \
-ACTION(SIMCALL_PROCESS_GET_PROPERTIES, process_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_PROCESS_GET_PID, process_get_PID, WITH_ANSWER, TINT(result), TDSPEC(process, smx_process_t)) sep  \
+ACTION(SIMCALL_PROCESS_GET_PPID, process_get_PPID, WITH_ANSWER, TINT(result), TDSPEC(process, smx_process_t)) sep  \
+ACTION(SIMCALL_PROCESS_GET_DATA, process_get_data, WITH_ANSWER, TDPTR(result), TDSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_PROCESS_SET_DATA, process_set_data, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t), TDPTR(data)) sep \
+ACTION(SIMCALL_PROCESS_GET_HOST, process_get_host, WITH_ANSWER, TDSPEC(result, smx_host_t), TDSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_PROCESS_GET_NAME, process_get_name, WITH_ANSWER, TSTRING(result), TDSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_PROCESS_IS_SUSPENDED, process_is_suspended, WITH_ANSWER, TINT(result), TDSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_PROCESS_GET_PROPERTIES, process_get_properties, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(process, smx_process_t)) sep \
 ACTION(SIMCALL_PROCESS_SLEEP, process_sleep, WITHOUT_ANSWER, TINT(result), TDOUBLE(duration)) sep \
-ACTION(SIMCALL_PROCESS_ON_EXIT, process_on_exit, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TSPEC(fun, int_f_pvoid_t), TPTR(data)) sep \
-ACTION(SIMCALL_PROCESS_AUTO_RESTART_SET, process_auto_restart_set, WITH_ANSWER, TVOID(result), TSPEC(process, smx_process_t), TINT(auto_restart)) sep \
-ACTION(SIMCALL_PROCESS_RESTART, process_restart, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(process, smx_process_t)) sep \
-ACTION(SIMCALL_RDV_CREATE, rdv_create, WITH_ANSWER, TSPEC(result, smx_rdv_t), TSTRING(name)) sep \
-ACTION(SIMCALL_RDV_DESTROY, rdv_destroy, WITH_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t)) sep \
-ACTION(SIMCALL_RDV_GET_BY_NAME, rdv_get_by_name, WITH_ANSWER, TSPEC(result, smx_host_t), TSTRING(name)) sep \
-ACTION(SIMCALL_RDV_COMM_COUNT_BY_HOST, rdv_comm_count_by_host, WITH_ANSWER, TUINT(result), TSPEC(rdv, smx_rdv_t), TSPEC(host, smx_host_t)) sep \
-ACTION(SIMCALL_RDV_GET_HEAD, rdv_get_head, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t)) sep \
-ACTION(SIMCALL_RDV_SET_RECV, rdv_set_receiver, WITH_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TSPEC(receiver, smx_process_t)) sep \
-ACTION(SIMCALL_RDV_GET_RECV, rdv_get_receiver, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(rdv, smx_rdv_t)) sep \
-ACTION(SIMCALL_COMM_IPROBE, comm_iprobe, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TINT(src), TINT(tag), TSPEC(match_fun, simix_match_func_t), TPTR(data)) sep \
-ACTION(SIMCALL_COMM_SEND, comm_send, WITHOUT_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TPTR(src_buff), TSIZE(src_buff_size), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(timeout)) sep \
-ACTION(SIMCALL_COMM_ISEND, comm_isend, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TPTR(src_buff), TSIZE(src_buff_size), TSPEC(match_fun, simix_match_func_t), TSPEC(clean_fun, simix_clean_func_t), TPTR(data), TINT(detached)) sep \
-ACTION(SIMCALL_COMM_RECV, comm_recv, WITHOUT_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(timeout)) sep \
-ACTION(SIMCALL_COMM_IRECV, comm_irecv, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data)) sep \
-ACTION(SIMCALL_COMM_RECV_BOUNDED, comm_recv_bounded, WITHOUT_ANSWER, TVOID(result), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(timeout), TDOUBLE(rate)) sep \
-ACTION(SIMCALL_COMM_IRECV_BOUNDED, comm_irecv_bounded, WITH_ANSWER, TSPEC(result, smx_action_t), TSPEC(rdv, smx_rdv_t), TPTR(dst_buff), TSPEC(dst_buff_size, size_t*), TSPEC(match_fun, simix_match_func_t), TPTR(data), TDOUBLE(rate)) sep \
-ACTION(SIMCALL_COMM_DESTROY, comm_destroy, WITH_ANSWER, TVOID(result), TSPEC(comm, smx_action_t)) sep \
-ACTION(SIMCALL_COMM_CANCEL, comm_cancel, WITH_ANSWER, TVOID(result), TSPEC(comm, smx_action_t)) sep \
-ACTION(SIMCALL_COMM_WAITANY, comm_waitany, WITHOUT_ANSWER, TINT(result), TSPEC(comms, xbt_dynar_t)) sep \
-ACTION(SIMCALL_COMM_WAIT, comm_wait, WITHOUT_ANSWER, TVOID(result), TSPEC(comm, smx_action_t), TDOUBLE(timeout)) sep \
-ACTION(SIMCALL_COMM_TEST, comm_test, WITHOUT_ANSWER, TINT(result), TSPEC(comm, smx_action_t)) sep \
-ACTION(SIMCALL_COMM_TESTANY, comm_testany, WITHOUT_ANSWER, TINT(result), TSPEC(comms, xbt_dynar_t)) sep \
-ACTION(SIMCALL_COMM_GET_REMAINS, comm_get_remains, WITH_ANSWER, TDOUBLE(result), TSPEC(comm, smx_action_t)) sep \
-ACTION(SIMCALL_COMM_GET_STATE, comm_get_state, WITH_ANSWER, TINT(result), TSPEC(comm, smx_action_t)) sep \
-ACTION(SIMCALL_COMM_GET_SRC_DATA, comm_get_src_data, WITH_ANSWER, TPTR(result), TSPEC(comm, smx_action_t)) sep \
-ACTION(SIMCALL_COMM_GET_DST_DATA, comm_get_dst_data, WITH_ANSWER, TPTR(result), TSPEC(comm, smx_action_t)) sep \
-ACTION(SIMCALL_COMM_GET_SRC_PROC, comm_get_src_proc, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(comm, smx_action_t)) sep \
-ACTION(SIMCALL_COMM_GET_DST_PROC, comm_get_dst_proc, WITH_ANSWER, TSPEC(result, smx_process_t), TSPEC(comm, smx_action_t)) sep \
-ACTION(SIMCALL_MUTEX_INIT, mutex_init, WITH_ANSWER, TSPEC(result, smx_mutex_t)) sep \
-ACTION(SIMCALL_MUTEX_DESTROY, mutex_destroy, WITH_ANSWER, TVOID(result), TSPEC(mutex, smx_mutex_t)) sep \
-ACTION(SIMCALL_MUTEX_LOCK, mutex_lock, WITHOUT_ANSWER, TVOID(result), TSPEC(mutex, smx_mutex_t)) sep \
-ACTION(SIMCALL_MUTEX_TRYLOCK, mutex_trylock, WITH_ANSWER, TINT(result), TSPEC(mutex, smx_mutex_t)) sep \
-ACTION(SIMCALL_MUTEX_UNLOCK, mutex_unlock, WITH_ANSWER, TVOID(result), TSPEC(mutex, smx_mutex_t)) sep \
-ACTION(SIMCALL_COND_INIT, cond_init, WITH_ANSWER, TSPEC(result, smx_cond_t)) sep \
-ACTION(SIMCALL_COND_DESTROY, cond_destroy, WITH_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t)) sep \
-ACTION(SIMCALL_COND_SIGNAL, cond_signal, WITH_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t)) sep \
-ACTION(SIMCALL_COND_WAIT, cond_wait, WITHOUT_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t), TSPEC(mutex, smx_mutex_t)) sep \
-ACTION(SIMCALL_COND_WAIT_TIMEOUT, cond_wait_timeout, WITHOUT_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t), TSPEC(mutex, smx_mutex_t), TDOUBLE(timeout)) sep \
-ACTION(SIMCALL_COND_BROADCAST, cond_broadcast, WITH_ANSWER, TVOID(result), TSPEC(cond, smx_cond_t)) sep \
-ACTION(SIMCALL_SEM_INIT, sem_init, WITH_ANSWER, TSPEC(result, smx_sem_t), TINT(capacity)) sep \
-ACTION(SIMCALL_SEM_DESTROY, sem_destroy, WITH_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t)) sep \
-ACTION(SIMCALL_SEM_RELEASE, sem_release, WITH_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t)) sep \
-ACTION(SIMCALL_SEM_WOULD_BLOCK, sem_would_block, WITH_ANSWER, TINT(result), TSPEC(sem, smx_sem_t)) sep \
-ACTION(SIMCALL_SEM_ACQUIRE, sem_acquire, WITHOUT_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t)) sep \
-ACTION(SIMCALL_SEM_ACQUIRE_TIMEOUT, sem_acquire_timeout, WITHOUT_ANSWER, TVOID(result), TSPEC(sem, smx_sem_t), TDOUBLE(timeout)) sep \
-ACTION(SIMCALL_SEM_GET_CAPACITY, sem_get_capacity, WITH_ANSWER, TINT(result), TSPEC(sem, smx_sem_t)) sep \
-ACTION(SIMCALL_FILE_GET_DATA, file_get_data, WITH_ANSWER, TPTR(result), TSPEC(fd, smx_file_t)) sep \
-ACTION(SIMCALL_FILE_SET_DATA, file_set_data, WITH_ANSWER, TVOID(result), TSPEC(fd, smx_file_t), TPTR(data)) sep \
-ACTION(SIMCALL_FILE_READ, file_read, WITHOUT_ANSWER, TSGSTSIZE(result), TSPEC(fd, smx_file_t), TSGSTSIZE(size)) sep \
-ACTION(SIMCALL_FILE_WRITE, file_write, WITHOUT_ANSWER, TSGSTSIZE(result), TSPEC(fd, smx_file_t), TSGSTSIZE(size)) sep \
-ACTION(SIMCALL_FILE_OPEN, file_open, WITHOUT_ANSWER, TSPEC(result, smx_file_t), TSTRING(mount), TSTRING(path)) sep \
-ACTION(SIMCALL_FILE_CLOSE, file_close, WITHOUT_ANSWER, TINT(result), TSPEC(fd, smx_file_t)) sep \
-ACTION(SIMCALL_FILE_UNLINK, file_unlink, WITH_ANSWER, TINT(result), TSPEC(fd, smx_file_t)) sep \
-ACTION(SIMCALL_FILE_LS, file_ls, WITHOUT_ANSWER, TSPEC(result, xbt_dict_t), TSTRING(mount), TSTRING(path)) sep \
-ACTION(SIMCALL_FILE_GET_SIZE, file_get_size, WITH_ANSWER, TSGSTSIZE(result), TSPEC(fd, smx_file_t)) sep \
-ACTION(SIMCALL_FILE_GET_INFO, file_get_info, WITH_ANSWER, TSPEC(result, xbt_dynar_t), TSPEC(fd, smx_file_t)) sep \
-ACTION(SIMCALL_STORAGE_FILE_RENAME, storage_file_rename, WITH_ANSWER, TVOID(result), TSPEC(storage, smx_storage_t), TSTRING(src), TSTRING(dest)) sep \
-ACTION(SIMCALL_STORAGE_GET_FREE_SIZE, storage_get_free_size, WITH_ANSWER, TSGSTSIZE(result), TSTRING(name)) sep \
-ACTION(SIMCALL_STORAGE_GET_USED_SIZE, storage_get_used_size, WITH_ANSWER, TSGSTSIZE(result), TSTRING(name)) sep \
-ACTION(SIMCALL_STORAGE_GET_PROPERTIES, storage_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(storage, smx_storage_t)) sep \
-ACTION(SIMCALL_STORAGE_GET_CONTENT, storage_get_content, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSPEC(storage, smx_storage_t)) sep \
-ACTION(SIMCALL_ASR_GET_PROPERTIES, asr_get_properties, WITH_ANSWER, TSPEC(result, xbt_dict_t), TSTRING(name)) sep 
+ACTION(SIMCALL_PROCESS_ON_EXIT, process_on_exit, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t), TFSPEC(fun, int_f_pvoid_t), TDPTR(data)) sep \
+ACTION(SIMCALL_PROCESS_AUTO_RESTART_SET, process_auto_restart_set, WITH_ANSWER, TVOID(result), TDSPEC(process, smx_process_t), TINT(auto_restart)) sep \
+ACTION(SIMCALL_PROCESS_RESTART, process_restart, WITH_ANSWER, TDSPEC(result, smx_process_t), TDSPEC(process, smx_process_t)) sep \
+ACTION(SIMCALL_RDV_CREATE, rdv_create, WITH_ANSWER, TDSPEC(result, smx_rdv_t), TSTRING(name)) sep \
+ACTION(SIMCALL_RDV_DESTROY, rdv_destroy, WITH_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t)) sep \
+ACTION(SIMCALL_RDV_GET_BY_NAME, rdv_get_by_name, WITH_ANSWER, TDSPEC(result, smx_host_t), TSTRING(name)) sep \
+ACTION(SIMCALL_RDV_COMM_COUNT_BY_HOST, rdv_comm_count_by_host, WITH_ANSWER, TUINT(result), TDSPEC(rdv, smx_rdv_t), TDSPEC(host, smx_host_t)) sep \
+ACTION(SIMCALL_RDV_GET_HEAD, rdv_get_head, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t)) sep \
+ACTION(SIMCALL_RDV_SET_RECV, rdv_set_receiver, WITH_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t), TDSPEC(receiver, smx_process_t)) sep \
+ACTION(SIMCALL_RDV_GET_RECV, rdv_get_receiver, WITH_ANSWER, TDSPEC(result, smx_process_t), TDSPEC(rdv, smx_rdv_t)) sep \
+ACTION(SIMCALL_COMM_IPROBE, comm_iprobe, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t), TINT(src), TINT(tag), TFSPEC(match_fun, simix_match_func_t), TDPTR(data)) sep \
+ACTION(SIMCALL_COMM_SEND, comm_send, WITHOUT_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TDPTR(src_buff), TSIZE(src_buff_size), TFSPEC(match_fun, simix_match_func_t), TDPTR(data), TDOUBLE(timeout)) sep \
+ACTION(SIMCALL_COMM_ISEND, comm_isend, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t), TDOUBLE(task_size), TDOUBLE(rate), TDPTR(src_buff), TSIZE(src_buff_size), TFSPEC(match_fun, simix_match_func_t), TFSPEC(clean_fun, simix_clean_func_t), TDPTR(data), TINT(detached)) sep \
+ACTION(SIMCALL_COMM_RECV, comm_recv, WITHOUT_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t), TDPTR(dst_buff), TDSPEC(dst_buff_size, size_t*), TFSPEC(match_fun, simix_match_func_t), TDPTR(data), TDOUBLE(timeout)) sep \
+ACTION(SIMCALL_COMM_IRECV, comm_irecv, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t), TDPTR(dst_buff), TDSPEC(dst_buff_size, size_t*), TFSPEC(match_fun, simix_match_func_t), TDPTR(data)) sep \
+ACTION(SIMCALL_COMM_RECV_BOUNDED, comm_recv_bounded, WITHOUT_ANSWER, TVOID(result), TDSPEC(rdv, smx_rdv_t), TDPTR(dst_buff), TDSPEC(dst_buff_size, size_t*), TFSPEC(match_fun, simix_match_func_t), TDPTR(data), TDOUBLE(timeout), TDOUBLE(rate)) sep \
+ACTION(SIMCALL_COMM_IRECV_BOUNDED, comm_irecv_bounded, WITH_ANSWER, TDSPEC(result, smx_action_t), TDSPEC(rdv, smx_rdv_t), TDPTR(dst_buff), TDSPEC(dst_buff_size, size_t*), TFSPEC(match_fun, simix_match_func_t), TDPTR(data), TDOUBLE(rate)) sep \
+ACTION(SIMCALL_COMM_DESTROY, comm_destroy, WITH_ANSWER, TVOID(result), TDSPEC(comm, smx_action_t)) sep \
+ACTION(SIMCALL_COMM_CANCEL, comm_cancel, WITH_ANSWER, TVOID(result), TDSPEC(comm, smx_action_t)) sep \
+ACTION(SIMCALL_COMM_WAITANY, comm_waitany, WITHOUT_ANSWER, TINT(result), TDSPEC(comms, xbt_dynar_t)) sep \
+ACTION(SIMCALL_COMM_WAIT, comm_wait, WITHOUT_ANSWER, TVOID(result), TDSPEC(comm, smx_action_t), TDOUBLE(timeout)) sep \
+ACTION(SIMCALL_COMM_TEST, comm_test, WITHOUT_ANSWER, TINT(result), TDSPEC(comm, smx_action_t)) sep \
+ACTION(SIMCALL_COMM_TESTANY, comm_testany, WITHOUT_ANSWER, TINT(result), TDSPEC(comms, xbt_dynar_t)) sep \
+ACTION(SIMCALL_COMM_GET_REMAINS, comm_get_remains, WITH_ANSWER, TDOUBLE(result), TDSPEC(comm, smx_action_t)) sep \
+ACTION(SIMCALL_COMM_GET_STATE, comm_get_state, WITH_ANSWER, TINT(result), TDSPEC(comm, smx_action_t)) sep \
+ACTION(SIMCALL_COMM_GET_SRC_DATA, comm_get_src_data, WITH_ANSWER, TDPTR(result), TDSPEC(comm, smx_action_t)) sep \
+ACTION(SIMCALL_COMM_GET_DST_DATA, comm_get_dst_data, WITH_ANSWER, TDPTR(result), TDSPEC(comm, smx_action_t)) sep \
+ACTION(SIMCALL_COMM_GET_SRC_PROC, comm_get_src_proc, WITH_ANSWER, TDSPEC(result, smx_process_t), TDSPEC(comm, smx_action_t)) sep \
+ACTION(SIMCALL_COMM_GET_DST_PROC, comm_get_dst_proc, WITH_ANSWER, TDSPEC(result, smx_process_t), TDSPEC(comm, smx_action_t)) sep \
+ACTION(SIMCALL_MUTEX_INIT, mutex_init, WITH_ANSWER, TDSPEC(result, smx_mutex_t)) sep \
+ACTION(SIMCALL_MUTEX_DESTROY, mutex_destroy, WITH_ANSWER, TVOID(result), TDSPEC(mutex, smx_mutex_t)) sep \
+ACTION(SIMCALL_MUTEX_LOCK, mutex_lock, WITHOUT_ANSWER, TVOID(result), TDSPEC(mutex, smx_mutex_t)) sep \
+ACTION(SIMCALL_MUTEX_TRYLOCK, mutex_trylock, WITH_ANSWER, TINT(result), TDSPEC(mutex, smx_mutex_t)) sep \
+ACTION(SIMCALL_MUTEX_UNLOCK, mutex_unlock, WITH_ANSWER, TVOID(result), TDSPEC(mutex, smx_mutex_t)) sep \
+ACTION(SIMCALL_COND_INIT, cond_init, WITH_ANSWER, TDSPEC(result, smx_cond_t)) sep \
+ACTION(SIMCALL_COND_DESTROY, cond_destroy, WITH_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t)) sep \
+ACTION(SIMCALL_COND_SIGNAL, cond_signal, WITH_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t)) sep \
+ACTION(SIMCALL_COND_WAIT, cond_wait, WITHOUT_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t), TDSPEC(mutex, smx_mutex_t)) sep \
+ACTION(SIMCALL_COND_WAIT_TIMEOUT, cond_wait_timeout, WITHOUT_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t), TDSPEC(mutex, smx_mutex_t), TDOUBLE(timeout)) sep \
+ACTION(SIMCALL_COND_BROADCAST, cond_broadcast, WITH_ANSWER, TVOID(result), TDSPEC(cond, smx_cond_t)) sep \
+ACTION(SIMCALL_SEM_INIT, sem_init, WITH_ANSWER, TDSPEC(result, smx_sem_t), TINT(capacity)) sep \
+ACTION(SIMCALL_SEM_DESTROY, sem_destroy, WITH_ANSWER, TVOID(result), TDSPEC(sem, smx_sem_t)) sep \
+ACTION(SIMCALL_SEM_RELEASE, sem_release, WITH_ANSWER, TVOID(result), TDSPEC(sem, smx_sem_t)) sep \
+ACTION(SIMCALL_SEM_WOULD_BLOCK, sem_would_block, WITH_ANSWER, TINT(result), TDSPEC(sem, smx_sem_t)) sep \
+ACTION(SIMCALL_SEM_ACQUIRE, sem_acquire, WITHOUT_ANSWER, TVOID(result), TDSPEC(sem, smx_sem_t)) sep \
+ACTION(SIMCALL_SEM_ACQUIRE_TIMEOUT, sem_acquire_timeout, WITHOUT_ANSWER, TVOID(result), TDSPEC(sem, smx_sem_t), TDOUBLE(timeout)) sep \
+ACTION(SIMCALL_SEM_GET_CAPACITY, sem_get_capacity, WITH_ANSWER, TINT(result), TDSPEC(sem, smx_sem_t)) sep \
+ACTION(SIMCALL_FILE_GET_DATA, file_get_data, WITH_ANSWER, TDPTR(result), TDSPEC(fd, smx_file_t)) sep \
+ACTION(SIMCALL_FILE_SET_DATA, file_set_data, WITH_ANSWER, TVOID(result), TDSPEC(fd, smx_file_t), TDPTR(data)) sep \
+ACTION(SIMCALL_FILE_READ, file_read, WITHOUT_ANSWER, TSIZE(result), TDSPEC(fd, smx_file_t),  TSIZE(size)) sep \
+ACTION(SIMCALL_FILE_WRITE, file_write, WITHOUT_ANSWER, TSIZE(result), TDSPEC(fd, smx_file_t), TSIZE(size)) sep \
+ACTION(SIMCALL_FILE_OPEN, file_open, WITHOUT_ANSWER, TDSPEC(result, smx_file_t), TSTRING(mount), TSTRING(path)) sep \
+ACTION(SIMCALL_FILE_CLOSE, file_close, WITHOUT_ANSWER, TINT(result), TDSPEC(fd, smx_file_t)) sep \
+ACTION(SIMCALL_FILE_UNLINK, file_unlink, WITH_ANSWER, TINT(result), TDSPEC(fd, smx_file_t)) sep \
+ACTION(SIMCALL_FILE_LS, file_ls, WITHOUT_ANSWER, TDSPEC(result, xbt_dict_t), TSTRING(mount), TSTRING(path)) sep \
+ACTION(SIMCALL_FILE_GET_SIZE, file_get_size, WITH_ANSWER, TSIZE(result), TDSPEC(fd, smx_file_t)) sep \
+ACTION(SIMCALL_FILE_GET_INFO, file_get_info, WITH_ANSWER, TDSPEC(result, xbt_dynar_t), TDSPEC(fd, smx_file_t)) sep \
+ACTION(SIMCALL_STORAGE_FILE_RENAME, storage_file_rename, WITH_ANSWER, TVOID(result), TDSPEC(storage, smx_storage_t), TSTRING(src), TSTRING(dest)) sep \
+ACTION(SIMCALL_STORAGE_GET_FREE_SIZE, storage_get_free_size, WITH_ANSWER, TSIZE(result), TSTRING(name)) sep \
+ACTION(SIMCALL_STORAGE_GET_USED_SIZE, storage_get_used_size, WITH_ANSWER, TSIZE(result), TSTRING(name)) sep \
+ACTION(SIMCALL_STORAGE_GET_PROPERTIES, storage_get_properties, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(storage, smx_storage_t)) sep \
+ACTION(SIMCALL_STORAGE_GET_CONTENT, storage_get_content, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TDSPEC(storage, smx_storage_t)) sep \
+ACTION(SIMCALL_ASR_GET_PROPERTIES, asr_get_properties, WITH_ANSWER, TDSPEC(result, xbt_dict_t), TSTRING(name)) sep 
 
 /* SIMCALL_COMM_IS_LATENCY_BOUNDED and SIMCALL_SET_CATEGORY make things complicated
  * because they are not always present */
 #ifdef HAVE_LATENCY_BOUND_TRACKING
 #define SIMCALL_LIST2(ACTION, sep) \
-ACTION(SIMCALL_COMM_IS_LATENCY_BOUNDED, comm_is_latency_bounded, WITH_ANSWER, TINT(result), TSPEC(comm, smx_action_t)) sep
+ACTION(SIMCALL_COMM_IS_LATENCY_BOUNDED, comm_is_latency_bounded, WITH_ANSWER, TINT(result), TDSPEC(comm, smx_action_t)) sep
 #else
 #define SIMCALL_LIST2(ACTION, sep)
 #endif
 
 #ifdef HAVE_TRACING
 #define SIMCALL_LIST3(ACTION, sep) \
-ACTION(SIMCALL_SET_CATEGORY, set_category, WITH_ANSWER, TVOID(result), TSPEC(action, smx_action_t), TSTRING(category)) sep
+ACTION(SIMCALL_SET_CATEGORY, set_category, WITH_ANSWER, TVOID(result), TDSPEC(action, smx_action_t), TSTRING(category)) sep
 #else
 #define SIMCALL_LIST3(ACTION, sep)
 #endif
 
 #ifdef HAVE_MC
 #define SIMCALL_LIST4(ACTION, sep) \
-ACTION(SIMCALL_MC_SNAPSHOT, mc_snapshot, WITH_ANSWER, TPTR(result)) sep \
-ACTION(SIMCALL_MC_COMPARE_SNAPSHOTS, mc_compare_snapshots, WITH_ANSWER, TINT(result), TPTR(s1), TPTR(s2)) sep \
+ACTION(SIMCALL_MC_SNAPSHOT, mc_snapshot, WITH_ANSWER, TDPTR(result)) sep \
+ACTION(SIMCALL_MC_COMPARE_SNAPSHOTS, mc_compare_snapshots, WITH_ANSWER, TINT(result), TDPTR(s1), TDPTR(s2)) sep \
 ACTION(SIMCALL_MC_RANDOM, mc_random, WITH_ANSWER, TINT(result), TINT(min), TINT(max)) sep
 #else
 #define SIMCALL_LIST4(ACTION, sep)
@@ -414,6 +448,7 @@ NUM_SIMCALLS
 
 typedef int (*simix_match_func_t)(void *, void *, smx_action_t);
 typedef void (*simix_clean_func_t)(void *);
+typedef void (*FPtr)(void); // Hide the ugliness
 
 /* Pack all possible scalar types in an union */
 union u_smx_scalar {
@@ -430,7 +465,8 @@ union u_smx_scalar {
   double          d;
   size_t          si;
   sg_storage_size_t  sgstsi;
-  void*           p;
+  void*           dp;
+  FPtr            fp;
   const void*     cp;
 };
 
@@ -454,8 +490,14 @@ typedef struct s_smx_simcall {
   };
 } s_smx_simcall_t, *smx_simcall_t;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 SIMCALL_LIST(SIMCALL_RES_GETSET, SIMCALL_SEP_NOTHING)
 SIMCALL_LIST(SIMCALL_ARG_GETSET, SIMCALL_SEP_NOTHING)
+#ifdef __cplusplus
+}
+#endif
 
 /******************************** General *************************************/
 
index c9d14d0..eebc903 100644 (file)
@@ -23,14 +23,15 @@ static void _SIMIX_sem_wait(smx_sem_t sem, double timeout, smx_process_t issuer,
 static smx_action_t SIMIX_synchro_wait(smx_host_t smx_host, double timeout)
 {
   XBT_IN("(%p, %f)",smx_host,timeout);
+
   smx_action_t action;
   action = xbt_mallocator_get(simix_global->action_mallocator);
   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 +71,8 @@ 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);
+  xbt_assert(action->type == SIMIX_ACTION_SYNCHRO);
+  surf_action_unref(action->synchro.sleep);
   xbt_free(action->name);
   xbt_mallocator_release(simix_global->action_mallocator, action);
   XBT_OUT();
@@ -79,9 +81,10 @@ 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)
+  xbt_assert(action->type == SIMIX_ACTION_SYNCHRO);
+  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);  
index 9694523..5c8bfea 100644 (file)
@@ -45,6 +45,28 @@ const char* simcall_host_get_name(smx_host_t host)
   return simcall_BODY_host_get_name(host);
 }
 
+/**
+ * \ingroup simix_host_management
+ * \brief Start the host if it is off
+ *
+ * \param host A SIMIX host
+ */
+void simcall_host_on(smx_host_t host)
+{
+  simcall_BODY_host_on(host);
+}
+
+/**
+ * \ingroup simix_host_management
+ * \brief Stop the host if it is on
+ *
+ * \param host A SIMIX host
+ */
+void simcall_host_off(smx_host_t host)
+{
+  simcall_BODY_host_off(host);
+}
+
 /**
  * \ingroup simix_host_management
  * \brief Returns a dict of the properties assigned to a host.
@@ -235,13 +257,13 @@ double simcall_host_get_consumed_energy(smx_host_t host)
  */
 smx_action_t simcall_host_execute(const char *name, smx_host_t host,
                                     double computation_amount,
-                                    double priority)
+                                    double priority, double bound, unsigned long affinity_mask)
 {
   /* checking for infinite values */
   xbt_assert(isfinite(computation_amount), "computation_amount is not finite!");
   xbt_assert(isfinite(priority), "priority is not finite!");
   
-  return simcall_BODY_host_execute(name, host, computation_amount, priority);
+  return simcall_BODY_host_execute(name, host, computation_amount, priority, bound, affinity_mask);
 }
 
 /**
@@ -351,6 +373,33 @@ void simcall_host_execution_set_priority(smx_action_t execution, double priority
   simcall_BODY_host_execution_set_priority(execution, priority);
 }
 
+/**
+ * \ingroup simix_host_management
+ * \brief Changes the capping (the maximum CPU utilization) of an execution action.
+ *
+ * This functions changes the capping only. It calls a surf function.
+ * \param execution The execution action
+ * \param bound The new bound
+ */
+void simcall_host_execution_set_bound(smx_action_t execution, double bound)
+{
+  simcall_BODY_host_execution_set_bound(execution, bound);
+}
+
+/**
+ * \ingroup simix_host_management
+ * \brief Changes the CPU affinity of an execution action.
+ *
+ * This functions changes the CPU affinity of an execution action. See taskset(1) on Linux.
+ * \param execution The execution action
+ * \param host Host
+ * \param mask Affinity mask
+ */
+void simcall_host_execution_set_affinity(smx_action_t execution, smx_host_t host, unsigned long mask)
+{
+  simcall_BODY_host_execution_set_affinity(execution, host, mask);
+}
+
 /**
  * \ingroup simix_host_management
  * \brief Waits for the completion of an execution action and destroy it.
@@ -362,6 +411,169 @@ e_smx_state_t simcall_host_execution_wait(smx_action_t execution)
   return simcall_BODY_host_execution_wait(execution);
 }
 
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Create a VM on the given physical host.
+ *
+ * \param name VM name
+ * \param host Physical host
+ *
+ * \return The host object of the VM
+ */
+void* simcall_vm_create(const char *name, smx_host_t phys_host){
+  /* will jump to SIMIX_pre_vm_create() in src/simix/smx_smurf_private.h */
+  return simcall_BODY_vm_create(name, phys_host);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Start the given VM to the given physical host
+ *
+ * \param vm VM
+ */
+void simcall_vm_start(smx_host_t vm)
+{
+  /* will jump to SIMIX_pre_vm_start in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_start(vm);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Get the state of the given VM
+ *
+ * \param vm VM
+ * \return The state of the VM
+ */
+int simcall_vm_get_state(smx_host_t vm)
+{
+  /* will jump to SIMIX_pre_vm_get_state in src/simix/smx_smurf_private.h */
+  return simcall_BODY_vm_get_state(vm);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Get the name of the physical host on which the given VM runs.
+ *
+ * \param vm VM
+ * \return The name of the physical host
+ */
+void *simcall_vm_get_pm(smx_host_t vm)
+{
+  /* will jump to SIMIX_pre_vm_migrate in src/simix/smx_smurf_private.h */
+  return simcall_BODY_vm_get_pm(vm);
+}
+
+void simcall_vm_set_bound(smx_host_t vm, double bound)
+{
+  /* will jump to SIMIX_pre_vm_set_bound in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_set_bound(vm, bound);
+}
+
+void simcall_vm_set_affinity(smx_host_t vm, smx_host_t pm, unsigned long mask)
+{
+  /* will jump to SIMIX_pre_vm_set_affinity in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_set_affinity(vm, pm, mask);
+}
+
+void simcall_host_get_params(smx_host_t vm, ws_params_t params)
+{
+  /* will jump to SIMIX_pre_host_get_params in src/simix/smx_smurf_private.h */
+  simcall_BODY_host_get_params(vm, params);
+}
+
+void simcall_host_set_params(smx_host_t vm, ws_params_t params)
+{
+  /* will jump to SIMIX_pre_host_set_params in src/simix/smx_smurf_private.h */
+  simcall_BODY_host_set_params(vm, params);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Migrate the given VM to the given physical host
+ *
+ * \param vm VM
+ * \param host Destination physical host
+ */
+void simcall_vm_migrate(smx_host_t vm, smx_host_t host)
+{
+  /* will jump to SIMIX_pre_vm_migrate in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_migrate(vm, host);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Suspend the given VM
+ *
+ * \param vm VM
+ */
+void simcall_vm_suspend(smx_host_t vm)
+{
+  /* will jump to SIMIX_pre_vm_suspend in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_suspend(vm);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Resume the given VM
+ *
+ * \param vm VM
+ */
+void simcall_vm_resume(smx_host_t vm)
+{
+  /* will jump to SIMIX_pre_vm_resume in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_resume(vm);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Save the given VM
+ *
+ * \param vm VM
+ */
+void simcall_vm_save(smx_host_t vm)
+{
+  /* will jump to SIMIX_pre_vm_save in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_save(vm);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Restore the given VM
+ *
+ * \param vm VM
+ */
+void simcall_vm_restore(smx_host_t vm)
+{
+  /* will jump to SIMIX_pre_vm_restore in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_restore(vm);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Shutdown the given VM
+ *
+ * \param vm VM
+ */
+void simcall_vm_shutdown(smx_host_t vm)
+{
+  /* will jump to SIMIX_pre_vm_shutdown in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_shutdown(vm);
+}
+
+/**
+ * \ingroup simix_vm_management
+ * \brief Destroy the given VM
+ *
+ * \param vm VM
+ */
+void simcall_vm_destroy(smx_host_t vm)
+{
+   /* will jump to SIMIX_pre_vm_destroy in src/simix/smx_smurf_private.h */
+  simcall_BODY_vm_destroy(vm);
+}
+
+
 /**
  * \ingroup simix_process_management
  * \brief Creates and runs a new SIMIX process.
diff --git a/src/simix/smx_vm.c b/src/simix/smx_vm.c
new file mode 100644 (file)
index 0000000..e56c555
--- /dev/null
@@ -0,0 +1,402 @@
+/* Copyright (c) 2007-2012. 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 "smx_private.h"
+#include "xbt/sysdep.h"
+#include "xbt/log.h"
+#include "xbt/dict.h"
+#include "mc/mc.h"
+
+//If you need to log some stuffs, just uncomment these two lines and uses XBT_DEBUG for instance
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_vm, simix, "Logging specific to SIMIX (vms)");
+
+/* **** create a VM **** */
+
+/**
+ * \brief Internal function to create a SIMIX host.
+ * \param name name of the host to create
+ * \param data some user data (may be NULL)
+ */
+smx_host_t SIMIX_vm_create(const char *name, smx_host_t ind_phys_host)
+{
+  /* Create surf associated resource */
+  surf_vm_workstation_model_create(name, ind_phys_host);
+
+  smx_host_t smx_host = SIMIX_host_create(name, ind_phys_host, NULL);
+
+  /* We will be able to register the VM to its physical host, so that we can promptly
+   * retrieve the list VMs on the physical host. */
+
+  return smx_host;
+}
+
+
+smx_host_t SIMIX_pre_vm_create(smx_simcall_t simcall, const char *name, smx_host_t ind_phys_host)
+{
+  return SIMIX_vm_create(name, ind_phys_host);
+}
+
+
+/* works for VMs and PMs */
+static long host_get_ramsize(smx_host_t vm, int *overcommit)
+{
+  s_ws_params_t params;
+  surf_workstation_get_params(vm, &params);
+
+  if (overcommit)
+    *overcommit = params.overcommit;
+
+  return params.ramsize;
+}
+
+/* **** start a VM **** */
+static int __can_be_started(smx_host_t vm)
+{
+  smx_host_t pm = surf_vm_workstation_get_pm(vm);
+
+  int pm_overcommit = 0;
+  long pm_ramsize = host_get_ramsize(pm, &pm_overcommit);
+  long vm_ramsize = host_get_ramsize(vm, NULL);
+
+  if (!pm_ramsize) {
+    /* We assume users do not want to care about ramsize. */
+    return 1;
+  }
+
+  if (pm_overcommit) {
+    XBT_INFO("%s allows memory overcommit.", pm->key);
+    return 1;
+  }
+
+  long total_ramsize_of_vms = 0;
+  xbt_dynar_t dyn_vms = surf_workstation_get_vms(pm);
+  {
+    unsigned int cursor = 0;
+    smx_host_t another_vm;
+    xbt_dynar_foreach(dyn_vms, cursor, another_vm) {
+      long another_vm_ramsize = host_get_ramsize(vm, NULL);
+      total_ramsize_of_vms += another_vm_ramsize;
+    }
+  }
+
+  if (vm_ramsize > pm_ramsize - total_ramsize_of_vms) {
+    XBT_WARN("cannnot start %s@%s due to memory shortage: vm_ramsize %ld, free %ld, pm_ramsize %ld (bytes).",
+        vm->key, pm->key, vm_ramsize, pm_ramsize - total_ramsize_of_vms, pm_ramsize);
+    xbt_dynar_free(&dyn_vms);
+    return 0;
+  }
+
+  xbt_dynar_free(&dyn_vms);
+       return 1;
+}
+
+void SIMIX_vm_start(smx_host_t ind_vm)
+{
+  if (__can_be_started(ind_vm))
+    SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_RUNNING);
+  else
+    THROWF(vm_error, 0, "The VM %s cannot be started", SIMIX_host_get_name(ind_vm));
+}
+
+
+
+void SIMIX_pre_vm_start(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_start(ind_vm);
+}
+
+/* ***** set/get state of a VM ***** */
+void SIMIX_vm_set_state(smx_host_t ind_vm, int state)
+{
+  /* jump to vm_ws_set_state */
+ surf_resource_set_state(surf_workstation_resource_priv(ind_vm), state);
+}
+
+void SIMIX_pre_vm_set_state(smx_simcall_t simcall, smx_host_t ind_vm, int state)
+{
+  SIMIX_vm_set_state(ind_vm, state);
+}
+
+int SIMIX_vm_get_state(smx_host_t ind_vm)
+{
+  return surf_resource_get_state(surf_workstation_resource_priv(ind_vm));
+}
+
+int SIMIX_pre_vm_get_state(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  return SIMIX_vm_get_state(ind_vm);
+}
+
+
+/**
+ * \brief Function to migrate a SIMIX VM host. 
+ *
+ * \param host the vm host to migrate (a smx_host_t)
+ */
+void SIMIX_vm_migrate(smx_host_t ind_vm, smx_host_t ind_dst_pm)
+{
+  /* precopy migration makes the VM temporally paused */
+  e_surf_vm_state_t state = SIMIX_vm_get_state(ind_vm);
+  xbt_assert(state == SURF_VM_STATE_SUSPENDED);
+
+  /* jump to vm_ws_migrate(). this will update the vm location. */
+  surf_vm_workstation_migrate(ind_vm, ind_dst_pm);
+}
+
+void SIMIX_pre_vm_migrate(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_dst_pm)
+{
+  SIMIX_vm_migrate(ind_vm, ind_dst_pm);
+}
+
+
+/**
+ * \brief Function to get the physical host of the given SIMIX VM host.
+ *
+ * \param host the vm host to get_phys_host (a smx_host_t)
+ */
+void *SIMIX_vm_get_pm(smx_host_t ind_vm)
+{
+  /* jump to vm_ws_get_pm(). this will return the vm name. */
+  return surf_vm_workstation_get_pm(ind_vm);
+}
+
+void *SIMIX_pre_vm_get_pm(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  return SIMIX_vm_get_pm(ind_vm);
+}
+
+
+/**
+ * \brief Function to set the CPU bound of the given SIMIX VM host.
+ *
+ * \param host the vm host (a smx_host_t)
+ * \param bound bound (a double)
+ */
+void SIMIX_vm_set_bound(smx_host_t ind_vm, double bound)
+{
+  /* jump to vm_ws_set_vm_bound(). */
+  surf_vm_workstation_set_bound(ind_vm, bound);
+}
+
+void SIMIX_pre_vm_set_bound(smx_simcall_t simcall, smx_host_t ind_vm, double bound)
+{
+  SIMIX_vm_set_bound(ind_vm, bound);
+}
+
+
+/**
+ * \brief Function to set the CPU affinity of the given SIMIX VM host.
+ *
+ * \param host the vm host (a smx_host_t)
+ * \param host the pm host (a smx_host_t)
+ * \param mask affinity mask (a unsigned long)
+ */
+void SIMIX_vm_set_affinity(smx_host_t ind_vm, smx_host_t ind_pm, unsigned long mask)
+{
+  /* make sure this at the MSG layer. */
+  xbt_assert(SIMIX_vm_get_pm(ind_vm) == ind_pm);
+
+  /* jump to vm_ws_set_vm_affinity(). */
+  surf_vm_workstation_set_affinity(ind_vm, ind_pm, mask);
+}
+
+void SIMIX_pre_vm_set_affinity(smx_simcall_t simcall, smx_host_t ind_vm, smx_host_t ind_pm, unsigned long mask)
+{
+  SIMIX_vm_set_affinity(ind_vm, ind_pm, mask);
+}
+
+
+/**
+ * \brief Function to suspend a SIMIX VM host. This function stops the exection of the
+ * VM. All the processes on this VM will pause. The state of the VM is
+ * preserved on memory. We can later resume it again.
+ *
+ * \param host the vm host to suspend (a smx_host_t)
+ */
+void SIMIX_vm_suspend(smx_host_t ind_vm, smx_process_t issuer)
+{
+  const char *name = SIMIX_host_get_name(ind_vm);
+
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+    THROWF(vm_error, 0, "VM(%s) is not running", name);
+
+  XBT_DEBUG("suspend VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+  /* jump to vm_ws_suspend. The state will be set. */
+  surf_vm_workstation_suspend(ind_vm);
+
+  smx_process_t smx_process, smx_process_safe;
+  xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+    XBT_DEBUG("suspend %s", smx_process->name);
+    SIMIX_process_suspend(smx_process, issuer);
+  }
+
+  XBT_DEBUG("suspend all processes on the VM done done");
+}
+
+void SIMIX_pre_vm_suspend(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  if (simcall->issuer->smx_host == ind_vm) {
+    XBT_ERROR("cannot suspend the VM where I run");
+    DIE_IMPOSSIBLE;
+  }
+
+  SIMIX_vm_suspend(ind_vm, simcall->issuer);
+
+  XBT_DEBUG("SIMIX_pre_vm_suspend done");
+}
+
+
+/**
+ * \brief Function to resume a SIMIX VM host. This function restart the execution of the
+ * VM. All the processes on this VM will run again. 
+ *
+ * \param host the vm host to resume (a smx_host_t)
+ */
+void SIMIX_vm_resume(smx_host_t ind_vm, smx_process_t issuer)
+{
+  const char *name = SIMIX_host_get_name(ind_vm);
+
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_SUSPENDED)
+    THROWF(vm_error, 0, "VM(%s) was not suspended", name);
+
+  XBT_DEBUG("resume VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+  /* jump to vm_ws_resume() */
+  surf_vm_workstation_resume(ind_vm);
+
+  smx_process_t smx_process, smx_process_safe;
+  xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+    XBT_DEBUG("resume %s", smx_process->name);
+    SIMIX_process_resume(smx_process, issuer);
+  }
+}
+
+void SIMIX_pre_vm_resume(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_resume(ind_vm, simcall->issuer);
+}
+
+
+/**
+ * \brief Function to save a SIMIX VM host.
+ * This function is the same as vm_suspend, but the state of the VM is saved to the disk, and not preserved on memory.
+ * We can later restore it again.
+ *
+ * \param host the vm host to save (a smx_host_t)
+ */
+void SIMIX_vm_save(smx_host_t ind_vm, smx_process_t issuer)
+{
+  const char *name = SIMIX_host_get_name(ind_vm);
+
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+    THROWF(vm_error, 0, "VM(%s) is not running", name);
+
+
+  XBT_DEBUG("save VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+  /* jump to vm_ws_save() */
+  surf_vm_workstation_save(ind_vm);
+
+  smx_process_t smx_process, smx_process_safe;
+  xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+    XBT_DEBUG("suspend %s", smx_process->name);
+    SIMIX_process_suspend(smx_process, issuer);
+  }
+}
+
+void SIMIX_pre_vm_save(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_save(ind_vm, simcall->issuer);
+}
+
+
+/**
+ * \brief Function to restore a SIMIX VM host. This function restart the execution of the
+ * VM. All the processes on this VM will run again. 
+ *
+ * \param host the vm host to restore (a smx_host_t)
+ */
+void SIMIX_vm_restore(smx_host_t ind_vm, smx_process_t issuer)
+{
+  const char *name = SIMIX_host_get_name(ind_vm);
+
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_SAVED)
+    THROWF(vm_error, 0, "VM(%s) was not saved", name);
+
+  XBT_DEBUG("restore VM(%s), where %d processes exist", name, xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+  /* jump to vm_ws_restore() */
+  surf_vm_workstation_resume(ind_vm);
+
+  smx_process_t smx_process, smx_process_safe;
+  xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+    XBT_DEBUG("resume %s", smx_process->name);
+    SIMIX_process_resume(smx_process, issuer);
+  }
+}
+
+void SIMIX_pre_vm_restore(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_restore(ind_vm, simcall->issuer);
+}
+
+
+/**
+ * \brief Function to shutdown a SIMIX VM host. This function powers off the
+ * VM. All the processes on this VM will be killed. But, the state of the VM is
+ * preserved on memory. We can later start it again.
+ *
+ * \param host the vm host to shutdown (a smx_host_t)
+ */
+void SIMIX_vm_shutdown(smx_host_t ind_vm, smx_process_t issuer)
+{
+  const char *name = SIMIX_host_get_name(ind_vm);
+
+  if (SIMIX_vm_get_state(ind_vm) != SURF_VM_STATE_RUNNING)
+    THROWF(vm_error, 0, "VM(%s) is not running", name);
+
+  XBT_DEBUG("%d processes in the VM", xbt_swag_size(SIMIX_host_priv(ind_vm)->process_list));
+
+  smx_process_t smx_process, smx_process_safe;
+  xbt_swag_foreach_safe(smx_process, smx_process_safe, SIMIX_host_priv(ind_vm)->process_list) {
+    XBT_DEBUG("shutdown %s", name);
+    SIMIX_process_kill(smx_process, issuer);
+  }
+
+  /* FIXME: we may have to do something at the surf layer, e.g., vcpu action */
+  SIMIX_vm_set_state(ind_vm, SURF_VM_STATE_CREATED);
+}
+
+void SIMIX_pre_vm_shutdown(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_shutdown(ind_vm, simcall->issuer);
+}
+
+
+/**
+ * \brief Function to destroy a SIMIX VM host.
+ *
+ * \param host the vm host to destroy (a smx_host_t)
+ */
+void SIMIX_vm_destroy(smx_host_t ind_vm)
+{
+  /* this code basically performs a similar thing like SIMIX_host_destroy() */
+
+  xbt_assert((ind_vm != NULL), "Invalid parameters");
+  const char *hostname = SIMIX_host_get_name(ind_vm);
+
+  /* this will call the registered callback function, i.e., SIMIX_host_destroy().  */
+  xbt_lib_unset(host_lib, hostname, SIMIX_HOST_LEVEL, 1);
+
+  /* jump to vm_ws_destroy(). The surf level resource will be freed. */
+  surf_vm_workstation_destroy(ind_vm);
+}
+
+void SIMIX_pre_vm_destroy(smx_simcall_t simcall, smx_host_t ind_vm)
+{
+  SIMIX_vm_destroy(ind_vm);
+}
index b0f25dc..ddd6832 100644 (file)
@@ -142,8 +142,8 @@ void smpi_execute_flops(double flops) {
   smx_action_t action;
   smx_host_t host;
   host = SIMIX_host_self();
-  XBT_DEBUG("Handle real computation time: %g flops", flops);
-  action = simcall_host_execute("computation", host, flops, 1);
+  XBT_DEBUG("Handle real computation time: %f flops", flops);
+  action = simcall_host_execute("computation", host, flops, 1, 0, 0);
 #ifdef HAVE_TRACING
   simcall_set_category (action, TRACE_internal_smpi_get_category());
 #endif
diff --git a/src/surf/cpu.cpp b/src/surf/cpu.cpp
new file mode 100644 (file)
index 0000000..2a9acf9
--- /dev/null
@@ -0,0 +1,250 @@
+#include "cpu.hpp"
+
+extern "C" {
+XBT_LOG_EXTERNAL_CATEGORY(surf_kernel);
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu, surf,
+                                "Logging specific to the SURF cpu module");
+}
+
+CpuModelPtr surf_cpu_model_pm;
+CpuModelPtr surf_cpu_model_vm;
+
+/*********
+ * Model *
+ *********/
+
+void CpuModel::updateActionsStateLazy(double now, double delta)
+{
+  void *_action;
+  CpuActionLmmPtr action;
+  while ((xbt_heap_size(p_actionHeap) > 0)
+         && (double_equals(xbt_heap_maxkey(p_actionHeap), now))) {
+    action = dynamic_cast<CpuActionLmmPtr>(static_cast<ActionLmmPtr>(xbt_heap_pop(p_actionHeap)));
+    XBT_CDEBUG(surf_kernel, "Something happened to action %p", action);
+#ifdef HAVE_TRACING
+    if (TRACE_is_enabled()) {
+      CpuPtr cpu = (CpuPtr) lmm_constraint_id(lmm_get_cnst_from_var(p_maxminSystem, action->p_variable, 0));
+      TRACE_surf_host_set_utilization(cpu->m_name, action->p_category,
+                                      lmm_variable_getvalue(action->p_variable),
+                                      action->m_lastUpdate,
+                                      now - action->m_lastUpdate);
+    }
+#endif
+
+    action->m_finish = surf_get_clock();
+    XBT_CDEBUG(surf_kernel, "Action %p finished", action);
+
+    action->updateEnergy();
+
+    /* set the remains to 0 due to precision problems when updating the remaining amount */
+    action->m_remains = 0;
+    action->setState(SURF_ACTION_DONE);
+    action->heapRemove(p_actionHeap); //FIXME: strange call since action was already popped
+  }
+#ifdef HAVE_TRACING
+  if (TRACE_is_enabled()) {
+    //defining the last timestamp that we can safely dump to trace file
+    //without losing the event ascending order (considering all CPU's)
+    double smaller = -1;
+    xbt_swag_foreach(_action, p_runningActionSet) {
+      action = dynamic_cast<CpuActionLmmPtr>(static_cast<ActionPtr>(_action));
+        if (smaller < 0) {
+          smaller = action->m_lastUpdate;
+          continue;
+        }
+        if (action->m_lastUpdate < smaller) {
+          smaller = action->m_lastUpdate;
+        }
+    }
+    if (smaller > 0) {
+      TRACE_last_timestamp_to_dump = smaller;
+    }
+  }
+#endif
+  return;
+}
+
+void CpuModel::updateActionsStateFull(double now, double delta)
+{
+  void *_action, *_next_action;
+  CpuActionLmmPtr action = NULL;
+  xbt_swag_t running_actions = p_runningActionSet;
+
+  xbt_swag_foreach_safe(_action, _next_action, running_actions) {
+    action = dynamic_cast<CpuActionLmmPtr>(static_cast<ActionPtr>(_action));
+#ifdef HAVE_TRACING
+    if (TRACE_is_enabled()) {
+      CpuPtr x = (CpuPtr) lmm_constraint_id(lmm_get_cnst_from_var
+                              (p_maxminSystem, action->p_variable, 0));
+
+      TRACE_surf_host_set_utilization(x->m_name,
+                                      action->p_category,
+                                      lmm_variable_getvalue(action->p_variable),
+                                      now - delta,
+                                      delta);
+      TRACE_last_timestamp_to_dump = now - delta;
+    }
+#endif
+
+    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->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);
+    }
+    action->updateEnergy();
+  }
+
+  return;
+}
+
+/************
+ * Resource *
+ ************/
+
+double Cpu::getSpeed(double load)
+{
+  return load * m_powerPeak;
+}
+
+double Cpu::getAvailableSpeed()
+{
+/* number between 0 and 1 */
+  return m_powerScale;
+}
+
+int Cpu::getCore()
+{
+  return m_core;
+}
+
+/**********
+ * Action *
+ **********/
+
+void CpuActionLmm::updateRemainingLazy(double now)
+{
+  double delta = 0.0;
+
+  xbt_assert(p_stateSet == p_model->p_runningActionSet,
+      "You're updating an action that is not running.");
+
+  /* bogus priority, skip it */
+  xbt_assert(m_priority > 0,
+      "You're updating an action that seems suspended.");
+
+  delta = now - m_lastUpdate;
+
+  if (m_remains > 0) {
+    XBT_CDEBUG(surf_kernel, "Updating action(%p): remains was %lf, last_update was: %lf", this, m_remains, m_lastUpdate);
+    double_update(&(m_remains), m_lastValue * delta);
+
+#ifdef HAVE_TRACING
+    if (TRACE_is_enabled()) {
+      CpuPtr cpu = (CpuPtr) lmm_constraint_id(lmm_get_cnst_from_var(p_model->p_maxminSystem, p_variable, 0));
+      TRACE_surf_host_set_utilization(cpu->m_name, p_category, m_lastValue, m_lastUpdate, now - m_lastUpdate);
+    }
+#endif
+    XBT_CDEBUG(surf_kernel, "Updating action(%p): remains is now %lf", this, m_remains);
+  }
+
+  m_lastUpdate = now;
+  m_lastValue = lmm_variable_getvalue(p_variable);
+}
+
+void CpuActionLmm::setBound(double bound)
+{
+  XBT_IN("(%p,%g)", this, bound);
+  m_bound = bound;
+  lmm_update_variable_bound(p_model->p_maxminSystem, p_variable, bound);
+
+  if (p_model->p_updateMechanism == UM_LAZY)
+       heapRemove(p_model->p_actionHeap);
+  XBT_OUT();
+}
+
+/*
+ *
+ * This function formulates a constraint problem that pins a given task to
+ * particular cores. Currently, it is possible to pin a task to an exactly one
+ * specific core. The system links the variable object of the task to the
+ * per-core constraint object.
+ *
+ * But, the taskset command on Linux takes a mask value specifying a CPU
+ * affinity setting of a given task. If the mask value is 0x03, the given task
+ * will be executed on the first core (CPU0) or the second core (CPU1) on the
+ * given PM. The schedular will determine appropriate placements of tasks,
+ * considering given CPU affinities and task activities.
+ *
+ * How should the system formulate constraint problems for an affinity to
+ * multiple cores?
+ *
+ * The cpu argument must be the host where the task is being executed. The
+ * action object does not have the information about the location where the
+ * action is being executed.
+ */
+void CpuActionLmm::setAffinity(CpuLmmPtr cpu, unsigned long mask)
+{
+  lmm_variable_t var_obj = p_variable;
+
+  XBT_IN("(%p,%lx)", this, mask);
+
+  {
+    unsigned long nbits = 0;
+
+    /* FIXME: There is much faster algorithms doing this. */
+    unsigned long i;
+    for (i = 0; i < cpu->m_core; i++) {
+      unsigned long has_affinity = (1UL << i) & mask;
+      if (has_affinity)
+        nbits += 1;
+    }
+
+    if (nbits > 1) {
+      XBT_CRITICAL("Do not specify multiple cores for an affinity mask.");
+      XBT_CRITICAL("See the comment in cpu_action_set_affinity().");
+      DIE_IMPOSSIBLE;
+    }
+  }
+
+
+
+  unsigned long i;
+  for (i = 0; i < cpu->m_core; i++) {
+    XBT_DEBUG("clear affinity %p to cpu-%lu@%s", this, i,  cpu->m_name);
+    lmm_shrink(cpu->p_model->p_maxminSystem, cpu->p_constraintCore[i], var_obj);
+
+    unsigned long has_affinity = (1UL << i) & mask;
+    if (has_affinity) {
+      /* This function only accepts an affinity setting on the host where the
+       * task is now running. In future, a task might move to another host.
+       * But, at this moment, this function cannot take an affinity setting on
+       * that future host.
+       *
+       * It might be possible to extend the code to allow this function to
+       * accept affinity settings on a future host. We might be able to assign
+       * zero to elem->value to maintain such inactive affinity settings in the
+       * system. But, this will make the system complex. */
+      XBT_DEBUG("set affinity %p to cpu-%lu@%s", this, i, cpu->m_name);
+      lmm_expand(cpu->p_model->p_maxminSystem, cpu->p_constraintCore[i], var_obj, 1.0);
+    }
+  }
+
+  if (cpu->p_model->p_updateMechanism == UM_LAZY) {
+    /* FIXME (hypervisor): Do we need to do something for the LAZY mode? */
+  }
+
+  XBT_OUT();
+}
diff --git a/src/surf/cpu.hpp b/src/surf/cpu.hpp
new file mode 100644 (file)
index 0000000..669578a
--- /dev/null
@@ -0,0 +1,97 @@
+#include "surf.hpp"
+
+#ifndef SURF_MODEL_CPU_H_
+#define SURF_MODEL_CPU_H_
+
+/***********
+ * Classes *
+ ***********/
+class CpuModel;
+typedef CpuModel *CpuModelPtr;
+
+class Cpu;
+typedef Cpu *CpuPtr;
+
+class CpuLmm;
+typedef CpuLmm *CpuLmmPtr;
+
+class CpuAction;
+typedef CpuAction *CpuActionPtr;
+
+class CpuActionLmm;
+typedef CpuActionLmm *CpuActionLmmPtr;
+
+/*********
+ * Model *
+ *********/
+class CpuModel : public Model {
+public:
+  CpuModel(string name) : Model(name) {};
+  CpuPtr createResource(string name);
+  void updateActionsStateLazy(double now, double delta);
+  void updateActionsStateFull(double now, double delta);
+
+  virtual void addTraces() =0;
+};
+
+/************
+ * Resource *
+ ************/
+class Cpu : virtual public Resource {
+public:
+  Cpu(){};
+  Cpu(CpuModelPtr model, const char* name, xbt_dict_t properties) : Resource(model, name, properties) {};
+  virtual ActionPtr execute(double size)=0;
+  virtual ActionPtr sleep(double duration)=0;
+  virtual int getCore();
+  virtual double getSpeed(double load);
+  virtual double getAvailableSpeed();
+
+  virtual double getCurrentPowerPeak()=0;
+  virtual double getPowerPeakAt(int pstate_index)=0;
+  virtual int getNbPstates()=0;
+  virtual void setPowerPeakAt(int pstate_index)=0;
+  virtual double getConsumedEnergy()=0;
+
+  void addTraces(void);
+  double m_powerPeak;            /*< CPU power peak */
+  double m_powerScale;           /*< Percentage of CPU disponible */
+  int m_core;
+protected:
+
+  //virtual boost::shared_ptr<Action> execute(double size) = 0;
+  //virtual boost::shared_ptr<Action> sleep(double duration) = 0;
+};
+
+class CpuLmm : public ResourceLmm, public Cpu {
+public:
+  CpuLmm(){};
+  CpuLmm(CpuModelPtr model, const char* name, xbt_dict_t properties) : ResourceLmm(), Cpu(model, name, properties) {};
+  /* Note (hypervisor): */
+  lmm_constraint_t *p_constraintCore;
+};
+
+/**********
+ * Action *
+ **********/
+class CpuAction : virtual public Action {
+public:
+  CpuAction(){};
+  CpuAction(ModelPtr model, double cost, bool failed)
+  : Action(model, cost, failed) {};
+};
+
+class CpuActionLmm : public ActionLmm, public CpuAction {
+public:
+  CpuActionLmm(){};
+  CpuActionLmm(ModelPtr model, double cost, bool failed)
+  : Action(model, cost, failed), ActionLmm(model, cost, failed), CpuAction(model, cost, failed) {};
+  void updateRemainingLazy(double now);
+  virtual void updateEnergy()=0;
+  void setAffinity(CpuLmmPtr cpu, unsigned long mask);
+  void setBound(double bound);
+  double m_bound;
+};
+
+
+#endif /* SURF_MODEL_CPU_H_ */
diff --git a/src/surf/cpu_cas01.c b/src/surf/cpu_cas01.c
deleted file mode 100644 (file)
index 15cf998..0000000
+++ /dev/null
@@ -1,601 +0,0 @@
-/* Copyright (c) 2009-2013. 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_private.h"
-#include "surf/surf_resource.h"
-#include "maxmin_private.h"
-#include "simgrid/sg_config.h"
-#include "cpu_cas01_private.h"
-
-#include "string.h"
-#include "stdlib.h"
-
-surf_model_t surf_cpu_model = NULL;
-
-
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu, surf,
-                                "Logging specific to the SURF CPU IMPROVED module");
-
-static xbt_swag_t
-    cpu_running_action_set_that_does_not_need_being_checked = NULL;
-
-/* Additionnal callback function to cleanup some data, called from surf_resource_free */
-
-static void cpu_cas01_cleanup(void* r){
-  cpu_Cas01_t cpu = (cpu_Cas01_t)r;
-  unsigned int iter;
-  xbt_dynar_t power_tuple = NULL;
-  xbt_dynar_foreach(cpu->energy->power_range_watts_list, iter, power_tuple)
-    xbt_dynar_free(&power_tuple);
-  xbt_dynar_free(&cpu->energy->power_range_watts_list);
-  xbt_dynar_free(&cpu->power_peak_list);
-  xbt_free(cpu->energy);
-  return;
-}
-
-/* This function is registered as a callback to sg_platf_new_host() and never called directly */
-static void *cpu_create_resource(const char *name, xbt_dynar_t power_peak,
-                                                                int pstate,
-                                 double power_scale,
-                                 tmgr_trace_t power_trace,
-                                 int core,
-                                 e_surf_resource_state_t state_initial,
-                                 tmgr_trace_t state_trace,
-                                 xbt_dict_t cpu_properties)
-{
-  cpu_Cas01_t cpu = NULL;
-
-  xbt_assert(!surf_cpu_resource_priv(surf_cpu_resource_by_name(name)),
-             "Host '%s' declared several times in the platform file",
-             name);
-  cpu = (cpu_Cas01_t) surf_resource_new(sizeof(s_cpu_Cas01_t),
-                                        surf_cpu_model, name,
-                                        cpu_properties,  &cpu_cas01_cleanup);
-  cpu->power_peak = xbt_dynar_get_as(power_peak, pstate, double);
-  cpu->power_peak_list = power_peak;
-  cpu->pstate = pstate;
-
-  cpu->energy = xbt_new(s_energy_cpu_cas01_t, 1);
-  cpu->energy->total_energy = 0;
-  cpu->energy->power_range_watts_list = cpu_get_watts_range_list(cpu);
-  cpu->energy->last_updated = surf_get_clock();
-
-  XBT_DEBUG("CPU create: peak=%f, pstate=%d",cpu->power_peak, cpu->pstate);
-
-  xbt_assert(cpu->power_peak > 0, "Power has to be >0");
-  cpu->power_scale = power_scale;
-  cpu->core = core;
-  xbt_assert(core > 0, "Invalid number of cores %d", core);
-
-  if (power_trace)
-    cpu->power_event =
-        tmgr_history_add_trace(history, power_trace, 0.0, 0, cpu);
-
-  cpu->state_current = state_initial;
-  if (state_trace)
-    cpu->state_event =
-        tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
-
-  cpu->constraint =
-      lmm_constraint_new(surf_cpu_model->model_private->maxmin_system, cpu,
-                         cpu->core * cpu->power_scale * cpu->power_peak);
-
-  xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, cpu);
-
-  return xbt_lib_get_elm_or_null(host_lib, name);;
-}
-
-
-static void parse_cpu_init(sg_platf_host_cbarg_t host)
-{
-  cpu_create_resource(host->id,
-                      host->power_peak,
-                      host->pstate,
-                      host->power_scale,
-                      host->power_trace,
-                      host->core_amount,
-                      host->initial_state,
-                      host->state_trace, host->properties);
-}
-
-static void cpu_add_traces_cpu(void)
-{
-  xbt_dict_cursor_t cursor = NULL;
-  char *trace_name, *elm;
-  static int called = 0;
-  if (called)
-    return;
-  called = 1;
-
-  /* connect all traces relative to hosts */
-  xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
-    tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
-    cpu_Cas01_t host = surf_cpu_resource_by_name(elm);
-
-    xbt_assert(host, "Host %s undefined", elm);
-    xbt_assert(trace, "Trace %s undefined", trace_name);
-
-    host->state_event =
-        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 = xbt_dict_get_or_null(traces_set_list, trace_name);
-    cpu_Cas01_t host = surf_cpu_resource_by_name(elm);
-
-    xbt_assert(host, "Host %s undefined", elm);
-    xbt_assert(trace, "Trace %s undefined", trace_name);
-
-    host->power_event =
-        tmgr_history_add_trace(history, trace, 0.0, 0, host);
-  }
-}
-
-static void cpu_define_callbacks()
-{
-  sg_platf_host_add_cb(parse_cpu_init);
-  sg_platf_postparse_add_cb(cpu_add_traces_cpu);
-}
-
-static int cpu_resource_used(void *resource)
-{
-  return lmm_constraint_used(surf_cpu_model->model_private->maxmin_system,
-                             ((cpu_Cas01_t) resource)->constraint);
-}
-
-static double cpu_share_resources_lazy(double now)
-{
-  return generic_share_resources_lazy(now, surf_cpu_model);
-}
-
-static double cpu_share_resources_full(double now)
-{
-  s_surf_action_cpu_Cas01_t action;
-  return generic_maxmin_share_resources(surf_cpu_model->states.
-                                        running_action_set,
-                                        xbt_swag_offset(action,
-                                                        generic_lmm_action.
-                                                        variable),
-                                        surf_cpu_model->model_private->maxmin_system, lmm_solve);
-}
-
-static void cpu_update_actions_state_lazy(double now, double delta)
-{
-  generic_update_actions_state_lazy(now, delta, surf_cpu_model);
-}
-
-static void cpu_update_actions_state_full(double now, double delta)
-{
-  generic_update_actions_state_full(now, delta, surf_cpu_model);
-}
-
-xbt_dynar_t cpu_get_watts_range_list(cpu_Cas01_t cpu_model)
-{
-       xbt_dynar_t power_range_list;
-       xbt_dynar_t power_tuple;
-       int i = 0, pstate_nb=0;
-       xbt_dynar_t current_power_values;
-       double min_power, max_power;
-       xbt_dict_t props = cpu_model->generic_resource.properties;
-
-       if (props == NULL)
-               return NULL;
-
-       char* all_power_values_str = xbt_dict_get_or_null(props, "power_per_state");
-
-       if (all_power_values_str == NULL)
-               return NULL;
-
-
-       power_range_list = xbt_dynar_new(sizeof(xbt_dynar_t), NULL);
-       xbt_dynar_t all_power_values = xbt_str_split(all_power_values_str, ",");
-
-       pstate_nb = xbt_dynar_length(all_power_values);
-       for (i=0; i< pstate_nb; i++)
-       {
-               /* retrieve the power values associated with the current pstate */
-               current_power_values = xbt_str_split(xbt_dynar_get_as(all_power_values, i, char*), ":");
-               xbt_assert(xbt_dynar_length(current_power_values) > 1,
-                               "Power properties incorrectly defined - could not retrieve min and max power values for host %s",
-                               cpu_model->generic_resource.name);
-
-               /* min_power corresponds to the idle power (cpu load = 0) */
-               /* max_power is the power consumed at 100% cpu load       */
-               min_power = atof(xbt_dynar_get_as(current_power_values, 0, char*));
-               max_power = atof(xbt_dynar_get_as(current_power_values, 1, char*));
-
-               power_tuple = xbt_dynar_new(sizeof(double), NULL);
-               xbt_dynar_push_as(power_tuple, double, min_power);
-               xbt_dynar_push_as(power_tuple, double, max_power);
-
-               xbt_dynar_push_as(power_range_list, xbt_dynar_t, power_tuple);
-               xbt_dynar_free(&current_power_values);
-       }
-       xbt_dynar_free(&all_power_values);
-       return power_range_list;
-
-}
-
-/**
- * Computes the power consumed by the host according to the current pstate and processor load
- *
- */
-static double cpu_get_current_watts_value(cpu_Cas01_t cpu_model, double cpu_load)
-{
-       xbt_dynar_t power_range_list = cpu_model->energy->power_range_watts_list;
-
-       if (power_range_list == NULL)
-       {
-               XBT_DEBUG("No power range properties specified for host %s", cpu_model->generic_resource.name);
-               return 0;
-       }
-       xbt_assert(xbt_dynar_length(power_range_list) == xbt_dynar_length(cpu_model->power_peak_list),
-                                               "The number of power ranges in the properties does not match the number of pstates for host %s",
-                                               cpu_model->generic_resource.name);
-
-    /* retrieve the power values associated with the current pstate */
-    xbt_dynar_t current_power_values = xbt_dynar_get_as(power_range_list, cpu_model->pstate, xbt_dynar_t);
-
-    /* min_power corresponds to the idle power (cpu load = 0) */
-    /* max_power is the power consumed at 100% cpu load       */
-    double min_power = xbt_dynar_get_as(current_power_values, 0, double);
-    double max_power = xbt_dynar_get_as(current_power_values, 1, double);
-    double power_slope = max_power - min_power;
-
-    double current_power = min_power + cpu_load * power_slope;
-
-       XBT_DEBUG("[get_current_watts] min_power=%f, max_power=%f, slope=%f", min_power, max_power, power_slope);
-    XBT_DEBUG("[get_current_watts] Current power (watts) = %f, load = %f", current_power, cpu_load);
-
-       return current_power;
-
-}
-
-/**
- * Updates the total energy consumed as the sum of the current energy and
- *                                              the energy consumed by the current action
- */
-void cpu_update_energy(cpu_Cas01_t cpu_model, double cpu_load)
-{
-
-  double start_time = cpu_model->energy->last_updated;
-  double finish_time = surf_get_clock();
-
-  XBT_DEBUG("[cpu_update_energy] action time interval=(%f-%f), current power peak=%f, current pstate=%d",
-                 start_time, finish_time, cpu_model->power_peak, cpu_model->pstate);
-  double current_energy = cpu_model->energy->total_energy;
-  double action_energy = cpu_get_current_watts_value(cpu_model, cpu_load)*(finish_time-start_time);
-
-  cpu_model->energy->total_energy = current_energy + action_energy;
-  cpu_model->energy->last_updated = finish_time;
-
-  XBT_DEBUG("[cpu_update_energy] old_energy_value=%f, action_energy_value=%f", current_energy, action_energy);
-
-}
-
-static void cpu_update_resource_state(void *id,
-                                      tmgr_trace_event_t event_type,
-                                      double value, double date)
-{
-  cpu_Cas01_t cpu = id;
-  lmm_variable_t var = NULL;
-  lmm_element_t elem = NULL;
-
-  if (event_type == cpu->power_event) {
-    cpu->power_scale = value;
-    lmm_update_constraint_bound(surf_cpu_model->model_private->maxmin_system, cpu->constraint,
-                                cpu->core * cpu->power_scale *
-                                cpu->power_peak);
-#ifdef HAVE_TRACING
-    TRACE_surf_host_set_power(date, cpu->generic_resource.name,
-                              cpu->core * cpu->power_scale *
-                              cpu->power_peak);
-#endif
-    while ((var = lmm_get_var_from_cnst
-            (surf_cpu_model->model_private->maxmin_system, cpu->constraint, &elem))) {
-      surf_action_cpu_Cas01_t action = lmm_variable_id(var);
-      lmm_update_variable_bound(surf_cpu_model->model_private->maxmin_system,
-                                GENERIC_LMM_ACTION(action).variable,
-                                cpu->power_scale * cpu->power_peak);
-    }
-    if (tmgr_trace_event_free(event_type))
-      cpu->power_event = NULL;
-  } else if (event_type == cpu->state_event) {
-    if (value > 0) {
-      if(cpu->state_current == SURF_RESOURCE_OFF)
-        xbt_dynar_push_as(host_that_restart, char*, (cpu->generic_resource.name));
-      cpu->state_current = SURF_RESOURCE_ON;
-    } else {
-      lmm_constraint_t cnst = cpu->constraint;
-
-      cpu->state_current = SURF_RESOURCE_OFF;
-
-      while ((var = lmm_get_var_from_cnst(surf_cpu_model->model_private->maxmin_system, cnst, &elem))) {
-        surf_action_t action = lmm_variable_id(var);
-
-        if (surf_action_state_get(action) == SURF_ACTION_RUNNING ||
-            surf_action_state_get(action) == SURF_ACTION_READY ||
-            surf_action_state_get(action) ==
-            SURF_ACTION_NOT_IN_THE_SYSTEM) {
-          action->finish = date;
-          surf_action_state_set(action, SURF_ACTION_FAILED);
-        }
-      }
-    }
-    if (tmgr_trace_event_free(event_type))
-      cpu->state_event = NULL;
-  } else {
-    XBT_CRITICAL("Unknown event ! \n");
-    xbt_abort();
-  }
-
-  return;
-}
-
-static surf_action_t cpu_execute(void *cpu, double size)
-{
-  surf_action_cpu_Cas01_t action = NULL;
-  //xbt_dict_cursor_t cursor = NULL;
-  cpu_Cas01_t CPU = surf_cpu_resource_priv(cpu);
-  //xbt_dict_t props = CPU->generic_resource.properties;
-
-  XBT_IN("(%s,%g)", surf_resource_name(CPU), size);
-  action =
-      surf_action_new(sizeof(s_surf_action_cpu_Cas01_t), size,
-                      surf_cpu_model,
-                      CPU->state_current != SURF_RESOURCE_ON);
-
-  GENERIC_LMM_ACTION(action).suspended = 0;     /* Should be useless because of the
-                                                   calloc but it seems to help valgrind... */
-
-  GENERIC_LMM_ACTION(action).variable =
-      lmm_variable_new(surf_cpu_model->model_private->maxmin_system, action,
-                       GENERIC_ACTION(action).priority,
-                       CPU->power_scale * CPU->power_peak, 1);
-  if (surf_cpu_model->model_private->update_mechanism == UM_LAZY) {
-    GENERIC_LMM_ACTION(action).index_heap = -1;
-    GENERIC_LMM_ACTION(action).last_update = surf_get_clock();
-    GENERIC_LMM_ACTION(action).last_value = 0.0;
-  }
-
-  lmm_expand(surf_cpu_model->model_private->maxmin_system, CPU->constraint,
-             GENERIC_LMM_ACTION(action).variable, 1.0);
-  XBT_OUT();
-  return (surf_action_t) action;
-}
-
-static surf_action_t cpu_action_sleep(void *cpu, double duration)
-{
-  surf_action_cpu_Cas01_t action = NULL;
-
-  if (duration > 0)
-    duration = MAX(duration, MAXMIN_PRECISION);
-
-  XBT_IN("(%s,%g)", surf_resource_name(surf_cpu_resource_priv(cpu)), duration);
-  action = (surf_action_cpu_Cas01_t) cpu_execute(cpu, 1.0);
-  // FIXME: sleep variables should not consume 1.0 in lmm_expand
-  GENERIC_ACTION(action).max_duration = duration;
-  GENERIC_LMM_ACTION(action).suspended = 2;
-  if (duration == NO_MAX_DURATION) {
-    /* Move to the *end* of the corresponding action set. This convention
-       is used to speed up update_resource_state  */
-    xbt_swag_remove(action, ((surf_action_t) action)->state_set);
-    ((surf_action_t) action)->state_set =
-        cpu_running_action_set_that_does_not_need_being_checked;
-    xbt_swag_insert(action, ((surf_action_t) action)->state_set);
-  }
-
-  lmm_update_variable_weight(surf_cpu_model->model_private->maxmin_system,
-                             GENERIC_LMM_ACTION(action).variable, 0.0);
-  if (surf_cpu_model->model_private->update_mechanism == UM_LAZY) {     // remove action from the heap
-    surf_action_lmm_heap_remove(surf_cpu_model->model_private->action_heap,(surf_action_lmm_t)action);
-    // this is necessary for a variable with weight 0 since such
-    // variables are ignored in lmm and we need to set its max_duration
-    // correctly at the next call to share_resources
-    xbt_swag_insert_at_head(action,surf_cpu_model->model_private->modified_set);
-  }
-
-  XBT_OUT();
-  return (surf_action_t) action;
-}
-
-static e_surf_resource_state_t cpu_get_state(void *cpu)
-{
-  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->state_current;
-}
-
-static double cpu_get_speed(void *cpu, double load)
-{
-  return load * ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak;
-}
-
-static int cpu_get_core(void *cpu)
-{
-  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->core;
-}
-
-
-static double cpu_get_available_speed(void *cpu)
-{
-  /* number between 0 and 1 */
-  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_scale;
-}
-
-static double cpu_get_current_power_peak(void *cpu)
-{
-  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak;
-}
-
-static double cpu_get_power_peak_at(void *cpu, int pstate_index)
-{
-  xbt_dynar_t plist = ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak_list;
-  xbt_assert((pstate_index <= xbt_dynar_length(plist)), "Invalid parameters (pstate index out of bounds)");
-
-  return xbt_dynar_get_as(plist, pstate_index, double);
-}
-
-static int cpu_get_nb_pstates(void *cpu)
-{
-  return xbt_dynar_length(((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->power_peak_list);
-}
-
-static void cpu_set_power_peak_at(void *cpu, int pstate_index)
-{
-  cpu_Cas01_t cpu_implem = (cpu_Cas01_t)surf_cpu_resource_priv(cpu);
-  xbt_dynar_t plist = cpu_implem->power_peak_list;
-  xbt_assert((pstate_index <= xbt_dynar_length(plist)), "Invalid parameters (pstate index out of bounds)");
-
-  double new_power_peak = xbt_dynar_get_as(plist, pstate_index, double);
-  cpu_implem->pstate = pstate_index;
-  cpu_implem->power_peak = new_power_peak;
-}
-
-static double cpu_get_consumed_energy(void *cpu)
-{
-  return ((cpu_Cas01_t)surf_cpu_resource_priv(cpu))->energy->total_energy;
-}
-
-static void cpu_finalize(void)
-{
-  lmm_system_free(surf_cpu_model->model_private->maxmin_system);
-  surf_cpu_model->model_private->maxmin_system = NULL;
-
-  if (surf_cpu_model->model_private->action_heap)
-    xbt_heap_free(surf_cpu_model->model_private->action_heap);
-  xbt_swag_free(surf_cpu_model->model_private->modified_set);
-
-  surf_model_exit(surf_cpu_model);
-  surf_cpu_model = NULL;
-
-  xbt_swag_free(cpu_running_action_set_that_does_not_need_being_checked);
-  cpu_running_action_set_that_does_not_need_being_checked = NULL;
-}
-
-static void surf_cpu_model_init_internal()
-{
-  s_surf_action_t action;
-  s_surf_action_cpu_Cas01_t comp;
-
-  char *optim = xbt_cfg_get_string(_sg_cfg_set, "cpu/optim");
-  int select =
-      xbt_cfg_get_boolean(_sg_cfg_set, "cpu/maxmin_selective_update");
-
-  surf_cpu_model = surf_model_init();
-
-  if (!strcmp(optim, "Full")) {
-    surf_cpu_model->model_private->update_mechanism = UM_FULL;
-    surf_cpu_model->model_private->selective_update = select;
-  } else if (!strcmp(optim, "Lazy")) {
-    surf_cpu_model->model_private->update_mechanism = UM_LAZY;
-    surf_cpu_model->model_private->selective_update = 1;
-    xbt_assert((select == 1)
-               ||
-               (xbt_cfg_is_default_value
-                (_sg_cfg_set, "cpu/maxmin_selective_update")),
-               "Disabling selective update while using the lazy update mechanism is dumb!");
-  } else {
-    xbt_die("Unsupported optimization (%s) for this model", optim);
-  }
-
-  cpu_running_action_set_that_does_not_need_being_checked =
-      xbt_swag_new(xbt_swag_offset(action, state_hookup));
-
-  surf_cpu_model->name = "cpu";
-
-  surf_cpu_model->action_unref = surf_action_unref;
-  surf_cpu_model->action_cancel = surf_action_cancel;
-  surf_cpu_model->action_state_set = surf_action_state_set;
-
-  surf_cpu_model->model_private->resource_used = cpu_resource_used;
-
-  if (surf_cpu_model->model_private->update_mechanism == UM_LAZY) {
-    surf_cpu_model->model_private->share_resources =
-        cpu_share_resources_lazy;
-    surf_cpu_model->model_private->update_actions_state =
-        cpu_update_actions_state_lazy;
-  } else if (surf_cpu_model->model_private->update_mechanism == UM_FULL) {
-    surf_cpu_model->model_private->share_resources =
-        cpu_share_resources_full;
-    surf_cpu_model->model_private->update_actions_state =
-        cpu_update_actions_state_full;
-  } else
-    xbt_die("Invalid cpu update mechanism!");
-
-  surf_cpu_model->model_private->update_resource_state =
-      cpu_update_resource_state;
-  surf_cpu_model->model_private->finalize = cpu_finalize;
-
-  surf_cpu_model->suspend = surf_action_suspend;
-  surf_cpu_model->resume = surf_action_resume;
-  surf_cpu_model->is_suspended = surf_action_is_suspended;
-  surf_cpu_model->set_max_duration = surf_action_set_max_duration;
-  surf_cpu_model->set_priority = surf_action_set_priority;
-#ifdef HAVE_TRACING
-  surf_cpu_model->set_category = surf_action_set_category;
-#endif
-  surf_cpu_model->get_remains = surf_action_get_remains;
-
-  surf_cpu_model->extension.cpu.execute = cpu_execute;
-  surf_cpu_model->extension.cpu.sleep = cpu_action_sleep;
-
-  surf_cpu_model->extension.cpu.get_state = cpu_get_state;
-  surf_cpu_model->extension.cpu.get_core = cpu_get_core;
-  surf_cpu_model->extension.cpu.get_speed = cpu_get_speed;
-  surf_cpu_model->extension.cpu.get_available_speed =
-      cpu_get_available_speed;
-  surf_cpu_model->extension.cpu.get_current_power_peak = cpu_get_current_power_peak;
-  surf_cpu_model->extension.cpu.get_power_peak_at = cpu_get_power_peak_at;
-  surf_cpu_model->extension.cpu.get_nb_pstates = cpu_get_nb_pstates;
-  surf_cpu_model->extension.cpu.set_power_peak_at = cpu_set_power_peak_at;
-  surf_cpu_model->extension.cpu.get_consumed_energy = cpu_get_consumed_energy;
-
-  surf_cpu_model->extension.cpu.add_traces = cpu_add_traces_cpu;
-
-  if (!surf_cpu_model->model_private->maxmin_system) {
-    surf_cpu_model->model_private->maxmin_system = lmm_system_new(surf_cpu_model->model_private->selective_update);
-  }
-  if (surf_cpu_model->model_private->update_mechanism == UM_LAZY) {
-    surf_cpu_model->model_private->action_heap = xbt_heap_new(8, NULL);
-    xbt_heap_set_update_callback(surf_cpu_model->model_private->action_heap,
-        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));
-    surf_cpu_model->model_private->maxmin_system->keep_track = surf_cpu_model->model_private->modified_set;
-  }
-}
-
-/*********************************************************************/
-/* Basic sharing model for CPU: that is where all this started... ;) */
-/*********************************************************************/
-/* @InProceedings{casanova01simgrid, */
-/*   author =       "H. Casanova", */
-/*   booktitle =    "Proceedings of the IEEE Symposium on Cluster Computing */
-/*                  and the Grid (CCGrid'01)", */
-/*   publisher =    "IEEE Computer Society", */
-/*   title =        "Simgrid: {A} Toolkit for the Simulation of Application */
-/*                  Scheduling", */
-/*   year =         "2001", */
-/*   month =        may, */
-/*   note =         "Available at */
-/*                  \url{http://grail.sdsc.edu/papers/simgrid_ccgrid01.ps.gz}." */
-/* } */
-
-void surf_cpu_model_init_Cas01()
-{
-  char *optim = xbt_cfg_get_string(_sg_cfg_set, "cpu/optim");
-
-  if (surf_cpu_model)
-    return;
-
-  if (!strcmp(optim, "TI")) {
-    surf_cpu_model_init_ti();
-    return;
-  }
-
-  surf_cpu_model_init_internal();
-  cpu_define_callbacks();
-  xbt_dynar_push(model_list, &surf_cpu_model);
-}
diff --git a/src/surf/cpu_cas01.cpp b/src/surf/cpu_cas01.cpp
new file mode 100644 (file)
index 0000000..0ea0217
--- /dev/null
@@ -0,0 +1,505 @@
+/* Copyright (c) 2009-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 "cpu_cas01.hpp"
+#include "cpu_ti.hpp"
+#include "surf.hpp"
+#include "maxmin_private.h"
+#include "simgrid/sg_config.h"
+
+extern "C" {
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu_cas, surf_cpu,
+                                "Logging specific to the SURF CPU IMPROVED module");
+}
+
+static xbt_swag_t
+    cpu_running_action_set_that_does_not_need_being_checked = NULL;
+
+/*************
+ * CallBacks *
+ *************/
+
+static void parse_cpu_init(sg_platf_host_cbarg_t host){
+  ((CpuCas01ModelPtr)surf_cpu_model_pm)->parseInit(host);
+}
+
+static void cpu_add_traces_cpu(){
+  surf_cpu_model_pm->addTraces();
+}
+
+static void cpu_define_callbacks()
+{
+  sg_platf_host_add_cb(parse_cpu_init);
+  sg_platf_postparse_add_cb(cpu_add_traces_cpu);
+}
+
+/*********
+ * Model *
+ *********/
+void surf_cpu_model_init_Cas01()
+{
+  char *optim = xbt_cfg_get_string(_sg_cfg_set, "cpu/optim");
+
+  if (surf_cpu_model_pm)
+    return;
+
+  if (!strcmp(optim, "TI")) {
+    surf_cpu_model_init_ti();
+    return;
+  }
+
+  surf_cpu_model_pm = new CpuCas01Model();
+  cpu_define_callbacks();
+  ModelPtr model = static_cast<ModelPtr>(surf_cpu_model_pm);
+  xbt_dynar_push(model_list, &model);
+}
+
+CpuCas01Model::CpuCas01Model() : CpuModel("cpu")
+{
+  ActionPtr action;
+  ActionLmmPtr actionlmm;
+
+  char *optim = xbt_cfg_get_string(_sg_cfg_set, "cpu/optim");
+  int select = xbt_cfg_get_boolean(_sg_cfg_set, "cpu/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, "cpu/maxmin_selective_update")),
+               "Disabling selective update while using the lazy update mechanism is dumb!");
+  } else {
+    xbt_die("Unsupported optimization (%s) for this model", optim);
+  }
+
+  cpu_running_action_set_that_does_not_need_being_checked =
+      xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
+
+  if (p_updateMechanism == UM_LAZY) {
+       shareResources = &CpuCas01Model::shareResourcesLazy;
+       updateActionsState = &CpuCas01Model::updateActionsStateLazy;
+
+  } else if (p_updateMechanism == UM_FULL) {
+       shareResources = &CpuCas01Model::shareResourcesFull;
+       updateActionsState = &CpuCas01Model::updateActionsStateFull;
+  } else
+    xbt_die("Invalid cpu update mechanism!");
+
+  if (!p_maxminSystem) {
+    p_maxminSystem = lmm_system_new(m_selectiveUpdate);
+  }
+
+  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(*actionlmm, p_actionListHookup));
+    p_maxminSystem->keep_track = p_modifiedSet;
+  }
+}
+
+CpuCas01Model::~CpuCas01Model()
+{
+  lmm_system_free(p_maxminSystem);
+  p_maxminSystem = NULL;
+
+  if (p_actionHeap)
+    xbt_heap_free(p_actionHeap);
+  xbt_swag_free(p_modifiedSet);
+
+  surf_cpu_model_pm = NULL;
+
+  xbt_swag_free(cpu_running_action_set_that_does_not_need_being_checked);
+  cpu_running_action_set_that_does_not_need_being_checked = NULL;
+}
+
+void CpuCas01Model::parseInit(sg_platf_host_cbarg_t host)
+{
+  createResource(host->id,
+        host->power_peak,
+        host->pstate,
+        host->power_scale,
+        host->power_trace,
+        host->core_amount,
+        host->initial_state,
+        host->state_trace,
+        host->properties);
+}
+
+CpuCas01LmmPtr CpuCas01Model::createResource(const char *name, xbt_dynar_t power_peak,
+                                 int pstate, double power_scale,
+                          tmgr_trace_t power_trace, int core,
+                          e_surf_resource_state_t state_initial,
+                          tmgr_trace_t state_trace,
+                          xbt_dict_t cpu_properties)
+{
+  CpuPtr cpu = NULL;
+  xbt_assert(!surf_cpu_resource_priv(surf_cpu_resource_by_name(name)),
+             "Host '%s' declared several times in the platform file",
+             name);
+  xbt_assert(power_peak > 0, "Power has to be >0");
+  xbt_assert(core > 0, "Invalid number of cores %d", core);
+
+  cpu = new CpuCas01Lmm(this, name, power_peak, pstate, power_scale, power_trace, core, state_initial, state_trace, cpu_properties);
+  xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, static_cast<ResourcePtr>(cpu));
+
+  return (CpuCas01LmmPtr) xbt_lib_get_elm_or_null(host_lib, name);
+}
+
+double CpuCas01Model::shareResourcesFull(double now)
+{
+  return Model::shareResourcesMaxMin(p_runningActionSet,
+                             p_maxminSystem, lmm_solve);
+}
+
+void CpuCas01Model::addTraces()
+{
+  xbt_dict_cursor_t cursor = NULL;
+  char *trace_name, *elm;
+  static int called = 0;
+  if (called)
+    return;
+  called = 1;
+
+  /* connect all traces relative to hosts */
+  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);
+    CpuCas01LmmPtr host = static_cast<CpuCas01LmmPtr>(surf_cpu_resource_priv(surf_cpu_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, static_cast<ResourcePtr>(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);
+    CpuCas01LmmPtr host = dynamic_cast<CpuCas01LmmPtr>(static_cast<ResourcePtr>(surf_cpu_resource_priv(surf_cpu_resource_by_name(elm))));
+
+    xbt_assert(host, "Host %s undefined", elm);
+    xbt_assert(trace, "Trace %s undefined", trace_name);
+
+    host->p_powerEvent =
+        tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(host));
+  }
+}
+
+/************
+ * Resource *
+ ************/
+CpuCas01Lmm::CpuCas01Lmm(CpuCas01ModelPtr model, const char *name, xbt_dynar_t powerPeak,
+               int pstate, double powerScale, tmgr_trace_t powerTrace, int core,
+        e_surf_resource_state_t stateInitial, tmgr_trace_t stateTrace,
+       xbt_dict_t properties) :
+       CpuLmm(model, name, properties), Resource(model, name, properties) {
+  m_powerPeak = xbt_dynar_get_as(powerPeak, pstate, double);
+  p_powerPeakList = powerPeak;
+  m_pstate = pstate;
+
+  p_energy = xbt_new(s_energy_cpu_cas01_t, 1);
+  p_energy->total_energy = 0;
+  p_energy->power_range_watts_list = getWattsRangeList();
+  p_energy->last_updated = surf_get_clock();
+
+  XBT_DEBUG("CPU create: peak=%f, pstate=%d", m_powerPeak, m_pstate);
+
+  m_powerScale = powerScale;
+  m_core = core;
+  p_stateCurrent = stateInitial;
+  if (powerTrace)
+    p_powerEvent = tmgr_history_add_trace(history, powerTrace, 0.0, 0, static_cast<ResourcePtr>(this));
+
+  if (stateTrace)
+    p_stateEvent = tmgr_history_add_trace(history, stateTrace, 0.0, 0, static_cast<ResourcePtr>(this));
+
+  p_constraint = lmm_constraint_new(p_model->p_maxminSystem, this, m_core * m_powerScale * m_powerPeak);
+}
+
+CpuCas01Lmm::~CpuCas01Lmm(){
+  unsigned int iter;
+  xbt_dynar_t power_tuple = NULL;
+  xbt_dynar_foreach(p_energy->power_range_watts_list, iter, power_tuple)
+    xbt_dynar_free(&power_tuple);
+  xbt_dynar_free(&p_energy->power_range_watts_list);
+  xbt_dynar_free(&p_powerPeakList);
+  xbt_free(p_energy);
+  return;
+}
+
+bool CpuCas01Lmm::isUsed()
+{
+  return lmm_constraint_used(p_model->p_maxminSystem, p_constraint);
+}
+
+void CpuCas01Lmm::updateState(tmgr_trace_event_t event_type, double value, double date)
+{
+  lmm_variable_t var = NULL;
+  lmm_element_t elem = NULL;
+
+  if (event_type == p_powerEvent) {
+    m_powerScale = value;
+    lmm_update_constraint_bound(surf_cpu_model_pm->p_maxminSystem, p_constraint,
+                                m_core * m_powerScale *
+                                m_powerPeak);
+#ifdef HAVE_TRACING
+    TRACE_surf_host_set_power(date, m_name,
+                              m_core * m_powerScale *
+                              m_powerPeak);
+#endif
+    while ((var = lmm_get_var_from_cnst
+            (surf_cpu_model_pm->p_maxminSystem, p_constraint, &elem))) {
+      CpuCas01ActionLmmPtr action = static_cast<CpuCas01ActionLmmPtr>(static_cast<ActionLmmPtr>(lmm_variable_id(var)));
+
+      lmm_update_variable_bound(surf_cpu_model_pm->p_maxminSystem,
+                                action->p_variable,
+                                m_powerScale * m_powerPeak);
+    }
+    if (tmgr_trace_event_free(event_type))
+      p_powerEvent = NULL;
+  } else if (event_type == p_stateEvent) {
+    if (value > 0) {
+      if(p_stateCurrent == SURF_RESOURCE_OFF)
+        xbt_dynar_push_as(host_that_restart, char*, (char *)m_name);
+      p_stateCurrent = SURF_RESOURCE_ON;
+    } else {
+      lmm_constraint_t cnst = p_constraint;
+
+      p_stateCurrent = SURF_RESOURCE_OFF;
+
+      while ((var = lmm_get_var_from_cnst(surf_cpu_model_pm->p_maxminSystem, cnst, &elem))) {
+        ActionLmmPtr action = static_cast<ActionLmmPtr>(lmm_variable_id(var));
+
+        if (action->getState() == SURF_ACTION_RUNNING ||
+            action->getState() == SURF_ACTION_READY ||
+            action->getState() == SURF_ACTION_NOT_IN_THE_SYSTEM) {
+          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();
+  }
+
+  return;
+}
+
+ActionPtr CpuCas01Lmm::execute(double size)
+{
+
+  XBT_IN("(%s,%g)", m_name, size);
+  CpuCas01ActionLmmPtr action = new CpuCas01ActionLmm(surf_cpu_model_pm, size, p_stateCurrent != SURF_RESOURCE_ON);
+
+  action->m_suspended = 0;     /* Should be useless because of the
+                                                   calloc but it seems to help valgrind... */
+
+  action->p_variable =
+      lmm_variable_new(surf_cpu_model_pm->p_maxminSystem, static_cast<ActionLmmPtr>(action),
+                       action->m_priority,
+                       m_powerScale * m_powerPeak, 1);
+  if (surf_cpu_model_pm->p_updateMechanism == UM_LAZY) {
+    action->m_indexHeap = -1;
+    action->m_lastUpdate = surf_get_clock();
+    action->m_lastValue = 0.0;
+  }
+  lmm_expand(surf_cpu_model_pm->p_maxminSystem, p_constraint,
+             action->p_variable, 1.0);
+  XBT_OUT();
+  return action;
+}
+
+ActionPtr CpuCas01Lmm::sleep(double duration)
+{
+  if (duration > 0)
+    duration = MAX(duration, MAXMIN_PRECISION);
+
+  XBT_IN("(%s,%g)", m_name, duration);
+  CpuCas01ActionLmmPtr action = dynamic_cast<CpuCas01ActionLmmPtr>(execute(1.0));
+
+  // FIXME: sleep variables should not consume 1.0 in lmm_expand
+  action->m_maxDuration = duration;
+  action->m_suspended = 2;
+  if (duration == NO_MAX_DURATION) {
+    /* Move to the *end* of the corresponding action set. This convention
+       is used to speed up update_resource_state  */
+    xbt_swag_remove(static_cast<ActionPtr>(action), action->p_stateSet);
+    action->p_stateSet = cpu_running_action_set_that_does_not_need_being_checked;
+    xbt_swag_insert(static_cast<ActionPtr>(action), action->p_stateSet);
+  }
+
+  lmm_update_variable_weight(surf_cpu_model_pm->p_maxminSystem,
+                             action->p_variable, 0.0);
+  if (surf_cpu_model_pm->p_updateMechanism == UM_LAZY) {     // remove action from the heap
+    action->heapRemove(surf_cpu_model_pm->p_actionHeap);
+    // this is necessary for a variable with weight 0 since such
+    // variables are ignored in lmm and we need to set its max_duration
+    // correctly at the next call to share_resources
+    xbt_swag_insert_at_head(static_cast<ActionLmmPtr>(action), surf_cpu_model_pm->p_modifiedSet);
+  }
+
+  XBT_OUT();
+  return action;
+}
+
+xbt_dynar_t CpuCas01Lmm::getWattsRangeList()
+{
+       xbt_dynar_t power_range_list;
+       xbt_dynar_t power_tuple;
+       int i = 0, pstate_nb=0;
+       xbt_dynar_t current_power_values;
+       double min_power, max_power;
+
+       if (m_properties == NULL)
+               return NULL;
+
+       char* all_power_values_str = (char*)xbt_dict_get_or_null(m_properties, "power_per_state");
+
+       if (all_power_values_str == NULL)
+               return NULL;
+
+
+       power_range_list = xbt_dynar_new(sizeof(xbt_dynar_t), NULL);
+       xbt_dynar_t all_power_values = xbt_str_split(all_power_values_str, ",");
+
+       pstate_nb = xbt_dynar_length(all_power_values);
+       for (i=0; i< pstate_nb; i++)
+       {
+               /* retrieve the power values associated with the current pstate */
+               current_power_values = xbt_str_split(xbt_dynar_get_as(all_power_values, i, char*), ":");
+               xbt_assert(xbt_dynar_length(current_power_values) > 1,
+                               "Power properties incorrectly defined - could not retrieve min and max power values for host %s",
+                               m_name);
+
+               /* min_power corresponds to the idle power (cpu load = 0) */
+               /* max_power is the power consumed at 100% cpu load       */
+               min_power = atof(xbt_dynar_get_as(current_power_values, 0, char*));
+               max_power = atof(xbt_dynar_get_as(current_power_values, 1, char*));
+
+               power_tuple = xbt_dynar_new(sizeof(double), NULL);
+               xbt_dynar_push_as(power_tuple, double, min_power);
+               xbt_dynar_push_as(power_tuple, double, max_power);
+
+               xbt_dynar_push_as(power_range_list, xbt_dynar_t, power_tuple);
+               xbt_dynar_free(&current_power_values);
+       }
+       xbt_dynar_free(&all_power_values);
+       return power_range_list;
+}
+
+/**
+ * Computes the power consumed by the host according to the current pstate and processor load
+ *
+ */
+double CpuCas01Lmm::getCurrentWattsValue(double cpu_load)
+{
+       xbt_dynar_t power_range_list = p_energy->power_range_watts_list;
+
+       if (power_range_list == NULL)
+       {
+               XBT_DEBUG("No power range properties specified for host %s", m_name);
+               return 0;
+       }
+       xbt_assert(xbt_dynar_length(power_range_list) == xbt_dynar_length(p_powerPeakList),
+                                               "The number of power ranges in the properties does not match the number of pstates for host %s",
+                                               m_name);
+
+    /* retrieve the power values associated with the current pstate */
+    xbt_dynar_t current_power_values = xbt_dynar_get_as(power_range_list, m_pstate, xbt_dynar_t);
+
+    /* min_power corresponds to the idle power (cpu load = 0) */
+    /* max_power is the power consumed at 100% cpu load       */
+    double min_power = xbt_dynar_get_as(current_power_values, 0, double);
+    double max_power = xbt_dynar_get_as(current_power_values, 1, double);
+    double power_slope = max_power - min_power;
+
+    double current_power = min_power + cpu_load * power_slope;
+
+       XBT_DEBUG("[get_current_watts] min_power=%f, max_power=%f, slope=%f", min_power, max_power, power_slope);
+    XBT_DEBUG("[get_current_watts] Current power (watts) = %f, load = %f", current_power, cpu_load);
+
+       return current_power;
+}
+
+/**
+ * Updates the total energy consumed as the sum of the current energy and
+ *                                              the energy consumed by the current action
+ */
+void CpuCas01Lmm::updateEnergy(double cpu_load)
+{
+  double start_time = p_energy->last_updated;
+  double finish_time = surf_get_clock();
+
+  XBT_DEBUG("[cpu_update_energy] action time interval=(%f-%f), current power peak=%f, current pstate=%d",
+                 start_time, finish_time, m_powerPeak, m_pstate);
+  double current_energy = p_energy->total_energy;
+  double action_energy = getCurrentWattsValue(cpu_load)*(finish_time-start_time);
+
+  p_energy->total_energy = current_energy + action_energy;
+  p_energy->last_updated = finish_time;
+
+  XBT_DEBUG("[cpu_update_energy] old_energy_value=%f, action_energy_value=%f", current_energy, action_energy);
+}
+
+double CpuCas01Lmm::getCurrentPowerPeak()
+{
+  return m_powerPeak;
+}
+
+double CpuCas01Lmm::getPowerPeakAt(int pstate_index)
+{
+  xbt_dynar_t plist = p_powerPeakList;
+  xbt_assert((pstate_index <= xbt_dynar_length(plist)), "Invalid parameters (pstate index out of bounds)");
+
+  return xbt_dynar_get_as(plist, pstate_index, double);
+}
+
+int CpuCas01Lmm::getNbPstates()
+{
+  return xbt_dynar_length(p_powerPeakList);
+}
+
+void CpuCas01Lmm::setPowerPeakAt(int pstate_index)
+{
+  xbt_dynar_t plist = p_powerPeakList;
+  xbt_assert((pstate_index <= xbt_dynar_length(plist)), "Invalid parameters (pstate index out of bounds)");
+
+  double new_power_peak = xbt_dynar_get_as(plist, pstate_index, double);
+  m_pstate = pstate_index;
+  m_powerPeak = new_power_peak;
+}
+
+double CpuCas01Lmm::getConsumedEnergy()
+{
+  return p_energy->total_energy;
+}
+
+/**********
+ * Action *
+ **********/
+
+/**
+ * Update the CPU total energy for a finished action
+ *
+ */
+void CpuCas01ActionLmm::updateEnergy()
+{
+  CpuCas01LmmPtr cpu  = static_cast<CpuCas01LmmPtr>(lmm_constraint_id(lmm_get_cnst_from_var
+                                                                                 (p_model->p_maxminSystem,
+                                                                                                 p_variable, 0)));
+
+  if(cpu->p_energy->last_updated < surf_get_clock()) {
+       double load = lmm_constraint_get_usage(cpu->p_constraint) / cpu->m_powerPeak;
+    cpu->updateEnergy(load);
+  }
+}
diff --git a/src/surf/cpu_cas01.hpp b/src/surf/cpu_cas01.hpp
new file mode 100644 (file)
index 0000000..5e12cc2
--- /dev/null
@@ -0,0 +1,88 @@
+#include "cpu.hpp"
+
+/***********
+ * Classes *
+ ***********/
+class CpuCas01Model;
+typedef CpuCas01Model *CpuCas01ModelPtr;
+
+class CpuCas01Lmm;
+typedef CpuCas01Lmm *CpuCas01LmmPtr;
+
+class CpuCas01ActionLmm;
+typedef CpuCas01ActionLmm *CpuCas01ActionLmmPtr;
+
+/*********
+ * Model *
+ *********/
+class CpuCas01Model : public CpuModel {
+public:
+  CpuCas01Model();
+  ~CpuCas01Model();
+
+  double (CpuCas01Model::*shareResources)(double now);
+  void (CpuCas01Model::*updateActionsState)(double now, double delta);
+
+  void parseInit(sg_platf_host_cbarg_t host);  
+  CpuCas01LmmPtr createResource(const char *name, xbt_dynar_t power_peak, int pstate,
+                                 double power_scale,
+                          tmgr_trace_t power_trace, int core,
+                          e_surf_resource_state_t state_initial,
+                          tmgr_trace_t state_trace,
+                          xbt_dict_t cpu_properties);
+  double shareResourcesFull(double now);  
+  void addTraces();
+};
+
+/************
+ * Resource *
+ ************/
+/*
+ * Energy-related properties for the cpu_cas01 model
+ */
+typedef struct energy_cpu_cas01 {
+       xbt_dynar_t power_range_watts_list;             /*< List of (min_power,max_power) pairs corresponding to each cpu pstate */
+       double total_energy;                                    /*< Total energy consumed by the host */
+       double last_updated;                                    /*< Timestamp of the last energy update event*/
+} s_energy_cpu_cas01_t, *energy_cpu_cas01_t;
+
+class CpuCas01Lmm : public CpuLmm {
+public:
+  CpuCas01Lmm(CpuCas01ModelPtr model, const char *name, xbt_dynar_t power_peak,
+        int pstate, double powerScale, tmgr_trace_t powerTrace, int core,
+        e_surf_resource_state_t stateInitial, tmgr_trace_t stateTrace,
+       xbt_dict_t properties) ;
+  ~CpuCas01Lmm();
+  void updateState(tmgr_trace_event_t event_type, double value, double date);
+  ActionPtr execute(double size);
+  ActionPtr sleep(double duration);
+
+  xbt_dynar_t getWattsRangeList();
+  double getCurrentWattsValue(double cpu_load);
+  void updateEnergy(double cpu_load);
+
+  double getCurrentPowerPeak();
+  double getPowerPeakAt(int pstate_index);
+  int getNbPstates();
+  void setPowerPeakAt(int pstate_index);
+  double getConsumedEnergy();
+
+  bool isUsed();
+
+  tmgr_trace_event_t p_powerEvent;
+
+  xbt_dynar_t p_powerPeakList;                         /*< List of supported CPU capacities */
+  int m_pstate;                                                                /*< Current pstate (index in the power_peak_list)*/
+  energy_cpu_cas01_t p_energy;                         /*< Structure with energy-consumption data */
+};
+
+/**********
+ * Action *
+ **********/
+class CpuCas01ActionLmm: public CpuActionLmm {
+public:
+  CpuCas01ActionLmm() {};
+  CpuCas01ActionLmm(ModelPtr model, double cost, bool failed): Action(model, cost, failed), CpuActionLmm(model, cost, failed) {};
+  void updateEnergy();
+
+};
index cb13350..c212ca5 100644 (file)
@@ -1,5 +1,4 @@
-
-/* Copyright (c) 2009-2010, 2013. The SimGrid Team.
+/* Copyright (c) 2013. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -19,7 +18,6 @@ typedef struct surf_action_cpu_cas01 {
   s_surf_action_lmm_t generic_lmm_action;
 } s_surf_action_cpu_Cas01_t, *surf_action_cpu_Cas01_t;
 
-
 /*
  * Energy-related properties for the cpu_cas01 model
  */
@@ -43,10 +41,24 @@ typedef struct cpu_Cas01 {
 
   xbt_dynar_t power_peak_list;                         /*< List of supported CPU capacities */
   int pstate;                                                          /*< Current pstate (index in the power_peak_list)*/
-  energy_cpu_cas01_t energy;                           /*< Structure with energy-consumption data */
+  energy_cpu_cas01_t energy;   
+
+  /* Note (hypervisor): */
+  lmm_constraint_t *constraint_core;
 
 } s_cpu_Cas01_t, *cpu_Cas01_t;
 
+void *cpu_cas01_create_resource(const char *name,
+       xbt_dynar_t power_peak,
+       int pstate,
+    double power_scale,
+    tmgr_trace_t power_trace,
+    int core,
+    e_surf_resource_state_t state_initial,
+    tmgr_trace_t state_trace,
+    xbt_dict_t cpu_properties,
+    surf_model_t cpu_model);
+
 xbt_dynar_t cpu_get_watts_range_list(cpu_Cas01_t cpu_model);
 void cpu_update_energy(cpu_Cas01_t cpu_model, double cpu_load);
 
diff --git a/src/surf/cpu_ti.c b/src/surf/cpu_ti.c
deleted file mode 100644 (file)
index b14ceec..0000000
+++ /dev/null
@@ -1,1099 +0,0 @@
-
-/* Copyright (c) 2009-2013. 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. */
-
-/*
-  commit: e2d6799c4182f00443b3013aadb1c2412372460f
-  This commit retrieves the old implementation of CPU_TI with multi-levels.
-*/
-
-#include "surf_private.h"
-#include "trace_mgr_private.h"
-#include "cpu_ti_private.h"
-#include "xbt/heap.h"
-#include "surf/surf_resource.h"
-
-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 = NULL;
-static xbt_swag_t cpu_ti_modified_cpu = NULL;
-static xbt_heap_t cpu_ti_action_heap;
-
-/* prototypes of new trace functions */
-static double surf_cpu_ti_integrate_trace(surf_cpu_ti_tgmr_t trace,
-                                          double a, double b);
-
-
-static double surf_cpu_ti_solve_trace(surf_cpu_ti_tgmr_t trace, double a,
-                                      double amount);
-static double surf_cpu_ti_solve_trace_somewhat_simple(surf_cpu_ti_tgmr_t
-                                                      trace, double a,
-                                                      double amount);
-
-static void surf_cpu_ti_free_tmgr(surf_cpu_ti_tgmr_t trace);
-
-static double surf_cpu_ti_integrate_trace_simple(surf_cpu_ti_trace_t trace,
-                                                 double a, double b);
-static double surf_cpu_ti_integrate_trace_simple_point(surf_cpu_ti_trace_t
-                                                       trace, double a);
-static double surf_cpu_ti_solve_trace_simple(surf_cpu_ti_trace_t trace,
-                                             double a, double amount);
-static int surf_cpu_ti_binary_search(double *array, double a, int low,
-                                     int high);
-/* end prototypes */
-
-static void surf_cpu_ti_free_trace(surf_cpu_ti_trace_t trace)
-{
-  xbt_free(trace->time_points);
-  xbt_free(trace->integral);
-  xbt_free(trace);
-}
-
-static void surf_cpu_ti_free_tmgr(surf_cpu_ti_tgmr_t trace)
-{
-  if (trace->trace)
-    surf_cpu_ti_free_trace(trace->trace);
-  xbt_free(trace);
-}
-
-static surf_cpu_ti_trace_t surf_cpu_ti_trace_new(tmgr_trace_t power_trace)
-{
-  surf_cpu_ti_trace_t trace;
-  s_tmgr_event_t val;
-  unsigned int cpt;
-  double integral = 0;
-  double time = 0;
-  int i = 0;
-  trace = xbt_new0(s_surf_cpu_ti_trace_t, 1);
-  trace->time_points =
-      xbt_malloc0(sizeof(double) *
-                  (xbt_dynar_length(power_trace->s_list.event_list) + 1));
-  trace->integral =
-      xbt_malloc0(sizeof(double) *
-                  (xbt_dynar_length(power_trace->s_list.event_list) + 1));
-  trace->nb_points = xbt_dynar_length(power_trace->s_list.event_list);
-  xbt_dynar_foreach(power_trace->s_list.event_list, cpt, val) {
-    trace->time_points[i] = time;
-    trace->integral[i] = integral;
-    integral += val.delta * val.value;
-    time += val.delta;
-    i++;
-  }
-  trace->time_points[i] = time;
-  trace->integral[i] = integral;
-  return trace;
-}
-
-/**
-* \brief Creates a new integration trace from a tmgr_trace_t
-*
-* \param  power_trace    CPU availability trace
-* \param  value          Percentage of CPU power available (useful to fixed tracing)
-* \param  spacing        Initial spacing
-* \return  Integration trace structure
-*/
-static surf_cpu_ti_tgmr_t cpu_ti_parse_trace(tmgr_trace_t power_trace,
-                                             double value)
-{
-  surf_cpu_ti_tgmr_t trace;
-  double total_time = 0.0;
-  s_tmgr_event_t val;
-  unsigned int cpt;
-  trace = xbt_new0(s_surf_cpu_ti_tgmr_t, 1);
-
-/* no availability file, fixed trace */
-  if (!power_trace) {
-    trace->type = TRACE_FIXED;
-    trace->value = value;
-    XBT_DEBUG("No availability trace. Constant value = %f", value);
-    return trace;
-  }
-
-  /* only one point available, fixed trace */
-  if (xbt_dynar_length(power_trace->s_list.event_list) == 1) {
-    xbt_dynar_get_cpy(power_trace->s_list.event_list, 0, &val);
-    trace->type = TRACE_FIXED;
-    trace->value = val.value;
-    return trace;
-  }
-
-  trace->type = TRACE_DYNAMIC;
-  trace->power_trace = power_trace;
-
-  /* count the total time of trace file */
-  xbt_dynar_foreach(power_trace->s_list.event_list, cpt, val) {
-    total_time += val.delta;
-  }
-  trace->trace = surf_cpu_ti_trace_new(power_trace);
-  trace->last_time = total_time;
-  trace->total =
-      surf_cpu_ti_integrate_trace_simple(trace->trace, 0, total_time);
-
-  XBT_DEBUG("Total integral %f, last_time %f ",
-         trace->total, trace->last_time);
-
-  return trace;
-}
-
-
-static void* cpu_ti_create_resource(const char *name, xbt_dynar_t power_peak,
-                                                  int pstate,
-                           double power_scale,
-                           tmgr_trace_t power_trace,
-                           int core,
-                           e_surf_resource_state_t state_initial,
-                           tmgr_trace_t state_trace,
-                           xbt_dict_t cpu_properties)
-{
-  tmgr_trace_t empty_trace;
-  s_tmgr_event_t val;
-  cpu_ti_t cpu = NULL;
-  s_surf_action_cpu_ti_t ti_action;
-  xbt_assert(core==1,"Multi-core not handled with this model yet");
-  xbt_assert(!surf_cpu_resource_priv(surf_cpu_resource_by_name(name)),
-              "Host '%s' declared several times in the platform file",
-              name);
-  xbt_assert(core==1,"Multi-core not handled with this model yet");
-  cpu = (cpu_ti_t) surf_resource_new(sizeof(s_cpu_ti_t),
-          surf_cpu_model, name,cpu_properties, NULL);
-  cpu->action_set =
-      xbt_swag_new(xbt_swag_offset(ti_action, cpu_list_hookup));
-
-  xbt_dynar_get_cpy(power_peak, 0, &cpu->power_peak);
-  xbt_dynar_free(&power_peak);  /* kill memory leak */
-  //cpu->power_peak = power_peak;
-  cpu->pstate = pstate;
-  XBT_DEBUG("CPU create: peak=%f, pstate=%d",cpu->power_peak, cpu->pstate);
-
-  xbt_assert(cpu->power_peak > 0, "Power has to be >0");
-  XBT_DEBUG("power scale %f", power_scale);
-  cpu->power_scale = power_scale;
-  cpu->avail_trace = cpu_ti_parse_trace(power_trace, power_scale);
-  cpu->state_current = state_initial;
-  if (state_trace)
-    cpu->state_event =
-        tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
-  if (power_trace && xbt_dynar_length(power_trace->s_list.event_list) > 1) {
-    /* add a fake trace event if periodicity == 0 */
-    xbt_dynar_get_cpy(power_trace->s_list.event_list,
-                      xbt_dynar_length(power_trace->s_list.event_list) - 1, &val);
-    if (val.delta == 0) {
-      empty_trace = tmgr_empty_trace_new();
-      cpu->power_event =
-          tmgr_history_add_trace(history, empty_trace,
-                                 cpu->avail_trace->last_time, 0, cpu);
-    }
-  }
-  xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, cpu);
-
-  return xbt_lib_get_elm_or_null(host_lib, name);
-}
-
-
-static void parse_cpu_ti_init(sg_platf_host_cbarg_t host)
-{
-  cpu_ti_create_resource(host->id,
-        host->power_peak,
-        host->pstate,
-        host->power_scale,
-        host->power_trace,
-        host->core_amount,
-        host->initial_state,
-        host->state_trace,
-        host->properties);
-
-}
-
-static void add_traces_cpu_ti(void)
-{
-  xbt_dict_cursor_t cursor = NULL;
-  char *trace_name, *elm;
-
-  static int called = 0;
-
-  if (called)
-    return;
-  called = 1;
-
-/* connect all traces relative to hosts */
-  xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
-    tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
-    cpu_ti_t cpu = surf_cpu_resource_priv(surf_cpu_resource_by_name(elm));
-
-    xbt_assert(cpu, "Host %s undefined", elm);
-    xbt_assert(trace, "Trace %s undefined", trace_name);
-
-    if (cpu->state_event) {
-      XBT_DEBUG("Trace already configured for this CPU(%s), ignoring it",
-             elm);
-      continue;
-    }
-    XBT_DEBUG("Add state trace: %s to CPU(%s)", trace_name, elm);
-    cpu->state_event = tmgr_history_add_trace(history, trace, 0.0, 0, cpu);
-  }
-
-  xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
-    tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
-    cpu_ti_t cpu = surf_cpu_resource_priv(surf_cpu_resource_by_name(elm));
-
-    xbt_assert(cpu, "Host %s undefined", elm);
-    xbt_assert(trace, "Trace %s undefined", trace_name);
-
-    XBT_DEBUG("Add power trace: %s to CPU(%s)", trace_name, elm);
-    if (cpu->avail_trace)
-      surf_cpu_ti_free_tmgr(cpu->avail_trace);
-
-    cpu->avail_trace = cpu_ti_parse_trace(trace, cpu->power_scale);
-
-    /* add a fake trace event if periodicity == 0 */
-    if (trace && xbt_dynar_length(trace->s_list.event_list) > 1) {
-      s_tmgr_event_t val;
-      xbt_dynar_get_cpy(trace->s_list.event_list,
-                        xbt_dynar_length(trace->s_list.event_list) - 1, &val);
-      if (val.delta == 0) {
-        tmgr_trace_t empty_trace;
-        empty_trace = tmgr_empty_trace_new();
-        cpu->power_event =
-            tmgr_history_add_trace(history, empty_trace,
-                                   cpu->avail_trace->last_time, 0, cpu);
-      }
-    }
-  }
-}
-
-static void cpu_ti_define_callbacks()
-{
-  sg_platf_host_add_cb(parse_cpu_ti_init);
-  sg_platf_postparse_add_cb(add_traces_cpu_ti);
-}
-
-static int cpu_ti_resource_used(void *resource_id)
-{
-  cpu_ti_t cpu = resource_id;
-  return xbt_swag_size(cpu->action_set);
-}
-
-static int cpu_ti_action_unref(surf_action_t action)
-{
-  action->refcount--;
-  if (!action->refcount) {
-    xbt_swag_remove(action, action->state_set);
-    /* remove from action_set */
-    xbt_swag_remove(action, ((cpu_ti_t)surf_cpu_resource_priv(ACTION_GET_CPU(action)))->action_set);
-    /* remove from heap */
-    xbt_heap_remove(cpu_ti_action_heap,
-                    ((surf_action_cpu_ti_t) action)->index_heap);
-    xbt_swag_insert(((cpu_ti_t)surf_cpu_resource_priv(ACTION_GET_CPU(action))), cpu_ti_modified_cpu);
-    surf_action_free(&action);
-    return 1;
-  }
-  return 0;
-}
-
-static void cpu_ti_action_cancel(surf_action_t action)
-{
-  surf_action_state_set(action, SURF_ACTION_FAILED);
-  xbt_heap_remove(cpu_ti_action_heap,
-                  ((surf_action_cpu_ti_t) action)->index_heap);
-  xbt_swag_insert(surf_cpu_resource_priv(ACTION_GET_CPU(action)), cpu_ti_modified_cpu);
-  return;
-}
-
-static void cpu_ti_action_state_set(surf_action_t action,
-                                    e_surf_action_state_t state)
-{
-  surf_action_state_set(action, state);
-  xbt_swag_insert(surf_cpu_resource_priv(ACTION_GET_CPU(action)), cpu_ti_modified_cpu);
-  return;
-}
-
-/**
-* \brief Update the remaining amount of actions
-*
-* \param  cpu    Cpu on which the actions are running
-* \param  now    Current time
-*/
-static void cpu_ti_update_remaining_amount(cpu_ti_t cpu, double now)
-{
-  double area_total;
-  surf_action_cpu_ti_t action;
-
-/* already updated */
-  if (cpu->last_update >= now)
-    return;
-
-/* calcule the surface */
-  area_total =
-      surf_cpu_ti_integrate_trace(cpu->avail_trace, cpu->last_update,
-                                  now) * cpu->power_peak;
-  XBT_DEBUG("Flops total: %f, Last update %f", area_total,
-         cpu->last_update);
-
-  xbt_swag_foreach(action, cpu->action_set) {
-    surf_action_t generic = (surf_action_t)action;
-    /* action not running, skip it */
-    if (generic->state_set !=
-        surf_cpu_model->states.running_action_set)
-      continue;
-
-    /* bogus priority, skip it */
-    if (generic->priority <= 0)
-      continue;
-
-    /* action suspended, skip it */
-    if (action->suspended != 0)
-      continue;
-
-    /* action don't need update */
-    if (generic->start >= now)
-      continue;
-
-    /* skip action that are finishing now */
-    if (generic->finish >= 0
-        && generic->finish <= now)
-      continue;
-
-    /* update remaining */
-    double_update(&(generic->remains),
-                  area_total / (cpu->sum_priority *
-                                generic->priority));
-    XBT_DEBUG("Update remaining action(%p) remaining %f", action,
-           generic->remains);
-  }
-  cpu->last_update = now;
-#undef GENERIC_ACTION
-}
-
-/**
-* \brief Update the finish date of action if necessary
-*
-* \param  cpu    Cpu on which the actions are running
-* \param  now    Current time
-*/
-static void cpu_ti_update_action_finish_date(cpu_ti_t cpu, double now)
-{
-#define GENERIC_ACTION(action) action->generic_action
-  surf_action_cpu_ti_t action;
-  double sum_priority = 0.0, total_area, min_finish = -1;
-
-/* update remaning amount of actions */
-  cpu_ti_update_remaining_amount(cpu, now);
-
-  xbt_swag_foreach(action, cpu->action_set) {
-    /* action not running, skip it */
-    if (GENERIC_ACTION(action).state_set !=
-        surf_cpu_model->states.running_action_set)
-      continue;
-
-    /* bogus priority, skip it */
-    if (GENERIC_ACTION(action).priority <= 0)
-      continue;
-
-    /* action suspended, skip it */
-    if (action->suspended != 0)
-      continue;
-
-    sum_priority += 1.0 / GENERIC_ACTION(action).priority;
-  }
-  cpu->sum_priority = sum_priority;
-
-  xbt_swag_foreach(action, cpu->action_set) {
-    min_finish = -1;
-    /* action not running, skip it */
-    if (GENERIC_ACTION(action).state_set !=
-        surf_cpu_model->states.running_action_set)
-      continue;
-
-    /* verify if the action is really running on cpu */
-    if (action->suspended == 0 && GENERIC_ACTION(action).priority > 0) {
-      /* total area needed to finish the action. Used in trace integration */
-      total_area =
-          (GENERIC_ACTION(action).remains) * sum_priority *
-          GENERIC_ACTION(action).priority;
-
-      total_area /= cpu->power_peak;
-
-      GENERIC_ACTION(action).finish =
-          surf_cpu_ti_solve_trace(cpu->avail_trace, now, total_area);
-      /* verify which event will happen before (max_duration or finish time) */
-      if ((GENERIC_ACTION(action).max_duration != NO_MAX_DURATION) &&
-          (GENERIC_ACTION(action).start +
-           GENERIC_ACTION(action).max_duration <
-           GENERIC_ACTION(action).finish))
-        min_finish = GENERIC_ACTION(action).start +
-            GENERIC_ACTION(action).max_duration;
-      else
-        min_finish = GENERIC_ACTION(action).finish;
-    } else {
-      /* put the max duration time on heap */
-      if (GENERIC_ACTION(action).max_duration != NO_MAX_DURATION)
-        min_finish =
-            (GENERIC_ACTION(action).start +
-             GENERIC_ACTION(action).max_duration);
-    }
-    /* add in action heap */
-    XBT_DEBUG("action(%p) index %d", action, action->index_heap);
-    if (action->index_heap >= 0) {
-      surf_action_cpu_ti_t heap_act =
-          xbt_heap_remove(cpu_ti_action_heap, action->index_heap);
-      if (heap_act != action)
-        DIE_IMPOSSIBLE;
-    }
-    if (min_finish != NO_MAX_DURATION)
-      xbt_heap_push(cpu_ti_action_heap, action, min_finish);
-
-    XBT_DEBUG
-        ("Update finish time: Cpu(%s) Action: %p, Start Time: %f Finish Time: %f Max duration %f",
-         cpu->generic_resource.name, action, GENERIC_ACTION(action).start,
-         GENERIC_ACTION(action).finish,
-         GENERIC_ACTION(action).max_duration);
-  }
-/* remove from modified cpu */
-  xbt_swag_remove(cpu, cpu_ti_modified_cpu);
-#undef GENERIC_ACTION
-}
-
-static double cpu_ti_share_resources(double now)
-{
-  cpu_ti_t cpu, cpu_next;
-  double min_action_duration = -1;
-
-/* iterates over modified cpus to update share resources */
-  xbt_swag_foreach_safe(cpu, cpu_next, cpu_ti_modified_cpu) {
-    cpu_ti_update_action_finish_date(cpu, now);
-  }
-/* get the min next event if heap not empty */
-  if (xbt_heap_size(cpu_ti_action_heap) > 0)
-    min_action_duration = xbt_heap_maxkey(cpu_ti_action_heap) - now;
-
-  XBT_DEBUG("Share resources, min next event date: %f", min_action_duration);
-
-  return min_action_duration;
-}
-
-static void cpu_ti_update_actions_state(double now, double delta)
-{
-#define GENERIC_ACTION(action) action->generic_action
-  surf_action_cpu_ti_t action;
-  while ((xbt_heap_size(cpu_ti_action_heap) > 0)
-         && (xbt_heap_maxkey(cpu_ti_action_heap) <= now)) {
-    action = xbt_heap_pop(cpu_ti_action_heap);
-    XBT_DEBUG("Action %p: finish", action);
-    GENERIC_ACTION(action).finish = surf_get_clock();
-    /* set the remains to 0 due to precision problems when updating the remaining amount */
-    GENERIC_ACTION(action).remains = 0;
-    cpu_ti_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
-    /* update remaining amount of all actions */
-    cpu_ti_update_remaining_amount(surf_cpu_resource_priv(action->cpu), surf_get_clock());
-  }
-#undef GENERIC_ACTION
-}
-
-static void cpu_ti_update_resource_state(void *id,
-                                         tmgr_trace_event_t event_type,
-                                         double value, double date)
-{
-  cpu_ti_t cpu = id;
-  surf_action_cpu_ti_t action;
-
-  if (event_type == cpu->power_event) {
-    tmgr_trace_t power_trace;
-    surf_cpu_ti_tgmr_t trace;
-    s_tmgr_event_t val;
-
-    XBT_DEBUG("Finish trace date: %f value %f date %f", surf_get_clock(),
-           value, date);
-    /* update remaining of actions and put in modified cpu swag */
-    cpu_ti_update_remaining_amount(cpu, date);
-    xbt_swag_insert(cpu, cpu_ti_modified_cpu);
-
-    power_trace = cpu->avail_trace->power_trace;
-    xbt_dynar_get_cpy(power_trace->s_list.event_list,
-                      xbt_dynar_length(power_trace->s_list.event_list) - 1, &val);
-    /* free old trace */
-    surf_cpu_ti_free_tmgr(cpu->avail_trace);
-    cpu->power_scale = val.value;
-
-    trace = xbt_new0(s_surf_cpu_ti_tgmr_t, 1);
-    trace->type = TRACE_FIXED;
-    trace->value = val.value;
-    XBT_DEBUG("value %f", val.value);
-
-    cpu->avail_trace = trace;
-
-    if (tmgr_trace_event_free(event_type))
-      cpu->power_event = NULL;
-
-  } else if (event_type == cpu->state_event) {
-    if (value > 0) {
-      if(cpu->state_current == SURF_RESOURCE_OFF)
-        xbt_dynar_push_as(host_that_restart, char*, (cpu->generic_resource.name));
-      cpu->state_current = SURF_RESOURCE_ON;
-    } else {
-      cpu->state_current = SURF_RESOURCE_OFF;
-
-      /* put all action running on cpu to failed */
-      xbt_swag_foreach(action, cpu->action_set) {
-        if (surf_action_state_get((surf_action_t) action) ==
-            SURF_ACTION_RUNNING
-            || surf_action_state_get((surf_action_t) action) ==
-            SURF_ACTION_READY
-            || surf_action_state_get((surf_action_t) action) ==
-            SURF_ACTION_NOT_IN_THE_SYSTEM) {
-          action->generic_action.finish = date;
-          cpu_ti_action_state_set((surf_action_t) action,
-                                  SURF_ACTION_FAILED);
-          if (action->index_heap >= 0) {
-            surf_action_cpu_ti_t heap_act =
-                xbt_heap_remove(cpu_ti_action_heap, action->index_heap);
-            if (heap_act != action)
-              DIE_IMPOSSIBLE;
-          }
-        }
-      }
-    }
-    if (tmgr_trace_event_free(event_type))
-      cpu->state_event = NULL;
-  } else {
-    XBT_CRITICAL("Unknown event ! \n");
-    xbt_abort();
-  }
-
-  return;
-}
-
-static surf_action_t cpu_ti_execute(void *cpu, double size)
-{
-  surf_action_cpu_ti_t action = NULL;
-  cpu_ti_t CPU = surf_cpu_resource_priv(cpu);
-
-  XBT_IN("(%s,%g)", surf_resource_name(CPU), size);
-  action =
-      surf_action_new(sizeof(s_surf_action_cpu_ti_t), size, surf_cpu_model,
-                      CPU->state_current != SURF_RESOURCE_ON);
-  action->cpu = cpu;
-  action->index_heap = -1;
-
-  xbt_swag_insert(CPU, cpu_ti_modified_cpu);
-
-  xbt_swag_insert(action, CPU->action_set);
-
-  action->suspended = 0;        /* Should be useless because of the
-                                   calloc but it seems to help valgrind... */
-
-  XBT_OUT();
-  return (surf_action_t) action;
-}
-
-static void cpu_ti_action_update_index_heap(void *action, int i)
-{
-  ((surf_action_cpu_ti_t) action)->index_heap = i;
-}
-
-static surf_action_t cpu_ti_action_sleep(void *cpu, double duration)
-{
-  surf_action_cpu_ti_t action = NULL;
-
-  if (duration > 0)
-    duration = MAX(duration, MAXMIN_PRECISION);
-
-  XBT_IN("(%s,%g)", surf_resource_name(surf_cpu_resource_priv(cpu)), duration);
-  action = (surf_action_cpu_ti_t) cpu_ti_execute(cpu, 1.0);
-  action->generic_action.max_duration = duration;
-  action->suspended = 2;
-  if (duration == NO_MAX_DURATION) {
-    /* Move to the *end* of the corresponding action set. This convention
-       is used to speed up update_resource_state  */
-    xbt_swag_remove(action, ((surf_action_t) action)->state_set);
-    ((surf_action_t) action)->state_set =
-        cpu_ti_running_action_set_that_does_not_need_being_checked;
-    xbt_swag_insert(action, ((surf_action_t) action)->state_set);
-  }
-  XBT_OUT();
-  return (surf_action_t) action;
-}
-
-static void cpu_ti_action_suspend(surf_action_t action)
-{
-  XBT_IN("(%p)", action);
-  if (((surf_action_cpu_ti_t) action)->suspended != 2) {
-    ((surf_action_cpu_ti_t) action)->suspended = 1;
-    xbt_heap_remove(cpu_ti_action_heap,
-                    ((surf_action_cpu_ti_t) action)->index_heap);
-    xbt_swag_insert(surf_cpu_resource_priv(ACTION_GET_CPU(action)), cpu_ti_modified_cpu);
-  }
-  XBT_OUT();
-}
-
-static void cpu_ti_action_resume(surf_action_t action)
-{
-  XBT_IN("(%p)", action);
-  if (((surf_action_cpu_ti_t) action)->suspended != 2) {
-    ((surf_action_cpu_ti_t) action)->suspended = 0;
-    xbt_swag_insert(surf_cpu_resource_priv(ACTION_GET_CPU(action)), cpu_ti_modified_cpu);
-  }
-  XBT_OUT();
-}
-
-static int cpu_ti_action_is_suspended(surf_action_t action)
-{
-  return (((surf_action_cpu_ti_t) action)->suspended == 1);
-}
-
-static void cpu_ti_action_set_max_duration(surf_action_t action,
-                                           double duration)
-{
-  surf_action_cpu_ti_t ACT = (surf_action_cpu_ti_t) action;
-  double min_finish;
-
-  XBT_IN("(%p,%g)", action, duration);
-
-  action->max_duration = duration;
-
-  if (duration >= 0)
-    min_finish =
-        (action->start + action->max_duration) <
-        action->finish ? (action->start +
-                          action->max_duration) : action->finish;
-  else
-    min_finish = action->finish;
-
-/* add in action heap */
-  if (ACT->index_heap >= 0) {
-    surf_action_cpu_ti_t heap_act =
-        xbt_heap_remove(cpu_ti_action_heap, ACT->index_heap);
-    if (heap_act != ACT)
-      DIE_IMPOSSIBLE;
-  }
-  xbt_heap_push(cpu_ti_action_heap, ACT, min_finish);
-
-  XBT_OUT();
-}
-
-static void cpu_ti_action_set_priority(surf_action_t action,
-                                       double priority)
-{
-  XBT_IN("(%p,%g)", action, priority);
-  action->priority = priority;
-  xbt_swag_insert(surf_cpu_resource_priv(ACTION_GET_CPU(action)), cpu_ti_modified_cpu);
-  XBT_OUT();
-}
-
-static double cpu_ti_action_get_remains(surf_action_t action)
-{
-  XBT_IN("(%p)", action);
-  cpu_ti_update_remaining_amount((cpu_ti_t)
-                                 ((surf_action_cpu_ti_t) action)->cpu,
-                                 surf_get_clock());
-  XBT_OUT();
-  return action->remains;
-}
-
-static e_surf_resource_state_t cpu_ti_get_state(void *cpu)
-{
-  return ((cpu_ti_t)surf_cpu_resource_priv(cpu))->state_current;
-}
-
-static double cpu_ti_get_speed(void *cpu, double load)
-{
-  return load * ((cpu_ti_t)surf_cpu_resource_priv(cpu))->power_peak;
-}
-
-/**
-* \brief Auxiliary function to update the CPU power scale.
-*
-*  This function uses the trace structure to return the power scale at the determined time a.
-* \param trace    Trace structure to search the updated power scale
-* \param a        Time
-* \return CPU power scale
-*/
-static double surf_cpu_ti_get_power_scale(surf_cpu_ti_tgmr_t trace,
-                                          double a)
-{
-  double reduced_a;
-  int point;
-  s_tmgr_event_t val;
-
-  reduced_a = a - floor(a / trace->last_time) * trace->last_time;
-  point =
-      surf_cpu_ti_binary_search(trace->trace->time_points, reduced_a, 0,
-                                trace->trace->nb_points - 1);
-  xbt_dynar_get_cpy(trace->power_trace->s_list.event_list, point, &val);
-  return val.value;
-}
-
-static double cpu_ti_get_available_speed(void *cpu)
-{
-  cpu_ti_t CPU = surf_cpu_resource_priv(cpu);
-  CPU->power_scale =
-      surf_cpu_ti_get_power_scale(CPU->avail_trace, surf_get_clock());
-/* number between 0 and 1 */
-  return CPU->power_scale;
-}
-
-static void cpu_ti_finalize(void)
-{
-  void **cpu;
-  xbt_lib_cursor_t cursor;
-  char *key;
-
-  xbt_lib_foreach(host_lib, cursor, key, cpu){
-    if(cpu[SURF_CPU_LEVEL])
-    {
-        cpu_ti_t CPU = cpu[SURF_CPU_LEVEL];
-        xbt_swag_free(CPU->action_set);
-        surf_cpu_ti_free_tmgr(CPU->avail_trace);
-    }
-  }
-
-  surf_model_exit(surf_cpu_model);
-  surf_cpu_model = NULL;
-
-  xbt_swag_free
-      (cpu_ti_running_action_set_that_does_not_need_being_checked);
-  xbt_swag_free(cpu_ti_modified_cpu);
-  cpu_ti_running_action_set_that_does_not_need_being_checked = NULL;
-  xbt_heap_free(cpu_ti_action_heap);
-}
-
-static void surf_cpu_ti_model_init_internal(void)
-{
-  s_surf_action_t action;
-  s_cpu_ti_t cpu;
-
-  surf_cpu_model = surf_model_init();
-
-  cpu_ti_running_action_set_that_does_not_need_being_checked =
-      xbt_swag_new(xbt_swag_offset(action, state_hookup));
-
-  cpu_ti_modified_cpu =
-      xbt_swag_new(xbt_swag_offset(cpu, modified_cpu_hookup));
-
-  surf_cpu_model->name = "cpu_ti";
-
-  surf_cpu_model->action_unref = cpu_ti_action_unref;
-  surf_cpu_model->action_cancel = cpu_ti_action_cancel;
-  surf_cpu_model->action_state_set = cpu_ti_action_state_set;
-
-  surf_cpu_model->model_private->resource_used = cpu_ti_resource_used;
-  surf_cpu_model->model_private->share_resources = cpu_ti_share_resources;
-  surf_cpu_model->model_private->update_actions_state =
-      cpu_ti_update_actions_state;
-  surf_cpu_model->model_private->update_resource_state =
-      cpu_ti_update_resource_state;
-  surf_cpu_model->model_private->finalize = cpu_ti_finalize;
-
-  surf_cpu_model->suspend = cpu_ti_action_suspend;
-  surf_cpu_model->resume = cpu_ti_action_resume;
-  surf_cpu_model->is_suspended = cpu_ti_action_is_suspended;
-  surf_cpu_model->set_max_duration = cpu_ti_action_set_max_duration;
-  surf_cpu_model->set_priority = cpu_ti_action_set_priority;
-  surf_cpu_model->get_remains = cpu_ti_action_get_remains;
-
-  surf_cpu_model->extension.cpu.execute = cpu_ti_execute;
-  surf_cpu_model->extension.cpu.sleep = cpu_ti_action_sleep;
-
-  surf_cpu_model->extension.cpu.get_state = cpu_ti_get_state;
-  surf_cpu_model->extension.cpu.get_speed = cpu_ti_get_speed;
-  surf_cpu_model->extension.cpu.get_available_speed =
-      cpu_ti_get_available_speed;
-  surf_cpu_model->extension.cpu.add_traces = add_traces_cpu_ti;
-
-  cpu_ti_action_heap = xbt_heap_new(8, NULL);
-  xbt_heap_set_update_callback(cpu_ti_action_heap,
-                               cpu_ti_action_update_index_heap);
-
-}
-
-void surf_cpu_model_init_ti()
-{
-  xbt_assert(!surf_cpu_model,"CPU model already initialized. This should not happen.");
-  surf_cpu_ti_model_init_internal();
-  cpu_ti_define_callbacks();
-  xbt_dynar_push(model_list, &surf_cpu_model);
-}
-
-
-/**
-* \brief Integrate trace
-*
-* Wrapper around surf_cpu_integrate_trace_simple() to get
-* the cyclic effect.
-*
-* \param trace Trace structure.
-* \param a      Begin of interval
-* \param b      End of interval
-* \return the integrate value. -1 if an error occurs.
-*/
-static double surf_cpu_ti_integrate_trace(surf_cpu_ti_tgmr_t trace,
-                                          double a, double b)
-{
-  double first_chunk;
-  double middle_chunk;
-  double last_chunk;
-  int a_index, b_index;
-
-  if ((a < 0.0) || (a > b)) {
-    XBT_CRITICAL
-        ("Error, invalid integration interval [%.2f,%.2f]. You probably have a task executing with negative computation amount. Check your code.",
-         a, b);
-    xbt_abort();
-  }
-  if (a == b)
-    return 0.0;
-
-  if (trace->type == TRACE_FIXED) {
-    return ((b - a) * trace->value);
-  }
-
-  if (ceil(a / trace->last_time) == a / trace->last_time)
-    a_index = 1 + (int) (ceil(a / trace->last_time));
-  else
-    a_index = (int) (ceil(a / trace->last_time));
-
-  b_index = (int) (floor(b / trace->last_time));
-
-  if (a_index > b_index) {      /* Same chunk */
-    return surf_cpu_ti_integrate_trace_simple(trace->trace,
-                                              a - (a_index -
-                                                   1) * trace->last_time,
-                                              b -
-                                              (b_index) *
-                                              trace->last_time);
-  }
-
-  first_chunk = surf_cpu_ti_integrate_trace_simple(trace->trace,
-                                                   a - (a_index -
-                                                        1) *
-                                                   trace->last_time,
-                                                   trace->last_time);
-  middle_chunk = (b_index - a_index) * trace->total;
-  last_chunk = surf_cpu_ti_integrate_trace_simple(trace->trace,
-                                                  0.0,
-                                                  b -
-                                                  (b_index) *
-                                                  trace->last_time);
-
-  XBT_DEBUG("first_chunk=%.2f  middle_chunk=%.2f  last_chunk=%.2f\n",
-         first_chunk, middle_chunk, last_chunk);
-
-  return (first_chunk + middle_chunk + last_chunk);
-}
-
-/**
- * \brief Auxiliary function to calculate the integral between a and b.
- *     It simply calculates the integral at point a and b and returns the difference 
- *   between them.
- * \param trace    Trace structure
- * \param a        Initial point
- * \param b  Final point
- * \return  Integral
-*/
-static double surf_cpu_ti_integrate_trace_simple(surf_cpu_ti_trace_t trace,
-                                                 double a, double b)
-{
-  return surf_cpu_ti_integrate_trace_simple_point(trace,
-                                                  b) -
-      surf_cpu_ti_integrate_trace_simple_point(trace, a);
-}
-
-/**
- * \brief Auxiliary function to calculate the integral at point a.
- * \param trace    Trace structure
- * \param a        point
- * \return  Integral
-*/
-static double surf_cpu_ti_integrate_trace_simple_point(surf_cpu_ti_trace_t
-                                                       trace, double a)
-{
-  double integral = 0;
-  int ind;
-  double a_aux = a;
-  ind =
-      surf_cpu_ti_binary_search(trace->time_points, a, 0,
-                                trace->nb_points - 1);
-  integral += trace->integral[ind];
-  XBT_DEBUG
-      ("a %f ind %d integral %f ind + 1 %f ind %f time +1 %f time %f",
-       a, ind, integral, trace->integral[ind + 1], trace->integral[ind],
-       trace->time_points[ind + 1], trace->time_points[ind]);
-  double_update(&a_aux, trace->time_points[ind]);
-  if (a_aux > 0)
-    integral +=
-        ((trace->integral[ind + 1] -
-          trace->integral[ind]) / (trace->time_points[ind + 1] -
-                                   trace->time_points[ind])) * (a -
-                                                                trace->
-                                                                time_points
-                                                                [ind]);
-  XBT_DEBUG("Integral a %f = %f", a, integral);
-
-  return integral;
-}
-
-/**
-* \brief Calculate the time needed to execute "amount" on cpu.
-*
-* Here, amount can span multiple trace periods
-*
-* \param trace   CPU trace structure
-* \param a        Initial time
-* \param amount  Amount to be executed
-* \return  End time
-*/
-static double surf_cpu_ti_solve_trace(surf_cpu_ti_tgmr_t trace, double a,
-                                      double amount)
-{
-  int quotient;
-  double reduced_b;
-  double reduced_amount;
-  double reduced_a;
-  double b;
-
-/* Fix very small negative numbers */
-  if ((a < 0.0) && (a > -EPSILON)) {
-    a = 0.0;
-  }
-  if ((amount < 0.0) && (amount > -EPSILON)) {
-    amount = 0.0;
-  }
-
-/* Sanity checks */
-  if ((a < 0.0) || (amount < 0.0)) {
-    XBT_CRITICAL
-        ("Error, invalid parameters [a = %.2f, amount = %.2f]. You probably have a task executing with negative computation amount. Check your code.",
-         a, amount);
-    xbt_abort();
-  }
-
-/* At this point, a and amount are positive */
-
-  if (amount < EPSILON)
-    return a;
-
-/* Is the trace fixed ? */
-  if (trace->type == TRACE_FIXED) {
-    return (a + (amount / trace->value));
-  }
-
-  XBT_DEBUG("amount %f total %f", amount, trace->total);
-/* Reduce the problem to one where amount <= trace_total */
-  quotient = (int) (floor(amount / trace->total));
-  reduced_amount = (trace->total) * ((amount / trace->total) -
-                                     floor(amount / trace->total));
-  reduced_a = a - (trace->last_time) * (int) (floor(a / trace->last_time));
-
-  XBT_DEBUG("Quotient: %d reduced_amount: %f reduced_a: %f", quotient,
-         reduced_amount, reduced_a);
-
-/* Now solve for new_amount which is <= trace_total */
-/*
-   fprintf(stderr,"reduced_a = %.2f\n",reduced_a);
-   fprintf(stderr,"reduced_amount = %.2f\n",reduced_amount);
- */
-  reduced_b =
-      surf_cpu_ti_solve_trace_somewhat_simple(trace, reduced_a,
-                                              reduced_amount);
-
-/* Re-map to the original b and amount */
-  b = (trace->last_time) * (int) (floor(a / trace->last_time)) +
-      (quotient * trace->last_time) + reduced_b;
-  return b;
-}
-
-/**
-* \brief Auxiliary function to solve integral
-*
-* Here, amount is <= trace->total
-* and a <=trace->last_time
-*
-*/
-static double surf_cpu_ti_solve_trace_somewhat_simple(surf_cpu_ti_tgmr_t
-                                                      trace, double a,
-                                                      double amount)
-{
-  double amount_till_end;
-  double b;
-
-  XBT_DEBUG("Solve integral: [%.2f, amount=%.2f]", a, amount);
-  amount_till_end =
-      surf_cpu_ti_integrate_trace(trace, a, trace->last_time);
-/*
-   fprintf(stderr,"amount_till_end=%.2f\n",amount_till_end);
- */
-
-  if (amount_till_end > amount) {
-    b = surf_cpu_ti_solve_trace_simple(trace->trace, a, amount);
-  } else {
-    b = trace->last_time +
-        surf_cpu_ti_solve_trace_simple(trace->trace, 0.0,
-                                       amount - amount_till_end);
-  }
-  return b;
-}
-
-/**
- * \brief Auxiliary function to solve integral.
- *  It returns the date when the requested amount of flops is available
- * \param trace    Trace structure
- * \param a        Initial point
- * \param amount  Amount of flops 
- * \return The date when amount is available.
-*/
-static double surf_cpu_ti_solve_trace_simple(surf_cpu_ti_trace_t trace,
-                                             double a, double amount)
-{
-  double integral_a;
-  int ind;
-  double time;
-  integral_a = surf_cpu_ti_integrate_trace_simple_point(trace, a);
-  ind =
-      surf_cpu_ti_binary_search(trace->integral, integral_a + amount, 0,
-                                trace->nb_points - 1);
-  time = trace->time_points[ind];
-  time +=
-      (integral_a + amount -
-       trace->integral[ind]) / ((trace->integral[ind + 1] -
-                                 trace->integral[ind]) /
-                                (trace->time_points[ind + 1] -
-                                 trace->time_points[ind]));
-
-  return time;
-}
-
-/**
- * \brief Binary search in array.
- *  It returns the first point of the interval in which "a" is. 
- * \param array    Array
- * \param a        Value to search
- * \param low     Low bound to search in array
- * \param high    Upper bound to search in array
- * \return Index of point
-*/
-static int surf_cpu_ti_binary_search(double *array, double a, int low,
-                                     int high)
-{
-  xbt_assert(low < high, "Wrong parameters: low (%d) should be smaller than"
-      " high (%d)", low, high);
-
-  int mid;
-  do {
-    mid = low + (high - low) / 2;
-    XBT_DEBUG("a %f low %d high %d mid %d value %f", a, low, high, mid,
-        array[mid]);
-
-    if (array[mid] > a)
-      high = mid;
-    else
-      low = mid;
-  }
-  while (low < high - 1);
-
-  return low;
-}
diff --git a/src/surf/cpu_ti.cpp b/src/surf/cpu_ti.cpp
new file mode 100644 (file)
index 0000000..922c9c7
--- /dev/null
@@ -0,0 +1,1006 @@
+#include "cpu_ti.hpp"
+#include "trace_mgr_private.h"
+#include "xbt/heap.h"
+
+#ifndef SURF_MODEL_CPUTI_H_
+#define SURF_MODEL_CPUTI_H_
+
+extern "C" {
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu_ti, surf_cpu,
+                                "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 void cpu_ti_action_update_index_heap(void *action, int i);
+
+/*********
+ * Trace *
+ *********/
+
+CpuTiTrace::CpuTiTrace(tmgr_trace_t power_trace)
+{
+  s_tmgr_event_t val;
+  unsigned int cpt;
+  double integral = 0;
+  double time = 0;
+  int i = 0;
+  p_timePoints = (double*) xbt_malloc0(sizeof(double) *
+                  (xbt_dynar_length(power_trace->s_list.event_list) + 1));
+  p_integral = (double*) xbt_malloc0(sizeof(double) *
+                  (xbt_dynar_length(power_trace->s_list.event_list) + 1));
+  m_nbPoints = xbt_dynar_length(power_trace->s_list.event_list);
+  xbt_dynar_foreach(power_trace->s_list.event_list, cpt, val) {
+    p_timePoints[i] = time;
+    p_integral[i] = integral;
+    integral += val.delta * val.value;
+    time += val.delta;
+    i++;
+  }
+  p_timePoints[i] = time;
+  p_integral[i] = integral;
+}
+
+CpuTiTrace::~CpuTiTrace()
+{
+  xbt_free(p_timePoints);
+  xbt_free(p_integral);
+}
+
+CpuTiTgmr::~CpuTiTgmr()
+{
+  if (p_trace)
+    delete p_trace;
+}
+
+/**
+* \brief Integrate trace
+*
+* Wrapper around surf_cpu_integrate_trace_simple() to get
+* the cyclic effect.
+*
+* \param trace Trace structure.
+* \param a      Begin of interval
+* \param b      End of interval
+* \return the integrate value. -1 if an error occurs.
+*/
+double CpuTiTgmr::integrate(double a, double b)
+{
+  double first_chunk;
+  double middle_chunk;
+  double last_chunk;
+  int a_index, b_index;
+
+  if ((a < 0.0) || (a > b)) {
+    XBT_CRITICAL
+        ("Error, invalid integration interval [%.2f,%.2f]. You probably have a task executing with negative computation amount. Check your code.",
+         a, b);
+    xbt_abort();
+  }
+  if (a == b)
+    return 0.0;
+
+  if (m_type == TRACE_FIXED) {
+    return ((b - a) * m_value);
+  }
+
+  if (ceil(a / m_lastTime) == a / m_lastTime)
+    a_index = 1 + (int) (ceil(a / m_lastTime));
+  else
+    a_index = (int) (ceil(a / m_lastTime));
+
+  b_index = (int) (floor(b / m_lastTime));
+
+  if (a_index > b_index) {      /* Same chunk */
+    return p_trace->integrateSimple(a - (a_index -
+                                              1) * m_lastTime,
+                                         b -
+                                         (b_index) *
+                                         m_lastTime);
+  }
+
+  first_chunk = p_trace->integrateSimple(a - (a_index -
+                                                   1) *
+                                              m_lastTime,
+                                              m_lastTime);
+  middle_chunk = (b_index - a_index) * m_total;
+  last_chunk = p_trace->integrateSimple(0.0,
+                                             b -
+                                             (b_index) *
+                                             m_lastTime);
+
+  XBT_DEBUG("first_chunk=%.2f  middle_chunk=%.2f  last_chunk=%.2f\n",
+         first_chunk, middle_chunk, last_chunk);
+
+  return (first_chunk + middle_chunk + last_chunk);
+}
+
+/**
+ * \brief Auxiliary function to calculate the integral between a and b.
+ *     It simply calculates the integral at point a and b and returns the difference 
+ *   between them.
+ * \param trace    Trace structure
+ * \param a        Initial point
+ * \param b  Final point
+ * \return  Integral
+*/
+double CpuTiTrace::integrateSimple(double a, double b)
+{
+  return integrateSimplePoint(b) - integrateSimplePoint(a);
+}
+
+/**
+ * \brief Auxiliary function to calculate the integral at point a.
+ * \param trace    Trace structure
+ * \param a        point
+ * \return  Integral
+*/
+double CpuTiTrace::integrateSimplePoint(double a)
+{
+  double integral = 0;
+  int ind;
+  double a_aux = a;
+  ind = binarySearch(p_timePoints, a, 0, m_nbPoints - 1);
+  integral += p_integral[ind];
+  XBT_DEBUG
+      ("a %f ind %d integral %f ind + 1 %f ind %f time +1 %f time %f",
+       a, ind, integral, p_integral[ind + 1], p_integral[ind],
+       p_timePoints[ind + 1], p_timePoints[ind]);
+  double_update(&a_aux, p_timePoints[ind]);
+  if (a_aux > 0)
+    integral +=
+        ((p_integral[ind + 1] -
+          p_integral[ind]) / (p_timePoints[ind + 1] -
+                              p_timePoints[ind])) * (a - p_timePoints[ind]);
+  XBT_DEBUG("Integral a %f = %f", a, integral);
+
+  return integral;
+}
+
+/**
+* \brief Calculate the time needed to execute "amount" on cpu.
+*
+* Here, amount can span multiple trace periods
+*
+* \param trace   CPU trace structure
+* \param a        Initial time
+* \param amount  Amount to be executed
+* \return  End time
+*/
+double CpuTiTgmr::solve(double a, double amount)
+{
+  int quotient;
+  double reduced_b;
+  double reduced_amount;
+  double reduced_a;
+  double b;
+
+/* Fix very small negative numbers */
+  if ((a < 0.0) && (a > -EPSILON)) {
+    a = 0.0;
+  }
+  if ((amount < 0.0) && (amount > -EPSILON)) {
+    amount = 0.0;
+  }
+
+/* Sanity checks */
+  if ((a < 0.0) || (amount < 0.0)) {
+    XBT_CRITICAL
+        ("Error, invalid parameters [a = %.2f, amount = %.2f]. You probably have a task executing with negative computation amount. Check your code.",
+         a, amount);
+    xbt_abort();
+  }
+
+/* At this point, a and amount are positive */
+
+  if (amount < EPSILON)
+    return a;
+
+/* Is the trace fixed ? */
+  if (m_type == TRACE_FIXED) {
+    return (a + (amount / m_value));
+  }
+
+  XBT_DEBUG("amount %f total %f", amount, m_total);
+/* Reduce the problem to one where amount <= trace_total */
+  quotient = (int) (floor(amount / m_total));
+  reduced_amount = (m_total) * ((amount / m_total) -
+                                     floor(amount / m_total));
+  reduced_a = a - (m_lastTime) * (int) (floor(a / m_lastTime));
+
+  XBT_DEBUG("Quotient: %d reduced_amount: %f reduced_a: %f", quotient,
+         reduced_amount, reduced_a);
+
+/* Now solve for new_amount which is <= trace_total */
+/*
+   fprintf(stderr,"reduced_a = %.2f\n",reduced_a);
+   fprintf(stderr,"reduced_amount = %.2f\n",reduced_amount);
+ */
+  reduced_b = solveSomewhatSimple(reduced_a, reduced_amount);
+
+/* Re-map to the original b and amount */
+  b = (m_lastTime) * (int) (floor(a / m_lastTime)) +
+      (quotient * m_lastTime) + reduced_b;
+  return b;
+}
+
+/**
+* \brief Auxiliary function to solve integral
+*
+* Here, amount is <= trace->total
+* and a <=trace->last_time
+*
+*/
+double CpuTiTgmr::solveSomewhatSimple(double a, double amount)
+{
+  double amount_till_end;
+  double b;
+
+  XBT_DEBUG("Solve integral: [%.2f, amount=%.2f]", a, amount);
+  amount_till_end = integrate(a, m_lastTime);
+/*
+   fprintf(stderr,"amount_till_end=%.2f\n",amount_till_end);
+ */
+
+  if (amount_till_end > amount) {
+    b = p_trace->solveSimple(a, amount);
+  } else {
+    b = m_lastTime + p_trace->solveSimple(0.0, amount - amount_till_end);
+  }
+  return b;
+}
+
+/**
+ * \brief Auxiliary function to solve integral.
+ *  It returns the date when the requested amount of flops is available
+ * \param trace    Trace structure
+ * \param a        Initial point
+ * \param amount  Amount of flops 
+ * \return The date when amount is available.
+*/
+double CpuTiTrace::solveSimple(double a, double amount)
+{
+  double integral_a;
+  int ind;
+  double time;
+  integral_a = integrateSimplePoint(a);
+  ind = binarySearch(p_integral, integral_a + amount, 0, m_nbPoints - 1);
+  time = p_timePoints[ind];
+  time +=
+      (integral_a + amount -
+       p_integral[ind]) / ((p_integral[ind + 1] -
+                                 p_integral[ind]) /
+                                (p_timePoints[ind + 1] -
+                                 p_timePoints[ind]));
+
+  return time;
+}
+
+/**
+* \brief Auxiliary function to update the CPU power scale.
+*
+*  This function uses the trace structure to return the power scale at the determined time a.
+* \param trace    Trace structure to search the updated power scale
+* \param a        Time
+* \return CPU power scale
+*/
+double CpuTiTgmr::getPowerScale(double a)
+{
+  double reduced_a;
+  int point;
+  s_tmgr_event_t val;
+
+  reduced_a = a - floor(a / m_lastTime) * m_lastTime;
+  point = p_trace->binarySearch(p_trace->p_timePoints, reduced_a, 0,
+                                p_trace->m_nbPoints - 1);
+  xbt_dynar_get_cpy(p_powerTrace->s_list.event_list, point, &val);
+  return val.value;
+}
+
+/**
+* \brief Creates a new integration trace from a tmgr_trace_t
+*
+* \param  power_trace    CPU availability trace
+* \param  value          Percentage of CPU power available (useful to fixed tracing)
+* \param  spacing        Initial spacing
+* \return  Integration trace structure
+*/
+CpuTiTgmr::CpuTiTgmr(tmgr_trace_t power_trace, double value)
+{
+  double total_time = 0.0;
+  s_tmgr_event_t val;
+  unsigned int cpt;
+  p_trace = 0;
+
+/* no availability file, fixed trace */
+  if (!power_trace) {
+    m_type = TRACE_FIXED;
+    m_value = value;
+    XBT_DEBUG("No availability trace. Constant value = %lf", value);
+    return;
+  }
+
+  /* only one point available, fixed trace */
+  if (xbt_dynar_length(power_trace->s_list.event_list) == 1) {
+    xbt_dynar_get_cpy(power_trace->s_list.event_list, 0, &val);
+    m_type = TRACE_FIXED;
+    m_value = val.value;
+    return;
+  }
+
+  m_type = TRACE_DYNAMIC;
+  p_powerTrace = power_trace;
+
+  /* count the total time of trace file */
+  xbt_dynar_foreach(power_trace->s_list.event_list, cpt, val) {
+    total_time += val.delta;
+  }
+  p_trace = new CpuTiTrace(power_trace);
+  m_lastTime = total_time;
+  m_total = p_trace->integrateSimple(0, total_time);
+
+  XBT_DEBUG("Total integral %lf, last_time %lf ",
+            m_total, m_lastTime);
+}
+
+/**
+ * \brief Binary search in array.
+ *  It returns the first point of the interval in which "a" is. 
+ * \param array    Array
+ * \param a        Value to search
+ * \param low     Low bound to search in array
+ * \param high    Upper bound to search in array
+ * \return Index of point
+*/
+int CpuTiTrace::binarySearch(double *array, double a, int low, int high)
+{
+  xbt_assert(low < high, "Wrong parameters: low (%d) should be smaller than"
+      " high (%d)", low, high);
+
+  int mid;
+  do {
+    mid = low + (high - low) / 2;
+    XBT_DEBUG("a %f low %d high %d mid %d value %f", a, low, high, mid,
+        array[mid]);
+
+    if (array[mid] > a)
+      high = mid;
+    else
+      low = mid;
+  }
+  while (low < high - 1);
+
+  return low;
+}
+
+/*************
+ * CallBacks *
+ *************/
+
+static void parse_cpu_ti_init(sg_platf_host_cbarg_t host){
+  ((CpuTiModelPtr)surf_cpu_model_pm)->parseInit(host);
+}
+
+static void add_traces_cpu_ti(){
+  surf_cpu_model_pm->addTraces();
+}
+
+static void cpu_ti_define_callbacks()
+{
+  sg_platf_host_add_cb(parse_cpu_ti_init);
+  sg_platf_postparse_add_cb(add_traces_cpu_ti);
+}
+
+/*********
+ * Model *
+ *********/
+
+void surf_cpu_model_init_ti()
+{
+  xbt_assert(!surf_cpu_model_pm,"CPU model already initialized. This should not happen.");
+  surf_cpu_model_pm = new CpuTiModel();
+  cpu_ti_define_callbacks();
+  ModelPtr model = static_cast<ModelPtr>(surf_cpu_model_pm);
+  xbt_dynar_push(model_list, &model);
+}
+
+CpuTiModel::CpuTiModel() : CpuModel("cpu_ti")
+{
+  xbt_assert(!surf_cpu_model_pm,"CPU model already initialized. This should not happen.");
+  ActionPtr action;
+  CpuTi cpu;
+
+  cpu_ti_running_action_set_that_does_not_need_being_checked =
+      xbt_swag_new(xbt_swag_offset(*action, p_stateHookup));
+
+  cpu_ti_modified_cpu =
+      xbt_swag_new(xbt_swag_offset(cpu, p_modifiedCpuHookup));
+
+  cpu_ti_action_heap = xbt_heap_new(8, NULL);
+  xbt_heap_set_update_callback(cpu_ti_action_heap,
+                               cpu_ti_action_update_index_heap);
+}
+
+CpuTiModel::~CpuTiModel()
+{
+  void **cpu;
+  xbt_lib_cursor_t cursor;
+  char *key;
+
+  xbt_lib_foreach(host_lib, cursor, key, cpu){
+    if(cpu[SURF_CPU_LEVEL])
+    {
+        CpuTiPtr CPU = dynamic_cast<CpuTiPtr>(static_cast<ResourcePtr>(cpu[SURF_CPU_LEVEL]));
+        xbt_swag_free(CPU->p_actionSet);
+        delete CPU->p_availTrace;
+    }
+  }
+
+  surf_cpu_model_pm = NULL;
+
+  xbt_swag_free
+      (cpu_ti_running_action_set_that_does_not_need_being_checked);
+  xbt_swag_free(cpu_ti_modified_cpu);
+  cpu_ti_running_action_set_that_does_not_need_being_checked = NULL;
+  xbt_heap_free(cpu_ti_action_heap);
+}
+
+void CpuTiModel::parseInit(sg_platf_host_cbarg_t host)
+{
+  createResource(host->id,
+        host->power_peak,
+        host->pstate,
+        host->power_scale,
+        host->power_trace,
+        host->core_amount,
+        host->initial_state,
+        host->state_trace,
+        host->properties);
+}
+
+CpuTiPtr CpuTiModel::createResource(const char *name,
+                              xbt_dynar_t powerPeak,
+                              int pstate,
+                           double powerScale,
+                           tmgr_trace_t powerTrace,
+                           int core,
+                           e_surf_resource_state_t stateInitial,
+                           tmgr_trace_t stateTrace,
+                           xbt_dict_t cpuProperties)
+{
+  tmgr_trace_t empty_trace;
+  s_tmgr_event_t val;
+  CpuTiActionPtr cpuAction;
+  xbt_assert(core==1,"Multi-core not handled with this model yet");
+  xbt_assert(!surf_cpu_resource_priv(surf_cpu_resource_by_name(name)),
+              "Host '%s' declared several times in the platform file",
+              name);
+  CpuTiPtr cpu = new CpuTi(this, name, powerPeak, pstate, powerScale, powerTrace,
+                          core, stateInitial, stateTrace, cpuProperties);
+  xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, static_cast<ResourcePtr>(cpu));
+  return (CpuTiPtr) xbt_lib_get_elm_or_null(host_lib, name);
+}
+
+CpuTiActionPtr CpuTiModel::createAction(double cost, bool failed)
+{
+  return NULL;//new CpuTiAction(this, cost, failed);
+}
+
+double CpuTiModel::shareResources(double now)
+{
+  void *_cpu, *_cpu_next;
+  double min_action_duration = -1;
+
+/* iterates over modified cpus to update share resources */
+  xbt_swag_foreach_safe(_cpu, _cpu_next, cpu_ti_modified_cpu) {
+    static_cast<CpuTiPtr>(_cpu)->updateActionFinishDate(now);
+  }
+/* get the min next event if heap not empty */
+  if (xbt_heap_size(cpu_ti_action_heap) > 0)
+    min_action_duration = xbt_heap_maxkey(cpu_ti_action_heap) - now;
+
+  XBT_DEBUG("Share resources, min next event date: %f", min_action_duration);
+
+  return min_action_duration;
+}
+
+void CpuTiModel::updateActionsState(double now, double delta)
+{
+  while ((xbt_heap_size(cpu_ti_action_heap) > 0)
+         && (xbt_heap_maxkey(cpu_ti_action_heap) <= now)) {
+    CpuTiActionPtr action = (CpuTiActionPtr) xbt_heap_pop(cpu_ti_action_heap);
+    XBT_DEBUG("Action %p: finish", action);
+    action->m_finish = surf_get_clock();
+    /* set the remains to 0 due to precision problems when updating the remaining amount */
+    action->m_remains = 0;
+    action->setState(SURF_ACTION_DONE);
+    /* update remaining amount of all actions */
+    action->p_cpu->updateRemainingAmount(surf_get_clock());
+  }
+}
+
+void CpuTiModel::addTraces()
+{
+  xbt_dict_cursor_t cursor = NULL;
+  char *trace_name, *elm;
+
+  static int called = 0;
+
+  if (called)
+    return;
+  called = 1;
+
+/* connect all traces relative to hosts */
+  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);
+    CpuTiPtr cpu = static_cast<CpuTiPtr>(surf_cpu_resource_priv(surf_cpu_resource_by_name(elm)));
+
+    xbt_assert(cpu, "Host %s undefined", elm);
+    xbt_assert(trace, "Trace %s undefined", trace_name);
+
+    if (cpu->p_stateEvent) {
+      XBT_DEBUG("Trace already configured for this CPU(%s), ignoring it",
+             elm);
+      continue;
+    }
+    XBT_DEBUG("Add state trace: %s to CPU(%s)", trace_name, elm);
+    cpu->p_stateEvent = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(cpu));
+  }
+
+  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);
+    CpuTiPtr cpu = dynamic_cast<CpuTiPtr>(static_cast<ResourcePtr>(surf_cpu_resource_priv(surf_cpu_resource_by_name(elm))));
+
+    xbt_assert(cpu, "Host %s undefined", elm);
+    xbt_assert(trace, "Trace %s undefined", trace_name);
+
+    XBT_DEBUG("Add power trace: %s to CPU(%s)", trace_name, elm);
+    if (cpu->p_availTrace)
+      delete cpu->p_availTrace;
+
+    cpu->p_availTrace = new CpuTiTgmr(trace, cpu->m_powerScale);
+
+    /* add a fake trace event if periodicity == 0 */
+    if (trace && xbt_dynar_length(trace->s_list.event_list) > 1) {
+      s_tmgr_event_t val;
+      xbt_dynar_get_cpy(trace->s_list.event_list,
+                        xbt_dynar_length(trace->s_list.event_list) - 1, &val);
+      if (val.delta == 0) {
+        tmgr_trace_t empty_trace;
+        empty_trace = tmgr_empty_trace_new();
+        cpu->p_powerEvent =
+            tmgr_history_add_trace(history, empty_trace,
+                                   cpu->p_availTrace->m_lastTime, 0, static_cast<ResourcePtr>(cpu));
+      }
+    }
+  }
+}
+
+/************
+ * Resource *
+ ************/
+CpuTi::CpuTi(CpuTiModelPtr model, const char *name, xbt_dynar_t powerPeak,
+        int pstate, double powerScale, tmgr_trace_t powerTrace, int core,
+        e_surf_resource_state_t stateInitial, tmgr_trace_t stateTrace,
+       xbt_dict_t properties) :
+       Resource(model, name, properties), Cpu(model, name, properties) {
+  p_stateCurrent = stateInitial;
+  m_powerScale = powerScale;
+  m_core = core;
+  tmgr_trace_t empty_trace;            
+  s_tmgr_event_t val;          
+  xbt_assert(core==1,"Multi-core not handled with this model yet");
+  XBT_DEBUG("power scale %lf", powerScale);
+  p_availTrace = new CpuTiTgmr(powerTrace, powerScale);
+
+  CpuTiActionPtr action;
+  p_actionSet = xbt_swag_new(xbt_swag_offset(*action, p_cpuListHookup));
+
+  xbt_dynar_get_cpy(powerPeak, 0, &m_powerPeak);
+  xbt_dynar_free(&powerPeak);  /* kill memory leak */
+  m_pstate = pstate;
+  XBT_DEBUG("CPU create: peak=%f, pstate=%d", m_powerPeak, m_pstate);
+
+  p_modifiedCpuHookup.prev = 0;
+  p_modifiedCpuHookup.next = 0;
+
+  if (stateTrace)
+    p_stateEvent = tmgr_history_add_trace(history, stateTrace, 0.0, 0, static_cast<ResourcePtr>(this));
+  if (powerTrace && xbt_dynar_length(powerTrace->s_list.event_list) > 1) {
+    // add a fake trace event if periodicity == 0 
+    xbt_dynar_get_cpy(powerTrace->s_list.event_list,
+                      xbt_dynar_length(powerTrace->s_list.event_list) - 1, &val);
+    if (val.delta == 0) {
+      empty_trace = tmgr_empty_trace_new();
+      p_powerEvent =
+        tmgr_history_add_trace(history, empty_trace,
+                               p_availTrace->m_lastTime, 0, static_cast<ResourcePtr>(this));
+    }
+  }
+};
+
+void CpuTi::updateState(tmgr_trace_event_t event_type,
+                        double value, double date)
+{
+  void *_action;
+  CpuTiActionPtr action;
+
+  if (event_type == p_powerEvent) {
+    tmgr_trace_t power_trace;
+    CpuTiTgmrPtr trace;
+    s_tmgr_event_t val;
+
+    XBT_DEBUG("Finish trace date: %f value %lf date %f", surf_get_clock(),
+           value, date);
+    /* update remaining of actions and put in modified cpu swag */
+    updateRemainingAmount(date);
+    xbt_swag_insert(this, cpu_ti_modified_cpu);
+
+    power_trace = p_availTrace->p_powerTrace;
+    xbt_dynar_get_cpy(power_trace->s_list.event_list,
+                      xbt_dynar_length(power_trace->s_list.event_list) - 1, &val);
+    /* free old trace */
+    delete p_availTrace;
+    m_powerScale = val.value;
+
+    trace = new CpuTiTgmr(TRACE_FIXED, val.value);
+    XBT_DEBUG("value %f", val.value);
+
+    p_availTrace = trace;
+
+    if (tmgr_trace_event_free(event_type))
+      p_powerEvent = NULL;
+
+  } else if (event_type == p_stateEvent) {
+    if (value > 0) {
+      if(p_stateCurrent == SURF_RESOURCE_OFF)
+        xbt_dynar_push_as(host_that_restart, char*, (char *)m_name);
+      p_stateCurrent = SURF_RESOURCE_ON;
+    } else {
+      p_stateCurrent = SURF_RESOURCE_OFF;
+
+      /* put all action running on cpu to failed */
+      xbt_swag_foreach(_action, p_actionSet) {
+       action = static_cast<CpuTiActionPtr>(_action);
+        if (action->getState() == SURF_ACTION_RUNNING
+         || action->getState() == SURF_ACTION_READY
+         || action->getState() == SURF_ACTION_NOT_IN_THE_SYSTEM) {
+          action->m_finish = date;
+          action->setState(SURF_ACTION_FAILED);
+          if (action->m_indexHeap >= 0) {
+            CpuTiActionPtr heap_act = (CpuTiActionPtr)
+                xbt_heap_remove(cpu_ti_action_heap, action->m_indexHeap);
+            if (heap_act != action)
+              DIE_IMPOSSIBLE;
+          }
+        }
+      }
+    }
+    if (tmgr_trace_event_free(event_type))
+      p_stateEvent = NULL;
+  } else {
+    XBT_CRITICAL("Unknown event ! \n");
+    xbt_abort();
+  }
+
+  return;
+}
+
+void CpuTi::updateActionFinishDate(double now)
+{
+  void *_action;
+  CpuTiActionPtr action;
+  double sum_priority = 0.0, total_area, min_finish = -1;
+
+/* update remaning amount of actions */
+updateRemainingAmount(now);
+
+  xbt_swag_foreach(_action, p_actionSet) {
+    action = static_cast<CpuTiActionPtr>(_action);
+    /* action not running, skip it */
+    if (action->p_stateSet !=
+        surf_cpu_model_pm->p_runningActionSet)
+      continue;
+
+    /* bogus priority, skip it */
+    if (action->m_priority <= 0)
+      continue;
+
+    /* action suspended, skip it */
+    if (action->m_suspended != 0)
+      continue;
+
+    sum_priority += 1.0 / action->m_priority;
+  }
+  m_sumPriority = sum_priority;
+
+  xbt_swag_foreach(_action, p_actionSet) {
+    action = static_cast<CpuTiActionPtr>(_action);
+    min_finish = -1;
+    /* action not running, skip it */
+    if (action->p_stateSet !=
+        surf_cpu_model_pm->p_runningActionSet)
+      continue;
+
+    /* verify if the action is really running on cpu */
+    if (action->m_suspended == 0 && action->m_priority > 0) {
+      /* total area needed to finish the action. Used in trace integration */
+      total_area =
+          (action->m_remains) * sum_priority *
+           action->m_priority;
+
+      total_area /= m_powerPeak;
+
+      action->m_finish = p_availTrace->solve(now, total_area);
+      /* verify which event will happen before (max_duration or finish time) */
+      if (action->m_maxDuration != NO_MAX_DURATION &&
+          action->m_start + action->m_maxDuration < action->m_finish)
+        min_finish = action->m_start + action->m_maxDuration;
+      else
+        min_finish = action->m_finish;
+    } else {
+      /* put the max duration time on heap */
+      if (action->m_maxDuration != NO_MAX_DURATION)
+        min_finish = action->m_start + action->m_maxDuration;
+    }
+    /* add in action heap */
+    XBT_DEBUG("action(%p) index %d", action, action->m_indexHeap);
+    if (action->m_indexHeap >= 0) {
+      CpuTiActionPtr heap_act = (CpuTiActionPtr)
+          xbt_heap_remove(cpu_ti_action_heap, action->m_indexHeap);
+      if (heap_act != action)
+        DIE_IMPOSSIBLE;
+    }
+    if (min_finish != NO_MAX_DURATION)
+      xbt_heap_push(cpu_ti_action_heap, action, min_finish);
+
+    XBT_DEBUG
+        ("Update finish time: Cpu(%s) Action: %p, Start Time: %f Finish Time: %f Max duration %f",
+         m_name, action, action->m_start,
+         action->m_finish,
+         action->m_maxDuration);
+  }
+/* remove from modified cpu */
+  xbt_swag_remove(this, cpu_ti_modified_cpu);
+}
+
+bool CpuTi::isUsed()
+{
+  return xbt_swag_size(p_actionSet);
+}
+
+
+
+double CpuTi::getAvailableSpeed()
+{
+  m_powerScale = p_availTrace->getPowerScale(surf_get_clock());
+  return Cpu::getAvailableSpeed();
+}
+
+/**
+* \brief Update the remaining amount of actions
+*
+* \param  now    Current time
+*/
+void CpuTi::updateRemainingAmount(double now)
+{
+  double area_total;
+  void* _action;
+  CpuTiActionPtr action;
+
+  /* already updated */
+  if (m_lastUpdate >= now)
+    return;
+
+/* calcule the surface */
+  area_total = p_availTrace->integrate(m_lastUpdate, now) * m_powerPeak;
+  XBT_DEBUG("Flops total: %f, Last update %f", area_total,
+         m_lastUpdate);
+
+  xbt_swag_foreach(_action, p_actionSet) {
+    action = static_cast<CpuTiActionPtr>(_action);
+    /* action not running, skip it */
+    if (action->p_stateSet !=
+        getModel()->p_runningActionSet)
+      continue;
+
+    /* bogus priority, skip it */
+    if (action->m_priority <= 0)
+      continue;
+
+    /* action suspended, skip it */
+    if (action->m_suspended != 0)
+      continue;
+
+    /* action don't need update */
+    if (action->m_start >= now)
+      continue;
+
+    /* skip action that are finishing now */
+    if (action->m_finish >= 0
+        && action->m_finish <= now)
+      continue;
+
+    /* update remaining */
+    double_update(&(action->m_remains),
+                  area_total / (m_sumPriority *
+                                action->m_priority));
+    XBT_DEBUG("Update remaining action(%p) remaining %f", action,
+           action->m_remains);
+  }
+  m_lastUpdate = 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(static_cast<CpuTiModelPtr>(p_model), size, p_stateCurrent != SURF_RESOURCE_ON);
+
+  action->p_cpu = this;
+  action->m_indexHeap = -1;
+
+  xbt_swag_insert(this, cpu_ti_modified_cpu);
+
+  xbt_swag_insert(action, p_actionSet);
+
+  action->m_suspended = 0;        /* Should be useless because of the
+              »                     calloc but it seems to help valgrind... */
+
+  XBT_OUT();
+  return action;
+}
+
+
+CpuActionPtr CpuTi::sleep(double duration)
+{
+  if (duration > 0)
+    duration = MAX(duration, MAXMIN_PRECISION);
+
+  XBT_IN("(%s,%g)", m_name, duration);
+  CpuTiActionPtr action = _execute(1.0);
+  action->m_maxDuration = duration;
+  action->m_suspended = 2;
+  if (duration == NO_MAX_DURATION) {
+    /* Move to the *end* of the corresponding action set. This convention
+       is used to speed up update_resource_state  */
+    xbt_swag_remove(static_cast<ActionPtr>(action), action->p_stateSet);
+    action->p_stateSet = cpu_ti_running_action_set_that_does_not_need_being_checked;
+    xbt_swag_insert(static_cast<ActionPtr>(action), action->p_stateSet);
+  }
+  XBT_OUT();
+  return action;
+}
+
+void CpuTi::printCpuTiModel()
+{
+  std::cout << getModel()->getName() << "<<plop"<< std::endl;
+};
+
+/**********
+ * Action *
+ **********/
+static void cpu_ti_action_update_index_heap(void *action, int i)
+{
+  ((CpuTiActionPtr)action)->updateIndexHeap(i); 
+}
+void CpuTiAction::updateIndexHeap(int i)
+{
+  m_indexHeap = i;
+}
+
+void CpuTiAction::setState(e_surf_action_state_t state)
+{
+  Action::setState(state);
+  xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
+}
+
+int CpuTiAction::unref()
+{
+  m_refcount--;
+  if (!m_refcount) {
+    xbt_swag_remove(static_cast<ActionPtr>(this), p_stateSet);
+    /* remove from action_set */
+    xbt_swag_remove(this, p_cpu->p_actionSet);
+    /* remove from heap */
+    xbt_heap_remove(cpu_ti_action_heap, this->m_indexHeap);
+    xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
+    delete this;
+    return 1;
+  }
+  return 0;
+}
+
+void CpuTiAction::cancel()
+{
+  this->setState(SURF_ACTION_FAILED);
+  xbt_heap_remove(cpu_ti_action_heap, this->m_indexHeap);
+  xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
+  return;
+}
+
+void CpuTiAction::recycle()
+{
+  DIE_IMPOSSIBLE;
+}
+
+void CpuTiAction::suspend()
+{
+  XBT_IN("(%p)", this);
+  if (m_suspended != 2) {
+    m_suspended = 1;
+    xbt_heap_remove(cpu_ti_action_heap, m_indexHeap);
+    xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
+  }
+  XBT_OUT();
+}
+
+void CpuTiAction::resume()
+{
+  XBT_IN("(%p)", this);
+  if (m_suspended != 2) {
+    m_suspended = 0;
+    xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
+  }
+  XBT_OUT();
+}
+
+bool CpuTiAction::isSuspended()
+{
+  return m_suspended == 1;
+}
+
+void CpuTiAction::setMaxDuration(double duration)
+{
+  double min_finish;
+
+  XBT_IN("(%p,%g)", this, duration);
+
+  m_maxDuration = duration;
+
+  if (duration >= 0)
+    min_finish = (m_start + m_maxDuration) < m_finish ?
+                 (m_start + m_maxDuration) : m_finish;
+  else
+    min_finish = m_finish;
+
+/* add in action heap */
+  if (m_indexHeap >= 0) {
+    CpuTiActionPtr heap_act = (CpuTiActionPtr)
+        xbt_heap_remove(cpu_ti_action_heap, m_indexHeap);
+    if (heap_act != this)
+      DIE_IMPOSSIBLE;
+  }
+  xbt_heap_push(cpu_ti_action_heap, this, min_finish);
+
+  XBT_OUT();
+}
+
+void CpuTiAction::setPriority(double priority)
+{
+  XBT_IN("(%p,%g)", this, priority);
+  m_priority = priority;
+  xbt_swag_insert(p_cpu, cpu_ti_modified_cpu);
+  XBT_OUT();
+}
+
+double CpuTiAction::getRemains()
+{
+  XBT_IN("(%p)", this);
+  p_cpu->updateRemainingAmount(surf_get_clock());
+  XBT_OUT();
+  return m_remains;
+}
+
+static void check() {
+  CpuTiActionPtr cupAction = new CpuTiAction(NULL, 0, true);
+}
+
+#endif /* SURF_MODEL_CPUTI_H_ */
+
diff --git a/src/surf/cpu_ti.hpp b/src/surf/cpu_ti.hpp
new file mode 100644 (file)
index 0000000..cccac33
--- /dev/null
@@ -0,0 +1,178 @@
+#include "cpu.hpp"
+#include "trace_mgr_private.h"
+#include "surf/surf_routing.h"
+
+/* Epsilon */
+#define EPSILON 0.000000001
+
+/***********
+ * Classes *
+ ***********/
+class CpuTiTrace;
+typedef CpuTiTrace *CpuTiTracePtr;
+
+class CpuTiTgmr;
+typedef CpuTiTgmr *CpuTiTgmrPtr;
+
+class CpuTiModel;
+typedef CpuTiModel *CpuTiModelPtr;
+
+class CpuTi;
+typedef CpuTi *CpuTiPtr;
+
+class CpuTiAction;
+typedef CpuTiAction *CpuTiActionPtr;
+
+/*********
+ * Trace *
+ *********/
+class CpuTiTrace {
+public:
+  CpuTiTrace(tmgr_trace_t powerTrace);
+  ~CpuTiTrace();
+
+  double integrateSimple(double a, double b);
+  double integrateSimplePoint(double a);
+  double solveSimple(double a, double amount);
+
+  double *p_timePoints;
+  double *p_integral;
+  int m_nbPoints;
+  int binarySearch(double *array, double a, int low, int high);
+
+private:
+};
+
+enum trace_type {
+  
+  TRACE_FIXED,                /*< Trace fixed, no availability file */
+  TRACE_DYNAMIC               /*< Dynamic, availability file disponible */
+};
+
+class CpuTiTgmr {
+public:
+  CpuTiTgmr(trace_type type, double value): m_type(type), m_value(value){};
+  CpuTiTgmr(tmgr_trace_t power_trace, double value);
+  ~CpuTiTgmr();
+
+  double integrate(double a, double b);
+  double solve(double a, double amount);
+  double solveSomewhatSimple(double a, double amount);
+  double getPowerScale(double a);
+
+  trace_type m_type;
+  double m_value;                 /*< Percentage of cpu power disponible. Value fixed between 0 and 1 */
+
+  /* Dynamic */
+  double m_lastTime;             /*< Integral interval last point (discret time) */
+  double m_total;                 /*< Integral total between 0 and last_pointn */
+
+  CpuTiTracePtr p_trace;
+  tmgr_trace_t p_powerTrace;
+};
+
+
+/*********
+ * Model *
+ *********/
+class CpuTiModel : public CpuModel {
+public:
+  CpuTiModel();
+  ~CpuTiModel();
+
+  void parseInit(sg_platf_host_cbarg_t host);
+  CpuTiPtr createResource(const char *name,  xbt_dynar_t powerPeak,
+                          int pstate, double power_scale,
+                          tmgr_trace_t power_trace, int core,
+                          e_surf_resource_state_t state_initial,
+                          tmgr_trace_t state_trace,
+                          xbt_dict_t cpu_properties);
+  CpuTiActionPtr createAction(double cost, bool failed);
+  double shareResources(double now);
+  void updateActionsState(double now, double delta);
+  void addTraces();
+
+protected:
+  void NotifyResourceTurnedOn(ResourcePtr r){};
+  void NotifyResourceTurnedOff(ResourcePtr r){};
+
+  void NotifyActionCancel(ActionPtr a){};
+  void NotifyActionResume(ActionPtr a){};
+  void NotifyActionSuspend(ActionPtr a){};
+};
+
+/************
+ * Resource *
+ ************/
+class CpuTi : public Cpu {
+public:
+  CpuTi() {};
+  CpuTi(CpuTiModelPtr model, const char *name, xbt_dynar_t powerPeak,
+        int pstate, double powerScale, tmgr_trace_t powerTrace, int core,
+        e_surf_resource_state_t stateInitial, tmgr_trace_t stateTrace,
+       xbt_dict_t properties) ;
+  ~CpuTi() {};
+
+  void updateState(tmgr_trace_event_t event_type, double value, double date);  
+  void updateActionFinishDate(double now);
+  bool isUsed();
+  void printCpuTiModel();
+  CpuActionPtr execute(double size);
+  CpuTiActionPtr _execute(double size);
+  CpuActionPtr sleep(double duration);
+  double getAvailableSpeed();
+
+  xbt_dynar_t getWattsRangeList() {};
+  double getCurrentWattsValue(double cpu_load) {};
+  void updateEnergy(double cpu_load) {};
+
+  double getCurrentPowerPeak() {};
+  double getPowerPeakAt(int pstate_index) {};
+  int getNbPstates() {};
+  void setPowerPeakAt(int pstate_index) {};
+  double getConsumedEnergy() {};
+
+  CpuTiTgmrPtr p_availTrace;       /*< Structure with data needed to integrate trace file */
+  tmgr_trace_event_t p_stateEvent;       /*< trace file with states events (ON or OFF) */
+  tmgr_trace_event_t p_powerEvent;       /*< trace file with availability events */
+  xbt_swag_t p_actionSet;        /*< set with all actions running on cpu */
+  s_xbt_swag_hookup_t p_modifiedCpuHookup;      /*< hookup to swag that indicates whether share resources must be recalculated or not */
+  double m_sumPriority;          /*< the sum of actions' priority that are running on cpu */
+  double m_lastUpdate;           /*< last update of actions' remaining amount done */
+
+  int m_pstate;                                                                /*< Current pstate (index in the power_peak_list)*/
+  double current_frequency;
+
+  void updateRemainingAmount(double now);
+};
+
+/**********
+ * Action *
+ **********/
+
+class CpuTiAction: public CpuAction {
+public:
+  CpuTiAction() {};
+  CpuTiAction(CpuTiModelPtr model, double cost, bool failed)
+  : Action(model, cost, failed), CpuAction(model, cost, failed) {
+       p_cpuListHookup.next = 0;
+       p_cpuListHookup.prev = 0;
+  };
+
+  void setState(e_surf_action_state_t state);
+  int unref();
+  void cancel();
+  void recycle();
+  void updateIndexHeap(int i);
+  void suspend();
+  void resume();
+  bool isSuspended();
+  void setMaxDuration(double duration);
+  void setPriority(double priority);
+  double getRemains();
+  CpuTiPtr p_cpu;
+  int m_indexHeap;
+  s_xbt_swag_hookup_t p_cpuListHookup;
+  int m_suspended;
+private:
+};
diff --git a/src/surf/cpu_ti_private.h b/src/surf/cpu_ti_private.h
deleted file mode 100644 (file)
index ba570d9..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-
-/* Copyright (c) 2009-2010, 2013. 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_CPU_TI_PRIVATE_H
-#define _SURF_CPU_TI_PRIVATE_H
-
-typedef struct surf_cpu_ti_trace {
-  double *time_points;
-  double *integral;
-  int nb_points;
-} s_surf_cpu_ti_trace_t, *surf_cpu_ti_trace_t;
-
-/* TRACE */
-typedef struct surf_cpu_ti_tgmr {
-  enum trace_type {
-    TRACE_FIXED,                /*< Trace fixed, no availability file */
-    TRACE_DYNAMIC               /*< Dynamic, availability file disponible */
-  } type;
-
-  double value;                 /*< Percentage of cpu power disponible. Value fixed between 0 and 1 */
-
-  /* Dynamic */
-  double last_time;             /*< Integral interval last point (discret time) */
-  double total;                 /*< Integral total between 0 and last_pointn */
-
-  surf_cpu_ti_trace_t trace;
-  tmgr_trace_t power_trace;
-
-} s_surf_cpu_ti_tgmr_t, *surf_cpu_ti_tgmr_t;
-
-
-/* CPU with trace integration feature */
-typedef struct cpu_ti {
-  s_surf_resource_t generic_resource;   /*< Structure with generic data. Needed at begin to interate with SURF */
-  double power_peak;            /*< CPU power peak */
-  int pstate;
-  double power_scale;           /*< Percentage of CPU disponible */
-  surf_cpu_ti_tgmr_t avail_trace;       /*< Structure with data needed to integrate trace file */
-  e_surf_resource_state_t state_current;        /*< CPU current state (ON or OFF) */
-  tmgr_trace_event_t state_event;       /*< trace file with states events (ON or OFF) */
-  tmgr_trace_event_t power_event;       /*< trace file with availability events */
-  xbt_swag_t action_set;        /*< set with all actions running on cpu */
-  s_xbt_swag_hookup_t modified_cpu_hookup;      /*< hookup to swag that indicacates whether share resources must be recalculated or not */
-  double sum_priority;          /*< the sum of actions' priority that are running on cpu */
-  double last_update;           /*< last update of actions' remaining amount done */
-  double current_frequency;
-} s_cpu_ti_t, *cpu_ti_t;
-
-typedef struct surf_action_ti {
-  s_surf_action_t generic_action;
-  s_xbt_swag_hookup_t cpu_list_hookup;
-  void *cpu;
-  int suspended;
-  int index_heap;
-} s_surf_action_cpu_ti_t, *surf_action_cpu_ti_t;
-
-/* Epsilon */
-#define EPSILON 0.000000001
-/* Usefull define to get the cpu where action is running on */
-#define ACTION_GET_CPU(action) ((cpu_ti_t)((surf_action_cpu_ti_t)action)->cpu)
-
-
-#endif                          /* _SURF_CPU_TI_PRIVATE_H */
diff --git a/src/surf/fair_bottleneck.cpp b/src/surf/fair_bottleneck.cpp
new file mode 100644 (file)
index 0000000..b4a0994
--- /dev/null
@@ -0,0 +1,192 @@
+/* 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 "solver.hpp"
+#include <stdlib.h>
+#include <math.h>
+
+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_next = NULL;
+  lmm_constraint_t cnst = NULL;
+  //s_lmm_constraint_t s_cnst;
+  lmm_constraint_t cnst_next = NULL;
+  xbt_swag_t cnst_list = NULL;
+  
+  xbt_swag_t elem_list = NULL;
+  int i;
+
+  static s_xbt_swag_t cnst_to_update;
+  vector<ConstraintPtr> cnstToUpdate;
+
+  if (!(lmm_system_modified(sys)))
+    return;
+
+  /* Init */
+
+  lmm_variable_t var = NULL;
+  lmm_element_t elem = NULL;  
+  std::vector<VariablePtr> *varList; 
+  std::vector<VariablePtr>::iterator varIt;
+  std::vector<ElementPtr> *elemList;  
+  std::vector<ElementPtr>::iterator elemIt;
+  std::vector<ConstraintPtr> *cnstList;
+  std::vector<ConstraintPtr>::iterator cnstIt;
+
+  varList = &(sys->m_variableSet);  
+  XBT_DEBUG("Variable set : %d", varList->size());
+  for (varIt=varList->begin(); varIt!=varList->end(); ++varIt) {
+    int nb = 0;
+    var = *varIt;
+    var->m_value = 0.0;
+    XBT_DEBUG("Handling variable %p", var);
+    sys->m_saturatedVariableSet.push_back(var);
+    for (elemIt=var->m_cnsts.begin(); elemIt!=var->m_cnsts.end(); ++elemIt) 
+      if ((*elemIt)->m_value == 0.0)
+       nb++; 
+    if ((nb == var->getNumberOfCnst()) && (var->m_weight > 0.0)) {
+      XBT_DEBUG("Err, finally, there is no need to take care of variable %p",
+               var);
+      sys->m_saturatedVariableSet.erase(std::find(sys->m_saturatedVariableSet.begin(), sys->m_saturatedVariableSet.end(), var));
+      var->m_value = 1.0;
+    }
+    if (var->m_weight <= 0.0) {
+      XBT_DEBUG("Err, finally, there is no need to take care of variable %p",
+             var);
+      sys->m_saturatedVariableSet.erase(std::find(sys->m_saturatedVariableSet.begin(), sys->m_saturatedVariableSet.end(), var));      
+    }
+  }
+  varList = &(sys->m_saturatedVariableSet);
+  cnstList = &(sys->m_activeConstraintSet);
+  XBT_DEBUG("Active constraints : %d", cnstList->size());
+  sys->m_saturatedConstraintSet.insert(sys->m_saturatedConstraintSet.end(), cnstList->begin(), cnstList->end());
+  cnstList = &(sys->m_saturatedConstraintSet);
+  for(cnstIt=cnstList->begin(); cnstIt!=cnstList->end(); ++cnstIt) {
+    (*cnstIt)->m_remaining = (*cnstIt)->m_bound;
+    (*cnstIt)->m_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 *******",
+           cnstList->size());
+    for (cnstIt=cnstList->begin(); cnstIt!=cnstList->end();){
+      cnst = *cnstIt;
+      int nb = 0;
+      XBT_DEBUG("Processing cnst %p ", cnst);
+      elemList = &(cnst->m_elementSet);
+      cnst->m_usage = 0.0;
+      for(elemIt=elemList->begin(); elemIt!=elemList->end(); elemIt++) {
+        if (elem->p_variable->m_weight <= 0)
+          break;
+        if ((elem->m_value > 0)
+            && std::find(varList->begin(), varList->end(), elem->p_variable)!=varList->end());
+          nb++;
+      }
+      XBT_DEBUG("\tThere are %d variables", nb);
+      if (nb > 0 && !cnst->m_shared)
+        nb = 1;
+      if (!nb) {
+        cnst->m_remaining = 0.0;
+        cnst->m_usage = cnst->m_remaining;
+        cnstList->erase(std::find(cnstList->begin(), cnstList->end(), *cnstIt));       
+        continue;
+      }
+      cnst->m_usage = cnst->m_remaining / nb;
+      XBT_DEBUG("\tConstraint Usage %p : %f with %d variables", cnst,
+             cnst->m_usage, nb);
+      ++cnstIt;      
+    }
+
+    for (varIt=varList->begin(); varIt!=varList->end();){
+      var = *varIt;
+      double minInc =
+          var->m_cnsts.front()->p_constraint->m_usage / var->m_cnsts.front()->m_value;
+      for (elemIt=++var->m_cnsts.begin(); elemIt!=var->m_cnsts.end(); ++elemIt) {
+       elem = (*elemIt);
+        minInc = MIN(minInc, elem->p_constraint->m_usage / elem->m_value);
+      }
+      if (var->m_bound > 0)
+        minInc = MIN(minInc, var->m_bound - var->m_value);
+      var->m_mu = minInc;
+      XBT_DEBUG("Updating variable %p maximum increment: %g", var, var->m_mu);
+      var->m_value += var->m_mu;
+      if (var->m_value == var->m_bound) {
+        varList->erase(std::find(varList->begin(), varList->end(), var));      
+      } else 
+       ++varIt;
+    }
+
+    for (cnstIt=cnstList->begin(); cnstIt!=cnstList->end();) {
+      cnst = *cnstIt;
+      XBT_DEBUG("Updating cnst %p ", cnst);
+      elemList = &(cnst->m_elementSet);
+      for (elemIt=elemList->begin(); elemIt!=elemList->end();++elemIt) {
+       elem = *elemIt;
+        if (elem->p_variable->m_weight <= 0)
+          break;
+        if (cnst->m_shared) {
+          XBT_DEBUG("\tUpdate constraint %p (%g) with variable %p by %g",
+                 cnst, cnst->m_remaining, elem->p_variable,
+                 elem->p_variable->m_mu);
+          double_update(&(cnst->m_remaining),
+                        elem->m_value * elem->p_variable->m_mu);
+        } else {
+          XBT_DEBUG
+              ("\tNon-Shared variable. Update constraint usage of %p (%g) with variable %p by %g",
+               cnst, cnst->m_usage, elem->p_variable, elem->p_variable->m_mu);
+          cnst->m_usage = MIN(cnst->m_usage, elem->m_value * elem->p_variable->m_mu);
+        }
+      }
+
+      if (!cnst->m_shared) {
+        XBT_DEBUG("\tUpdate constraint %p (%g) by %g",
+               cnst, cnst->m_remaining, cnst->m_usage);
+
+        double_update(&(cnst->m_remaining), cnst->m_usage);
+      }
+
+      XBT_DEBUG("\tRemaining for %p : %g", cnst, cnst->m_remaining);
+      if (cnst->m_remaining == 0.0) {
+        XBT_DEBUG("\tGet rid of constraint %p", cnst);
+
+        cnstList->erase(std::find(cnstList->begin(), cnstList->end(), cnst));
+
+        for (elemIt=elemList->begin(); elemIt!=elemList->end();++elemIt) {
+          if (elem->p_variable->m_weight <= 0)
+            break;
+          if (elem->m_value > 0) {
+            XBT_DEBUG("\t\tGet rid of variable %p", elem->p_variable);
+            varList->erase(std::find(varList->begin(), varList->end(), elem->p_variable));     
+          }
+        }
+      } else
+       ++cnstIt;
+    }
+  } while (!varList->empty());
+  
+  cnstList->clear();
+  sys->m_modified = 0;
+  if (XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug)) {
+    XBT_DEBUG("Fair bottleneck done");
+    sys->print();
+  }
+}
index e3e652f..35a0118 100644 (file)
@@ -8,7 +8,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");
@@ -130,14 +130,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);
     }
   }
@@ -151,7 +151,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);
     }
@@ -329,7 +329,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;
@@ -449,18 +449,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)
@@ -468,7 +468,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;
index e9570dd..71e63b4 100644 (file)
@@ -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.cpp b/src/surf/lagrange.cpp
new file mode 100644 (file)
index 0000000..1b4cc95
--- /dev/null
@@ -0,0 +1,674 @@
+/* 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 "solver.h"
+#include "solver.hpp"
+#include <stdlib.h>
+#ifndef MATH
+#include <math.h>
+#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(std::vector<ConstraintPtr> *cnstList, std::vector<VariablePtr> *varList,
+                            int warn)
+{
+  std::vector<ElementPtr> *elemList = NULL;
+  lmm_element_t elem = NULL;
+  lmm_constraint_t cnst = NULL;
+  lmm_variable_t var = NULL;
+  std::vector<VariablePtr>::iterator varIt;
+  std::vector<ElementPtr>::iterator elemIt;
+  std::vector<ConstraintPtr>::iterator cnstIt;
+
+  double tmp;
+
+  for (cnstIt=cnstList->begin(); cnstIt!=cnstList->end(); ++cnstIt) {
+    cnst = (*cnstIt);
+    tmp = 0;
+    elemList = &(cnst->m_elementSet);
+    for (elemIt=elemList->begin(); elemIt!=elemList->end(); ++elemIt) {
+      var = (*elemIt)->p_variable;
+      if (var->m_weight <= 0)
+        continue;
+      tmp += var->m_value;
+    }
+
+    if (double_positive(tmp - cnst->m_bound)) {
+      if (warn)
+        XBT_WARN
+            ("The link (%p) is over-used. Expected less than %f and got %f",
+             cnst, cnst->m_bound, tmp);
+      return 0;
+    }
+    XBT_DEBUG
+        ("Checking feasability for constraint (%p): sat = %f, lambda = %f ",
+         cnst, tmp - cnst->m_bound, cnst->m_lambda);
+  }
+
+  for (varIt=varList->begin(); varIt!=varList->end(); ++varIt) {
+    if (!var->m_weight)
+      break;
+    if (var->m_bound < 0)
+      continue;
+    XBT_DEBUG("Checking feasability for variable (%p): sat = %f mu = %f", var,
+           var->m_value - var->m_bound, var->m_mu);
+
+    if (double_positive(var->m_value - var->m_bound)) {
+      if (warn)
+        XBT_WARN
+            ("The variable (%p) is too large. Expected less than %f and got %f",
+             var, var->m_bound, var->m_value);
+      return 0;
+    }
+  }  
+  return 1;
+}
+
+static double new_value(lmm_variable_t var)
+{
+  double tmp = 0;
+  int i;
+  std::vector<ElementPtr>::iterator elemIt;
+
+  for (elemIt=var->m_cnsts.begin(); elemIt!=var->m_cnsts.end(); ++elemIt) {
+    tmp += ((*elemIt)->p_constraint)->m_lambda;
+  }
+  if (var->m_bound > 0)
+    tmp += var->m_mu;
+  XBT_DEBUG("\t Working on var (%p). cost = %e; Weight = %e", var, tmp,
+         var->m_weight);
+  //uses the partial differential inverse function
+  return var->p_funcFPI(var, tmp);
+}
+
+static double new_mu(lmm_variable_t var)
+{
+  double mu_i = 0.0;
+  double sigma_i = 0.0;
+  int j;
+  std::vector<ElementPtr>::iterator elemIt;
+
+  for (elemIt=var->m_cnsts.begin(); elemIt!=var->m_cnsts.end(); ++elemIt) {
+    sigma_i += ((*elemIt)->p_constraint)->m_lambda;
+  }
+  mu_i = var->p_funcFP(var, var->m_bound) - sigma_i;
+  if (mu_i < 0.0)
+    return 0.0;
+  return mu_i;
+}
+
+static double dual_objective(std::vector<VariablePtr> *varList, std::vector<ConstraintPtr> *cnstList)
+{
+  lmm_constraint_t cnst = NULL;
+  lmm_variable_t var = NULL;
+
+  double obj = 0.0;
+  std::vector<VariablePtr>::iterator varIt;
+  std::vector<ElementPtr>::iterator elemIt;
+  std::vector<ConstraintPtr>::iterator cnstIt;
+
+  for (varIt=varList->begin(); varIt!=varList->end(); ++varIt) {
+    var = (*varIt);
+    double sigma_i = 0.0;
+    int j;
+
+    if (!var->m_weight)
+      break;
+
+    for (elemIt=var->m_cnsts.begin(); elemIt!=var->m_cnsts.end(); ++elemIt)
+      sigma_i += ((*elemIt)->p_constraint)->m_lambda;
+       
+    if (var->m_bound > 0)
+      sigma_i += var->m_mu;
+
+    XBT_DEBUG("var %p : sigma_i = %1.20f", var, sigma_i);
+
+    obj += var->p_funcF(var, var->p_funcFPI(var, sigma_i)) -
+        sigma_i * var->p_funcFPI(var, sigma_i);
+
+    if (var->m_bound > 0)
+      obj += var->m_mu * var->m_bound;
+  }
+
+  for (cnstIt=cnstList->begin(); cnstIt!=cnstList->end(); ++cnstIt)
+    obj += (*cnstIt)->m_lambda * (*cnstIt)->m_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.
+   */
+  std::vector<ConstraintPtr> *cnstList = NULL;
+  std::vector<ConstraintPtr>::iterator cnstIt;  
+  lmm_constraint_t cnst = NULL;
+
+  std::vector<VariablePtr> *varList = NULL;
+  std::vector<VariablePtr>::iterator varIt;  
+  lmm_variable_t var = NULL;
+
+  std::vector<ElementPtr>::iterator elemIt;  
+
+  /*
+   * 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->m_modified))
+    return;
+
+  /* 
+   * Initialize lambda.
+   */
+  cnstList = &(sys->m_activeConstraintSet);
+  for (cnstIt=cnstList->begin(); cnstIt!=cnstList->end(); ++cnstIt) {
+    cnst = *cnstIt;
+    cnst->m_lambda = 1.0;
+    cnst->m_newLambda = 2.0;
+    XBT_DEBUG("#### cnst(%p)->lambda :  %e", cnst, cnst->m_lambda);
+  }
+
+  /* 
+   * Initialize the var list variable with only the active variables. 
+   * Associate an index in the swag variables. Initialize mu.
+   */
+  varList = &(sys->m_variableSet);
+  i = 0;
+  for (varIt=varList->begin(); varIt!=varList->end(); ++varIt) {
+    var = *varIt;
+    if (!var->m_weight)
+      var->m_value = 0.0;
+    else {
+      int nb = 0;
+      if (var->m_bound < 0.0) {
+        XBT_DEBUG("#### NOTE var(%d) is a boundless variable", i);
+        var->m_mu = -1.0;
+        var->m_value = new_value(var);
+      } else {
+        var->m_mu = 1.0;
+        var->m_newMu = 2.0;
+        var->m_value = new_value(var);
+      }
+      XBT_DEBUG("#### var(%p) ->weight :  %e", var, var->m_weight);
+      XBT_DEBUG("#### var(%p) ->mu :  %e", var, var->m_mu);
+      XBT_DEBUG("#### var(%p) ->weight: %e", var, var->m_weight);
+      XBT_DEBUG("#### var(%p) ->bound: %e", var, var->m_bound);
+      for (elemIt=var->m_cnsts.begin(); elemIt!=var->m_cnsts.end(); ++elemIt) {
+        if ((*elemIt)->m_value == 0.0)
+          nb++;
+      }
+      if (nb == var->m_cnsts.size())
+        var->m_value = 1.0;
+    }
+  }
+
+  /* 
+   * Compute dual objective.
+   */
+  obj = dual_objective(varList, cnstList);
+
+  /*
+   * 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
+     */
+    for (varIt=varList->begin(); varIt!=varList->end(); ++varIt) {
+      var = *varIt;    
+      if (!var->m_weight)
+        break;
+      if (var->m_bound >= 0) {
+        XBT_DEBUG("Working on var (%p)", var);
+        var->m_newMu = 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->m_mu, var->m_newMu);
+        var->m_mu = var->m_newMu;
+
+        new_obj = dual_objective(varList, cnstList);
+        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
+     */
+    for (cnstIt=cnstList->begin(); cnstIt!=cnstList->end(); ++cnstIt) {
+      cnst = *cnstIt;
+      XBT_DEBUG("Working on cnst (%p)", cnst);
+      cnst->m_newLambda =
+          dichotomy(cnst->m_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->m_lambda, cnst->m_newLambda);
+      cnst->m_lambda = cnst->m_newLambda;
+
+      new_obj = dual_objective(varList, cnstList);
+      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;
+    for (varIt=varList->begin(); varIt!=varList->end(); ++varIt) {
+      var = *varIt;
+      if (var->m_weight <= 0)
+        var->m_value = 0.0;
+      else {
+        tmp = new_value(var);
+
+        overall_modification =
+            MAX(overall_modification, fabs(var->m_value - tmp));
+
+        var->m_value = tmp;
+        XBT_DEBUG("New value of var (%p)  = %e, overall_modification = %e",
+               var, var->m_value, overall_modification);
+      }
+    }
+
+    XBT_DEBUG("-------------- Check feasability ----------");
+    if (!__check_feasible(cnstList, varList, 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(cnstList, varList, 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)
+{
+  #ifdef TOREPAIR
+  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);
+  #endif
+}
+
+static double partial_diff_lambda(double lambda, void *param_cnst)
+{
+  #ifdef TOREPAIR
+  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;
+  #endif
+}
+
+/** \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)
+{
+  #ifdef TOREPAIR  
+  xbt_assert(x > 0.0, "Don't call me with stupid values! (%1.20f)", x);
+  return VEGAS_SCALING * var->weight * log(x);
+  #endif
+}
+
+double func_vegas_fp(lmm_variable_t var, double x)
+{
+  #ifdef TOREPAIR  
+  xbt_assert(x > 0.0, "Don't call me with stupid values! (%1.20f)", x);
+  return VEGAS_SCALING * var->weight / x;
+  #endif
+}
+
+double func_vegas_fpi(lmm_variable_t var, double x)
+{
+  #ifdef TOREPAIR  
+  xbt_assert(x > 0.0, "Don't call me with stupid values! (%1.20f)", x);
+  return var->weight / (x / VEGAS_SCALING);
+  #endif
+}
+
+/*
+ * 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->m_weight > 0.0, "Don't call me with stupid values!");
+
+  return RENO_SCALING * sqrt(3.0 / 2.0) / var->m_weight *
+      atan(sqrt(3.0 / 2.0) * var->m_weight * x);
+}
+
+double func_reno_fp(lmm_variable_t var, double x)
+{
+  return RENO_SCALING * 3.0 / (3.0 * var->m_weight * var->m_weight * x * x +
+                               2.0);
+}
+
+double func_reno_fpi(lmm_variable_t var, double x)
+{
+  double res_fpi;
+
+  xbt_assert(var->m_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->m_weight * var->m_weight * (x / RENO_SCALING)) -
+      2.0 / (3.0 * var->m_weight * var->m_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->m_weight > 0.0, "Don't call me with stupid values!");
+  return RENO2_SCALING * (1.0 / var->m_weight) * log((x * var->m_weight) /
+                                                   (2.0 * x * var->m_weight +
+                                                    3.0));
+}
+
+double func_reno2_fp(lmm_variable_t var, double x)
+{
+  return RENO2_SCALING * 3.0 / (var->m_weight * x *
+                                (2.0 * var->m_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->m_weight * var->m_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;
+}
index 420695c..5eee02a 100644 (file)
@@ -258,6 +258,90 @@ XBT_INLINE double lmm_variable_getbound(lmm_variable_t var)
   return (var->bound);
 }
 
+/* Replace the content of elem_a with elem_b. The content of elem_b is cleared. */
+static void renew_elem_entry(lmm_element_t elem_a, lmm_element_t elem_b)
+{
+    elem_a->constraint = elem_b->constraint;
+    elem_a->variable   = elem_b->variable;
+    elem_a->value      = elem_b->value;
+
+    /* If elem_b is in the element_set swag, register the new element to the swag. */
+    if (xbt_swag_remove(elem_b, &(elem_b->constraint->element_set))) {
+      if (elem_a->variable->weight)
+        xbt_swag_insert_at_head(elem_a, &(elem_a->constraint->element_set));
+      else
+        xbt_swag_insert_at_tail(elem_a, &(elem_a->constraint->element_set));
+    }
+
+    if (xbt_swag_remove(elem_b, &(elem_b->constraint->active_element_set))) {
+      if (elem_a->variable->weight)
+        xbt_swag_insert_at_head(elem_a, &(elem_a->constraint->active_element_set));
+      else
+        xbt_swag_insert_at_tail(elem_a, &(elem_a->constraint->active_element_set));
+    }
+
+    elem_b->constraint = NULL;
+    elem_b->variable   = NULL;
+    elem_b->value      = 0;
+}
+
+void lmm_shrink(lmm_system_t sys, lmm_constraint_t cnst,
+                lmm_variable_t var)
+{
+  lmm_element_t elem = NULL;
+  int found = 0;
+
+  int i;
+  for (i = 0; i < var->cnsts_number; i++) {
+    elem = &(var->cnsts[i]);
+    if (elem->constraint == cnst) {
+      found = 1;
+      break;
+    }
+  }
+
+  if (!found) {
+    XBT_DEBUG("cnst %p is not found in var %p", cnst, var);
+    return;
+  }
+
+  sys->modified = 1;
+
+  XBT_DEBUG("remove elem(value %lf, cnst %p, var %p) in var %p",
+      elem->value, elem->constraint, elem->variable, var);
+
+
+
+  /* We are going to change the constraint object and the variable object.
+   * Propagate this change to other objects. Calling here (not after
+   * modification) is correct? */
+  lmm_update_modified_set(sys, cnst);
+  lmm_update_modified_set(sys, var->cnsts[0].constraint); // will look up element_set of this constraint, and then each var in the element_set, and each var->cnsts[i].
+
+
+
+  /* now var->cnsts[i] is not necessary any more */
+
+  xbt_swag_remove(elem, &(elem->constraint->element_set));
+  xbt_swag_remove(elem, &(elem->constraint->active_element_set));
+  elem->constraint = NULL;
+  elem->variable = NULL;
+  elem->value = 0;
+
+
+
+  /* We do not want to have an empty element entry before the last entry. So,
+   * plug up the hole with the last one. */
+  if (i < var->cnsts_number - 1)
+    renew_elem_entry(&var->cnsts[i], &var->cnsts[var->cnsts_number - 1]);
+
+  var->cnsts_number -= 1;
+
+
+  if (xbt_swag_size(&(cnst->element_set)) == 0)
+    make_constraint_inactive(sys, cnst);
+}
+
 void lmm_expand(lmm_system_t sys, lmm_constraint_t cnst,
                 lmm_variable_t var, double value)
 {
diff --git a/src/surf/maxmin_private_.h b/src/surf/maxmin_private_.h
new file mode 100644 (file)
index 0000000..bdf6fc4
--- /dev/null
@@ -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 */
index 21a86ea..c959b37 100644 (file)
@@ -326,18 +326,18 @@ int net_get_link_latency_limited(surf_action_t action)
 }
 #endif
 
-static double net_share_resources_full(double now)
+static double net_share_resources_full(surf_model_t network_model, double now)
 {
   s_surf_action_lmm_t s_action;
   surf_action_network_CM02_t action = NULL;
   xbt_swag_t running_actions =
-      surf_network_model->states.running_action_set;
+      network_model->states.running_action_set;
   double min;
 
   min = generic_maxmin_share_resources(running_actions,
                                        xbt_swag_offset(s_action,
                                                        variable),
-                                                       surf_network_model->model_private->maxmin_system,
+                                                       network_model->model_private->maxmin_system,
                                        network_solve);
 
 #define VARIABLE(action) (*((lmm_variable_t*)(((char *) (action)) + xbt_swag_offset(s_action, variable)  )))
@@ -360,19 +360,19 @@ static double net_share_resources_full(double now)
   return min;
 }
 
-static double net_share_resources_lazy(double now)
+static double net_share_resources_lazy(surf_model_t network_model, double now)
 {
-  return generic_share_resources_lazy(now, surf_network_model);
+  return generic_share_resources_lazy(now, network_model);
 }
 
-static void net_update_actions_state_full(double now, double delta)
+static void net_update_actions_state_full(surf_model_t network_model, double now, double delta)
 {
-  generic_update_actions_state_full(now, delta, surf_network_model);
+  generic_update_actions_state_full(now, delta, network_model);
 }
 
-static void net_update_actions_state_lazy(double now, double delta)
+static void net_update_actions_state_lazy(surf_model_t network_model, double now, double delta)
 {
-  generic_update_actions_state_lazy(now, delta, surf_network_model);
+  generic_update_actions_state_lazy(now, delta, network_model);
 }
 
 static void net_update_resource_state(void *id,
@@ -653,18 +653,18 @@ static int net_link_shared(const void *link)
       lmm_constraint_is_shared(((surf_resource_lmm_t) link)->constraint);
 }
 
-static void net_finalize(void)
+static void net_finalize(surf_model_t network_model)
 {
-  lmm_system_free(surf_network_model->model_private->maxmin_system);
-  surf_network_model->model_private->maxmin_system = NULL;
+  lmm_system_free(network_model->model_private->maxmin_system);
+  network_model->model_private->maxmin_system = NULL;
 
-  if (surf_network_model->model_private->update_mechanism == UM_LAZY) {
-    xbt_heap_free(surf_network_model->model_private->action_heap);
-    xbt_swag_free(surf_network_model->model_private->modified_set);
+  if (network_model->model_private->update_mechanism == UM_LAZY) {
+    xbt_heap_free(network_model->model_private->action_heap);
+    xbt_swag_free(network_model->model_private->modified_set);
   }
 
-  surf_model_exit(surf_network_model);
-  surf_network_model = NULL;
+  surf_model_exit(network_model);
+  network_model = NULL;
 
   xbt_dict_free(&gap_lookup);
   xbt_dynar_free(&smpi_bw_factor);
@@ -763,6 +763,7 @@ static void surf_network_model_init_internal(void)
   set_update_mechanism();
 
   surf_network_model->name = "network";
+  surf_network_model->type = SURF_MODEL_TYPE_NETWORK;
   surf_network_model->action_unref = surf_action_unref;
   surf_network_model->action_cancel = surf_action_cancel;
   surf_network_model->action_recycle = net_action_recycle;
@@ -796,7 +797,11 @@ static void surf_network_model_init_internal(void)
   surf_network_model->suspend = surf_action_suspend;
   surf_network_model->resume = surf_action_resume;
   surf_network_model->is_suspended = surf_action_is_suspended;
-  surf_cpu_model->set_max_duration = surf_action_set_max_duration;
+
+  xbt_assert(surf_cpu_model_pm);
+  xbt_assert(surf_cpu_model_vm);
+  surf_cpu_model_pm->set_max_duration = surf_action_set_max_duration;
+  surf_cpu_model_vm->set_max_duration = surf_action_set_max_duration;
 
   surf_network_model->extension.network.communicate = net_communicate;
   surf_network_model->extension.network.get_route = net_get_route;
diff --git a/src/surf/network.cpp b/src/surf/network.cpp
new file mode 100644 (file)
index 0000000..e8e886e
--- /dev/null
@@ -0,0 +1,698 @@
+#include "network.hpp"
+#include "maxmin_private.h"
+#include "simgrid/sg_config.h"
+
+extern "C" {
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_network, surf,
+                                "Logging specific to the SURF network module");
+}
+
+NetworkCm02ModelPtr surf_network_model = NULL;
+
+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 */
+
+double sg_tcp_gamma = 0.0;
+int sg_network_crosstraffic = 0;
+
+/*************
+ * CallBacks *
+ *************/
+
+static void net_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);
+    surf_network_model->createResource(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);
+    surf_network_model->createResource(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);
+  } else {
+       surf_network_model->createResource(link->id,
+                      link->bandwidth,
+                      link->bandwidth_trace,
+                      link->latency,
+                      link->latency_trace,
+                      link->state,
+                      link->state_trace, link->policy, link->properties);
+  }
+}
+
+static void net_add_traces(void){
+  xbt_dict_cursor_t cursor = NULL;
+  char *trace_name, *elm;
+
+  static int called = 0;
+  if (called)
+    return;
+  called = 1;
+
+  /* connect all 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);
+    NetworkCm02LinkLmmPtr link = dynamic_cast<NetworkCm02LinkLmmPtr>(
+                                    static_cast<ResourcePtr>(
+                                                 xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL)));
+
+    xbt_assert(link, "Cannot connect trace %s to link %s: link undefined",
+               trace_name, elm);
+    xbt_assert(trace,
+               "Cannot connect trace %s to link %s: trace undefined",
+               trace_name, elm);
+
+    link->p_stateEvent = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(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);
+    NetworkCm02LinkLmmPtr link = dynamic_cast<NetworkCm02LinkLmmPtr>(
+                                 static_cast<ResourcePtr>(
+                                             xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL)));
+
+    xbt_assert(link, "Cannot connect trace %s to link %s: link undefined",
+               trace_name, elm);
+    xbt_assert(trace,
+               "Cannot connect trace %s to link %s: trace undefined",
+               trace_name, elm);
+
+    link->p_power.event = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(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);
+    NetworkCm02LinkLmmPtr link = dynamic_cast<NetworkCm02LinkLmmPtr>(
+                                 static_cast<ResourcePtr>(
+                                             xbt_lib_get_or_null(link_lib, elm, SURF_LINK_LEVEL)));
+
+    xbt_assert(link, "Cannot connect trace %s to link %s: link undefined",
+               trace_name, elm);
+    xbt_assert(trace,
+               "Cannot connect trace %s to link %s: trace undefined",
+               trace_name, elm);
+
+    link->p_latEvent = tmgr_history_add_trace(history, trace, 0.0, 0, static_cast<ResourcePtr>(link));
+  }
+}
+
+void net_define_callbacks(void)
+{
+  /* Figuring out the network links */
+  sg_platf_link_add_cb(net_parse_link_init);
+  sg_platf_postparse_add_cb(net_add_traces);
+}
+
+/*********
+ * Model *
+ *********/
+
+/************************************************************************/
+/* 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();
+  net_define_callbacks();
+  ModelPtr model = static_cast<ModelPtr>(surf_network_model);
+  xbt_dynar_push(model_list, &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();
+  net_define_callbacks();
+  ModelPtr model = static_cast<ModelPtr>(surf_network_model);
+  xbt_dynar_push(model_list, &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();
+  net_define_callbacks();
+  ModelPtr model = static_cast<ModelPtr>(surf_network_model);
+  xbt_dynar_push(model_list, &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();
+  net_define_callbacks();
+  ModelPtr model = static_cast<ModelPtr>(surf_network_model);
+  xbt_dynar_push(model_list, &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();
+  net_define_callbacks();
+  ModelPtr model = static_cast<ModelPtr>(surf_network_model);
+  xbt_dynar_push(model_list, &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){
+  ActionLmmPtr 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(static_cast<ResourcePtr>(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, static_cast<ResourcePtr>(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)
+         && (double_equals(xbt_heap_maxkey(p_actionHeap), now))) {
+    action = (NetworkCm02ActionLmmPtr) xbt_heap_pop(p_actionHeap);
+    XBT_DEBUG("Something happened to action %p", action);
+#ifdef HAVE_TRACING
+    if (TRACE_is_enabled()) {
+      int n = lmm_get_number_of_cnst_from_var(p_maxminSystem, action->p_variable);
+      unsigned int i;
+      for (i = 0; i < n; i++){
+        lmm_constraint_t constraint = lmm_get_cnst_from_var(p_maxminSystem,
+                                                            action->p_variable,
+                                                            i);
+        NetworkCm02LinkPtr link = static_cast<NetworkCm02LinkPtr>(lmm_constraint_id(constraint));
+        TRACE_surf_link_set_utilization(link->m_name,
+                                        action->p_category,
+                                        (lmm_variable_getvalue(action->p_variable)*
+                                            lmm_get_cnst_weight_from_var(p_maxminSystem,
+                                                action->p_variable,
+                                                i)),
+                                        action->m_lastUpdate,
+                                        now - action->m_lastUpdate);
+      }
+    }
+#endif
+
+    // if I am wearing a latency hat
+    if (action->m_hat == LATENCY) {
+      XBT_DEBUG("Latency paid for action %p. Activating", action);
+      lmm_update_variable_weight(p_maxminSystem, action->p_variable, action->m_weight);
+      action->heapRemove(p_actionHeap);
+      action->m_lastUpdate = surf_get_clock();
+
+        // if I am wearing a max_duration or normal hat
+    } else if (action->m_hat == MAX_DURATION ||
+        action->m_hat == NORMAL) {
+        // no need to communicate anymore
+        // assume that flows that reached max_duration have remaining of 0
+      action->m_finish = surf_get_clock();
+      XBT_DEBUG("Action %p finished", action);
+      action->m_remains = 0;
+      action->m_finish = surf_get_clock();
+      action->setState(SURF_ACTION_DONE);
+      action->heapRemove(p_actionHeap);
+
+      action->gapRemove();
+    }
+  }
+  return;
+}
+
+xbt_dynar_t NetworkCm02Model::getRoute(RoutingEdgePtr src, RoutingEdgePtr dst)
+{
+  xbt_dynar_t route = NULL;
+  routing_platf->getRouteAndLatency(src, dst, &route, NULL);
+  return route;
+}
+
+ActionPtr NetworkCm02Model::communicate(RoutingEdgePtr src, RoutingEdgePtr dst,
+                                                double size, double rate)
+{
+  unsigned int i;
+  void *_link;
+  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) {
+       link = dynamic_cast<NetworkCm02LinkLmmPtr>(static_cast<ResourcePtr>(_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) {
+      link = dynamic_cast<NetworkCm02LinkLmmPtr>(static_cast<ResourcePtr>(_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;
+
+  //FIXME:REMOVxbt_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) {
+      link = dynamic_cast<NetworkCm02LinkLmmPtr>(static_cast<ResourcePtr>(_link));
+      action->m_weight +=
+         sg_weight_S_parameter /
+         (link->p_power.peak * link->p_power.scale);
+    }
+  }
+  xbt_dynar_foreach(route, i, _link) {
+       link = dynamic_cast<NetworkCm02LinkLmmPtr>(static_cast<ResourcePtr>(_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);
+    link = dynamic_cast<NetworkCm02LinkLmmPtr>(*static_cast<ResourcePtr *>(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) {
+       link = dynamic_cast<NetworkCm02LinkLmmPtr>(static_cast<ResourcePtr>(_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) {
+      link = dynamic_cast<NetworkCm02LinkLmmPtr>(static_cast<ResourcePtr>(_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)
+: Resource(model, name, props),
+  ResourceLmm(model, name, props, system, constraint_value, history, state_init, state_trace, metric_peak, metric_trace),
+  NetworkCm02Link(model, name, props)
+{
+  m_latCurrent = lat_initial;
+  if (lat_trace)
+       p_latEvent = tmgr_history_add_trace(history, lat_trace, 0.0, 0, static_cast<ResourcePtr>(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("[" "%g" "] Asking to update network card \"%s\" with value " */
+  /*     "%g" " 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 *
+ **********/
+void NetworkCm02ActionLmm::updateRemainingLazy(double now)
+{
+  double delta = 0.0;
+
+  if (m_suspended != 0)
+    return;
+
+  delta = now - m_lastUpdate;
+
+  if (m_remains > 0) {
+    XBT_DEBUG("Updating action(%p): remains was %lf, last_update was: %lf", this, m_remains, m_lastUpdate);
+    double_update(&(m_remains), m_lastValue * delta);
+
+    XBT_DEBUG("Updating action(%p): remains is now %lf", this, m_remains);
+  }
+
+  if (m_maxDuration != NO_MAX_DURATION)
+    double_update(&m_maxDuration, delta);
+
+  if (m_remains <= 0 &&
+      (lmm_get_variable_weight(p_variable) > 0)) {
+    m_finish = surf_get_clock();
+    setState(SURF_ACTION_DONE);
+
+    heapRemove(p_model->p_actionHeap);
+  } else if (((m_maxDuration != NO_MAX_DURATION)
+      && (m_maxDuration <= 0))) {
+    m_finish = surf_get_clock();
+    setState(SURF_ACTION_DONE);
+    heapRemove(p_model->p_actionHeap);
+  }
+
+  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
new file mode 100644 (file)
index 0000000..f51a46e
--- /dev/null
@@ -0,0 +1,135 @@
+#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_
+
+/***********
+ * Classes *
+ ***********/
+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;
+
+void net_define_callbacks(void);
+
+/*********
+ * Model *
+ *********/
+class NetworkCm02Model : public Model {
+public:
+  NetworkCm02Model(int i) : Model("network") {};//FIXME: add network clean interface
+  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);
+  virtual void gapAppend(double size, const NetworkCm02LinkLmmPtr link, NetworkCm02ActionLmmPtr action) {};
+  virtual ActionPtr 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;
+  virtual double latencyFactor(double size);
+  virtual double bandwidthFactor(double size);
+  virtual double bandwidthConstraint(double rate, double bound, double size);
+  bool m_haveGap = false;
+};
+
+/************
+ * Resource *
+ ************/
+
+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;
+  virtual double getLatency();
+  virtual bool isShared()=0;
+  /* Using this object with the public part of
+    model does not make sense */
+  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 properties)
+   : ResourceLmm(), NetworkCm02Link(model, name, properties) {};
+  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 *
+ **********/
+class NetworkCm02Action : virtual public Action {
+public:
+  NetworkCm02Action(ModelPtr model, double cost, bool failed)
+ : Action(model, cost, failed) {};
+  double m_latency;
+  double m_latCurrent;
+  double m_weight;
+  double m_rate;
+  const char* p_senderLinkName;
+  double m_senderGap;
+  double m_senderSize;
+  xbt_fifo_item_t p_senderFifoItem;
+#ifdef HAVE_LATENCY_BOUND_TRACKING
+  int m_latencyLimited;
+#endif
+
+};
+
+class NetworkCm02ActionLmm : public ActionLmm, public NetworkCm02Action {
+public:
+  NetworkCm02ActionLmm(ModelPtr model, double cost, bool failed)
+ : Action(model, cost, failed),
+   ActionLmm(model, cost, failed),
+   NetworkCm02Action(model, cost, failed) {};
+  void updateRemainingLazy(double now);
+  void recycle();
+};
+
+#endif /* SURF_MODEL_NETWORK_H_ */
index 8d0b9da..7eaa9d8 100644 (file)
@@ -49,11 +49,11 @@ static void netcste_action_cancel(surf_action_t action)
   return;
 }
 
-static double netcste_share_resources(double now)
+static double netcste_share_resources(surf_model_t network_model, double now)
 {
   surf_action_network_Constant_t action = NULL;
   xbt_swag_t running_actions =
-      surf_network_model->states.running_action_set;
+      network_model->states.running_action_set;
   double min = -1.0;
 
   xbt_swag_foreach(action, running_actions) {
@@ -68,12 +68,12 @@ static double netcste_share_resources(double now)
   return min;
 }
 
-static void netcste_update_actions_state(double now, double delta)
+static void netcste_update_actions_state(surf_model_t network_model, double now, double delta)
 {
   surf_action_network_Constant_t action = NULL;
   surf_action_network_Constant_t next_action = NULL;
   xbt_swag_t running_actions =
-      surf_network_model->states.running_action_set;
+      network_model->states.running_action_set;
 
   xbt_swag_foreach_safe(action, next_action, running_actions) {
     if (action->latency > 0) {
@@ -90,12 +90,12 @@ static void netcste_update_actions_state(double now, double delta)
 
     if (action->generic_action.remains <= 0) {
       action->generic_action.finish = surf_get_clock();
-      surf_network_model->action_state_set((surf_action_t) action,
+      network_model->action_state_set((surf_action_t) action,
                                            SURF_ACTION_DONE);
     } else if ((action->generic_action.max_duration != NO_MAX_DURATION)
                && (action->generic_action.max_duration <= 0)) {
       action->generic_action.finish = surf_get_clock();
-      surf_network_model->action_state_set((surf_action_t) action,
+      network_model->action_state_set((surf_action_t) action,
                                            SURF_ACTION_DONE);
     }
   }
@@ -180,10 +180,10 @@ static int netcste_action_is_suspended(surf_action_t action)
   return ((surf_action_network_Constant_t) action)->suspended;
 }
 
-static void netcste_finalize(void)
+static void netcste_finalize(surf_model_t network_model)
 {
-  surf_model_exit(surf_network_model);
-  surf_network_model = NULL;
+  surf_model_exit(network_model);
+  network_model = NULL;
 }
 
 
@@ -216,7 +216,11 @@ void surf_network_model_init_Constant()
   surf_network_model->suspend = netcste_action_suspend;
   surf_network_model->resume = netcste_action_resume;
   surf_network_model->is_suspended = netcste_action_is_suspended;
-  surf_cpu_model->set_max_duration = surf_action_set_max_duration;
+
+  xbt_assert(surf_cpu_model_pm);
+  xbt_assert(surf_cpu_model_vm);
+  surf_cpu_model_pm->set_max_duration = surf_action_set_max_duration;
+  surf_cpu_model_vm->set_max_duration = surf_action_set_max_duration;
 
   surf_network_model->extension.network.communicate = netcste_communicate;
   surf_network_model->extension.network.get_link_bandwidth =
diff --git a/src/surf/network_constant.cpp b/src/surf/network_constant.cpp
new file mode 100644 (file)
index 0000000..13fff27
--- /dev/null
@@ -0,0 +1,168 @@
+#include "network_constant.hpp"
+#include "surf/random_mgr.h"
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_network);
+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();
+
+  sg_platf_host_add_cb(netcste_count_hosts);
+
+  ModelPtr model = static_cast<ModelPtr>(surf_network_model);
+  xbt_dynar_push(model_list, &model);
+
+  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 = dynamic_cast<NetworkConstantActionLmmPtr>(static_cast<ActionPtr>(_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 = dynamic_cast<NetworkConstantActionLmmPtr>(static_cast<ActionPtr>(_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);
+    }
+  }
+}
+
+ActionPtr 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(static_cast<ActionPtr>(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 (file)
index 0000000..c9c140d
--- /dev/null
@@ -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);
+  ActionPtr 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):
+         Action(model, 0, false), NetworkCm02ActionLmm(model, 0, false), m_latInit(latency) {
+       m_latency = latency;
+       if (m_latency <= 0.0) {
+         p_stateSet = p_model->p_doneActionSet;
+         xbt_swag_insert(static_cast<ActionPtr>(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_ */
index 4392bb3..8dec8b5 100644 (file)
@@ -196,7 +196,7 @@ static void action_state_set(surf_action_t action,
   surf_action_state_set(action, state);
 }
 
-static double share_resources(double now)
+static double share_resources(surf_model_t network_model, double now)
 {
   xbt_swag_t running_actions =
       surf_network_model->states.running_action_set;
@@ -216,11 +216,11 @@ static double share_resources(double now)
   return time_to_next_flow_completion;
 }
 
-static void update_actions_state(double now, double delta)
+static void update_actions_state(surf_model_t network_model, double now, double delta)
 {
   surf_action_network_GTNETS_t action = NULL;
   xbt_swag_t running_actions =
-      surf_network_model->states.running_action_set;
+      network_model->states.running_action_set;
 
   /* If there are no running flows, just return */
   if (time_to_next_flow_completion < 0.0) {
@@ -400,7 +400,7 @@ static void gtnets_action_set_category(surf_action_t action, const char *categor
 }
 #endif
 
-static void finalize(void)
+static void finalize(surf_model_t network_model)
 {
   gtnets_finalize();
 }
@@ -410,6 +410,7 @@ static void surf_network_model_init_internal(void)
   surf_network_model = surf_model_init();
 
   surf_network_model->name = "network GTNetS";
+  surf_network_model->type = SURF_MODEL_TYPE_NETWORK;
   surf_network_model->action_unref = action_unref;
   surf_network_model->action_cancel = action_cancel;
   surf_network_model->action_recycle = action_recycle;
diff --git a/src/surf/network_gtnets.cpp b/src/surf/network_gtnets.cpp
new file mode 100644 (file)
index 0000000..5570c20
--- /dev/null
@@ -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<int,GTNETS_Link*>::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 (file)
index 0000000..a2af26d
--- /dev/null
@@ -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<int, Uniform*> p_uniformJitterGenerator;
+
+   map<int, TCPServer*> p_gtnetsServers;
+   map<int, TCPSend*> p_gtnetsClients;
+   map<int, Linkp2p*> p_gtnetsLinks_;
+   map<int, Node*> p_gtnetsNodes;
+   map<void*, int> p_gtnetsActionToFlow;
+
+   map <int, void*> p_gtnetsMetadata;
+
+   // From Topology
+   int m_nodeID;
+   map<int, GTNETS_Link*> p_links;
+   vector<GTNETS_Node*> p_nodes;
+   map<int, int> p_hosts;      //hostid->nodeid
+   set<int > 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_ */
index 6398a4b..dc56b4d 100644 (file)
@@ -23,9 +23,9 @@ extern xbt_dict_t dict_socket;
 
 static double time_to_next_flow_completion = -1;
 
-static double ns3_share_resources(double min);
-static void ns3_update_actions_state(double now, double delta);
-static void finalize(void);
+static double ns3_share_resources(surf_model_t network_model, double min);
+static void ns3_update_actions_state(surf_model_t network_model, double now, double delta);
+static void finalize(surf_model_t network_model);
 static surf_action_t ns3_communicate(sg_routing_edge_t src_elm,
                                      sg_routing_edge_t dst_elm,
                                      double size, double rate);
@@ -342,6 +342,7 @@ void surf_network_model_init_NS3()
 
   surf_network_model = surf_model_init();
   surf_network_model->name = "network NS3";
+  surf_network_model->type = SURF_MODEL_TYPE_NETWORK;
   surf_network_model->extension.network.get_link_latency = ns3_get_link_latency;
   surf_network_model->extension.network.get_link_bandwidth = ns3_get_link_bandwidth;
   surf_network_model->extension.network.get_route = ns3_get_route;
@@ -380,19 +381,19 @@ void surf_network_model_init_NS3()
 #endif
 }
 
-static void finalize(void)
+static void finalize(surf_model_t network_model)
 {
   ns3_finalize();
   xbt_dynar_free_container(&IPV4addr);
   xbt_dict_free(&dict_socket);
 }
 
-static double ns3_share_resources(double min)
+static double ns3_share_resources(surf_model_t network_model, double min)
 {
   XBT_DEBUG("ns3_share_resources");
 
   xbt_swag_t running_actions =
-    surf_network_model->states.running_action_set;
+    network_model->states.running_action_set;
 
   //get the first relevant value from the running_actions list
   if (!xbt_swag_size(running_actions) || min == 0.0)
@@ -411,7 +412,7 @@ static double ns3_share_resources(double min)
   return time_to_next_flow_completion;
 }
 
-static void ns3_update_actions_state(double now, double delta)
+static void ns3_update_actions_state(surf_model_t network_model, double now, double delta)
 {
   xbt_dict_cursor_t cursor = NULL;
   char *key;
@@ -422,7 +423,7 @@ static void ns3_update_actions_state(double now, double delta)
 
   surf_action_network_ns3_t action = NULL;
   xbt_swag_t running_actions =
-    surf_network_model->states.running_action_set;
+    network_model->states.running_action_set;
 
   /* If there are no running flows, just return */
   if (!xbt_swag_size(running_actions)) {
diff --git a/src/surf/network_private.h b/src/surf/network_private.h
deleted file mode 100644 (file)
index e9c56fb..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (c) 2004-2012. 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_NETWORK_PRIVATE_H
-#define _SURF_NETWORK_PRIVATE_H
-
-#include "surf_private.h"
-#include "xbt/dict.h"
-#include "xbt/fifo.h"
-
-typedef struct network_link_CM02 {
-  s_surf_resource_lmm_t lmm_resource;   /* must remain first to be added to a trace */
-
-  /* Using this object with the public part of
-     model does not make sense */
-  double lat_current;
-  tmgr_trace_event_t lat_event;
-} s_link_CM02_t, *link_CM02_t;
-
-typedef struct surf_action_network_CM02 {
-  s_surf_action_lmm_t generic_lmm_action;
-  double latency;
-  double lat_current;
-  double weight;
-  double rate;
-  struct {
-     const char* link_name;
-     double gap;
-     double size;
-     xbt_fifo_item_t fifo_item;
-  } sender;
-#ifdef HAVE_LATENCY_BOUND_TRACKING
-  int latency_limited;
-#endif
-} s_surf_action_network_CM02_t, *surf_action_network_CM02_t;
-
-#endif                          /* _SURF_NETWORK_PRIVATE_H */
diff --git a/src/surf/network_smpi.cpp b/src/surf/network_smpi.cpp
new file mode 100644 (file)
index 0000000..ee6e415
--- /dev/null
@@ -0,0 +1,197 @@
+#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();
+  net_define_callbacks();
+  xbt_dynar_push(model_list, &surf_network_model);
+  //network_solve = lmm_solve;
+
+  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_homogeneous(NULL);
+    }
+    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::bandwidthFactor(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("%f <= %ld return %f", size, fact.factor, current);
+      return current;
+    }else
+      current=fact.value;
+  }
+  XBT_DEBUG("%f > %ld return %f", size, fact.factor, current);
+
+  return current;
+}
+double NetworkSmpiModel::latencyFactor(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("%f <= %ld return %f", size, fact.factor, current);
+      return current;
+    }else
+      current=fact.value;
+  }
+  XBT_DEBUG("%f > %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 (file)
index 0000000..f5d38fa
--- /dev/null
@@ -0,0 +1,40 @@
+#include "network.hpp"
+
+/***********
+ * Classes *
+ ***********/
+
+class NetworkSmpiModel;
+typedef NetworkSmpiModel *NetworkSmpiModelPtr;
+
+/*********
+ * Tools *
+ *********/
+
+/*********
+ * Model *
+ *********/
+
+class NetworkSmpiModel : public NetworkCm02Model {
+public:
+  NetworkSmpiModel() : NetworkCm02Model() {m_haveGap=true;};
+  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 *
+ ************/
+
+
+/**********
+ * Action *
+ **********/
+
+
+
index b4346d9..7db8f09 100644 (file)
@@ -47,25 +47,25 @@ static void* new_model_create_resource(const char* id, const char* model,const c
   return NULL;
 }
 
-static void new_model_finalize(void)
+static void new_model_finalize(surf_model_t new_model)
 {
   lmm_system_free(new_model_maxmin_system);
   new_model_maxmin_system = NULL;
 
-  surf_model_exit(surf_new_model);
-  surf_new_model = NULL;
+  surf_model_exit(new_model);
+  new_model = NULL;
 
   xbt_swag_free
       (new_model_running_action_set_that_does_not_need_being_checked);
   new_model_running_action_set_that_does_not_need_being_checked = NULL;
 }
 
-static void new_model_update_actions_state(double now, double delta)
+static void new_model_update_actions_state(surf_model_t new_model, double now, double delta)
 {
   return;
 }
 
-static double new_model_share_resources(double NOW)
+static double new_model_share_resources(surf_model_t new_model, double NOW)
 {
   return -1;
 }
@@ -147,6 +147,7 @@ static void surf_new_model_init_internal(void)
       xbt_swag_new(xbt_swag_offset(action, state_hookup));
 
   surf_new_model->name = "New Model";
+  surf_new_model->type = SURF_MODEL_TYPE_NEW_MODEL;
   surf_new_model->action_unref = new_model_action_unref;
   surf_new_model->action_cancel = new_model_action_cancel;
   surf_new_model->action_state_set = new_model_action_state_set;
diff --git a/src/surf/new_model_private.h b/src/surf/new_model_private.h
deleted file mode 100644 (file)
index 3cdbeeb..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * TUTORIAL: New model
- * new_model_private.h
- *
- *  Created on: 12 October 2012
- *      Author: navarro
- */
-
-#ifndef NEW_MODEL_PRIVATE_H_
-#define NEW_MODEL_PRIVATE_H_
-
-
-
-#endif /* NEW_MODEL_PRIVATE_H_ */
index a5a59ae..0522c26 100644 (file)
@@ -292,13 +292,13 @@ static void* storage_create_resource(const char* id, const char* model,
   return storage;
 }
 
-static void storage_finalize(void)
+static void storage_finalize(surf_model_t storage_model)
 {
   lmm_system_free(storage_maxmin_system);
   storage_maxmin_system = NULL;
 
-  surf_model_exit(surf_storage_model);
-  surf_storage_model = NULL;
+  surf_model_exit(storage_model);
+  storage_model = NULL;
 
   xbt_dynar_free(&storage_list);
 
@@ -307,11 +307,11 @@ static void storage_finalize(void)
   storage_running_action_set_that_does_not_need_being_checked = NULL;
 }
 
-static void storage_update_actions_state(double now, double delta)
+static void storage_update_actions_state(surf_model_t storage_model, double now, double delta)
 {
   surf_action_storage_t action = NULL;
   surf_action_storage_t next_action = NULL;
-  xbt_swag_t running_actions = surf_storage_model->states.running_action_set;
+  xbt_swag_t running_actions = storage_model->states.running_action_set;
 
 
   xbt_swag_foreach_safe(action, next_action, running_actions) {
@@ -362,7 +362,7 @@ static void storage_update_actions_state(double now, double delta)
   return;
 }
 
-static double storage_share_resources(double NOW)
+static double storage_share_resources(surf_model_t storage_model, double NOW)
 {
   XBT_DEBUG("storage_share_resources %f",NOW);
   s_surf_action_storage_t action;
@@ -370,7 +370,7 @@ static double storage_share_resources(double NOW)
   storage_t storage;
   surf_action_storage_t write_action;
 
-  double min_completion = generic_maxmin_share_resources(surf_storage_model->states.running_action_set,
+  double min_completion = generic_maxmin_share_resources(storage_model->states.running_action_set,
       xbt_swag_offset(action, generic_lmm_action.variable),
       storage_maxmin_system, lmm_solve);
 
@@ -532,6 +532,7 @@ static void surf_storage_model_init_internal(void)
       xbt_swag_new(xbt_swag_offset(action, state_hookup));
 
   surf_storage_model->name = "Storage";
+  surf_storage_model->type = SURF_MODEL_TYPE_STORAGE;
   surf_storage_model->action_unref = storage_action_unref;
   surf_storage_model->action_cancel = storage_action_cancel;
   surf_storage_model->action_state_set = storage_action_state_set;
diff --git a/src/surf/storage.cpp b/src/surf/storage.cpp
new file mode 100644 (file)
index 0000000..d0b2766
--- /dev/null
@@ -0,0 +1,717 @@
+#include "storage.hpp"
+#include "surf_private.h"
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.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;
+
+static int storage_selective_update = 0;
+static xbt_swag_t storage_running_action_set_that_does_not_need_being_checked = NULL;
+
+/*************
+ * CallBacks *
+ *************/
+
+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));
+  xbt_dict_free(&(stype->properties));
+  free(stype);
+}
+
+static XBT_INLINE void surf_storage_resource_free(void *r)
+{
+  // specific to storage
+  StoragePtr storage = dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(r));
+  xbt_dict_free(&storage->p_content);
+  xbt_dynar_free(&storage->p_writeActions);
+  free(storage->p_typeId);
+  free(storage->p_contentType);
+  // 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);
+}
+
+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;
+    storage->content_type = ((storage_type_t) stype)->content_type;
+    XBT_DEBUG("For disk '%s' content is empty, inherit the content (of type %s) from storage type '%s' ",
+        storage->id,((storage_type_t) stype)->content_type,
+        ((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\tcontent_type '%s' "
+      "\n\t\tproperties '%p'\n",
+      storage->id,
+      ((storage_type_t) stype)->model,
+      ((storage_type_t) stype)->type_id,
+      storage->content,
+      storage->content_type,
+      ((storage_type_t) stype)->properties);
+
+  surf_storage_model->createResource(storage->id, ((storage_type_t) stype)->model,
+                                     ((storage_type_t) stype)->type_id,
+                                     storage->content,
+                                     storage->content_type,
+                                     storage->properties);
+}
+
+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, sg_storage_size_t *used_size)
+{
+  *used_size = 0;
+  if ((!filename) || (strcmp(filename, "") == 0))
+    return NULL;
+
+  xbt_dict_t parse_content = xbt_dict_new_homogeneous(xbt_free);
+  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];
+  sg_storage_size_t size;
+
+
+  while ((read = xbt_getline(&line, &len, file)) != -1) {
+    if (read){
+    if(sscanf(line,"%s %" SCNu64, path, &size) == 2) {
+        *used_size += size;
+        sg_storage_size_t *psize = xbt_new(sg_storage_size_t, 1);
+        *psize = size;
+        xbt_dict_set(parse_content,path,psize,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->content_type = xbt_strdup(storage_type->content_type);
+  stype->type_id = xbt_strdup(storage_type->id);
+  stype->size = storage_type->size;
+
+  XBT_DEBUG("ROUTING Create a storage type id '%s' with model '%s', "
+      "content '%s', and content_type '%s'",
+      stype->type_id,
+      stype->model,
+      storage_type->content,
+      storage_type->content_type);
+
+  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->storageId, ROUTING_STORAGE_LEVEL);
+#endif
+  xbt_assert(storage,"Disk id \"%s\" does not exists", mount->storageId);
+
+  XBT_DEBUG("ROUTING Mount '%s' on '%s'",mount->storageId, mount->name);
+
+  s_mount_t mnt;
+  mnt.storage = surf_storage_resource_priv(surf_storage_resource_by_name(mount->storageId));
+  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 void storage_define_callbacks()
+{
+  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);
+}
+
+void storage_register_callbacks() {
+
+  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);
+}
+
+/*********
+ * Model *
+ *********/
+
+void surf_storage_model_init_default(void)
+{
+  surf_storage_model = new StorageModel();
+  storage_define_callbacks();
+  xbt_dynar_push(model_list, &surf_storage_model);
+}
+
+StorageModel::StorageModel() : Model("Storage") {
+  StorageActionLmm action;
+
+  XBT_DEBUG("surf_storage_model_init_internal");
+
+  storage_running_action_set_that_does_not_need_being_checked =
+      xbt_swag_new(xbt_swag_offset(action, p_stateHookup));
+
+  if (!p_maxminSystem) {
+    p_maxminSystem = lmm_system_new(storage_selective_update);
+  }
+}
+
+
+StorageModel::~StorageModel(){
+  lmm_system_free(p_maxminSystem);
+
+  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, const char* content_type, xbt_dict_t properties)
+{
+
+  xbt_assert(!surf_storage_resource_priv(surf_storage_resource_by_name(id)),
+              "Storage '%s' declared several times in the platform file",
+              id);
+
+  storage_type_t storage_type = (storage_type_t) xbt_lib_get_or_null(storage_type_lib, type_id,ROUTING_STORAGE_TYPE_LEVEL);
+
+  double Bread  = surf_parse_get_bandwidth((char*)xbt_dict_get(storage_type->properties, "Bread"));
+  double Bwrite = surf_parse_get_bandwidth((char*)xbt_dict_get(storage_type->properties, "Bwrite"));
+  double Bconnection   = surf_parse_get_bandwidth((char*)xbt_dict_get(storage_type->properties, "Bconnection"));
+
+  StoragePtr storage = new StorageLmm(this, id, properties, p_maxminSystem,
+                 Bread, Bwrite, Bconnection,
+                 type_id, (char *)content_name, xbt_strdup(content_type), storage_type->size);
+
+  xbt_lib_set(storage_lib, id, SURF_STORAGE_LEVEL, static_cast<ResourcePtr>(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);
+  unsigned int i, j;
+  StoragePtr storage;
+  StorageActionLmmPtr write_action;
+
+  double min_completion = shareResourcesMaxMin(p_runningActionSet,
+      p_maxminSystem, 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;
+
+  xbt_swag_foreach_safe(_action, _next_action, p_runningActionSet) {
+       action = dynamic_cast<StorageActionLmmPtr>(static_cast<ActionPtr>(_action));
+    if(action->m_type == WRITE)
+    {
+      // Update the disk usage
+     // Update the file size
+     // For each action of 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 sg_storage_size_t). */
+      long incr = delta * rate + MAXMIN_PRECISION;
+      action->p_storage->m_usedSize += incr; // disk usage
+      action->p_file->size += incr; // file size
+
+      sg_storage_size_t *psize = xbt_new(sg_storage_size_t,1);
+      *psize = action->p_file->size;
+
+      xbt_dict_t content_dict = action->p_storage->p_content;
+      xbt_dict_set(content_dict, action->p_file->name, psize, NULL);
+    }
+
+    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 Storage::parseContent(char *filename)
+{
+  m_usedSize = 0;
+  if ((!filename) || (strcmp(filename, "") == 0))
+    return NULL;
+
+  xbt_dict_t parse_content = xbt_dict_new_homogeneous(xbt_free);
+  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];
+  sg_storage_size_t size;
+
+
+  while ((read = xbt_getline(&line, &len, file)) != -1) {
+    if (read){
+    if(sscanf(line,"%s %" SCNu64, path, &size) == 2) {
+        m_usedSize += size;
+        sg_storage_size_t *psize = xbt_new(sg_storage_size_t, 1);
+        *psize = size;
+        xbt_dict_set(parse_content,path,psize,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)
+:  Resource(model, name, properties)
+{
+  p_writeActions = xbt_dynar_new(sizeof(char *),NULL);
+}
+
+StorageLmm::StorageLmm(StorageModelPtr model, const char* name, xbt_dict_t properties,
+            lmm_system_t maxminSystem, double bread, double bwrite, double bconnection,
+            const char* type_id, char *content_name, char *content_type, size_t size)
+ :  Resource(model, name, properties), ResourceLmm(), Storage(model, name, properties) {
+  XBT_DEBUG("Create resource with Bconnection '%f' Bread '%f' Bwrite '%f' and Size '%lu'", bconnection, bread, bwrite, ((unsigned long)size));
+
+  p_stateCurrent = SURF_RESOURCE_ON;
+  m_usedSize = 0;
+  m_size = 0;
+
+  p_content = parseContent(content_name);
+  p_contentType = content_type;
+  p_constraint = lmm_constraint_new(maxminSystem, this, bconnection);
+  p_constraintRead  = lmm_constraint_new(maxminSystem, this, bread);
+  p_constraintWrite = lmm_constraint_new(maxminSystem, this, bwrite);
+  m_size = size;
+  p_typeId = xbt_strdup(type_id);
+}
+
+bool Storage::isUsed()
+{
+  THROW_UNIMPLEMENTED;
+  return false;
+}
+
+void Storage::updateState(tmgr_trace_event_t event_type, double value, double date)
+{
+  THROW_UNIMPLEMENTED;
+}
+
+StorageActionPtr StorageLmm::ls(const char* path)
+{
+  StorageActionLmmPtr action = new StorageActionLmm(p_model, 0, p_stateCurrent != SURF_RESOURCE_ON, this, LS);
+
+  action->p_lsDict = NULL;
+  xbt_dict_t ls_dict = xbt_dict_new_homogeneous(xbt_free);
+
+  char* key;
+  sg_storage_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){
+        sg_storage_size_t *psize = xbt_new(sg_storage_size_t, 1);
+        *psize=size;
+        xbt_dict_set(ls_dict, file, psize, 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;
+}
+
+StorageActionPtr StorageLmm::open(const char* mount, const char* path)
+{
+  XBT_DEBUG("\tOpen file '%s'",path);
+  sg_storage_size_t size, *psize;
+  psize = (sg_storage_size_t*) xbt_dict_get_or_null(p_content, path);
+  // if file does not exist create an empty file
+  if(psize)
+    size = *psize;
+  else {
+       psize = xbt_new(sg_storage_size_t,1);
+    size = 0;
+    *psize = size;
+    xbt_dict_set(p_content, path, psize, 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->mount = xbt_strdup(mount);
+
+  StorageActionLmmPtr action = new StorageActionLmm(p_model, 0, p_stateCurrent != SURF_RESOURCE_ON, this, OPEN);
+  action->p_file = file;
+  return action;
+}
+
+StorageActionPtr StorageLmm::close(surf_file_t fd)
+{
+  char *filename = fd->name;
+  XBT_DEBUG("\tClose file '%s' size '%" PRIu64 "'", 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->mount);
+  xbt_free(fd);
+  StorageActionLmmPtr action = new StorageActionLmm(p_model, 0, p_stateCurrent != SURF_RESOURCE_ON, this, CLOSE);
+  return action;
+}
+
+StorageActionPtr StorageLmm::read(surf_file_t fd, sg_storage_size_t size)
+{
+  if(size > fd->size)
+    size = fd->size;
+  StorageActionLmmPtr action = new StorageActionLmm(p_model, size, p_stateCurrent != SURF_RESOURCE_ON, this, READ);
+  return action;
+}
+
+StorageActionPtr StorageLmm::write(surf_file_t fd, sg_storage_size_t size)
+{
+  char *filename = fd->name;
+  XBT_DEBUG("\tWrite file '%s' size '%" PRIu64 "/%" PRIu64 "'",filename,size,fd->size);
+
+  StorageActionLmmPtr action = new StorageActionLmm(p_model, size, p_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;
+}
+
+void StorageLmm::rename(const char *src, const char *dest)
+{
+  sg_storage_size_t *psize, *new_psize;
+  psize = (sg_storage_size_t*) xbt_dict_get_or_null(p_content,src);
+  new_psize = xbt_new(sg_storage_size_t, 1);
+  *new_psize = *psize;
+  if (psize){// src file exists
+    xbt_dict_remove(p_content, src);
+    xbt_dict_set(p_content, dest, new_psize,NULL);
+    XBT_DEBUG("Change file name from %s to %s, size '%" PRIu64 "'",src, dest, *psize);
+  }
+  else
+    XBT_DEBUG("File %s doesn't exist",src);
+}
+
+xbt_dict_t StorageLmm::getContent()
+{
+  /* For the moment this action has no cost, but in the future we could take in account access latency of the disk */
+  /*surf_action_t action = storage_action_execute(storage,0, LS);*/
+
+  xbt_dict_t content_dict = xbt_dict_new_homogeneous(NULL);
+  xbt_dict_cursor_t cursor = NULL;
+  char *file;
+  sg_storage_size_t *psize;
+
+  xbt_dict_foreach(p_content, cursor, file, psize){
+    xbt_dict_set(content_dict,file,psize,NULL);
+  }
+  return content_dict;
+}
+
+sg_storage_size_t StorageLmm::getSize(){
+  return m_size;
+}
+
+/**********
+ * Action *
+ **********/
+
+StorageActionLmm::StorageActionLmm(ModelPtr model, double cost, bool failed, StorageLmmPtr storage, e_surf_action_storage_type_t type)
+  : Action(model, cost, failed), ActionLmm(model, cost, failed), StorageAction(model, cost, failed, storage, type) {
+  XBT_IN("(%s,%" PRIu64, storage->m_name, cost);
+  p_variable = lmm_variable_new(p_model->p_maxminSystem, this, 1.0, -1.0 , 3);
+
+  // Must be less than the max bandwidth for all actions
+  lmm_expand(p_model->p_maxminSystem, storage->p_constraint, p_variable, 1.0);
+  switch(type) {
+  case OPEN:
+  case CLOSE:
+  case STAT:
+  case LS:
+    break;
+  case READ:
+    lmm_expand(p_model->p_maxminSystem, storage->p_constraintRead,
+               p_variable, 1.0);
+    break;
+  case WRITE:
+    lmm_expand(p_model->p_maxminSystem, storage->p_constraintWrite,
+               p_variable, 1.0);
+    xbt_dynar_push(storage->p_writeActions, static_cast<ActionPtr>(this));
+    break;
+  }
+  XBT_OUT();
+}
+
+int StorageActionLmm::unref()
+{
+  m_refcount--;
+  if (!m_refcount) {
+    xbt_swag_remove(static_cast<ActionPtr>(this), p_stateSet);
+    if (p_variable)
+      lmm_variable_free(p_model->p_maxminSystem, 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(p_model->p_maxminSystem,
+                               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 (file)
index 0000000..bf16cef
--- /dev/null
@@ -0,0 +1,153 @@
+#include "surf.hpp"
+
+#ifndef STORAGE_HPP_
+#define STORAGE_HPP_
+
+/***********
+ * Classes *
+ ***********/
+
+class StorageModel;
+typedef StorageModel *StorageModelPtr;
+
+class Storage;
+typedef Storage *StoragePtr;
+
+class StorageLmm;
+typedef StorageLmm *StorageLmmPtr;
+
+class StorageAction;
+typedef StorageAction *StorageActionPtr;
+
+class StorageActionLmm;
+typedef StorageActionLmm *StorageActionLmmPtr;
+
+
+/*********
+ * Model *
+ *********/
+class StorageModel : public Model {
+public:
+  StorageModel();
+  ~StorageModel();
+  StoragePtr createResource(const char* id, const char* model, const char* type_id,
+                  const char* content_name, const char* content_type, xbt_dict_t properties);
+  double shareResources(double now);
+  void updateActionsState(double now, double delta);
+
+};
+
+/************
+ * Resource *
+ ************/
+
+class Storage : virtual public Resource {
+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);
+
+  xbt_dict_t p_content;
+  char* p_contentType;
+  sg_storage_size_t m_size;
+  sg_storage_size_t m_usedSize;
+  char * p_typeId;
+
+  virtual StorageActionPtr open(const char* mount, const char* path)=0;
+  virtual StorageActionPtr close(surf_file_t fd)=0;
+  //virtual StorageActionPtr unlink(surf_file_t fd)=0;
+  virtual StorageActionPtr ls(const char *path)=0;
+  virtual StorageActionPtr read(surf_file_t fd, sg_storage_size_t size)=0;
+  virtual StorageActionPtr write(surf_file_t fd, sg_storage_size_t size)=0;
+  virtual void rename(const char *src, const char *dest)=0;
+
+  virtual xbt_dict_t getContent()=0;
+  virtual sg_storage_size_t getSize()=0;
+
+  xbt_dict_t parseContent(char *filename);
+
+  xbt_dynar_t p_writeActions;
+};
+
+class StorageLmm : public ResourceLmm, public Storage {
+public:
+  StorageLmm(StorageModelPtr model, const char* name, xbt_dict_t properties,
+                    lmm_system_t maxminSystem, double bread, double bwrite, double bconnection,
+                    const char* type_id, char *content_name, char *content_type, size_t size);
+
+  StorageActionPtr open(const char* mount, const char* path);
+  StorageActionPtr close(surf_file_t fd);
+  //StorageActionPtr unlink(surf_file_t fd);
+  StorageActionPtr ls(const char *path);
+  xbt_dict_t getContent();
+  sg_storage_size_t getSize();
+  StorageActionPtr read(surf_file_t fd, sg_storage_size_t size);//FIXME:why we have a useless param ptr ??
+  StorageActionPtr write(surf_file_t fd, sg_storage_size_t size);//FIXME:why we have a useless param ptr ??
+  void rename(const char *src, const char *dest);
+
+  lmm_constraint_t p_constraintWrite;    /* Constraint for maximum write bandwidth*/
+  lmm_constraint_t p_constraintRead;     /* Constraint for maximum write bandwidth*/
+};
+
+/**********
+ * Action *
+ **********/
+
+typedef enum {
+  READ=0, WRITE, STAT, OPEN, CLOSE, LS
+} e_surf_action_storage_type_t;
+
+
+class StorageAction : virtual public Action {
+public:
+  StorageAction(){};
+  StorageAction(ModelPtr model, double cost, bool failed, StoragePtr storage, e_surf_action_storage_type_t type)
+   : p_storage(storage), m_type(type) {};
+
+
+
+  e_surf_action_storage_type_t m_type;
+  StoragePtr p_storage;
+  surf_file_t p_file;
+  xbt_dict_t p_lsDict;
+};
+
+class StorageActionLmm : public ActionLmm, public StorageAction {
+public:
+  StorageActionLmm(){};
+  StorageActionLmm(ModelPtr model, double cost, bool failed, StorageLmmPtr storage, e_surf_action_storage_type_t type);
+  void suspend();
+  int unref();
+  void cancel();
+  //FIXME:??void recycle();
+  void resume();
+  bool isSuspended();
+  void setMaxDuration(double duration);
+  void setPriority(double priority);
+
+};
+
+
+typedef struct s_storage_type {
+  char *model;
+  char *content;
+  char *content_type;
+  char *type_id;
+  xbt_dict_t properties;
+  sg_storage_size_t size;
+} s_storage_type_t, *storage_type_t;
+
+typedef struct s_mount {
+  void *storage;
+  char *name;
+} s_mount_t, *mount_t;
+
+typedef struct surf_file {
+  char *name;
+  char *mount;
+  sg_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
deleted file mode 100644 (file)
index ee023b4..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (c) 2009, 2012-2013. 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 STORAGE_PRIVATE_H_
-#define STORAGE_PRIVATE_H_
-
-typedef struct s_storage_type {
-  char *model;
-  char *content;
-  char *content_type;
-  char *type_id;
-  xbt_dict_t properties;
-  sg_storage_size_t size;
-} s_storage_type_t, *storage_type_t;
-
-typedef struct s_mount {
-  void *storage;
-  char *name;
-} s_mount_t, *mount_t;
-
-typedef struct surf_file {
-  char *name;
-  char *mount;
-  sg_storage_size_t size;
-} s_surf_file_t;
-
-typedef struct surf_storage {
-  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*/
-  lmm_constraint_t constraint_read;     /* Constraint for maximum write bandwidth*/
-  xbt_dict_t content;
-  char* content_type;
-  sg_storage_size_t size;
-  sg_storage_size_t used_size;
-  char *type_id;
-  xbt_dynar_t write_actions;
-  xbt_dict_t properties;
-} s_storage_t, *storage_t;
-
-typedef enum {
-  READ=0, WRITE, STAT, OPEN, CLOSE, LS
-} e_surf_action_storage_type_t;
-
-typedef struct surf_action_storage {
-  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;
-
-#endif /* STORAGE_PRIVATE_H_ */
index 807bfaf..f208537 100644 (file)
@@ -110,7 +110,11 @@ int __surf_is_absolute_file_path(const char *file_path)
 
 double NOW = 0;
 
-xbt_dynar_t model_list = NULL;
+/* model_list_invoke contains only surf_workstation and surf_vm_workstation.
+ * The callback functions of cpu_model and network_model will be called from
+ * those of these workstation models. */
+xbt_dynar_t model_list = NULL; /* for destroying all models correctly */
+xbt_dynar_t model_list_invoke = NULL;  /* for invoking callbacks */
 tmgr_history_t history = NULL;
 lmm_system_t maxmin_system = NULL;
 xbt_dynar_t surf_path = NULL;
@@ -418,6 +422,8 @@ void surf_init(int *argc, char **argv)
   xbt_init(argc, argv);
   if (!model_list)
     model_list = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
+  if (!model_list_invoke)
+    model_list_invoke = xbt_dynar_new(sizeof(surf_model_private_t), NULL);
   if (!history)
     history = tmgr_history_new();
 
@@ -476,8 +482,11 @@ void surf_exit(void)
   sg_config_finalize();
 
   xbt_dynar_foreach(model_list, iter, model)
-      model->model_private->finalize();
+      model->model_private->finalize(model);
   xbt_dynar_free(&model_list);
+
+  xbt_dynar_free(&model_list_invoke);
+
   routing_exit();
 
   if (maxmin_system) {
@@ -538,12 +547,15 @@ void surf_presolve(void)
       }
     }
   }
+
+  /* FIXME: see what is check_update_action_state(). if necessary, use model_list_invoke. */
   xbt_dynar_foreach(model_list, iter, model)
-      model->model_private->update_actions_state(NOW, 0.0);
+      model->model_private->update_actions_state(model, NOW, 0.0);
 }
 
 double surf_solve(double max_date)
 {
+                 
   min = -1.0; /* duration */
   double next_event_date = -1.0;
   double model_next_action_end = -1.0;
@@ -563,17 +575,16 @@ double surf_solve(double max_date)
   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_mins = xbt_new(double, xbt_dynar_length(model_list_invoke));
   }
   surf_min_index = 0;
 
   /* sequential version */
-  xbt_dynar_foreach(model_list, iter, model) {
+  xbt_dynar_foreach(model_list_invoke, iter, model) {
     surf_share_resources(model);
   }
-
   unsigned i;
-  for (i = 0; i < xbt_dynar_length(model_list); i++) {
+  for (i = 0; i < xbt_dynar_length(model_list_invoke); i++) {
     if ((min < 0.0 || surf_mins[i] < min)
         && surf_mins[i] >= 0.0) {
       min = surf_mins[i];
@@ -598,7 +609,7 @@ double surf_solve(double max_date)
 
       XBT_DEBUG("Run for network at most %f", min);
       // run until min or next flow
-      model_next_action_end = surf_network_model->model_private->share_resources(min);
+      model_next_action_end = surf_network_model->model_private->share_resources(surf_network_model, min);
 
       XBT_DEBUG("Min for network : %f", model_next_action_end);
       if(model_next_action_end>=0.0)
@@ -647,7 +658,7 @@ double surf_solve(double max_date)
   XBT_DEBUG("Duration set to %f", min);
 
   NOW = NOW + min;
-
+  /* FIXME: model_list or model_list_invoke? revisit here later */
   /* sequential version */
   xbt_dynar_foreach(model_list, iter, model) {
     surf_update_actions_state(model);
@@ -671,7 +682,7 @@ static void surf_share_resources(surf_model_t model)
   int i = __sync_fetch_and_add(&surf_min_index, 1);
   if (strcmp(model->name,"network NS3")) {
     XBT_DEBUG("Running for Resource [%s]", model->name);
-    next_action_end = model->model_private->share_resources(NOW);
+    next_action_end = model->model_private->share_resources(model, NOW);
     XBT_DEBUG("Resource [%s] : next action end = %f",
         model->name, next_action_end);
   }
@@ -680,6 +691,6 @@ static void surf_share_resources(surf_model_t model)
 
 static void surf_update_actions_state(surf_model_t model)
 {
-  model->model_private->update_actions_state(NOW, min);
+  model->model_private->update_actions_state(model, NOW, min);
 }
 
diff --git a/src/surf/surf.cpp b/src/surf/surf.cpp
new file mode 100644 (file)
index 0000000..366e6ed
--- /dev/null
@@ -0,0 +1,1051 @@
+#include "surf_private.h"
+#include "surf.hpp"
+#include "network.hpp"
+#include "cpu.hpp"
+#include "workstation.hpp"
+#include "vm_workstation.hpp"
+#include "simix/smx_host_private.h"
+#include "surf_routing.hpp"
+#include "simgrid/sg_config.h"
+#include "mc/mc.h"
+
+extern "C" {
+XBT_LOG_NEW_CATEGORY(surf, "All SURF categories");
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_kernel, surf,
+                                "Logging specific to SURF (kernel)");
+}
+
+/*********
+ * Utils *
+ *********/
+
+/* 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.
+ * Instead, each model change a global data, and then the caller of surf_solve must
+ * pick into these sets of action_failed and action_done.
+ *
+ * This was not clean but ok as long as we didn't had to restart the processes when the resource comes back up.
+ * We worked by putting sentinel actions on every resources we are interested in,
+ * so that surf informs us if/when the corresponding resource fails.
+ *
+ * But this does not work to get Simix informed of when a resource comes back up, and this is where this pimple comes.
+ * We have a set of resources that are currently down and for which simix needs to know when it comes back up.
+ * And the current function is called *at every simulation step* to sweep over that set, searching for a resource
+ * that was turned back up in the meanwhile. This is UGLY and slow.
+ *
+ * The proper solution would be to not rely on globals for the action_failed and action_done swags.
+ * They must be passed as parameter by the caller (the handling of these actions in simix may let you
+ * think that these two sets can be merged, but their handling in SimDag induce the contrary unless this
+ * simdag code can check by itself whether the action is done of failed -- seems very doable, but yet more
+ * cleanup to do).
+ *
+ * Once surf_solve() is passed the set of actions that changed, you want to add a new set of resources back up
+ * as parameter to this function. You also want to add a boolean field "restart_watched" to each resource, and
+ * make sure that whenever a resource with this field enabled comes back up, it's added to that set so that Simix
+ * sees it and react accordingly. This would kill that need for surf to call simix.
+ *
+ */
+
+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);
+}*/
+
+/* model_list_invoke contains only surf_workstation and surf_vm_workstation.
+ * The callback functions of cpu_model and network_model will be called from
+ * those of these workstation models. */
+xbt_dynar_t model_list = NULL; /* for destroying all models correctly */
+xbt_dynar_t model_list_invoke = NULL;  /* for invoking callbacks */
+
+tmgr_history_t history = NULL;
+lmm_system_t maxmin_system = NULL;
+xbt_dynar_t surf_path = NULL;
+xbt_dynar_t host_that_restart = NULL;
+xbt_dict_t watched_hosts_lib;
+
+/* 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_vm_workstation_model_description[] = {
+  {"default",
+   "Default vm workstation model.)",
+   surf_vm_workstation_model_init_current_default},
+  {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 */
+};
+
+#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;
+
+double surf_get_clock(void)
+{
+  return NOW;
+}
+
+#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_cpu_free(void *r)
+{
+  delete dynamic_cast<CpuPtr>(static_cast<ResourcePtr>(r));
+}
+
+static XBT_INLINE void surf_link_free(void *r)
+{
+  delete dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(r));
+}
+
+static XBT_INLINE void surf_workstation_free(void *r)
+{
+  delete dynamic_cast<WorkstationCLM03Ptr>(static_cast<ResourcePtr>(r));
+}
+
+
+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_homogeneous(NULL);
+
+  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_cpu_free);
+  SURF_WKS_LEVEL = xbt_lib_add_level(host_lib,surf_workstation_free);
+  SURF_LINK_LEVEL = xbt_lib_add_level(link_lib,surf_link_free);
+
+  xbt_init(argc, argv);
+  if (!model_list)
+    model_list = xbt_dynar_new(sizeof(ModelPtr), NULL);
+  if (!model_list_invoke)
+    model_list_invoke = xbt_dynar_new(sizeof(ModelPtr), 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);
+
+  if (MC_is_active())
+    MC_memory_init();
+}
+
+void surf_exit(void)
+{
+  unsigned int iter;
+  ModelPtr model = NULL;
+
+#ifdef HAVE_TRACING
+  TRACE_end();                  /* Just in case it was not called by the upper
+                                 * layer (or there is no upper layer) */
+#endif
+
+  sg_config_finalize();
+
+  xbt_dynar_foreach(model_list, iter, model)
+    delete model;
+  xbt_dynar_free(&model_list);
+  xbt_dynar_free(&model_list_invoke);
+  routing_exit();
+
+  if (maxmin_system) {
+    lmm_system_free(maxmin_system);
+    maxmin_system = NULL;
+  }
+  if (history) {
+    tmgr_history_free(history);
+    history = NULL;
+  }
+
+#ifdef CONTEXT_THREADS
+  xbt_parmap_destroy(surf_parmap);
+  xbt_free(surf_mins);
+  surf_mins = NULL;
+#endif
+  xbt_dynar_free(&host_that_restart);
+  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),
+   p_maxminSystem(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: set the good function once and for all
+  if (p_updateMechanism == UM_LAZY)
+       return shareResourcesLazy(now);
+  else if (p_updateMechanism == UM_FULL)
+       return shareResourcesFull(now);
+  else
+       xbt_die("Invalid cpu update mechanism!");
+}
+
+double Model::shareResourcesLazy(double now)
+{
+  ActionLmmPtr action = NULL;
+  double min = -1;
+  double value;
+
+  XBT_DEBUG
+      ("Before share resources, the size of modified actions set is %d",
+       xbt_swag_size(p_modifiedSet));
+
+  lmm_solve(p_maxminSystem);
+
+  XBT_DEBUG
+      ("After share resources, The size of modified actions set is %d",
+       xbt_swag_size(p_modifiedSet));
+
+  while((action = static_cast<ActionLmmPtr>(xbt_swag_extract(p_modifiedSet)))) {
+    int max_dur_flag = 0;
+
+    if (action->p_stateSet != p_runningActionSet)
+      continue;
+
+    /* bogus priority, skip it */
+    if (action->m_priority <= 0)
+      continue;
+
+    action->updateRemainingLazy(now);
+
+    min = -1;
+    value = lmm_variable_getvalue(action->p_variable);
+    if (value > 0) {
+      if (action->m_remains > 0) {
+        value = action->m_remains / value;
+        min = now + value;
+      } else {
+        value = 0.0;
+        min = now;
+      }
+    }
+
+    if ((action->m_maxDuration != NO_MAX_DURATION)
+        && (min == -1
+            || action->m_start +
+            action->m_maxDuration < min)) {
+      min = action->m_start +
+          action->m_maxDuration;
+      max_dur_flag = 1;
+    }
+
+    XBT_DEBUG("Action(%p) Start %lf Finish %lf Max_duration %lf", action,
+        action->m_start, now + value,
+        action->m_maxDuration);
+
+    if (min != -1) {
+      action->heapRemove(p_actionHeap);
+      action->heapInsert(p_actionHeap, min, max_dur_flag ? MAX_DURATION : NORMAL);
+      XBT_DEBUG("Insert at heap action(%p) min %lf now %lf", action, min,
+                now);
+    } else DIE_IMPOSSIBLE;
+  }
+
+  //hereafter must have already the min value for this resource model
+  if (xbt_heap_size(p_actionHeap) > 0)
+    min = xbt_heap_maxkey(p_actionHeap) - now;
+  else
+    min = -1;
+
+  XBT_DEBUG("The minimum with the HEAP %lf", min);
+
+  return min;
+}
+
+double Model::shareResourcesFull(double now) {
+  THROW_UNIMPLEMENTED;
+}
+
+
+double Model::shareResourcesMaxMin(xbt_swag_t running_actions,
+                          lmm_system_t sys,
+                          void (*solve) (lmm_system_t))
+{
+  void *_action = NULL;
+  ActionLmmPtr action = NULL;
+  double min = -1;
+  double value = -1;
+
+  solve(sys);
+
+  xbt_swag_foreach(_action, running_actions) {
+    action = dynamic_cast<ActionLmmPtr>(static_cast<ActionPtr>(_action));
+    value = lmm_variable_getvalue(action->p_variable);
+    if ((value > 0) || (action->m_maxDuration >= 0))
+      break;
+  }
+
+  if (!_action)
+    return -1.0;
+
+  if (value > 0) {
+    if (action->m_remains > 0)
+      min = action->m_remains / value;
+    else
+      min = 0.0;
+    if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min))
+      min = action->m_maxDuration;
+  } else
+    min = action->m_maxDuration;
+
+
+  for (_action = xbt_swag_getNext(static_cast<ActionPtr>(action), running_actions->offset);
+       _action;
+       _action = xbt_swag_getNext(static_cast<ActionPtr>(action), running_actions->offset)) {
+       action = dynamic_cast<ActionLmmPtr>(static_cast<ActionPtr>(_action));
+    value = lmm_variable_getvalue(action->p_variable);
+    if (value > 0) {
+      if (action->m_remains > 0)
+        value = action->m_remains / value;
+      else
+        value = 0.0;
+      if (value < min) {
+        min = value;
+        XBT_DEBUG("Updating min (value) with %p: %f", action, min);
+      }
+    }
+    if ((action->m_maxDuration >= 0) && (action->m_maxDuration < min)) {
+      min = action->m_maxDuration;
+      XBT_DEBUG("Updating min (duration) with %p: %f", action, min);
+    }
+  }
+  XBT_DEBUG("min value : %f", min);
+
+  return min;
+}
+
+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)
+{
+
+}
+
+void Model::updateActionsStateFull(double now, double delta)
+{
+
+}
+
+
+void Model::addTurnedOnCallback(ResourceCallback rc)
+{
+  m_resOnCB = rc;
+}
+
+void Model::notifyResourceTurnedOn(ResourcePtr r)
+{
+  m_resOnCB(r);
+}
+
+void Model::addTurnedOffCallback(ResourceCallback rc)
+{
+  m_resOffCB = rc;
+}
+
+void Model::notifyResourceTurnedOff(ResourcePtr r)
+{
+  m_resOffCB(r);
+}
+
+void Model::addActionCancelCallback(ActionCallback ac)
+{
+  m_actCancelCB = ac;
+}
+
+void Model::notifyActionCancel(ActionPtr a)
+{
+  m_actCancelCB(a);
+}
+
+void Model::addActionResumeCallback(ActionCallback ac)
+{
+  m_actResumeCB = ac;
+}
+
+void Model::notifyActionResume(ActionPtr a)
+{
+  m_actResumeCB(a);
+}
+
+void Model::addActionSuspendCallback(ActionCallback ac)
+{
+  m_actSuspendCB = ac;
+}
+
+void Model::notifyActionSuspend(ActionPtr a)
+{
+  m_actSuspendCB(a);
+}
+
+
+/************
+ * Resource *
+ ************/
+
+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);
+  //FIXME: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 p_stateCurrent;
+}
+
+void Resource::setState(e_surf_resource_state_t state)
+{
+  p_stateCurrent = state;
+}
+
+bool Resource::isOn()
+{
+  return m_running;
+}
+
+void Resource::turnOn()
+{
+  if (!m_running) {
+    m_running = true;
+    p_model->notifyResourceTurnedOn(this);
+  }
+}
+
+void Resource::turnOff()
+{
+  if (m_running) {
+    m_running = false;
+    p_model->notifyResourceTurnedOff(this);
+  }
+}
+
+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, static_cast<ResourcePtr>(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, static_cast<ResourcePtr>(this));
+}
+
+/**********
+ * Action *
+ **********/
+
+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"
+};
+
+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
+  p_stateHookup.prev = 0;
+  p_stateHookup.next = 0;
+  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()
+{
+  if (p_stateSet ==  p_model->p_readyActionSet)
+    return SURF_ACTION_READY;
+  if (p_stateSet ==  p_model->p_runningActionSet)
+    return SURF_ACTION_RUNNING;
+  if (p_stateSet ==  p_model->p_failedActionSet)
+    return SURF_ACTION_FAILED;
+  if (p_stateSet ==  p_model->p_doneActionSet)
+    return SURF_ACTION_DONE;
+  return SURF_ACTION_NOT_IN_THE_SYSTEM;
+}
+
+void Action::setState(e_surf_action_state_t state)
+{
+  //surf_action_state_t action_state = &(action->model_type->states);
+  XBT_IN("(%p,%s)", this, surf_action_state_names[state]);
+  xbt_swag_remove(this, p_stateSet);
+
+  if (state == SURF_ACTION_READY)
+    p_stateSet = p_model->p_readyActionSet;
+  else if (state == SURF_ACTION_RUNNING)
+    p_stateSet = p_model->p_runningActionSet;
+  else if (state == SURF_ACTION_FAILED)
+    p_stateSet = p_model->p_failedActionSet;
+  else if (state == SURF_ACTION_DONE)
+    p_stateSet = p_model->p_doneActionSet;
+  else
+    p_stateSet = NULL;
+
+  if (p_stateSet)
+    xbt_swag_insert(this, p_stateSet);
+  XBT_OUT();
+}
+
+double Action::getStartTime()
+{
+  return m_start;
+}
+
+double Action::getFinishTime()
+{
+  /* keep the function behavior, some models (cpu_ti) change the finish time before the action end */
+  return m_remains == 0 ? m_finish : -1;
+}
+
+double Action::getRemains()
+{
+  XBT_IN("(%p)", this);
+  XBT_OUT();
+  return m_remains;
+}
+
+void Action::setData(void* data)
+{
+  p_data = data;
+}
+
+#ifdef HAVE_TRACING
+void Action::setCategory(const char *category)
+{
+  XBT_IN("(%p,%s)", this, category);
+  p_category = xbt_strdup(category);
+  XBT_OUT();
+}
+#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(static_cast<ActionPtr>(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:
+ *
+ * NORMAL = this is a normal heap entry stating the date to finish transmitting
+ * LATENCY = this is a heap entry to warn us when the latency is payed
+ * MAX_DURATION =this is a heap entry to warn us when the max_duration limit is reached
+ */
+void ActionLmm::heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat)
+{
+  m_hat = hat;
+  xbt_heap_push(heap, this, key);
+}
+
+void ActionLmm::heapRemove(xbt_heap_t heap)
+{
+  m_hat = NOTSET;
+  if (m_indexHeap >= 0) {
+    xbt_heap_remove(heap, m_indexHeap);
+  }
+}
+
+/* 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);
+  /* update remains before return it */
+  if (p_model->p_updateMechanism == UM_LAZY)      /* update remains before return it */
+    updateRemainingLazy(surf_get_clock());
+  XBT_OUT();
+  return m_remains;
+}
+
+//FIXME split code in the right places
+void ActionLmm::updateRemainingLazy(double now)
+{
+  double delta = 0.0;
+
+  if(p_model == static_cast<ModelPtr>(surf_network_model))
+  {
+    if (m_suspended != 0)
+      return;
+  }
+  else
+  {
+    xbt_assert(p_stateSet == p_model->p_runningActionSet,
+        "You're updating an action that is not running.");
+
+      /* bogus priority, skip it */
+    xbt_assert(m_priority > 0,
+        "You're updating an action that seems suspended.");
+  }
+
+  delta = now - m_lastUpdate;
+
+  if (m_remains > 0) {
+    XBT_DEBUG("Updating action(%p): remains was %f, last_update was: %f", this, m_remains, m_lastUpdate);
+    double_update(&m_remains, m_lastValue * delta);
+
+#ifdef HAVE_TRACING
+    if (p_model == static_cast<ModelPtr>(surf_cpu_model_pm) && TRACE_is_enabled()) {
+      ResourcePtr cpu = static_cast<ResourcePtr>(lmm_constraint_id(lmm_get_cnst_from_var(p_model->p_maxminSystem, p_variable, 0)));
+      TRACE_surf_host_set_utilization(cpu->m_name, p_category, m_lastValue, m_lastUpdate, now - m_lastUpdate);
+    }
+#endif
+    XBT_DEBUG("Updating action(%p): remains is now %f", this, m_remains);
+  }
+
+  if(p_model == static_cast<ModelPtr>(surf_network_model))
+  {
+    if (m_maxDuration != NO_MAX_DURATION)
+      double_update(&m_maxDuration, delta);
+
+    //FIXME: duplicated code
+    if ((m_remains <= 0) &&
+        (lmm_get_variable_weight(p_variable) > 0)) {
+      m_finish = surf_get_clock();
+      setState(SURF_ACTION_DONE);
+      heapRemove(p_model->p_actionHeap);
+    } else if (((m_maxDuration != NO_MAX_DURATION)
+        && (m_maxDuration <= 0))) {
+      m_finish = surf_get_clock();
+      setState(SURF_ACTION_DONE);
+      heapRemove(p_model->p_actionHeap);
+    }
+  }
+
+  m_lastUpdate = now;
+  m_lastValue = lmm_variable_getvalue(p_variable);
+}
+
+/*void Action::cancel()
+{
+  p_model->notifyActionCancel(this);
+}
+
+void Action::suspend()
+{
+  p_model->notifyActionSuspend(this);
+}
+
+void Action::resume()
+{
+  p_model->notifyActionResume(this);
+}
+
+bool Action::isSuspended()
+{
+  return false;
+}*/
+
diff --git a/src/surf/surf.hpp b/src/surf/surf.hpp
new file mode 100644 (file)
index 0000000..2afb2ce
--- /dev/null
@@ -0,0 +1,332 @@
+//using namespace generic;
+
+#ifndef SURF_MODEL_H_
+#define SURF_MODEL_H_
+
+#include <xbt.h>
+#include <string>
+#include <vector>
+#include <memory>
+#include <boost/smart_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/functional/factory.hpp>
+#include <boost/bind.hpp>
+#include "surf/trace_mgr.h"
+#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;
+
+/** \ingroup SURF_simulation
+ *  \brief Return the current time
+ *
+ *  Return the current time in millisecond.
+ */
+
+/*********
+ * 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
+XBT_PUBLIC(double) surf_get_clock(void);
+#ifdef __cplusplus
+}
+#endif
+
+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;
+typedef Model* ModelPtr;
+
+//class Resource;
+typedef Resource* ResourcePtr;
+typedef boost::function<void (ResourcePtr r)> ResourceCallback;
+                       
+//class Action;
+typedef Action* ActionPtr;
+typedef boost::function<void (ActionPtr a)> ActionCallback;
+
+//class ActionLmm;
+typedef ActionLmm* ActionLmmPtr;
+
+enum heap_action_type{
+  LATENCY = 100,
+  MAX_DURATION,
+  NORMAL,
+  NOTSET
+};
+
+/*********
+ * Trace *
+ *********/
+/* For the trace and trace:connect tag (store their content till the end of the parsing) */
+XBT_PUBLIC_DATA(xbt_dict_t) traces_set_list;
+XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_host_avail;
+XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_power;
+XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_link_avail; 
+XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_bandwidth; 
+XBT_PUBLIC_DATA(xbt_dict_t) trace_connect_list_latency;
+
+
+/*********
+ * Model *
+ *********/
+XBT_PUBLIC_DATA(xbt_dynar_t) model_list;
+
+class Model {
+public:
+  Model(string name);
+  virtual ~Model();
+
+  ResourcePtr createResource(string name);
+  ActionPtr createAction(double _cost, bool _failed);
+  virtual double shareResources(double now);
+  virtual double shareResourcesLazy(double now);
+  virtual double shareResourcesFull(double now);
+  double shareResourcesMaxMin(xbt_swag_t running_actions,
+                                      lmm_system_t sys,
+                                      void (*solve) (lmm_system_t));
+  virtual void updateActionsState(double now, double delta);
+  virtual void updateActionsStateLazy(double now, double delta);
+  virtual void updateActionsStateFull(double now, double delta);
+
+  string getName() {return m_name;};
+
+  void addTurnedOnCallback(ResourceCallback rc);
+  void notifyResourceTurnedOn(ResourcePtr r);
+
+  void addTurnedOffCallback(ResourceCallback rc);  
+  void notifyResourceTurnedOff(ResourcePtr r);
+
+  void addActionCancelCallback(ActionCallback ac);
+  void notifyActionCancel(ActionPtr a);
+  void addActionResumeCallback(ActionCallback ac);
+  void notifyActionResume(ActionPtr a);
+  void addActionSuspendCallback(ActionCallback ac);  
+  void notifyActionSuspend(ActionPtr a);
+
+  lmm_system_t p_maxminSystem;
+  e_UM_t p_updateMechanism;
+  xbt_swag_t p_modifiedSet;
+  xbt_heap_t p_actionHeap;
+  int m_selectiveUpdate;
+
+  xbt_swag_t p_readyActionSet; /**< Actions in state SURF_ACTION_READY */
+  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<ActionPtr> m_failedActions, m_runningActions;
+
+private:
+  ResourceCallback m_resOnCB, m_resOffCB;
+  ActionCallback m_actCancelCB, m_actSuspendCB, m_actResumeCB;
+};
+
+/************
+ * Resource *
+ ************/
+
+/**
+ * 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;
+
+class Resource {
+public:
+  Resource();
+  Resource(ModelPtr model, const char *name, xbt_dict_t properties);
+  virtual ~Resource() {};
+
+  virtual void updateState(tmgr_trace_event_t event_type, double value, double date)=0;
+
+  //private
+  virtual bool isUsed()=0;
+  //FIXME:updateActionState();
+  //FIXME:updateResourceState();
+  //FIXME:finilize();
+
+  bool isOn();
+  void turnOn();
+  void turnOff();
+  void setName(string name);
+  const char *getName();
+  virtual xbt_dict_t getProperties();
+
+  ModelPtr getModel() {return p_model;};
+  virtual e_surf_resource_state_t getState();
+  virtual void setState(e_surf_resource_state_t state);
+  void printModel() { std::cout << p_model->getName() << "<<plop"<<std::endl;};
+  void *p_resource;
+  const char *m_name;
+  xbt_dict_t m_properties;
+  ModelPtr p_model;
+  e_surf_resource_state_t p_stateCurrent;
+
+protected:
+
+private:
+  bool m_running;  
+};
+
+class ResourceLmm: virtual public Resource {
+public:
+  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);
+  lmm_constraint_t p_constraint;
+  tmgr_trace_event_t p_stateEvent;
+  s_surf_metric_t p_power;
+};
+
+/**********
+ * Action *
+ **********/
+
+class Action {
+public:
+  Action();
+  Action(ModelPtr model, double cost, bool failed);
+  virtual ~Action();
+  
+  s_xbt_swag_hookup_t p_stateHookup;
+
+  e_surf_action_state_t getState(); /**< get the state*/
+  virtual void setState(e_surf_action_state_t state); /**< Change state*/
+  double getStartTime(); /**< Return the start time of an action */
+  double getFinishTime(); /**< Return the finish time of an action */
+  void setData(void* data);
+
+  void ref();
+  virtual int unref();     /**< 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. */
+  virtual void cancel();     /**< Cancel a running action */
+  virtual void recycle();     /**< Recycle an action */
+  
+  virtual void suspend()=0;     /**< Suspend an action */
+  virtual void resume()=0;     /**< Resume a suspended action */
+  virtual bool isSuspended()=0;     /**< Return whether an action is suspended */
+  virtual void setMaxDuration(double duration)=0;     /**< Set the max duration of an action*/
+  virtual void setPriority(double priority)=0;     /**< Set the priority of an action */
+#ifdef HAVE_TRACING
+  void setCategory(const char *category); /**< Set the category of an action */
+#endif
+  virtual double getRemains();     /**< Get the remains of an action */
+#ifdef HAVE_LATENCY_BOUND_TRACKING
+  int getLatencyLimited();     /**< Return 1 if action is limited by latency, 0 otherwise */
+#endif
+
+  xbt_swag_t p_stateSet;
+
+  double m_priority; /**< priority (1.0 by default) */
+  double m_bound;              /**< the capping of the CPU use  */
+  bool m_failed;
+  double m_start; /**< start time  */
+  double m_finish; /**< finish time : this is modified during the run and fluctuates until the task is completed */
+  double m_remains; /**< How much of that cost remains to be done in the currently running task */
+  #ifdef HAVE_LATENCY_BOUND_TRACKING
+  int m_latencyLimited;               /**< Set to 1 if is limited by latency, 0 otherwise */
+  #endif
+  double m_maxDuration; /*< max_duration (may fluctuate until the task is completed) */  
+  char *p_category;               /**< tracing category for categorized resource utilization monitoring */  
+  int    m_cost;
+  void *p_data; /**< for your convenience */
+protected:
+  ModelPtr p_model;  
+  int    m_refcount;
+#ifdef HAVE_TRACING
+#endif
+  e_UM_t p_updateMechanism;
+
+private:
+  int resourceUsed(void *resource_id);
+  /* Share the resources to the actions and return in how much time
+     the next action may terminate */
+  double shareResources(double now);
+  /* Update the actions' state */
+  void updateActionsState(double now, double delta);
+  void updateResourceState(void *id, tmgr_trace_event_t event_type,
+                                 double value, double time);
+
+  xbt_swag_t p_modifiedSet;
+  xbt_heap_t p_actionHeap;
+  int m_selectiveUpdate;
+};
+
+//FIXME:REMOVE
+void surf_action_lmm_update_index_heap(void *action, int i);
+
+class ActionLmm: virtual public Action {
+public:
+  ActionLmm() : m_suspended(false) {
+       p_actionListHookup.prev = 0;
+       p_actionListHookup.next = 0;
+  };
+  ActionLmm(ModelPtr model, double cost, bool failed) : m_suspended(false) {
+       p_actionListHookup.prev = 0;
+       p_actionListHookup.next = 0;
+  };
+
+  virtual void updateRemainingLazy(double now);
+  void heapInsert(xbt_heap_t heap, double key, enum heap_action_type hat);
+  void heapRemove(xbt_heap_t heap);
+  double getRemains();     /**< Get the remains of an action */
+  void updateIndexHeap(int i);
+
+  virtual int unref();
+  void cancel();
+  void suspend();
+  void resume();
+  bool isSuspended();
+  void setMaxDuration(double duration);
+  void setPriority(double priority);
+  void gapRemove();
+
+  lmm_variable_t p_variable;
+  s_xbt_swag_hookup_t p_actionListHookup;
+  int m_indexHeap;
+  double m_lastUpdate;
+  double m_lastValue;
+  enum heap_action_type m_hat;
+  int m_suspended;
+};
+
+#endif /* SURF_MODEL_H_ */
index 86e752d..0189b49 100644 (file)
@@ -77,7 +77,7 @@ void *surf_action_new(size_t size, double cost, surf_model_t model,
   action->max_duration = NO_MAX_DURATION;
   action->start = surf_get_clock();
   action->finish = -1.0;
-  action->model_type = model;
+  action->model_obj = model;
 #ifdef HAVE_TRACING
   action->category = NULL;
 #endif
@@ -94,7 +94,7 @@ void *surf_action_new(size_t size, double cost, surf_model_t model,
 
 e_surf_action_state_t surf_action_state_get(surf_action_t action)
 {
-  surf_action_state_t action_state = &(action->model_type->states);
+  surf_action_state_t action_state = &(action->model_obj->states);
 
   if (action->state_set == action_state->ready_action_set)
     return SURF_ACTION_READY;
@@ -127,7 +127,7 @@ XBT_INLINE void surf_action_free(surf_action_t * action)
 void surf_action_state_set(surf_action_t action,
                            e_surf_action_state_t state)
 {
-  surf_action_state_t action_state = &(action->model_type->states);
+  surf_action_state_t action_state = &(action->model_obj->states);
   XBT_IN("(%p,%s)", action, surf_action_state_names[state]);
   xbt_swag_remove(action, action->state_set);
 
@@ -190,7 +190,7 @@ void surf_action_lmm_heap_remove(xbt_heap_t heap, surf_action_lmm_t action)
 
 void surf_action_cancel(surf_action_t action)
 {
-  surf_model_t model = action->model_type;
+  surf_model_t model = action->model_obj;
   surf_action_state_set(action, SURF_ACTION_FAILED);
   if (model->model_private->update_mechanism == UM_LAZY) {
     xbt_swag_remove(action, model->model_private->modified_set);
@@ -201,7 +201,7 @@ void surf_action_cancel(surf_action_t action)
 
 int surf_action_unref(surf_action_t action)
 {
-  surf_model_t model = action->model_type;
+  surf_model_t model = action->model_obj;
   action->refcount--;
   if (!action->refcount) {
     xbt_swag_remove(action, action->state_set);
@@ -224,7 +224,7 @@ int surf_action_unref(surf_action_t action)
 
 void surf_action_suspend(surf_action_t action)
 {
-  surf_model_t model = action->model_type;
+  surf_model_t model = action->model_obj;
   XBT_IN("(%p)", action);
   if (((surf_action_lmm_t) action)->suspended != 2) {
     lmm_update_variable_weight(model->model_private->maxmin_system,
@@ -239,7 +239,7 @@ void surf_action_suspend(surf_action_t action)
 
 void surf_action_resume(surf_action_t action)
 {
-  surf_model_t model = action->model_type;
+  surf_model_t model = action->model_obj;
   XBT_IN("(%p)", action);
   if (((surf_action_lmm_t) action)->suspended != 2) {
     lmm_update_variable_weight(model->model_private->maxmin_system,
@@ -259,7 +259,7 @@ int surf_action_is_suspended(surf_action_t action)
 
 void surf_action_set_max_duration(surf_action_t action, double duration)
 {
-  surf_model_t model = action->model_type;
+  surf_model_t model = action->model_obj;
   XBT_IN("(%p,%g)", action, duration);
   action->max_duration = duration;
   if (model->model_private->update_mechanism == UM_LAZY)      // remove action from the heap
@@ -269,7 +269,7 @@ void surf_action_set_max_duration(surf_action_t action, double duration)
 
 void surf_action_set_priority(surf_action_t action, double priority)
 {
-  surf_model_t model = action->model_type;
+  surf_model_t model = action->model_obj;
   XBT_IN("(%p,%g)", action, priority);
   action->priority = priority;
   lmm_update_variable_weight(model->model_private->maxmin_system,
@@ -281,6 +281,18 @@ void surf_action_set_priority(surf_action_t action, double priority)
   XBT_OUT();
 }
 
+void surf_action_set_bound(surf_action_t action, double bound)
+{
+  surf_model_t model = action->model_obj;
+  XBT_IN("(%p,%g)", action, bound);
+  action->bound = bound;
+  lmm_update_variable_bound(model->model_private->maxmin_system, ((surf_action_lmm_t) action)->variable, bound);
+
+  if (model->model_private->update_mechanism == UM_LAZY)
+    surf_action_lmm_heap_remove(model->model_private->action_heap, (surf_action_lmm_t) action);
+  XBT_OUT();
+}
+
 #ifdef HAVE_TRACING
 void surf_action_set_category(surf_action_t action,
                                     const char *category)
@@ -294,7 +306,7 @@ void surf_action_set_category(surf_action_t action,
 void generic_update_action_remaining_lazy( surf_action_lmm_t action, double now)
 {
   double delta = 0.0;
-  surf_model_t model = action->generic_action.model_type;
+  surf_model_t model = action->generic_action.model_obj;
 
   if(model == surf_network_model)
   {
@@ -319,7 +331,7 @@ void generic_update_action_remaining_lazy( surf_action_lmm_t action, double now)
         action->last_value * delta);
 
 #ifdef HAVE_TRACING
-    if (model == surf_cpu_model && TRACE_is_enabled()) {
+    if (model->type == SURF_MODEL_TYPE_CPU && TRACE_is_enabled()) {
       surf_resource_t cpu =
           lmm_constraint_id(lmm_get_cnst_from_var
               (model->model_private->maxmin_system,
@@ -363,7 +375,7 @@ void generic_update_action_remaining_lazy( surf_action_lmm_t action, double now)
 double surf_action_get_remains(surf_action_t action)
 {
   XBT_IN("(%p)", action);
-  surf_model_t model = action->model_type;
+  surf_model_t model = action->model_obj;
   /* update remains before return it */
   if (model->model_private->update_mechanism == UM_LAZY)      /* update remains before return it */
     generic_update_action_remaining_lazy((surf_action_lmm_t)action, surf_get_clock());
@@ -377,7 +389,7 @@ double surf_action_get_remains(surf_action_t action)
  */
 void update_resource_energy(surf_model_t model, surf_action_lmm_t action)
 {
-    if(model == surf_cpu_model){
+    if(model->type == SURF_MODEL_TYPE_CPU){
         cpu_Cas01_t cpu_model = (cpu_Cas01_t)lmm_constraint_id(lmm_get_cnst_from_var
                                                                                  (model->model_private->maxmin_system,
                                                                                                  action->variable, 0));
@@ -401,7 +413,7 @@ void generic_update_actions_state_lazy(double now, double delta, surf_model_t mo
     XBT_DEBUG("Something happened to action %p", action);
 #ifdef HAVE_TRACING
     if (TRACE_is_enabled()) {
-      if(model == surf_cpu_model){
+      if(model->type == SURF_MODEL_TYPE_CPU){
       surf_resource_t cpu =
           lmm_constraint_id(lmm_get_cnst_from_var
                             (model->model_private->maxmin_system,
@@ -433,7 +445,7 @@ void generic_update_actions_state_lazy(double now, double delta, surf_model_t mo
     }
 #endif
 
-    if(model == surf_cpu_model){
+    if(model->type == SURF_MODEL_TYPE_CPU){
       action->generic_action.finish = surf_get_clock();
 
       update_resource_energy(model, action);
@@ -471,7 +483,7 @@ void generic_update_actions_state_lazy(double now, double delta, surf_model_t mo
     }
   }
 #ifdef HAVE_TRACING
-  if (TRACE_is_enabled() && model == surf_cpu_model) {
+  if (TRACE_is_enabled() && model->type == SURF_MODEL_TYPE_CPU) {
     //defining the last timestamp that we can safely dump to trace file
     //without losing the event ascending order (considering all CPU's)
     double smaller = -1;
diff --git a/src/surf/surf_interface.cpp b/src/surf/surf_interface.cpp
new file mode 100644 (file)
index 0000000..b23ea89
--- /dev/null
@@ -0,0 +1,520 @@
+#include "surf.hpp"
+#include "workstation.hpp"
+#include "vm_workstation.hpp"
+#include "network.hpp"
+#include "surf_routing_cluster.hpp"
+#include "instr/instr_private.h"
+
+XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(surf_kernel);
+
+/*********
+ * TOOLS *
+ *********/
+extern double NOW;
+
+static CpuPtr get_casted_cpu(surf_resource_t resource){
+  return dynamic_cast<CpuPtr>(static_cast<ResourcePtr>(surf_cpu_resource_priv(resource)));
+}
+
+static WorkstationCLM03Ptr get_casted_workstation(surf_resource_t resource){
+  return dynamic_cast<WorkstationCLM03Ptr>(static_cast<ResourcePtr>(surf_workstation_resource_priv(resource)));
+}
+
+static WorkstationVM2013Ptr get_casted_vm_workstation(surf_resource_t resource){
+  return dynamic_cast<WorkstationVM2013Ptr>(static_cast<ResourcePtr>(surf_workstation_resource_priv(resource)));
+}
+
+char *surf_routing_edge_name(sg_routing_edge_t edge){
+  return edge->p_name;
+}
+
+#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;
+  ResourcePtr resource = NULL;
+  ModelPtr 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;
+  ResourcePtr resource = NULL;
+  ModelPtr model = NULL;
+  tmgr_trace_event_t event = NULL;
+  unsigned int iter;
+
+  if(!host_that_restart)
+    host_that_restart = xbt_dynar_new(sizeof(char*), NULL);
+
+  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_invoke));
+  }
+  surf_min_index = 0;
+
+  /* sequential version */
+  xbt_dynar_foreach(model_list_invoke, iter, model) {
+    surf_share_resources(static_cast<ModelPtr>(model));
+  }
+
+  unsigned i;
+  for (i = 0; i < xbt_dynar_length(model_list_invoke); 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() || xbt_dict_get_or_null(watched_hosts_lib, resource->m_name)) {
+        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->m_name, 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;
+  /* FIXME: model_list or model_list_invoke? revisit here later */
+  /* 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 *
+ *********/
+
+surf_model_t surf_resource_model(const void *host, int level) {
+  /* If level is SURF_WKS_LEVEL, ws is a workstation_CLM03 object. It has
+   * surf_resource at the generic_resource field. */
+  ResourcePtr ws = static_cast<ResourcePtr>(xbt_lib_get_level((xbt_dictelm_t) host, level));
+  return ws->p_model;
+}
+
+void *surf_as_cluster_get_backbone(AS_t as){
+  return static_cast<AsClusterPtr>(as)->p_backbone;
+}
+
+void surf_as_cluster_set_backbone(AS_t as, void* backbone){
+  static_cast<AsClusterPtr>(as)->p_backbone = dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(backbone));
+}
+
+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 static_cast<ActionPtr>(model->executeParallelTask(workstation_nb, workstation_list, computation_amount, communication_amount, rate));
+}
+
+surf_action_t surf_workstation_model_communicate(surf_workstation_model_t model, surf_resource_t src, surf_resource_t dst, double size, double rate){
+  return model->communicate(get_casted_workstation(src), get_casted_workstation(dst), size, rate);
+}
+
+xbt_dynar_t surf_workstation_model_get_route(surf_workstation_model_t model,
+                                                    surf_resource_t src, surf_resource_t dst){
+  return model->getRoute(get_casted_workstation(src), get_casted_workstation(dst));
+}
+
+void surf_vm_workstation_model_create(const char *name, surf_resource_t ind_phys_host){
+  surf_vm_workstation_model->createResource(name, ind_phys_host);
+}
+
+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){
+  return model->communicate(src, dst, size, rate);
+}
+
+const char *surf_resource_name(surf_cpp_resource_t resource){
+  return resource->m_name;
+}
+
+xbt_dict_t surf_resource_get_properties(surf_cpp_resource_t resource){
+  return resource->getProperties();
+}
+
+e_surf_resource_state_t surf_resource_get_state(surf_cpp_resource_t resource){
+  return resource->getState();
+}
+
+void surf_resource_set_state(surf_cpp_resource_t resource, e_surf_resource_state_t state){
+  resource->setState(state);
+}
+
+surf_action_t surf_workstation_sleep(surf_resource_t resource, double duration){
+  return get_casted_workstation(resource)->sleep(duration);
+}
+
+double surf_workstation_get_speed(surf_resource_t resource, double load){
+  return get_casted_workstation(resource)->getSpeed(load);
+}
+
+double surf_workstation_get_available_speed(surf_resource_t resource){
+  return get_casted_workstation(resource)->getAvailableSpeed();
+}
+
+int surf_workstation_get_core(surf_resource_t resource){
+  return get_casted_workstation(resource)->getCore();
+}
+
+surf_action_t surf_workstation_execute(surf_resource_t resource, double size){
+  return get_casted_workstation(resource)->execute(size);
+}
+
+double surf_workstation_get_current_power_peak(surf_resource_t resource){
+  return get_casted_workstation(resource)->getCurrentPowerPeak();
+}
+
+double surf_workstation_get_power_peak_at(surf_resource_t resource, int pstate_index){
+  return get_casted_workstation(resource)->getPowerPeakAt(pstate_index);
+}
+
+int surf_workstation_get_nb_pstates(surf_resource_t resource){
+  return get_casted_workstation(resource)->getNbPstates();
+}
+
+void surf_workstation_set_power_peak_at(surf_resource_t resource, int pstate_index){
+  return get_casted_workstation(resource)->setPowerPeakAt(pstate_index);
+}
+
+double surf_workstation_get_consumed_energy(surf_resource_t resource){
+  return get_casted_workstation(resource)->getConsumedEnergy();
+}
+
+xbt_dict_t surf_workstation_get_storage_list(surf_resource_t workstation){
+  return get_casted_workstation(workstation)->getStorageList();
+}
+
+surf_action_t surf_workstation_open(surf_resource_t workstation, const char* mount, const char* path){
+  return get_casted_workstation(workstation)->open(mount, path);
+}
+
+surf_action_t surf_workstation_close(surf_resource_t workstation, surf_file_t fd){
+  return get_casted_workstation(workstation)->close(fd);
+}
+
+int surf_workstation_unlink(surf_resource_t workstation, surf_file_t fd){
+  return get_casted_workstation(workstation)->unlink(fd);
+}
+
+surf_action_t surf_workstation_ls(surf_resource_t workstation, const char* mount, const char *path){
+  return get_casted_workstation(workstation)->ls(mount, path);
+}
+
+size_t surf_workstation_get_size(surf_resource_t workstation, surf_file_t fd){
+  return get_casted_workstation(workstation)->getSize(fd);
+}
+
+surf_action_t surf_workstation_read(surf_resource_t resource, surf_file_t fd, sg_storage_size_t size){
+  return get_casted_workstation(resource)->read(fd, size);
+}
+
+surf_action_t surf_workstation_write(surf_resource_t resource, surf_file_t fd, sg_storage_size_t size){
+  return get_casted_workstation(resource)->write(fd, size);
+}
+
+xbt_dynar_t surf_workstation_get_info(surf_resource_t resource, surf_file_t fd){
+  return get_casted_workstation(resource)->getInfo(fd);
+}
+
+sg_storage_size_t surf_workstation_get_free_size(surf_resource_t resource, const char* name){
+  return get_casted_workstation(resource)->getFreeSize(name);
+}
+
+sg_storage_size_t surf_workstation_get_used_size(surf_resource_t resource, const char* name){
+  return get_casted_workstation(resource)->getUsedSize(name);
+}
+
+xbt_dynar_t surf_workstation_get_vms(surf_resource_t resource){
+  return get_casted_workstation(resource)->getVms();
+}
+
+void surf_workstation_get_params(surf_resource_t resource, ws_params_t params){
+  get_casted_workstation(resource)->getParams(params);
+}
+
+void surf_workstation_set_params(surf_resource_t resource, ws_params_t params){
+  get_casted_workstation(resource)->setParams(params);
+}
+
+void surf_vm_workstation_destroy(surf_resource_t resource){
+  delete get_casted_vm_workstation(resource);
+}
+
+void surf_vm_workstation_suspend(surf_resource_t resource){
+  get_casted_vm_workstation(resource)->suspend();
+}
+
+void surf_vm_workstation_resume(surf_resource_t resource){
+  get_casted_vm_workstation(resource)->resume();
+}
+
+void surf_vm_workstation_save(surf_resource_t resource){
+  get_casted_vm_workstation(resource)->save();
+}
+
+void surf_vm_workstation_restore(surf_resource_t resource){
+  get_casted_vm_workstation(resource)->restore();
+}
+
+void surf_vm_workstation_migrate(surf_resource_t resource, surf_resource_t ind_vm_ws_dest){
+  get_casted_vm_workstation(resource)->migrate(ind_vm_ws_dest);
+}
+
+surf_resource_t surf_vm_workstation_get_pm(surf_resource_t resource){
+  return get_casted_vm_workstation(resource)->getPm();
+}
+
+void surf_vm_workstation_set_bound(surf_resource_t resource, double bound){
+  return get_casted_vm_workstation(resource)->setBound(bound);
+}
+
+void surf_vm_workstation_set_affinity(surf_resource_t resource, surf_resource_t cpu, unsigned long mask){
+  return get_casted_vm_workstation(resource)->setAffinity(dynamic_cast<CpuLmmPtr>(get_casted_cpu(cpu)), mask);
+}
+
+int surf_network_link_is_shared(surf_cpp_resource_t link){
+  return dynamic_cast<NetworkCm02LinkPtr>(link)->isShared();
+}
+
+double surf_network_link_get_bandwidth(surf_cpp_resource_t link){
+  return dynamic_cast<NetworkCm02LinkPtr>(link)->getBandwidth();
+}
+
+double surf_network_link_get_latency(surf_cpp_resource_t link){
+  return dynamic_cast<NetworkCm02LinkPtr>(link)->getLatency();
+}
+
+xbt_dict_t surf_storage_get_content(surf_resource_t resource){
+  return dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(surf_storage_resource_priv(resource)))->getContent();
+}
+
+sg_storage_size_t surf_storage_get_size(surf_resource_t resource){
+  return dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(surf_storage_resource_priv(resource)))->getSize();
+}
+
+void surf_storage_rename(surf_resource_t resource, const char* src, const char* dest){
+  dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(surf_storage_resource_priv(resource)))->rename(src, dest);
+}
+
+surf_action_t surf_cpu_execute(surf_resource_t cpu, double size){
+  return get_casted_cpu(cpu)->execute(size);
+}
+
+surf_action_t surf_cpu_sleep(surf_resource_t cpu, double duration){
+  return get_casted_cpu(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->getRemains();
+}
+
+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->resume();
+}
+
+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;
+}
+
+void surf_cpu_action_set_affinity(surf_action_t action, surf_resource_t cpu, unsigned long mask) {
+  dynamic_cast<CpuActionLmmPtr>(action)->setAffinity( dynamic_cast<CpuLmmPtr>(get_casted_cpu(cpu)), mask);
+}
+
+void surf_cpu_action_set_bound(surf_action_t action, double bound) {
+  dynamic_cast<CpuActionLmmPtr>(action)->setBound(bound);
+}
+
+surf_file_t surf_storage_action_get_file(surf_action_t action){
+  return dynamic_cast<StorageActionPtr>(action)->p_file;
+}
+
+xbt_dict_t surf_storage_action_get_ls_dict(surf_action_t action){
+  return dynamic_cast<StorageActionPtr>(action)->p_lsDict;
+}
+
+
diff --git a/src/surf/surf_model.c b/src/surf/surf_model.c
deleted file mode 100644 (file)
index 3cb98f1..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-
-/* Copyright (c) 2009-2012. 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_private.h"
-#include "xbt/dict.h"
-
-static void void_die_impossible_paction(surf_action_t action)
-{
-  DIE_IMPOSSIBLE;
-}
-
-static int int_die_impossible_paction(surf_action_t action)
-{
-  DIE_IMPOSSIBLE;
-  return -1;
-}
-
-/** @brief initialize common datastructures to all models */
-surf_model_t surf_model_init(void)
-{
-  s_surf_action_t action;
-  surf_model_t model = xbt_new0(s_surf_model_t, 1);
-
-  model->model_private = xbt_new0(s_surf_model_private_t, 1);
-
-  model->states.ready_action_set =
-      xbt_swag_new(xbt_swag_offset(action, state_hookup));
-  model->states.running_action_set =
-      xbt_swag_new(xbt_swag_offset(action, state_hookup));
-  model->states.failed_action_set =
-      xbt_swag_new(xbt_swag_offset(action, state_hookup));
-  model->states.done_action_set =
-      xbt_swag_new(xbt_swag_offset(action, state_hookup));
-
-  model->action_unref = int_die_impossible_paction;
-  model->action_cancel = void_die_impossible_paction;
-  model->action_recycle = void_die_impossible_paction;
-
-  model->action_state_get = surf_action_state_get;
-  model->action_state_set = surf_action_state_set;
-  model->action_get_start_time = surf_action_get_start_time;
-  model->action_get_finish_time = surf_action_get_finish_time;
-  model->action_data_set = surf_action_data_set;
-
-  model->model_private->modified_set = NULL;
-  model->model_private->action_heap = NULL;
-  model->model_private->update_mechanism = UM_UNDEFINED;
-  model->model_private->selective_update = 0;
-
-  return model;
-}
-
-/** @brief finalize common datastructures to all models */
-void surf_model_exit(surf_model_t model)
-{
-  xbt_swag_free(model->states.ready_action_set);
-  xbt_swag_free(model->states.running_action_set);
-  xbt_swag_free(model->states.failed_action_set);
-  xbt_swag_free(model->states.done_action_set);
-  free(model->model_private);
-  free(model);
-}
index 10066b0..4240c00 100644 (file)
 
 #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];
@@ -27,99 +31,18 @@ typedef enum {
   UM_UNDEFINED
 } e_UM_t;
 
-typedef struct surf_model_private {
-  int (*resource_used) (void *resource_id);
-  /* Share the resources to the actions and return in how much time
-     the next action may terminate */
-  double (*share_resources) (double now);
-  /* Update the actions' state */
-  void (*update_actions_state) (double now, double delta);
-  void (*update_resource_state) (void *id, tmgr_trace_event_t event_type,
-                                 double value, double time);
-  void (*finalize) (void);
-
-  lmm_system_t maxmin_system;
-  e_UM_t update_mechanism;
-  xbt_swag_t modified_set;
-  xbt_heap_t action_heap;
-  int selective_update;
-
-} s_surf_model_private_t;
-
-double generic_maxmin_share_resources(xbt_swag_t running_actions,
-                                      size_t offset,
-                                      lmm_system_t sys,
-                                      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 */
-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 */
-
-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);
-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);
-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);
-void surf_action_set_max_duration(surf_action_t action, double duration);
-void surf_action_set_priority(surf_action_t action, double priority);
-#ifdef HAVE_TRACING
-void surf_action_set_category(surf_action_t action,
-                                    const char *category);
-#endif
-double surf_action_get_remains(surf_action_t action);
-void update_resource_energy(surf_model_t model, surf_action_lmm_t action);
-void generic_update_action_remaining_lazy( surf_action_lmm_t action, double now);
-void generic_update_actions_state_lazy(double now, double delta, surf_model_t model);
-void generic_update_actions_state_full(double now, double delta, surf_model_t model);
 
 FILE *surf_fopen(const char *name, const char *mode);
 
 extern tmgr_history_t history;
 
-//void surf_config_init(int *argc, char **argv);
-//void surf_config_finalize(void);
-//void surf_config(const char *name, va_list pa);
-
-void net_action_recycle(surf_action_t action);
-#ifdef HAVE_LATENCY_BOUND_TRACKING
-int net_get_link_latency_limited(surf_action_t action);
-#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);
 
-typedef struct s_routing_edge {
-  AS_t rc_component;
-  e_surf_network_element_type_t rc_type;
-  int id;
-  char *name;
-} s_routing_edge_t;
-
-/*
- * Link of lenght 1, alongside with its source and destination. This is mainly usefull in the bindings to gtnets and ns3
- */
-typedef struct s_onelink {
-  sg_routing_edge_t src;
-  sg_routing_edge_t dst;
-  void *link_ptr;
-} s_onelink_t, *onelink_t;
-
 /**
  * Routing logic
  */
@@ -138,47 +61,10 @@ typedef enum {
   SURF_ROUTING_RECURSIVE   /**< Recursive case: also return gateway informations */
 } e_surf_routing_hierarchy_t;
 
-typedef struct s_as {
-  xbt_dynar_t index_network_elm;
-  xbt_dict_t bypassRoutes;    /* store bypass routes */
-  routing_model_description_t model_desc;
-  e_surf_routing_hierarchy_t hierarchy;
-  char *name;
-  struct s_as *routing_father;
-  xbt_dict_t routing_sons;
-  sg_routing_edge_t net_elem;
-  xbt_dynar_t link_up_down_list;
-
-  void (*get_route_and_latency) (AS_t as, sg_routing_edge_t src, sg_routing_edge_t dst, sg_platf_route_cbarg_t into, double *latency);
-
-  xbt_dynar_t(*get_onelink_routes) (AS_t as);
-  void (*get_graph) (xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges, AS_t rc);
-  sg_platf_route_cbarg_t(*get_bypass_route) (AS_t as, sg_routing_edge_t src, sg_routing_edge_t dst, double *lat);
-  void (*finalize) (AS_t as);
-
-
-  /* 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 (*parse_PU) (AS_t as, sg_routing_edge_t elm); /* A host or a router, whatever */
-  int (*parse_AS) (AS_t as, sg_routing_edge_t elm);
-  void (*parse_route) (AS_t as, sg_platf_route_cbarg_t route);
-  void (*parse_ASroute) (AS_t as, sg_platf_route_cbarg_t route);
-  void (*parse_bypassroute) (AS_t as, sg_platf_route_cbarg_t e_route);
-
-} s_as_t;
-
-struct s_routing_platf {
-  AS_t root;
-  void *loopback;
-  xbt_dynar_t last_route;
-  xbt_dynar_t(*get_onelink_routes) (void);
-};
-
 XBT_PUBLIC(void) routing_model_create(void *loopback);
 XBT_PUBLIC(void) routing_exit(void);
 XBT_PUBLIC(void) storage_register_callbacks(void);
+
 /* ***************************************** */
 /* TUTORIAL: New TAG                         */
 XBT_PUBLIC(void) gpu_register_callbacks(void);
@@ -196,8 +82,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;
 
@@ -206,5 +92,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 */
similarity index 82%
rename from src/surf/surf_routing.c
rename to src/surf/surf_routing.cpp
index ec7334f..d667710 100644 (file)
@@ -1,14 +1,15 @@
-/* Copyright (c) 2009-2013. The SimGrid Team.
+/* 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.hpp"
+#include "surf_routing_private.hpp"
+
 #include "simgrid/platf_interface.h"    // platform creation API internal interface
 #include "simgrid/sg_config.h"
 
-#include "surf_routing_private.h"
-#include "surf/surf_routing.h"
 #include "surf/surfxml_parse_values.h"
 
 /**
@@ -46,24 +47,28 @@ 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
  */
-sg_routing_edge_t sg_routing_edge_by_name_or_null(const char *name) {
-    sg_routing_edge_t net_elm = xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL);
-    if(!net_elm) net_elm = xbt_lib_get_or_null(as_router_lib, name, ROUTING_ASR_LEVEL);
+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 */
-routing_platf_t routing_platf = NULL;
-AS_t current_routing = NULL;
+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 */
@@ -108,11 +113,10 @@ struct s_model_type routing_models[] = {
  */
 static void parse_S_host_link(sg_platf_host_link_cbarg_t host)
 {
-  sg_routing_edge_t info = NULL;
-  info = 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->model_desc == &routing_models[SURF_MODEL_CLUSTER] ||
-      current_routing->model_desc == &routing_models[SURF_MODEL_VIVALDI],
+  RoutingEdgePtr info = static_cast<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;
@@ -124,16 +128,16 @@ static void parse_S_host_link(sg_platf_host_link_cbarg_t host)
   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->link_up_down_list)
-    current_routing->link_up_down_list = xbt_dynar_new(sizeof(s_surf_parsing_link_up_down_t),NULL);
+  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->link_up_down_list) > info->id &&
-      xbt_dynar_get_as(current_routing->link_up_down_list,info->id,void*))
+  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->name,info->id);
-  xbt_dynar_set_as(current_routing->link_up_down_list,info->id,s_surf_parsing_link_up_down_t,link_up_down);
+  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);
 }
 
 /**
@@ -141,19 +145,18 @@ static void parse_S_host_link(sg_platf_host_link_cbarg_t host)
  */
 static void parse_S_host(sg_platf_host_cbarg_t host)
 {
-  sg_routing_edge_t info = NULL;
-  if (current_routing->hierarchy == SURF_ROUTING_NULL)
-    current_routing->hierarchy = SURF_ROUTING_BASE;
+  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);
 
-  info = xbt_new0(s_routing_edge_t, 1);
-  info->rc_component = current_routing;
-  info->rc_type = SURF_NETWORK_ELEMENT_HOST;
-  info->name = xbt_strdup(host->id);
-  info->id = current_routing->parse_PU(current_routing, (void *) info);
+  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->id);
+  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);
@@ -185,20 +188,19 @@ static void parse_S_host(sg_platf_host_cbarg_t host)
  */
 static void parse_S_router(sg_platf_router_cbarg_t router)
 {
-  sg_routing_edge_t info = NULL;
-  if (current_routing->hierarchy == SURF_ROUTING_NULL)
-    current_routing->hierarchy = SURF_ROUTING_BASE;
+  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);
 
-  info = xbt_new0(s_routing_edge_t, 1);
-  info->rc_component = current_routing;
-  info->rc_type = SURF_NETWORK_ELEMENT_ROUTER;
-  info->name = xbt_strdup(router->id);
-  info->id = current_routing->parse_PU(current_routing, (void *) info);
+  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->id);
+  XBT_DEBUG("Having set name '%s' id '%d'", router->id, info->m_id);
 
   if (router->coord && strcmp(router->coord, "")) {
     unsigned int cursor;
@@ -225,11 +227,11 @@ static void parse_S_router(sg_platf_router_cbarg_t router)
  */
 static void parse_E_route(sg_platf_route_cbarg_t route)
 {
-  xbt_assert(current_routing->parse_route,
+  /*FIXME:REMOVE:xbt_assert(current_routing->parse_route,
              "no defined method \"set_route\" in \"%s\"",
-             current_routing->name);
+             current_routing->name);*/
 
-  current_routing->parse_route(current_routing, route);
+  current_routing->parseRoute(route);
 }
 
 /**
@@ -237,10 +239,10 @@ static void parse_E_route(sg_platf_route_cbarg_t route)
  */
 static void parse_E_ASroute(sg_platf_route_cbarg_t ASroute)
 {
-  xbt_assert(current_routing->parse_ASroute,
+  /*FIXME:REMOVE:xbt_assert(current_routing->parse_ASroute,
              "no defined method \"set_ASroute\" in \"%s\"",
-             current_routing->name);
-  current_routing->parse_ASroute(current_routing, ASroute);
+             current_routing->name);*/
+  current_routing->parseASroute(ASroute);
 }
 
 /**
@@ -248,11 +250,11 @@ static void parse_E_ASroute(sg_platf_route_cbarg_t ASroute)
  */
 static void parse_E_bypassRoute(sg_platf_route_cbarg_t route)
 {
-  xbt_assert(current_routing->parse_bypassroute,
+  /*FIXME:REMOVE:xbt_assert(current_routing->parse_bypassroute,
              "Bypassing mechanism not implemented by routing '%s'",
-             current_routing->name);
+             current_routing->name);*/
 
-  current_routing->parse_bypassroute(current_routing, route);
+  current_routing->parseBypassroute(route);
 }
 
 /**
@@ -260,10 +262,10 @@ static void parse_E_bypassRoute(sg_platf_route_cbarg_t route)
  */
 static void parse_E_bypassASroute(sg_platf_route_cbarg_t ASroute)
 {
-  xbt_assert(current_routing->parse_bypassroute,
+  /*FIXME:REMOVE:xbt_assert(current_routing->parse_bypassroute,
              "Bypassing mechanism not implemented by routing '%s'",
-             current_routing->name);
-  current_routing->parse_bypassroute(current_routing, ASroute);
+             current_routing->name);*/
+  current_routing->parseBypassroute(ASroute);
 }
 
 static void routing_parse_trace(sg_platf_trace_cbarg_t trace)
@@ -336,7 +338,6 @@ static void routing_parse_trace_connect(sg_platf_trace_connect_cbarg_t trace_con
 void routing_AS_begin(sg_platf_AS_cbarg_t AS)
 {
   XBT_DEBUG("routing_AS_begin");
-  AS_t new_as;
   routing_model_description_t model = NULL;
 
   xbt_assert(!xbt_lib_get_or_null
@@ -361,50 +362,50 @@ void routing_AS_begin(sg_platf_AS_cbarg_t AS)
   }
 
   /* make a new routing component */
-  new_as = (AS_t) model->create();
-  new_as->model_desc = model;
-  new_as->hierarchy = SURF_ROUTING_NULL;
-  new_as->name = xbt_strdup(AS->id);
+  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);
 
-  sg_routing_edge_t info = NULL;
-  info = xbt_new0(s_routing_edge_t, 1);
+  RoutingEdgePtr info = new RoutingEdge();
 
-  if (current_routing == NULL && routing_platf->root == NULL) {
+  if (current_routing == NULL && routing_platf->p_root == NULL) {
 
     /* it is the first one */
-    new_as->routing_father = NULL;
-    routing_platf->root = new_as;
-    info->id = -1;
-  } else if (current_routing != NULL && routing_platf->root != NULL) {
+    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->routing_sons, AS->id),
+               (current_routing->p_routingSons, AS->id),
                "The AS \"%s\" already exists", AS->id);
     /* it is a part of the tree */
-    new_as->routing_father = current_routing;
+    new_as->p_routingFather = current_routing;
     /* set the father behavior */
-    if (current_routing->hierarchy == SURF_ROUTING_NULL)
-      current_routing->hierarchy = SURF_ROUTING_RECURSIVE;
+    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->routing_sons, AS->id,
+    xbt_dict_set(current_routing->p_routingSons, AS->id,
                  (void *) new_as, NULL);
     /* add to the father element list */
-    info->id = current_routing->parse_AS(current_routing, (void *) info);
+    info->m_id = current_routing->parseAS(info);
   } else {
     THROWF(arg_error, 0, "All defined components must be belong to a AS");
   }
 
-  info->rc_component = new_as->routing_father;
-  info->rc_type = SURF_NETWORK_ELEMENT_AS;
-  info->name = new_as->name;
+  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->name, ROUTING_ASR_LEVEL,
+  xbt_lib_set(as_router_lib, info->p_name, ROUTING_ASR_LEVEL,
               (void *) info);
-  XBT_DEBUG("Having set name '%s' id '%d'",new_as->name,info->id);
+  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->net_elem = info;
+  current_routing->p_netElem = info;
 
 }
 
@@ -425,9 +426,9 @@ 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->model_desc->end)
-      current_routing->model_desc->end(current_routing);
-    current_routing = current_routing->routing_father;
+    if (current_routing->p_modelDesc->end)
+      current_routing->p_modelDesc->end(current_routing);
+    current_routing = current_routing->p_routingFather;
   }
 }
 
@@ -436,10 +437,10 @@ void routing_AS_end(sg_platf_AS_cbarg_t AS)
 /**
  * \brief Get the AS father and the first elements of the chain
  *
- * \param src the source host name 
+ * \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 
+ *
+ * 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,
@@ -449,36 +450,36 @@ static void elements_father(sg_routing_edge_t src, sg_routing_edge_t 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];
+  AsPtr src_as, dst_as;
+  AsPtr path_src[ELEMENTS_FATHER_MAXDEPTH];
+  AsPtr 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;
+  AsPtr current;
+  AsPtr current_src;
+  AsPtr current_dst;
+  AsPtr 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->rc_component;
-  dst_as = dst_data->rc_component;
+  src_as = src_data->p_rcComponent;
+  dst_as = dst_data->p_rcComponent;
 #ifndef NDEBUG
-  char* src_name = src_data->name;
-  char* dst_name = dst_data->name;
+  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->routing_father) {
+  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->routing_father) {
+  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;
@@ -509,45 +510,46 @@ static void elements_father(sg_routing_edge_t src, sg_routing_edge_t dst,
 /**
  * \brief Recursive function for get_route_latency
  *
- * \param src the source host name 
+ * \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(sg_routing_edge_t src, sg_routing_edge_t dst,
+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->name, dst->name);
+  XBT_DEBUG("Solve route/latency  \"%s\" to \"%s\"", src->p_name, dst->p_name);
 
   /* Find how src and dst are interconnected */
-  AS_t common_father, src_father, dst_father;
+  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->name,src_father->name,dst_father->name);
+      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;
-  if (common_father->get_bypass_route)
-    e_route_bypass = common_father->get_bypass_route(common_father, src, dst, latency);
+  //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);
-    generic_free_route(e_route_bypass);
+    //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->get_route_and_latency(common_father, src, dst, &route,latency);
+    common_father->getRouteAndLatency(src, dst, &route, latency);
     // if vivaldi latency+=vivaldi(src,dst)
     return;
   }
@@ -556,15 +558,14 @@ static void _get_route_and_latency(sg_routing_edge_t src, sg_routing_edge_t dst,
 
   route.link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
   // Find the net_card corresponding to father
-  sg_routing_edge_t src_father_net_elm = src_father->net_elem;
-  sg_routing_edge_t dst_father_net_elm = dst_father->net_elem;
+  RoutingEdgePtr src_father_net_elm = src_father->p_netElem;
+  RoutingEdgePtr dst_father_net_elm = dst_father->p_netElem;
 
-  common_father->get_route_and_latency(common_father,
-                                       src_father_net_elm, dst_father_net_elm,
-                                       &route, latency);
+  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->name, dst->name);
+      "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;
@@ -581,6 +582,15 @@ static void _get_route_and_latency(sg_routing_edge_t src, sg_routing_edge_t dst,
   // 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
  *
@@ -595,28 +605,31 @@ static void _get_route_and_latency(sg_routing_edge_t src, sg_routing_edge_t dst,
  * walk through the routing components tree and find a route between hosts
  * by calling the differents "get_route" functions in each routing component.
  */
-void routing_get_route_and_latency(sg_routing_edge_t src,
-                                   sg_routing_edge_t dst,
-                                   xbt_dynar_t * route, double *latency)
+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->name,dst->name);
+  XBT_DEBUG("routing_get_route_and_latency from %s to %s", src->p_name, dst->p_name);
   if (!*route) {
-    xbt_dynar_reset(routing_platf->last_route);
-    *route = routing_platf->last_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->name, dst->name);
+             "negative latency on route between \"%s\" and \"%s\"", src->p_name, dst->p_name);
+}
+
+xbt_dynar_t RoutingPlatf::getOneLinkRoutes(){
+  return recursiveGetOneLinkRoutes(p_root);
 }
 
-static xbt_dynar_t recursive_get_onelink_routes(AS_t rc)
+xbt_dynar_t RoutingPlatf::recursiveGetOneLinkRoutes(AsPtr rc)
 {
-  xbt_dynar_t ret = xbt_dynar_new(sizeof(onelink_t), xbt_free);
+  xbt_dynar_t ret = xbt_dynar_new(sizeof(OnelinkPtr), xbt_free);
 
   //adding my one link routes
-  xbt_dynar_t onelink_mine = rc->get_onelink_routes(rc);
+  xbt_dynar_t onelink_mine = rc->getOneLinkRoutes();
   if (onelink_mine)
     xbt_dynar_merge(&ret,&onelink_mine);
 
@@ -624,41 +637,35 @@ static xbt_dynar_t recursive_get_onelink_routes(AS_t rc)
   char *key;
   xbt_dict_cursor_t cursor = NULL;
   AS_t rc_child;
-  xbt_dict_foreach(rc->routing_sons, cursor, key, rc_child) {
-    xbt_dynar_t onelink_child = recursive_get_onelink_routes(rc_child);
+  xbt_dict_foreach(rc->p_routingSons, cursor, key, rc_child) {
+    xbt_dynar_t onelink_child = recursiveGetOneLinkRoutes(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->root);
-}
-
 e_surf_network_element_type_t routing_get_network_element_type(const char *name)
 {
-  sg_routing_edge_t rc = sg_routing_edge_by_name_or_null(name);
+  RoutingEdgePtr rc = sg_routing_edge_by_name_or_null(name);
   if (rc)
-    return rc->rc_type;
+    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 = xbt_new0(s_routing_platf_t, 1);
-  routing_platf->root = NULL;
-  routing_platf->get_onelink_routes = get_onelink_routes;
-  routing_platf->loopback = loopback;
-  routing_platf->last_route = xbt_dynar_new(sizeof(sg_routing_link_t),NULL);
+  routing_platf = new RoutingPlatf();
+  routing_platf->p_root = NULL;
+  routing_platf->p_loopback = loopback;
+  routing_platf->p_lastRoute = xbt_dynar_new(sizeof(sg_routing_link_t),NULL);
   /* no current routing at moment */
   current_routing = NULL;
 }
@@ -711,11 +718,11 @@ void routing_model_create( void *loopback)
 /* ************************* GENERIC PARSE FUNCTIONS ************************ */
 
 void routing_cluster_add_backbone(void* bb) {
-  xbt_assert(current_routing->model_desc == &routing_models[SURF_MODEL_CLUSTER],
+  xbt_assert(current_routing->p_modelDesc == &routing_models[SURF_MODEL_CLUSTER],
         "You have to be in model Cluster to use tag backbone!");
-  xbt_assert(!((as_cluster_t)current_routing)->backbone,"The backbone link is already defined!");
-  ((as_cluster_t)current_routing)->backbone = bb;
-  XBT_DEBUG("Add a backbone to AS '%s'",current_routing->name);
+  xbt_assert(!surf_as_cluster_get_backbone(current_routing), "The backbone link is already defined!");
+  surf_as_cluster_set_backbone(current_routing, bb);
+  XBT_DEBUG("Add a backbone to AS '%s'", current_routing->p_name);
 }
 
 static void routing_parse_cabinet(sg_platf_cabinet_cbarg_t cabinet)
@@ -817,7 +824,7 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
   AS.routing = A_surfxml_AS_routing_Cluster;
   sg_platf_new_AS_begin(&AS);
 
-  current_routing->link_up_down_list
+  current_routing->p_linkUpDownList
             = xbt_dynar_new(sizeof(s_surf_parsing_link_up_down_t),NULL);
 
   //Make all hosts
@@ -905,13 +912,13 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
         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){      
+
+      if(cluster->limiter_link!=0){
         char *tmp_link = bprintf("%s_limiter", link_id);
         XBT_DEBUG("<limiter\tid=\"%s\"\tbw=\"%f\"/>", tmp_link,
                 cluster->limiter_link);
 
-        
+
         memset(&link, 0, sizeof(link));
         link.id = tmp_link;
         link.bandwidth = cluster->limiter_link;
@@ -925,13 +932,13 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
       }else{
         info.limiter_link =NULL;
       }
-      
-      if(cluster->loopback_bw!=0 || cluster->loopback_lat!=0){      
+
+      if(cluster->loopback_bw!=0 || cluster->loopback_lat!=0){
         char *tmp_link = bprintf("%s_loopback", link_id);
         XBT_DEBUG("<loopback\tid=\"%s\"\tbw=\"%f\"/>", tmp_link,
                 cluster->limiter_link);
 
-        
+
         memset(&link, 0, sizeof(link));
         link.id = tmp_link;
         link.bandwidth = cluster->loopback_bw;
@@ -945,8 +952,8 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
       }else{
         info.loopback_link =NULL;
       }
-      
-      xbt_dynar_push(current_routing->link_up_down_list,&info);
+
+      xbt_dynar_push(current_routing->p_linkUpDownList, &info);
       xbt_free(link_id);
       xbt_free(host_id);
     }
@@ -969,7 +976,7 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
         bprintf("%s%s_router%s", cluster->prefix, cluster->id,
                 cluster->suffix);
   sg_platf_new_router(&router);
-  ((as_cluster_t)current_routing)->router = xbt_lib_get_or_null(as_router_lib, router.id, ROUTING_ASR_LEVEL);
+  ((AsClusterPtr)current_routing)->p_router = (RoutingEdgePtr) xbt_lib_get_or_null(as_router_lib, router.id, ROUTING_ASR_LEVEL);
   free(newid);
 
   //Make the backbone
@@ -1019,8 +1026,7 @@ static void routing_parse_peer(sg_platf_peer_cbarg_t peer)
   AS.routing = A_surfxml_AS_routing_Cluster;
   sg_platf_new_AS_begin(&AS);
 
-  current_routing->link_up_down_list
-            = xbt_dynar_new(sizeof(s_surf_parsing_link_up_down_t),NULL);
+  current_routing->p_linkUpDownList = xbt_dynar_new(sizeof(s_surf_parsing_link_up_down_t),NULL);
 
   XBT_DEBUG("<host\tid=\"%s\"\tpower=\"%f\"/>", host_id, peer->power);
   s_sg_platf_host_cbarg_t host;
@@ -1073,7 +1079,7 @@ static void routing_parse_peer(sg_platf_peer_cbarg_t peer)
   router.id = router_id;
   router.coord = peer->coord;
   sg_platf_new_router(&router);
-  ((as_cluster_t)current_routing)->router = xbt_lib_get_or_null(as_router_lib, router.id, ROUTING_ASR_LEVEL);
+  static_cast<AsClusterPtr>(current_routing)->p_router = static_cast<RoutingEdgePtr>(xbt_lib_get_or_null(as_router_lib, router.id, ROUTING_ASR_LEVEL));
 
   XBT_DEBUG("</AS>");
   sg_platf_new_AS_end();
@@ -1243,56 +1249,61 @@ void routing_register_callbacks()
  * This fuction is call by "finalize". It allow to finalize the
  * AS or routing components. It delete all the structures.
  */
-static void finalize_rec(AS_t as) {
+static void finalize_rec(AsPtr as) {
   xbt_dict_cursor_t cursor = NULL;
   char *key;
   AS_t elem;
 
-  xbt_dict_foreach(as->routing_sons, cursor, key, elem) {
+  xbt_dict_foreach(as->p_routingSons, cursor, key, elem) {
     finalize_rec(elem);
   }
 
-  as->finalize(as);
+  delete as;;
 }
 
 /** \brief Frees all memory allocated by the routing module */
 void routing_exit(void) {
   if (!routing_platf)
     return;
-  xbt_dynar_free(&routing_platf->last_route);
-  finalize_rec(routing_platf->root);
+  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->root;  
+  return routing_platf->p_root;
 }
 
-const char *surf_AS_get_name(AS_t as) {
-  return as->name;
+const char *surf_AS_get_name(AsPtr as) {
+  return as->p_name;
 }
 
-xbt_dict_t surf_AS_get_routing_sons(AS_t as) {
-  return as->routing_sons;
+xbt_dict_t surf_AS_get_routing_sons(AsPtr as) {
+  return as->p_routingSons;
 }
 
-const char *surf_AS_get_model(AS_t as) {
-  return as->model_desc->name;
+const char *surf_AS_get_model(AsPtr as) {
+  return as->p_modelDesc->name;
 }
 
-xbt_dynar_t surf_AS_get_hosts(AS_t as) {
-  xbt_dynar_t elms = as->index_network_elm;
+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, sg_routing_edge_t);
-     delm = xbt_lib_get_elm_or_null(host_lib, relm->name);
+     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 (file)
index 0000000..d61d3fa
--- /dev/null
@@ -0,0 +1,101 @@
+#include "surf.hpp"
+#include <float.h>
+
+#ifndef NETWORK_ROUTING_HPP_
+#define NETWORK_ROUTING_HPP_
+
+void routing_model_create( void *loopback);
+
+/* ************************************************************************** */
+/* ************************* 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);
+
+/***********
+ * 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:
+  Onelink(void *link, RoutingEdgePtr src, RoutingEdgePtr dst)
+   : p_link(link), p_src(src), p_dst(dst) {};
+  RoutingEdgePtr p_src;
+  RoutingEdgePtr p_dst;
+  void *p_link;
+};
+
+class RoutingPlatf {
+public:
+  AsPtr p_root;
+  void *p_loopback;
+  xbt_dynar_t p_lastRoute;
+  xbt_dynar_t getOneLinkRoutes(void);
+  xbt_dynar_t recursiveGetOneLinkRoutes(AsPtr rc);
+  void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, xbt_dynar_t * links, double *latency);
+};
+
+#endif /* NETWORK_ROUTING_HPP_ */
diff --git a/src/surf/surf_routing_cluster.c b/src/surf/surf_routing_cluster.c
deleted file mode 100644 (file)
index 4e17552..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/* Copyright (c) 2009-2013. 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_private.h"
-#include "xbt/graph.h"
-
-/* Global vars */
-
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_cluster, surf, "Routing part of surf");
-
-/* This routing is specifically setup to represent clusters, aka homogeneous sets of machines
- * Note that a router is created, easing the interconnexion with the rest of the world.
- */
-
-/* Business methods */
-static void cluster_get_route_and_latency(AS_t as,
-                                          sg_routing_edge_t src,
-                                          sg_routing_edge_t dst,
-                                          sg_platf_route_cbarg_t route,
-                                          double *lat)
-{
-
-  s_surf_parsing_link_up_down_t info;
-  XBT_VERB("cluster_get_route_and_latency from '%s'[%d] to '%s'[%d]",
-            src->name, src->id, dst->name, dst->id);
-
-  if (src->rc_type != SURF_NETWORK_ELEMENT_ROUTER) {    // No specific link for router
-    info =
-        xbt_dynar_get_as(as->link_up_down_list, src->id,
-                         s_surf_parsing_link_up_down_t);
-                         
-    if((src->id == dst->id) && info.loopback_link  ){
-      xbt_dynar_push_as(route->link_list, void *, info.loopback_link);
-      if (lat)
-        *lat +=
-            surf_network_model->extension.network.get_link_latency(info.
-                                                                   loopback_link);
-      return;
-    }
-                         
-                         
-    if (info.limiter_link)          // limiter for sender
-      xbt_dynar_push_as(route->link_list, void *, info.limiter_link);
-    
-    if (info.link_up) {         // link up
-      xbt_dynar_push_as(route->link_list, void *, info.link_up);
-      if (lat)
-        *lat +=
-            surf_network_model->extension.network.get_link_latency(info.
-                                                                   link_up);
-    }
-  }
-
-  if (((as_cluster_t) as)->backbone) {
-    xbt_dynar_push_as(route->link_list, void *, ((as_cluster_t) as)->backbone);
-    if (lat)
-      *lat +=
-          surf_network_model->extension.network.
-          get_link_latency(((as_cluster_t) as)->backbone);
-  }
-
-  if (dst->rc_type != SURF_NETWORK_ELEMENT_ROUTER) {    // No specific link for router
-    info =
-        xbt_dynar_get_as(as->link_up_down_list, dst->id,
-                         s_surf_parsing_link_up_down_t);
-    if (info.link_down) {       // link down
-      xbt_dynar_push_as(route->link_list, void *, info.link_down);
-      if (lat)
-        *lat +=
-            surf_network_model->extension.network.get_link_latency(info.
-                                                                   link_down);
-    }
-    
-    if (info.limiter_link)          // limiter for receiver
-      xbt_dynar_push_as(route->link_list, void *, info.limiter_link);
-    
-  }
-}
-
-static void cluster_get_graph(xbt_graph_t graph, xbt_dict_t nodes,
-                              xbt_dict_t edges, AS_t rc)
-{
-  int isrc;
-  int table_size = xbt_dynar_length(rc->index_network_elm);
-
-  sg_routing_edge_t src;
-  xbt_node_t current, previous, backboneNode = NULL, routerNode;
-  s_surf_parsing_link_up_down_t info;
-
-  xbt_assert(((as_cluster_t) rc)->router,"Malformed cluster");
-
-  /* create the router */
-  char *link_name =
-    ((sg_routing_edge_t) ((as_cluster_t) rc)->router)->name;
-  routerNode = new_xbt_graph_node(graph, link_name, nodes);
-
-  if(((as_cluster_t) rc)->backbone) {
-    char *link_nameR =
-      ((surf_resource_t) ((as_cluster_t) rc)->backbone)->name;
-    backboneNode = new_xbt_graph_node(graph, link_nameR, nodes);
-
-    new_xbt_graph_edge(graph, routerNode, backboneNode, edges);
-  }
-
-  for (isrc = 0; isrc < table_size; isrc++) {
-    src = xbt_dynar_get_as(rc->index_network_elm, isrc, sg_routing_edge_t);
-
-    if (src->rc_type != SURF_NETWORK_ELEMENT_ROUTER) {
-      previous = new_xbt_graph_node(graph, src->name, nodes);
-
-      info = xbt_dynar_get_as(rc->link_up_down_list, src->id,
-                              s_surf_parsing_link_up_down_t);
-
-      if (info.link_up) {     // link up
-
-        char *link_name = ((surf_resource_t) info.link_up)->name;
-        current = new_xbt_graph_node(graph, link_name, nodes);
-        new_xbt_graph_edge(graph, previous, current, edges);
-
-        if (((as_cluster_t) rc)->backbone) {
-          new_xbt_graph_edge(graph, current, backboneNode, edges);
-        } else {
-          new_xbt_graph_edge(graph, current, routerNode, edges);
-        }
-
-      }
-
-      if (info.link_down) {    // link down
-        char *link_name = ((surf_resource_t) info.link_down)->name;
-        current = new_xbt_graph_node(graph, link_name, nodes);
-        new_xbt_graph_edge(graph, previous, current, edges);
-
-        if (((as_cluster_t) rc)->backbone) {
-          new_xbt_graph_edge(graph, current, backboneNode, edges);
-        } else {
-          new_xbt_graph_edge(graph, current, routerNode, edges);
-        }
-      }
-    }
-
-  }
-}
-
-static void model_cluster_finalize(AS_t as)
-{
-  model_none_finalize(as);
-}
-
-static int cluster_parse_PU(AS_t rc, sg_routing_edge_t elm) {
-  XBT_DEBUG("Load process unit \"%s\"", elm->name);
-  xbt_dynar_push_as(rc->index_network_elm,sg_routing_edge_t,elm);
-  return xbt_dynar_length(rc->index_network_elm)-1;
-}
-
-static int cluster_parse_AS(AS_t rc, sg_routing_edge_t elm) {
-  XBT_DEBUG("Load Autonomous system \"%s\"", elm->name);
-  xbt_dynar_push_as(rc->index_network_elm,sg_routing_edge_t,elm);
-  return xbt_dynar_length(rc->index_network_elm)-1;
-}
-
-/* Creation routing model functions */
-AS_t model_cluster_create(void)
-{
-  AS_t result = model_none_create_sized(sizeof(s_as_cluster_t));
-  result->get_route_and_latency = cluster_get_route_and_latency;
-  result->finalize = model_cluster_finalize;
-  result->get_graph = cluster_get_graph;
-  result->parse_AS = cluster_parse_AS;
-  result->parse_PU = cluster_parse_PU;
-
-  return (AS_t) result;
-}
diff --git a/src/surf/surf_routing_cluster.cpp b/src/surf/surf_routing_cluster.cpp
new file mode 100644 (file)
index 0000000..110e685
--- /dev/null
@@ -0,0 +1,150 @@
+/* Copyright (c) 2009, 2010, 2011. The SimGrid Team.
+
+/* 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_cluster.hpp"
+
+extern "C" {
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_cluster, surf, "Routing part of surf");
+}
+
+/* This routing is specifically setup to represent clusters, aka homogeneous sets of machines
+ * Note that a router is created, easing the interconnexion with the rest of the world.
+ */
+
+AS_t model_cluster_create(void)
+{
+  return new AsCluster();
+}
+
+/* Creation routing model functions */
+AsCluster::AsCluster() : AsNone()
+{
+  p_backbone = 0;
+  p_loopback = 0;
+  p_router = 0;
+}
+
+/* Business methods */
+void AsCluster::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t route, double *lat)
+{
+  s_surf_parsing_link_up_down_t info;
+  XBT_VERB("cluster_get_route_and_latency from '%s'[%d] to '%s'[%d]",
+            src->p_name, src->m_id, dst->p_name, dst->m_id);
+
+  if (src->p_rcType != SURF_NETWORK_ELEMENT_ROUTER) {    // No specific link for router
+    info = xbt_dynar_get_as(p_linkUpDownList, src->m_id, s_surf_parsing_link_up_down_t);
+
+    if((src->m_id == dst->m_id) && info.loopback_link  ){
+      xbt_dynar_push_as(route->link_list, void *, info.loopback_link);
+      if (lat)
+        *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(info.loopback_link))->getLatency();
+      return;
+    }
+
+
+    if (info.limiter_link)          // limiter for sender
+      xbt_dynar_push_as(route->link_list, void *, info.limiter_link);
+
+    if (info.link_up) {         // link up
+      xbt_dynar_push_as(route->link_list, void *, info.link_up);
+      if (lat)
+        *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(info.link_up))->getLatency();
+    }
+  }
+
+  if (p_backbone) {
+    xbt_dynar_push_as(route->link_list, void *, static_cast<ResourcePtr>(p_backbone));
+    if (lat)
+      *lat += p_backbone->getLatency();
+  }
+
+  if (dst->p_rcType != SURF_NETWORK_ELEMENT_ROUTER) {    // No specific link for router
+    info =
+        xbt_dynar_get_as(p_linkUpDownList, dst->m_id, s_surf_parsing_link_up_down_t);
+    if (info.link_down) {       // link down
+      xbt_dynar_push_as(route->link_list, void *, info.link_down);
+      if (lat)
+        *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(info.link_down))->getLatency();
+    }
+
+    if (info.limiter_link)          // limiter for receiver
+      xbt_dynar_push_as(route->link_list, void *, info.limiter_link);
+
+  }
+}
+
+void AsCluster::getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges)
+{
+  int isrc;
+  int table_size = xbt_dynar_length(p_indexNetworkElm);
+
+  RoutingEdgePtr src;
+  xbt_node_t current, previous, backboneNode = NULL, routerNode;
+  s_surf_parsing_link_up_down_t info;
+
+  xbt_assert(p_router,"Malformed cluster");
+
+  /* create the router */
+  char *link_name = p_router->p_name;
+  routerNode = new_xbt_graph_node(graph, link_name, nodes);
+
+  if(p_backbone) {
+    const char *link_nameR = p_backbone->m_name;
+    backboneNode = new_xbt_graph_node(graph, link_nameR, nodes);
+
+    new_xbt_graph_edge(graph, routerNode, backboneNode, edges);
+  }
+
+  for (isrc = 0; isrc < table_size; isrc++) {
+    src = xbt_dynar_get_as(p_indexNetworkElm, isrc, RoutingEdgePtr);
+
+    if (src->p_rcType != SURF_NETWORK_ELEMENT_ROUTER) {
+      previous = new_xbt_graph_node(graph, src->p_name, nodes);
+
+      info = xbt_dynar_get_as(p_linkUpDownList, src->m_id, s_surf_parsing_link_up_down_t);
+
+      if (info.link_up) {     // link up
+
+        const char *link_name = ((ResourcePtr) info.link_up)->m_name;
+        current = new_xbt_graph_node(graph, link_name, nodes);
+        new_xbt_graph_edge(graph, previous, current, edges);
+
+        if (p_backbone) {
+          new_xbt_graph_edge(graph, current, backboneNode, edges);
+        } else {
+          new_xbt_graph_edge(graph, current, routerNode, edges);
+        }
+
+      }
+
+      if (info.link_down) {    // link down
+        const char *link_name = ((ResourcePtr) info.link_down)->m_name;
+        current = new_xbt_graph_node(graph, link_name, nodes);
+        new_xbt_graph_edge(graph, previous, current, edges);
+
+        if (p_backbone) {
+          new_xbt_graph_edge(graph, current, backboneNode, edges);
+        } else {
+          new_xbt_graph_edge(graph, current, routerNode, edges);
+        }
+      }
+    }
+
+  }
+}
+
+int AsCluster::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 AsCluster::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;
+}
+
+
diff --git a/src/surf/surf_routing_cluster.hpp b/src/surf/surf_routing_cluster.hpp
new file mode 100644 (file)
index 0000000..c3e8871
--- /dev/null
@@ -0,0 +1,44 @@
+#include "surf_routing_none.hpp"
+#include "network.hpp"
+
+#ifndef SURF_ROUTING_CLUSTER_HPP_
+#define SURF_ROUTING_CLUSTER_HPP_
+
+/***********
+ * Classes *
+ ***********/
+class AsCluster;
+typedef AsCluster *AsClusterPtr;
+
+
+/* ************************************************** */
+/* **************  Cluster ROUTING   **************** */
+
+class AsCluster: public AsNone {
+public:
+  AsCluster();
+
+  void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
+  //xbt_dynar_t getOneLinkRoutes();
+  //void parseRoute(sg_platf_route_cbarg_t route);
+  //void parseASroute(sg_platf_route_cbarg_t route);
+
+  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);
+
+  /* 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);
+
+  //virtual void parseBypassroute(sg_platf_route_cbarg_t e_route)=0;
+
+  NetworkCm02LinkPtr p_backbone;
+  void *p_loopback;
+  RoutingEdgePtr p_router;
+};
+
+
+#endif /* SURF_ROUTING_CLUSTER_HPP_ */
similarity index 56%
rename from src/surf/surf_routing_dijkstra.c
rename to src/surf/surf_routing_dijkstra.cpp
index 8d204bc..d3ae335 100644 (file)
@@ -4,35 +4,15 @@
 /* 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_private.h"
+#include "surf_routing_dijkstra.hpp"
+#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");
-
-typedef struct {
-  s_as_t generic_routing;
-  xbt_graph_t route_graph;      /* xbt_graph */
-  xbt_dict_t graph_node_map;    /* map */
-  xbt_dict_t route_cache;       /* use in cache mode */
-  int cached;
-} s_as_dijkstra_t, *as_dijkstra_t;
-
-
-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;
+}
 
 /* Free functions */
 
@@ -60,10 +40,46 @@ static void graph_edge_data_free(void *e) // FIXME: useless code duplication
   }
 }
 
+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)
+{
+  AsDijkstraPtr THIS_AS = static_cast<AsDijkstraPtr>(as);
+  xbt_node_t node = NULL;
+  unsigned int cursor2;
+  xbt_dynar_t nodes = NULL;
+
+  /* Create the topology graph */
+  if(!THIS_AS->p_routeGraph)
+    THIS_AS->p_routeGraph = xbt_graph_new_graph(1, NULL);
+  if(!THIS_AS->p_graphNodeMap)
+    THIS_AS->p_graphNodeMap = xbt_dict_new_homogeneous(&graph_node_map_elem_free);
+
+  if (THIS_AS->m_cached && !THIS_AS->p_routeCache)
+    THIS_AS->p_routeCache = xbt_dict_new_homogeneous(&route_cache_elem_free);
+
+  /* Add the loopback if needed */
+  if (routing_platf->p_loopback && as->p_hierarchy == SURF_ROUTING_BASE)
+    THIS_AS->addLoopback();
+
+  /* initialize graph indexes in nodes after graph has been built */
+  nodes = xbt_graph_get_nodes(THIS_AS->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;
+  }
+}
+
 /* Utility functions */
 
-static xbt_node_t route_graph_new_node(as_dijkstra_t as,
-    int id, int graph_id)
+xbt_node_t AsDijkstra::routeGraphNewNode(int id, int graph_id)
 {
   xbt_node_t node = NULL;
   graph_node_data_t data = NULL;
@@ -72,21 +88,20 @@ static xbt_node_t route_graph_new_node(as_dijkstra_t as,
   data = xbt_new0(struct graph_node_data, 1);
   data->id = id;
   data->graph_id = graph_id;
-  node = xbt_graph_new_node(as->route_graph, data);
+  node = xbt_graph_new_node(p_routeGraph, data);
 
   elm = xbt_new0(struct graph_node_map_element, 1);
   elm->node = node;
-  xbt_dict_set_ext(as->graph_node_map, (char *) (&id), sizeof(int),
+  xbt_dict_set_ext(p_graphNodeMap, (char *) (&id), sizeof(int),
       (xbt_set_elm_t) elm, NULL);
 
   return node;
 }
 
-static graph_node_map_element_t
-graph_node_map_search(as_dijkstra_t as, int id)
+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(as->graph_node_map,
+          xbt_dict_get_or_null_ext(p_graphNodeMap,
               (char *) (&id),
               sizeof(int));
   return elm;
@@ -94,19 +109,18 @@ graph_node_map_search(as_dijkstra_t as, int id)
 
 /* Parsing */
 
-static void route_new_dijkstra(as_dijkstra_t as, int src_id,
-    int dst_id, sg_platf_route_cbarg_t e_route)
+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(as->graph_node_map,
+          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(as->graph_node_map,
+          xbt_dict_get_or_null_ext(p_graphNodeMap,
               (char *) (&dst_id),
               sizeof(int));
 
@@ -119,23 +133,23 @@ static void route_new_dijkstra(as_dijkstra_t as, int src_id,
 
   /* add nodes if they don't exist in the graph */
   if (src_id == dst_id && src == NULL && dst == NULL) {
-    src = route_graph_new_node(as, src_id, -1);
+    src = this->routeGraphNewNode(src_id, -1);
     dst = src;
   } else {
     if (src == NULL) {
-      src = route_graph_new_node(as, src_id, -1);
+      src = this->routeGraphNewNode(src_id, -1);
     }
     if (dst == NULL) {
-      dst = route_graph_new_node(as, dst_id, -1);
+      dst = this->routeGraphNewNode(dst_id, -1);
     }
   }
 
   /* add link as edge to graph */
-  xbt_graph_new_edge(as->route_graph, src, dst, e_route);
+  xbt_graph_new_edge(p_routeGraph, src, dst, e_route);
 }
 
-static void add_loopback_dijkstra(as_dijkstra_t as) {
-  xbt_dynar_t nodes = xbt_graph_get_nodes(as->route_graph);
+void AsDijkstra::addLoopback() {
+  xbt_dynar_t nodes = xbt_graph_get_nodes(p_routeGraph);
 
   xbt_node_t node = NULL;
   unsigned int cursor2;
@@ -156,42 +170,37 @@ static void add_loopback_dijkstra(as_dijkstra_t as) {
     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->loopback);
-      xbt_graph_new_edge(as->route_graph, node, node, e_route);
+      xbt_dynar_push(e_route->link_list, &routing_platf->p_loopback);
+      xbt_graph_new_edge(p_routeGraph, node, node, e_route);
     }
   }
 }
 
-static void dijkstra_get_route_and_latency(AS_t as_generic,
-    sg_routing_edge_t src, sg_routing_edge_t dst, sg_platf_route_cbarg_t route, double *lat);
-
-static xbt_dynar_t dijkstra_get_onelink_routes(AS_t as)
+xbt_dynar_t AsDijkstra::getOnelinkRoutes()
 {
-  xbt_dynar_t ret = xbt_dynar_new(sizeof(onelink_t), xbt_free);
+  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;
-  sg_routing_edge_t src_elm, dst_elm;
-  size_t table_size = xbt_dynar_length(as->index_network_elm);
+  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(as->index_network_elm,src,sg_routing_edge_t);
-      dst_elm = xbt_dynar_get_as(as->index_network_elm,dst,sg_routing_edge_t);
-      dijkstra_get_route_and_latency(as, src_elm, dst_elm,route, NULL);
+      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);
-        onelink_t onelink = xbt_new0(s_onelink_t, 1);
-        onelink->link_ptr = link;
-        if (as->hierarchy == SURF_ROUTING_BASE) {
-          onelink->src = src_elm;
-          onelink->dst = dst_elm;
-        } else if (as->hierarchy == SURF_ROUTING_RECURSIVE) {
-          onelink->src = route->gw_src;
-          onelink->dst = route->gw_dst;
-        }
+        OnelinkPtr onelink;
+        if (p_hierarchy == SURF_ROUTING_BASE)
+          onelink = new Onelink(link, src_elm, dst_elm);
+        else if (p_hierarchy == SURF_ROUTING_RECURSIVE)
+          onelink = new Onelink(link, route->gw_src, route->gw_dst);
+        else
+          onelink = new Onelink(link, NULL, NULL);
         xbt_dynar_push(ret, &onelink);
       }
     }
@@ -199,20 +208,17 @@ static xbt_dynar_t dijkstra_get_onelink_routes(AS_t as)
   return ret;
 }
 
-static void dijkstra_get_route_and_latency(AS_t asg,
-    sg_routing_edge_t src, sg_routing_edge_t dst,
-    sg_platf_route_cbarg_t route, double *lat)
+void AsDijkstra::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t route, double *lat)
 {
 
   /* set utils vars */
-  as_dijkstra_t as = (as_dijkstra_t) asg;
 
-  generic_src_dst_check(asg, src, dst);
-  int *src_id = &(src->id);
-  int *dst_id = &(dst->id);
+  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->name,dst->name);
+    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;
@@ -225,13 +231,11 @@ static void dijkstra_get_route_and_latency(AS_t asg,
   void *link;
   xbt_dynar_t links = NULL;
   route_cache_element_t elm = NULL;
-  xbt_dynar_t nodes = xbt_graph_get_nodes(as->route_graph);
+  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 =
-      graph_node_map_search(as, *src_id);
-  graph_node_map_element_t dst_elm =
-      graph_node_map_search(as, *dst_id);
+  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;
@@ -243,11 +247,10 @@ static void dijkstra_get_route_and_latency(AS_t asg,
 
     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(as->route_graph, node_s_v, node_e_v);
+    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->name,dst->name);
+      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);
 
@@ -255,15 +258,15 @@ static void dijkstra_get_route_and_latency(AS_t asg,
     xbt_dynar_foreach(links, cpt, link) {
       xbt_dynar_unshift(route->link_list, &link);
       if (lat)
-        *lat += surf_network_model->extension.network.get_link_latency(link);
+        *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(link))->getLatency();
     }
 
   }
 
-  if (as->cached) {
+  if (m_cached) {
     /*check if there is a cached predecessor list avail */
     elm = (route_cache_element_t)
-            xbt_dict_get_or_null_ext(as->route_cache, (char *) (&src_id),
+            xbt_dict_get_or_null_ext(p_routeCache, (char *) (&src_id),
                 sizeof(int));
   }
 
@@ -298,7 +301,7 @@ static void dijkstra_get_route_and_latency(AS_t asg,
 
     /* apply dijkstra using the indexes from the graph's node array */
     while (xbt_heap_size(pqueue) > 0) {
-      int *v_id = xbt_heap_pop(pqueue);
+      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;
@@ -306,7 +309,7 @@ static void dijkstra_get_route_and_latency(AS_t asg,
 
       xbt_dynar_foreach(out_edges, cursor, edge) {
         xbt_node_t u_node = xbt_graph_edge_get_target(edge);
-        graph_node_data_t data = xbt_graph_node_get_data(u_node);
+        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 */
@@ -329,18 +332,18 @@ static void dijkstra_get_route_and_latency(AS_t asg,
   }
 
   /* compose route path with links */
-  sg_routing_edge_t gw_src = NULL, gw_dst, prev_gw_src, first_gw = NULL;
-  sg_routing_edge_t gw_dst_net_elm = NULL, prev_gw_src_net_elm = NULL;
+  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(as->route_graph, node_pred_v, node_v);
+        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->name,dst->name);
+      THROWF(arg_error, 0, "No route from '%s' to '%s'", src->p_name, dst->p_name);
 
     prev_gw_src = gw_src;
 
@@ -351,18 +354,19 @@ static void dijkstra_get_route_and_latency(AS_t asg,
     if (v == dst_node_id)
       first_gw = gw_dst;
 
-    if (asg->hierarchy == SURF_ROUTING_RECURSIVE && v != dst_node_id
-        && strcmp(gw_dst->name, prev_gw_src->name)) {
+    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_get_route_and_latency(gw_dst_net_elm, prev_gw_src_net_elm, &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->name,dst->name);
+        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 += surf_network_model->extension.network.get_link_latency(link);
+          *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(link))->getLatency();
         pos++;
       }
     }
@@ -371,102 +375,89 @@ static void dijkstra_get_route_and_latency(AS_t asg,
     xbt_dynar_foreach(links, cpt, link) {
       xbt_dynar_unshift(route->link_list, &link);
       if (lat)
-        *lat += surf_network_model->extension.network.get_link_latency(link);
+        *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(link))->getLatency();
     }
     size++;
   }
 
-  if (asg->hierarchy == SURF_ROUTING_RECURSIVE) {
+  if (p_hierarchy == SURF_ROUTING_RECURSIVE) {
     route->gw_src = gw_src;
     route->gw_dst = first_gw;
   }
 
-  if (as->cached && elm == NULL) {
+  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(as->route_cache, (char *) (&src_id), sizeof(int),
+    xbt_dict_set_ext(p_routeCache, (char *) (&src_id), sizeof(int),
         (xbt_set_elm_t) elm, NULL);
   }
 
-  if (!as->cached)
+  if (!m_cached)
     xbt_free(pred_arr);
 }
 
-static void dijkstra_finalize(AS_t asg)
+AsDijkstra::~AsDijkstra()
 {
-  as_dijkstra_t as = (as_dijkstra_t) asg;
-
-  xbt_graph_free_graph(as->route_graph, &xbt_free,
+  xbt_graph_free_graph(p_routeGraph, &xbt_free,
       &graph_edge_data_free, &xbt_free);
-  xbt_dict_free(&as->graph_node_map);
-  if (as->cached)
-    xbt_dict_free(&as->route_cache);
-
-  model_generic_finalize(asg);
+  xbt_dict_free(&p_graphNodeMap);
+  if (m_cached)
+    xbt_dict_free(&p_routeCache);
 }
 
 /* Creation routing model functions */
 
-AS_t model_dijkstra_both_create(int cached)
-{
-  as_dijkstra_t new_component = (as_dijkstra_t)
-          model_generic_create_sized(sizeof(s_as_dijkstra_t));
+AsDijkstra::AsDijkstra() : AsGeneric(), m_cached(0) {}
 
-  new_component->generic_routing.parse_route = model_dijkstra_both_parse_route;
+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;
-
-  return (AS_t)new_component;
+  new_component->cached = cached;*/
 }
 
-AS_t model_dijkstra_create(void)
+void AsDijkstra::end()
 {
-  return model_dijkstra_both_create(0);
-}
-
-AS_t model_dijkstracache_create(void)
-{
-  return model_dijkstra_both_create(1);
-}
-
-void model_dijkstra_both_end(AS_t as)
-{
-  as_dijkstra_t THIS_AS = (as_dijkstra_t) as;
-
   xbt_node_t node = NULL;
   unsigned int cursor2;
   xbt_dynar_t nodes = NULL;
 
   /* Create the topology graph */
-  if(!THIS_AS->route_graph)
-    THIS_AS->route_graph = xbt_graph_new_graph(1, NULL);
-  if(!THIS_AS->graph_node_map)
-    THIS_AS->graph_node_map = xbt_dict_new_homogeneous(&graph_node_map_elem_free);
+  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 (THIS_AS->cached && !THIS_AS->route_cache)
-    THIS_AS->route_cache = xbt_dict_new_homogeneous(&route_cache_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->loopback && as->hierarchy == SURF_ROUTING_BASE)
-    add_loopback_dijkstra(THIS_AS);
+  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(THIS_AS->route_graph);
+  nodes = xbt_graph_get_nodes(p_routeGraph);
 
   xbt_dynar_foreach(nodes, cursor2, node) {
-    graph_node_data_t data = xbt_graph_node_get_data(node);
+    graph_node_data_t data = (graph_node_data_t) xbt_graph_node_get_data(node);
     data->graph_id = cursor2;
   }
 
 }
-void model_dijkstra_both_parse_route (AS_t asg, sg_platf_route_cbarg_t route)
+
+void AsDijkstra::parseASroute(sg_platf_route_cbarg_t route)
+{
+  parseRoute(route);
+}
+
+void AsDijkstra::parseRoute(sg_platf_route_cbarg_t route)
 {
   char *src = (char*)(route->src);
   char *dst = (char*)(route->dst);
@@ -476,16 +467,15 @@ void model_dijkstra_both_parse_route (AS_t asg, sg_platf_route_cbarg_t route)
     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->name, dst, route->gw_dst->name);
+        route->gw_src->p_name, dst, route->gw_dst->p_name);
     as_route = 1;
-    if(route->gw_dst->rc_type == SURF_NETWORK_ELEMENT_NULL)
-      xbt_die("The gw_dst '%s' does not exist!",route->gw_dst->name);
-    if(route->gw_src->rc_type == SURF_NETWORK_ELEMENT_NULL)
-      xbt_die("The gw_src '%s' does not exist!",route->gw_src->name);
+    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);
   }
 
-  as_dijkstra_t as = (as_dijkstra_t) asg;
-  sg_routing_edge_t src_net_elm, dst_net_elm;
+  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);
@@ -494,16 +484,16 @@ void model_dijkstra_both_parse_route (AS_t asg, sg_platf_route_cbarg_t route)
   xbt_assert(dst_net_elm, "Network elements %s not found", dst);
 
   /* Create the topology graph */
-  if(!as->route_graph)
-    as->route_graph = xbt_graph_new_graph(1, NULL);
-  if(!as->graph_node_map)
-    as->graph_node_map = xbt_dict_new_homogeneous(&graph_node_map_elem_free);
+  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 (as->cached && !as->route_cache)
-    as->route_cache = xbt_dict_new_homogeneous(&route_cache_elem_free);
+  if (m_cached && !p_routeCache)
+    p_routeCache = xbt_dict_new_homogeneous(&route_cache_elem_free);
 
-  sg_platf_route_cbarg_t e_route = generic_new_extended_route(asg->hierarchy, route, 1);
-  route_new_dijkstra(as, src_net_elm->id, dst_net_elm->id, e_route);
+  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)
@@ -514,25 +504,25 @@ void model_dijkstra_both_parse_route (AS_t asg, sg_platf_route_cbarg_t route)
       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->name, src, route->gw_src->name);
+          route->gw_dst->p_name, src, route->gw_src->p_name);
 
-    xbt_dynar_t nodes = xbt_graph_get_nodes(as->route_graph);
-    xbt_node_t node_s_v = xbt_dynar_get_as(nodes, src_net_elm->id, xbt_node_t);
-    xbt_node_t node_e_v = xbt_dynar_get_as(nodes, dst_net_elm->id, xbt_node_t);
+    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(as->route_graph, node_e_v, node_s_v);
+        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) {
-      sg_routing_edge_t gw_tmp;
+      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 = generic_new_extended_route(asg->hierarchy, route, 0);
-    route_new_dijkstra(as, dst_net_elm->id, src_net_elm->id, link_route_back);
+    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 (file)
index 0000000..ef68386
--- /dev/null
@@ -0,0 +1,48 @@
+#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;
+
+/***********
+ * Classes *
+ ***********/
+class AsDijkstra;
+typedef AsDijkstra *AsDijkstraPtr;
+
+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 parseASroute(sg_platf_route_cbarg_t route);
+       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_ */
similarity index 54%
rename from src/surf/surf_routing_floyd.c
rename to src/surf/surf_routing_floyd.cpp
index 0c1d32a..17472ea 100644 (file)
@@ -4,58 +4,72 @@
 /* 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_private.h"
-
-/* Global vars */
-extern routing_platf_t routing_platf;
+#include "surf_routing_floyd.hpp"
+#include "network.hpp"
 
+extern "C" {
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_floyd, surf, "Routing part of surf");
+}
 
-#define TO_FLOYD_COST(i,j) (as->cost_table)[(i)+(j)*table_size]
-#define TO_FLOYD_PRED(i,j) (as->predecessor_table)[(i)+(j)*table_size]
-#define TO_FLOYD_LINK(i,j) (as->link_table)[(i)+(j)*table_size]
+#define TO_FLOYD_COST(i,j) (p_costTable)[(i)+(j)*table_size]
+#define TO_FLOYD_PRED(i,j) (p_predecessorTable)[(i)+(j)*table_size]
+#define TO_FLOYD_LINK(i,j) (p_linkTable)[(i)+(j)*table_size]
 
-/* Routing model structure */
+AS_t model_floyd_create(void)
+{
+  return new AsFloyd();
+}
 
-typedef struct {
-  s_as_t generic_routing;
-  /* vars for calculate the floyd algorithm. */
-  int *predecessor_table;
-  double *cost_table;
-  sg_platf_route_cbarg_t *link_table;
-} s_as_floyd_t, *as_floyd_t;
+void model_floyd_end(AS_t current_routing)
+{
+  static_cast<AsFloydPtr>(current_routing)->end();
+}
 
-static void floyd_get_route_and_latency(AS_t asg, sg_routing_edge_t src, sg_routing_edge_t dst,
-    sg_platf_route_cbarg_t res, double *lat);
+AsFloyd::AsFloyd(): AsGeneric() {
+}
+
+AsFloyd::~AsFloyd(){
+  int i, j;
+  size_t table_size;
+  table_size = xbt_dynar_length(p_indexNetworkElm);
+    /* Delete link_table */
+    for (i = 0; i < table_size; i++)
+      for (j = 0; j < table_size; j++)
+        generic_free_route(TO_FLOYD_LINK(i, j));
+    xbt_free(p_linkTable);
+    /* Delete bypass dict */
+    xbt_dict_free(&p_bypassRoutes);
+    /* Delete predecessor and cost table */
+    xbt_free(p_predecessorTable);
+    xbt_free(p_costTable);
+}
 
 /* Business methods */
-static xbt_dynar_t floyd_get_onelink_routes(AS_t asg)
+xbt_dynar_t AsFloyd::getOneLinkRoutes()
 {
-  xbt_dynar_t ret = xbt_dynar_new(sizeof(onelink_t), xbt_free);
+  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;
   sg_routing_edge_t src_elm, dst_elm;
-  int table_size = xbt_dynar_length(asg->index_network_elm);
+  int 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(asg->index_network_elm,src,sg_routing_edge_t);
-      dst_elm = xbt_dynar_get_as(asg->index_network_elm,dst,sg_routing_edge_t);
-      floyd_get_route_and_latency(asg, src_elm, dst_elm, route, NULL);
+      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);
-        onelink_t onelink = xbt_new0(s_onelink_t, 1);
-        onelink->link_ptr = link;
-        if (asg->hierarchy == SURF_ROUTING_BASE) {
-          onelink->src = src_elm;
-          onelink->dst = dst_elm;
-        } else if (asg->hierarchy == SURF_ROUTING_RECURSIVE) {
-          onelink->src = route->gw_src;
-          onelink->dst = route->gw_dst;
-        }
+        OnelinkPtr onelink;
+        if (p_hierarchy == SURF_ROUTING_BASE)
+          onelink = new Onelink(link, src_elm, dst_elm);
+        else if (p_hierarchy == SURF_ROUTING_RECURSIVE)
+          onelink = new Onelink(link, route->gw_src, route->gw_dst);
+        else
+          onelink = new Onelink(link, NULL, NULL);
         xbt_dynar_push(ret, &onelink);
       }
     }
@@ -64,29 +78,27 @@ static xbt_dynar_t floyd_get_onelink_routes(AS_t asg)
   return ret;
 }
 
-static void floyd_get_route_and_latency(AS_t asg, sg_routing_edge_t src, sg_routing_edge_t dst,
-    sg_platf_route_cbarg_t res, double *lat)
+void AsFloyd::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t res, double *lat)
 {
 
   /* set utils vars */
-  as_floyd_t as = (as_floyd_t)asg;
-  size_t table_size = xbt_dynar_length(asg->index_network_elm);
+  size_t table_size = xbt_dynar_length(p_indexNetworkElm);
 
-  generic_src_dst_check(asg, src, dst);
+  this->srcDstCheck(src, dst);
 
   /* create a result route */
   xbt_dynar_t route_stack = xbt_dynar_new(sizeof(sg_platf_route_cbarg_t), NULL);
   int pred;
-  int cur = dst->id;
+  int cur = dst->m_id;
   do {
-    pred = TO_FLOYD_PRED(src->id, cur);
+    pred = TO_FLOYD_PRED(src->m_id, cur);
     if (pred == -1)
-      THROWF(arg_error, 0, "No route from '%s' to '%s'", src->name, dst->name);
+      THROWF(arg_error, 0, "No route from '%s' to '%s'", src->p_name, dst->p_name);
     xbt_dynar_push_as(route_stack, sg_platf_route_cbarg_t, TO_FLOYD_LINK(pred, cur));
     cur = pred;
-  } while (cur != src->id);
+  } while (cur != src->m_id);
 
-  if (asg->hierarchy == SURF_ROUTING_RECURSIVE) {
+  if (p_hierarchy == SURF_ROUTING_RECURSIVE) {
     res->gw_src = xbt_dynar_getlast_as(route_stack, sg_platf_route_cbarg_t)->gw_src;
     res->gw_dst = xbt_dynar_getfirst_as(route_stack, sg_platf_route_cbarg_t)->gw_dst;
   }
@@ -95,11 +107,11 @@ static void floyd_get_route_and_latency(AS_t asg, sg_routing_edge_t src, sg_rout
   while (!xbt_dynar_is_empty(route_stack)) {
     sg_platf_route_cbarg_t e_route = xbt_dynar_pop_as(route_stack, sg_platf_route_cbarg_t);
     xbt_dynar_t links;
-    sg_routing_link_t link;
+    void *link;
     unsigned int cpt;
 
-    if (asg->hierarchy == SURF_ROUTING_RECURSIVE && prev_dst_gw != NULL
-        && strcmp(prev_dst_gw->name, e_route->gw_src->name)) {
+    if (p_hierarchy == SURF_ROUTING_RECURSIVE && prev_dst_gw != NULL
+        && strcmp(prev_dst_gw->p_name, e_route->gw_src->p_name)) {
       routing_get_route_and_latency(prev_dst_gw, e_route->gw_src,
                                     &res->link_list, lat);
     }
@@ -108,7 +120,7 @@ static void floyd_get_route_and_latency(AS_t asg, sg_routing_edge_t src, sg_rout
     xbt_dynar_foreach(links, cpt, link) {
       xbt_dynar_push_as(res->link_list, sg_routing_link_t, link);
       if (lat)
-        *lat += surf_network_model->extension.network.get_link_latency(link);
+        *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(link))->getLatency();
     }
 
     prev_dst_gw = e_route->gw_dst;
@@ -116,119 +128,24 @@ static void floyd_get_route_and_latency(AS_t asg, sg_routing_edge_t src, sg_rout
   xbt_dynar_free(&route_stack);
 }
 
-static void floyd_finalize(AS_t rc)
-{
-  as_floyd_t as = (as_floyd_t) rc;
-  int i, j;
-  size_t table_size;
-  if (as) {
-    table_size = xbt_dynar_length(as->generic_routing.index_network_elm);
-    /* Delete link_table */
-    for (i = 0; i < table_size; i++)
-      for (j = 0; j < table_size; j++)
-        generic_free_route(TO_FLOYD_LINK(i, j));
-    xbt_free(as->link_table);
-    /* Delete bypass dict */
-    xbt_dict_free(&as->generic_routing.bypassRoutes);
-    /* Delete predecessor and cost table */
-    xbt_free(as->predecessor_table);
-    xbt_free(as->cost_table);
-
-    model_generic_finalize(rc);
-  }
-}
-
-AS_t model_floyd_create(void)
-{
-  as_floyd_t new_component = (as_floyd_t)model_generic_create_sized(sizeof(s_as_floyd_t));
-  new_component->generic_routing.parse_route = model_floyd_parse_route;
-  new_component->generic_routing.parse_ASroute = model_floyd_parse_route;
-  new_component->generic_routing.get_route_and_latency = floyd_get_route_and_latency;
-  new_component->generic_routing.get_onelink_routes =
-      floyd_get_onelink_routes;
-  new_component->generic_routing.get_graph = generic_get_graph;
-  new_component->generic_routing.finalize = floyd_finalize;
-  return (AS_t)new_component;
-}
-
-void model_floyd_end(AS_t current_routing)
-{
-
-  as_floyd_t as =
-      ((as_floyd_t) current_routing);
-
-  unsigned int i, j, a, b, c;
-
-  /* set the size of table routing */
-  size_t table_size = xbt_dynar_length(as->generic_routing.index_network_elm);
-
-  if(!as->link_table)
-  {
-    /* Create Cost, Predecessor and Link tables */
-    as->cost_table = xbt_new0(double, table_size * table_size);       /* link cost from host to host */
-    as->predecessor_table = xbt_new0(int, table_size * table_size);  /* predecessor host numbers */
-    as->link_table = xbt_new0(sg_platf_route_cbarg_t, table_size * table_size);    /* actual link between src and dst */
-
-    /* Initialize costs and predecessors */
-    for (i = 0; i < table_size; i++)
-      for (j = 0; j < table_size; j++) {
-        TO_FLOYD_COST(i, j) = DBL_MAX;
-        TO_FLOYD_PRED(i, j) = -1;
-        TO_FLOYD_LINK(i, j) = NULL;       /* fixed, missing in the previous version */
-      }
-  }
-
-  /* Add the loopback if needed */
-  if (routing_platf->loopback && current_routing->hierarchy == SURF_ROUTING_BASE) {
-    for (i = 0; i < table_size; i++) {
-      sg_platf_route_cbarg_t e_route = TO_FLOYD_LINK(i, i);
-      if (!e_route) {
-        e_route = xbt_new0(s_sg_platf_route_cbarg_t, 1);
-        e_route->gw_src = NULL;
-        e_route->gw_dst = NULL;
-        e_route->link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
-        xbt_dynar_push(e_route->link_list, &routing_platf->loopback);
-        TO_FLOYD_LINK(i, i) = e_route;
-        TO_FLOYD_PRED(i, i) = i;
-        TO_FLOYD_COST(i, i) = 1;
-      }
-    }
-  }
-  /* Calculate path costs */
-  for (c = 0; c < table_size; c++) {
-    for (a = 0; a < table_size; a++) {
-      for (b = 0; b < table_size; b++) {
-        if (TO_FLOYD_COST(a, c) < DBL_MAX && TO_FLOYD_COST(c, b) < DBL_MAX) {
-          if (TO_FLOYD_COST(a, b) == DBL_MAX ||
-              (TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b) <
-                  TO_FLOYD_COST(a, b))) {
-            TO_FLOYD_COST(a, b) =
-                TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b);
-            TO_FLOYD_PRED(a, b) = TO_FLOYD_PRED(c, b);
-          }
-        }
-      }
-    }
-  }
-}
-
 static int floyd_pointer_resource_cmp(const void *a, const void *b) {
   return a != b;
 }
 
-//FIXME: kill dupplicates in next function with full routing
+void AsFloyd::parseASroute(sg_platf_route_cbarg_t route){
+  parseRoute(route);
+}
 
-void model_floyd_parse_route(AS_t rc, sg_platf_route_cbarg_t route)
+void AsFloyd::parseRoute(sg_platf_route_cbarg_t route)
 {
   char *src = (char*)(route->src);
   char *dst = (char*)(route->dst);
 
   int as_route = 0;
-  as_floyd_t as = (as_floyd_t) rc;
 
   /* set the size of table routing */
-  size_t table_size = xbt_dynar_length(rc->index_network_elm);
-  sg_routing_edge_t src_net_elm, dst_net_elm;
+  size_t table_size = xbt_dynar_length(p_indexNetworkElm);
+  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);
@@ -236,13 +153,13 @@ void model_floyd_parse_route(AS_t rc, sg_platf_route_cbarg_t route)
   xbt_assert(src_net_elm, "Network elements %s not found", src);
   xbt_assert(dst_net_elm, "Network elements %s not found", dst);
 
-  if(!as->link_table)
+  if(!p_linkTable)
   {
     int i,j;
     /* Create Cost, Predecessor and Link tables */
-    as->cost_table = xbt_new0(double, table_size * table_size);       /* link cost from host to host */
-    as->predecessor_table = xbt_new0(int, table_size * table_size);  /* predecessor host numbers */
-    as->link_table = xbt_new0(sg_platf_route_cbarg_t, table_size * table_size);    /* actual link between src and dst */
+    p_costTable = xbt_new0(double, table_size * table_size);       /* link cost from host to host */
+    p_predecessorTable = xbt_new0(int, table_size * table_size);  /* predecessor host numbers */
+    p_linkTable = xbt_new0(sg_platf_route_cbarg_t, table_size * table_size);    /* actual link between src and dst */
 
     /* Initialize costs and predecessors */
     for (i = 0; i < table_size; i++)
@@ -257,14 +174,14 @@ void model_floyd_parse_route(AS_t rc, sg_platf_route_cbarg_t route)
   else{
     as_route = 1;
     XBT_DEBUG("Load ASroute from \"%s(%s)\" to \"%s(%s)\"", src,
-        route->gw_src->name, dst, route->gw_dst->name);
-    if(route->gw_dst->rc_type == SURF_NETWORK_ELEMENT_NULL)
-      xbt_die("The dst_gateway '%s' does not exist!",route->gw_dst->name);
-    if(route->gw_src->rc_type == SURF_NETWORK_ELEMENT_NULL)
-      xbt_die("The src_gateway '%s' does not exist!",route->gw_src->name);
+        route->gw_src->p_name, dst, route->gw_dst->p_name);
+    if(route->gw_dst->p_rcType == SURF_NETWORK_ELEMENT_NULL)
+      xbt_die("The dst_gateway '%s' does not exist!",route->gw_dst->p_name);
+    if(route->gw_src->p_rcType == SURF_NETWORK_ELEMENT_NULL)
+      xbt_die("The src_gateway '%s' does not exist!",route->gw_src->p_name);
   }
 
-  if(TO_FLOYD_LINK(src_net_elm->id, dst_net_elm->id))
+  if(TO_FLOYD_LINK(src_net_elm->m_id, dst_net_elm->m_id))
   {
 
     char * link_name;
@@ -277,44 +194,44 @@ void model_floyd_parse_route(AS_t rc, sg_platf_route_cbarg_t route)
       xbt_dynar_push(link_route_to_test,&link);
     }
     xbt_assert(!xbt_dynar_compare(
-        (void*)TO_FLOYD_LINK(src_net_elm->id, dst_net_elm->id)->link_list,
-        (void*)link_route_to_test,
+        TO_FLOYD_LINK(src_net_elm->m_id, dst_net_elm->m_id)->link_list,
+        link_route_to_test,
         (int_f_cpvoid_cpvoid_t) floyd_pointer_resource_cmp),
         "The route between \"%s\" and \"%s\" already exists", src,dst);
   }
   else
   {
-    TO_FLOYD_LINK(src_net_elm->id, dst_net_elm->id) =
-        generic_new_extended_route(rc->hierarchy, route, 1);
-    TO_FLOYD_PRED(src_net_elm->id, dst_net_elm->id) = src_net_elm->id;
-    TO_FLOYD_COST(src_net_elm->id, dst_net_elm->id) =
-        ((TO_FLOYD_LINK(src_net_elm->id, dst_net_elm->id))->link_list)->used;   /* count of links, old model assume 1 */
+    TO_FLOYD_LINK(src_net_elm->m_id, dst_net_elm->m_id) =
+        newExtendedRoute(p_hierarchy, route, 1);
+    TO_FLOYD_PRED(src_net_elm->m_id, dst_net_elm->m_id) = src_net_elm->m_id;
+    TO_FLOYD_COST(src_net_elm->m_id, dst_net_elm->m_id) =
+        ((TO_FLOYD_LINK(src_net_elm->m_id, dst_net_elm->m_id))->link_list)->used;   /* count of links, old model assume 1 */
   }
 
   if ( (route->symmetrical == TRUE && as_route == 0)
       || (route->symmetrical == TRUE && as_route == 1)
   )
   {
-    if(TO_FLOYD_LINK(dst_net_elm->id, src_net_elm->id))
+    if(TO_FLOYD_LINK(dst_net_elm->m_id, src_net_elm->m_id))
     {
       if(!route->gw_dst && !route->gw_src)
         XBT_DEBUG("See Route from \"%s\" to \"%s\"", dst, src);
       else
         XBT_DEBUG("See ASroute from \"%s(%s)\" to \"%s(%s)\"", dst,
-            route->gw_src->name, src, route->gw_dst->name);
+            route->gw_src->p_name, src, route->gw_dst->p_name);
       char * link_name;
       unsigned int i;
       xbt_dynar_t link_route_to_test = xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
       for(i=xbt_dynar_length(route->link_list) ;i>0 ;i--)
       {
-        link_name = xbt_dynar_get_as(route->link_list,i-1,void *);
+        link_name = xbt_dynar_get_as(route->link_list,i-1,char *);
         void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL);
         xbt_assert(link,"Link : '%s' doesn't exists.",link_name);
         xbt_dynar_push(link_route_to_test,&link);
       }
       xbt_assert(!xbt_dynar_compare(
-          (void*)TO_FLOYD_LINK(dst_net_elm->id, src_net_elm->id)->link_list,
-          (void*)link_route_to_test,
+          TO_FLOYD_LINK(dst_net_elm->m_id, src_net_elm->m_id)->link_list,
+          link_route_to_test,
           (int_f_cpvoid_cpvoid_t) floyd_pointer_resource_cmp),
           "The route between \"%s\" and \"%s\" already exists", src,dst);
     }
@@ -332,14 +249,69 @@ void model_floyd_parse_route(AS_t rc, sg_platf_route_cbarg_t route)
         XBT_DEBUG("Load Route from \"%s\" to \"%s\"", dst, src);
       else
         XBT_DEBUG("Load ASroute from \"%s(%s)\" to \"%s(%s)\"", dst,
-            route->gw_src->name, src, route->gw_dst->name);
+            route->gw_src->p_name, src, route->gw_dst->p_name);
 
-      TO_FLOYD_LINK(dst_net_elm->id, src_net_elm->id) =
-          generic_new_extended_route(rc->hierarchy, route, 0);
-      TO_FLOYD_PRED(dst_net_elm->id, src_net_elm->id) = dst_net_elm->id;
-      TO_FLOYD_COST(dst_net_elm->id, src_net_elm->id) =
-          ((TO_FLOYD_LINK(dst_net_elm->id, src_net_elm->id))->link_list)->used;   /* count of links, old model assume 1 */
+      TO_FLOYD_LINK(dst_net_elm->m_id, src_net_elm->m_id) =
+                newExtendedRoute(p_hierarchy, route, 0);
+      TO_FLOYD_PRED(dst_net_elm->m_id, src_net_elm->m_id) = dst_net_elm->m_id;
+      TO_FLOYD_COST(dst_net_elm->m_id, src_net_elm->m_id) =
+          ((TO_FLOYD_LINK(dst_net_elm->m_id, src_net_elm->m_id))->link_list)->used;   /* count of links, old model assume 1 */
     }
   }
   xbt_dynar_free(&route->link_list);
 }
+
+void AsFloyd::end(){
+  unsigned int i, j, a, b, c;
+
+  /* set the size of table routing */
+  size_t table_size = xbt_dynar_length(p_indexNetworkElm);
+
+  if(!p_linkTable) {
+    /* Create Cost, Predecessor and Link tables */
+    p_costTable = xbt_new0(double, table_size * table_size);       /* link cost from host to host */
+    p_predecessorTable = xbt_new0(int, table_size * table_size);  /* predecessor host numbers */
+    p_linkTable = xbt_new0(sg_platf_route_cbarg_t, table_size * table_size);    /* actual link between src and dst */
+
+    /* Initialize costs and predecessors */
+    for (i = 0; i < table_size; i++)
+      for (j = 0; j < table_size; j++) {
+        TO_FLOYD_COST(i, j) = DBL_MAX;
+        TO_FLOYD_PRED(i, j) = -1;
+        TO_FLOYD_LINK(i, j) = NULL;       /* fixed, missing in the previous version */
+      }
+  }
+
+  /* Add the loopback if needed */
+  if (routing_platf->p_loopback && p_hierarchy == SURF_ROUTING_BASE) {
+    for (i = 0; i < table_size; i++) {
+      sg_platf_route_cbarg_t e_route = TO_FLOYD_LINK(i, i);
+      if (!e_route) {
+        e_route = xbt_new0(s_sg_platf_route_cbarg_t, 1);
+        e_route->gw_src = NULL;
+        e_route->gw_dst = NULL;
+        e_route->link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
+        xbt_dynar_push(e_route->link_list, &routing_platf->p_loopback);
+        TO_FLOYD_LINK(i, i) = e_route;
+        TO_FLOYD_PRED(i, i) = i;
+        TO_FLOYD_COST(i, i) = 1;
+      }
+    }
+  }
+  /* Calculate path costs */
+  for (c = 0; c < table_size; c++) {
+    for (a = 0; a < table_size; a++) {
+      for (b = 0; b < table_size; b++) {
+        if (TO_FLOYD_COST(a, c) < DBL_MAX && TO_FLOYD_COST(c, b) < DBL_MAX) {
+          if (TO_FLOYD_COST(a, b) == DBL_MAX ||
+              (TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b) <
+                  TO_FLOYD_COST(a, b))) {
+            TO_FLOYD_COST(a, b) =
+                TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b);
+            TO_FLOYD_PRED(a, b) = TO_FLOYD_PRED(c, b);
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/surf/surf_routing_floyd.hpp b/src/surf/surf_routing_floyd.hpp
new file mode 100644 (file)
index 0000000..56b6805
--- /dev/null
@@ -0,0 +1,45 @@
+#include "surf_routing_generic.hpp"
+
+#ifndef SURF_ROUTING_FLOYD_HPP_
+#define SURF_ROUTING_FLOYD_HPP_
+
+
+/***********
+ * Classes *
+ ***********/
+class AsFloyd;
+typedef AsFloyd *AsFloydPtr;
+
+class AsFloyd: public AsGeneric {
+public:
+  AsFloyd();
+  ~AsFloyd();
+
+  void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
+  xbt_dynar_t getOneLinkRoutes();
+  void parseASroute(sg_platf_route_cbarg_t route);
+  void parseRoute(sg_platf_route_cbarg_t route);
+  void end();
+  //void parseASroute(sg_platf_route_cbarg_t route);
+
+  //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);
+
+  /* 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);
+
+  //virtual void parseBypassroute(sg_platf_route_cbarg_t e_route)=0;
+
+  /* vars for calculate the floyd algorith. */
+  int *p_predecessorTable;
+  double *p_costTable;
+  sg_platf_route_cbarg_t *p_linkTable;
+};
+
+
+
+#endif /* SURF_ROUTING_FLOYD_HPP_ */
similarity index 57%
rename from src/surf/surf_routing_full.c
rename to src/surf/surf_routing_full.cpp
index 89e305f..9c74b22 100644 (file)
@@ -4,49 +4,91 @@
 /* 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_private.h"
+#include "surf_routing_full.hpp"
+#include "network.hpp"
+
+extern "C" {
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_full, surf, "Routing part of surf");
+}
 
 /* Global vars */
 extern routing_platf_t routing_platf;
 extern int surf_parse_lineno;
 
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_full, surf, "Routing part of surf");
+#define TO_ROUTE_FULL(i,j) p_routingTable[(i)+(j)*table_size]
 
-#define TO_ROUTE_FULL(i,j) routing->routing_table[(i)+(j)*table_size]
+AS_t model_full_create(void)
+{
+  return new AsFull();
+}
 
-/* Routing model structure */
+void model_full_end(AS_t _routing)
+{
+  unsigned int i;
+  sg_platf_route_cbarg_t e_route;
+
+  /* set utils vars */
+  AsFullPtr routing = ((AsFullPtr) _routing);
+  size_t table_size = xbt_dynar_length(routing->p_indexNetworkElm);
 
-typedef struct s_routing_component_full {
-  s_as_t generic_routing;
-  sg_platf_route_cbarg_t *routing_table;
-} s_routing_component_full_t, *routing_component_full_t;
+  /* Create table if necessary */
+  if (!routing->p_routingTable)
+    routing->p_routingTable = xbt_new0(sg_platf_route_cbarg_t, table_size * table_size);
 
-/* Business methods */
-static xbt_dynar_t full_get_onelink_routes(AS_t rc)
+  /* Add the loopback if needed */
+  if (routing_platf->p_loopback && routing->p_hierarchy == SURF_ROUTING_BASE) {
+    for (i = 0; i < table_size; i++) {
+      e_route = routing->TO_ROUTE_FULL(i, i);
+      if (!e_route) {
+        e_route = xbt_new0(s_sg_platf_route_cbarg_t, 1);
+        e_route->gw_src = NULL;
+        e_route->gw_dst = NULL;
+        e_route->link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
+        xbt_dynar_push(e_route->link_list, &routing_platf->p_loopback);
+        routing->TO_ROUTE_FULL(i, i) = e_route;
+      }
+    }
+  }
+}
+
+AsFull::AsFull(){
+  p_routingTable = 0;
+}
+
+AsFull::~AsFull(){
+  size_t table_size = xbt_dynar_length(p_indexNetworkElm);
+  int i, j;
+  /* Delete routing table */
+  for (i = 0; i < table_size; i++)
+    for (j = 0; j < table_size; j++)
+      delete TO_ROUTE_FULL(i,j);
+  xbt_free(p_routingTable);
+}
+
+xbt_dynar_t AsFull::getOneLinkRoutes()
 {
-  xbt_dynar_t ret = xbt_dynar_new(sizeof(onelink_t), xbt_free);
-  routing_component_full_t routing = (routing_component_full_t) rc;
+  xbt_dynar_t ret = xbt_dynar_new(sizeof(OnelinkPtr), xbt_free);
 
-  int src,dst;
-  int table_size = xbt_dynar_length(rc->index_network_elm);
+  int src, dst;
+  int table_size = xbt_dynar_length(p_indexNetworkElm);
 
   for(src=0; src < table_size; src++) {
     for(dst=0; dst< table_size; dst++) {
-      sg_platf_route_cbarg_t route = TO_ROUTE_FULL(src, dst);
+      sg_platf_route_cbarg_t route = TO_ROUTE_FULL(src,dst);
       if (route) {
         if (xbt_dynar_length(route->link_list) == 1) {
           void *link = *(void **) xbt_dynar_get_ptr(route->link_list, 0);
-          onelink_t onelink = xbt_new0(s_onelink_t, 1);
-          onelink->link_ptr = link;
-          if (rc->hierarchy == SURF_ROUTING_BASE) {
-            onelink->src = xbt_dynar_get_as(rc->index_network_elm,src,sg_routing_edge_t);
-            onelink->src->id = src;
-            onelink->dst = xbt_dynar_get_as(rc->index_network_elm,dst,sg_routing_edge_t);
-            onelink->dst->id = dst;
-          } else if (rc->hierarchy == SURF_ROUTING_RECURSIVE) {
-            onelink->src = route->gw_src;
-            onelink->dst = route->gw_dst;
-          }
+          OnelinkPtr onelink;
+          if (p_hierarchy == SURF_ROUTING_BASE) {
+               RoutingEdgePtr tmp_src = xbt_dynar_get_as(p_indexNetworkElm, src, sg_routing_edge_t);
+            tmp_src->m_id = src;
+               RoutingEdgePtr tmp_dst = xbt_dynar_get_as(p_indexNetworkElm, dst, sg_routing_edge_t);
+               tmp_dst->m_id = dst;
+            onelink = new Onelink(link, tmp_src, tmp_dst);
+          } else if (p_hierarchy == SURF_ROUTING_RECURSIVE)
+            onelink = new Onelink(link, route->gw_src, route->gw_dst);
+          else
+            onelink = new Onelink(link, NULL, NULL);
           xbt_dynar_push(ret, &onelink);
           XBT_DEBUG("Push route from '%d' to '%d'",
               src,
@@ -58,25 +100,22 @@ static xbt_dynar_t full_get_onelink_routes(AS_t rc)
   return ret;
 }
 
-static void full_get_route_and_latency(AS_t rc,
-    sg_routing_edge_t src, sg_routing_edge_t dst,
-    sg_platf_route_cbarg_t res, double *lat)
+void AsFull::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t res, double *lat)
 {
   XBT_DEBUG("full_get_route_and_latency from %s[%d] to %s[%d]",
-      src->name,
-      src->id,
-      dst->name,
-      dst->id  );
+      src->p_name,
+      src->m_id,
+      dst->p_name,
+      dst->m_id  );
 
   /* set utils vars */
-  routing_component_full_t routing = (routing_component_full_t) rc;
-  size_t table_size = xbt_dynar_length(routing->generic_routing.index_network_elm);
+  size_t table_size = xbt_dynar_length(p_indexNetworkElm);
 
   sg_platf_route_cbarg_t e_route = NULL;
   void *link;
   unsigned int cpt = 0;
 
-  e_route = TO_ROUTE_FULL(src->id, dst->id);
+  e_route = TO_ROUTE_FULL(src->m_id, dst->m_id);
 
   if (e_route) {
     res->gw_src = e_route->gw_src;
@@ -84,73 +123,13 @@ static void full_get_route_and_latency(AS_t rc,
     xbt_dynar_foreach(e_route->link_list, cpt, link) {
       xbt_dynar_push(res->link_list, &link);
       if (lat)
-        *lat += surf_network_model->extension.network.get_link_latency(link);
+        *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(link))->getLatency();
     }
   }
 }
 
-static void full_finalize(AS_t rc)
-{
-  routing_component_full_t routing = (routing_component_full_t) rc;
-  size_t table_size = xbt_dynar_length(routing->generic_routing.index_network_elm);
-  int i, j;
-  if (routing) {
-    /* Delete routing table */
-    for (i = 0; i < table_size; i++)
-      for (j = 0; j < table_size; j++)
-        generic_free_route(TO_ROUTE_FULL(i, j));
-    xbt_free(routing->routing_table);
-    model_generic_finalize(rc);
-  }
-}
-
-/* Creation routing model functions */
-
-AS_t model_full_create(void)
-{
-  routing_component_full_t new_component = (routing_component_full_t)
-          model_generic_create_sized(sizeof(s_routing_component_full_t));
-
-  new_component->generic_routing.parse_route = model_full_set_route;
-  new_component->generic_routing.parse_ASroute = model_full_set_route;
-  new_component->generic_routing.get_route_and_latency =
-      full_get_route_and_latency;
-  new_component->generic_routing.get_graph = generic_get_graph;
-
-  new_component->generic_routing.get_onelink_routes = full_get_onelink_routes;
-  new_component->generic_routing.finalize = full_finalize;
-
-  return (AS_t) new_component;
-}
-
-void model_full_end(AS_t current_routing)
-{
-  unsigned int i;
-  sg_platf_route_cbarg_t e_route;
-
-  /* set utils vars */
-  routing_component_full_t routing =
-      ((routing_component_full_t) current_routing);
-  size_t table_size = xbt_dynar_length(routing->generic_routing.index_network_elm);
-
-  /* Create table if necessary */
-  if (!routing->routing_table)
-    routing->routing_table = xbt_new0(sg_platf_route_cbarg_t, table_size * table_size);
-
-  /* Add the loopback if needed */
-  if (routing_platf->loopback && current_routing->hierarchy == SURF_ROUTING_BASE) {
-    for (i = 0; i < table_size; i++) {
-      e_route = TO_ROUTE_FULL(i, i);
-      if (!e_route) {
-        e_route = xbt_new0(s_sg_platf_route_cbarg_t, 1);
-        e_route->gw_src = NULL;
-        e_route->gw_dst = NULL;
-        e_route->link_list = xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
-        xbt_dynar_push(e_route->link_list, &routing_platf->loopback);
-        TO_ROUTE_FULL(i, i) = e_route;
-      }
-    }
-  }
+void AsFull::parseASroute(sg_platf_route_cbarg_t route){
+  parseRoute(route);
 }
 
 static int full_pointer_resource_cmp(const void *a, const void *b)
@@ -158,29 +137,28 @@ static int full_pointer_resource_cmp(const void *a, const void *b)
   return a != b;
 }
 
-void model_full_set_route(AS_t rc, sg_platf_route_cbarg_t route)
+void AsFull::parseRoute(sg_platf_route_cbarg_t route)
 {
   int as_route = 0;
   char *src = (char*)(route->src);
   char *dst = (char*)(route->dst);
-  sg_routing_edge_t src_net_elm, dst_net_elm;
+  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);
 
-  routing_component_full_t routing = (routing_component_full_t) rc;
-  size_t table_size = xbt_dynar_length(routing->generic_routing.index_network_elm);
+  size_t table_size = xbt_dynar_length(p_indexNetworkElm);
 
   xbt_assert(!xbt_dynar_is_empty(route->link_list),
       "Invalid count of links, must be greater than zero (%s,%s)",
       src, dst);
 
-  if (!routing->routing_table)
-    routing->routing_table = xbt_new0(sg_platf_route_cbarg_t, table_size * table_size);
+  if (!p_routingTable)
+    p_routingTable = xbt_new0(sg_platf_route_cbarg_t, table_size * table_size);
 
-  if (TO_ROUTE_FULL(src_net_elm->id, dst_net_elm->id)) {
+  if (TO_ROUTE_FULL(src_net_elm->m_id, dst_net_elm->m_id)) {
     char *link_name;
     unsigned int i;
     xbt_dynar_t link_route_to_test =
@@ -190,7 +168,7 @@ void model_full_set_route(AS_t rc, sg_platf_route_cbarg_t route)
       xbt_assert(link, "Link : '%s' doesn't exists.", link_name);
       xbt_dynar_push(link_route_to_test, &link);
     }
-    if (xbt_dynar_compare(TO_ROUTE_FULL(src_net_elm->id, dst_net_elm->id)->link_list,
+    if (xbt_dynar_compare(TO_ROUTE_FULL(src_net_elm->m_id, dst_net_elm->m_id)->link_list,
         link_route_to_test, full_pointer_resource_cmp)) {
       surf_parse_error("A route between \"%s\" and \"%s\" already exists "
           "with a different content. "
@@ -233,15 +211,14 @@ void model_full_set_route(AS_t rc, sg_platf_route_cbarg_t route)
       //                         route->dst_gateway, subas->name);
       as_route = 1;
       XBT_DEBUG("Load ASroute from \"%s(%s)\" to \"%s(%s)\"",
-          src, route->gw_src->name, dst, route->gw_dst->name);
-      if (route->gw_dst->rc_type == SURF_NETWORK_ELEMENT_NULL)
-        xbt_die("The dst_gateway '%s' does not exist!", route->gw_dst->name);
-      if (route->gw_src->rc_type == SURF_NETWORK_ELEMENT_NULL)
-        xbt_die("The src_gateway '%s' does not exist!", route->gw_src->name);
+          src, route->gw_src->p_name, dst, route->gw_dst->p_name);
+      if (route->gw_dst->p_rcType == SURF_NETWORK_ELEMENT_NULL)
+        xbt_die("The dst_gateway '%s' does not exist!", route->gw_dst->p_name);
+      if (route->gw_src->p_rcType == SURF_NETWORK_ELEMENT_NULL)
+        xbt_die("The src_gateway '%s' does not exist!", route->gw_src->p_name);
     }
-    TO_ROUTE_FULL(src_net_elm->id, dst_net_elm->id) =
-        generic_new_extended_route(rc->hierarchy, route, 1);
-    xbt_dynar_shrink(TO_ROUTE_FULL(src_net_elm->id, dst_net_elm->id)->link_list, 0);
+    TO_ROUTE_FULL(src_net_elm->m_id, dst_net_elm->m_id) = newExtendedRoute(p_hierarchy, route, 1);
+    xbt_dynar_shrink(TO_ROUTE_FULL(src_net_elm->m_id, dst_net_elm->m_id)->link_list, 0);
   }
 
   if ( (route->symmetrical == TRUE && as_route == 0)
@@ -253,18 +230,18 @@ void model_full_set_route(AS_t rc, sg_platf_route_cbarg_t route)
       route->gw_src = route->gw_dst;
       route->gw_dst = gw_tmp;
     }
-    if (TO_ROUTE_FULL(dst_net_elm->id, src_net_elm->id)) {
+    if (TO_ROUTE_FULL(dst_net_elm->m_id, src_net_elm->m_id)) {
       char *link_name;
       unsigned int i;
       xbt_dynar_t link_route_to_test =
           xbt_dynar_new(sizeof(sg_routing_link_t), NULL);
       for (i = xbt_dynar_length(route->link_list); i > 0; i--) {
-        link_name = xbt_dynar_get_as(route->link_list, i - 1, void *);
+        link_name = xbt_dynar_get_as(route->link_list, i - 1, char *);
         void *link = xbt_lib_get_or_null(link_lib, link_name, SURF_LINK_LEVEL);
         xbt_assert(link, "Link : '%s' doesn't exists.", link_name);
         xbt_dynar_push(link_route_to_test, &link);
       }
-      xbt_assert(!xbt_dynar_compare(TO_ROUTE_FULL(dst_net_elm->id, src_net_elm->id)->link_list,
+      xbt_assert(!xbt_dynar_compare(TO_ROUTE_FULL(dst_net_elm->m_id, src_net_elm->m_id)->link_list,
           link_route_to_test,
           full_pointer_resource_cmp),
           "The route between \"%s\" and \"%s\" already exists", src,
@@ -274,11 +251,14 @@ void model_full_set_route(AS_t rc, sg_platf_route_cbarg_t route)
         XBT_DEBUG("Load Route from \"%s\" to \"%s\"", dst, src);
       else
         XBT_DEBUG("Load ASroute from \"%s(%s)\" to \"%s(%s)\"",
-            dst, route->gw_src->name, src, route->gw_dst->name);
-      TO_ROUTE_FULL(dst_net_elm->id, src_net_elm->id) =
-          generic_new_extended_route(rc->hierarchy, route, 0);
-      xbt_dynar_shrink(TO_ROUTE_FULL(dst_net_elm->id, src_net_elm->id)->link_list, 0);
+            dst, route->gw_src->p_name, src, route->gw_dst->p_name);
+      TO_ROUTE_FULL(dst_net_elm->m_id, src_net_elm->m_id) = newExtendedRoute(p_hierarchy, route, 0);
+      xbt_dynar_shrink(TO_ROUTE_FULL(dst_net_elm->m_id, src_net_elm->m_id)->link_list, 0);
     }
   }
   xbt_dynar_free(&route->link_list);
 }
+
+
+
+
diff --git a/src/surf/surf_routing_full.hpp b/src/surf/surf_routing_full.hpp
new file mode 100644 (file)
index 0000000..e3500c7
--- /dev/null
@@ -0,0 +1,38 @@
+#include "surf_routing_generic.hpp"
+
+#ifndef SURF_ROUTING_FULL_HPP_
+#define SURF_ROUTING_FULL_HPP_
+
+/***********
+ * Classes *
+ ***********/
+class AsFull;
+typedef AsFull *AsFullPtr;
+
+class AsFull: public AsGeneric {
+public:
+  sg_platf_route_cbarg_t *p_routingTable;
+
+  AsFull();
+  ~AsFull();
+
+  void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
+  xbt_dynar_t getOneLinkRoutes();
+  void parseRoute(sg_platf_route_cbarg_t route);
+  void parseASroute(sg_platf_route_cbarg_t route);
+
+  //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);
+
+  /* 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 parseBypassroute(sg_platf_route_cbarg_t e_route)=0;
+};
+
+
+#endif /* SURF_ROUTING_FULL_HPP_ */
similarity index 57%
rename from src/surf/surf_routing_generic.c
rename to src/surf/surf_routing_generic.cpp
index 9c0d4f9..d78421c 100644 (file)
@@ -6,52 +6,59 @@
 
 #include "simgrid/platf_interface.h"    // platform creation API internal interface
 
-#include "surf_routing_private.h"
-#include "surf/surf_routing.h"
-#include "surf/surfxml_parse_values.h"
+#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;
 
-AS_t model_generic_create_sized(size_t childsize) {
-  AS_t new_component = model_none_create_sized(childsize);
-
-  new_component->parse_PU = generic_parse_PU;
-  new_component->parse_AS = generic_parse_AS;
-  new_component->parse_route = NULL;
-  new_component->parse_ASroute = NULL;
-  new_component->parse_bypassroute = generic_parse_bypassroute;
-  new_component->get_route_and_latency = NULL;
-  new_component->get_onelink_routes = NULL;
-  new_component->get_bypass_route =
-      generic_get_bypassroute;
-  new_component->finalize = model_generic_finalize;
-  new_component->bypassRoutes = xbt_dict_new_homogeneous((void (*)(void *)) generic_free_route);
-
-  return new_component;
+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;
+}
+
+AsGeneric::AsGeneric() {
+  p_bypassRoutes = xbt_dict_new_homogeneous((void (*)(void *)) generic_free_route);
 }
-void model_generic_finalize(AS_t as) {
-  xbt_dict_free(&as->bypassRoutes);
-  model_none_finalize(as);
+
+AsGeneric::~AsGeneric() {
+  xbt_dict_free(&p_bypassRoutes);
 }
 
-int generic_parse_PU(AS_t as, sg_routing_edge_t elm)
+int AsGeneric::parsePU(RoutingEdgePtr elm)
 {
-  XBT_DEBUG("Load process unit \"%s\"", elm->name);
-  xbt_dynar_push_as(as->index_network_elm,sg_routing_edge_t,elm);
-  return xbt_dynar_length(as->index_network_elm)-1;
+  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 generic_parse_AS(AS_t as, sg_routing_edge_t elm)
+int AsGeneric::parseAS(RoutingEdgePtr elm)
 {
-  XBT_DEBUG("Load Autonomous system \"%s\"", elm->name);
-  xbt_dynar_push_as(as->index_network_elm,sg_routing_edge_t,elm);
-  return xbt_dynar_length(as->index_network_elm)-1;
+  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 generic_parse_bypassroute(AS_t rc, sg_platf_route_cbarg_t e_route)
+void AsGeneric::parseBypassroute(sg_platf_route_cbarg_t e_route)
 {
   char *src = (char*)(e_route->src);
   char *dst = (char*)(e_route->dst);
@@ -60,7 +67,7 @@ void generic_parse_bypassroute(AS_t rc, sg_platf_route_cbarg_t e_route)
     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 = rc->bypassRoutes;
+  xbt_dict_t dict_bypassRoutes = p_bypassRoutes;
   char *route_name;
 
   route_name = bprintf("%s#%s", src, dst);
@@ -69,13 +76,13 @@ void generic_parse_bypassroute(AS_t rc, sg_platf_route_cbarg_t e_route)
       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->name, dst, e_route->gw_dst->name);
+      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 =  generic_new_extended_route(SURF_ROUTING_RECURSIVE, e_route, 1);
+    new_e_route =  newExtendedRoute(SURF_ROUTING_RECURSIVE, e_route, 1);
   else
-    new_e_route =  generic_new_extended_route(SURF_ROUTING_BASE, e_route, 1);
+    new_e_route =  newExtendedRoute(SURF_ROUTING_BASE, e_route, 1);
 
   xbt_dynar_free(&(e_route->link_list));
 
@@ -87,7 +94,7 @@ void generic_parse_bypassroute(AS_t rc, sg_platf_route_cbarg_t e_route)
 /* ************************************************************************** */
 /* *********************** GENERIC BUSINESS METHODS ************************* */
 
-xbt_dynar_t generic_get_onelink_routes(AS_t rc) { // FIXME: kill that stub
+xbt_dynar_t AsGeneric::getOneLinkRoutes() { // FIXME: kill that stub
   xbt_die("\"generic_get_onelink_routes\" not implemented yet");
   return NULL;
 }
@@ -102,7 +109,7 @@ static const char *instr_node_name(xbt_node_t node)
 xbt_node_t new_xbt_graph_node(xbt_graph_t graph, const char *name,
                               xbt_dict_t nodes)
 {
-  xbt_node_t ret = xbt_dict_get_or_null(nodes, name);
+  xbt_node_t ret = (xbt_node_t) xbt_dict_get_or_null(nodes, name);
   if (ret)
     return ret;
 
@@ -123,10 +130,10 @@ xbt_edge_t new_xbt_graph_edge(xbt_graph_t graph, xbt_node_t s, xbt_node_t d,
 
 
   snprintf(name, len, "%s%s", sn, dn);
-  ret = xbt_dict_get_or_null(edges, name);
+  ret = (xbt_edge_t) xbt_dict_get_or_null(edges, name);
   if (ret == NULL) {
     snprintf(name, len, "%s%s", dn, sn);
-    ret = xbt_dict_get_or_null(edges, name);
+    ret = (xbt_edge_t) xbt_dict_get_or_null(edges, name);
   }
 
   if (ret == NULL) {
@@ -137,28 +144,27 @@ xbt_edge_t new_xbt_graph_edge(xbt_graph_t graph, xbt_node_t s, xbt_node_t d,
   return ret;
 }
 
-void generic_get_graph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges,
-                       AS_t rc)
+void AsGeneric::getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges)
 {
   int src, dst;
-  int table_size = xbt_dynar_length(rc->index_network_elm);
+  int table_size = xbt_dynar_length(p_indexNetworkElm);
 
 
   for (src = 0; src < table_size; src++) {
-    sg_routing_edge_t my_src =
-        xbt_dynar_get_as(rc->index_network_elm, src, sg_routing_edge_t);
+    RoutingEdgePtr my_src =
+        xbt_dynar_get_as(p_indexNetworkElm, src, RoutingEdgePtr);
     for (dst = 0; dst < table_size; dst++) {
       if (src == dst)
         continue;
-      sg_routing_edge_t my_dst =
-          xbt_dynar_get_as(rc->index_network_elm, dst, sg_routing_edge_t);
+      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);
 
-      rc->get_route_and_latency(rc, my_src, my_dst, route, NULL);
+      getRouteAndLatency(my_src, my_dst, route, NULL);
 
-      XBT_DEBUG ("get_route_and_latency %s -> %s", my_src->name, my_dst->name);
+      XBT_DEBUG ("get_route_and_latency %s -> %s", my_src->p_name, my_dst->p_name);
 
       unsigned int cpt;
       void *link;
@@ -167,15 +173,15 @@ void generic_get_graph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges,
       const char *previous_name, *current_name;
 
       if (route->gw_src) {
-        previous = new_xbt_graph_node(graph, route->gw_src->name, nodes);
-        previous_name = route->gw_src->name;
+        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->name, nodes);
-        previous_name = my_src->name;
+        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) {
-        char *link_name = ((surf_resource_t) link)->name;
+        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);
@@ -185,11 +191,11 @@ void generic_get_graph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges,
       }
 
       if (route->gw_dst) {
-        current = new_xbt_graph_node(graph, route->gw_dst->name, nodes);
-        current_name = route->gw_dst->name;
+        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->name, nodes);
-        current_name = my_dst->name;
+        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);
@@ -200,67 +206,67 @@ void generic_get_graph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges,
   }
 }
 
-sg_platf_route_cbarg_t generic_get_bypassroute(AS_t rc, sg_routing_edge_t src,
-                                               sg_routing_edge_t dst,
+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->name, dst->name);
+  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 = rc->bypassRoutes;
+  xbt_dict_t dict_bypassRoutes = p_bypassRoutes;
 
-  if(dst->rc_component == rc && src->rc_component == rc ){
-    char *route_name = bprintf("%s#%s", src->name, dst->name);
-    e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
+  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{
-    AS_t src_as, dst_as;
+    AsPtr src_as, dst_as;
     int index_src, index_dst;
     xbt_dynar_t path_src = NULL;
     xbt_dynar_t path_dst = NULL;
-    AS_t current = NULL;
-    AS_t *current_src = NULL;
-    AS_t *current_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->name, dst->name, rc->name);
+          src->p_name, dst->p_name, p_name);
 
-    src_as = src->rc_component;
-    dst_as = dst->rc_component;
+    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(AS_t), NULL);
+    path_src = xbt_dynar_new(sizeof(AsPtr), NULL);
     current = src_as;
     while (current != NULL) {
       xbt_dynar_push(path_src, &current);
-      current = current->routing_father;
+      current = current->p_routingFather;
     }
-    path_dst = xbt_dynar_new(sizeof(AS_t), NULL);
+    path_dst = xbt_dynar_new(sizeof(AsPtr), NULL);
     current = dst_as;
     while (current != NULL) {
       xbt_dynar_push(path_dst, &current);
-      current = current->routing_father;
+      current = current->p_routingFather;
     }
 
     /* (3) find the common father */
     index_src = path_src->used - 1;
     index_dst = path_dst->used - 1;
-    current_src = xbt_dynar_get_ptr(path_src, index_src);
-    current_dst = xbt_dynar_get_ptr(path_dst, index_dst);
+    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 = xbt_dynar_get_ptr(path_src, index_src);
-      current_dst = xbt_dynar_get_ptr(path_dst, 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;
@@ -273,22 +279,22 @@ sg_platf_route_cbarg_t generic_get_bypassroute(AS_t rc, sg_routing_edge_t src,
       for (i = 0; i < max; i++) {
         if (i <= max_index_src && max <= max_index_dst) {
           char *route_name = bprintf("%s#%s",
-              (*(AS_t *)
-                  (xbt_dynar_get_ptr(path_src, i)))->name,
-                  (*(AS_t *)
-                      (xbt_dynar_get_ptr(path_dst, max)))->name);
-          e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
+              (*(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",
-              (*(AS_t *)
-                  (xbt_dynar_get_ptr(path_src, max)))->name,
-                  (*(AS_t *)
-                      (xbt_dynar_get_ptr(path_dst, i)))->name);
-          e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
+              (*(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)
@@ -300,11 +306,11 @@ sg_platf_route_cbarg_t generic_get_bypassroute(AS_t rc, sg_routing_edge_t src,
 
       if (max <= max_index_src && max <= max_index_dst) {
         char *route_name = bprintf("%s#%s",
-            (*(AS_t *)
-                (xbt_dynar_get_ptr(path_src, max)))->name,
-                (*(AS_t *)
-                    (xbt_dynar_get_ptr(path_dst, max)))->name);
-        e_route_bypass = xbt_dict_get_or_null(dict_bypassRoutes, route_name);
+            (*(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)
@@ -317,7 +323,7 @@ sg_platf_route_cbarg_t generic_get_bypassroute(AS_t rc, sg_routing_edge_t src,
 
   sg_platf_route_cbarg_t new_e_route = NULL;
   if (e_route_bypass) {
-    void *link;
+    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;
@@ -327,7 +333,7 @@ sg_platf_route_cbarg_t generic_get_bypassroute(AS_t rc, sg_routing_edge_t src,
     xbt_dynar_foreach(e_route_bypass->link_list, cpt, link) {
       xbt_dynar_push(new_e_route->link_list, &link);
       if (lat)
-        *lat += surf_network_model->extension.network.get_link_latency(link);
+        *lat += link->getLatency();
     }
   }
 
@@ -337,9 +343,8 @@ sg_platf_route_cbarg_t generic_get_bypassroute(AS_t rc, sg_routing_edge_t src,
 /* ************************************************************************** */
 /* ************************* GENERIC AUX FUNCTIONS ************************** */
 /* change a route containing link names into a route containing link entities */
-sg_platf_route_cbarg_t
-generic_new_extended_route(e_surf_routing_hierarchy_t hierarchy,
-    sg_platf_route_cbarg_t routearg, int change_order) {
+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;
@@ -377,24 +382,17 @@ generic_new_extended_route(e_surf_routing_hierarchy_t hierarchy,
   return result;
 }
 
-void generic_free_route(sg_platf_route_cbarg_t route)
-{
-  if (route) {
-    xbt_dynar_free(&route->link_list);
-    xbt_free(route);
-  }
-}
 
-static AS_t generic_as_exist(AS_t find_from,
-    AS_t to_find)
+
+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;
-  AS_t elem;
-  xbt_dict_foreach(find_from->routing_sons, cursor, key, elem) {
-    if (to_find == elem || generic_as_exist(elem, to_find)) {
+  AsGenericPtr elem;
+  xbt_dict_foreach(p_routingSons, cursor, key, elem) {
+    if (to_find == elem || elem->asExist(to_find)) {
       found = 1;
       break;
     }
@@ -404,24 +402,23 @@ static AS_t generic_as_exist(AS_t find_from,
   return NULL;
 }
 
-AS_t
-generic_autonomous_system_exist(AS_t rc, char *element)
+AsPtr AsGeneric::autonomousSystemExist(char *element)
 {
   //return rc; // FIXME: BYPASSERROR OF FOREACH WITH BREAK
-  AS_t element_as, result, elem;
+  AsPtr element_as, result, elem;
   xbt_dict_cursor_t cursor = NULL;
   char *key;
-  element_as = ((sg_routing_edge_t)
+  element_as = ((RoutingEdgePtr)
       xbt_lib_get_or_null(as_router_lib, element,
-          ROUTING_ASR_LEVEL))->rc_component;
-  result = ((AS_t) - 1);
-  if (element_as != rc)
-    result = generic_as_exist(rc, element_as);
+          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->routing_sons, cursor, key, elem) {
-      found = !strcmp(elem->name, element);
+    xbt_dict_foreach(element_as->p_routingSons, cursor, key, elem) {
+      found = !strcmp(elem->p_name, element);
       if (found)
         break;
     }
@@ -431,47 +428,45 @@ generic_autonomous_system_exist(AS_t rc, char *element)
   return NULL;
 }
 
-AS_t
-generic_processing_units_exist(AS_t rc, char *element)
+AsPtr AsGeneric::processingUnitsExist(char *element)
 {
-  AS_t element_as;
-  element_as = ((sg_routing_edge_t)
+  AsPtr element_as;
+  element_as = ((RoutingEdgePtr)
       xbt_lib_get_or_null(host_lib,
-          element, ROUTING_HOST_LEVEL))->rc_component;
-  if (element_as == rc)
+          element, ROUTING_HOST_LEVEL))->p_rcComponent;
+  if (element_as == this)
     return element_as;
-  return generic_as_exist(rc, element_as);
+  return asExist(element_as);
 }
 
-void generic_src_dst_check(AS_t rc, sg_routing_edge_t src,
-    sg_routing_edge_t dst)
+void AsGeneric::srcDstCheck(RoutingEdgePtr src, RoutingEdgePtr dst)
 {
 
-  sg_routing_edge_t src_data = src;
-  sg_routing_edge_t dst_data = 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->name,
-        dst->name,
-        rc->name);
+        src->p_name,
+        dst->p_name,
+        p_name);
 
-  AS_t src_as =
-      (src_data)->rc_component;
-  AS_t dst_as =
-      (dst_data)->rc_component;
+  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->name, src_as->name,
-        dst->name, dst_as->name);
+        src->p_name, src_as->p_name,
+        dst->p_name, dst_as->p_name);
 
-  if (rc != dst_as)
+  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->name,
-        dst->name,
-        src_as->name,
-        dst_as->name,
-        rc->name);
+        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 (file)
index 0000000..ae6a615
--- /dev/null
@@ -0,0 +1,38 @@
+#include "surf_routing_none.hpp"
+
+#ifndef SURF_ROUTING_GENERIC_HPP_
+#define SURF_ROUTING_GENERIC_HPP_
+
+class AsGeneric;
+typedef AsGeneric *AsGenericPtr;
+
+void generic_free_route(sg_platf_route_cbarg_t route);
+
+class AsGeneric : public AsNone {
+public:
+  AsGeneric();
+  ~AsGeneric();
+
+  virtual void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
+  virtual xbt_dynar_t getOneLinkRoutes();
+  virtual void getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges);
+  virtual sg_platf_route_cbarg_t getBypassRoute(RoutingEdgePtr src, RoutingEdgePtr dst, double *lat);
+
+  /* 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); /* A host or a router, whatever */
+  virtual int parseAS( RoutingEdgePtr elm);
+  virtual void parseRoute(sg_platf_route_cbarg_t route);
+  virtual void parseASroute(sg_platf_route_cbarg_t route);
+  virtual void parseBypassroute(sg_platf_route_cbarg_t e_route);
+
+  virtual sg_platf_route_cbarg_t newExtendedRoute(e_surf_routing_hierarchy_t hierarchy, sg_platf_route_cbarg_t routearg, int change_order);
+  virtual AsPtr asExist(AsPtr to_find);
+  virtual AsPtr autonomousSystemExist(char *element);
+  virtual AsPtr processingUnitsExist(char *element);
+  virtual 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
deleted file mode 100644 (file)
index 1887c32..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Copyright (c) 2009-2013. 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_private.h"
-
-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;
-}
-
-static void none_get_route_and_latency(AS_t rc, sg_routing_edge_t src, sg_routing_edge_t dst,
-    sg_platf_route_cbarg_t res,double *lat)
-{
-  *lat = 0.0;
-}
-
-static void none_get_graph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges, AS_t rc)
-{
-       XBT_INFO("No routing no graph");
-}
-
-static sg_platf_route_cbarg_t none_get_bypass_route(AS_t rc,
-    sg_routing_edge_t src,
-    sg_routing_edge_t dst, double *lat) {
-  return NULL;
-}
-
-static int none_parse_PU(AS_t rc, sg_routing_edge_t elm) {
-  XBT_DEBUG("Load process unit \"%s\"", elm->name);
-  xbt_dynar_push_as(rc->index_network_elm,sg_routing_edge_t,elm);
-  /* don't care about PUs */
-  return -1;
-}
-
-static int none_parse_AS(AS_t rc, sg_routing_edge_t elm) {
-  XBT_DEBUG("Load Autonomous system \"%s\"", elm->name);
-  xbt_dynar_push_as(rc->index_network_elm,sg_routing_edge_t,elm);
-  /* even don't care about sub-ASes -- I'm as nihilist as an old punk*/
-  return -1;
-}
-
-/* Creation routing model functions */
-AS_t model_none_create() {
-  return model_none_create_sized(sizeof(s_as_t));
-}
-AS_t model_none_create_sized(size_t childsize) {
-  AS_t new_component = xbt_malloc0(childsize);
-  new_component->parse_PU = none_parse_PU;
-  new_component->parse_AS = none_parse_AS;
-  new_component->parse_route = NULL;
-  new_component->parse_ASroute = NULL;
-  new_component->parse_bypassroute = NULL;
-  new_component->get_route_and_latency = none_get_route_and_latency;
-  new_component->get_onelink_routes = none_get_onelink_routes;
-  new_component->get_bypass_route = none_get_bypass_route;
-  new_component->finalize = model_none_finalize;
-  new_component->get_graph = none_get_graph;
-  new_component->routing_sons = xbt_dict_new_homogeneous(NULL);
-  new_component->index_network_elm = xbt_dynar_new(sizeof(char*),NULL);
-
-  return new_component;
-}
-
-void model_none_finalize(AS_t as) {
-  xbt_dict_free(&as->routing_sons);
-  xbt_dynar_free(&as->index_network_elm);
-  xbt_dynar_free(&as->link_up_down_list);
-  xbt_free(as);
-}
-
diff --git a/src/surf/surf_routing_none.cpp b/src/surf/surf_routing_none.cpp
new file mode 100644 (file)
index 0000000..a8c4883
--- /dev/null
@@ -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"
+
+extern "C" {
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_none, surf, "Routing part of surf");
+}
+
+AS_t model_none_create(void)
+{
+  return new AsNone();
+}
+
+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 (file)
index 0000000..2e6d24a
--- /dev/null
@@ -0,0 +1,27 @@
+#include "surf_routing.hpp"
+
+#ifndef SURF_ROUTING_NONE_HPP_
+#define SURF_ROUTING_NONE_HPP_
+
+class AsNone : public As {
+public:
+  AsNone();
+  ~AsNone();
+  virtual void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
+  virtual xbt_dynar_t getOneLinkRoutes();
+  virtual void getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges);
+  virtual sg_platf_route_cbarg_t getBypassRoute(RoutingEdgePtr src, RoutingEdgePtr dst, double *lat);
+
+  /* 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); /* A host or a router, whatever */
+  virtual int parseAS( RoutingEdgePtr elm);
+  virtual void parseRoute(sg_platf_route_cbarg_t route);
+  virtual void parseASroute(sg_platf_route_cbarg_t route);
+  virtual void parseBypassroute(sg_platf_route_cbarg_t e_route);
+};
+
+
+#endif /* SURF_ROUTING_NONE_HPP_ */
similarity index 93%
rename from src/surf/surf_routing_private.h
rename to src/surf/surf_routing_private.hpp
index 6c2e754..e3d718b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2013. The SimGrid Team.
+/* Copyright (c) 2009, 2010, 2011. The SimGrid Team.
  * All rights reserved.                                                     */
 
 /* This program is free software; you can redistribute it and/or modify it
@@ -10,7 +10,7 @@
 #include <float.h>
 #include "internal_config.h"
 
-#include "surf_private.h"
+#include "surf.hpp"
 #include "xbt/dynar.h"
 #include "xbt/str.h"
 #include "xbt/config.h"
@@ -65,14 +65,16 @@ void model_floyd_parse_route(AS_t rc, sg_platf_route_cbarg_t route);
 
 /* ************************************************** */
 /* **************  Cluster ROUTING   **************** */
-typedef struct {
-  s_as_t generic_routing;
+class AsCluster : public As {
+public:
   void *backbone;
   void *loopback;
-  sg_routing_edge_t router;
-} s_as_cluster_t, *as_cluster_t;
+  RoutingEdgePtr p_router;
+};
+typedef AsCluster *AsClusterPtr;
+//FIXME:remove} s_as_cluster_t, *as_cluster_t;
 
-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   **************** */
diff --git a/src/surf/surf_routing_vivaldi.c b/src/surf/surf_routing_vivaldi.c
deleted file mode 100644 (file)
index 2a925fc..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright (c) 2009-2013. 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_private.h"
-
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_vivaldi, surf, "Routing part of surf");
-
-static XBT_INLINE double euclidean_dist_comp(int index, xbt_dynar_t src, xbt_dynar_t dst) {
-  double src_coord, dst_coord;
-
-  src_coord = xbt_dynar_get_as(src, index, double);
-  dst_coord = xbt_dynar_get_as(dst, index, double);
-
-  return (src_coord-dst_coord)*(src_coord-dst_coord);
-}
-
-static void vivaldi_get_route_and_latency(
-    AS_t rc, sg_routing_edge_t src_p, sg_routing_edge_t dst_p,
-    sg_platf_route_cbarg_t route, double *lat)
-{
-  s_surf_parsing_link_up_down_t info;
-
-  XBT_DEBUG("vivaldi_get_route_and_latency from '%s'[%d] '%s'[%d]",src_p->name,src_p->id,dst_p->name,dst_p->id);
-  char *src = (char*)src_p->name;
-  char *dst = (char*)dst_p->name;
-
-  if(src_p->rc_type == SURF_NETWORK_ELEMENT_AS) {
-    char *rp_src = ROUTER_PEER(src);
-    char *rp_dst = ROUTER_PEER(dst);
-    route->gw_src = xbt_lib_get_or_null(as_router_lib, rp_src,
-                                        ROUTING_ASR_LEVEL);
-    route->gw_dst = xbt_lib_get_or_null(as_router_lib, rp_dst,
-                                        ROUTING_ASR_LEVEL);
-    xbt_free(rp_src);
-    xbt_free(rp_dst);
-  }
-
-  double euclidean_dist;
-  xbt_dynar_t src_ctn, dst_ctn;
-  char *tmp_src_name, *tmp_dst_name;
-
-  if(src_p->rc_type == SURF_NETWORK_ELEMENT_HOST){
-    tmp_src_name = HOST_PEER(src);
-
-    if(rc->link_up_down_list){
-      info = xbt_dynar_get_as(rc->link_up_down_list,src_p->id,s_surf_parsing_link_up_down_t);
-      if(info.link_up) { // link up
-        xbt_dynar_push_as(route->link_list,void*,info.link_up);
-        if (lat)
-          *lat += surf_network_model->extension.network.get_link_latency(info.link_up);
-      }
-    }
-    src_ctn = xbt_lib_get_or_null(host_lib, tmp_src_name, COORD_HOST_LEVEL);
-    if(!src_ctn ) src_ctn = xbt_lib_get_or_null(host_lib, src, COORD_HOST_LEVEL);
-  }
-  else if(src_p->rc_type == SURF_NETWORK_ELEMENT_ROUTER || src_p->rc_type == SURF_NETWORK_ELEMENT_AS){
-    tmp_src_name = ROUTER_PEER(src);
-    src_ctn = xbt_lib_get_or_null(as_router_lib, tmp_src_name, COORD_ASR_LEVEL);
-  }
-  else{
-    THROW_IMPOSSIBLE;
-  }
-
-  if(dst_p->rc_type == SURF_NETWORK_ELEMENT_HOST){
-    tmp_dst_name = HOST_PEER(dst);
-
-    if(rc->link_up_down_list){
-      info = xbt_dynar_get_as(rc->link_up_down_list,dst_p->id,s_surf_parsing_link_up_down_t);
-      if(info.link_down) { // link down
-        xbt_dynar_push_as(route->link_list,void*,info.link_down);
-        if (lat)
-          *lat += surf_network_model->extension.network.get_link_latency(info.link_down);
-      }
-    }
-    dst_ctn = xbt_lib_get_or_null(host_lib, tmp_dst_name, COORD_HOST_LEVEL);
-    if(!dst_ctn ) dst_ctn = xbt_lib_get_or_null(host_lib, dst, COORD_HOST_LEVEL);
-  }
-  else if(dst_p->rc_type == SURF_NETWORK_ELEMENT_ROUTER || dst_p->rc_type == SURF_NETWORK_ELEMENT_AS){
-    tmp_dst_name = ROUTER_PEER(dst);
-    dst_ctn = xbt_lib_get_or_null(as_router_lib, tmp_dst_name, COORD_ASR_LEVEL);
-  }
-  else{
-    THROW_IMPOSSIBLE;
-  }
-
-  xbt_assert(src_ctn,"No coordinate found for element '%s'",tmp_src_name);
-  xbt_assert(dst_ctn,"No coordinate found for element '%s'",tmp_dst_name);
-  free(tmp_src_name);
-  free(tmp_dst_name);
-
-  euclidean_dist = sqrt (euclidean_dist_comp(0,src_ctn,dst_ctn)+euclidean_dist_comp(1,src_ctn,dst_ctn))
-                      + fabs(xbt_dynar_get_as(src_ctn, 2, double))+fabs(xbt_dynar_get_as(dst_ctn, 2, double));
-
-  if (lat){
-    XBT_DEBUG("Updating latency %f += %f",*lat,euclidean_dist);
-    *lat += euclidean_dist / 1000.0; //From .ms to .s
-  }
-}
-
-static int vivaldi_parse_PU(AS_t rc, sg_routing_edge_t elm) {
-  XBT_DEBUG("Load process unit \"%s\"", elm->name);
-  xbt_dynar_push_as(rc->index_network_elm,sg_routing_edge_t,elm);
-  return xbt_dynar_length(rc->index_network_elm)-1;
-}
-
-/* Creation routing model functions */
-AS_t model_vivaldi_create(void)
-{
-  AS_t new_component = model_generic_create_sized(sizeof *new_component);
-  
-  new_component->get_route_and_latency = vivaldi_get_route_and_latency;
-  new_component->parse_PU = vivaldi_parse_PU;
-  new_component->get_graph = generic_get_graph;
-  return new_component;
-}
diff --git a/src/surf/surf_routing_vivaldi.cpp b/src/surf/surf_routing_vivaldi.cpp
new file mode 100644 (file)
index 0000000..00e0552
--- /dev/null
@@ -0,0 +1,99 @@
+#include "surf_routing_vivaldi.hpp"
+
+extern "C" {
+  XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_vivaldi, surf, "Routing part of surf");
+}
+
+static XBT_INLINE double euclidean_dist_comp(int index, xbt_dynar_t src, xbt_dynar_t dst) {
+  double src_coord, dst_coord;
+
+  src_coord = xbt_dynar_get_as(src, index, double);
+  dst_coord = xbt_dynar_get_as(dst, index, double);
+
+  return (src_coord-dst_coord)*(src_coord-dst_coord);
+}
+
+AS_t model_vivaldi_create(void)
+{
+  return new AsVivaldi();
+}
+
+void AsVivaldi::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t route, double *lat)
+{
+  s_surf_parsing_link_up_down_t info;
+
+  XBT_DEBUG("vivaldi_get_route_and_latency from '%s'[%d] '%s'[%d]",
+                 src->p_name, src->m_id, dst->p_name, dst->m_id);
+
+  if(src->p_rcType == SURF_NETWORK_ELEMENT_AS) {
+    route->gw_src = (sg_routing_edge_t) xbt_lib_get_or_null(as_router_lib, ROUTER_PEER(src->p_name), ROUTING_ASR_LEVEL);
+    route->gw_dst = (sg_routing_edge_t) xbt_lib_get_or_null(as_router_lib, ROUTER_PEER(dst->p_name), ROUTING_ASR_LEVEL);
+  }
+
+  double euclidean_dist;
+  xbt_dynar_t src_ctn, dst_ctn;
+  char *tmp_src_name, *tmp_dst_name;
+
+  if(src->p_rcType == SURF_NETWORK_ELEMENT_HOST){
+    tmp_src_name = HOST_PEER(src->p_name);
+
+    if(p_linkUpDownList){
+      info = xbt_dynar_get_as(p_linkUpDownList, src->m_id, s_surf_parsing_link_up_down_t);
+      if(info.link_up) { // link up
+        xbt_dynar_push_as(route->link_list, void*, info.link_up);
+        if (lat)
+          *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(info.link_up))->getLatency();
+      }
+    }
+    src_ctn = (xbt_dynar_t) xbt_lib_get_or_null(host_lib, tmp_src_name, COORD_HOST_LEVEL);
+    if(!src_ctn ) src_ctn = (xbt_dynar_t) xbt_lib_get_or_null(host_lib, src->p_name, COORD_HOST_LEVEL);
+  }
+  else if(src->p_rcType == SURF_NETWORK_ELEMENT_ROUTER || src->p_rcType == SURF_NETWORK_ELEMENT_AS){
+    tmp_src_name = ROUTER_PEER(src->p_name);
+    src_ctn = (xbt_dynar_t) xbt_lib_get_or_null(as_router_lib, tmp_src_name, COORD_ASR_LEVEL);
+  }
+  else{
+    THROW_IMPOSSIBLE;
+  }
+
+  if(dst->p_rcType == SURF_NETWORK_ELEMENT_HOST){
+    tmp_dst_name = HOST_PEER(dst->p_name);
+
+    if(p_linkUpDownList){
+      info = xbt_dynar_get_as(p_linkUpDownList, dst->m_id, s_surf_parsing_link_up_down_t);
+      if(info.link_down) { // link down
+        xbt_dynar_push_as(route->link_list,void*,info.link_down);
+        if (lat)
+          *lat += dynamic_cast<NetworkCm02LinkPtr>(static_cast<ResourcePtr>(info.link_down))->getLatency();
+      }
+    }
+    dst_ctn = (xbt_dynar_t) xbt_lib_get_or_null(host_lib, tmp_dst_name, COORD_HOST_LEVEL);
+    if(!dst_ctn ) dst_ctn = (xbt_dynar_t) xbt_lib_get_or_null(host_lib, dst->p_name, COORD_HOST_LEVEL);
+  }
+  else if(dst->p_rcType == SURF_NETWORK_ELEMENT_ROUTER || dst->p_rcType == SURF_NETWORK_ELEMENT_AS){
+    tmp_dst_name = ROUTER_PEER(dst->p_name);
+    dst_ctn = (xbt_dynar_t) xbt_lib_get_or_null(as_router_lib, tmp_dst_name, COORD_ASR_LEVEL);
+  }
+  else{
+    THROW_IMPOSSIBLE;
+  }
+
+  xbt_assert(src_ctn,"No coordinate found for element '%s'",tmp_src_name);
+  xbt_assert(dst_ctn,"No coordinate found for element '%s'",tmp_dst_name);
+  free(tmp_src_name);
+  free(tmp_dst_name);
+
+  euclidean_dist = sqrt (euclidean_dist_comp(0,src_ctn,dst_ctn)+euclidean_dist_comp(1,src_ctn,dst_ctn))
+                      + fabs(xbt_dynar_get_as(src_ctn, 2, double))+fabs(xbt_dynar_get_as(dst_ctn, 2, double));
+
+  if (lat){
+    XBT_DEBUG("Updating latency %f += %f",*lat,euclidean_dist);
+    *lat += euclidean_dist / 1000.0; //From .ms to .s
+  }
+}
+
+int AsVivaldi::parsePU(RoutingEdgePtr elm) {
+  XBT_DEBUG("Load process unit \"%s\"", elm->p_name);
+  xbt_dynar_push_as(p_indexNetworkElm, sg_routing_edge_t, elm);
+  return xbt_dynar_length(p_indexNetworkElm)-1;
+}
diff --git a/src/surf/surf_routing_vivaldi.hpp b/src/surf/surf_routing_vivaldi.hpp
new file mode 100644 (file)
index 0000000..c71cb00
--- /dev/null
@@ -0,0 +1,42 @@
+#include "surf_routing_generic.hpp"
+#include "network.hpp"
+
+#ifndef SURF_ROUTING_VIVALDI_HPP_
+#define SURF_ROUTING_VIVALDI_HPP_
+
+/* ************************************************** */
+/* **************  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)
+
+/***********
+ * Classes *
+ ***********/
+class AsVivaldi;
+typedef AsVivaldi *AsVivaldiPtr;
+
+class AsVivaldi: public AsGeneric {
+public:
+  sg_platf_route_cbarg_t *p_routingTable;
+
+  AsVivaldi() : AsGeneric() {};
+  ~AsVivaldi() {};
+
+  void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
+  //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);
+
+  /* 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 */
+  //virtual int parseAS( RoutingEdgePtr elm)=0;
+
+  //virtual void parseBypassroute(sg_platf_route_cbarg_t e_route)=0;
+};
+
+
+#endif /* SURF_ROUTING_VIVALDI_HPP_ */
index cae8e45..2013d9a 100644 (file)
@@ -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/vm_workstation.c b/src/surf/vm_workstation.c
new file mode 100644 (file)
index 0000000..145d1c8
--- /dev/null
@@ -0,0 +1,559 @@
+/* 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. */
+
+#include "xbt/ex.h"
+#include "xbt/dict.h"
+#include "portable.h"
+#include "surf_private.h"
+#include "surf/surf_resource.h"
+#include "simgrid/sg_config.h"
+#include "vm_workstation_private.h"
+#include "cpu_cas01_private.h"
+#include "maxmin_private.h"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_vm_workstation, surf,
+                                "Logging specific to the SURF VM workstation module");
+
+
+surf_model_t surf_vm_workstation_model = NULL;
+
+/* ind means ''indirect'' that this is a reference on the whole dict_elm
+ * structure (i.e not on the surf_resource_private infos) */
+
+static void vm_ws_create(const char *name, void *ind_phys_workstation)
+{
+  workstation_CLM03_t sub_ws = surf_workstation_resource_priv(ind_phys_workstation);
+  const char *sub_ws_name = sub_ws->generic_resource.name;
+
+  /* The workstation_VM2013 struct inherits the workstation_CLM03 struct. We
+   * create a physical workstation resource, but specifying the size of
+   * s_workstation_VM2013_t and the vm workstation model object. */
+  workstation_CLM03_t ws = (workstation_CLM03_t) surf_resource_new(sizeof(s_workstation_VM2013_t),
+      surf_vm_workstation_model, name, NULL, NULL);
+
+  /* Currently, we assume a VM has no storage. */
+  ws->storage = NULL;
+
+  /* Currently, a VM uses the network resource of its physical host. In
+   * host_lib, this network resource object is refered from two different keys.
+   * When deregistering the reference that points the network resource object
+   * from the VM name, we have to make sure that the system does not call the
+   * free callback for the network resource object. The network resource object
+   * is still used by the physical machine. */
+  ws->net_elm = xbt_lib_get_or_null(host_lib, sub_ws_name, ROUTING_HOST_LEVEL);
+  xbt_lib_set(host_lib, name, ROUTING_HOST_LEVEL, ws->net_elm);
+
+  /* The SURF_WKS_LEVEL at host_lib saves workstation_CLM03 objects. Please
+   * note workstation_VM2013 objects, inheriting the workstation_CLM03
+   * structure, are also saved there. 
+   *
+   * If you want to get a workstation_VM2013 object from host_lib, see
+   * ws->generic_resouce.model->type first. If it is
+   * SURF_MODEL_TYPE_VM_WORKSTATION, you can cast ws to vm_ws. */
+  XBT_INFO("Create VM(%s)@PM(%s) with %ld mounted disks", name, sub_ws_name, xbt_dynar_length(ws->storage));
+  xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, ws);
+
+
+  /* We initialize the VM-specific members. */
+  workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
+  vm_ws->sub_ws = sub_ws;
+  vm_ws->current_state = SURF_VM_STATE_CREATED;
+
+
+
+  // //// CPU  RELATED STUFF ////
+  // Roughly, create a vcpu resource by using the values of the sub_cpu one.
+  cpu_Cas01_t sub_cpu = surf_cpu_resource_priv(ind_phys_workstation);
+
+  /* We can assume one core and cas01 cpu for the first step.
+   * Do xbt_lib_set(host_lib, name, SURF_CPU_LEVEL, cpu) if you get the resource. */
+  cpu_cas01_create_resource(name, // name
+      sub_cpu->power_peak_list,        // host->power_peak,
+      sub_cpu->pstate,
+      1,                          // host->power_scale,
+      NULL,                       // host->power_trace,
+      1,                          // host->core_amount,
+      SURF_RESOURCE_ON,           // host->initial_state,
+      NULL,                       // host->state_trace,
+      NULL,                       // host->properties,
+      surf_cpu_model_vm);
+
+
+
+  /* We create cpu_action corresponding to a VM process on the host operating system. */
+  /* FIXME: TODO: we have to peridocally input GUESTOS_NOISE to the system? how ? */
+  // vm_ws->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_phys_workstation, GUESTOS_NOISE);
+  vm_ws->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_phys_workstation, 0);
+
+
+  /* TODO:
+   * - check how network requests are scheduled between distinct processes competing for the same card.
+   */
+}
+
+/*
+ * Update the physical host of the given VM
+ */
+static void vm_ws_migrate(void *ind_vm, void *ind_dst_pm)
+{ 
+   /* ind_phys_workstation equals to smx_host_t */
+   workstation_VM2013_t ws_vm2013 = surf_workstation_resource_priv(ind_vm);
+   workstation_CLM03_t ws_clm03_dst = surf_workstation_resource_priv(ind_dst_pm);
+   const char *vm_name = ws_vm2013->ws.generic_resource.name;
+   const char *pm_name_src = ws_vm2013->sub_ws->generic_resource.name;
+   const char *pm_name_dst = ws_clm03_dst->generic_resource.name;
+
+   xbt_assert(ws_vm2013);
+   xbt_assert(ws_clm03_dst);
+
+   /* do something */
+
+   /* update net_elm with that of the destination physical host */
+   void *old_net_elm = ws_vm2013->ws.net_elm;
+   void *new_net_elm = xbt_lib_get_or_null(host_lib, pm_name_dst, ROUTING_HOST_LEVEL);
+   xbt_assert(new_net_elm);
+
+   /* Unregister the current net_elm from host_lib. Do not call the free callback. */
+   xbt_lib_unset(host_lib, vm_name, ROUTING_HOST_LEVEL, 0);
+
+   /* Then, resister the new one. */
+   ws_vm2013->ws.net_elm = new_net_elm;
+   xbt_lib_set(host_lib, vm_name, ROUTING_HOST_LEVEL, ws_vm2013->ws.net_elm);
+
+   ws_vm2013->sub_ws = ws_clm03_dst;
+
+   /* Update vcpu's action for the new pm */
+   {
+#if 0
+     XBT_INFO("cpu_action->remains %g", ws_vm2013->cpu_action->remains);
+     XBT_INFO("cost %f remains %f start %f finish %f", ws_vm2013->cpu_action->cost,
+         ws_vm2013->cpu_action->remains,
+         ws_vm2013->cpu_action->start,
+         ws_vm2013->cpu_action->finish
+         );
+     XBT_INFO("cpu_action state %d", surf_action_state_get(ws_vm2013->cpu_action));
+#endif
+
+     /* create a cpu action bound to the pm model at the destination. */
+     surf_action_t new_cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_dst_pm, 0);
+
+     e_surf_action_state_t state = surf_action_state_get(ws_vm2013->cpu_action);
+     if (state != SURF_ACTION_DONE)
+       XBT_CRITICAL("FIXME: may need a proper handling, %d", state);
+     if (ws_vm2013->cpu_action->remains > 0)
+       XBT_CRITICAL("FIXME: need copy the state(?), %f", ws_vm2013->cpu_action->remains);
+
+     int ret = surf_cpu_model_pm->action_unref(ws_vm2013->cpu_action);
+     xbt_assert(ret == 1, "Bug: some resource still remains");
+
+     ws_vm2013->cpu_action = new_cpu_action;
+   }
+
+   XBT_DEBUG("migrate VM(%s): change net_elm (%p to %p)", vm_name, old_net_elm, new_net_elm);
+   XBT_DEBUG("migrate VM(%s): change PM (%s to %s)", vm_name, pm_name_src, pm_name_dst);
+}
+
+/*
+ * A physical host does not disapper in the current SimGrid code, but a VM may
+ * disapper during a simulation.
+ */
+static void vm_ws_destroy(void *ind_vm_workstation)
+{ 
+       /* ind_phys_workstation equals to smx_host_t */
+
+  /* Before clearing the entries in host_lib, we have to pick up resources. */
+       workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_workstation);
+  cpu_Cas01_t cpu = surf_cpu_resource_priv(ind_vm_workstation);
+       const char *name = vm_ws->ws.generic_resource.name;
+
+       xbt_assert(vm_ws);
+       xbt_assert(vm_ws->ws.generic_resource.model == surf_vm_workstation_model);
+
+
+  /* We deregister objects from host_lib, without invoking the freeing callback
+   * of each level.
+   *
+   * Do not call xbt_lib_remove() here. It deletes all levels of the key,
+   * including MSG_HOST_LEVEL and others. We should unregister only what we know.
+   */
+  xbt_lib_unset(host_lib, name, SURF_CPU_LEVEL, 0);
+  xbt_lib_unset(host_lib, name, ROUTING_HOST_LEVEL, 0);
+  xbt_lib_unset(host_lib, name, SURF_WKS_LEVEL, 0);
+
+  /* TODO: comment out when VM stroage is implemented. */
+  // xbt_lib_unset(host_lib, name, SURF_STORAGE_LEVEL, 0);
+
+
+  /* Free the cpu_action of the VM. */
+  int ret = surf_cpu_model_pm->action_unref(vm_ws->cpu_action);
+  xbt_assert(ret == 1, "Bug: some resource still remains");
+
+  /* Free the cpu resource of the VM. If using power_trace, we will have to
+   * free other objects than lmm_constraint. */
+  surf_model_t cpu_model = cpu->generic_resource.model;
+  lmm_constraint_free(cpu_model->model_private->maxmin_system, cpu->constraint);
+  {
+    unsigned long i;
+    for (i = 0; i < cpu->core; i++) {
+      void *cnst_id = cpu->constraint_core[i]->id;
+      lmm_constraint_free(cpu_model->model_private->maxmin_system, cpu->constraint_core[i]);
+      xbt_free(cnst_id);
+    }
+
+    xbt_free(cpu->constraint_core);
+  }
+
+  surf_resource_free(cpu);
+
+  /* Free the network resource of the VM. */
+       // Nothing has to be done, because net_elmts is just a pointer on the physical one
+
+  /* Free the storage resource of the VM. */
+  // Not relevant yet
+
+       /* Free the workstation resource of the VM. */
+  surf_resource_free(vm_ws);
+}
+
+static int vm_ws_get_state(void *ind_vm_ws)
+{
+       return ((workstation_VM2013_t) surf_workstation_resource_priv(ind_vm_ws))->current_state;
+}
+
+static void vm_ws_set_state(void *ind_vm_ws, int state)
+{
+        ((workstation_VM2013_t) surf_workstation_resource_priv(ind_vm_ws))->current_state = state;
+}
+
+static void vm_ws_suspend(void *ind_vm_ws)
+{
+  workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+  surf_action_suspend(vm_ws->cpu_action);
+
+  vm_ws->current_state = SURF_VM_STATE_SUSPENDED;
+}
+
+static void vm_ws_resume(void *ind_vm_ws)
+{
+  workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+  surf_action_resume(vm_ws->cpu_action);
+
+  vm_ws->current_state = SURF_VM_STATE_RUNNING;
+}
+
+static void vm_ws_save(void *ind_vm_ws)
+{
+  workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+  vm_ws->current_state = SURF_VM_STATE_SAVING;
+
+  /* FIXME: do something here */
+  surf_action_suspend(vm_ws->cpu_action);
+
+  vm_ws->current_state = SURF_VM_STATE_SAVED;
+}
+
+static void vm_ws_restore(void *ind_vm_ws)
+{
+  workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+
+  vm_ws->current_state = SURF_VM_STATE_RESTORING;
+
+  /* FIXME: do something here */
+  surf_action_resume(vm_ws->cpu_action);
+
+  vm_ws->current_state = SURF_VM_STATE_RUNNING;
+}
+
+static double get_solved_value(surf_action_t cpu_action)
+{
+  lmm_variable_t var = ((surf_action_lmm_t) cpu_action)->variable;
+
+  return var->value;
+}
+
+/* In the real world, processes on the guest operating system will be somewhat
+ * degraded due to virtualization overhead. The total CPU share that these
+ * processes get is smaller than that of the VM process gets on a host
+ * operating system. */
+// const double virt_overhead = 0.95;
+const double virt_overhead = 1;
+
+static double vm_ws_share_resources(surf_model_t workstation_model, double now)
+{
+  /* TODO: udpate action's cost with the total cost of processes on the VM. */
+
+
+  /* 0. Make sure that we already calculated the resource share at the physical
+   * machine layer. */
+  {
+    unsigned int index_of_pm_ws_model = xbt_dynar_search(model_list_invoke, &surf_workstation_model);
+    unsigned int index_of_vm_ws_model = xbt_dynar_search(model_list_invoke, &surf_vm_workstation_model);
+    xbt_assert((index_of_pm_ws_model < index_of_vm_ws_model), "Cannot assume surf_workstation_model comes before");
+    /* Another option is that we call sub_ws->share_resource() here. The
+     * share_resource() function has no side-effect. We can call it here to
+     * ensure that. */
+  }
+
+
+  /* 1. Now we know how many resource should be assigned to each virtual
+   * machine. We update constraints of the virtual machine layer.
+   *
+   *
+   * If we have two virtual machine (VM1 and VM2) on a physical machine (PM1).
+   *     X1 + X2 = C       (Equation 1)
+   * where
+   *    the resource share of VM1: X1
+   *    the resource share of VM2: X2
+   *    the capacity of PM1: C
+   *
+   * Then, if we have two process (P1 and P2) on VM1.
+   *     X1_1 + X1_2 = X1  (Equation 2)
+   * where
+   *    the resource share of P1: X1_1
+   *    the resource share of P2: X1_2
+   *    the capacity of VM1: X1
+   *
+   * Equation 1 was solved in the physical machine layer.
+   * Equation 2 is solved in the virtual machine layer (here).
+   * X1 must be passed to the virtual machine laye as a constraint value.
+   *
+   **/
+
+  /* iterate for all hosts including virtual machines */
+  xbt_lib_cursor_t cursor;
+  char *key;
+  void **ind_host;
+  xbt_lib_foreach(host_lib, cursor, key, ind_host) {
+    workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
+    cpu_Cas01_t cpu_cas01 = ind_host[SURF_CPU_LEVEL];
+
+    if (!ws_clm03)
+      continue;
+    /* skip if it is not a virtual machine */
+    if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
+      continue;
+    xbt_assert(cpu_cas01, "cpu-less workstation");
+
+    /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
+    workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
+
+    double solved_value = get_solved_value(ws_vm2013->cpu_action);
+    XBT_DEBUG("assign %f to vm %s @ pm %s", solved_value,
+        ws_clm03->generic_resource.name, ws_vm2013->sub_ws->generic_resource.name);
+
+    // TODO: check lmm_update_constraint_bound() works fine instead of the below manual substitution.
+    // cpu_cas01->constraint->bound = solved_value;
+    surf_model_t cpu_model = cpu_cas01->generic_resource.model;
+    xbt_assert(cpu_model == surf_cpu_model_vm);
+    lmm_system_t vcpu_system = cpu_model->model_private->maxmin_system;
+    lmm_update_constraint_bound(vcpu_system, cpu_cas01->constraint, virt_overhead * solved_value);
+  }
+
+
+  /* 2. Calculate resource share at the virtual machine layer. */
+  double ret = ws_share_resources(workstation_model, now);
+
+
+  /* FIXME: 3. do we have to re-initialize our cpu_action object? */
+#if 0
+  /* iterate for all hosts including virtual machines */
+  xbt_lib_foreach(host_lib, cursor, key, ind_host) {
+    workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
+
+    /* skip if it is not a virtual machine */
+    if (!ws_clm03)
+      continue;
+    if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
+      continue;
+
+    /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
+    {
+#if 0
+      workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;            
+      XBT_INFO("cost %f remains %f start %f finish %f", ws_vm2013->cpu_action->cost,
+          ws_vm2013->cpu_action->remains,
+          ws_vm2013->cpu_action->start,
+          ws_vm2013->cpu_action->finish
+          );
+#endif
+#if 0
+      void *ind_sub_host = xbt_lib_get_elm_or_null(host_lib, ws_vm2013->sub_ws->generic_resource.name);      
+      surf_cpu_model_pm->action_unref(ws_vm2013->cpu_action);
+      /* FIXME: this means busy loop? */
+      // ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, GUESTOS_NOISE);
+      ws_vm2013->cpu_action = surf_cpu_model_pm->extension.cpu.execute(ind_sub_host, 0);
+#endif
+
+    }
+  }
+#endif
+
+
+  return ret;
+}
+
+
+/*
+ * A surf level object will be useless in the upper layer. Returing the
+ * dict_elm of the host.
+ **/
+static void *vm_ws_get_pm(void *ind_vm_ws)
+{
+       workstation_VM2013_t vm_ws = surf_workstation_resource_priv(ind_vm_ws);
+  const char *sub_ws_name = vm_ws->sub_ws->generic_resource.name;
+
+  return xbt_lib_get_elm_or_null(host_lib, sub_ws_name);
+}
+
+
+/* Adding a task to a VM updates the VCPU task on its physical machine. */
+static surf_action_t vm_ws_execute(void *workstation, double size)
+{
+  surf_resource_t ws = ((surf_resource_t) surf_workstation_resource_priv(workstation));
+
+  xbt_assert(ws->model->type == SURF_MODEL_TYPE_VM_WORKSTATION);
+  workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
+
+  double old_cost = vm_ws->cpu_action->cost;
+  double new_cost = old_cost + size;
+
+  XBT_DEBUG("VM(%s)@PM(%s): update dummy action's cost (%f -> %f)",
+      ws->name, vm_ws->sub_ws->generic_resource.name,
+      old_cost, new_cost);
+
+  vm_ws->cpu_action->cost = new_cost;
+
+  return ws_execute(workstation, size);
+}
+
+static void vm_ws_action_cancel(surf_action_t action)
+{
+  XBT_CRITICAL("FIXME: Not yet implemented. Reduce dummy action's cost by %f", action->cost);
+
+  ws_action_cancel(action);
+}
+
+
+/* Now we can set bound for each task by using MSG_task_set_bound. But, it does
+ * not work for the dummy CPU action of a VM. Here, we add the set_bound
+ * function for the dummy CPU action. */
+static void vm_ws_set_vm_bound(void *vm, double bound)
+{
+  surf_resource_t ws = ((surf_resource_t) surf_workstation_resource_priv(vm));
+  xbt_assert(ws->model->type == SURF_MODEL_TYPE_VM_WORKSTATION);
+  workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
+
+  surf_action_set_bound(vm_ws->cpu_action, bound);
+}
+
+
+/* set the affinity of a VM to the CPU cores of a PM */
+static void vm_ws_set_vm_affinity(void *vm, void *pm, unsigned long mask)
+{
+  surf_resource_t ws = ((surf_resource_t) surf_workstation_resource_priv(vm));
+  xbt_assert(ws->model->type == SURF_MODEL_TYPE_VM_WORKSTATION);
+  workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
+
+  surf_cpu_model_pm->set_affinity(vm_ws->cpu_action, pm, mask);
+}
+
+
+static void surf_vm_workstation_model_init_internal(void)
+{
+  surf_model_t model = surf_model_init();
+
+  model->name = "Virtual Workstation";
+  model->type = SURF_MODEL_TYPE_VM_WORKSTATION;
+
+  model->action_unref     = ws_action_unref;
+  model->action_cancel    = vm_ws_action_cancel;
+  // model->action_state_set = ws_action_state_set;
+
+
+  model->model_private->share_resources       = vm_ws_share_resources;
+  model->model_private->resource_used         = ws_resource_used;
+  model->model_private->update_actions_state  = ws_update_actions_state;
+  model->model_private->update_resource_state = ws_update_resource_state;
+  model->model_private->finalize              = ws_finalize;
+
+
+  /* operation for an action, not for VM it self */
+  model->suspend          = ws_action_suspend;
+  model->resume           = ws_action_resume;
+//   model->is_suspended     = ws_action_is_suspended;
+//   model->set_max_duration = ws_action_set_max_duration;
+  model->set_priority     = ws_action_set_priority;
+  model->set_bound        = ws_action_set_bound;
+  model->set_affinity     = ws_action_set_affinity;
+// #ifdef HAVE_TRACING
+//   model->set_category     = ws_action_set_category;
+// #endif
+  model->get_remains      = ws_action_get_remains;
+// #ifdef HAVE_LATENCY_BOUND_TRACKING
+//   model->get_latency_limited = ws_get_latency_limited;
+// #endif
+
+
+
+
+
+
+
+  xbt_assert(surf_cpu_model_vm);
+  model->extension.workstation.cpu_model = surf_cpu_model_vm;
+
+  model->extension.workstation.execute   = vm_ws_execute;
+  model->extension.workstation.sleep     = ws_action_sleep;
+  model->extension.workstation.get_state = ws_get_state;
+  model->extension.workstation.get_speed = ws_get_speed;
+  // model->extension.workstation.get_available_speed = ws_get_available_speed;
+
+  // model->extension.workstation.communicate           = ws_communicate;
+  // model->extension.workstation.get_route             = ws_get_route;
+  // model->extension.workstation.execute_parallel_task = ws_execute_parallel_task;
+  // model->extension.workstation.get_link_bandwidth    = ws_get_link_bandwidth;
+  // model->extension.workstation.get_link_latency      = ws_get_link_latency;
+  // model->extension.workstation.link_shared           = ws_link_shared;
+  // model->extension.workstation.get_properties        = ws_get_properties;
+
+  // model->extension.workstation.open   = ws_action_open;
+  // model->extension.workstation.close  = ws_action_close;
+  // model->extension.workstation.read   = ws_action_read;
+  // model->extension.workstation.write  = ws_action_write;
+  // model->extension.workstation.stat   = ws_action_stat;
+  // model->extension.workstation.unlink = ws_action_unlink;
+  // model->extension.workstation.ls     = ws_action_ls;
+
+
+  model->extension.vm_workstation.create        = vm_ws_create;
+  model->extension.vm_workstation.set_state     = vm_ws_set_state;
+  model->extension.vm_workstation.get_state     = vm_ws_get_state;
+  model->extension.vm_workstation.migrate       = vm_ws_migrate;
+  model->extension.vm_workstation.destroy       = vm_ws_destroy;
+  model->extension.vm_workstation.suspend       = vm_ws_suspend;
+  model->extension.vm_workstation.resume        = vm_ws_resume;
+  model->extension.vm_workstation.save          = vm_ws_save;
+  model->extension.vm_workstation.restore       = vm_ws_restore;
+  model->extension.vm_workstation.get_pm        = vm_ws_get_pm;
+  model->extension.vm_workstation.set_vm_bound  = vm_ws_set_vm_bound;
+  model->extension.vm_workstation.set_vm_affinity  = vm_ws_set_vm_affinity;
+
+  model->extension.workstation.set_params    = ws_set_params;
+  model->extension.workstation.get_params    = ws_get_params;
+
+  surf_vm_workstation_model = model;
+}
+
+void surf_vm_workstation_model_init(void)
+{
+  surf_vm_workstation_model_init_internal();
+  xbt_dynar_push(model_list, &surf_vm_workstation_model);
+  xbt_dynar_push(model_list_invoke, &surf_vm_workstation_model);
+}
diff --git a/src/surf/vm_workstation_private.h b/src/surf/vm_workstation_private.h
new file mode 100644 (file)
index 0000000..9524f9b
--- /dev/null
@@ -0,0 +1,37 @@
+/* Copyright (c) 2009, 2013. 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 VM_WS_PRIVATE_H_
+#define VM_WS_PRIVATE_H_
+
+#define GUESTOS_NOISE 100 // This value corresponds to the cost of the global action associated to the VM
+                          // It corresponds to the cost of a VM running no tasks.
+
+#include "workstation_private.h"
+
+/* NOTE:
+ * The workstation_VM2013 struct includes the workstation_CLM03 struct in
+ * its first member. The workstation_VM2013_t struct inherites all
+ * characteristics of the workstation_CLM03 struct. So, we can treat a
+ * workstation_VM2013 object as a workstation_CLM03 if necessary.
+ **/
+typedef struct workstation_VM2013 {
+  s_workstation_CLM03_t ws;    /* a VM is a ''v''host */
+
+  /* The workstation object of the lower layer */
+  workstation_CLM03_t sub_ws;  // Pointer to the ''host'' OS
+
+  e_surf_vm_state_t current_state;
+
+
+  surf_action_t cpu_action;
+
+} s_workstation_VM2013_t, *workstation_VM2013_t;
+
+
+void surf_vm_workstation_model_init(void);
+
+#endif /* VM_WS_PRIVATE_H_ */
index 69255a4..873cae5 100644 (file)
@@ -11,6 +11,7 @@
 #include "storage_private.h"
 #include "surf/surf_resource.h"
 #include "simgrid/sg_config.h"
+<<<<<<< HEAD
 #include <inttypes.h>
 
 typedef struct workstation_CLM03 {
@@ -18,28 +19,39 @@ typedef struct workstation_CLM03 {
   void *net_elm;
   xbt_dynar_t storage;
 } s_workstation_CLM03_t, *workstation_CLM03_t;
+||||||| merged common ancestors
+
+typedef struct workstation_CLM03 {
+  s_surf_resource_t generic_resource;   /* Must remain first to add this to a trace */
+  void *net_elm;
+  xbt_dynar_t storage;
+} s_workstation_CLM03_t, *workstation_CLM03_t;
+=======
+#include "workstation_private.h"
+#include "vm_workstation_private.h"
+#include "cpu_cas01_private.h"
+#include "maxmin_private.h"
+>>>>>>> surf++
 
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_workstation, surf,
                                 "Logging specific to the SURF workstation module");
 
 surf_model_t surf_workstation_model = NULL;
 
+
 static void workstation_new(sg_platf_host_cbarg_t host)
 {
-  workstation_CLM03_t workstation = xbt_new0(s_workstation_CLM03_t, 1);
+  const char *name = host->id;
 
-  workstation->generic_resource.model = surf_workstation_model;
-  workstation->generic_resource.name = xbt_strdup(host->id);
-  workstation->storage = xbt_lib_get_or_null(storage_lib,host->id,ROUTING_STORAGE_HOST_LEVEL);
-  workstation->net_elm = xbt_lib_get_or_null(host_lib,host->id,ROUTING_HOST_LEVEL);
-  XBT_DEBUG("Create workstation %s with %ld mounted disks",host->id,xbt_dynar_length(workstation->storage));
-  xbt_lib_set(host_lib, host->id, SURF_WKS_LEVEL, workstation);
-}
+  /* NOTE: The properties object is NULL, because the current code uses that of
+   * that of a cpu resource. */
+  workstation_CLM03_t ws = (workstation_CLM03_t) surf_resource_new(sizeof(s_workstation_CLM03_t), surf_workstation_model, name, NULL, NULL);
 
-static int ws_resource_used(void *resource_id)
-{
-  THROW_IMPOSSIBLE;             /* This model does not implement parallel tasks */
-  return -1;
+  ws->storage = xbt_lib_get_or_null(storage_lib, name, ROUTING_STORAGE_HOST_LEVEL);
+  ws->net_elm = xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL);
+
+  XBT_DEBUG("Create ws %s with %ld mounted disks", name, xbt_dynar_length(ws->storage));
+  xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, ws);
 }
 
 static void ws_parallel_action_cancel(surf_action_t action)
@@ -53,26 +65,28 @@ static int ws_parallel_action_free(surf_action_t action)
   return -1;
 }
 
-static int ws_action_unref(surf_action_t action)
+int ws_action_unref(surf_action_t action)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     return surf_network_model->action_unref(action);
-  else if (action->model_type == surf_cpu_model)
-    return surf_cpu_model->action_unref(action);
-  else if (action->model_type == surf_workstation_model)
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    return action->model_obj->action_unref(action);
+      // previously was: Adrien/Arnaud 6 feb
+         // surf_cpu_model->action_unref(action);
+  else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
     return ws_parallel_action_free(action);
   else
     DIE_IMPOSSIBLE;
   return 0;
 }
 
-static void ws_action_cancel(surf_action_t action)
+void ws_action_cancel(surf_action_t action)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->action_cancel(action);
-  else if (action->model_type == surf_cpu_model)
-    surf_cpu_model->action_cancel(action);
-  else if (action->model_type == surf_workstation_model)
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    action->model_obj->action_cancel(action);
+  else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
     ws_parallel_action_cancel(action);
   else
     DIE_IMPOSSIBLE;
@@ -82,72 +96,209 @@ static void ws_action_cancel(surf_action_t action)
 static void ws_action_state_set(surf_action_t action,
                                 e_surf_action_state_t state)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->action_state_set(action, state);
-  else if (action->model_type == surf_cpu_model)
-    surf_cpu_model->action_state_set(action, state);
-  else if (action->model_type == surf_workstation_model)
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    action->model_obj->action_state_set(action, state);
+  else if (action->model_obj->type == SURF_MODEL_TYPE_WORKSTATION)
     surf_action_state_set(action, state);
   else
     DIE_IMPOSSIBLE;
   return;
 }
 
-static double ws_share_resources(double now)
+
+/* -- The callback functions at model_private -- */
+/* These callbacks are also used for the vm workstation model. */
+int ws_resource_used(void *resource_id)
 {
-  return -1.0;
+  /* This model does not implement parallel tasks */
+  THROW_IMPOSSIBLE;
+  return -1;
+}
+
+
+/* TODO: iterating active constraint_set may be faster? */
+#if 0
+static void deactivate_dummy_cpu_action(void)
+{
+  lmm_system_t sys = surf_cpu_model_vm->model_private->maxmin_system;
+
+  lmm_constraint_t cnst;
+  xbt_swag_foreach(cnst, &sys->active_constraint_set) {
+    /* get vcpu resource */
+    surf_resource_t cpu = lmm_constraint_id(cnst);
+    xbt_assert(cpu->model == surf_cpu_model_vm);
+
+    /* get vm_ws resource */
+    workstation_CLM03_t ws = xbt_lib_get_or_null(host_lib, cpu->name, SURF_WKS_LEVEL);
+
+    /* make sure we can cast */
+    xbt_assert(ws->generic_resouce.model == surf_vm_workstation_model);
+    workstation_VM2013_t vm_ws = (workstation_VM2013_t) ws;
+
+    /* make it active in the PM layer */
+    surf_action_set_priority(vm_ws->cpu_action, 1);
+  }
+}
+#endif
+
+
+/* TODO: Delete this unused code if everything looks good. */
+#if 0
+static int constraint_is_active(cpu_Cas01_t cpu_cas01)
+{
+  surf_model_t cpu_model = cpu_cas01->generic_resource.model;
+  lmm_system_t sys = cpu_model->model_private->maxmin_system;
+  int found = 0;
+  lmm_constraint_t cnst_tmp;
+
+  xbt_swag_foreach(cnst_tmp, &sys->active_constraint_set) {
+    if (cnst_tmp == cpu_cas01->constraint) {
+      found = 1;
+      break;
+    }
+  }
+
+  return found;
+}
+#endif
+
+
+/* Each VM has a dummy CPU action on the PM layer. This CPU action works as the
+ * constraint (capacity) of the VM in the PM layer. If the VM does not have any
+ * active task, the dummy CPU action must be deactivated, so that the VM does
+ * not get any CPU share in the PM layer. */
+static void adjust_weight_of_dummy_cpu_actions(void)
+{
+  /* iterate for all hosts including virtual machines */
+  xbt_lib_cursor_t cursor;
+  char *key;
+  void **ind_host;
+
+  xbt_lib_foreach(host_lib, cursor, key, ind_host) {
+    workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
+    cpu_Cas01_t cpu_cas01 = ind_host[SURF_CPU_LEVEL];
+
+    if (!ws_clm03)
+      continue;
+    /* skip if it is not a virtual machine */
+    if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
+      continue;
+    xbt_assert(cpu_cas01, "cpu-less workstation");
+
+    /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
+    workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
+
+    lmm_system_t sys = surf_cpu_model_vm->model_private->maxmin_system;
+    int is_active = lmm_constraint_used(sys, cpu_cas01->constraint);
+    // int is_active_old = constraint_is_active(cpu_cas01);
+
+    // {
+    //   xbt_assert(is_active == is_active_old, "%d %d", is_active, is_active_old);
+    // }
+
+    if (is_active) {
+      /* some tasks exist on this VM */
+      XBT_DEBUG("set the weight of the dummy CPU action on PM to 1");
+
+      /* FIXME: we shoud use lmm_update_variable_weight() ? */
+      /* FIXME: If we assgign 1.05 and 0.05, the system makes apparently wrong values. */
+      surf_action_set_priority(ws_vm2013->cpu_action, 1);
+
+    } else {
+      /* no task exits on this VM */
+      XBT_DEBUG("set the weight of the dummy CPU action on PM to 0");
+
+      surf_action_set_priority(ws_vm2013->cpu_action, 0);
+    }
+  }
 }
 
-static void ws_update_actions_state(double now, double delta)
+
+double ws_share_resources(surf_model_t workstation_model, double now)
+{
+  if (workstation_model->type == SURF_MODEL_TYPE_WORKSTATION)
+    adjust_weight_of_dummy_cpu_actions();
+
+  /* Invoke the share_resources() callback of the physical cpu model object and
+   * the network model objects. */
+  surf_model_t cpu_model = workstation_model->extension.workstation.cpu_model;
+  surf_model_t net_model = surf_network_model;
+
+  double min_by_cpu = cpu_model->model_private->share_resources(cpu_model, now);
+  double min_by_net = net_model->model_private->share_resources(net_model, now);
+
+  XBT_DEBUG("model %p, %s min_by_cpu %f, %s min_by_net %f",
+      workstation_model, cpu_model->name, min_by_cpu, net_model->name, min_by_net);
+
+  if (min_by_cpu >= 0.0 && min_by_net >= 0.0)
+    return min(min_by_cpu, min_by_net);
+  else if (min_by_cpu >= 0.0)
+    return min_by_cpu;
+  else if (min_by_net >= 0.0)
+    return min_by_net;
+  else
+    return min_by_cpu;  /* probably min_by_cpu == min_by_net == -1 */
+}
+
+void ws_update_actions_state(surf_model_t workstation_model, double now, double delta)
 {
   return;
 }
 
-static void ws_update_resource_state(void *id,
-                                     tmgr_trace_event_t event_type,
-                                     double value, double date)
+void ws_update_resource_state(void *id, tmgr_trace_event_t event_type, double value, double date)
 {
-  THROW_IMPOSSIBLE;             /* This model does not implement parallel tasks */
+  /* This model does not implement parallel tasks */
+  THROW_IMPOSSIBLE;
 }
 
-static surf_action_t ws_execute(void *workstation, double size)
+void ws_finalize(surf_model_t workstation_model)
+{
+  surf_model_exit(workstation_model);
+  workstation_model = NULL;
+}
+
+
+
+surf_action_t ws_execute(void *workstation, double size)
 {
   surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
   return cpu->model->extension.cpu.execute(workstation, size);
 }
 
-static surf_action_t ws_action_sleep(void *workstation, double duration)
+surf_action_t ws_action_sleep(void *workstation, double duration)
 {
-  return surf_cpu_model->extension.cpu.
-      sleep(workstation, duration);
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  return cpu->model->extension.cpu.sleep(workstation, duration);
 }
 
-static void ws_action_suspend(surf_action_t action)
+void ws_action_suspend(surf_action_t action)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->suspend(action);
-  else if (action->model_type == surf_cpu_model)
-    surf_cpu_model->suspend(action);
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    action->model_obj->suspend(action);
   else
     DIE_IMPOSSIBLE;
 }
 
-static void ws_action_resume(surf_action_t action)
+void ws_action_resume(surf_action_t action)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->resume(action);
-  else if (action->model_type == surf_cpu_model)
-    surf_cpu_model->resume(action);
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    action->model_obj->resume(action);
   else
     DIE_IMPOSSIBLE;
 }
 
 static int ws_action_is_suspended(surf_action_t action)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     return surf_network_model->is_suspended(action);
-  if (action->model_type == surf_cpu_model)
-    return surf_cpu_model->is_suspended(action);
+  if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    return action->model_obj->is_suspended(action);
   DIE_IMPOSSIBLE;
   return -1;
 }
@@ -155,20 +306,41 @@ static int ws_action_is_suspended(surf_action_t action)
 static void ws_action_set_max_duration(surf_action_t action,
                                        double duration)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->set_max_duration(action, duration);
-  else if (action->model_type == surf_cpu_model)
-    surf_cpu_model->set_max_duration(action, duration);
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    action->model_obj->set_max_duration(action, duration);
   else
     DIE_IMPOSSIBLE;
 }
 
-static void ws_action_set_priority(surf_action_t action, double priority)
+void ws_action_set_priority(surf_action_t action, double priority)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->set_priority(action, priority);
-  else if (action->model_type == surf_cpu_model)
-    surf_cpu_model->set_priority(action, priority);
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    action->model_obj->set_priority(action, priority);
+  else
+    DIE_IMPOSSIBLE;
+}
+
+void ws_action_set_bound(surf_action_t action, double bound)
+{
+  /* FIXME: only for CPU model object? */
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
+    surf_network_model->set_bound(action, bound);
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    action->model_obj->set_bound(action, bound);
+  else
+    DIE_IMPOSSIBLE;
+}
+
+void ws_action_set_affinity(surf_action_t action, void *workstation, unsigned long mask)
+{
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
+    DIE_IMPOSSIBLE;
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    action->model_obj->set_affinity(action, workstation, mask);
   else
     DIE_IMPOSSIBLE;
 }
@@ -176,10 +348,10 @@ static void ws_action_set_priority(surf_action_t action, double priority)
 #ifdef HAVE_TRACING
 static void ws_action_set_category(surf_action_t action, const char *category)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     surf_network_model->set_category(action, category);
-  else if (action->model_type == surf_cpu_model)
-    surf_cpu_model->set_category(action, category);
+  else if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    action->model_obj->set_category(action, category);
   else
     DIE_IMPOSSIBLE;
 }
@@ -188,19 +360,19 @@ static void ws_action_set_category(surf_action_t action, const char *category)
 #ifdef HAVE_LATENCY_BOUND_TRACKING
 static int ws_get_latency_limited(surf_action_t action)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     return surf_network_model->get_latency_limited(action);
   else
     return 0;
 }
 #endif
 
-static double ws_action_get_remains(surf_action_t action)
+double ws_action_get_remains(surf_action_t action)
 {
-  if (action->model_type == surf_network_model)
+  if (action->model_obj->type == SURF_MODEL_TYPE_NETWORK)
     return surf_network_model->get_remains(action);
-  if (action->model_type == surf_cpu_model)
-    return surf_cpu_model->get_remains(action);
+  if (action->model_obj->type == SURF_MODEL_TYPE_CPU)
+    return action->model_obj->get_remains(action);
   DIE_IMPOSSIBLE;
   return -1.0;
 }
@@ -216,59 +388,67 @@ static surf_action_t ws_communicate(void *workstation_src,
                   dst->net_elm, size, rate);
 }
 
-static e_surf_resource_state_t ws_get_state(void *workstation)
+e_surf_resource_state_t ws_get_state(void *workstation)
 {
-  return surf_cpu_model->extension.cpu.
-      get_state(workstation);
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  return cpu->model->extension.cpu.get_state(workstation);
 }
 
-static double ws_get_speed(void *workstation, double load)
+static void ws_set_state(void *workstation, e_surf_resource_state_t state)
 {
-  return surf_cpu_model->extension.cpu.
-      get_speed(workstation, load);
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  cpu->model->extension.cpu.set_state(workstation, state);
 }
 
-static int ws_get_core(void *workstation)
+double ws_get_speed(void *workstation, double load)
 {
-  return surf_cpu_model->extension.cpu.
-      get_core(workstation);
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  return cpu->model->extension.cpu.get_speed(workstation, load);
 }
 
-
-
+static int ws_get_core(void *workstation)
+{
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  return cpu->model->extension.cpu.get_core(workstation);
+}
 static double ws_get_available_speed(void *workstation)
 {
-  return surf_cpu_model->extension.cpu.
-      get_available_speed(workstation);
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  return cpu->model->extension.cpu.get_available_speed(workstation);
 }
 
 static double ws_get_current_power_peak(void *workstation)
 {
-  return surf_cpu_model->extension.cpu.
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  return cpu->model->extension.cpu.
       get_current_power_peak(workstation);
 }
 
 static double ws_get_power_peak_at(void *workstation, int pstate_index)
 {
-  return surf_cpu_model->extension.cpu.
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  return cpu->model->extension.cpu.
       get_power_peak_at(workstation, pstate_index);
 }
 
 static int ws_get_nb_pstates(void *workstation)
 {
-  return surf_cpu_model->extension.cpu.
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  return cpu->model->extension.cpu.
       get_nb_pstates(workstation);
 }
 
 static void ws_set_power_peak_at(void *workstation, int pstate_index)
 {
-  surf_cpu_model->extension.cpu.
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  cpu->model->extension.cpu.
       set_power_peak_at(workstation, pstate_index);
 }
 
 static double ws_get_consumed_energy(void *workstation)
 {
-  return surf_cpu_model->extension.cpu.
+  surf_resource_t cpu = ((surf_resource_t) surf_cpu_resource_priv(workstation));
+  return cpu->model->extension.cpu.
       get_consumed_energy(workstation);
 }
 
@@ -334,12 +514,6 @@ static int ws_link_shared(const void *link)
   return surf_network_model->extension.network.link_shared(link);
 }
 
-static void ws_finalize(void)
-{
-  surf_model_exit(surf_workstation_model);
-  surf_workstation_model = NULL;
-}
-
 static xbt_dict_t ws_get_properties(const void *ws)
 {
   return surf_resource_properties(surf_cpu_resource_priv(ws));
@@ -486,94 +660,146 @@ static sg_storage_size_t ws_storage_get_used_size(void *workstation,const char*
   return st->used_size;
 }
 
-static void surf_workstation_model_init_internal(void)
+void ws_get_params(void *ws, ws_params_t params)
 {
-  surf_workstation_model = surf_model_init();
-
-  surf_workstation_model->name = "Workstation";
-  surf_workstation_model->action_unref = ws_action_unref;
-  surf_workstation_model->action_cancel = ws_action_cancel;
-  surf_workstation_model->action_state_set = ws_action_state_set;
-
-  surf_workstation_model->model_private->resource_used = ws_resource_used;
-  surf_workstation_model->model_private->share_resources =
-      ws_share_resources;
-  surf_workstation_model->model_private->update_actions_state =
-      ws_update_actions_state;
-  surf_workstation_model->model_private->update_resource_state =
-      ws_update_resource_state;
-  surf_workstation_model->model_private->finalize = ws_finalize;
-
-  surf_workstation_model->suspend = ws_action_suspend;
-  surf_workstation_model->resume = ws_action_resume;
-  surf_workstation_model->is_suspended = ws_action_is_suspended;
-  surf_workstation_model->set_max_duration = ws_action_set_max_duration;
-  surf_workstation_model->set_priority = ws_action_set_priority;
-#ifdef HAVE_TRACING
-  surf_workstation_model->set_category = ws_action_set_category;
-#endif
-  surf_workstation_model->get_remains = ws_action_get_remains;
-#ifdef HAVE_LATENCY_BOUND_TRACKING
-  surf_workstation_model->get_latency_limited = ws_get_latency_limited;
-#endif
+  workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
+  memcpy(params, &ws_clm03->params, sizeof(s_ws_params_t));
+}
 
-  surf_workstation_model->extension.workstation.execute = ws_execute;
-  surf_workstation_model->extension.workstation.sleep = ws_action_sleep;
-  surf_workstation_model->extension.workstation.get_state = ws_get_state;
-  surf_workstation_model->extension.workstation.get_core = ws_get_core;
-  surf_workstation_model->extension.workstation.get_speed = ws_get_speed;
-  surf_workstation_model->extension.workstation.get_available_speed =
+void ws_set_params(void *ws, ws_params_t params)
+{
+  workstation_CLM03_t ws_clm03 = surf_workstation_resource_priv(ws);
+  /* may check something here. */
+  memcpy(&ws_clm03->params, params, sizeof(s_ws_params_t));
+}
+
+static xbt_dynar_t ws_get_vms(void *pm)
+{
+  xbt_dynar_t dyn = xbt_dynar_new(sizeof(smx_host_t), NULL);
+
+  /* iterate for all hosts including virtual machines */
+  xbt_lib_cursor_t cursor;
+  char *key;
+  void **ind_host;
+  xbt_lib_foreach(host_lib, cursor, key, ind_host) {
+    workstation_CLM03_t ws_clm03 = ind_host[SURF_WKS_LEVEL];
+    if (!ws_clm03)
+      continue;
+    /* skip if it is not a virtual machine */
+    if (ws_clm03->generic_resource.model != surf_vm_workstation_model)
+      continue;
+
+    /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
+    workstation_VM2013_t ws_vm2013 = (workstation_VM2013_t) ws_clm03;
+    if (pm == ws_vm2013->sub_ws)
+      xbt_dynar_push(dyn, &ws_vm2013->sub_ws);
+  }
+
+  return dyn;
+}
+
+
+static void surf_workstation_model_init_internal(void)
+{
+  surf_model_t model = surf_model_init();
+
+  model->name = "Workstation";
+  model->type = SURF_MODEL_TYPE_WORKSTATION;
+  model->action_unref     = ws_action_unref;
+  model->action_cancel    = ws_action_cancel;
+  model->action_state_set = ws_action_state_set;
+
+  model->model_private->resource_used         = ws_resource_used;
+  model->model_private->share_resources       = ws_share_resources;
+  model->model_private->update_actions_state  = ws_update_actions_state;
+  model->model_private->update_resource_state = ws_update_resource_state;
+  model->model_private->finalize              = ws_finalize;
+
+  model->suspend          = ws_action_suspend;
+  model->resume           = ws_action_resume;
+  model->is_suspended     = ws_action_is_suspended;
+  model->set_max_duration = ws_action_set_max_duration;
+  model->set_priority     = ws_action_set_priority;
+  model->set_bound        = ws_action_set_bound;
+  model->set_affinity     = ws_action_set_affinity;
+  #ifdef HAVE_TRACING
+  model->set_category     = ws_action_set_category;
+  #endif
+  model->get_remains      = ws_action_get_remains;
+  #ifdef HAVE_LATENCY_BOUND_TRACKING
+  model->get_latency_limited = ws_get_latency_limited;
+  #endif
+
+  /* For VM support, we have a surf cpu model object for each workstation model
+   * object. The physical workstation model object has the cpu model object of
+   * the physical machine layer. */
+  xbt_assert(surf_cpu_model_pm);
+  model->extension.workstation.cpu_model = surf_cpu_model_pm;
+
+  model->extension.workstation.execute   = ws_execute;
+  model->extension.workstation.sleep     = ws_action_sleep;
+  model->extension.workstation.get_state = ws_get_state;
+  model->extension.workstation.set_state = ws_set_state;
+  model->extension.workstation.get_core  = ws_get_core;
+  model->extension.workstation.get_speed = ws_get_speed;
+  model->extension.workstation.get_available_speed =
       ws_get_available_speed;
-  surf_workstation_model->extension.workstation.get_current_power_peak = ws_get_current_power_peak;
-  surf_workstation_model->extension.workstation.get_power_peak_at = ws_get_power_peak_at;
-  surf_workstation_model->extension.workstation.get_nb_pstates = ws_get_nb_pstates;
-  surf_workstation_model->extension.workstation.set_power_peak_at = ws_set_power_peak_at;
-  surf_workstation_model->extension.workstation.get_consumed_energy = ws_get_consumed_energy;
-
-  surf_workstation_model->extension.workstation.communicate =
-      ws_communicate;
-  surf_workstation_model->extension.workstation.get_route = ws_get_route;
-  surf_workstation_model->extension.workstation.execute_parallel_task =
-      ws_execute_parallel_task;
-  surf_workstation_model->extension.workstation.get_link_bandwidth =
-      ws_get_link_bandwidth;
-  surf_workstation_model->extension.workstation.get_link_latency =
-      ws_get_link_latency;
-  surf_workstation_model->extension.workstation.link_shared =
-      ws_link_shared;
-  surf_workstation_model->extension.workstation.get_properties =
-      ws_get_properties;
-
-  surf_workstation_model->extension.workstation.open = ws_action_open;
-  surf_workstation_model->extension.workstation.close = ws_action_close;
-  surf_workstation_model->extension.workstation.read = ws_action_read;
-  surf_workstation_model->extension.workstation.write = ws_action_write;
-  surf_workstation_model->extension.workstation.unlink = ws_file_unlink;
-  surf_workstation_model->extension.workstation.ls = ws_action_ls;
-  surf_workstation_model->extension.workstation.get_size = ws_file_get_size;
-  surf_workstation_model->extension.workstation.get_info = ws_file_get_info;
-  surf_workstation_model->extension.workstation.get_free_size = ws_storage_get_free_size;
-  surf_workstation_model->extension.workstation.get_used_size = ws_storage_get_used_size;
-  surf_workstation_model->extension.workstation.get_storage_list = ws_get_storage_list;
+  model->extension.workstation.get_current_power_peak = ws_get_current_power_peak;
+  model->extension.workstation.get_power_peak_at = ws_get_power_peak_at;
+  model->extension.workstation.get_nb_pstates = ws_get_nb_pstates;
+  model->extension.workstation.set_power_peak_at = ws_set_power_peak_at;
+  model->extension.workstation.get_consumed_energy = ws_get_consumed_energy;
+
+  model->extension.workstation.communicate = ws_communicate;
+  model->extension.workstation.get_route = ws_get_route;
+  model->extension.workstation.execute_parallel_task = ws_execute_parallel_task;
+  model->extension.workstation.get_link_bandwidth = ws_get_link_bandwidth;
+  model->extension.workstation.get_link_latency = ws_get_link_latency;
+  model->extension.workstation.link_shared = ws_link_shared;
+  model->extension.workstation.get_properties = ws_get_properties;
+
+  model->extension.workstation.open = ws_action_open;
+  model->extension.workstation.close = ws_action_close;
+  model->extension.workstation.read = ws_action_read;
+  model->extension.workstation.write = ws_action_write;
+  model->extension.workstation.unlink = ws_file_unlink;
+  model->extension.workstation.ls = ws_action_ls;
+  model->extension.workstation.get_size = ws_file_get_size;
+  model->extension.workstation.get_info = ws_file_get_info;
+  model->extension.workstation.get_free_size = ws_storage_get_free_size;
+  model->extension.workstation.get_used_size = ws_storage_get_used_size;
+  model->extension.workstation.get_storage_list = ws_get_storage_list;
+
+  model->extension.workstation.get_params = ws_get_params;
+  model->extension.workstation.set_params = ws_set_params;
+  model->extension.workstation.get_vms    = ws_get_vms;
+
+  surf_workstation_model = model;
 }
 
 void surf_workstation_model_init_current_default(void)
 {
-  surf_workstation_model_init_internal();
   xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", "yes");
   surf_cpu_model_init_Cas01();
   surf_network_model_init_LegrandVelho();
 
+  /* surf_cpu_mode_pm and surf_network_model must be initialized in advance. */
+  xbt_assert(surf_cpu_model_pm);
+  xbt_assert(surf_network_model);
+  surf_workstation_model_init_internal();
+
   xbt_dynar_push(model_list, &surf_workstation_model);
+  xbt_dynar_push(model_list_invoke, &surf_workstation_model);
   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_cpu_model_pm, "No CPU model defined yet!");
   xbt_assert(surf_network_model, "No network model defined yet!");
+
   surf_workstation_model_init_internal();
   xbt_dynar_push(model_list, &surf_workstation_model);
+  xbt_dynar_push(model_list_invoke, &surf_workstation_model);
   sg_platf_host_add_cb(workstation_new);
 }
diff --git a/src/surf/workstation.cpp b/src/surf/workstation.cpp
new file mode 100644 (file)
index 0000000..4771d97
--- /dev/null
@@ -0,0 +1,427 @@
+#include "workstation.hpp"
+#include "vm_workstation.hpp"
+#include "cpu_cas01.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
+
+/*************
+ * CallBacks *
+ *************/
+
+static void workstation_new(sg_platf_host_cbarg_t host){
+  surf_workstation_model->createResource(host->id);
+}
+
+/*********
+ * Model *
+ *********/
+
+void surf_workstation_model_init_current_default(void)
+{
+  surf_workstation_model = new WorkstationModel();
+  xbt_cfg_setdefault_boolean(_sg_cfg_set, "network/crosstraffic", "yes");
+  surf_cpu_model_init_Cas01();
+  surf_network_model_init_LegrandVelho();
+
+  ModelPtr model = static_cast<ModelPtr>(surf_workstation_model);
+  xbt_dynar_push(model_list, &model);
+  xbt_dynar_push(model_list_invoke, &model);
+  sg_platf_host_add_cb(workstation_new);
+}
+
+void surf_workstation_model_init_compound()
+{
+
+  xbt_assert(surf_cpu_model_pm, "No CPU model defined yet!");
+  xbt_assert(surf_network_model, "No network model defined yet!");
+  surf_workstation_model = new WorkstationModel();
+
+  ModelPtr model = static_cast<ModelPtr>(surf_workstation_model);
+  xbt_dynar_push(model_list, &model);
+  xbt_dynar_push(model_list_invoke, &model);
+  sg_platf_host_add_cb(workstation_new);
+}
+
+WorkstationModel::WorkstationModel() : Model("Workstation") {
+}
+
+WorkstationModel::~WorkstationModel() {
+}
+
+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),
+                 dynamic_cast<CpuPtr>(static_cast<ResourcePtr>(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, static_cast<ResourcePtr>(workstation));
+  return workstation;
+}
+
+/* Each VM has a dummy CPU action on the PM layer. This CPU action works as the
+ * constraint (capacity) of the VM in the PM layer. If the VM does not have any
+ * active task, the dummy CPU action must be deactivated, so that the VM does
+ * not get any CPU share in the PM layer. */
+void WorkstationModel::adjustWeightOfDummyCpuActions()
+{
+  /* iterate for all hosts including virtual machines */
+  xbt_lib_cursor_t cursor;
+  char *key;
+  void **ind_host;
+
+  xbt_lib_foreach(host_lib, cursor, key, ind_host) {
+    WorkstationCLM03Ptr ws_clm03 = dynamic_cast<WorkstationCLM03Ptr>(
+                                      static_cast<ResourcePtr>(ind_host[SURF_WKS_LEVEL]));
+    CpuCas01LmmPtr cpu_cas01 = dynamic_cast<CpuCas01LmmPtr>(
+                               static_cast<ResourcePtr>(ind_host[SURF_CPU_LEVEL]));
+
+    if (!ws_clm03)
+      continue;
+    /* skip if it is not a virtual machine */
+    if (ws_clm03->p_model != static_cast<ModelPtr>(surf_vm_workstation_model))
+      continue;
+    xbt_assert(cpu_cas01, "cpu-less workstation");
+
+    /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
+    WorkstationVM2013Ptr ws_vm2013 = dynamic_cast<WorkstationVM2013Ptr>(ws_clm03);
+
+    int is_active = lmm_constraint_used(cpu_cas01->p_model->p_maxminSystem, cpu_cas01->p_constraint);
+    // int is_active_old = constraint_is_active(cpu_cas01);
+
+    // {
+    //   xbt_assert(is_active == is_active_old, "%d %d", is_active, is_active_old);
+    // }
+
+    if (is_active) {
+      /* some tasks exist on this VM */
+      XBT_DEBUG("set the weight of the dummy CPU action on PM to 1");
+
+      /* FIXME: we shoud use lmm_update_variable_weight() ? */
+      /* FIXME: If we assgign 1.05 and 0.05, the system makes apparently wrong values. */
+      surf_action_set_priority(ws_vm2013->p_action, 1);
+
+    } else {
+      /* no task exits on this VM */
+      XBT_DEBUG("set the weight of the dummy CPU action on PM to 0");
+
+      surf_action_set_priority(ws_vm2013->p_action, 0);
+    }
+  }
+}
+
+double WorkstationModel::shareResources(double now){
+  adjustWeightOfDummyCpuActions();
+
+  double min_by_cpu = surf_cpu_model_pm->shareResources(now);
+  double min_by_net = surf_network_model->shareResources(now);
+
+  XBT_DEBUG("model %p, %s min_by_cpu %f, %s min_by_net %f",
+      this, surf_cpu_model_pm->m_name.c_str(), min_by_cpu, surf_network_model->m_name.c_str(), min_by_net);
+
+  if (min_by_cpu >= 0.0 && min_by_net >= 0.0)
+    return min(min_by_cpu, min_by_net);
+  else if (min_by_cpu >= 0.0)
+    return min_by_cpu;
+  else if (min_by_net >= 0.0)
+    return min_by_net;
+  else
+    return min_by_cpu;  /* probably min_by_cpu == min_by_net == -1 */
+}
+
+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){
+  return 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();
+}
+
+double WorkstationCLM03::getCurrentPowerPeak()
+{
+  return p_cpu->getCurrentPowerPeak();
+}
+
+double WorkstationCLM03::getPowerPeakAt(int pstate_index)
+{
+  return p_cpu->getPowerPeakAt(pstate_index);
+}
+
+int WorkstationCLM03::getNbPstates()
+{
+  return p_cpu->getNbPstates();
+}
+
+void WorkstationCLM03::setPowerPeakAt(int pstate_index)
+{
+       p_cpu->setPowerPeakAt(pstate_index);
+}
+
+double WorkstationCLM03::getConsumedEnergy()
+{
+  return p_cpu->getConsumedEnergy();
+}
+
+
+xbt_dict_t WorkstationCLM03::getProperties()
+{
+  return p_cpu->m_properties;
+}
+
+
+StoragePtr WorkstationCLM03::findStorageOnMountList(const char* mount)
+{
+  StoragePtr st = NULL;
+  s_mount_t mnt;
+  unsigned int cursor;
+
+  XBT_DEBUG("Search for storage name '%s' on '%s'", mount, m_name);
+  xbt_dynar_foreach(p_storage,cursor,mnt)
+  {
+    XBT_DEBUG("See '%s'",mnt.name);
+    if(!strcmp(mount,mnt.name)){
+      st = dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(mnt.storage));
+      break;
+    }
+  }
+  if(!st) xbt_die("Can't find mount '%s' for '%s'", mount, m_name);
+  return st;
+}
+
+xbt_dict_t WorkstationCLM03::getStorageList()
+{
+  s_mount_t mnt;
+  unsigned int i;
+  xbt_dict_t storage_list = xbt_dict_new_homogeneous(NULL);
+  char *storage_name = NULL;
+
+  xbt_dynar_foreach(p_storage,i,mnt){
+    storage_name = (char *)dynamic_cast<StoragePtr>(static_cast<ResourcePtr>(mnt.storage))->m_name;
+    xbt_dict_set(storage_list,mnt.name,storage_name,NULL);
+  }
+  return storage_list;
+}
+
+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->mount);
+  XBT_DEBUG("CLOSE on disk '%s'",st->m_name);
+  return st->close(fd);
+}
+
+ActionPtr WorkstationCLM03::read(surf_file_t fd, sg_storage_size_t size) {
+  StoragePtr st = findStorageOnMountList(fd->mount);
+  XBT_DEBUG("READ on disk '%s'",st->m_name);
+  return st->read(fd, size);
+}
+
+ActionPtr WorkstationCLM03::write(surf_file_t fd, sg_storage_size_t size) {
+  StoragePtr st = findStorageOnMountList(fd->mount);
+  XBT_DEBUG("WRITE on disk '%s'",st->m_name);
+  return st->write(fd, size);
+}
+
+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->mount);
+    /* 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->mount);
+      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);
+}
+
+sg_storage_size_t WorkstationCLM03::getSize(surf_file_t fd){
+  return fd->size;
+}
+
+xbt_dynar_t WorkstationCLM03::getInfo( surf_file_t fd)
+{
+  StoragePtr st = findStorageOnMountList(fd->mount);
+  sg_storage_size_t *psize = xbt_new(sg_storage_size_t, 1);
+  *psize = fd->size;
+  xbt_dynar_t info = xbt_dynar_new(sizeof(void*), NULL);
+  xbt_dynar_push_as(info, sg_storage_size_t *, psize);
+  xbt_dynar_push_as(info, void *, fd->mount);
+  xbt_dynar_push_as(info, void *, (void *)st->m_name);
+  xbt_dynar_push_as(info, void *, st->p_typeId);
+  xbt_dynar_push_as(info, void *, st->p_contentType);
+
+  return info;
+}
+
+sg_storage_size_t WorkstationCLM03::getFreeSize(const char* name)
+{
+  StoragePtr st = findStorageOnMountList(name);
+  return st->m_size - st->m_usedSize;
+}
+
+sg_storage_size_t WorkstationCLM03::getUsedSize(const char* name)
+{
+  StoragePtr st = findStorageOnMountList(name);
+  return st->m_usedSize;
+}
+
+e_surf_resource_state_t WorkstationCLM03Lmm::getState() {
+  return WorkstationCLM03::getState();
+}
+
+xbt_dynar_t WorkstationCLM03::getVms()
+{
+  xbt_dynar_t dyn = xbt_dynar_new(sizeof(smx_host_t), NULL);
+
+  /* iterate for all hosts including virtual machines */
+  xbt_lib_cursor_t cursor;
+  char *key;
+  void **ind_host;
+  xbt_lib_foreach(host_lib, cursor, key, ind_host) {
+    WorkstationCLM03Ptr ws_clm03 = dynamic_cast<WorkstationCLM03Ptr>(static_cast<ResourcePtr>(ind_host[SURF_WKS_LEVEL]));
+    if (!ws_clm03)
+      continue;
+    /* skip if it is not a virtual machine */
+    if (ws_clm03->p_model != static_cast<ModelPtr>(surf_vm_workstation_model))
+      continue;
+
+    /* It is a virtual machine, so we can cast it to workstation_VM2013_t */
+    WorkstationVM2013Ptr ws_vm2013 = dynamic_cast<WorkstationVM2013Ptr>(ws_clm03);
+    if (this == ws_vm2013-> p_subWs)
+      xbt_dynar_push(dyn, &ws_vm2013->p_subWs);
+  }
+
+  return dyn;
+}
+
+void WorkstationCLM03::getParams(ws_params_t params)
+{
+  memcpy(params, &p_params, sizeof(s_ws_params_t));
+}
+
+void WorkstationCLM03::setParams(ws_params_t params)
+{
+  /* may check something here. */
+  memcpy(&p_params, params, sizeof(s_ws_params_t));
+}
+/**********
+ * Action *
+ **********/
diff --git a/src/surf/workstation.hpp b/src/surf/workstation.hpp
new file mode 100644 (file)
index 0000000..d3c18ad
--- /dev/null
@@ -0,0 +1,131 @@
+#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 WorkstationCLM03Lmm;
+typedef WorkstationCLM03Lmm *WorkstationCLM03LmmPtr;
+
+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();
+  ~WorkstationModel();
+  virtual void parseInit(sg_platf_host_cbarg_t host);
+  WorkstationCLM03Ptr createResource(string name);
+  double shareResources(double now);
+  virtual void adjustWeightOfDummyCpuActions();
+
+  void updateActionsState(double now, double delta);
+
+  virtual ActionPtr executeParallelTask(int workstation_nb,
+                                        void **workstation_list,
+                                        double *computation_amount,
+                                        double *communication_amount,
+                                        double rate);
+ virtual xbt_dynar_t getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst);
+ virtual 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);
+
+  virtual ActionPtr execute(double size);
+  virtual ActionPtr sleep(double duration);
+  e_surf_resource_state_t getState();
+
+  virtual int getCore();
+  virtual double getSpeed(double load);
+  virtual double getAvailableSpeed();
+  virtual double getCurrentPowerPeak();
+  virtual double getPowerPeakAt(int pstate_index);
+  virtual int getNbPstates();
+  virtual void setPowerPeakAt(int pstate_index);
+  virtual double getConsumedEnergy();
+
+  xbt_dict_t getProperties();
+
+  StoragePtr findStorageOnMountList(const char* storage);
+  xbt_dict_t getStorageList();
+  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);
+  sg_storage_size_t getSize(surf_file_t fd);
+  ActionPtr read(surf_file_t fd, sg_storage_size_t size);
+  ActionPtr write(surf_file_t fd, sg_storage_size_t size);
+  xbt_dynar_t getInfo( surf_file_t fd);
+  sg_storage_size_t getFreeSize(const char* name);
+  sg_storage_size_t getUsedSize(const char* name);
+
+  bool isUsed();
+  //bool isShared();
+  xbt_dynar_t p_storage;
+  RoutingEdgePtr p_netElm;
+  CpuPtr p_cpu;
+  NetworkCm02LinkPtr p_network;
+
+  xbt_dynar_t getVms();
+
+  /* common with vm */
+  void getParams(ws_params_t params);
+  void setParams(ws_params_t params);
+  s_ws_params_t p_params;
+};
+
+class WorkstationCLM03Lmm : virtual public WorkstationCLM03, public ResourceLmm {
+public:
+  WorkstationCLM03Lmm(WorkstationModelPtr model, const char* name, xbt_dict_t props, xbt_dynar_t storage, RoutingEdgePtr netElm, CpuPtr cpu):
+         WorkstationCLM03(model, name, props, storage, netElm, cpu){};
+  e_surf_resource_state_t getState();
+};
+
+/**********
+ * 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_private.h b/src/surf/workstation_private.h
new file mode 100644 (file)
index 0000000..dfe3af6
--- /dev/null
@@ -0,0 +1,42 @@
+/* Copyright (c) 2009, 2013. 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 WS_PRIVATE_H_
+#define WS_PRIVATE_H_
+typedef struct workstation_CLM03 {
+  s_surf_resource_t generic_resource;   /* Must remain first to add this to a trace */
+  void *net_elm;
+  xbt_dynar_t storage;
+
+  /* common with vm */
+  s_ws_params_t params;
+
+} s_workstation_CLM03_t, *workstation_CLM03_t;
+
+int ws_action_unref(surf_action_t action);
+
+int ws_resource_used(void *resource_id);
+double ws_share_resources(surf_model_t workstation_model, double now);
+void ws_update_actions_state(surf_model_t workstation_model, double now, double delta);
+void ws_update_resource_state(void *id, tmgr_trace_event_t event_type, double value, double date);
+void ws_finalize(surf_model_t workstation_model);
+
+void ws_action_set_priority(surf_action_t action, double priority);
+void ws_action_set_bound(surf_action_t action, double bound);
+void ws_action_set_affinity(surf_action_t action, void *workstation, unsigned long mask);
+
+surf_action_t ws_execute(void *workstation, double size);
+surf_action_t ws_action_sleep(void *workstation, double duration);
+void ws_action_suspend(surf_action_t action);
+void ws_action_resume(surf_action_t action);
+void ws_action_cancel(surf_action_t action);
+e_surf_resource_state_t ws_get_state(void *workstation);
+double ws_get_speed(void *workstation, double load);
+double ws_action_get_remains(surf_action_t action);
+
+void ws_get_params(void *ws, ws_params_t params);
+void ws_set_params(void *ws, ws_params_t params);
+#endif /* WS_PRIVATE_H_ */
index e6d026b..5c171d1 100644 (file)
@@ -219,13 +219,13 @@ static int ptask_resource_used(void *resource_id)
 
 }
 
-static double ptask_share_resources(double now)
+static double ptask_share_resources(surf_model_t workstation_model, double now)
 {
   s_surf_action_workstation_L07_t s_action;
   surf_action_workstation_L07_t action = NULL;
 
   xbt_swag_t running_actions =
-      surf_workstation_model->states.running_action_set;
+      workstation_model->states.running_action_set;
   double min = generic_maxmin_share_resources(running_actions,
                                               xbt_swag_offset(s_action,
                                                               variable),
@@ -251,13 +251,13 @@ static double ptask_share_resources(double now)
   return min;
 }
 
-static void ptask_update_actions_state(double now, double delta)
+static void ptask_update_actions_state(surf_model_t workstation_model, double now, double delta)
 {
   double deltap = 0.0;
   surf_action_workstation_L07_t action = NULL;
   surf_action_workstation_L07_t next_action = NULL;
   xbt_swag_t running_actions =
-      surf_workstation_model->states.running_action_set;
+      workstation_model->states.running_action_set;
 
   xbt_swag_foreach_safe(action, next_action, running_actions) {
     deltap = delta;
@@ -410,12 +410,12 @@ static void ptask_update_resource_state(void *id,
   return;
 }
 
-static void ptask_finalize(void)
+static void ptask_finalize(surf_model_t workstation_model)
 {
   xbt_dict_free(&ptask_parallel_task_link_set);
 
-  surf_model_exit(surf_workstation_model);
-  surf_workstation_model = NULL;
+  surf_model_exit(workstation_model);
+  workstation_model = NULL;
   surf_model_exit(surf_network_model);
   surf_network_model = NULL;
 
@@ -890,6 +890,7 @@ static void ptask_model_init_internal(void)
   surf_workstation_model->set_priority = ptask_action_set_priority;
   surf_workstation_model->get_remains = ptask_action_get_remains;
   surf_workstation_model->name = "Workstation ptask_L07";
+  surf_workstation_model->type = SURF_MODEL_TYPE_WORKSTATION;
 
   surf_workstation_model->model_private->resource_used =
       ptask_resource_used;
@@ -958,7 +959,7 @@ static void ptask_model_init_internal(void)
 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_cpu_model_pm, "CPU model type already defined");
   xbt_assert(!surf_network_model, "network model type already defined");
   ptask_define_callbacks();
   ptask_model_init_internal();
diff --git a/src/surf/workstation_ptask_L07.cpp b/src/surf/workstation_ptask_L07.cpp
new file mode 100644 (file)
index 0000000..0010a53
--- /dev/null
@@ -0,0 +1,863 @@
+/* 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);
+  surf_workstation_model = NULL;
+  surf_network_model = new NetworkL07Model();
+  surf_cpu_model_pm = new CpuL07Model();
+  routing_model_create(p_networkModel->createResource("__loopback__",
+                                                         498000000, NULL,
+                                                         0.000015, NULL,
+                                                         SURF_RESOURCE_ON, NULL,
+                                                         SURF_LINK_FATPIPE, NULL));
+}
+
+WorkstationL07Model::~WorkstationL07Model() {
+  xbt_dict_free(&ptask_parallel_task_link_set);
+
+  delete surf_cpu_model_pm;
+  delete surf_network_model;
+  ptask_host_count = 0;
+
+  if (ptask_maxmin_system) {
+    lmm_system_free(ptask_maxmin_system);
+    ptask_maxmin_system = NULL;
+  }
+}
+
+double WorkstationL07Model::shareResources(double now)
+{
+  void *_action;
+  WorkstationL07ActionLmmPtr action;
+
+  xbt_swag_t running_actions = this->p_runningActionSet;
+  double min = this->shareResourcesMaxMin(running_actions,
+                                              ptask_maxmin_system,
+                                              bottleneck_solve);
+
+  xbt_swag_foreach(_action, running_actions) {
+       action = dynamic_cast<WorkstationL07ActionLmmPtr>(static_cast<ActionPtr>(_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_foreach_safe(_action, _next_action, p_runningActionSet) {
+    action = dynamic_cast<WorkstationL07ActionLmmPtr>(static_cast<ActionPtr>(_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 (static_cast<WorkstationCLM03LmmPtr>(constraint_id)->p_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;
+        void *_link;
+        LinkL07Ptr link;
+
+        routing_platf->getRouteAndLatency(dynamic_cast<WorkstationL07Ptr>(
+                                                  static_cast<ResourcePtr>(
+                                                   workstation_list[i]))->p_netElm,
+                                                 dynamic_cast<WorkstationL07Ptr>(
+                                                  static_cast<ResourcePtr>(
+                                                       workstation_list[j]))->p_netElm,
+                                                 &route,
+                                                 &lat);
+        latency = MAX(latency, lat);
+
+        xbt_dynar_foreach(route, cpt, _link) {
+           link = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(_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,
+              static_cast<CpuLmmPtr>(dynamic_cast<WorkstationL07Ptr>(
+                                          static_cast<ResourcePtr>(workstation_list[i]))->p_cpu)->p_constraint,
+               action->p_variable, computation_amount[i]);
+
+  for (i = 0; i < workstation_nb; i++) {
+    for (j = 0; j < workstation_nb; j++) {
+      void *_link;
+      LinkL07Ptr link;
+
+      xbt_dynar_t route=NULL;
+      if (communication_amount[i * workstation_nb + j] == 0.0)
+        continue;
+
+      routing_platf->getRouteAndLatency(dynamic_cast<WorkstationL07Ptr>(
+                                         static_cast<ResourcePtr>(workstation_list[i]))->p_netElm,
+                                        dynamic_cast<WorkstationL07Ptr>(
+                                         static_cast<ResourcePtr>(workstation_list[j]))->p_netElm,
+                                           &route, NULL);
+
+      xbt_dynar_foreach(route, cpt, _link) {
+        link = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(_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 static_cast<ActionPtr>(action);
+}
+
+ResourcePtr WorkstationL07Model::createResource(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)
+{
+  WorkstationL07Ptr wk = NULL;
+  xbt_assert(!surf_workstation_resource_priv(surf_workstation_resource_by_name(name)),
+              "Host '%s' declared several times in the platform file.",
+              name);
+
+  wk = new WorkstationL07(this, name, cpu_properties,
+                                 static_cast<RoutingEdgePtr>(xbt_lib_get_or_null(host_lib, name, ROUTING_HOST_LEVEL)),
+                                 dynamic_cast<CpuPtr>(static_cast<ResourcePtr>(xbt_lib_get_or_null(host_lib, name, SURF_CPU_LEVEL))));
+
+  xbt_lib_set(host_lib, name, SURF_WKS_LEVEL, static_cast<ResourcePtr>(wk));
+
+  return wk;//FIXME:xbt_lib_get_elm_or_null(host_lib, name);
+}
+
+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] = static_cast<ResourcePtr>(src);
+  workstation_list[1] = static_cast<ResourcePtr>(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(src->p_netElm, dst->p_netElm, &route, NULL);
+  return route;
+}
+
+ResourcePtr CpuL07Model::createResource(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_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, static_cast<ResourcePtr>(cpu));
+
+  cpu->p_stateCurrent = state_initial;
+  if (state_trace)
+    cpu->p_stateEvent =
+        tmgr_history_add_trace(history, state_trace, 0.0, 0, static_cast<ResourcePtr>(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_CPU_LEVEL, static_cast<ResourcePtr>(cpu));
+
+  return cpu;//FIXME:xbt_lib_get_elm_or_null(host_lib, name);
+}
+
+ResourcePtr NetworkL07Model::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)
+{
+  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, static_cast<ResourcePtr>(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, static_cast<ResourcePtr>(nw_link));
+  if (state_trace)
+    nw_link->p_stateEvent =
+        tmgr_history_add_trace(history, state_trace, 0.0, 0, static_cast<ResourcePtr>(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, static_cast<ResourcePtr>(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 = dynamic_cast<CpuL07Ptr>(
+                          static_cast<ResourcePtr>(
+                            surf_cpu_resource_priv(
+                              surf_cpu_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, static_cast<ResourcePtr>(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 = dynamic_cast<CpuL07Ptr>(
+                          static_cast<ResourcePtr>(
+                            surf_cpu_resource_priv(
+                              surf_cpu_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, static_cast<ResourcePtr>(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 = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(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, static_cast<ResourcePtr>(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 = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(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, static_cast<ResourcePtr>(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 = dynamic_cast<LinkL07Ptr>(static_cast<ResourcePtr>(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, static_cast<ResourcePtr>(link));
+  }
+}
+
+/************
+ * Resource *
+ ************/
+
+WorkstationL07::WorkstationL07(WorkstationModelPtr model, const char* name, xbt_dict_t props, RoutingEdgePtr netElm, CpuPtr cpu)
+  : Resource(model, name, props),
+    WorkstationCLM03Lmm(model, name, props, NULL, netElm, cpu),
+    WorkstationCLM03(model, name, props, NULL, netElm, cpu)
+{
+}
+
+double WorkstationL07::getPowerPeakAt(int pstate_index)
+{
+       XBT_DEBUG("[ws_get_power_peak_at] Not implemented for workstation_ptask_L07");
+       return 0.0;
+}
+
+int WorkstationL07::getNbPstates()
+{
+       XBT_DEBUG("[ws_get_nb_pstates] Not implemented for workstation_ptask_L07");
+       return 0.0;
+}
+
+void WorkstationL07::setPowerPeakAt(int pstate_index)
+{
+       XBT_DEBUG("[ws_set_power_peak_at] Not implemented for workstation_ptask_L07");
+}
+
+double WorkstationL07::getConsumedEnergy()
+{
+       XBT_DEBUG("[ws_get_consumed_energy] Not implemented for workstation_ptask_L07");
+       return 0.0;
+}
+
+CpuL07::CpuL07(CpuL07ModelPtr model, const char* name, xbt_dict_t props)
+ : Resource(model, name, props), CpuLmm(model, name, props) {
+
+}
+
+LinkL07::LinkL07(NetworkL07ModelPtr model, const char* name, xbt_dict_t props)
+ : Resource(model, name, props), NetworkCm02LinkLmm(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 WorkstationL07::getState()
+{
+  return p_cpu->p_stateCurrent;
+}
+
+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 WorkstationL07::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] = static_cast<ResourcePtr>(this);
+  communication_amount[0] = 0.0;
+  computation_amount[0] = size;
+
+  return static_cast<WorkstationL07ModelPtr>(p_model)->executeParallelTask(1, workstation_list,
+                                             computation_amount,
+                                     communication_amount, -1);
+}
+
+ActionPtr WorkstationL07::sleep(double duration)
+{
+  WorkstationL07ActionLmmPtr action = NULL;
+
+  XBT_IN("(%s,%g)", m_name, duration);
+
+  action = dynamic_cast<WorkstationL07ActionLmmPtr>(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(dynamic_cast<WorkstationL07Ptr>(
+                                           static_cast<ResourcePtr>(((void**)p_workstationList)[i]))->p_netElm,
+                                          dynamic_cast<WorkstationL07Ptr>(
+                                           static_cast<ResourcePtr>(((void**)p_workstationList)[j]))->p_netElm,
+                                                         &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(static_cast<ActionPtr>(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_workstation_init(sg_platf_host_cbarg_t host)
+{
+  double power_peak = xbt_dynar_get_as(host->power_peak, host->pstate, double);
+  //cpu->power_peak = power_peak;
+  xbt_dynar_free(&(host->power_peak));  /* kill memory leak */
+  static_cast<WorkstationL07ModelPtr>(surf_workstation_model)->createResource(
+      host->id,
+      power_peak,
+      host->power_scale,
+      host->power_trace,
+      host->initial_state,
+      host->state_trace,
+      host->properties);
+}
+
+static void ptask_parse_cpu_init(sg_platf_host_cbarg_t host)
+{
+  double power_peak = xbt_dynar_get_as(host->power_peak, host->pstate, double);
+  static_cast<CpuL07ModelPtr>(surf_cpu_model_pm)->createResource(
+      host->id,
+      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);
+    static_cast<NetworkL07ModelPtr>(surf_network_model)->createResource(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);
+    static_cast<NetworkL07ModelPtr>(surf_network_model)->createResource(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 {
+         static_cast<NetworkL07ModelPtr>(surf_network_model)->createResource(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_add_traces(){
+  static_cast<WorkstationL07ModelPtr>(surf_workstation_model)->addTraces();
+}
+
+static void ptask_define_callbacks()
+{
+  sg_platf_host_add_cb(ptask_parse_cpu_init);
+  sg_platf_host_add_cb(ptask_parse_workstation_init);
+  sg_platf_link_add_cb(ptask_parse_link_init);
+  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_pm, "CPU model type already defined");
+  xbt_assert(!surf_network_model, "network model type already defined");
+  ptask_define_callbacks();
+  surf_workstation_model = new WorkstationL07Model();
+  ModelPtr model = static_cast<ModelPtr>(surf_workstation_model);
+  xbt_dynar_push(model_list, &model);
+}
diff --git a/src/surf/workstation_ptask_L07.hpp b/src/surf/workstation_ptask_L07.hpp
new file mode 100644 (file)
index 0000000..0fcb23c
--- /dev/null
@@ -0,0 +1,184 @@
+#include "workstation.hpp"
+
+#ifndef WORKSTATION_L07_HPP_
+#define WORKSTATION_L07_HPP_
+
+/***********
+ * Classes *
+ ***********/
+
+class WorkstationL07Model;
+typedef WorkstationL07Model *WorkstationL07ModelPtr;
+
+class CpuL07Model;
+typedef CpuL07Model *CpuL07ModelPtr;
+
+class NetworkL07Model;
+typedef NetworkL07Model *NetworkL07ModelPtr;
+
+class WorkstationL07;
+typedef WorkstationL07 *WorkstationL07Ptr;
+
+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();
+  ~WorkstationL07Model();
+
+  double shareResources(double now);
+  void updateActionsState(double now, double delta);
+  ResourcePtr createResource(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);
+  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);
+  void addTraces();
+  CpuL07ModelPtr p_cpuModel;
+  NetworkL07ModelPtr p_networkModel;
+};
+
+class CpuL07Model : public CpuModel {
+public:
+  CpuL07Model() : CpuModel("cpuL07") {};
+  ~CpuL07Model() {surf_cpu_model_pm = NULL;};
+  ResourcePtr createResource(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);
+  void addTraces() {DIE_IMPOSSIBLE;};
+  WorkstationL07ModelPtr p_workstationModel;
+};
+
+class NetworkL07Model : public NetworkCm02Model {
+public:
+  NetworkL07Model() : NetworkCm02Model(0) {};
+  ~NetworkL07Model() {surf_network_model = NULL;};
+  ResourcePtr 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_dynar_t getRoute(WorkstationCLM03Ptr src, WorkstationCLM03Ptr dst) {DIE_IMPOSSIBLE;};
+  ActionPtr communicate(RoutingEdgePtr src, RoutingEdgePtr dst, double size, double rate) {DIE_IMPOSSIBLE;};
+  void addTraces() {DIE_IMPOSSIBLE;};
+  WorkstationL07ModelPtr p_workstationModel;
+};
+
+/************
+ * Resource *
+ ************/
+
+class WorkstationL07 : public WorkstationCLM03Lmm {
+public:
+  WorkstationL07(WorkstationModelPtr model, const char* name, xbt_dict_t props, RoutingEdgePtr netElm, CpuPtr cpu);
+  //bool isUsed();
+  bool isUsed() {DIE_IMPOSSIBLE;};
+  void updateState(tmgr_trace_event_t event_type, double value, double date) {DIE_IMPOSSIBLE;};
+  ActionPtr execute(double size);
+  ActionPtr sleep(double duration);
+  e_surf_resource_state_t getState();
+  double getPowerPeakAt(int pstate_index);
+  int getNbPstates();
+  void setPowerPeakAt(int pstate_index);
+  double getConsumedEnergy();
+};
+
+class CpuL07 : public CpuLmm {
+public:
+  CpuL07(CpuL07ModelPtr model, const char* name, xbt_dict_t properties);
+  bool isUsed();
+  //bool isUsed() {DIE_IMPOSSIBLE;};
+  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) {DIE_IMPOSSIBLE;};
+  ActionPtr sleep(double duration) {DIE_IMPOSSIBLE;};
+
+  double getCurrentPowerPeak() {};
+  double getPowerPeakAt(int pstate_index) {};
+  int getNbPstates() {};
+  void setPowerPeakAt(int pstate_index) {};
+  double getConsumedEnergy() {};
+
+  double m_powerCurrent;
+};
+
+class LinkL07 : public NetworkCm02LinkLmm {
+public:
+  LinkL07(NetworkL07ModelPtr 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)
+  : Action(model, cost, 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_ */
index 9433046..e53837c 100644 (file)
@@ -223,6 +223,9 @@ const char *xbt_ex_catname(xbt_errcat_t cat)
     return "tracing error";
   case io_error:
     return "io error";
+  case vm_error:
+    return "vm error";
+
   }
   return "INVALID ERROR";
 }
index cc6f9e6..572c303 100644 (file)
@@ -70,6 +70,37 @@ void xbt_lib_set(xbt_lib_t lib, const char *key, int level, void *obj)
   elts[level] = obj;
 }
 
+/* for vm */
+void xbt_lib_unset(xbt_lib_t lib, const char *key, int level, int invoke_callback)
+{
+  void **elts = xbt_dict_get_or_null(lib->dict, key);
+  if (!elts) {
+     XBT_WARN("no key %s", key);
+     return;
+  }
+
+  void *obj = elts[level];
+
+  if (!obj) {
+     XBT_WARN("no key %s at level %d", key, level);
+  } else {
+     XBT_DEBUG("Remove %p of key %s at level %d", obj, key, level);
+     if (invoke_callback)
+       lib->free_f[level](obj);
+     elts[level] = NULL;
+  }
+
+  /* check if there still remains any elements of this key */
+  int i;
+  for (i = 0; i < lib->levels; i++) {
+     if (elts[i] != NULL)
+       return;
+  }
+
+  /* there is no element at any level, so delete the key */
+  xbt_dict_remove(lib->dict, key);
+}
+
 void *xbt_lib_get_or_null(xbt_lib_t lib, const char *key, int level)
 {
   void **elts = xbt_dict_get_or_null(lib->dict, key);
@@ -85,3 +116,7 @@ void *xbt_lib_get_level(xbt_dictelm_t elm, int level){
   void **elts = elm->content;
   return elts ? elts[level] : NULL;
 }
+
+void xbt_lib_remove(xbt_lib_t lib, const char *key){
+  xbt_dict_remove(lib->dict, key);
+}
index dbea34a..b692dba 100644 (file)
@@ -683,7 +683,6 @@ static void xbt_log_connect_categories(void)
   XBT_LOG_CONNECT(surf_lagrange_dichotomy);
   XBT_LOG_CONNECT(surf_maxmin);
   XBT_LOG_CONNECT(surf_network);
-  XBT_LOG_CONNECT(surf_new_model);
 #ifdef HAVE_GTNETS
   XBT_LOG_CONNECT(surf_network_gtnets);
   XBT_LOG_CONNECT(surf_network_gtnets_interface);
index 47dc3ba..a5430b2 100644 (file)
@@ -14,7 +14,6 @@
 #include "xbt/log.h"
 #include "xbt/swag.h"
 
-
 /** Creates a new swag.
  * \param offset where the hookup is located in the structure
  * \see xbt_swag_offset
index 46ae1b4..0b735e4 100644 (file)
@@ -160,8 +160,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("  <router id=\"%s\"/>\n",key);
       }
@@ -203,7 +203,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);
         }
@@ -222,7 +222,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);
           }
@@ -248,7 +248,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);
             }
@@ -266,7 +266,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);
           }
index 1a922a8..8ca7102 100644 (file)
@@ -58,23 +58,23 @@ void test(char *platform)
   parse_platform_file(platform);
 
   /*********************** CPU ***********************************/
-  XBT_DEBUG("%p", surf_cpu_model);
+  XBT_DEBUG("%p", surf_cpu_model_pm);
   cpuA = surf_cpu_resource_by_name("Cpu A");
   cpuB = surf_cpu_resource_by_name("Cpu B");
 
   /* Let's check that those two processors exist */
-  XBT_DEBUG("%s : %p", surf_resource_name(cpuA), cpuA);
-  XBT_DEBUG("%s : %p", surf_resource_name(cpuB), cpuB);
+  XBT_DEBUG("%s : %p", surf_resource_name(surf_cpu_resource_priv(cpuA)), cpuA);
+  XBT_DEBUG("%s : %p", surf_resource_name(surf_cpu_resource_priv(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));
@@ -87,12 +87,11 @@ void test(char *platform)
   cardB = sg_routing_edge_by_name_or_null("Cpu B");
 
   /* Let's check that those two processors exist */
-  XBT_DEBUG("%s : %p", surf_resource_name(cardA), cardA);
-  XBT_DEBUG("%s : %p", surf_resource_name(cardB), cardB);
+  XBT_DEBUG("%s : %p", surf_routing_edge_name(cardA), cardA);
+  XBT_DEBUG("%s : %p", surf_routing_edge_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_pm)))) {
       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_pm)))) {
       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_pm))) &&
            surf_solve(-1.0) >= 0.0);
 
   XBT_DEBUG("Simulation Terminated");
index 896f959..d07a552 100644 (file)
@@ -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;
       }
     }