source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.cpp @ 1973

Last change on this file since 1973 was 1973, checked in by ymipsl, 4 years ago

Big cleaning on XIOS coupling branch
YM

  • 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
File size: 89.9 KB
Line 
1#include "context.hpp"
2#include "attribute_template.hpp"
3#include "object_template.hpp"
4#include "group_template.hpp"
5
6#include "calendar_type.hpp"
7#include "duration.hpp"
8
9#include "context_client.hpp"
10#include "context_server.hpp"
11#include "nc4_data_output.hpp"
12#include "node_type.hpp"
13#include "message.hpp"
14#include "type.hpp"
15#include "xios_spl.hpp"
16#include "timer.hpp"
17#include "memtrack.hpp"
18#include <limits>
19#include <fstream>
20#include "server.hpp"
21#include "distribute_file_server2.hpp"
22#include "services_manager.hpp"
23#include "contexts_manager.hpp"
24#include "cxios.hpp"
25#include "client.hpp"
26#include "coupler_in.hpp"
27#include "coupler_out.hpp"
28
29namespace xios {
30
31  std::shared_ptr<CContextGroup> CContext::root;
32
33   /// ////////////////////// Définitions ////////////////////// ///
34
35   CContext::CContext(void)
36      : CObjectTemplate<CContext>(), CContextAttributes()
37      , calendar(), hasClient(false), hasServer(false)
38      , isPostProcessed(false), finalized(false)
39      , client(nullptr), server(nullptr)
40      , allProcessed(false), countChildContextFinalized_(0), isProcessingEvent_(false)
41
42   { /* Ne rien faire de plus */ }
43
44   CContext::CContext(const StdString & id)
45      : CObjectTemplate<CContext>(id), CContextAttributes()
46      , calendar(), hasClient(false), hasServer(false)
47      , isPostProcessed(false), finalized(false)
48      , client(nullptr), server(nullptr)
49      , allProcessed(false), countChildContextFinalized_(0), isProcessingEvent_(false)
50   { /* Ne rien faire de plus */ }
51
52   CContext::~CContext(void)
53   {
54     delete client;
55     delete server;
56     for (std::vector<CContextClient*>::iterator it = clientPrimServer.begin(); it != clientPrimServer.end(); it++)  delete *it;
57     for (std::vector<CContextServer*>::iterator it = serverPrimServer.begin(); it != serverPrimServer.end(); it++)  delete *it;
58
59   }
60
61   //----------------------------------------------------------------
62   //! Get name of context
63   StdString CContext::GetName(void)   { return (StdString("context")); }
64   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
65   ENodeType CContext::GetType(void)   { return (eContext); }
66
67   //----------------------------------------------------------------
68
69   /*!
70   \brief Get context group (context root)
71   \return Context root
72   */
73   CContextGroup* CContext::getRoot(void)
74   TRY
75   {
76      if (root.get()==NULL) root=std::shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName()));
77      return root.get();
78   }
79   CATCH
80
81   //----------------------------------------------------------------
82
83   /*!
84   \brief Get calendar of a context
85   \return Calendar
86   */
87   std::shared_ptr<CCalendar> CContext::getCalendar(void) const
88   TRY
89   {
90      return (this->calendar);
91   }
92   CATCH
93
94   //----------------------------------------------------------------
95
96   /*!
97   \brief Set a context with a calendar
98   \param[in] newCalendar new calendar
99   */
100   void CContext::setCalendar(std::shared_ptr<CCalendar> newCalendar)
101   TRY
102   {
103      this->calendar = newCalendar;
104   }
105   CATCH_DUMP_ATTR
106
107   //----------------------------------------------------------------
108   /*!
109   \brief Parse xml file and write information into context object
110   \param [in] node xmld node corresponding in xml file
111   */
112   void CContext::parse(xml::CXMLNode & node)
113   TRY
114   {
115      CContext::SuperClass::parse(node);
116
117      // PARSING POUR GESTION DES ENFANTS
118      xml::THashAttributes attributes = node.getAttributes();
119
120      if (attributes.end() != attributes.find("src"))
121      {
122         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
123         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
124            ERROR("void CContext::parse(xml::CXMLNode & node)",
125                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
126         if (!ifs.good())
127            ERROR("CContext::parse(xml::CXMLNode & node)",
128                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
129         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
130      }
131
132      if (node.getElementName().compare(CContext::GetName()))
133         DEBUG("Le noeud is wrong defined but will be considered as a context !");
134
135      if (!(node.goToChildElement()))
136      {
137         DEBUG("Le context ne contient pas d'enfant !");
138      }
139      else
140      {
141         do { // Parcours des contextes pour traitement.
142
143            StdString name = node.getElementName();
144            attributes.clear();
145            attributes = node.getAttributes();
146
147            if (attributes.end() != attributes.find("id"))
148            {
149              DEBUG(<< "Definition node has an id,"
150                    << "it will not be taking account !");
151            }
152
153#define DECLARE_NODE(Name_, name_)    \
154   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
155   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node); continue; }
156#define DECLARE_NODE_PAR(Name_, name_)
157#include "node_type.conf"
158
159            DEBUG(<< "The element \'"     << name
160                  << "\' in the context \'" << CContext::getCurrent()->getId()
161                  << "\' is not a definition !");
162
163         } while (node.goToNextElement());
164
165         node.goToParentElement(); // Retour au parent
166      }
167   }
168   CATCH_DUMP_ATTR
169
170   //----------------------------------------------------------------
171   //! Show tree structure of context
172   void CContext::ShowTree(StdOStream & out)
173   TRY
174   {
175      StdString currentContextId = CContext::getCurrent() -> getId();
176      std::vector<CContext*> def_vector =
177         CContext::getRoot()->getChildList();
178      std::vector<CContext*>::iterator
179         it = def_vector.begin(), end = def_vector.end();
180
181      out << "<? xml version=\"1.0\" ?>" << std::endl;
182      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
183
184      for (; it != end; it++)
185      {
186         CContext* context = *it;
187         CContext::setCurrent(context->getId());
188         out << *context << std::endl;
189      }
190
191      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
192      CContext::setCurrent(currentContextId);
193   }
194   CATCH
195
196   //----------------------------------------------------------------
197
198   //! Convert context object into string (to print)
199   StdString CContext::toString(void) const
200   TRY
201   {
202      StdOStringStream oss;
203      oss << "<" << CContext::GetName()
204          << " id=\"" << this->getId() << "\" "
205          << SuperClassAttribute::toString() << ">" << std::endl;
206      if (!this->hasChild())
207      {
208         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
209      }
210      else
211      {
212
213#define DECLARE_NODE(Name_, name_)    \
214   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
215   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
216#define DECLARE_NODE_PAR(Name_, name_)
217#include "node_type.conf"
218
219      }
220      oss << "</" << CContext::GetName() << " >";
221      return (oss.str());
222   }
223   CATCH
224
225   //----------------------------------------------------------------
226
227   /*!
228   \brief Find all inheritace among objects in a context.
229   \param [in] apply (true) write attributes of parent into ones of child if they are empty
230                     (false) write attributes of parent into a new container of child
231   \param [in] parent unused
232   */
233   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
234   TRY
235   {
236#define DECLARE_NODE(Name_, name_)    \
237   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
238     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
239#define DECLARE_NODE_PAR(Name_, name_)
240#include "node_type.conf"
241   }
242   CATCH_DUMP_ATTR
243
244   //----------------------------------------------------------------
245
246   //! Verify if all root definition in the context have child.
247   bool CContext::hasChild(void) const
248   TRY
249   {
250      return (
251#define DECLARE_NODE(Name_, name_)    \
252   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
253#define DECLARE_NODE_PAR(Name_, name_)
254#include "node_type.conf"
255      false);
256}
257   CATCH
258
259   //----------------------------------------------------------------
260
261   void CContext::CleanTree(void)
262   TRY
263   {
264#define DECLARE_NODE(Name_, name_) C##Name_##Definition::ClearAllAttributes();
265#define DECLARE_NODE_PAR(Name_, name_)
266#include "node_type.conf"
267   }
268   CATCH
269
270   ///---------------------------------------------------------------
271
272
273   void CContext::setClientServerBuffer(vector<CField*>& fields, bool bufferForWriting)
274   TRY
275   {
276      // Estimated minimum event size for small events (20 is an arbitrary constant just for safety)
277     const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int);
278      // Ensure there is at least some room for 20 of such events in the buffers
279     size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize);
280
281#define DECLARE_NODE(Name_, name_)    \
282     if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
283#define DECLARE_NODE_PAR(Name_, name_)
284#include "node_type.conf"
285#undef DECLARE_NODE
286#undef DECLARE_NODE_PAR
287
288
289     map<CContextClient*,map<int,size_t>> dataSize ;
290     map<CContextClient*,map<int,size_t>> maxEventSize ;
291     map<CContextClient*,map<int,size_t>> attributesSize ; 
292
293     for(auto field : fields)
294     {
295       field->setContextClientDataBufferSize(dataSize, maxEventSize, bufferForWriting) ;
296       field->setContextClientAttributesBufferSize(attributesSize, maxEventSize, bufferForWriting) ;
297     }
298     
299
300     for(auto& it : attributesSize)
301     {
302       auto contextClient = it.first ;
303       auto& contextDataSize =  dataSize[contextClient] ;
304       auto& contextAttributesSize =  attributesSize[contextClient] ;
305       auto& contextMaxEventSize =  maxEventSize[contextClient] ;
306   
307       for (auto& it : contextAttributesSize)
308       {
309         auto serverRank=it.first ;
310         auto& buffer = contextAttributesSize[serverRank] ;
311         if (contextDataSize[serverRank] > buffer) buffer=contextDataSize[serverRank] ;
312         buffer *= CXios::bufferSizeFactor;
313         if (buffer < minBufferSize) buffer = minBufferSize;
314         if (buffer > CXios::maxBufferSize ) buffer = CXios::maxBufferSize;
315       }
316
317       // Leaders will have to send some control events so ensure there is some room for those in the buffers
318       if (contextClient->isServerLeader())
319         for(auto& rank : contextClient->getRanksServerLeader())
320           if (!contextAttributesSize.count(rank))
321           {
322             contextAttributesSize[rank] = minBufferSize;
323             contextMaxEventSize[rank] = minEventSize;
324           }
325     
326       contextClient->setBufferSize(contextAttributesSize, contextMaxEventSize);   
327     }
328   }
329   CATCH_DUMP_ATTR
330
331
332    /*!
333    Sets client buffers.
334    \param [in] contextClient
335    \param [in] bufferForWriting True if buffers are used for sending data for writing
336    This flag is only true for client and server-1 for communication with server-2
337  */
338  // ym obsolete to be removed
339   void CContext::setClientServerBuffer(CContextClient* contextClient, bool bufferForWriting)
340   TRY
341   {
342      // Estimated minimum event size for small events (20 is an arbitrary constant just for safety)
343     const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int);
344
345      // Ensure there is at least some room for 20 of such events in the buffers
346      size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize);
347
348#define DECLARE_NODE(Name_, name_)    \
349     if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
350#define DECLARE_NODE_PAR(Name_, name_)
351#include "node_type.conf"
352#undef DECLARE_NODE
353#undef DECLARE_NODE_PAR
354
355     // Compute the buffer sizes needed to send the attributes and data corresponding to fields
356     std::map<int, StdSize> maxEventSize;
357     std::map<int, StdSize> bufferSize = getAttributesBufferSize(maxEventSize, contextClient, bufferForWriting);
358     std::map<int, StdSize> dataBufferSize = getDataBufferSize(maxEventSize, contextClient, bufferForWriting);
359
360     std::map<int, StdSize>::iterator it, ite = dataBufferSize.end();
361     for (it = dataBufferSize.begin(); it != ite; ++it)
362       if (it->second > bufferSize[it->first]) bufferSize[it->first] = it->second;
363
364     // Apply the buffer size factor, check that we are above the minimum buffer size and below the maximum size
365     ite = bufferSize.end();
366     for (it = bufferSize.begin(); it != ite; ++it)
367     {
368       it->second *= CXios::bufferSizeFactor;
369       if (it->second < minBufferSize) it->second = minBufferSize;
370       if (it->second > CXios::maxBufferSize) it->second = CXios::maxBufferSize;
371     }
372
373     // Leaders will have to send some control events so ensure there is some room for those in the buffers
374     if (contextClient->isServerLeader())
375     {
376       const std::list<int>& ranks = contextClient->getRanksServerLeader();
377       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
378       {
379         if (!bufferSize.count(*itRank))
380         {
381           bufferSize[*itRank] = minBufferSize;
382           maxEventSize[*itRank] = minEventSize;
383         }
384       }
385     }
386     contextClient->setBufferSize(bufferSize, maxEventSize);
387   }
388   CATCH_DUMP_ATTR
389
390 /*!
391    * Compute the required buffer size to send the fields data.
392    * \param maxEventSize [in/out] the size of the bigger event for each connected server
393    * \param [in] contextClient
394    * \param [in] bufferForWriting True if buffers are used for sending data for writing
395      This flag is only true for client and server-1 for communication with server-2
396    */
397   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize,
398                                                      CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
399   TRY
400   {
401     std::map<int, StdSize> dataSize;
402
403     // Find all reference domain and axis of all active fields
404     std::vector<CFile*>& fileList = bufferForWriting ? this->enabledWriteModeFiles : this->enabledReadModeFiles;
405     size_t numEnabledFiles = fileList.size();
406     for (size_t i = 0; i < numEnabledFiles; ++i)
407     {
408       CFile* file = fileList[i];
409       if (file->getContextClient() == contextClient)
410       {
411         std::vector<CField*> enabledFields = file->getEnabledFields();
412         size_t numEnabledFields = enabledFields.size();
413         for (size_t j = 0; j < numEnabledFields; ++j)
414         {
415           // const std::vector<std::map<int, StdSize> > mapSize = enabledFields[j]->getGridDataBufferSize(contextClient);
416           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize(contextClient,bufferForWriting);
417           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
418           for (; it != itE; ++it)
419           {
420             // If dataSize[it->first] does not exist, it will be zero-initialized
421             // so we can use it safely without checking for its existance
422           if (CXios::isOptPerformance)
423               dataSize[it->first] += it->second;
424             else if (dataSize[it->first] < it->second)
425               dataSize[it->first] = it->second;
426
427           if (maxEventSize[it->first] < it->second)
428               maxEventSize[it->first] = it->second;
429           }
430         }
431       }
432     }
433     return dataSize;
434   }
435   CATCH_DUMP_ATTR
436
437/*!
438    * Compute the required buffer size to send the attributes (mostly those grid related).
439    * \param maxEventSize [in/out] the size of the bigger event for each connected server
440    * \param [in] contextClient
441    * \param [in] bufferForWriting True if buffers are used for sending data for writing
442      This flag is only true for client and server-1 for communication with server-2
443    */
444   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize,
445                                                           CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
446   TRY
447   {
448   // As calendar attributes are sent even if there are no active files or fields, maps are initialized according the size of calendar attributes
449     std::map<int, StdSize> attributesSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient);
450     maxEventSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient);
451
452     std::vector<CFile*>& fileList = this->enabledFiles;
453     size_t numEnabledFiles = fileList.size();
454     for (size_t i = 0; i < numEnabledFiles; ++i)
455     {
456//         CFile* file = this->enabledWriteModeFiles[i];
457        CFile* file = fileList[i];
458        std::vector<CField*> enabledFields = file->getEnabledFields();
459        size_t numEnabledFields = enabledFields.size();
460        for (size_t j = 0; j < numEnabledFields; ++j)
461        {
462          const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize(contextClient, bufferForWriting);
463          std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
464          for (; it != itE; ++it)
465          {
466         // If attributesSize[it->first] does not exist, it will be zero-initialized
467         // so we can use it safely without checking for its existence
468             if (attributesSize[it->first] < it->second)
469         attributesSize[it->first] = it->second;
470
471         if (maxEventSize[it->first] < it->second)
472         maxEventSize[it->first] = it->second;
473          }
474        }
475     }
476     return attributesSize;
477   }
478   CATCH_DUMP_ATTR
479
480
481
482   //! Verify whether a context is initialized
483   bool CContext::isInitialized(void)
484   TRY
485   {
486     return hasClient;
487   }
488   CATCH_DUMP_ATTR
489
490
491   void CContext::init(CServerContext* parentServerContext, MPI_Comm intraComm, int serviceType)
492   TRY
493   {
494     parentServerContext_ = parentServerContext ;
495     if (serviceType==CServicesManager::CLIENT) 
496       initClient(intraComm, serviceType) ;
497     else
498       initServer(intraComm, serviceType) ;
499    }
500    CATCH_DUMP_ATTR
501
502
503
504//! Initialize client side
505   void CContext::initClient(MPI_Comm intraComm, int serviceType)
506   TRY
507   {
508      intraComm_=intraComm ;
509      MPI_Comm_rank(intraComm_, &intraCommRank_) ;
510      MPI_Comm_size(intraComm_, &intraCommSize_) ;
511
512      serviceType_ = CServicesManager::CLIENT ;
513      if (serviceType_==CServicesManager::CLIENT)
514      {
515        hasClient=true ;
516        hasServer=false ;
517      }
518      contextId_ = getId() ;
519     
520      attached_mode=true ;
521      if (!CXios::isUsingServer()) attached_mode=false ;
522
523
524      string contextRegistryId=getId() ;
525      registryIn=new CRegistry(intraComm);
526      registryIn->setPath(contextRegistryId) ;
527     
528      int commRank ;
529      MPI_Comm_rank(intraComm_,&commRank) ;
530      if (commRank==0) registryIn->fromFile("xios_registry.bin") ;
531      registryIn->bcastRegistry() ;
532      registryOut=new CRegistry(intraComm_) ;
533      registryOut->setPath(contextRegistryId) ;
534     
535   }
536   CATCH_DUMP_ATTR
537
538   
539   void CContext::initServer(MPI_Comm intraComm, int serviceType)
540   TRY
541   {
542     hasServer=true;
543     intraComm_=intraComm ;
544     MPI_Comm_rank(intraComm_, &intraCommRank_) ;
545     MPI_Comm_size(intraComm_, &intraCommSize_) ;
546
547     serviceType_=serviceType ;
548
549     if (serviceType_==CServicesManager::GATHERER)
550     {
551       hasClient=true ;
552       hasServer=true ;
553     }
554     else if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
555     {
556       hasClient=false ;
557       hasServer=true ;
558     }
559
560     CXios::getContextsManager()->getContextId(getId(), contextId_, intraComm) ;
561     
562     registryIn=new CRegistry(intraComm);
563     registryIn->setPath(contextId_) ;
564     
565     int commRank ;
566     MPI_Comm_rank(intraComm_,&commRank) ;
567     if (commRank==0) registryIn->fromFile("xios_registry.bin") ;
568   
569     registryIn->bcastRegistry() ;
570     registryOut=new CRegistry(intraComm) ;
571     registryOut->setPath(contextId_) ;
572
573   }
574   CATCH_DUMP_ATTR
575
576
577  void CContext::createClientInterComm(MPI_Comm interCommClient, MPI_Comm interCommServer) // for servers
578  TRY
579  {
580    MPI_Comm intraCommClient ;
581    MPI_Comm_dup(intraComm_, &intraCommClient);
582    comms.push_back(intraCommClient);
583    // attached_mode=parentServerContext_->isAttachedMode() ; //ym probably inherited from source context
584    server = new CContextServer(this,intraComm_, interCommServer); // check if we need to dupl. intraComm_ ?
585    client = new CContextClient(this,intraCommClient,interCommClient);
586    client->setAssociatedServer(server) ; 
587    server->setAssociatedClient(client) ; 
588
589  }
590  CATCH_DUMP_ATTR
591
592  void CContext::createServerInterComm(void) 
593  TRY
594  {
595   
596    MPI_Comm interCommClient, interCommServer ;
597
598    if (serviceType_ == CServicesManager::CLIENT)
599    {
600
601      int commRank ;
602      MPI_Comm_rank(intraComm_,&commRank) ;
603      if (commRank==0)
604      {
605        if (attached_mode) CXios::getContextsManager()->createServerContext(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, getContextId()) ;
606        else if (CXios::usingServer2) CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId()) ;
607        else  CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId()) ;
608      }
609
610      MPI_Comm interComm ;
611     
612      if (attached_mode)
613      {
614        parentServerContext_->createIntercomm(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, getContextId(), intraComm_, 
615                                              interCommClient, interCommServer) ;
616        int type ; 
617        if (commRank==0) CXios::getServicesManager()->getServiceType(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, type) ;
618        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
619        setCurrent(getId()) ; // getCurrent/setCurrent may be supress, it can cause a lot of trouble
620      }
621      else if (CXios::usingServer2)
622      { 
623//      CXios::getContextsManager()->createServerContextIntercomm(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId(), intraComm_, interComm) ;
624        parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId(), intraComm_,
625                                              interCommClient, interCommServer) ;
626        int type ; 
627        if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultGathererId, 0, type) ;
628        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
629      }
630      else
631      {
632        //CXios::getContextsManager()->createServerContextIntercomm(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId(), intraComm_, interComm) ;
633        parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId(), intraComm_,
634                                              interCommClient, interCommServer) ;
635        int type ; 
636        if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultServerId, 0, type) ;
637        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
638      }
639
640        // intraComm client is not duplicated. In all the code we use client->intraComm for MPI
641        // in future better to replace it by intracommuncator associated to the context
642   
643      MPI_Comm intraCommClient, intraCommServer ;
644      intraCommClient=intraComm_ ;
645      MPI_Comm_dup(intraComm_, &intraCommServer) ;
646      client = new CContextClient(this, intraCommClient, interCommClient);
647      server = new CContextServer(this, intraCommServer, interCommServer);
648      client->setAssociatedServer(server) ;
649      server->setAssociatedClient(client) ;
650    }
651   
652    if (serviceType_ == CServicesManager::GATHERER)
653    {
654      int commRank ;
655      MPI_Comm_rank(intraComm_,&commRank) ;
656     
657      int nbPartitions ;
658      if (commRank==0) 
659      { 
660        CXios::getServicesManager()->getServiceNbPartitions(CXios::defaultPoolId, CXios::defaultServerId, 0, nbPartitions) ;
661        for(int i=0 ; i<nbPartitions; i++)
662          CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultServerId, i, getContextId()) ;
663      }     
664      MPI_Bcast(&nbPartitions, 1, MPI_INT, 0, intraComm_) ;
665     
666      MPI_Comm interComm ;
667      for(int i=0 ; i<nbPartitions; i++)
668      {
669        parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultServerId, i, getContextId(), intraComm_, interCommClient, interCommServer) ;
670        int type ; 
671        if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultServerId, 0, type) ;
672        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
673        primServerId_.push_back(CXios::getContextsManager()->getServerContextName(CXios::defaultPoolId, CXios::defaultServerId, i, type, getContextId())) ;
674
675        // intraComm client is not duplicated. In all the code we use client->intraComm for MPI
676        // in future better to replace it by intracommuncator associated to the context
677     
678        MPI_Comm intraCommClient, intraCommServer ;
679
680        intraCommClient=intraComm_ ;
681        MPI_Comm_dup(intraComm_, &intraCommServer) ;
682
683        CContextClient* client = new CContextClient(this, intraCommClient, interCommClient) ;
684        CContextServer* server = new CContextServer(this, intraCommServer, interCommServer) ;
685        client->setAssociatedServer(server) ;
686        server->setAssociatedClient(client) ;
687        clientPrimServer.push_back(client);
688        serverPrimServer.push_back(server); 
689
690     
691      }
692    }
693  }
694  CATCH_DUMP_ATTR
695
696   
697
698  bool CContext::eventLoop(bool enableEventsProcessing)
699  {
700    bool finished=true; 
701
702    if (client!=nullptr && !finalized) client->checkBuffers();
703   
704    for (int i = 0; i < clientPrimServer.size(); ++i)
705    {
706      if (!finalized) clientPrimServer[i]->checkBuffers();
707      if (!finalized) finished &= serverPrimServer[i]->eventLoop(enableEventsProcessing);
708    }
709
710    for (auto couplerOut : couplerOutClient_)
711      if (!finalized) couplerOut.second->checkBuffers();
712   
713    for (auto couplerIn : couplerInClient_)
714      if (!finalized) couplerIn.second->checkBuffers();
715   
716    for (auto couplerOut : couplerOutServer_)
717      if (!finalized) couplerOut.second->eventLoop(enableEventsProcessing);
718
719    for (auto couplerIn : couplerInServer_)
720      if (!finalized) couplerIn.second->eventLoop(enableEventsProcessing);
721   
722    if (server!=nullptr) if (!finalized) finished &= server->eventLoop(enableEventsProcessing);
723 
724    return finalized && finished ;
725  }
726
727  void CContext::addCouplingChanel(const std::string& fullContextId, bool out)
728  {
729     int contextLeader ;
730     
731     if (out)
732     { 
733       if (couplerOutClient_.find(fullContextId)==couplerOutClient_.end()) 
734       {
735         bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ;
736     
737         MPI_Comm interComm, interCommClient, interCommServer  ;
738         MPI_Comm intraCommClient, intraCommServer ;
739
740         if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
741
742        MPI_Comm_dup(intraComm_, &intraCommClient) ;
743        MPI_Comm_dup(intraComm_, &intraCommServer) ;
744        MPI_Comm_dup(interComm, &interCommClient) ;
745        MPI_Comm_dup(interComm, &interCommServer) ;
746        CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
747        CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
748        client->setAssociatedServer(server) ;
749        server->setAssociatedClient(client) ;
750        MPI_Comm_free(&interComm) ;
751        couplerOutClient_[fullContextId] = client ;
752        couplerOutServer_[fullContextId] = server ;
753
754/*
755      // for now, we don't now which beffer size must be used for client coupler
756      // It will be evaluated later. Fix a constant size for now...
757      // set to 10Mb for development
758       map<int,size_t> bufferSize, maxEventSize ;
759       for(int i=0;i<client->getRemoteSize();i++)
760       {
761         bufferSize[i]=10000000 ;
762         maxEventSize[i]=10000000 ;
763       }
764
765       client->setBufferSize(bufferSize, maxEventSize);   
766*/
767      }
768    }
769    else if (couplerInClient_.find(fullContextId)==couplerInClient_.end())
770    {
771      bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ;
772     
773       MPI_Comm interComm, interCommClient, interCommServer  ;
774       MPI_Comm intraCommClient, intraCommServer ;
775
776       if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
777
778       MPI_Comm_dup(intraComm_, &intraCommClient) ;
779       MPI_Comm_dup(intraComm_, &intraCommServer) ;
780       MPI_Comm_dup(interComm, &interCommServer) ;
781       MPI_Comm_dup(interComm, &interCommClient) ;
782       CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
783       CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
784       client->setAssociatedServer(server) ;
785       server->setAssociatedClient(client) ;
786       MPI_Comm_free(&interComm) ;
787
788       map<int,size_t> bufferSize, maxEventSize ;
789       for(int i=0;i<client->getRemoteSize();i++)
790       {
791         bufferSize[i]=10000000 ;
792         maxEventSize[i]=10000000 ;
793       }
794
795       client->setBufferSize(bufferSize, maxEventSize);   
796       couplerInClient_[fullContextId] = client ;
797       couplerInServer_[fullContextId] = server ;       
798    }
799  }
800 
801  void CContext::globalEventLoop(void)
802  {
803    CXios::getDaemonsManager()->eventLoop() ;
804    setCurrent(getId()) ;
805  }
806
807
808   void CContext::finalize(void)
809   TRY
810   {
811      registryOut->hierarchicalGatherRegistry() ;
812      if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
813
814      if (serviceType_==CServicesManager::CLIENT)
815      {
816//ym        doPreTimestepOperationsForEnabledReadModeFiles(); // For now we only use server level 1 to read data
817
818        triggerLateFields() ;
819
820        // inform couplerIn that I am finished
821        for(auto& couplerInClient : couplerInClient_) sendCouplerInContextFinalized(couplerInClient.second) ;
822
823        // wait until received message from couplerOut that they have finished
824        bool couplersInFinalized ;
825        do
826        {
827          couplersInFinalized=true ;
828          for(auto& couplerOutClient : couplerOutClient_) couplersInFinalized &= isCouplerInContextFinalized(couplerOutClient.second) ; 
829          globalEventLoop() ;
830        } while (!couplersInFinalized) ;
831
832        info(100)<<"DEBUG: context "<<getId()<<" Send client finalize"<<endl ;
833        client->finalize();
834        info(100)<<"DEBUG: context "<<getId()<<" Client finalize sent"<<endl ;
835        while (client->havePendingRequests()) client->checkBuffers();
836        info(100)<<"DEBUG: context "<<getId()<<" no pending request ok"<<endl ;
837        bool notifiedFinalized=false ;
838        do
839        {
840          notifiedFinalized=client->isNotifiedFinalized() ;
841        } while (!notifiedFinalized) ;
842        client->releaseBuffers();
843        info(100)<<"DEBUG: context "<<getId()<<" release client ok"<<endl ;
844      }
845      else if (serviceType_==CServicesManager::GATHERER)
846      {
847         for (int i = 0; i < clientPrimServer.size(); ++i)
848         {
849           clientPrimServer[i]->finalize();
850           bool bufferReleased;
851           do
852           {
853             clientPrimServer[i]->checkBuffers();
854             bufferReleased = !clientPrimServer[i]->havePendingRequests();
855           } while (!bufferReleased);
856           
857           bool notifiedFinalized=false ;
858           do
859           {
860             notifiedFinalized=clientPrimServer[i]->isNotifiedFinalized() ;
861           } while (!notifiedFinalized) ;
862           clientPrimServer[i]->releaseBuffers();
863         }
864         closeAllFile();
865
866      }
867      else if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
868      {
869        closeAllFile();
870      }
871
872      freeComms() ;
873       
874      parentServerContext_->freeComm() ;
875      finalized = true;
876      info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl;
877   }
878   CATCH_DUMP_ATTR
879
880   //! Free internally allocated communicators
881   void CContext::freeComms(void)
882   TRY
883   {
884     for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
885       MPI_Comm_free(&(*it));
886     comms.clear();
887   }
888   CATCH_DUMP_ATTR
889
890   //! Deallocate buffers allocated by clientContexts
891   void CContext::releaseClientBuffers(void)
892   TRY
893   {
894     client->releaseBuffers();
895     for (int i = 0; i < clientPrimServer.size(); ++i)
896       clientPrimServer[i]->releaseBuffers();
897   }
898   CATCH_DUMP_ATTR
899
900   
901   /*!
902   \brief Close all the context defintion and do processing data
903      After everything is well defined on client side, they will be processed and sent to server
904   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
905   all necessary information to server, from which each server can build its own database.
906   Because the role of server is to write out field data on a specific netcdf file,
907   the only information that it needs is the enabled files
908   and the active fields (fields will be written onto active files)
909   */
910  void CContext::closeDefinition(void)
911   TRY
912   {
913     CTimer::get("Context : close definition").resume() ;
914     
915     // create intercommunicator with servers.
916     // not sure it is the good place to be called here
917     createServerInterComm() ;
918
919
920     // After xml is parsed, there are some more works with post processing
921//     postProcessing();
922
923   
924    // Make sure the calendar was correctly created
925    if (serviceType_!=CServicesManager::CLIENT) CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
926    if (!calendar)
927      ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
928    else if (calendar->getTimeStep() == NoneDu)
929      ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
930    // Calendar first update to set the current date equals to the start date
931    calendar->update(0);
932
933    // Résolution des héritages descendants (càd des héritages de groupes)
934    // pour chacun des contextes.
935    solveDescInheritance(true);
936 
937    // Solve inheritance for field to know if enabled or not.
938    for (auto field : CField::getAll()) field->solveRefInheritance();
939
940    // Check if some axis, domains or grids are eligible to for compressed indexed output.
941    // Warning: This must be done after solving the inheritance and before the rest of post-processing
942    // --> later ????    checkAxisDomainsGridsEligibilityForCompressedOutput();     
943
944      // Check if some automatic time series should be generated
945      // Warning: This must be done after solving the inheritance and before the rest of post-processing     
946
947    // The timeseries should only be prepared in client
948    prepareTimeseries();
949
950    //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
951    findEnabledFiles();
952    findEnabledWriteModeFiles();
953    findEnabledReadModeFiles();
954    findEnabledCouplerIn();
955    findEnabledCouplerOut();
956    createCouplerInterCommunicator() ;
957
958    // Find all enabled fields of each file     
959    vector<CField*>&& fileOutField = findAllEnabledFieldsInFileOut(this->enabledWriteModeFiles);
960    vector<CField*>&& fileInField = findAllEnabledFieldsInFileIn(this->enabledReadModeFiles);
961    vector<CField*>&& couplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut);
962    vector<CField*>&& couplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn);
963    findFieldsWithReadAccess();
964    vector<CField*>& fieldWithReadAccess = fieldsWithReadAccess_ ;
965    vector<CField*> fieldModelIn ; // fields potentially from model
966     
967    // define if files are on clientSied or serverSide
968    if (serviceType_==CServicesManager::CLIENT)
969    {
970      for (auto& file : enabledWriteModeFiles) file->setClientSide() ;
971      for (auto& file : enabledReadModeFiles) file->setClientSide() ;
972    }
973    else
974    {
975      for (auto& file : enabledWriteModeFiles) file->setServerSide() ;
976      for (auto& file : enabledReadModeFiles) file->setServerSide() ;
977    }
978
979   
980    for (auto& field : couplerInField)
981    {
982      field->unsetGridCompleted() ;
983    }
984// find all field potentially at workflow end
985    vector<CField*> endWorkflowFields ;
986    endWorkflowFields.reserve(fileOutField.size()+couplerOutField.size()+fieldWithReadAccess.size()) ;
987    endWorkflowFields.insert(endWorkflowFields.end(),fileOutField.begin(), fileOutField.end()) ;
988    endWorkflowFields.insert(endWorkflowFields.end(),couplerOutField.begin(), couplerOutField.end()) ;
989    endWorkflowFields.insert(endWorkflowFields.end(),fieldWithReadAccess.begin(), fieldWithReadAccess.end()) ;
990
991    bool workflowGraphIsCompleted ;
992
993    bool first=true ;
994    do
995    {
996      workflowGraphIsCompleted=true; 
997      for(auto endWorkflowField : endWorkflowFields) 
998      {
999        workflowGraphIsCompleted &= endWorkflowField->buildWorkflowGraph(garbageCollector) ;
1000      }
1001
1002      for(auto couplerIn : enabledCouplerIn) couplerIn->assignContext() ;
1003      for(auto field : couplerInField) field->makeGridAliasForCoupling();
1004      for(auto field : couplerInField) this->sendCouplerInReady(field->getContextClient()) ;
1005   
1006
1007      // assign context to coupler out and related fields
1008      for(auto couplerOut : enabledCouplerOut) couplerOut->assignContext() ;
1009      // for now supose that all coupling out endpoint are succesfull. The difficultie is client/server buffer evaluation
1010      for(auto field : couplerOutField) 
1011      {
1012        // connect to couplerOut -> to do
1013      }
1014      if (first) setClientServerBuffer(couplerOutField, true) ; // set buffer context --> to check
1015   
1016      bool couplersReady ;
1017      do 
1018      {
1019        couplersReady=true ;
1020        for(auto field : couplerOutField)
1021        {
1022          bool ready = isCouplerInReady(field->getContextClient()) ; 
1023          if (ready) field->sendFieldToCouplerOut() ;
1024          couplersReady &= ready ;
1025        }
1026        if (!couplersReady) this->eventLoop() ;
1027      } while (!couplersReady) ;
1028
1029      first=false ;
1030      this->eventLoop() ;
1031    } while (!workflowGraphIsCompleted) ;
1032
1033    for( auto field : couplerInField) couplerInFields_.push_back(field) ;
1034
1035    // get all field coming potentially from model
1036    for (auto field : CField::getAll() ) if (field->getModelIn()) fieldModelIn.push_back(field) ;
1037
1038    // Distribute files between secondary servers according to the data size => assign a context to a file and then to fields
1039    if (serviceType_==CServicesManager::GATHERER) distributeFiles(this->enabledWriteModeFiles);
1040    else if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledWriteModeFiles) file->setContextClient(client) ;
1041
1042    // client side, assign context for file reading
1043    if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ;
1044   
1045    // server side, assign context where to send file data read
1046    if (serviceType_==CServicesManager::CServicesManager::GATHERER || serviceType_==CServicesManager::IO_SERVER) 
1047      for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ;
1048   
1049    // workflow endpoint => sent to IO/SERVER
1050    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER)
1051    {
1052      for(auto field : fileOutField) 
1053      {
1054        field->connectToFileServer(garbageCollector) ; // connect the field to server filter
1055      }
1056      setClientServerBuffer(fileOutField, true) ; // set buffer context --> to review
1057      for(auto field : fileOutField) field->sendFieldToFileServer() ;
1058    }
1059
1060    // workflow endpoint => write to file
1061    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
1062    {
1063      for(auto field : fileOutField) 
1064      {
1065        field->connectToFileWriter(garbageCollector) ; // connect the field to server filter
1066      }
1067    }
1068   
1069    // workflow endpoint => Send data from server to client
1070    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER)
1071    {
1072      for(auto field : fileInField) 
1073      {
1074        field->connectToServerToClient(garbageCollector) ;
1075      }
1076    }
1077
1078    // workflow endpoint => sent to model on client side
1079    if (serviceType_==CServicesManager::CLIENT)
1080    {
1081      for(auto field : fieldWithReadAccess) field->connectToModelOutput(garbageCollector) ;
1082    }
1083
1084
1085    // workflow startpoint => data from model
1086    if (serviceType_==CServicesManager::CLIENT)
1087    {
1088      for(auto field : fieldModelIn) 
1089      {
1090        field->connectToModelInput(garbageCollector) ; // connect the field to server filter
1091        // grid index will be computed on the fly
1092      }
1093    }
1094   
1095    // workflow startpoint => data from client on server side
1096    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER || serviceType_==CServicesManager::OUT_SERVER)
1097    {
1098      for(auto field : fieldModelIn) 
1099      {
1100        field->connectToClientInput(garbageCollector) ; // connect the field to server filter
1101      }
1102    }
1103
1104   
1105    for(auto field : couplerInField) 
1106    {
1107      field->connectToCouplerIn(garbageCollector) ; // connect the field to server filter
1108    }
1109   
1110   
1111    for(auto field : couplerOutField) 
1112    {
1113      field->connectToCouplerOut(garbageCollector) ; // for now the same kind of filter that for file server
1114    }
1115
1116     // workflow startpoint => data from server on client side
1117    if (serviceType_==CServicesManager::CLIENT)
1118    {
1119      for(auto field : fileInField) 
1120      {
1121        field->connectToServerInput(garbageCollector) ; // connect the field to server filter
1122        field->sendFieldToInputFileServer() ;
1123        fileInFields_.push_back(field) ;
1124      }
1125    }
1126
1127    // workflow startpoint => data read from file on server side
1128    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER)
1129    {
1130      for(auto field : fileInField) 
1131      {
1132        field->connectToFileReader(garbageCollector) ;
1133      }
1134    }
1135   
1136    // construct slave server list
1137    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 
1138    {
1139      for(auto field : fileOutField) slaveServers_.insert(field->getContextClient()) ; 
1140      for(auto field : fileInField)  slaveServers_.insert(field->getContextClient()) ; 
1141    }
1142
1143    for(auto& slaveServer : slaveServers_) sendCloseDefinition(slaveServer) ;
1144
1145    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 
1146    {
1147      createFileHeader();
1148    }
1149
1150    if (serviceType_==CServicesManager::CLIENT) startPrefetchingOfEnabledReadModeFiles();
1151   
1152    // send signal to couplerIn context that definition phasis is done
1153
1154    for(auto& couplerInClient : couplerInClient_) sendCouplerInCloseDefinition(couplerInClient.second) ;
1155
1156    // wait until all couplerIn signal that closeDefition is done.
1157    bool ok;
1158    do
1159    {
1160      ok = true ;
1161      for(auto& couplerOutClient : couplerOutClient_) ok &= isCouplerInCloseDefinition(couplerOutClient.second) ;
1162      this->eventLoop() ; 
1163    } while (!ok) ;
1164
1165     CTimer::get("Context : close definition").suspend() ;
1166  }
1167  CATCH_DUMP_ATTR
1168
1169
1170  vector<CField*> CContext::findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles)
1171   TRY
1172   {
1173     vector<CField*> fields ;
1174     for(auto file : activeFiles)
1175     {
1176        const vector<CField*>&& fieldList=file->getEnabledFields() ;
1177        for(auto field : fieldList) field->setFileOut(file) ;
1178        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1179     }
1180     return fields ;
1181   }
1182   CATCH_DUMP_ATTR
1183
1184   vector<CField*> CContext::findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles)
1185   TRY
1186   {
1187     vector<CField*> fields ;
1188     for(auto file : activeFiles)
1189     {
1190        const vector<CField*>&& fieldList=file->getEnabledFields() ;
1191        for(auto field : fieldList) field->setFileIn(file) ;
1192        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1193     }
1194     return fields ;
1195   }
1196   CATCH_DUMP_ATTR
1197
1198   vector<CField*> CContext::findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut)
1199   TRY
1200   {
1201     vector<CField*> fields ;
1202     for (auto couplerOut :activeCouplerOut)
1203     {
1204        const vector<CField*>&& fieldList=couplerOut->getEnabledFields() ;
1205        for(auto field : fieldList) field->setCouplerOut(couplerOut) ;
1206        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1207     }
1208     return fields ;
1209   }
1210   CATCH_DUMP_ATTR
1211
1212   vector<CField*> CContext::findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn)
1213   TRY
1214   {
1215     vector<CField*> fields ;
1216     for (auto couplerIn :activeCouplerIn)
1217     {
1218        const vector<CField*>&& fieldList=couplerIn->getEnabledFields() ;
1219        for(auto field : fieldList) field->setCouplerIn(couplerIn) ;
1220        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1221     }
1222     return fields ;
1223   }
1224   CATCH_DUMP_ATTR
1225
1226 /*!
1227  * Send context attribute and calendar to file server, it must be done once by context file server
1228  * \param[in] client : context client to send   
1229  */ 
1230  void CContext::sendContextToFileServer(CContextClient* client)
1231  {
1232    if (sendToFileServer_done_.count(client)!=0) return ;
1233    else sendToFileServer_done_.insert(client) ;
1234   
1235    this->sendAllAttributesToServer(client); // Send all attributes of current context to server
1236    CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(client); // Send all attributes of current cale
1237  }
1238
1239 
1240   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
1241   TRY
1242   {
1243      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
1244        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
1245   }
1246   CATCH_DUMP_ATTR
1247
1248   void CContext::sendGridComponentEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
1249   TRY
1250   {
1251     int size = activeFiles.size();
1252     for (int i = 0; i < size; ++i)
1253     {       
1254       activeFiles[i]->sendGridComponentOfEnabledFields();
1255     }
1256   }
1257   CATCH_DUMP_ATTR
1258
1259   /*!
1260      Send active (enabled) fields in file from a client to others
1261      \param [in] activeFiles files contains enabled fields to send
1262   */
1263   void CContext::sendGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
1264   TRY
1265   {
1266     int size = activeFiles.size();
1267     for (int i = 0; i < size; ++i)
1268     {       
1269       activeFiles[i]->sendGridOfEnabledFields();
1270     }
1271   }
1272   CATCH_DUMP_ATTR
1273
1274   void CContext::checkGridEnabledFields()
1275   TRY
1276   {
1277     int size = enabledFiles.size();
1278     for (int i = 0; i < size; ++i)
1279     {
1280       enabledFiles[i]->checkGridOfEnabledFields();       
1281     }
1282
1283     size = enabledCouplerOut.size();
1284     for (int i = 0; i < size; ++i)
1285     {
1286       enabledCouplerOut[i]->checkGridOfEnabledFields();       
1287     }
1288   }
1289   CATCH_DUMP_ATTR
1290
1291   /*!
1292      Check grid of active (enabled) fields in file
1293      \param [in] activeFiles files contains enabled fields whose grid needs checking
1294   */
1295   void CContext::checkGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
1296   TRY
1297   {
1298     int size = activeFiles.size();
1299     for (int i = 0; i < size; ++i)
1300     {
1301       activeFiles[i]->checkGridOfEnabledFields();       
1302     }
1303   }
1304   CATCH_DUMP_ATTR
1305
1306    /*!
1307      Go up the hierachical tree via field_ref and do check of attributes of fields
1308      This can be done in a client then all computed information will be sent from this client to others
1309      \param [in] sendToServer Flag to indicate whether calculated information will be sent
1310   */
1311   void CContext::solveOnlyRefOfEnabledFields(void)
1312   TRY
1313   {
1314     int size = this->enabledFiles.size();
1315     for (int i = 0; i < size; ++i)
1316     {
1317       this->enabledFiles[i]->solveOnlyRefOfEnabledFields();
1318     }
1319
1320     for (int i = 0; i < size; ++i)
1321     {
1322       this->enabledFiles[i]->generateNewTransformationGridDest();
1323     }
1324
1325     size = this->enabledCouplerOut.size();
1326     for (int i = 0; i < size; ++i)
1327     {
1328       this->enabledCouplerOut[i]->solveOnlyRefOfEnabledFields();
1329     }
1330
1331     for (int i = 0; i < size; ++i)
1332     {
1333       this->enabledCouplerOut[i]->generateNewTransformationGridDest();
1334     }
1335   }
1336   CATCH_DUMP_ATTR
1337
1338    /*!
1339      Go up the hierachical tree via field_ref and do check of attributes of fields.
1340      The transformation can be done in this step.
1341      All computed information will be sent from this client to others.
1342      \param [in] sendToServer Flag to indicate whether calculated information will be sent
1343   */
1344   void CContext::solveAllRefOfEnabledFieldsAndTransform(void)
1345   TRY
1346   {
1347     int size = this->enabledFiles.size();
1348     for (int i = 0; i < size; ++i)
1349     {
1350       this->enabledFiles[i]->solveAllRefOfEnabledFieldsAndTransform();
1351     }
1352
1353     size = this->enabledCouplerOut.size();
1354     for (int i = 0; i < size; ++i)
1355     {
1356       this->enabledCouplerOut[i]->solveAllRefOfEnabledFieldsAndTransform();
1357     }
1358
1359   }
1360   CATCH_DUMP_ATTR
1361
1362   void CContext::buildFilterGraphOfEnabledFields()
1363   TRY
1364   {
1365     int size = this->enabledFiles.size();
1366     for (int i = 0; i < size; ++i)
1367     {
1368       this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);
1369     }
1370
1371     size = this->enabledCouplerOut.size();
1372     for (int i = 0; i < size; ++i)
1373     {
1374       this->enabledCouplerOut[i]->buildFilterGraphOfEnabledFields(garbageCollector);
1375     }
1376   }
1377   CATCH_DUMP_ATTR
1378
1379   void CContext::postProcessFilterGraph()
1380   TRY
1381   {
1382     int size = enabledFiles.size();
1383     for (int i = 0; i < size; ++i)
1384     {
1385        enabledFiles[i]->postProcessFilterGraph();
1386     }
1387   }
1388   CATCH_DUMP_ATTR
1389
1390   void CContext::startPrefetchingOfEnabledReadModeFiles()
1391   TRY
1392   {
1393     int size = enabledReadModeFiles.size();
1394     for (int i = 0; i < size; ++i)
1395     {
1396        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
1397     }
1398   }
1399   CATCH_DUMP_ATTR
1400
1401   void CContext::doPreTimestepOperationsForEnabledReadModeFiles()
1402   TRY
1403   {
1404     int size = enabledReadModeFiles.size();
1405     for (int i = 0; i < size; ++i)
1406     {
1407        enabledReadModeFiles[i]->doPreTimestepOperationsForEnabledReadModeFields();
1408     }
1409   }
1410   CATCH_DUMP_ATTR
1411
1412   void CContext::doPostTimestepOperationsForEnabledReadModeFiles()
1413   TRY
1414   {
1415     int size = enabledReadModeFiles.size();
1416     for (int i = 0; i < size; ++i)
1417     {
1418        enabledReadModeFiles[i]->doPostTimestepOperationsForEnabledReadModeFields();
1419     }
1420   }
1421   CATCH_DUMP_ATTR
1422
1423  void CContext::findFieldsWithReadAccess(void)
1424  TRY
1425  {
1426    fieldsWithReadAccess_.clear();
1427    const vector<CField*> allFields = CField::getAll();
1428    for (size_t i = 0; i < allFields.size(); ++i)
1429    {
1430      CField* field = allFields[i];
1431      if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
1432      {
1433        fieldsWithReadAccess_.push_back(field);
1434        field->setModelOut() ;
1435      }
1436    }
1437  }
1438  CATCH_DUMP_ATTR
1439
1440  void CContext::solveAllRefOfFieldsWithReadAccess()
1441  TRY
1442  {
1443    for (size_t i = 0; i < fieldsWithReadAccess_.size(); ++i)
1444      fieldsWithReadAccess_[i]->solveAllReferenceEnabledField(false);
1445  }
1446  CATCH_DUMP_ATTR
1447
1448  void CContext::buildFilterGraphOfFieldsWithReadAccess()
1449  TRY
1450  {
1451    for (size_t i = 0; i < fieldsWithReadAccess_.size(); ++i)
1452      fieldsWithReadAccess_[i]->buildFilterGraph(garbageCollector, true);
1453  }
1454  CATCH_DUMP_ATTR
1455
1456   void CContext::solveAllInheritance(bool apply)
1457   TRY
1458   {
1459     // Résolution des héritages descendants (càd des héritages de groupes)
1460     // pour chacun des contextes.
1461      solveDescInheritance(apply);
1462
1463     // Résolution des héritages par référence au niveau des fichiers.
1464      const vector<CFile*> allFiles=CFile::getAll();
1465      const vector<CCouplerIn*> allCouplerIn=CCouplerIn::getAll();
1466      const vector<CCouplerOut*> allCouplerOut=CCouplerOut::getAll();
1467      const vector<CGrid*> allGrids= CGrid::getAll();
1468
1469      if (serviceType_==CServicesManager::CLIENT)
1470      {
1471        for (unsigned int i = 0; i < allFiles.size(); i++)
1472          allFiles[i]->solveFieldRefInheritance(apply);
1473
1474        for (unsigned int i = 0; i < allCouplerIn.size(); i++)
1475          allCouplerIn[i]->solveFieldRefInheritance(apply);
1476
1477        for (unsigned int i = 0; i < allCouplerOut.size(); i++)
1478          allCouplerOut[i]->solveFieldRefInheritance(apply);
1479      }
1480
1481      unsigned int vecSize = allGrids.size();
1482      unsigned int i = 0;
1483      for (i = 0; i < vecSize; ++i)
1484        allGrids[i]->solveElementsRefInheritance(apply);
1485
1486   }
1487  CATCH_DUMP_ATTR
1488
1489   void CContext::findEnabledFiles(void)
1490   TRY
1491   {
1492      const std::vector<CFile*> allFiles = CFile::getAll();
1493      const CDate& initDate = calendar->getInitDate();
1494
1495      for (unsigned int i = 0; i < allFiles.size(); i++)
1496         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
1497         {
1498            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
1499            {
1500              if (allFiles[i]->output_freq.isEmpty())
1501              {
1502                 ERROR("CContext::findEnabledFiles()",
1503                     << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1504                     <<" \".")
1505              }
1506              if ((initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1507              {
1508                error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1509                    << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1510                    <<"\" is less than the time step. File will not be written."<<endl;
1511              }
1512              else
1513               enabledFiles.push_back(allFiles[i]);
1514            }
1515         }
1516         else
1517         {
1518           if (allFiles[i]->output_freq.isEmpty())
1519           {
1520              ERROR("CContext::findEnabledFiles()",
1521                  << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1522                  <<" \".")
1523           }
1524           if ( (initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1525           {
1526             error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1527                 << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1528                 <<"\" is less than the time step. File will not be written."<<endl;
1529           }
1530           else
1531             enabledFiles.push_back(allFiles[i]); // otherwise true by default
1532         }
1533
1534      if (enabledFiles.size() == 0)
1535         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
1536               << getId() << "\" !");
1537
1538   }
1539   CATCH_DUMP_ATTR
1540
1541   void CContext::findEnabledCouplerIn(void)
1542   TRY
1543   {
1544      const std::vector<CCouplerIn*> allCouplerIn = CCouplerIn::getAll();
1545      bool enabled ;
1546      for (size_t i = 0; i < allCouplerIn.size(); i++)
1547      {
1548        if (allCouplerIn[i]->enabled.isEmpty()) enabled=true ;
1549        else enabled=allCouplerIn[i]->enabled ;
1550        if (enabled) enabledCouplerIn.push_back(allCouplerIn[i]) ;
1551      }
1552   }
1553   CATCH_DUMP_ATTR
1554
1555   void CContext::findEnabledCouplerOut(void)
1556   TRY
1557   {
1558      const std::vector<CCouplerOut*> allCouplerOut = CCouplerOut::getAll();
1559      bool enabled ;
1560      for (size_t i = 0; i < allCouplerOut.size(); i++)
1561      {
1562        if (allCouplerOut[i]->enabled.isEmpty()) enabled=true ;
1563        else enabled=allCouplerOut[i]->enabled ;
1564        if (enabled) enabledCouplerOut.push_back(allCouplerOut[i]) ;
1565      }
1566   }
1567   CATCH_DUMP_ATTR
1568
1569
1570
1571
1572   void CContext::distributeFiles(const vector<CFile*>& files)
1573   TRY
1574   {
1575     bool distFileMemory=false ;
1576     distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory);
1577
1578     if (distFileMemory) distributeFileOverMemoryBandwith(files) ;
1579     else distributeFileOverBandwith(files) ;
1580   }
1581   CATCH_DUMP_ATTR
1582
1583   void CContext::distributeFileOverBandwith(const vector<CFile*>& files)
1584   TRY
1585   {
1586     double eps=std::numeric_limits<double>::epsilon()*10 ;
1587     
1588     std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out);
1589     int nbPools = clientPrimServer.size();
1590
1591     // (1) Find all enabled files in write mode
1592     // for (int i = 0; i < this->enabledFiles.size(); ++i)
1593     // {
1594     //   if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1595     //    enabledWriteModeFiles.push_back(enabledFiles[i]);
1596     // }
1597
1598     // (2) Estimate the data volume for each file
1599     int size = files.size();
1600     std::vector<std::pair<double, CFile*> > dataSizeMap;
1601     double dataPerPool = 0;
1602     int nfield=0 ;
1603     ofs<<size<<endl ;
1604     for (size_t i = 0; i < size; ++i)
1605     {
1606       CFile* file = files[i];
1607       ofs<<file->getId()<<endl ;
1608       StdSize dataSize=0;
1609       std::vector<CField*> enabledFields = file->getEnabledFields();
1610       size_t numEnabledFields = enabledFields.size();
1611       ofs<<numEnabledFields<<endl ;
1612       for (size_t j = 0; j < numEnabledFields; ++j)
1613       {
1614         dataSize += enabledFields[j]->getGlobalWrittenSize() ;
1615         ofs<<enabledFields[j]->getGrid()->getId()<<endl ;
1616         ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ;
1617       }
1618       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1619       double dataSizeSec= dataSize/ outFreqSec;
1620       ofs<<dataSizeSec<<endl ;
1621       nfield++ ;
1622// add epsilon*nField to dataSizeSec in order to  preserve reproductive ordering when sorting
1623       dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file));
1624       dataPerPool += dataSizeSec;
1625     }
1626     dataPerPool /= nbPools;
1627     std::sort(dataSizeMap.begin(), dataSizeMap.end());
1628
1629     // (3) Assign contextClient to each enabled file
1630
1631     std::multimap<double,int> poolDataSize ;
1632// multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11
1633
1634     int j;
1635     double dataSize ;
1636     for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ; 
1637             
1638     for (int i = dataSizeMap.size()-1; i >= 0; --i)
1639     {
1640       dataSize=(*poolDataSize.begin()).first ;
1641       j=(*poolDataSize.begin()).second ;
1642       dataSizeMap[i].second->setContextClient(clientPrimServer[j]);
1643       dataSize+=dataSizeMap[i].first;
1644       poolDataSize.erase(poolDataSize.begin()) ;
1645       poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 
1646     }
1647
1648     for (std::multimap<double,int>:: iterator it=poolDataSize.begin() ; it!=poolDataSize.end(); ++it) info(30)<<"Load Balancing for servers (perfect=1) : "<<it->second<<" :  ratio "<<it->first*1./dataPerPool<<endl ;
1649   }
1650   CATCH_DUMP_ATTR
1651
1652   void CContext::distributeFileOverMemoryBandwith(const vector<CFile*>& filesList)
1653   TRY
1654   {
1655     int nbPools = clientPrimServer.size();
1656     double ratio=0.5 ;
1657     ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio);
1658
1659     int nFiles = filesList.size();
1660     vector<SDistFile> files(nFiles);
1661     vector<SDistGrid> grids;
1662     map<string,int> gridMap ;
1663     string gridId; 
1664     int gridIndex=0 ;
1665
1666     for (size_t i = 0; i < nFiles; ++i)
1667     {
1668       StdSize dataSize=0;
1669       CFile* file = filesList[i];
1670       std::vector<CField*> enabledFields = file->getEnabledFields();
1671       size_t numEnabledFields = enabledFields.size();
1672
1673       files[i].id_=file->getId() ;
1674       files[i].nbGrids_=numEnabledFields;
1675       files[i].assignedGrid_ = new int[files[i].nbGrids_] ;
1676         
1677       for (size_t j = 0; j < numEnabledFields; ++j)
1678       {
1679         gridId=enabledFields[j]->getGrid()->getId() ;
1680         if (gridMap.find(gridId)==gridMap.end())
1681         {
1682            gridMap[gridId]=gridIndex  ;
1683            SDistGrid newGrid; 
1684            grids.push_back(newGrid) ;
1685            gridIndex++ ;
1686         }
1687         files[i].assignedGrid_[j]=gridMap[gridId] ;
1688         grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ;
1689         dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull
1690       }
1691       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1692       files[i].bandwith_= dataSize/ outFreqSec ;
1693     }
1694
1695     double bandwith=0 ;
1696     double memory=0 ;
1697   
1698     for(int i=0; i<nFiles; i++)  bandwith+=files[i].bandwith_ ;
1699     for(int i=0; i<nFiles; i++)  files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ;
1700
1701     for(int i=0; i<grids.size(); i++)  memory+=grids[i].size_ ;
1702     for(int i=0; i<grids.size(); i++)  grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ;
1703       
1704     distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ;
1705
1706     vector<double> memorySize(nbPools,0.) ;
1707     vector< set<int> > serverGrids(nbPools) ;
1708     vector<double> bandwithSize(nbPools,0.) ;
1709       
1710     for (size_t i = 0; i < nFiles; ++i)
1711     {
1712       bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ;
1713       for(int j=0 ; j<files[i].nbGrids_;j++)
1714       {
1715         if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end())
1716         {
1717           memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio);
1718           serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ;
1719         }
1720       }
1721       filesList[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ;
1722       delete [] files[i].assignedGrid_ ;
1723     }
1724
1725     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned file bandwith "<<bandwithSize[i]*86400.*4./1024/1024.<<" Mb / days"<<endl ;
1726     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ;
1727
1728   }
1729   CATCH_DUMP_ATTR
1730
1731   /*!
1732      Find all files in write mode
1733   */
1734   void CContext::findEnabledWriteModeFiles(void)
1735   TRY
1736   {
1737     int size = this->enabledFiles.size();
1738     for (int i = 0; i < size; ++i)
1739     {
1740       if (enabledFiles[i]->mode.isEmpty() || 
1741          (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1742        enabledWriteModeFiles.push_back(enabledFiles[i]);
1743     }
1744   }
1745   CATCH_DUMP_ATTR
1746
1747   /*!
1748      Find all files in read mode
1749   */
1750   void CContext::findEnabledReadModeFiles(void)
1751   TRY
1752   {
1753     int size = this->enabledFiles.size();
1754     for (int i = 0; i < size; ++i)
1755     {
1756       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
1757        enabledReadModeFiles.push_back(enabledFiles[i]);
1758     }
1759   }
1760   CATCH_DUMP_ATTR
1761
1762   void CContext::closeAllFile(void)
1763   TRY
1764   {
1765     std::vector<CFile*>::const_iterator
1766            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
1767
1768     for (; it != end; it++)
1769     {
1770       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
1771       (*it)->close();
1772     }
1773   }
1774   CATCH_DUMP_ATTR
1775
1776   /*!
1777   \brief Dispatch event received from client
1778      Whenever a message is received in buffer of server, it will be processed depending on
1779   its event type. A new event type should be added in the switch list to make sure
1780   it processed on server side.
1781   \param [in] event: Received message
1782   */
1783   bool CContext::dispatchEvent(CEventServer& event)
1784   TRY
1785   {
1786
1787      if (SuperClass::dispatchEvent(event)) return true;
1788      else
1789      {
1790        switch(event.type)
1791        {
1792           case EVENT_ID_CLOSE_DEFINITION :
1793             recvCloseDefinition(event);
1794             return true;
1795             break;
1796           case EVENT_ID_UPDATE_CALENDAR:
1797             recvUpdateCalendar(event);
1798             return true;
1799             break;
1800           case EVENT_ID_CREATE_FILE_HEADER :
1801             recvCreateFileHeader(event);
1802             return true;
1803             break;
1804           case EVENT_ID_SEND_REGISTRY:
1805             recvRegistry(event);
1806             return true;
1807             break;
1808           case EVENT_ID_COUPLER_IN_READY:
1809             recvCouplerInReady(event);
1810             return true;
1811             break;
1812           case EVENT_ID_COUPLER_IN_CLOSE_DEFINITION:
1813             recvCouplerInCloseDefinition(event);
1814             return true;
1815             break;
1816           case EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED:
1817             recvCouplerInContextFinalized(event);
1818             return true;
1819             break; 
1820           default :
1821             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
1822                    <<"Unknown Event");
1823           return false;
1824         }
1825      }
1826   }
1827   CATCH
1828
1829   //! Client side: Send a message to server to make it close
1830   // ym obsolete
1831   void CContext::sendCloseDefinition(void)
1832   TRY
1833   {
1834    int nbSrvPools ;
1835    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
1836    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
1837    else nbSrvPools = 0 ;
1838    CContextClient* contextClientTmp ;
1839
1840    for (int i = 0; i < nbSrvPools; ++i)
1841     {
1842       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
1843       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
1844       CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
1845       if (contextClientTmp->isServerLeader())
1846       {
1847         CMessage msg;
1848         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1849         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1850           event.push(*itRank,1,msg);
1851         contextClientTmp->sendEvent(event);
1852       }
1853       else contextClientTmp->sendEvent(event);
1854     }
1855   }
1856   CATCH_DUMP_ATTR
1857   
1858   //  ! Client side: Send a message to server to make it close
1859   void CContext::sendCloseDefinition(CContextClient* client)
1860   TRY
1861   {
1862      if (sendCloseDefinition_done_.count(client)!=0) return ;
1863      else sendCloseDefinition_done_.insert(client) ;
1864
1865      CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
1866      if (client->isServerLeader())
1867      {
1868        CMessage msg;
1869        for(auto rank : client->getRanksServerLeader()) event.push(rank,1,msg);
1870        client->sendEvent(event);
1871      }
1872     else client->sendEvent(event);
1873   }
1874   CATCH_DUMP_ATTR
1875
1876   //! Server side: Receive a message of client announcing a context close
1877   void CContext::recvCloseDefinition(CEventServer& event)
1878   TRY
1879   {
1880      CBufferIn* buffer=event.subEvents.begin()->buffer;
1881      getCurrent()->closeDefinition();
1882   }
1883   CATCH
1884
1885   //! Client side: Send a message to update calendar in each time step
1886   void CContext::sendUpdateCalendar(int step)
1887   TRY
1888   {
1889     CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
1890     for(auto client : slaveServers_) 
1891     {
1892       if (client->isServerLeader())
1893       {
1894         CMessage msg;
1895         msg<<step;
1896         for (auto& rank : client->getRanksServerLeader() ) event.push(rank,1,msg);
1897         client->sendEvent(event);
1898       }
1899       else client->sendEvent(event);
1900     }
1901   }
1902   CATCH_DUMP_ATTR
1903
1904   //! Server side: Receive a message of client annoucing calendar update
1905   void CContext::recvUpdateCalendar(CEventServer& event)
1906   TRY
1907   {
1908      CBufferIn* buffer=event.subEvents.begin()->buffer;
1909      getCurrent()->recvUpdateCalendar(*buffer);
1910   }
1911   CATCH
1912
1913   //! Server side: Receive a message of client annoucing calendar update
1914   void CContext::recvUpdateCalendar(CBufferIn& buffer)
1915   TRY
1916   {
1917      int step;
1918      buffer>>step;
1919      updateCalendar(step);
1920      if (serviceType_==CServicesManager::GATHERER)
1921      {       
1922        sendUpdateCalendar(step);
1923      }
1924   }
1925   CATCH_DUMP_ATTR
1926
1927   //! Client side: Send a message to create header part of netcdf file
1928   void CContext::sendCreateFileHeader(void)
1929   TRY
1930   {
1931     int nbSrvPools ;
1932     if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
1933     else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
1934     else nbSrvPools = 0 ;
1935     CContextClient* contextClientTmp ;
1936
1937     for (int i = 0; i < nbSrvPools; ++i)
1938     {
1939       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
1940       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
1941       CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
1942
1943       if (contextClientTmp->isServerLeader())
1944       {
1945         CMessage msg;
1946         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1947         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1948           event.push(*itRank,1,msg) ;
1949         contextClientTmp->sendEvent(event);
1950       }
1951       else contextClientTmp->sendEvent(event);
1952     }
1953   }
1954   CATCH_DUMP_ATTR
1955
1956   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1957   void CContext::recvCreateFileHeader(CEventServer& event)
1958   TRY
1959   {
1960      CBufferIn* buffer=event.subEvents.begin()->buffer;
1961      getCurrent()->recvCreateFileHeader(*buffer);
1962   }
1963   CATCH
1964
1965   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1966   void CContext::recvCreateFileHeader(CBufferIn& buffer)
1967   TRY
1968   {
1969      if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 
1970        createFileHeader();
1971   }
1972   CATCH_DUMP_ATTR
1973
1974   void CContext::createCouplerInterCommunicator(void)
1975   TRY
1976   {
1977      int rank=this->getIntraCommRank() ;
1978      map<string,list<CCouplerOut*>> listCouplerOut ; 
1979      map<string,list<CCouplerIn*>> listCouplerIn ; 
1980
1981      for(auto couplerOut : enabledCouplerOut) listCouplerOut[couplerOut->getCouplingContextId()].push_back(couplerOut) ;
1982      for(auto couplerIn : enabledCouplerIn) listCouplerIn[couplerIn->getCouplingContextId()].push_back(couplerIn) ;
1983
1984      CCouplerManager* couplerManager = CXios::getCouplerManager() ;
1985      if (rank==0)
1986      {
1987        for(auto couplerOut : listCouplerOut) couplerManager->registerCoupling(this->getContextId(),couplerOut.first) ;
1988        for(auto couplerIn : listCouplerIn) couplerManager->registerCoupling(couplerIn.first,this->getContextId()) ;
1989      }
1990
1991      do
1992      {
1993        for(auto couplerOut : listCouplerOut) 
1994        {
1995          bool isNextCoupling ;
1996          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(this->getContextId(),couplerOut.first) ;
1997          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
1998          if (isNextCoupling) 
1999          {
2000            addCouplingChanel(couplerOut.first, true) ;
2001            listCouplerOut.erase(couplerOut.first) ;
2002            break ;
2003          }           
2004        }
2005        for(auto couplerIn : listCouplerIn) 
2006        {
2007          bool isNextCoupling ;
2008          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(couplerIn.first,this->getContextId());
2009          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
2010          if (isNextCoupling) 
2011          {
2012            addCouplingChanel(couplerIn.first, false) ;
2013            listCouplerIn.erase(couplerIn.first) ;
2014            break ;
2015          }           
2016        }
2017
2018      } while (!listCouplerOut.empty() || !listCouplerIn.empty()) ;
2019
2020   }
2021   CATCH_DUMP_ATTR
2022
2023 
2024     //! Client side: Send infomation of active files (files are enabled to write out)
2025   void CContext::sendEnabledFiles(const std::vector<CFile*>& activeFiles)
2026   TRY
2027   {
2028     int size = activeFiles.size();
2029
2030     // In a context, each type has a root definition, e.g: axis, domain, field.
2031     // Every object must be a child of one of these root definition. In this case
2032     // all new file objects created on server must be children of the root "file_definition"
2033     StdString fileDefRoot("file_definition");
2034     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
2035
2036     for (int i = 0; i < size; ++i)
2037     {
2038       CFile* f = activeFiles[i];
2039       cfgrpPtr->sendCreateChild(f->getId(),f->getContextClient());
2040       f->sendAllAttributesToServer(f->getContextClient());
2041       f->sendAddAllVariables(f->getContextClient());
2042     }
2043   }
2044   CATCH_DUMP_ATTR
2045
2046   //! Client side: Send information of active fields (ones are written onto files)
2047   void CContext::sendEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
2048   TRY
2049   {
2050     int size = activeFiles.size();
2051     for (int i = 0; i < size; ++i)
2052     {
2053       activeFiles[i]->sendEnabledFields(activeFiles[i]->getContextClient());
2054     }
2055   }
2056   CATCH_DUMP_ATTR
2057
2058 
2059   //! Client side: Prepare the timeseries by adding the necessary files
2060   void CContext::prepareTimeseries()
2061   TRY
2062   {
2063     const std::vector<CFile*> allFiles = CFile::getAll();
2064     for (size_t i = 0; i < allFiles.size(); i++)
2065     {
2066       CFile* file = allFiles[i];
2067
2068       std::vector<CVariable*> fileVars, fieldVars, vars = file->getAllVariables();
2069       for (size_t k = 0; k < vars.size(); k++)
2070       {
2071         CVariable* var = vars[k];
2072
2073         if (var->ts_target.isEmpty()
2074              || var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both)
2075           fileVars.push_back(var);
2076
2077         if (!var->ts_target.isEmpty()
2078              && (var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both))
2079           fieldVars.push_back(var);
2080       }
2081
2082       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
2083       {
2084         StdString fileNameStr("%file_name%") ;
2085         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : fileNameStr ;
2086         
2087         StdString fileName=file->getFileOutputName();
2088         size_t pos=tsPrefix.find(fileNameStr) ;
2089         while (pos!=std::string::npos)
2090         {
2091           tsPrefix=tsPrefix.replace(pos,fileNameStr.size(),fileName) ;
2092           pos=tsPrefix.find(fileNameStr) ;
2093         }
2094       
2095         const std::vector<CField*> allFields = file->getAllFields();
2096         for (size_t j = 0; j < allFields.size(); j++)
2097         {
2098           CField* field = allFields[j];
2099
2100           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
2101           {
2102             CFile* tsFile = CFile::create();
2103             tsFile->duplicateAttributes(file);
2104
2105             // Add variables originating from file and targeted to timeserie file
2106             for (size_t k = 0; k < fileVars.size(); k++)
2107               tsFile->getVirtualVariableGroup()->addChild(fileVars[k]);
2108
2109           
2110             tsFile->name = tsPrefix + "_";
2111             if (!field->name.isEmpty())
2112               tsFile->name.get() += field->name;
2113             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
2114               tsFile->name.get() += field->field_ref;
2115             else
2116               tsFile->name.get() += field->getId();
2117
2118             if (!field->ts_split_freq.isEmpty())
2119               tsFile->split_freq = field->ts_split_freq;
2120
2121             CField* tsField = tsFile->addField();
2122             tsField->field_ref = field->getId();
2123
2124             // Add variables originating from file and targeted to timeserie field
2125             for (size_t k = 0; k < fieldVars.size(); k++)
2126               tsField->getVirtualVariableGroup()->addChild(fieldVars[k]);
2127
2128             vars = field->getAllVariables();
2129             for (size_t k = 0; k < vars.size(); k++)
2130             {
2131               CVariable* var = vars[k];
2132
2133               // Add variables originating from field and targeted to timeserie field
2134               if (var->ts_target.isEmpty()
2135                    || var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both)
2136                 tsField->getVirtualVariableGroup()->addChild(var);
2137
2138               // Add variables originating from field and targeted to timeserie file
2139               if (!var->ts_target.isEmpty()
2140                    && (var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both))
2141                 tsFile->getVirtualVariableGroup()->addChild(var);
2142             }
2143
2144             tsFile->solveFieldRefInheritance(true);
2145
2146             if (file->timeseries == CFile::timeseries_attr::exclusive)
2147               field->enabled = false;
2148           }
2149         }
2150
2151         // Finally disable the original file is need be
2152         if (file->timeseries == CFile::timeseries_attr::only)
2153          file->enabled = false;
2154       }
2155     }
2156   }
2157   CATCH_DUMP_ATTR
2158
2159   //! Client side: Send information of reference grid of active fields
2160   void CContext::sendRefGrid(const std::vector<CFile*>& activeFiles)
2161   TRY
2162   {
2163     std::set<pair<StdString,CContextClient*>> gridIds;
2164
2165     int sizeFile = activeFiles.size();
2166     CFile* filePtr(NULL);
2167
2168     // Firstly, find all reference grids of all active fields
2169     for (int i = 0; i < sizeFile; ++i)
2170     {
2171       filePtr = activeFiles[i];
2172       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
2173       int sizeField = enabledFields.size();
2174       for (int numField = 0; numField < sizeField; ++numField)
2175       {
2176         if (0 != enabledFields[numField]->getRelGrid())
2177           gridIds.insert(make_pair(CGrid::get(enabledFields[numField]->getRelGrid())->getId(),enabledFields[numField]->getContextClient()));
2178       }
2179     }
2180
2181     // Create all reference grids on server side
2182     StdString gridDefRoot("grid_definition");
2183     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
2184     for (auto it = gridIds.begin(); it != gridIds.end(); ++it)
2185     {
2186       gridPtr->sendCreateChild(it->first,it->second);
2187       CGrid::get(it->first)->sendAllAttributesToServer(it->second);
2188       CGrid::get(it->first)->sendAllDomains(it->second);
2189       CGrid::get(it->first)->sendAllAxis(it->second);
2190       CGrid::get(it->first)->sendAllScalars(it->second);
2191     }
2192   }
2193   CATCH_DUMP_ATTR
2194
2195   //! Client side: Send information of reference domain, axis and scalar of active fields
2196   void CContext::sendRefDomainsAxisScalars(const std::vector<CFile*>& activeFiles)
2197   TRY
2198   {
2199     std::set<pair<StdString,CContextClient*>> domainIds, axisIds, scalarIds;
2200
2201     // Find all reference domain and axis of all active fields
2202     int numEnabledFiles = activeFiles.size();
2203     for (int i = 0; i < numEnabledFiles; ++i)
2204     {
2205       std::vector<CField*> enabledFields = activeFiles[i]->getEnabledFields();
2206       int numEnabledFields = enabledFields.size();
2207       for (int j = 0; j < numEnabledFields; ++j)
2208       {
2209         CContextClient* contextClient=enabledFields[j]->getContextClient() ;
2210         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
2211         if ("" != prDomAxisScalarId[0]) domainIds.insert(make_pair(prDomAxisScalarId[0],contextClient));
2212         if ("" != prDomAxisScalarId[1]) axisIds.insert(make_pair(prDomAxisScalarId[1],contextClient));
2213         if ("" != prDomAxisScalarId[2]) scalarIds.insert(make_pair(prDomAxisScalarId[2],contextClient));
2214       }
2215     }
2216
2217     // Create all reference axis on server side
2218     std::set<StdString>::iterator itDom, itAxis, itScalar;
2219     std::set<StdString>::const_iterator itE;
2220
2221     StdString scalarDefRoot("scalar_definition");
2222     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
2223     
2224     for (auto itScalar = scalarIds.begin(); itScalar != scalarIds.end(); ++itScalar)
2225     {
2226       if (!itScalar->first.empty())
2227       {
2228         scalarPtr->sendCreateChild(itScalar->first,itScalar->second);
2229         CScalar::get(itScalar->first)->sendAllAttributesToServer(itScalar->second);
2230       }
2231     }
2232
2233     StdString axiDefRoot("axis_definition");
2234     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
2235     
2236     for (auto itAxis = axisIds.begin(); itAxis != axisIds.end(); ++itAxis)
2237     {
2238       if (!itAxis->first.empty())
2239       {
2240         axisPtr->sendCreateChild(itAxis->first, itAxis->second);
2241         CAxis::get(itAxis->first)->sendAllAttributesToServer(itAxis->second);
2242       }
2243     }
2244
2245     // Create all reference domains on server side
2246     StdString domDefRoot("domain_definition");
2247     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
2248     
2249     for (auto itDom = domainIds.begin(); itDom != domainIds.end(); ++itDom)
2250     {
2251       if (!itDom->first.empty()) {
2252          domPtr->sendCreateChild(itDom->first, itDom->second);
2253          CDomain::get(itDom->first)->sendAllAttributesToServer(itDom->second);
2254       }
2255     }
2256   }
2257   CATCH_DUMP_ATTR
2258
2259   void CContext::triggerLateFields(void)
2260   TRY
2261   {
2262    for(auto& field : fileInFields_) field->triggerLateField() ;
2263    for(auto& field : couplerInFields_) field->triggerLateField() ;
2264   }
2265   CATCH_DUMP_ATTR
2266
2267   //! Update calendar in each time step
2268   void CContext::updateCalendar(int step)
2269   TRY
2270   {
2271      int prevStep = calendar->getStep();
2272
2273      if (prevStep < step)
2274      {
2275        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2276        {
2277          triggerLateFields();
2278        }
2279
2280        info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
2281        calendar->update(step);
2282        info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
2283  #ifdef XIOS_MEMTRACK_LIGHT
2284        info(50) << " Current memory used by XIOS : "<<  MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte, at timestep "<<step<<" of context "<<this->getId()<<endl ;
2285  #endif
2286
2287        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2288        {
2289          doPostTimestepOperationsForEnabledReadModeFiles();
2290          garbageCollector.invalidate(calendar->getCurrentDate());
2291        }
2292      }
2293      else if (prevStep == step)
2294        info(50) << "updateCalendar: already at step " << step << ", no operation done." << endl;
2295      else // if (prevStep > step)
2296        ERROR("void CContext::updateCalendar(int step)",
2297              << "Illegal calendar update: previous step was " << prevStep << ", new step " << step << "is in the past!")
2298   }
2299   CATCH_DUMP_ATTR
2300
2301   void CContext::initReadFiles(void)
2302   TRY
2303   {
2304      vector<CFile*>::const_iterator it;
2305
2306      for (it=enabledReadModeFiles.begin(); it != enabledReadModeFiles.end(); it++)
2307      {
2308         (*it)->initRead();
2309      }
2310   }
2311   CATCH_DUMP_ATTR
2312
2313   //! Server side: Create header of netcdf file
2314   void CContext::createFileHeader(void)
2315   TRY
2316   {
2317      vector<CFile*>::const_iterator it;
2318
2319      //for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
2320      for (it=enabledWriteModeFiles.begin(); it != enabledWriteModeFiles.end(); it++)
2321      {
2322         (*it)->initWrite();
2323      }
2324   }
2325   CATCH_DUMP_ATTR
2326
2327   //! Get current context
2328   CContext* CContext::getCurrent(void)
2329   TRY
2330   {
2331     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
2332   }
2333   CATCH
2334
2335   /*!
2336   \brief Set context with an id be the current context
2337   \param [in] id identity of context to be set to current
2338   */
2339   void CContext::setCurrent(const string& id)
2340   TRY
2341   {
2342     CObjectFactory::SetCurrentContextId(id);
2343     CGroupFactory::SetCurrentContextId(id);
2344   }
2345   CATCH
2346
2347  /*!
2348  \brief Create a context with specific id
2349  \param [in] id identity of new context
2350  \return pointer to the new context or already-existed one with identity id
2351  */
2352  CContext* CContext::create(const StdString& id)
2353  TRY
2354  {
2355    CContext::setCurrent(id);
2356
2357    bool hasctxt = CContext::has(id);
2358    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
2359    getRoot();
2360    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
2361
2362#define DECLARE_NODE(Name_, name_) \
2363    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
2364#define DECLARE_NODE_PAR(Name_, name_)
2365#include "node_type.conf"
2366
2367    return (context);
2368  }
2369  CATCH
2370
2371     //! Server side: Receive a message to do some post processing
2372  void CContext::recvRegistry(CEventServer& event)
2373  TRY
2374  {
2375    CBufferIn* buffer=event.subEvents.begin()->buffer;
2376    getCurrent()->recvRegistry(*buffer);
2377  }
2378  CATCH
2379
2380  void CContext::recvRegistry(CBufferIn& buffer)
2381  TRY
2382  {
2383    if (server->intraCommRank==0)
2384    {
2385      CRegistry registry(server->intraComm) ;
2386      registry.fromBuffer(buffer) ;
2387      registryOut->mergeRegistry(registry) ;
2388    }
2389  }
2390  CATCH_DUMP_ATTR
2391
2392  void CContext::sendRegistry(void)
2393  TRY
2394  {
2395    registryOut->hierarchicalGatherRegistry() ;
2396
2397    int nbSrvPools ;
2398    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
2399    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
2400    else nbSrvPools = 0 ;
2401    CContextClient* contextClientTmp ;
2402
2403    for (int i = 0; i < nbSrvPools; ++i)
2404    {
2405      if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
2406      else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
2407
2408      CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
2409      if (contextClientTmp->isServerLeader())
2410      {
2411        CMessage msg ;
2412        if (contextClientTmp->clientRank==0) msg<<*registryOut ;
2413        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
2414        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2415             event.push(*itRank,1,msg);
2416        contextClientTmp->sendEvent(event);
2417      }
2418      else contextClientTmp->sendEvent(event);
2419    }
2420  }
2421  CATCH_DUMP_ATTR
2422
2423 
2424  void CContext::sendFinalizeClient(CContextClient* contextClient, const string& contextClientId)
2425  TRY
2426  {
2427    CEventClient event(getType(),EVENT_ID_CONTEXT_FINALIZE_CLIENT);
2428    if (contextClient->isServerLeader())
2429    {
2430      CMessage msg;
2431      msg<<contextClientId ;
2432      const std::list<int>& ranks = contextClient->getRanksServerLeader();
2433      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2434           event.push(*itRank,1,msg);
2435      contextClient->sendEvent(event);
2436    }
2437    else contextClient->sendEvent(event);
2438  }
2439  CATCH_DUMP_ATTR
2440
2441 
2442  void CContext::recvFinalizeClient(CEventServer& event)
2443  TRY
2444  {
2445    CBufferIn* buffer=event.subEvents.begin()->buffer;
2446    string id;
2447    *buffer>>id;
2448    get(id)->recvFinalizeClient(*buffer);
2449  }
2450  CATCH
2451
2452  void CContext::recvFinalizeClient(CBufferIn& buffer)
2453  TRY
2454  {
2455    countChildContextFinalized_++ ;
2456  }
2457  CATCH_DUMP_ATTR
2458
2459
2460
2461
2462 //! Client side: Send a message  announcing that context can receive grid definition from coupling
2463   void CContext::sendCouplerInReady(CContextClient* client)
2464   TRY
2465   {
2466      if (sendCouplerInReady_done_.count(client)!=0) return ;
2467      else sendCouplerInReady_done_.insert(client) ;
2468
2469      CEventClient event(getType(),EVENT_ID_COUPLER_IN_READY);
2470
2471      if (client->isServerLeader())
2472      {
2473        CMessage msg;
2474        msg<<this->getId();
2475        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2476        client->sendEvent(event);
2477      }
2478      else client->sendEvent(event);
2479   }
2480   CATCH_DUMP_ATTR
2481
2482   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2483   void CContext::recvCouplerInReady(CEventServer& event)
2484   TRY
2485   {
2486      CBufferIn* buffer=event.subEvents.begin()->buffer;
2487      getCurrent()->recvCouplerInReady(*buffer);
2488   }
2489   CATCH
2490
2491   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2492   void CContext::recvCouplerInReady(CBufferIn& buffer)
2493   TRY
2494   {
2495      string contextId ;
2496      buffer>>contextId;
2497      couplerInReady_.insert(getCouplerOutClient(contextId)) ;
2498   }
2499   CATCH_DUMP_ATTR
2500
2501
2502
2503
2504
2505 //! Client side: Send a message  announcing that a coupling context have done it closeDefinition, so data can be sent now.
2506   void CContext::sendCouplerInCloseDefinition(CContextClient* client)
2507   TRY
2508   {
2509      if (sendCouplerInCloseDefinition_done_.count(client)!=0) return ;
2510      else sendCouplerInCloseDefinition_done_.insert(client) ;
2511
2512      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CLOSE_DEFINITION);
2513
2514      if (client->isServerLeader())
2515      {
2516        CMessage msg;
2517        msg<<this->getId();
2518        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2519        client->sendEvent(event);
2520      }
2521      else client->sendEvent(event);
2522   }
2523   CATCH_DUMP_ATTR
2524
2525   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2526   void CContext::recvCouplerInCloseDefinition(CEventServer& event)
2527   TRY
2528   {
2529      CBufferIn* buffer=event.subEvents.begin()->buffer;
2530      getCurrent()->recvCouplerInCloseDefinition(*buffer);
2531   }
2532   CATCH
2533
2534   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2535   void CContext::recvCouplerInCloseDefinition(CBufferIn& buffer)
2536   TRY
2537   {
2538      string contextId ;
2539      buffer>>contextId;
2540      couplerInCloseDefinition_.insert(getCouplerOutClient(contextId)) ;
2541   }
2542   CATCH_DUMP_ATTR
2543
2544
2545
2546
2547//! Client side: Send a message  announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2548   void CContext::sendCouplerInContextFinalized(CContextClient* client)
2549   TRY
2550   {
2551      if (sendCouplerInContextFinalized_done_.count(client)!=0) return ;
2552      else sendCouplerInContextFinalized_done_.insert(client) ;
2553
2554      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED);
2555
2556      if (client->isServerLeader())
2557      {
2558        CMessage msg;
2559        msg<<this->getId();
2560        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2561        client->sendEvent(event);
2562      }
2563      else client->sendEvent(event);
2564   }
2565   CATCH_DUMP_ATTR
2566
2567   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2568   void CContext::recvCouplerInContextFinalized(CEventServer& event)
2569   TRY
2570   {
2571      CBufferIn* buffer=event.subEvents.begin()->buffer;
2572      getCurrent()->recvCouplerInContextFinalized(*buffer);
2573   }
2574   CATCH
2575
2576   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2577   void CContext::recvCouplerInContextFinalized(CBufferIn& buffer)
2578   TRY
2579   {
2580      string contextId ;
2581      buffer>>contextId;
2582      couplerInContextFinalized_.insert(getCouplerOutClient(contextId)) ;
2583   }
2584   CATCH_DUMP_ATTR
2585
2586
2587
2588
2589  /*!
2590  * \fn bool CContext::isFinalized(void)
2591  * Context is finalized if it received context post finalize event.
2592  */
2593  bool CContext::isFinalized(void)
2594  TRY
2595  {
2596    return finalized;
2597  }
2598  CATCH_DUMP_ATTR
2599  ///--------------------------------------------------------------
2600  StdString CContext::dumpClassAttributes(void)
2601  {
2602    StdString str;
2603    str.append("enabled files=\"");
2604    int size = this->enabledFiles.size();
2605    for (int i = 0; i < size; ++i)
2606    {
2607      str.append(enabledFiles[i]->getId());
2608      str.append(" ");
2609    }
2610    str.append("\"");
2611    return str;
2612  }
2613
2614} // namespace xios
Note: See TracBrowser for help on using the repository browser.