source: XIOS3/trunk/src/client.cpp @ 2628

Last change on this file since 2628 was 2628, checked in by jderouillat, 7 weeks ago

New timers integration/reporting

  • 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: 24.5 KB
Line 
1#include "globalScopeData.hpp"
2#include "xios_spl.hpp"
3#include "cxios.hpp"
4#include "client.hpp"
5#include <boost/functional/hash.hpp>
6#include "type.hpp"
7#include "context.hpp"
8#include "context_client.hpp"
9#include "oasis_cinterface.hpp"
10#include "mpi.hpp"
11#include "timer.hpp"
12#include "buffer_client.hpp"
13#include "string_tools.hpp"
14#include "ressources_manager.hpp"
15#include "services_manager.hpp"
16#include <functional>
17#include <cstdio>
18#include "workflow_graph.hpp"
19#include "release_static_allocation.hpp"
20#include "mem_checker.hpp"
21
22namespace xios
23{
24
25    const double serverPublishDefaultTimeout=10;
26
27    MPI_Comm CClient::intraComm_ ;
28    MPI_Comm CClient::interComm_ ;
29    MPI_Comm CClient::clientsComm_ ;
30
31    std::list<MPI_Comm> CClient::contextInterComms;
32    int CClient::serverLeader ;
33    bool CClient::is_MPI_Initialized ;
34    int CClient::rank_ = INVALID_RANK;
35    StdOFStream CClient::m_infoStream;
36    StdOFStream CClient::m_errorStream;
37    CPoolRessource* CClient::poolRessource_=nullptr ;
38    extern CLogType logTimers ;
39
40    MPI_Comm& CClient::getInterComm(void)   { return (interComm_); }
41     
42///---------------------------------------------------------------
43/*!
44 * \fn void CClient::initialize(const string& codeId, MPI_Comm& localComm, MPI_Comm& returnComm)
45 * Function creates intraComm (CClient::intraComm) for client group with id=codeId and interComm (CClient::interComm) between client and server groups.
46 * \param [in] codeId identity of context.
47 * \param [in/out] localComm local communicator.
48 * \param [in/out] returnComm (intra)communicator of client group.
49 */
50
51    void CClient::initialize(const string& codeId, MPI_Comm& localComm, MPI_Comm& returnComm)
52    {
53   
54       MPI_Comm clientComm ;
55      // initialize MPI if not initialized
56      int initialized ;
57      MPI_Initialized(&initialized) ;
58      if (initialized) is_MPI_Initialized=true ;
59      else is_MPI_Initialized=false ;
60     
61      MPI_Comm globalComm=CXios::getGlobalComm() ;
62
63      /////////////////////////////////////////
64      ///////////// PART 1 ////////////////////
65      /////////////////////////////////////////
66     
67
68      // localComm isn't given
69      if (localComm == MPI_COMM_NULL)
70      {
71         
72        // don't use OASIS
73        if (!CXios::usingOasis)
74        {
75
76          if (!is_MPI_Initialized)
77          {
78            MPI_Init(NULL, NULL);
79          }
80          CTimer::get("XIOS").resume() ;
81          CTimer::get("XIOS init/finalize",false).resume() ;
82         
83          // split the global communicator
84          // get hash from all model to attribute a unique color (int) and then split to get client communicator
85          // every mpi process of globalComm (MPI_COMM_WORLD) must participate
86
87          int commRank, commSize ;
88          MPI_Comm_rank(globalComm,&commRank) ;
89          MPI_Comm_size(globalComm,&commSize) ;
90
91          std::hash<string> hashString ;
92          size_t hashClient=hashString(codeId) ;
93         
94          size_t* hashAll = new size_t[commSize] ;
95          MPI_Allgather(&hashClient,1,MPI_SIZE_T,hashAll,1,MPI_SIZE_T,globalComm) ;
96         
97          int color=0 ;
98          map<size_t,int> listHash ;
99          for(int i=0 ; i<=commSize ; i++) 
100            if (listHash.count(hashAll[i])==0) 
101            {
102              listHash[hashAll[i]]=color ;
103              color=color+1 ;
104            }
105            color=listHash[hashClient] ;
106          delete[] hashAll ;
107
108          xios::MPI_Comm_split(globalComm, color, commRank, &clientComm) ;
109          CXios::getMpiGarbageCollector().registerCommunicator(clientComm) ;
110        }
111        else
112        {
113          ERROR("void CClient::initialize(const string& codeId, MPI_Comm& localComm, MPI_Comm& returnComm)", <<"OASIS usage is set. In these conditions, XIOS initialization needs the local_comm created by OASIS."<<endl) ;
114        }
115      }
116      else // localComm is given
117      {
118        CTimer::get("XIOS").resume() ;
119        CTimer::get("XIOS init/finalize",false).resume() ;
120        xios::MPI_Comm_dup(localComm,&clientComm) ;
121        CXios::getMpiGarbageCollector().registerCommunicator(clientComm) ;
122        xios::MPI_Comm_dup(localComm,&intraComm_) ;
123        CXios::getMpiGarbageCollector().registerCommunicator(intraComm_) ;
124
125        if (CXios::usingServer)
126        {
127          MPI_Comm_rank(intraComm_,&rank_) ;
128        }
129
130      }
131     
132     
133      /////////////////////////////////////////
134      ///////////// PART 2 ////////////////////
135      /////////////////////////////////////////
136     
137
138      // Create the XIOS communicator for every process which is related
139      // to XIOS, as well on client side as on server side
140     
141      MPI_Comm xiosGlobalComm ;
142      string strIds=CXios::getin<string>("clients_code_id","") ;
143      vector<string> clientsCodeId=splitRegex(strIds,"\\s*,\\s*") ;
144      if (strIds.empty())
145      {
146         // no code Ids given, suppose XIOS initialisation is global           
147         int commRank, commGlobalRank, serverLeader, clientLeader,serverRemoteLeader,clientRemoteLeader ;
148         MPI_Comm splitComm,interComm ;
149         MPI_Comm_rank(globalComm,&commGlobalRank) ;
150         xios::MPI_Comm_split(globalComm, 0, commGlobalRank, &splitComm) ;
151         int splitCommSize, globalCommSize ;
152       
153         MPI_Comm_size(splitComm,&splitCommSize) ;
154         MPI_Comm_size(globalComm,&globalCommSize) ;
155         if (splitCommSize==globalCommSize) // no server
156         {
157           xios::MPI_Comm_dup(globalComm,&xiosGlobalComm) ;
158           CXios::setXiosComm(xiosGlobalComm) ;
159         }
160         else
161         {
162           MPI_Comm_rank(splitComm,&commRank) ;
163           if (commRank==0) clientLeader=commGlobalRank ;
164           else clientLeader=0 ;
165           serverLeader=0 ;
166           MPI_Allreduce(&clientLeader,&clientRemoteLeader,1,MPI_INT,MPI_SUM,globalComm) ;
167           MPI_Allreduce(&serverLeader,&serverRemoteLeader,1,MPI_INT,MPI_SUM,globalComm) ;
168           xios::MPI_Intercomm_create(splitComm, 0, globalComm, serverRemoteLeader,1341,&interComm) ;
169           xios::MPI_Intercomm_merge(interComm,true,&xiosGlobalComm) ;
170           CXios::setXiosComm(xiosGlobalComm) ;
171           xios::MPI_Comm_free( &interComm );
172         }
173         xios::MPI_Comm_free( &splitComm );
174      }
175      else
176      {
177
178        xiosGlobalCommByFileExchange(clientComm, codeId) ;
179     
180      }
181
182      int commRank ;
183      MPI_Comm_rank(CXios::getXiosComm(), &commRank) ;
184      xios::MPI_Comm_split(CXios::getXiosComm(),false,commRank, &clientsComm_) ;
185      CXios::getMpiGarbageCollector().registerCommunicator(clientsComm_) ;
186     
187      // is using server or not ?
188      int xiosCommSize, clientsCommSize ; 
189      MPI_Comm_size(CXios::getXiosComm(), &xiosCommSize) ;
190      MPI_Comm_size(clientsComm_, &clientsCommSize) ;
191      if (xiosCommSize==clientsCommSize) CXios::setNotUsingServer() ;
192      else CXios::setUsingServer() ;
193
194      /////////////////////////////////////////
195      ///////////// PART 3 ////////////////////
196      /////////////////////////////////////////
197     
198      CXios::launchDaemonsManager(false) ;
199      shared_ptr<CEventScheduler> eventScheduler ;
200      poolRessource_ = new CPoolRessource(clientComm, eventScheduler, codeId, false) ;
201
202      /////////////////////////////////////////
203      ///////////// PART 4 ////////////////////
204      /////////////////////////////////////////     
205/*
206      MPI_Request req ;
207      MPI_Status status ;
208      MPI_Ibarrier(CXios::getXiosComm(),&req) ; // be sure that all services are created now, could be remove later if more asynchronisity
209      int ok=false ;
210      while (!ok)
211      {
212        CXios::getDaemonsManager()->eventLoop() ;
213        MPI_Test(&req,&ok,&status) ;
214      }
215*/     
216      returnComm = clientComm ;
217    }
218
219
220    void CClient::xiosGlobalCommByFileExchange(MPI_Comm clientComm, const string& codeId)
221    {
222 
223      MPI_Comm globalComm=CXios::getGlobalComm() ;
224      MPI_Comm xiosGlobalComm ;
225
226      string strIds=CXios::getin<string>("clients_code_id","") ;
227      vector<string> clientsCodeId=splitRegex(strIds,"\\s*,\\s*") ;
228
229      int commRank, globalRank, clientRank, serverRank ;
230      MPI_Comm_rank(clientComm, &commRank) ;
231      MPI_Comm_rank(globalComm, &globalRank) ;
232      string clientFileName("__xios_publisher::"+codeId+"__to_remove__") ;
233           
234      int error ;
235
236      if (commRank==0) // if root process publish name
237      { 
238        std::ofstream ofs (clientFileName, std::ofstream::out);
239        ofs<<globalRank ;
240        ofs.close();
241       
242  // get server root rank
243
244        std::ifstream ifs ;
245        string fileName=("__xios_publisher::"+CXios::xiosCodeId+"__to_remove__") ;
246     
247        double timeout = CXios::getin<double>("server_puplish_timeout",serverPublishDefaultTimeout) ;
248        double time ;
249         
250        do
251        {
252          CTimer::get("server_publish_timeout").resume() ; 
253          ifs.clear() ;
254          ifs.open(fileName, std::ifstream::in) ;
255          CTimer::get("server_publish_timeout").suspend() ;
256        } while (ifs.fail() && CTimer::get("server_publish_timeout").getCumulatedTime()<timeout) ;
257       
258        if (CTimer::get("server_publish_timeout").getCumulatedTime()>=timeout || ifs.fail())
259        {
260          ifs.clear() ;
261          ifs.close() ;
262          ifs.clear() ;
263          error=true ;           
264        }
265        else 
266        {
267          ifs>>serverRank ;
268          ifs.close() ;
269          error=false ;
270        } 
271
272      } 
273      MPI_Bcast(&error,1,MPI_INT,0,clientComm) ;
274     
275      if (error==false)  // you have a server
276      {
277        MPI_Comm intraComm ;
278        xios::MPI_Comm_dup(clientComm,&intraComm) ;
279        MPI_Comm interComm ;
280       
281        int pos=0 ;
282        for(int i=0 ; codeId!=clientsCodeId[i]; i++) pos=pos+1 ;
283
284        bool high=true ;
285        for(int i=pos ; i<clientsCodeId.size(); i++)
286        { 
287          xios::MPI_Intercomm_create(intraComm, 0, globalComm, serverRank, 3141, &interComm);
288          CXios::getMpiGarbageCollector().registerCommunicator(interComm) ;
289          xios::MPI_Comm_free(&intraComm) ;
290          xios::MPI_Intercomm_merge(interComm,high, &intraComm ) ;
291          high=false ;
292          if (i==pos) {
293            interComm_=interComm ;
294          }
295        }
296        xiosGlobalComm=intraComm ;
297      }
298      else  // no server detected
299      {
300        vector<int> clientsRank(clientsCodeId.size()) ;
301       
302        if (commRank==0)
303        { 
304          for(int i=0;i<clientsRank.size();i++)
305          {
306            std::ifstream ifs ;
307            string fileName=("__xios_publisher::"+clientsCodeId[i]+"__to_remove__") ;
308            do
309            {
310              ifs.clear() ;
311              ifs.open(fileName, std::ifstream::in) ;
312            } while (ifs.fail()) ;
313            ifs>>clientsRank[i] ;
314            ifs.close() ;
315          }
316        }
317         
318        int client ;
319        MPI_Comm intraComm ;
320        xios::MPI_Comm_dup(clientComm,&intraComm) ;
321        MPI_Comm interComm ;
322       
323        int pos=0 ;
324        for(int i=0 ; codeId!=clientsCodeId[i]; i++) pos=pos+1 ;
325       
326        bool high=true ;
327        for(int i=pos+1 ; i<clientsCodeId.size(); i++)
328        { 
329          if (codeId==clientsCodeId[0])   // first model play the server rule
330          {         
331            xios::MPI_Intercomm_create(intraComm, 0, globalComm, clientsRank[i], 3141, &interComm);
332            xios::MPI_Intercomm_merge(interComm,false, &intraComm ) ;
333          }
334          else
335          {         
336            xios::MPI_Intercomm_create(intraComm, 0, globalComm, clientsRank[0], 3141, &interComm);
337            xios::MPI_Intercomm_merge(interComm,high, &intraComm ) ;
338            high=false ;
339          }
340          if (i==pos) {
341            interComm_=interComm ; // NOT TESTED !
342          }
343        }
344        xiosGlobalComm=intraComm ;
345      }
346
347      MPI_Barrier(xiosGlobalComm);
348      if (commRank==0) std::remove(clientFileName.c_str()) ;         
349      MPI_Barrier(xiosGlobalComm);
350 
351      CXios::setXiosComm(xiosGlobalComm) ;
352
353    }
354
355// to check on other architecture
356    void CClient::xiosGlobalCommByPublishing(MPI_Comm clientComm, const string& codeId)
357    {
358
359      // untested. need to be developped an a true MPI compliant library
360
361/*
362        // try to discover other client/server
363        // do you have a xios server ?
364        char portName[MPI_MAX_PORT_NAME];
365        int ierr ;
366        int commRank ;
367        MPI_Comm_rank(clientComm,&commRank) ;
368
369        MPI_Barrier(globalComm) ;
370        if (commRank==0)
371        {
372             
373          MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN );
374          const char* serviceName=CXios::xiosCodeId.c_str() ;
375          ierr=MPI_Lookup_name(CXios::xiosCodeId.c_str(), MPI_INFO_NULL, portName);
376          MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL );
377        }
378        ierr=MPI_SUCCESS ;
379        MPI_Bcast(&ierr,1,MPI_INT,0,clientComm) ;
380
381        if (ierr==MPI_SUCCESS) // you have a server
382        { 
383          MPI_Comm intraComm=clientComm ;
384          MPI_Comm interComm ;
385          for(int i=0 ; i<clientsCodeId.size(); i++)
386          { 
387            MPI_Comm_connect(portName, MPI_INFO_NULL, 0, intraComm, &interComm);
388            xios::MPI_Intercomm_merge(interComm, true, &intraComm ) ;
389          }
390          xiosGlobalComm=intraComm ;
391        }
392        else  // you don't have any server
393        {
394          if (codeId==clientsCodeId[0]) // first code will publish his name
395          {
396
397            if (commRank==0) // if root process publish name
398            { 
399              MPI_Open_port(MPI_INFO_NULL, portName);
400              MPI_Publish_name(CXios::xiosCodeId.c_str(), MPI_INFO_NULL, portName);
401            }
402
403            MPI_Comm intraComm=clientComm ;
404            MPI_Comm interComm ;
405            for(int i=0 ; i<clientsCodeId.size()-1; i++)
406            { 
407              MPI_Comm_accept(portName, MPI_INFO_NULL, 0, intraComm, &interComm);
408              xios::MPI_Intercomm_merge(interComm,false, &intraComm ) ;
409            }
410          }
411          else  // other clients are connecting to the first one
412          {
413            if (commRank==0)
414            {
415
416              MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN );
417              ierr=MPI_Lookup_name(CXios::xiosCodeId.c_str(), MPI_INFO_NULL, portName);
418              MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL );
419             }
420
421            MPI_Bcast(&ierr,1,MPI_INT,0,clientComm) ;
422
423            if (ierr==MPI_SUCCESS) // you can connect
424            { 
425              MPI_Comm intraComm=clientComm ;
426              MPI_Comm interComm ;
427              for(int i=0 ; i<clientsCodeId.size()-1; i++)
428              { 
429                MPI_Comm_connect(portName, MPI_INFO_NULL, 0, intraComm, &interComm);
430                xios::MPI_Intercomm_merge(interComm, true, &intraComm ) ;
431              }
432              xiosGlobalComm=intraComm ;
433            }
434          }
435        } 
436      */
437    }
438
439
440///---------------------------------------------------------------
441/*!
442 * \fn void CClient::registerContext(const string& id, MPI_Comm contextComm)
443 * \brief Sends a request to create a context to server. Creates client/server contexts.
444 * \param [in] id id of context.
445 * \param [in] contextComm.
446 * Function is only called by client.
447 */
448    void CClient::registerContext(const string& id, MPI_Comm contextComm)
449    {
450      int commRank, commSize ;
451      MPI_Comm_rank(contextComm,&commRank) ;
452      MPI_Comm_size(contextComm,&commSize) ;
453     
454      shared_ptr<CEventScheduler> eventScheduler ;
455     
456      getPoolRessource()->createService(contextComm, eventScheduler, id, 0, CServicesManager::CLIENT, 1) ;
457//      getPoolRessource()->createService(contextComm, eventScheduler, id+"_"+CXios::defaultWriterId, 0, CServicesManager::WRITER, 1) ;
458      getPoolRessource()->createNewServiceOnto(id+"_"+CXios::defaultWriterId, CServicesManager::WRITER, id) ;
459//      getPoolRessource()->createService(contextComm, eventScheduler, id+"_"+CXios::defaultReaderId, 0, CServicesManager::READER, 1) ;
460      getPoolRessource()->createNewServiceOnto(id+"_"+CXios::defaultReaderId, CServicesManager::READER, id) ;
461
462      if (commRank==0) while (!CXios::getServicesManager()->hasService(getPoolRessource()->getId(), id, 0)) { CXios::getDaemonsManager()->eventLoop();}
463
464      if (commRank==0) CXios::getContextsManager()->createServerContext(getPoolRessource()->getId(), id, 0, id) ;
465      int type=CServicesManager::CLIENT ;
466      string name = CXios::getContextsManager()->getServerContextName(getPoolRessource()->getId(), id, 0, type, id) ;
467      double time ;
468      double lastTime=0 ;
469      double latency=0 ;
470      bool out=false ;
471      while (!out)
472      {
473        time=MPI_Wtime() ;
474        if (time-lastTime > latency) 
475        {
476          out=CXios::getContextsManager()->hasContext(name, contextComm);
477          lastTime=time ;
478        }
479        if (!out) CXios::getDaemonsManager()->eventLoop() ;
480      }
481
482    }
483
484
485
486/*!
487 * \fn void CClient::callOasisEnddef(void)
488 * \brief Send the order to the servers to call "oasis_enddef". It must be done by each compound of models before calling oasis_enddef on client side
489 * Function is only called by client.
490 */
491    void CClient::callOasisEnddef(void)
492    {
493      bool oasisEnddef=CXios::getin<bool>("call_oasis_enddef",true) ;
494      if (!oasisEnddef) ERROR("void CClient::callOasisEnddef(void)", <<"Function xios_oasis_enddef called but variable <call_oasis_enddef> is set to false."<<endl
495                                                                     <<"Variable <call_oasis_enddef> must be set to true"<<endl) ;
496      if (!CXios::isClient) // != isServer (change recently )
497      // Attached mode
498      {
499        // nothing to do   
500      }
501      else
502      {
503        int rank ;
504        int msg=0 ;
505
506        MPI_Comm_rank(intraComm_,&rank) ;
507        if (rank==0) 
508        {
509          MPI_Send(&msg,1,MPI_INT,0,5,interComm_) ; // tags oasis_endded = 5
510        }
511
512      }
513    }
514
515    void CClient::finalize(void)
516    {
517      MPI_Barrier(clientsComm_) ;
518      int commRank ;
519      MPI_Comm_rank(clientsComm_, &commRank) ;
520      if (commRank==0) CXios::getRessourcesManager()->finalize() ;
521     
522      CTimer::get("XIOS finalize").suspend();
523      CTimer::get("XIOS init/finalize",false).suspend() ;
524      CTimer::get("XIOS").suspend() ;
525      CXios::finalizeDaemonsManager() ;
526      finalizePoolRessource() ;
527      CContext::removeAllContexts() ; // free memory for related context
528      CXios::getMpiGarbageCollector().release() ; // release unfree MPI ressources
529      MPI_Comm xiosComm=CXios::getXiosComm() ;
530      xios::MPI_Comm_free(&xiosComm) ;
531      CCommTrack::dumpComm() ;
532      if (!is_MPI_Initialized)
533      {
534        if (!CXios::usingOasis) MPI_Finalize() ;
535      }
536     
537      info(20) << "Client side context is finalized"<<endl ;
538      report(0) <<" Performance report : Whole time from XIOS init and finalize: "<< CTimer::get("XIOS init/finalize").getCumulatedTime()<<" s"<<endl ;
539      report(0) <<" Performance report : total time spent for XIOS : "<< CTimer::get("XIOS").getCumulatedTime()<<" s"<<endl ;
540      report(0)<< " Performance report : time spent for waiting free buffer : "<< CTimer::get("Blocking time").getCumulatedTime()<<" s"<<endl ;
541      report(0)<< " Performance report : Ratio : "<< CTimer::get("Blocking time").getCumulatedTime()/CTimer::get("XIOS init/finalize").getCumulatedTime()*100.<<" %"<<endl ;
542      report(0)<< " Performance report : This ratio must be close to zero. Otherwise it may be usefull to increase buffer size or numbers of server"<<endl ;
543//      report(0)<< " Memory report : Current buffer_size : "<<CXios::bufferSize<<endl ;
544      report(0)<< " Memory report : Minimum buffer size required : " << CClientBuffer::maxRequestSize << " bytes" << endl ;
545      report(0)<< " Memory report : increasing it by a factor will increase performance, depending of the volume of data wrote in file at each time step of the file"<<endl ;
546
547      if (info.isActive(logProfile))
548      {
549        printProfile();
550      }
551       
552      if (info.isActive(logTimers)) report(0)<<"\n"<<CTimer::getAllCumulatedTime()<<endl ;
553      if (CXios::reportMemory)
554      {
555        report(100)<<CMemChecker::getAllCumulatedMem()<<endl ;
556      }
557      CWorkflowGraph::drawWorkFlowGraph_client();
558
559      xios::releaseStaticAllocation() ;
560
561    }
562
563    void CClient::printProfile()
564    {
565      list< pair<string,int> > timer_name;
566      timer_name.push_back({"XIOS init",0});
567      timer_name.push_back({"XIOS init context",0});
568      timer_name.push_back({"XIOS close definition",0});
569      timer_name.push_back({"XIOS solve inheritance",0});
570      timer_name.push_back({"XIOS update calendar",0});
571      timer_name.push_back({"Check late data (read)",1});
572      timer_name.push_back({"XIOS recv field",0});
573      timer_name.push_back({"XIOS send field",0});
574      timer_name.push_back({"Context event loop",1});
575      timer_name.push_back({"Model to client",1});
576      timer_name.push_back({"Client workflow",1});
577      timer_name.push_back({"Applying filters",2});
578      timer_name.push_back({"Transformation transfers",3});
579      timer_name.push_back({"Transformation MPI",4});
580      timer_name.push_back({"Temporal filters",3});
581      timer_name.push_back({"Scatter event",3});
582      timer_name.push_back({"Field : send data",4});
583      timer_name.push_back({"Blocking time",0});
584      timer_name.push_back({"XIOS context finalize",0});
585      timer_name.push_back({"XIOS finalize",0});
586     
587      report(0)<< endl;
588      double total_time = CTimer::get("XIOS").getCumulatedTime();
589      for(auto it_timer_name = timer_name.begin(); it_timer_name != timer_name.end(); it_timer_name++)
590      {
591        double timer_time = CTimer::get(it_timer_name->first).getCumulatedTime();
592        if ( timer_time / total_time > 0.001 )
593        {
594          ostringstream printed_line;
595          printed_line << setprecision(3) << std::fixed;
596          for(int itab=0;itab<it_timer_name->second;itab++)
597              printed_line << "  ";
598          printed_line << it_timer_name->first << " : " << timer_time <<endl;
599          string string_line = printed_line.str();
600          report(0)<< string_line;
601        }
602      }
603    }
604   
605    void CClient::finalizePoolRessource() 
606    { 
607      delete poolRessource_ ; poolRessource_=nullptr ;
608    }
609
610    /*!
611    * Return global rank without oasis and current rank in model intraComm in case of oasis
612    */
613   int CClient::getRank()
614   {
615     return rank_;
616   }
617
618    /*!
619    * Open a file specified by a suffix and an extension and use it for the given file buffer.
620    * The file name will be suffix+rank+extension.
621    *
622    * \param fileName[in] protype file name
623    * \param ext [in] extension of the file
624    * \param fb [in/out] the file buffer
625    */
626    void CClient::openStream(const StdString& fileName, const StdString& ext, std::filebuf* fb)
627    {
628      StdStringStream fileNameClient;
629      int numDigit = 0;
630      int size = 0;
631      int rank;
632      MPI_Comm_size(CXios::getGlobalComm(), &size);
633      MPI_Comm_rank(CXios::getGlobalComm(),&rank);
634      while (size)
635      {
636        size /= 10;
637        ++numDigit;
638      }
639
640      fileNameClient << fileName << "_" << std::setfill('0') << std::setw(numDigit) << rank << ext;
641
642      fb->open(fileNameClient.str().c_str(), std::ios::out);
643      if (!fb->is_open())
644        ERROR("void CClient::openStream(const StdString& fileName, const StdString& ext, std::filebuf* fb)",
645              << std::endl << "Can not open <" << fileNameClient.str() << "> file to write the client log(s).");
646    }
647
648    /*!
649    * \brief Open a file stream to write the info logs
650    * Open a file stream with a specific file name suffix+rank
651    * to write the info logs.
652    * \param fileName [in] protype file name
653    */
654    void CClient::openInfoStream(const StdString& fileName)
655    {
656      std::filebuf* fb = m_infoStream.rdbuf();
657      openStream(fileName, ".out", fb);
658
659      info.write2File(fb);
660      report.write2File(fb);
661    }
662
663    //! Write the info logs to standard output
664    void CClient::openInfoStream()
665    {
666      info.write2StdOut();
667      report.write2StdOut();
668    }
669
670    //! Close the info logs file if it opens
671    void CClient::closeInfoStream()
672    {
673      if (m_infoStream.is_open()) m_infoStream.close();
674    }
675
676    /*!
677    * \brief Open a file stream to write the error log
678    * Open a file stream with a specific file name suffix+rank
679    * to write the error log.
680    * \param fileName [in] protype file name
681    */
682    void CClient::openErrorStream(const StdString& fileName)
683    {
684      std::filebuf* fb = m_errorStream.rdbuf();
685      openStream(fileName, ".err", fb);
686
687      error.write2File(fb);
688    }
689
690    //! Write the error log to standard error output
691    void CClient::openErrorStream()
692    {
693      error.write2StdErr();
694    }
695
696    //! Close the error log file if it opens
697    void CClient::closeErrorStream()
698    {
699      if (m_errorStream.is_open()) m_errorStream.close();
700    }
701}
Note: See TracBrowser for help on using the repository browser.