source: XIOS1/branches/xios-1.0/src/client.cpp @ 2520

Last change on this file since 2520 was 548, checked in by rlacroix, 10 years ago

Backport r523 into the stable branch.

Improve the message error handling by mimicking the behavior of the info/report logs.

Output the error messages to the standart error message until the context is correctly initialized. Then, output the error messages to a file if the user has set "print_file" parameter to "true".

  • Fix: Errors that occured before MPI was initialized (e.g. during the config file parsing) caused a MPI error on top of the original error.
  • Fix: The error file could sometimes be misnamed if the error happened before the context was completely known.
  • 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: 9.6 KB
Line 
1#include "globalScopeData.hpp"
2#include "xmlioserver_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
14namespace xios
15{
16
17    MPI_Comm CClient::intraComm ;
18    MPI_Comm CClient::interComm ;
19    int CClient::serverLeader ;
20    bool CClient::is_MPI_Initialized ;
21    int CClient::rank = INVALID_RANK;
22    StdOFStream CClient::m_infoStream;
23    StdOFStream CClient::m_errorStream;
24
25    void CClient::initialize(const string& codeId,MPI_Comm& localComm,MPI_Comm& returnComm)
26    {
27      int initialized ;
28      MPI_Initialized(&initialized) ;
29      if (initialized) is_MPI_Initialized=true ;
30      else is_MPI_Initialized=false ;
31
32// don't use OASIS
33      if (!CXios::usingOasis)
34      {
35// localComm doesn't given
36        if (localComm == MPI_COMM_NULL)
37        {
38          if (!is_MPI_Initialized)
39          {
40            int argc=0;
41            char** argv=NULL;
42            MPI_Init(&argc,&argv) ;
43          }
44          CTimer::get("XIOS").resume() ;
45          CTimer::get("XIOS init").resume() ;
46          boost::hash<string> hashString ;
47
48          unsigned long hashClient=hashString(codeId) ;
49          unsigned long hashServer=hashString(CXios::xiosCodeId) ;
50          unsigned long* hashAll ;
51          int size ;
52          int myColor ;
53          int i,c ;
54          MPI_Comm newComm ;
55
56          MPI_Comm_size(CXios::globalComm,&size) ;
57          MPI_Comm_rank(CXios::globalComm,&rank);
58
59          hashAll=new unsigned long[size] ;
60
61          MPI_Allgather(&hashClient,1,MPI_LONG,hashAll,1,MPI_LONG,CXios::globalComm) ;
62
63          map<unsigned long, int> colors ;
64          map<unsigned long, int> leaders ;
65
66          for(i=0,c=0;i<size;i++)
67          {
68            if (colors.find(hashAll[i])==colors.end())
69            {
70              colors[hashAll[i]] =c ;
71              leaders[hashAll[i]]=i ;
72              c++ ;
73            }
74          }
75
76          // Verify whether we are on server mode or not
77          CXios::setNotUsingServer();
78          for (i=0; i < size; ++i)
79          {
80            if (hashServer == hashAll[i])
81            {
82              CXios::setUsingServer();
83              break;
84            }
85          }
86
87          myColor=colors[hashClient] ;
88
89          MPI_Comm_split(CXios::globalComm,myColor,rank,&intraComm) ;
90
91          if (CXios::usingServer)
92          {
93            int clientLeader=leaders[hashClient] ;
94            serverLeader=leaders[hashServer] ;
95
96            int intraCommSize, intraCommRank ;
97            MPI_Comm_size(intraComm,&intraCommSize) ;
98            MPI_Comm_rank(intraComm,&intraCommRank) ;
99            info(50)<<"intercommCreate::client "<<rank<<" intraCommSize : "<<intraCommSize
100                 <<" intraCommRank :"<<intraCommRank<<"  clientLeader "<< serverLeader<<endl ;
101            MPI_Intercomm_create(intraComm,0,CXios::globalComm,serverLeader,0,&interComm) ;
102          }
103          else
104          {
105            MPI_Comm_dup(intraComm,&interComm) ;
106          }
107          delete [] hashAll ;
108        }
109        // localComm argument is given
110        else
111        {
112          if (CXios::usingServer)
113          {
114            //ERROR("void CClient::initialize(const string& codeId,MPI_Comm& localComm,MPI_Comm& returnComm)", << " giving a local communictor is not compatible with using server mode") ;
115          }
116          else
117          {
118            MPI_Comm_dup(localComm,&intraComm) ;
119            MPI_Comm_dup(intraComm,&interComm) ;
120          }
121        }
122      }
123      // using OASIS
124      else
125      {
126        // localComm doesn't given
127        if (localComm == MPI_COMM_NULL)
128        {
129          if (!is_MPI_Initialized) oasis_init(codeId) ;
130          oasis_get_localcomm(intraComm) ;
131        }
132        else MPI_Comm_dup(localComm,&intraComm) ;
133        CTimer::get("XIOS").resume() ;
134        CTimer::get("XIOS init").resume() ;
135 
136        if (CXios::usingServer) 
137        {
138          MPI_Status status ;
139          MPI_Comm_rank(intraComm,&rank) ;
140
141          oasis_get_intercomm(interComm,CXios::xiosCodeId) ;
142          if (rank==0) MPI_Recv(&serverLeader,1, MPI_INT, 0, 0, interComm, &status) ;
143          MPI_Bcast(&serverLeader,1,MPI_INT,0,intraComm) ;
144
145        }
146        else MPI_Comm_dup(intraComm,&interComm) ;
147      }
148
149      MPI_Comm_dup(intraComm,&returnComm) ;
150    }
151
152
153    void CClient::registerContext(const string& id,MPI_Comm contextComm)
154    {
155      CContext::setCurrent(id) ;
156      CContext* context=CContext::create(id) ;
157
158      if (!CXios::isServer)
159      {
160        int size,rank,globalRank ;
161        size_t message_size ;
162        int leaderRank ;
163        MPI_Comm contextInterComm ;
164
165        MPI_Comm_size(contextComm,&size) ;
166        MPI_Comm_rank(contextComm,&rank) ;
167        MPI_Comm_rank(CXios::globalComm,&globalRank) ;
168        if (rank!=0) globalRank=0 ;
169
170
171        CMessage msg ;
172        msg<<id<<size<<globalRank ;
173
174        int messageSize=msg.size() ;
175        void * buff = new char[messageSize] ;
176        CBufferOut buffer(buff,messageSize) ;
177        buffer<<msg ;
178
179        MPI_Send(buff,buffer.count(),MPI_CHAR,serverLeader,1,CXios::globalComm) ;
180        delete [] buff ;
181
182        MPI_Intercomm_create(contextComm,0,CXios::globalComm,serverLeader,10+globalRank,&contextInterComm) ;
183        info(10)<<"Register new Context : "<<id<<endl ;
184
185        MPI_Comm inter ;
186        MPI_Intercomm_merge(contextInterComm,0,&inter) ;
187        MPI_Barrier(inter) ;
188
189        context->initClient(contextComm,contextInterComm) ;
190      }
191      else
192      {
193        MPI_Comm contextInterComm ;
194        MPI_Comm_dup(contextComm,&contextInterComm) ;
195        context->initClient(contextComm,contextInterComm) ;
196        context->initServer(contextComm,contextInterComm) ;
197      }
198    }
199
200    void CClient::finalize(void)
201    {
202      int rank ;
203      int msg=0 ;
204      if (!CXios::isServer)
205      {
206        MPI_Comm_rank(intraComm,&rank) ;
207        if (rank==0)
208        {
209          MPI_Send(&msg,1,MPI_INT,0,0,interComm) ;
210        }
211      }
212
213     CTimer::get("XIOS finalize").suspend() ;
214     CTimer::get("XIOS").suspend() ;
215
216      if (!is_MPI_Initialized)
217      {
218        if (CXios::usingOasis) oasis_finalize();
219        else MPI_Finalize() ;
220      }
221      info(20) << "Client side context is finalized"<<endl ;
222      report(0) <<" Performance report : total time spent for XIOS : "<< CTimer::get("XIOS").getCumulatedTime()<<" s"<<endl ;
223      report(0)<< " Performance report : time spent for waiting free buffer : "<< CTimer::get("Blocking time").getCumulatedTime()<<" s"<<endl ;
224      report(0)<< " Performance report : Ratio : "<< CTimer::get("Blocking time").getCumulatedTime()/CTimer::get("XIOS").getCumulatedTime()*100.<<" %"<<endl ;
225      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 ;
226      report(0)<< " Memory report : Current buffer_size : "<<CXios::bufferSize<<endl ;
227      report(0)<< " Memory report : Minimum buffer size required : "<<maxRequestSize*2<<endl ;
228      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 ;
229   }
230
231   int CClient::getRank()
232   {
233     return rank;
234   }
235
236    /*!
237    * Open a file specified by a suffix and an extension and use it for the given file buffer.
238    * The file name will be suffix+rank+extension.
239    *
240    * \param fileName[in] protype file name
241    * \param ext [in] extension of the file
242    * \param fb [in/out] the file buffer
243    */
244    void CClient::openStream(const StdString& fileName, const StdString& ext, std::filebuf* fb)
245    {
246      StdStringStream fileNameClient;
247      int numDigit = 0;
248      int size = 0;
249      MPI_Comm_size(CXios::globalComm, &size);
250      while (size)
251      {
252        size /= 10;
253        ++numDigit;
254      }
255
256      fileNameClient << fileName << "_" << std::setfill('0') << std::setw(numDigit) << getRank() << ext;
257      fb->open(fileNameClient.str().c_str(), std::ios::out);
258      if (!fb->is_open())
259        ERROR("void CClient::openStream(const StdString& fileName, const StdString& ext, std::filebuf* fb)",
260              << std::endl << "Can not open <" << fileNameClient << "> file to write the client log(s).");
261    }
262
263    /*!
264    * \brief Open a file stream to write the info logs
265    * Open a file stream with a specific file name suffix+rank
266    * to write the info logs.
267    * \param fileName [in] protype file name
268    */
269    void CClient::openInfoStream(const StdString& fileName)
270    {
271      std::filebuf* fb = m_infoStream.rdbuf();
272      openStream(fileName, ".out", fb);
273
274      info.write2File(fb);
275      report.write2File(fb);
276    }
277
278    //! Write the info logs to standard output
279    void CClient::openInfoStream()
280    {
281      info.write2StdOut();
282      report.write2StdOut();
283    }
284
285    //! Close the info logs file if it opens
286    void CClient::closeInfoStream()
287    {
288      if (m_infoStream.is_open()) m_infoStream.close();
289    }
290
291    /*!
292    * \brief Open a file stream to write the error log
293    * Open a file stream with a specific file name suffix+rank
294    * to write the error log.
295    * \param fileName [in] protype file name
296    */
297    void CClient::openErrorStream(const StdString& fileName)
298    {
299      std::filebuf* fb = m_errorStream.rdbuf();
300      openStream(fileName, ".err", fb);
301
302      error.write2File(fb);
303    }
304
305    //! Write the error log to standard error output
306    void CClient::openErrorStream()
307    {
308      error.write2StdErr();
309    }
310
311    //! Close the error log file if it opens
312    void CClient::closeErrorStream()
313    {
314      if (m_errorStream.is_open()) m_errorStream.close();
315    }
316}
Note: See TracBrowser for help on using the repository browser.