source: XIOS2/trunk/src/cxios.cpp @ 2439

Last change on this file since 2439 was 2439, checked in by jderouillat, 19 months ago

Add the ability to specify the location of iodef through an environment variable XIOS_IODEF_PATH.

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:eol-style set to native
File size: 10.6 KB
RevLine 
[300]1
[591]2#include "xios_spl.hpp"
[300]3#include "cxios.hpp"
[342]4#include "client.hpp"
5#include "server.hpp"
[346]6#include "xml_parser.hpp"
[300]7#include <boost/functional/hash.hpp>
[382]8#include "mpi.hpp"
[2439]9#include <unistd.h>
[400]10#include "memory.hpp"
11#include <new>
[401]12#include "memtrack.hpp"
[2428]13#include "mem_checker.hpp"
[697]14#include "registry.hpp"
[300]15
[1704]16#include "graphviz.hpp"
17
[335]18namespace xios
[300]19{
20  string CXios::rootFile="./iodef.xml" ;
21  string CXios::xiosCodeId="xios.x" ;
[499]22  string CXios::clientFile="./xios_client";
23  string CXios::serverFile="./xios_server";
[1021]24  string CXios::serverPrmFile="./xios_server1";
25  string CXios::serverSndFile="./xios_server2";
[490]26
[1622]27  bool CXios::xiosStack = true;
28  bool CXios::systemStack = false;
29
[300]30  bool CXios::isClient ;
31  bool CXios::isServer ;
[1639]32  MPI_Comm CXios::globalComm ;
[300]33  bool CXios::usingOasis ;
[491]34  bool CXios::usingServer = false;
[1021]35  bool CXios::usingServer2 = false;
36  int CXios::ratioServer2 = 50;
[1243]37  int CXios::nbPoolsServer2 = 1;
[718]38  double CXios::bufferSizeFactor = 1.0;
39  const double CXios::defaultBufferSizeFactor = 1.0;
[719]40  StdSize CXios::minBufferSize = 1024 * sizeof(double);
[1227]41  StdSize CXios::maxBufferSize = std::numeric_limits<int>::max() ;
[523]42  bool CXios::printLogs2Files;
[511]43  bool CXios::isOptPerformance = true;
[697]44  CRegistry* CXios::globalRegistry = 0;
[1375]45  double CXios::recvFieldTimeout = 300.0;
[1377]46  bool CXios::checkEventSync=false ;
[2330]47  bool CXios::checkSumRecv=false ;
48  bool CXios::checkSumSend=false ;
[2428]49  bool CXios::logMemory=false ;
[1376]50 
[512]51  //! Parse configuration file and create some objects from it
[300]52  void CXios::initialize()
53  {
[400]54    set_new_handler(noMemory);
[2439]55    char startPath[256];
56    getcwd(startPath, sizeof(startPath));
57    if(const char* userPath = std::getenv("XIOS_IODEF_PATH"))
58    {
59      if ( chdir( userPath ) != 0)
60      {
61        ERROR("CXios::initialize()", << "XIOS_IODEF_PATH not defined correctly : " << userPath << endl );
62      }
63    }
[346]64    parseFile(rootFile);
[511]65    parseXiosConfig();
[2439]66    chdir( startPath );
[511]67  }
68
[512]69  /*!
70  \brief Parse xios part of configuration file (.iodef.xml)
71   Both client and server need information returned from this function
72  */
[511]73  void CXios::parseXiosConfig()
74  {
[311]75    usingOasis=getin<bool>("using_oasis",false) ;
[506]76    usingServer=getin<bool>("using_server",false) ;
[1021]77    usingServer2=getin<bool>("using_server2",false) ;
78    ratioServer2=getin<int>("ratio_server2",50);
[1519]79    nbPoolsServer2=getin<int>("number_pools_server2",0);
[311]80    info.setLevel(getin<int>("info_level",0)) ;
[512]81    report.setLevel(getin<int>("info_level",50));
[523]82    printLogs2Files=getin<bool>("print_file",false);
[512]83
[1622]84    xiosStack=getin<bool>("xios_stack",true) ;
85    systemStack=getin<bool>("system_stack",false) ;
86    if (xiosStack && systemStack)
87    {
88      xiosStack = false;
89    }
90
[511]91    StdString bufMemory("memory");
92    StdString bufPerformance("performance");
93    StdString bufOpt = getin<StdString>("optimal_buffer_size", bufPerformance);
94    std::transform(bufOpt.begin(), bufOpt.end(), bufOpt.begin(), ::tolower);
95    if (0 == bufOpt.compare(bufMemory)) isOptPerformance = false;
96    else if (0 != bufOpt.compare(bufPerformance))
97    {
98      ERROR("CXios::parseXiosConfig()", << "optimal_buffer_size must be memory or performance "<< endl );
99    }
100
[718]101    bufferSizeFactor = getin<double>("buffer_size_factor", defaultBufferSizeFactor);
[719]102    minBufferSize = getin<int>("min_buffer_size", 1024 * sizeof(double));
[1227]103    maxBufferSize = getin<int>("max_buffer_size", std::numeric_limits<int>::max());
[1376]104    recvFieldTimeout = getin<double>("recv_field_timeout", recvFieldTimeout);
[1158]105    if (recvFieldTimeout < 0.0)
106      ERROR("CXios::parseXiosConfig()", "recv_field_timeout cannot be negative.");
[718]107
[1377]108    checkEventSync = getin<bool>("check_event_sync", checkEventSync);
[1639]109
[2330]110    checkSumSend = getin<bool>("checksum_send_fields", false);
111    checkSumRecv = getin<bool>("checksum_recv_fields", false);
[2428]112
113    logMemory = getin<bool>("log_memory", false);
[2330]114 
[300]115    globalComm=MPI_COMM_WORLD ;
116  }
117
[512]118  /*!
119  Initialize client
120  \param [in] codeId identity of context
121  \param [in] localComm local communicator
122  \param [in/out] returnComm communicator corresponding to group of client with same codeId
123  */
[1639]124  void CXios::initClientSide(const string& codeId, MPI_Comm& localComm, MPI_Comm& returnComm)
[1622]125  TRY
[300]126  {
127    initialize() ;
[490]128
[1639]129    isClient = true;
[491]130
131    CClient::initialize(codeId,localComm,returnComm) ;
[697]132    if (CClient::getRank()==0) globalRegistry = new CRegistry(returnComm) ;
[491]133
[956]134    // If there are no server processes then we are in attached mode
135    // and the clients are also servers
136    isServer = !usingServer;
[490]137
[523]138    if (printLogs2Files)
139    {
[499]140      CClient::openInfoStream(clientFile);
[523]141      CClient::openErrorStream(clientFile);
142    }
[490]143    else
[523]144    {
[490]145      CClient::openInfoStream();
[523]146      CClient::openErrorStream();
147    }
[2428]148    CMemChecker::logMem("CXios::initClientSide");
[490]149  }
[1622]150  CATCH
[300]151
152  void CXios::clientFinalize(void)
153  {
[2428]154     CMemChecker::logMem("CXios::clientFinalize", true);
[490]155     CClient::finalize() ;
[697]156     if (CClient::getRank()==0)
157     {
158       info(80)<<"Write data base Registry"<<endl<<globalRegistry->toString()<<endl ;
159       globalRegistry->toFile("xios_registry.bin") ;
160       delete globalRegistry ;
[1704]161       CGraphviz::buildWorkflowGraphVisjs_with_info();
[697]162     }
[490]163
[401]164#ifdef XIOS_MEMTRACK
[1158]165
166#ifdef XIOS_MEMTRACK_LIGHT
167       report(10) << " Memory report : current memory used by XIOS : "<<  MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte" << endl ;
168       report(10) << " Memory report : maximum memory used by XIOS : "<<  MemTrack::getMaxMemorySize()*1.0/(1024*1024)<<" Mbyte" << endl ;
169#endif
170
171#ifdef XIOS_MEMTRACK_FULL
[401]172     MemTrack::TrackListMemoryUsage() ;
[490]173     MemTrack::TrackDumpBlocks();
[401]174#endif
[1158]175
176     CClient::closeInfoStream();
177
178#endif
[490]179  }
180
[512]181  //! Init server by parsing only xios part of config file
[509]182  void CXios::initServer()
183  {
184    set_new_handler(noMemory);
185    std::set<StdString> parseList;
186    parseList.insert("xios");
[2439]187    char startPath[256];
188    getcwd(startPath, sizeof(startPath));
189    if(const char* userPath = std::getenv("XIOS_IODEF_PATH"))
190    {
191      if ( chdir( userPath ) != 0)
192      {
193        ERROR("CXios::initialize()", << "XIOS_IODEF_PATH not defined correctly : " << userPath << endl );
194      }
195    }
[509]196    xml::CXMLParser::ParseFile(rootFile, parseList);
[511]197    parseXiosConfig();
[2439]198    chdir( startPath );
[509]199  }
200
[512]201  //! Initialize server then put it into listening state
[1054]202  void CXios::initServerSide(void)
[300]203  {
[1639]204    initServer();
[1638]205    isClient = false;
206    isServer = true;
207
[1021]208    // Initialize all aspects MPI
209    CServer::initialize();
[1330]210    if (CServer::getRank()==0 && CServer::serverLevel != 1) globalRegistry = new CRegistry(CServer::intraComm) ;
[697]211   
[523]212    if (printLogs2Files)
213    {
[1021]214      if (CServer::serverLevel == 0)
[983]215      {
216        CServer::openInfoStream(serverFile);
217        CServer::openErrorStream(serverFile);
218      }
[1021]219      else if (CServer::serverLevel == 1)
[983]220      {
[1021]221        CServer::openInfoStream(serverPrmFile);
222        CServer::openErrorStream(serverPrmFile);
[983]223      }
224      else
225      {
[1021]226        CServer::openInfoStream(serverSndFile);
227        CServer::openErrorStream(serverSndFile);
[983]228      }
[523]229    }
[490]230    else
[523]231    {
[490]232      CServer::openInfoStream();
[523]233      CServer::openErrorStream();
234    }
[2428]235    CMemChecker::logMem( "CServer::initialize" );
[490]236
[491]237    // Enter the loop to listen message from Client
[490]238    CServer::eventLoop();
239
[491]240    // Finalize
[1234]241    if (CServer::serverLevel == 0)
[1168]242    {
243      if (CServer::getRank()==0)
244      {
245        info(80)<<"Write data base Registry"<<endl<<globalRegistry->toString()<<endl ;
246        globalRegistry->toFile("xios_registry.bin") ;
247        delete globalRegistry ;
248      }
249    }
250    else
251    {
[1243]252      // If using two server levels:
253      // (1) merge registries on each pool
254      // (2) send merged registries to the first pool
255      // (3) merge received registries on the first pool
[1168]256      if (CServer::serverLevel == 2)
257      {
258        vector<int>& secondaryServerGlobalRanks = CServer::getSecondaryServerGlobalRanks();
259        int firstPoolGlobalRank = secondaryServerGlobalRanks[0];
260        int rankGlobal;
[1639]261        MPI_Comm_rank(globalComm, &rankGlobal);
[1168]262
[1243]263        // Merge registries defined on each pools
264        CRegistry globalRegistrySndServers (CServer::intraComm);
265
[1168]266        // All pools (except the first): send globalRegistry to the first pool
[1243]267        for (int i=1; i<secondaryServerGlobalRanks.size(); i++)
[1168]268        {
[1243]269          if (rankGlobal == secondaryServerGlobalRanks[i])
270          {
271            globalRegistrySndServers.mergeRegistry(*globalRegistry) ;
272            int registrySize = globalRegistrySndServers.size();
[1639]273            MPI_Send(&registrySize,1,MPI_LONG,firstPoolGlobalRank,15,CXios::globalComm) ;
[1243]274            CBufferOut buffer(registrySize) ;
275            globalRegistrySndServers.toBuffer(buffer) ;
[1639]276            MPI_Send(buffer.start(),registrySize,MPI_CHAR,firstPoolGlobalRank,15,CXios::globalComm) ;
[1243]277          }
[1168]278        }
279
280        // First pool: receive globalRegistry of all secondary server pools, merge and write the resultant registry
[1243]281        if (rankGlobal == firstPoolGlobalRank)
[1168]282        {
[1639]283          MPI_Status status;
[1168]284          char* recvBuff;
285
286          globalRegistrySndServers.mergeRegistry(*globalRegistry) ;
287
288          for (int i=1; i< secondaryServerGlobalRanks.size(); i++)
289          {
290            int rank = secondaryServerGlobalRanks[i];
291            int registrySize = 0;
[1639]292            MPI_Recv(&registrySize, 1, MPI_LONG, rank, 15, CXios::globalComm, &status);
[1168]293            recvBuff = new char[registrySize];
[1639]294            MPI_Recv(recvBuff, registrySize, MPI_CHAR, rank, 15, CXios::globalComm, &status);
[1168]295            CBufferIn buffer(recvBuff, registrySize) ;
296            CRegistry recvRegistry;
297            recvRegistry.fromBuffer(buffer) ;
298            globalRegistrySndServers.mergeRegistry(recvRegistry) ;
299            delete[] recvBuff;
300          }
301
302          info(80)<<"Write data base Registry"<<endl<<globalRegistrySndServers.toString()<<endl ;
303          globalRegistrySndServers.toFile("xios_registry.bin") ;
304
305        }
306      }
307      delete globalRegistry;
308    }
[490]309    CServer::finalize();
[1158]310
311#ifdef XIOS_MEMTRACK
312
313#ifdef XIOS_MEMTRACK_LIGHT
314       report(10) << " Memory report : current memory used by XIOS : "<<  MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte" << endl ;
315       report(10) << " Memory report : maximum memory used by XIOS : "<<  MemTrack::getMaxMemorySize()*1.0/(1024*1024)<<" Mbyte" << endl ;
316#endif
317
318#ifdef XIOS_MEMTRACK_FULL
319     MemTrack::TrackListMemoryUsage() ;
320     MemTrack::TrackDumpBlocks();
321#endif
322#endif
[490]323    CServer::closeInfoStream();
324  }
325
[512]326  //! Parse configuration file
[346]327  void CXios::parseFile(const string& filename)
328  {
[490]329    xml::CXMLParser::ParseFile(filename);
[346]330  }
[491]331
[512]332  //! Set using server
[491]333  void CXios::setUsingServer()
334  {
335    usingServer = true;
336  }
337
[512]338  //! Unset using server
[491]339  void CXios::setNotUsingServer()
340  {
341    usingServer = false;
342  }
[300]343}
Note: See TracBrowser for help on using the repository browser.