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
Line 
1
2#include "xios_spl.hpp"
3#include "cxios.hpp"
4#include "client.hpp"
5#include "server.hpp"
6#include "xml_parser.hpp"
7#include <boost/functional/hash.hpp>
8#include "mpi.hpp"
9#include <unistd.h>
10#include "memory.hpp"
11#include <new>
12#include "memtrack.hpp"
13#include "mem_checker.hpp"
14#include "registry.hpp"
15
16#include "graphviz.hpp"
17
18namespace xios
19{
20  string CXios::rootFile="./iodef.xml" ;
21  string CXios::xiosCodeId="xios.x" ;
22  string CXios::clientFile="./xios_client";
23  string CXios::serverFile="./xios_server";
24  string CXios::serverPrmFile="./xios_server1";
25  string CXios::serverSndFile="./xios_server2";
26
27  bool CXios::xiosStack = true;
28  bool CXios::systemStack = false;
29
30  bool CXios::isClient ;
31  bool CXios::isServer ;
32  MPI_Comm CXios::globalComm ;
33  bool CXios::usingOasis ;
34  bool CXios::usingServer = false;
35  bool CXios::usingServer2 = false;
36  int CXios::ratioServer2 = 50;
37  int CXios::nbPoolsServer2 = 1;
38  double CXios::bufferSizeFactor = 1.0;
39  const double CXios::defaultBufferSizeFactor = 1.0;
40  StdSize CXios::minBufferSize = 1024 * sizeof(double);
41  StdSize CXios::maxBufferSize = std::numeric_limits<int>::max() ;
42  bool CXios::printLogs2Files;
43  bool CXios::isOptPerformance = true;
44  CRegistry* CXios::globalRegistry = 0;
45  double CXios::recvFieldTimeout = 300.0;
46  bool CXios::checkEventSync=false ;
47  bool CXios::checkSumRecv=false ;
48  bool CXios::checkSumSend=false ;
49  bool CXios::logMemory=false ;
50 
51  //! Parse configuration file and create some objects from it
52  void CXios::initialize()
53  {
54    set_new_handler(noMemory);
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    }
64    parseFile(rootFile);
65    parseXiosConfig();
66    chdir( startPath );
67  }
68
69  /*!
70  \brief Parse xios part of configuration file (.iodef.xml)
71   Both client and server need information returned from this function
72  */
73  void CXios::parseXiosConfig()
74  {
75    usingOasis=getin<bool>("using_oasis",false) ;
76    usingServer=getin<bool>("using_server",false) ;
77    usingServer2=getin<bool>("using_server2",false) ;
78    ratioServer2=getin<int>("ratio_server2",50);
79    nbPoolsServer2=getin<int>("number_pools_server2",0);
80    info.setLevel(getin<int>("info_level",0)) ;
81    report.setLevel(getin<int>("info_level",50));
82    printLogs2Files=getin<bool>("print_file",false);
83
84    xiosStack=getin<bool>("xios_stack",true) ;
85    systemStack=getin<bool>("system_stack",false) ;
86    if (xiosStack && systemStack)
87    {
88      xiosStack = false;
89    }
90
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
101    bufferSizeFactor = getin<double>("buffer_size_factor", defaultBufferSizeFactor);
102    minBufferSize = getin<int>("min_buffer_size", 1024 * sizeof(double));
103    maxBufferSize = getin<int>("max_buffer_size", std::numeric_limits<int>::max());
104    recvFieldTimeout = getin<double>("recv_field_timeout", recvFieldTimeout);
105    if (recvFieldTimeout < 0.0)
106      ERROR("CXios::parseXiosConfig()", "recv_field_timeout cannot be negative.");
107
108    checkEventSync = getin<bool>("check_event_sync", checkEventSync);
109
110    checkSumSend = getin<bool>("checksum_send_fields", false);
111    checkSumRecv = getin<bool>("checksum_recv_fields", false);
112
113    logMemory = getin<bool>("log_memory", false);
114 
115    globalComm=MPI_COMM_WORLD ;
116  }
117
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  */
124  void CXios::initClientSide(const string& codeId, MPI_Comm& localComm, MPI_Comm& returnComm)
125  TRY
126  {
127    initialize() ;
128
129    isClient = true;
130
131    CClient::initialize(codeId,localComm,returnComm) ;
132    if (CClient::getRank()==0) globalRegistry = new CRegistry(returnComm) ;
133
134    // If there are no server processes then we are in attached mode
135    // and the clients are also servers
136    isServer = !usingServer;
137
138    if (printLogs2Files)
139    {
140      CClient::openInfoStream(clientFile);
141      CClient::openErrorStream(clientFile);
142    }
143    else
144    {
145      CClient::openInfoStream();
146      CClient::openErrorStream();
147    }
148    CMemChecker::logMem("CXios::initClientSide");
149  }
150  CATCH
151
152  void CXios::clientFinalize(void)
153  {
154     CMemChecker::logMem("CXios::clientFinalize", true);
155     CClient::finalize() ;
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 ;
161       CGraphviz::buildWorkflowGraphVisjs_with_info();
162     }
163
164#ifdef XIOS_MEMTRACK
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
172     MemTrack::TrackListMemoryUsage() ;
173     MemTrack::TrackDumpBlocks();
174#endif
175
176     CClient::closeInfoStream();
177
178#endif
179  }
180
181  //! Init server by parsing only xios part of config file
182  void CXios::initServer()
183  {
184    set_new_handler(noMemory);
185    std::set<StdString> parseList;
186    parseList.insert("xios");
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    }
196    xml::CXMLParser::ParseFile(rootFile, parseList);
197    parseXiosConfig();
198    chdir( startPath );
199  }
200
201  //! Initialize server then put it into listening state
202  void CXios::initServerSide(void)
203  {
204    initServer();
205    isClient = false;
206    isServer = true;
207
208    // Initialize all aspects MPI
209    CServer::initialize();
210    if (CServer::getRank()==0 && CServer::serverLevel != 1) globalRegistry = new CRegistry(CServer::intraComm) ;
211   
212    if (printLogs2Files)
213    {
214      if (CServer::serverLevel == 0)
215      {
216        CServer::openInfoStream(serverFile);
217        CServer::openErrorStream(serverFile);
218      }
219      else if (CServer::serverLevel == 1)
220      {
221        CServer::openInfoStream(serverPrmFile);
222        CServer::openErrorStream(serverPrmFile);
223      }
224      else
225      {
226        CServer::openInfoStream(serverSndFile);
227        CServer::openErrorStream(serverSndFile);
228      }
229    }
230    else
231    {
232      CServer::openInfoStream();
233      CServer::openErrorStream();
234    }
235    CMemChecker::logMem( "CServer::initialize" );
236
237    // Enter the loop to listen message from Client
238    CServer::eventLoop();
239
240    // Finalize
241    if (CServer::serverLevel == 0)
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    {
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
256      if (CServer::serverLevel == 2)
257      {
258        vector<int>& secondaryServerGlobalRanks = CServer::getSecondaryServerGlobalRanks();
259        int firstPoolGlobalRank = secondaryServerGlobalRanks[0];
260        int rankGlobal;
261        MPI_Comm_rank(globalComm, &rankGlobal);
262
263        // Merge registries defined on each pools
264        CRegistry globalRegistrySndServers (CServer::intraComm);
265
266        // All pools (except the first): send globalRegistry to the first pool
267        for (int i=1; i<secondaryServerGlobalRanks.size(); i++)
268        {
269          if (rankGlobal == secondaryServerGlobalRanks[i])
270          {
271            globalRegistrySndServers.mergeRegistry(*globalRegistry) ;
272            int registrySize = globalRegistrySndServers.size();
273            MPI_Send(&registrySize,1,MPI_LONG,firstPoolGlobalRank,15,CXios::globalComm) ;
274            CBufferOut buffer(registrySize) ;
275            globalRegistrySndServers.toBuffer(buffer) ;
276            MPI_Send(buffer.start(),registrySize,MPI_CHAR,firstPoolGlobalRank,15,CXios::globalComm) ;
277          }
278        }
279
280        // First pool: receive globalRegistry of all secondary server pools, merge and write the resultant registry
281        if (rankGlobal == firstPoolGlobalRank)
282        {
283          MPI_Status status;
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;
292            MPI_Recv(&registrySize, 1, MPI_LONG, rank, 15, CXios::globalComm, &status);
293            recvBuff = new char[registrySize];
294            MPI_Recv(recvBuff, registrySize, MPI_CHAR, rank, 15, CXios::globalComm, &status);
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    }
309    CServer::finalize();
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
323    CServer::closeInfoStream();
324  }
325
326  //! Parse configuration file
327  void CXios::parseFile(const string& filename)
328  {
329    xml::CXMLParser::ParseFile(filename);
330  }
331
332  //! Set using server
333  void CXios::setUsingServer()
334  {
335    usingServer = true;
336  }
337
338  //! Unset using server
339  void CXios::setNotUsingServer()
340  {
341    usingServer = false;
342  }
343}
Note: See TracBrowser for help on using the repository browser.