source: XIOS/dev/dev_olga/src/server.cpp @ 1150

Last change on this file since 1150 was 1150, checked in by oabramkina, 7 years ago

Initializaion in case of oasis is corrected. Not tested.

  • 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: 23.8 KB
Line 
1#include "globalScopeData.hpp"
2#include "xios_spl.hpp"
3#include "cxios.hpp"
4#include "server.hpp"
5#include "client.hpp"
6#include "type.hpp"
7#include "context.hpp"
8#include "object_template.hpp"
9#include "oasis_cinterface.hpp"
10#include <boost/functional/hash.hpp>
11#include <boost/algorithm/string.hpp>
12#include "mpi.hpp"
13#include "tracer.hpp"
14#include "timer.hpp"
15#include "event_scheduler.hpp"
16
17namespace xios
18{
19    MPI_Comm CServer::intraComm ;
20    list<MPI_Comm> CServer::interCommLeft ;
21    list<MPI_Comm> CServer::interCommRight ;
22//    list<MPI_Comm> CServer::interComm ;
23    std::list<MPI_Comm> CServer::contextInterComms;
24    std::list<MPI_Comm> CServer::contextIntraComms;
25    int CServer::serverLevel = 0 ;
26    int CServer::serverLeader_ = 0;
27    int CServer::serverSize_ = 0;
28    int CServer::nbPools = 0;
29    int CServer::poolId = 0;
30    int CServer::nbContexts = 0;
31    bool CServer::isRoot = false ;
32    int CServer::rank_ = INVALID_RANK;
33    StdOFStream CServer::m_infoStream;
34    StdOFStream CServer::m_errorStream;
35    map<string,CContext*> CServer::contextList ;
36    bool CServer::finished=false ;
37    bool CServer::is_MPI_Initialized ;
38    CEventScheduler* CServer::eventScheduler = 0;
39
40//---------------------------------------------------------------
41/*!
42 * \fn void CServer::initialize(void)
43 * Creates intraComm for each possible type of servers (classical, primary or secondary).
44 * In case of secondary servers intraComm is created for each secondary server pool.
45 * (For now the assumption is that there is one proc per pool.)
46 * Creates interComm and stores them into the following lists:
47 *   classical server -- interCommLeft
48 *   primary server -- interCommLeft and interCommRight
49 *   secondary server -- interCommLeft for each pool.
50 */
51    void CServer::initialize(void)
52    {
53      int initialized ;
54      MPI_Initialized(&initialized) ;
55      if (initialized) is_MPI_Initialized=true ;
56      else is_MPI_Initialized=false ;
57
58      // Not using OASIS
59      if (!CXios::usingOasis)
60      {
61
62        if (!is_MPI_Initialized)
63        {
64          MPI_Init(NULL, NULL);
65        }
66        CTimer::get("XIOS").resume() ;
67
68        boost::hash<string> hashString ;
69        unsigned long hashServer = hashString(CXios::xiosCodeId);
70
71        unsigned long* hashAll ;
72
73//        int rank ;
74        int size ;
75        int myColor ;
76        int i,c ;
77        MPI_Comm newComm, serversComm;
78
79        MPI_Comm_size(CXios::globalComm, &size) ;
80        MPI_Comm_rank(CXios::globalComm, &rank_);
81
82        hashAll=new unsigned long[size] ;
83        MPI_Allgather(&hashServer, 1, MPI_LONG, hashAll, 1, MPI_LONG, CXios::globalComm) ;
84
85        map<unsigned long, int> colors ;
86        map<unsigned long, int> leaders ;
87        map<unsigned long, int>::iterator it ;
88
89        int nbSrv = 0;
90        for(i=0,c=0;i<size;i++)
91        {
92          if (colors.find(hashAll[i])==colors.end())
93          {
94            colors[hashAll[i]]=c ;
95            leaders[hashAll[i]]=i ;
96            c++ ;
97          }
98          if (hashAll[i] == hashServer) ++serverSize_;
99        }
100
101        // Setting the number of secondary pools
102        myColor = colors[hashServer];
103        if (CXios::usingServer2)
104        {
105          int serverRank = rank_ - leaders[hashServer]; // server proc rank starting 0
106          nbPools = serverSize_ * CXios::ratioServer2 / 100;
107          if ( serverRank < (serverSize_ - nbPools) )
108          {
109            serverLevel = 1;
110          }
111          else
112          {
113            serverLevel = 2;
114            poolId = serverRank - serverSize_ + nbPools;
115            myColor = rank_ + size; // + size to make sure that myColor is unique among not only servers but also clients. It's only a temporary solution
116          }
117        }
118
119        MPI_Comm_split(CXios::globalComm, myColor, rank_, &intraComm) ;
120
121        if (serverLevel == 0)
122        {
123          int clientLeader;
124          for(it=leaders.begin();it!=leaders.end();it++)
125          {
126            if (it->first!=hashServer)
127            {
128              clientLeader=it->second ;
129              int intraCommSize, intraCommRank ;
130              MPI_Comm_size(intraComm,&intraCommSize) ;
131              MPI_Comm_rank(intraComm,&intraCommRank) ;
132              info(50)<<"intercommCreate::server (classical mode) "<<rank_<<" intraCommSize : "<<intraCommSize
133                       <<" intraCommRank :"<<intraCommRank<<"  clientLeader "<< clientLeader<<endl ;
134
135              MPI_Intercomm_create(intraComm, 0, CXios::globalComm, clientLeader, 0, &newComm) ;
136               interCommLeft.push_back(newComm) ;
137            }
138          }
139        }
140        else if (serverLevel == 1)
141        {
142          int clientLeader, srvSndLeader;
143          int srvPrmLeader ;
144          for (it=leaders.begin();it!=leaders.end();it++)
145          {
146            if (it->first != hashServer)
147            {
148              clientLeader=it->second ;
149              int intraCommSize, intraCommRank ;
150              MPI_Comm_size(intraComm, &intraCommSize) ;
151              MPI_Comm_rank(intraComm, &intraCommRank) ;
152              info(50)<<"intercommCreate::server (server level 1) "<<rank_<<" intraCommSize : "<<intraCommSize
153                       <<" intraCommRank :"<<intraCommRank<<"  clientLeader "<< clientLeader<<endl ;
154              MPI_Intercomm_create(intraComm, 0, CXios::globalComm, clientLeader, 0, &newComm) ;
155              interCommLeft.push_back(newComm) ;
156            }
157            else
158              serverLeader_ = it->second;
159          }
160
161          for (int i = 0; i < nbPools; ++i)
162          {
163            srvSndLeader = serverLeader_ + serverSize_ - nbPools + i;
164            int intraCommSize, intraCommRank ;
165            MPI_Comm_size(intraComm, &intraCommSize) ;
166            MPI_Comm_rank(intraComm, &intraCommRank) ;
167            info(50)<<"intercommCreate::client (server level 1) "<<rank_<<" intraCommSize : "<<intraCommSize
168                <<" intraCommRank :"<<intraCommRank<<"  clientLeader "<< srvSndLeader<<endl ;
169            MPI_Intercomm_create(intraComm, 0, CXios::globalComm, srvSndLeader, 1, &newComm) ;
170            interCommRight.push_back(newComm) ;
171          }
172        } // primary server
173        else
174        {
175          int clientLeader;
176          clientLeader = leaders[hashString(CXios::xiosCodeId)];
177          int intraCommSize, intraCommRank ;
178          MPI_Comm_size(intraComm, &intraCommSize) ;
179          MPI_Comm_rank(intraComm, &intraCommRank) ;
180          info(50)<<"intercommCreate::server (server level 2) "<<rank_<<" intraCommSize : "<<intraCommSize
181                   <<" intraCommRank :"<<intraCommRank<<"  clientLeader "<< clientLeader<<endl ;
182
183          MPI_Intercomm_create(intraComm, 0, CXios::globalComm, clientLeader, 1, &newComm) ;
184          interCommLeft.push_back(newComm) ;
185        } // secondary server
186
187        delete [] hashAll ;
188
189      }
190      // using OASIS
191      else
192      {
193        int size, rank;
194        int myColor;
195        if (!is_MPI_Initialized) oasis_init(CXios::xiosCodeId);
196
197        CTimer::get("XIOS").resume() ;
198        MPI_Comm localComm;
199        oasis_get_localcomm(localComm);
200
201        // Create server intraComm
202        if (!CXios::usingServer2)
203          MPI_Comm_dup(localComm, &intraComm);
204        else
205        {
206          MPI_Comm_rank(localComm,&rank) ;
207          MPI_Comm_size(localComm,&serverSize_) ;
208          nbPools = serverSize_ * CXios::ratioServer2 / 100;
209          if ( rank < (serverSize_ - nbPools) )
210          {
211            serverLevel = 1;
212            myColor = 0;
213          }
214          else
215          {
216            serverLevel = 2;
217            poolId = rank - serverSize_ + nbPools;
218            myColor = rank;
219          }
220          MPI_Comm_split(localComm, myColor, rank, &intraComm) ;
221
222        }
223        MPI_Comm_rank(intraComm,&rank_) ;
224        MPI_Comm_size(intraComm,&size) ;
225
226        string codesId=CXios::getin<string>("oasis_codes_id") ;
227
228        vector<string> splitted ;
229        boost::split( splitted, codesId, boost::is_any_of(","), boost::token_compress_on ) ;
230        vector<string>::iterator it ;
231
232        MPI_Comm newComm ;
233        int globalRank ;
234        MPI_Comm_rank(CXios::globalComm,&globalRank);
235        if (rank_ == 0)
236          serverLeader_ = globalRank;
237
238        for(it=splitted.begin();it!=splitted.end();it++)
239        {
240          oasis_get_intercomm(newComm,*it) ;
241//        interComm.push_back(newComm) ;
242          if ( !CXios::usingServer2)
243          {
244            interCommLeft.push_back(newComm) ;
245            if (rank_==0) MPI_Send(&globalRank,1,MPI_INT,0,0,newComm) ;
246          }
247          else
248          {
249            if (serverLevel == 1)
250            {
251              interCommLeft.push_back(newComm) ;
252              if (rank_==0) MPI_Send(&globalRank,1,MPI_INT,0,0,newComm) ;
253              for (int i = 0; i < nbPools; ++i)
254              {
255                int srvSndLeader = serverLeader_ + serverSize_ - nbPools + i;
256                info(50)<<"intercommCreate::client (server level 1) "<<globalRank<<" intraCommSize : "<<size
257                    <<" intraCommRank :"<<rank_<<"  clientLeader "<< srvSndLeader<<endl ;
258                MPI_Intercomm_create(intraComm, 0, CXios::globalComm, srvSndLeader, 0, &newComm) ;
259                interCommRight.push_back(newComm) ;
260              }
261            }
262            else if (serverLevel == 2)
263            {
264              info(50)<<"intercommCreate::server "<<rank_<<" intraCommSize : "<<size
265                       <<" intraCommRank :"<<rank_<<"  clientLeader "<< 0<<endl ;
266              MPI_Intercomm_create(intraComm, 0, localComm, 0, 0, &newComm) ;
267              interCommLeft.push_back(newComm) ;
268            }
269          }
270//          MPI_Comm_remote_size(newComm,&size);
271        }
272              oasis_enddef() ;
273      }
274
275      MPI_Comm_rank(intraComm, &rank_) ;
276      if (rank_==0) isRoot=true;
277      else isRoot=false;
278     
279      eventScheduler = new CEventScheduler(intraComm) ;
280    }
281
282    void CServer::finalize(void)
283    {
284
285      CTimer::get("XIOS").suspend() ;
286     
287      delete eventScheduler ;
288
289      for (std::list<MPI_Comm>::iterator it = contextInterComms.begin(); it != contextInterComms.end(); it++)
290        MPI_Comm_free(&(*it));
291
292      for (std::list<MPI_Comm>::iterator it = contextIntraComms.begin(); it != contextIntraComms.end(); it++)
293        MPI_Comm_free(&(*it));
294
295//      for (std::list<MPI_Comm>::iterator it = interComm.begin(); it != interComm.end(); it++)
296//        MPI_Comm_free(&(*it));
297
298//        for (std::list<MPI_Comm>::iterator it = interCommLeft.begin(); it != interCommLeft.end(); it++)
299//          MPI_Comm_free(&(*it));
300
301        for (std::list<MPI_Comm>::iterator it = interCommRight.begin(); it != interCommRight.end(); it++)
302          MPI_Comm_free(&(*it));
303
304      MPI_Comm_free(&intraComm);
305
306      if (!is_MPI_Initialized)
307      {
308        if (CXios::usingOasis) oasis_finalize();
309        else MPI_Finalize() ;
310      }
311      report(0)<<"Performance report : Time spent for XIOS : "<<CTimer::get("XIOS server").getCumulatedTime()<<endl  ;
312      report(0)<<"Performance report : Time spent in processing events : "<<CTimer::get("Process events").getCumulatedTime()<<endl  ;
313      report(0)<<"Performance report : Ratio : "<<CTimer::get("Process events").getCumulatedTime()/CTimer::get("XIOS server").getCumulatedTime()*100.<<"%"<<endl  ;
314    }
315
316     void CServer::eventLoop(void)
317     {
318       bool stop=false ;
319
320       CTimer::get("XIOS server").resume() ;
321       while(!stop)
322       {
323         if (isRoot)
324         {
325           listenContext();
326           listenRootContext();
327           if (!finished) listenFinalize() ;
328         }
329         else
330         {
331           listenRootContext();
332           if (!finished) listenRootFinalize() ;
333         }
334
335         contextEventLoop() ;
336         if (finished && contextList.empty()) stop=true ;
337         eventScheduler->checkEvent() ;
338
339       }
340       CTimer::get("XIOS server").suspend() ;
341     }
342
343     void CServer::listenFinalize(void)
344     {
345        list<MPI_Comm>::iterator it, itr;
346        int msg ;
347        int flag ;
348
349        for(it=interCommLeft.begin();it!=interCommLeft.end();it++)
350        {
351           MPI_Status status ;
352           traceOff() ;
353           MPI_Iprobe(0,0,*it,&flag,&status) ;
354           traceOn() ;
355           if (flag==true)
356           {
357              MPI_Recv(&msg,1,MPI_INT,0,0,*it,&status) ;
358              info(20)<<" CServer : Receive client finalize"<<endl ;
359              // Sending server finalize message to secondary servers (if any)
360              for(itr=interCommRight.begin();itr!=interCommRight.end();itr++)
361              {
362                MPI_Send(&msg,1,MPI_INT,0,0,*itr) ;
363              }
364              MPI_Comm_free(&(*it));
365              interCommLeft.erase(it) ;
366              break ;
367            }
368         }
369
370         if (interCommLeft.empty())
371         {
372           int i,size ;
373           MPI_Comm_size(intraComm,&size) ;
374           MPI_Request* requests= new MPI_Request[size-1] ;
375           MPI_Status* status= new MPI_Status[size-1] ;
376
377           for(int i=1;i<size;i++) MPI_Isend(&msg,1,MPI_INT,i,4,intraComm,&requests[i-1]) ;
378           MPI_Waitall(size-1,requests,status) ;
379
380           finished=true ;
381           delete [] requests ;
382           delete [] status ;
383         }
384     }
385
386
387     void CServer::listenRootFinalize()
388     {
389        int flag ;
390        MPI_Status status ;
391        int msg ;
392
393        traceOff() ;
394        MPI_Iprobe(0,4,intraComm, &flag, &status) ;
395        traceOn() ;
396        if (flag==true)
397        {
398           MPI_Recv(&msg,1,MPI_INT,0,4,intraComm,&status) ;
399           finished=true ;
400        }
401      }
402
403     void CServer::listenContext(void)
404     {
405
406       MPI_Status status ;
407       int flag ;
408       static void* buffer ;
409       static MPI_Request request ;
410       static bool recept=false ;
411       int rank ;
412       int count ;
413
414       if (recept==false)
415       {
416         traceOff() ;
417         MPI_Iprobe(MPI_ANY_SOURCE,1,CXios::globalComm, &flag, &status) ;
418         traceOn() ;
419         if (flag==true)
420         {
421           rank=status.MPI_SOURCE ;
422           MPI_Get_count(&status,MPI_CHAR,&count) ;
423           buffer=new char[count] ;
424           MPI_Irecv(buffer,count,MPI_CHAR,rank,1,CXios::globalComm,&request) ;
425           recept=true ;
426         }
427       }
428       else
429       {
430         traceOff() ;
431         MPI_Test(&request,&flag,&status) ;
432         traceOn() ;
433         if (flag==true)
434         {
435           rank=status.MPI_SOURCE ;
436           MPI_Get_count(&status,MPI_CHAR,&count) ;
437           recvContextMessage(buffer,count) ;
438           delete [] buffer;
439           recept=false ;
440         }
441       }
442     }
443
444     void CServer::recvContextMessage(void* buff,int count)
445     {
446       static map<string,contextMessage> recvContextId;
447       map<string,contextMessage>::iterator it ;
448       CBufferIn buffer(buff,count) ;
449       string id ;
450       int clientLeader ;
451       int nbMessage ;
452
453       buffer>>id>>nbMessage>>clientLeader ;
454
455       it=recvContextId.find(id) ;
456       if (it==recvContextId.end())
457       {
458         contextMessage msg={0,0} ;
459         pair<map<string,contextMessage>::iterator,bool> ret ;
460         ret=recvContextId.insert(pair<string,contextMessage>(id,msg)) ;
461         it=ret.first ;
462       }
463       it->second.nbRecv+=1 ;
464       it->second.leaderRank+=clientLeader ;
465
466       if (it->second.nbRecv==nbMessage)
467       {
468         int size ;
469         MPI_Comm_size(intraComm,&size) ;
470//         MPI_Request* requests= new MPI_Request[size-1] ;
471//         MPI_Status* status= new MPI_Status[size-1] ;
472         MPI_Request* requests= new MPI_Request[size] ;
473         MPI_Status* status= new MPI_Status[size] ;
474
475         CMessage msg ;
476         msg<<id<<it->second.leaderRank;
477         int messageSize=msg.size() ;
478         void * sendBuff = new char[messageSize] ;
479         CBufferOut sendBuffer(sendBuff,messageSize) ;
480         sendBuffer<<msg ;
481
482         // Include root itself in order not to have a divergence
483         for(int i=0; i<size; i++)
484         {
485           MPI_Isend(sendBuff,count,MPI_CHAR,i,2,intraComm,&requests[i]) ;
486         }
487
488//         for(int i=1;i<size;i++)
489//         {
490//            MPI_Isend(buff,count,MPI_CHAR,i,2,intraComm,&requests[i-1]) ;
491//         }
492//         MPI_Waitall(size-1,requests,status) ;
493//         registerContext(buff,count,it->second.leaderRank) ;
494
495         recvContextId.erase(it) ;
496         delete [] requests ;
497         delete [] status ;
498
499       }
500     }
501
502     void CServer::listenRootContext(void)
503     {
504       MPI_Status status ;
505       int flag ;
506       static void* buffer ;
507       static MPI_Request request ;
508       static bool recept=false ;
509       int rank ;
510//       int count ;
511       static int count ;
512       const int root=0 ;
513       boost::hash<string> hashString;
514       size_t hashId = hashString("RegisterContext");
515
516       // (1) Receive context id from the root
517       if (recept==false)
518       {
519         traceOff() ;
520         MPI_Iprobe(root,2,intraComm, &flag, &status) ;
521         traceOn() ;
522         if (flag==true)
523         {
524           MPI_Get_count(&status,MPI_CHAR,&count) ;
525           buffer=new char[count] ;
526           MPI_Irecv(buffer,count,MPI_CHAR,root,2,intraComm,&request) ;
527           recept=true ;
528         }
529       }
530       // (2) If context id is received, save it into a buffer and register an event
531       else
532       {
533         MPI_Test(&request,&flag,&status) ;
534         if (flag==true)
535         {
536           MPI_Get_count(&status,MPI_CHAR,&count) ;
537           eventScheduler->registerEvent(nbContexts,hashId);
538//           registerContext(buffer,count) ;
539//           delete [] buffer ;
540           recept=false ;
541         }
542       }
543       // (3) If event has been scheduled, call register context
544       if (eventScheduler->queryEvent(nbContexts,hashId))
545       {
546         registerContext(buffer,count) ;
547         ++nbContexts;
548         delete [] buffer ;
549       }
550     }
551
552     void CServer::registerContext(void* buff, int count, int leaderRank)
553     {
554       string contextId;
555       CBufferIn buffer(buff, count);
556//       buffer >> contextId;
557       buffer >> contextId>>leaderRank;
558       CContext* context;
559
560       info(20) << "CServer : Register new Context : " << contextId << endl;
561
562       if (contextList.find(contextId) != contextList.end())
563         ERROR("void CServer::registerContext(void* buff, int count, int leaderRank)",
564               << "Context '" << contextId << "' has already been registred");
565
566       context=CContext::create(contextId);
567       contextList[contextId]=context;
568
569       // Primary or classical server: create communication channel with a client
570       // (1) create interComm (with a client)
571       // (2) initialize client and server (contextClient and contextServer)
572       MPI_Comm inter;
573       if (serverLevel < 2)
574       {
575         MPI_Comm contextInterComm;
576         MPI_Intercomm_create(intraComm, 0, CXios::globalComm, leaderRank, 10+leaderRank, &contextInterComm);
577         MPI_Intercomm_merge(contextInterComm,1,&inter);
578         MPI_Barrier(inter);
579         MPI_Comm_free(&inter);
580         context->initServer(intraComm,contextInterComm);
581         contextInterComms.push_back(contextInterComm);
582
583       }
584       // Secondary server: create communication channel with a primary server
585       // (1) duplicate interComm with a primary server
586       // (2) initialize client and server (contextClient and contextServer)
587       // Remark: in the case of the secondary server there is no need to create an interComm calling MPI_Intercomm_create,
588       //         because interComm of CContext is defined on the same processes as the interComm of CServer.
589       //         So just duplicate it.
590       else if (serverLevel == 2)
591       {
592         MPI_Comm_dup(interCommLeft.front(), &inter);
593         contextInterComms.push_back(inter);
594         context->initServer(intraComm, contextInterComms.back());
595       }
596
597       // Primary server:
598       // (1) send create context message to secondary servers
599       // (2) initialize communication channels with secondary servers (create contextClient and contextServer)
600       if (serverLevel == 1)
601       {
602         int i = 0, size;
603         CMessage msg;
604         int messageSize;
605         MPI_Comm_size(intraComm, &size) ;
606         for (std::list<MPI_Comm>::iterator it = interCommRight.begin(); it != interCommRight.end(); it++, ++i)
607         {
608           StdString str = contextId +"_server_" + boost::lexical_cast<string>(i);
609           msg<<str<<size<<rank_ ;
610           messageSize = msg.size() ;
611           buff = new char[messageSize] ;
612           CBufferOut buffer(buff,messageSize) ;
613           buffer<<msg ;
614           int sndServerGloRanks = serverSize_-nbPools+serverLeader_ +i;  // the assumption is that there is only one proc per secondary server pool
615           MPI_Send(buff, buffer.count(), MPI_CHAR, sndServerGloRanks, 1, CXios::globalComm) ;
616           MPI_Comm_dup(*it, &inter);
617           contextInterComms.push_back(inter);
618           MPI_Comm_dup(intraComm, &inter);
619           contextIntraComms.push_back(inter);
620           context->initClient(contextIntraComms.back(), contextInterComms.back()) ;
621           delete [] buff ;
622         }
623       }
624     }
625
626     void CServer::contextEventLoop(void)
627     {
628       bool isFinalized ;
629       map<string,CContext*>::iterator it ;
630
631       for(it=contextList.begin();it!=contextList.end();it++)
632       {
633         isFinalized=it->second->isFinalized();
634         if (isFinalized)
635         {
636           contextList.erase(it) ;
637           break ;
638         }
639         else
640           it->second->checkBuffersAndListen();
641       }
642     }
643
644     //! Get rank of the current process in the intraComm
645     int CServer::getRank()
646     {
647       return rank_;
648     }
649
650    /*!
651    * Open a file specified by a suffix and an extension and use it for the given file buffer.
652    * The file name will be suffix+rank+extension.
653    *
654    * \param fileName[in] protype file name
655    * \param ext [in] extension of the file
656    * \param fb [in/out] the file buffer
657    */
658    void CServer::openStream(const StdString& fileName, const StdString& ext, std::filebuf* fb)
659    {
660      StdStringStream fileNameClient;
661      int numDigit = 0;
662      int size = 0;
663      int id;
664      MPI_Comm_size(CXios::globalComm, &size);
665      while (size)
666      {
667        size /= 10;
668        ++numDigit;
669      }
670
671      if (!CXios::usingServer2)
672        id = getRank();
673      else
674      {
675        if (serverLevel == 1)
676          id = rank_;
677        else
678          id = poolId;
679      }
680      fileNameClient << fileName << "_" << std::setfill('0') << std::setw(numDigit) << id << ext;
681      fb->open(fileNameClient.str().c_str(), std::ios::out);
682      if (!fb->is_open())
683        ERROR("void CServer::openStream(const StdString& fileName, const StdString& ext, std::filebuf* fb)",
684              << std::endl << "Can not open <" << fileNameClient << "> file to write the server log(s).");
685    }
686
687    /*!
688    * \brief Open a file stream to write the info logs
689    * Open a file stream with a specific file name suffix+rank
690    * to write the info logs.
691    * \param fileName [in] protype file name
692    */
693    void CServer::openInfoStream(const StdString& fileName)
694    {
695      std::filebuf* fb = m_infoStream.rdbuf();
696      openStream(fileName, ".out", fb);
697
698      info.write2File(fb);
699      report.write2File(fb);
700    }
701
702    //! Write the info logs to standard output
703    void CServer::openInfoStream()
704    {
705      info.write2StdOut();
706      report.write2StdOut();
707    }
708
709    //! Close the info logs file if it opens
710    void CServer::closeInfoStream()
711    {
712      if (m_infoStream.is_open()) m_infoStream.close();
713    }
714
715    /*!
716    * \brief Open a file stream to write the error log
717    * Open a file stream with a specific file name suffix+rank
718    * to write the error log.
719    * \param fileName [in] protype file name
720    */
721    void CServer::openErrorStream(const StdString& fileName)
722    {
723      std::filebuf* fb = m_errorStream.rdbuf();
724      openStream(fileName, ".err", fb);
725
726      error.write2File(fb);
727    }
728
729    //! Write the error log to standard error output
730    void CServer::openErrorStream()
731    {
732      error.write2StdErr();
733    }
734
735    //! Close the error log file if it opens
736    void CServer::closeErrorStream()
737    {
738      if (m_errorStream.is_open()) m_errorStream.close();
739    }
740}
Note: See TracBrowser for help on using the repository browser.