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

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

intermediate commit for new tranformation engine?
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: 86.2 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    /*!
1249      Go up the hierachical tree via field_ref and do check of attributes of fields
1250      This can be done in a client then all computed information will be sent from this client to others
1251      \param [in] sendToServer Flag to indicate whether calculated information will be sent
1252   */
1253   void CContext::solveOnlyRefOfEnabledFields(void)
1254   TRY
1255   {
1256     int size = this->enabledFiles.size();
1257     for (int i = 0; i < size; ++i)
1258     {
1259       this->enabledFiles[i]->solveOnlyRefOfEnabledFields();
1260     }
1261
1262     for (int i = 0; i < size; ++i)
1263     {
1264       this->enabledFiles[i]->generateNewTransformationGridDest();
1265     }
1266
1267     size = this->enabledCouplerOut.size();
1268     for (int i = 0; i < size; ++i)
1269     {
1270       this->enabledCouplerOut[i]->solveOnlyRefOfEnabledFields();
1271     }
1272
1273     for (int i = 0; i < size; ++i)
1274     {
1275       this->enabledCouplerOut[i]->generateNewTransformationGridDest();
1276     }
1277   }
1278   CATCH_DUMP_ATTR
1279
1280    /*!
1281      Go up the hierachical tree via field_ref and do check of attributes of fields.
1282      The transformation can be done in this step.
1283      All computed information will be sent from this client to others.
1284      \param [in] sendToServer Flag to indicate whether calculated information will be sent
1285   */
1286   void CContext::solveAllRefOfEnabledFieldsAndTransform(void)
1287   TRY
1288   {
1289     int size = this->enabledFiles.size();
1290     for (int i = 0; i < size; ++i)
1291     {
1292       this->enabledFiles[i]->solveAllRefOfEnabledFieldsAndTransform();
1293     }
1294
1295     size = this->enabledCouplerOut.size();
1296     for (int i = 0; i < size; ++i)
1297     {
1298       this->enabledCouplerOut[i]->solveAllRefOfEnabledFieldsAndTransform();
1299     }
1300
1301   }
1302   CATCH_DUMP_ATTR
1303
1304
1305   void CContext::postProcessFilterGraph()
1306   TRY
1307   {
1308     int size = enabledFiles.size();
1309     for (int i = 0; i < size; ++i)
1310     {
1311        enabledFiles[i]->postProcessFilterGraph();
1312     }
1313   }
1314   CATCH_DUMP_ATTR
1315
1316   void CContext::startPrefetchingOfEnabledReadModeFiles()
1317   TRY
1318   {
1319     int size = enabledReadModeFiles.size();
1320     for (int i = 0; i < size; ++i)
1321     {
1322        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
1323     }
1324   }
1325   CATCH_DUMP_ATTR
1326
1327   void CContext::doPreTimestepOperationsForEnabledReadModeFiles()
1328   TRY
1329   {
1330     int size = enabledReadModeFiles.size();
1331     for (int i = 0; i < size; ++i)
1332     {
1333        enabledReadModeFiles[i]->doPreTimestepOperationsForEnabledReadModeFields();
1334     }
1335   }
1336   CATCH_DUMP_ATTR
1337
1338   void CContext::doPostTimestepOperationsForEnabledReadModeFiles()
1339   TRY
1340   {
1341     int size = enabledReadModeFiles.size();
1342     for (int i = 0; i < size; ++i)
1343     {
1344        enabledReadModeFiles[i]->doPostTimestepOperationsForEnabledReadModeFields();
1345     }
1346   }
1347   CATCH_DUMP_ATTR
1348
1349  void CContext::findFieldsWithReadAccess(void)
1350  TRY
1351  {
1352    fieldsWithReadAccess_.clear();
1353    const vector<CField*> allFields = CField::getAll();
1354    for (size_t i = 0; i < allFields.size(); ++i)
1355    {
1356      CField* field = allFields[i];
1357      if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
1358      {
1359        fieldsWithReadAccess_.push_back(field);
1360        field->setModelOut() ;
1361      }
1362    }
1363  }
1364  CATCH_DUMP_ATTR
1365
1366 
1367   void CContext::solveAllInheritance(bool apply)
1368   TRY
1369   {
1370     // Résolution des héritages descendants (càd des héritages de groupes)
1371     // pour chacun des contextes.
1372      solveDescInheritance(apply);
1373
1374     // Résolution des héritages par référence au niveau des fichiers.
1375      const vector<CFile*> allFiles=CFile::getAll();
1376      const vector<CCouplerIn*> allCouplerIn=CCouplerIn::getAll();
1377      const vector<CCouplerOut*> allCouplerOut=CCouplerOut::getAll();
1378      const vector<CGrid*> allGrids= CGrid::getAll();
1379
1380      if (serviceType_==CServicesManager::CLIENT)
1381      {
1382        for (unsigned int i = 0; i < allFiles.size(); i++)
1383          allFiles[i]->solveFieldRefInheritance(apply);
1384
1385        for (unsigned int i = 0; i < allCouplerIn.size(); i++)
1386          allCouplerIn[i]->solveFieldRefInheritance(apply);
1387
1388        for (unsigned int i = 0; i < allCouplerOut.size(); i++)
1389          allCouplerOut[i]->solveFieldRefInheritance(apply);
1390      }
1391
1392      unsigned int vecSize = allGrids.size();
1393      unsigned int i = 0;
1394      for (i = 0; i < vecSize; ++i)
1395        allGrids[i]->solveElementsRefInheritance(apply);
1396
1397   }
1398  CATCH_DUMP_ATTR
1399
1400   void CContext::findEnabledFiles(void)
1401   TRY
1402   {
1403      const std::vector<CFile*> allFiles = CFile::getAll();
1404      const CDate& initDate = calendar->getInitDate();
1405
1406      for (unsigned int i = 0; i < allFiles.size(); i++)
1407         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
1408         {
1409            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
1410            {
1411              if (allFiles[i]->output_freq.isEmpty())
1412              {
1413                 ERROR("CContext::findEnabledFiles()",
1414                     << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1415                     <<" \".")
1416              }
1417              if ((initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1418              {
1419                error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1420                    << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1421                    <<"\" is less than the time step. File will not be written."<<endl;
1422              }
1423              else
1424               enabledFiles.push_back(allFiles[i]);
1425            }
1426         }
1427         else
1428         {
1429           if (allFiles[i]->output_freq.isEmpty())
1430           {
1431              ERROR("CContext::findEnabledFiles()",
1432                  << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1433                  <<" \".")
1434           }
1435           if ( (initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1436           {
1437             error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1438                 << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1439                 <<"\" is less than the time step. File will not be written."<<endl;
1440           }
1441           else
1442             enabledFiles.push_back(allFiles[i]); // otherwise true by default
1443         }
1444
1445      if (enabledFiles.size() == 0)
1446         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
1447               << getId() << "\" !");
1448
1449   }
1450   CATCH_DUMP_ATTR
1451
1452   void CContext::findEnabledCouplerIn(void)
1453   TRY
1454   {
1455      const std::vector<CCouplerIn*> allCouplerIn = CCouplerIn::getAll();
1456      bool enabled ;
1457      for (size_t i = 0; i < allCouplerIn.size(); i++)
1458      {
1459        if (allCouplerIn[i]->enabled.isEmpty()) enabled=true ;
1460        else enabled=allCouplerIn[i]->enabled ;
1461        if (enabled) enabledCouplerIn.push_back(allCouplerIn[i]) ;
1462      }
1463   }
1464   CATCH_DUMP_ATTR
1465
1466   void CContext::findEnabledCouplerOut(void)
1467   TRY
1468   {
1469      const std::vector<CCouplerOut*> allCouplerOut = CCouplerOut::getAll();
1470      bool enabled ;
1471      for (size_t i = 0; i < allCouplerOut.size(); i++)
1472      {
1473        if (allCouplerOut[i]->enabled.isEmpty()) enabled=true ;
1474        else enabled=allCouplerOut[i]->enabled ;
1475        if (enabled) enabledCouplerOut.push_back(allCouplerOut[i]) ;
1476      }
1477   }
1478   CATCH_DUMP_ATTR
1479
1480
1481
1482
1483   void CContext::distributeFiles(const vector<CFile*>& files)
1484   TRY
1485   {
1486     bool distFileMemory=false ;
1487     distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory);
1488
1489     if (distFileMemory) distributeFileOverMemoryBandwith(files) ;
1490     else distributeFileOverBandwith(files) ;
1491   }
1492   CATCH_DUMP_ATTR
1493
1494   void CContext::distributeFileOverBandwith(const vector<CFile*>& files)
1495   TRY
1496   {
1497     double eps=std::numeric_limits<double>::epsilon()*10 ;
1498     
1499     std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out);
1500     int nbPools = clientPrimServer.size();
1501
1502     // (1) Find all enabled files in write mode
1503     // for (int i = 0; i < this->enabledFiles.size(); ++i)
1504     // {
1505     //   if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1506     //    enabledWriteModeFiles.push_back(enabledFiles[i]);
1507     // }
1508
1509     // (2) Estimate the data volume for each file
1510     int size = files.size();
1511     std::vector<std::pair<double, CFile*> > dataSizeMap;
1512     double dataPerPool = 0;
1513     int nfield=0 ;
1514     ofs<<size<<endl ;
1515     for (size_t i = 0; i < size; ++i)
1516     {
1517       CFile* file = files[i];
1518       ofs<<file->getId()<<endl ;
1519       StdSize dataSize=0;
1520       std::vector<CField*> enabledFields = file->getEnabledFields();
1521       size_t numEnabledFields = enabledFields.size();
1522       ofs<<numEnabledFields<<endl ;
1523       for (size_t j = 0; j < numEnabledFields; ++j)
1524       {
1525         dataSize += enabledFields[j]->getGlobalWrittenSize() ;
1526         ofs<<enabledFields[j]->getGrid()->getId()<<endl ;
1527         ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ;
1528       }
1529       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1530       double dataSizeSec= dataSize/ outFreqSec;
1531       ofs<<dataSizeSec<<endl ;
1532       nfield++ ;
1533// add epsilon*nField to dataSizeSec in order to  preserve reproductive ordering when sorting
1534       dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file));
1535       dataPerPool += dataSizeSec;
1536     }
1537     dataPerPool /= nbPools;
1538     std::sort(dataSizeMap.begin(), dataSizeMap.end());
1539
1540     // (3) Assign contextClient to each enabled file
1541
1542     std::multimap<double,int> poolDataSize ;
1543// multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11
1544
1545     int j;
1546     double dataSize ;
1547     for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ; 
1548             
1549     for (int i = dataSizeMap.size()-1; i >= 0; --i)
1550     {
1551       dataSize=(*poolDataSize.begin()).first ;
1552       j=(*poolDataSize.begin()).second ;
1553       dataSizeMap[i].second->setContextClient(clientPrimServer[j]);
1554       dataSize+=dataSizeMap[i].first;
1555       poolDataSize.erase(poolDataSize.begin()) ;
1556       poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 
1557     }
1558
1559     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 ;
1560   }
1561   CATCH_DUMP_ATTR
1562
1563   void CContext::distributeFileOverMemoryBandwith(const vector<CFile*>& filesList)
1564   TRY
1565   {
1566     int nbPools = clientPrimServer.size();
1567     double ratio=0.5 ;
1568     ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio);
1569
1570     int nFiles = filesList.size();
1571     vector<SDistFile> files(nFiles);
1572     vector<SDistGrid> grids;
1573     map<string,int> gridMap ;
1574     string gridId; 
1575     int gridIndex=0 ;
1576
1577     for (size_t i = 0; i < nFiles; ++i)
1578     {
1579       StdSize dataSize=0;
1580       CFile* file = filesList[i];
1581       std::vector<CField*> enabledFields = file->getEnabledFields();
1582       size_t numEnabledFields = enabledFields.size();
1583
1584       files[i].id_=file->getId() ;
1585       files[i].nbGrids_=numEnabledFields;
1586       files[i].assignedGrid_ = new int[files[i].nbGrids_] ;
1587         
1588       for (size_t j = 0; j < numEnabledFields; ++j)
1589       {
1590         gridId=enabledFields[j]->getGrid()->getId() ;
1591         if (gridMap.find(gridId)==gridMap.end())
1592         {
1593            gridMap[gridId]=gridIndex  ;
1594            SDistGrid newGrid; 
1595            grids.push_back(newGrid) ;
1596            gridIndex++ ;
1597         }
1598         files[i].assignedGrid_[j]=gridMap[gridId] ;
1599         grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ;
1600         dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull
1601       }
1602       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1603       files[i].bandwith_= dataSize/ outFreqSec ;
1604     }
1605
1606     double bandwith=0 ;
1607     double memory=0 ;
1608   
1609     for(int i=0; i<nFiles; i++)  bandwith+=files[i].bandwith_ ;
1610     for(int i=0; i<nFiles; i++)  files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ;
1611
1612     for(int i=0; i<grids.size(); i++)  memory+=grids[i].size_ ;
1613     for(int i=0; i<grids.size(); i++)  grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ;
1614       
1615     distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ;
1616
1617     vector<double> memorySize(nbPools,0.) ;
1618     vector< set<int> > serverGrids(nbPools) ;
1619     vector<double> bandwithSize(nbPools,0.) ;
1620       
1621     for (size_t i = 0; i < nFiles; ++i)
1622     {
1623       bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ;
1624       for(int j=0 ; j<files[i].nbGrids_;j++)
1625       {
1626         if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end())
1627         {
1628           memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio);
1629           serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ;
1630         }
1631       }
1632       filesList[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ;
1633       delete [] files[i].assignedGrid_ ;
1634     }
1635
1636     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 ;
1637     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ;
1638
1639   }
1640   CATCH_DUMP_ATTR
1641
1642   /*!
1643      Find all files in write mode
1644   */
1645   void CContext::findEnabledWriteModeFiles(void)
1646   TRY
1647   {
1648     int size = this->enabledFiles.size();
1649     for (int i = 0; i < size; ++i)
1650     {
1651       if (enabledFiles[i]->mode.isEmpty() || 
1652          (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1653        enabledWriteModeFiles.push_back(enabledFiles[i]);
1654     }
1655   }
1656   CATCH_DUMP_ATTR
1657
1658   /*!
1659      Find all files in read mode
1660   */
1661   void CContext::findEnabledReadModeFiles(void)
1662   TRY
1663   {
1664     int size = this->enabledFiles.size();
1665     for (int i = 0; i < size; ++i)
1666     {
1667       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
1668        enabledReadModeFiles.push_back(enabledFiles[i]);
1669     }
1670   }
1671   CATCH_DUMP_ATTR
1672
1673   void CContext::closeAllFile(void)
1674   TRY
1675   {
1676     std::vector<CFile*>::const_iterator
1677            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
1678
1679     for (; it != end; it++)
1680     {
1681       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
1682       (*it)->close();
1683     }
1684   }
1685   CATCH_DUMP_ATTR
1686
1687   /*!
1688   \brief Dispatch event received from client
1689      Whenever a message is received in buffer of server, it will be processed depending on
1690   its event type. A new event type should be added in the switch list to make sure
1691   it processed on server side.
1692   \param [in] event: Received message
1693   */
1694   bool CContext::dispatchEvent(CEventServer& event)
1695   TRY
1696   {
1697
1698      if (SuperClass::dispatchEvent(event)) return true;
1699      else
1700      {
1701        switch(event.type)
1702        {
1703           case EVENT_ID_CLOSE_DEFINITION :
1704             recvCloseDefinition(event);
1705             return true;
1706             break;
1707           case EVENT_ID_UPDATE_CALENDAR:
1708             recvUpdateCalendar(event);
1709             return true;
1710             break;
1711           case EVENT_ID_CREATE_FILE_HEADER :
1712             recvCreateFileHeader(event);
1713             return true;
1714             break;
1715           case EVENT_ID_SEND_REGISTRY:
1716             recvRegistry(event);
1717             return true;
1718             break;
1719           case EVENT_ID_COUPLER_IN_READY:
1720             recvCouplerInReady(event);
1721             return true;
1722             break;
1723           case EVENT_ID_COUPLER_IN_CLOSE_DEFINITION:
1724             recvCouplerInCloseDefinition(event);
1725             return true;
1726             break;
1727           case EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED:
1728             recvCouplerInContextFinalized(event);
1729             return true;
1730             break; 
1731           default :
1732             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
1733                    <<"Unknown Event");
1734           return false;
1735         }
1736      }
1737   }
1738   CATCH
1739
1740   //! Client side: Send a message to server to make it close
1741   // ym obsolete
1742   void CContext::sendCloseDefinition(void)
1743   TRY
1744   {
1745    int nbSrvPools ;
1746    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
1747    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
1748    else nbSrvPools = 0 ;
1749    CContextClient* contextClientTmp ;
1750
1751    for (int i = 0; i < nbSrvPools; ++i)
1752     {
1753       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
1754       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
1755       CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
1756       if (contextClientTmp->isServerLeader())
1757       {
1758         CMessage msg;
1759         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1760         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1761           event.push(*itRank,1,msg);
1762         contextClientTmp->sendEvent(event);
1763       }
1764       else contextClientTmp->sendEvent(event);
1765     }
1766   }
1767   CATCH_DUMP_ATTR
1768   
1769   //  ! Client side: Send a message to server to make it close
1770   void CContext::sendCloseDefinition(CContextClient* client)
1771   TRY
1772   {
1773      if (sendCloseDefinition_done_.count(client)!=0) return ;
1774      else sendCloseDefinition_done_.insert(client) ;
1775
1776      CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
1777      if (client->isServerLeader())
1778      {
1779        CMessage msg;
1780        for(auto rank : client->getRanksServerLeader()) event.push(rank,1,msg);
1781        client->sendEvent(event);
1782      }
1783     else client->sendEvent(event);
1784   }
1785   CATCH_DUMP_ATTR
1786
1787   //! Server side: Receive a message of client announcing a context close
1788   void CContext::recvCloseDefinition(CEventServer& event)
1789   TRY
1790   {
1791      CBufferIn* buffer=event.subEvents.begin()->buffer;
1792      getCurrent()->closeDefinition();
1793   }
1794   CATCH
1795
1796   //! Client side: Send a message to update calendar in each time step
1797   void CContext::sendUpdateCalendar(int step)
1798   TRY
1799   {
1800     CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
1801     for(auto client : slaveServers_) 
1802     {
1803       if (client->isServerLeader())
1804       {
1805         CMessage msg;
1806         msg<<step;
1807         for (auto& rank : client->getRanksServerLeader() ) event.push(rank,1,msg);
1808         client->sendEvent(event);
1809       }
1810       else client->sendEvent(event);
1811     }
1812   }
1813   CATCH_DUMP_ATTR
1814
1815   //! Server side: Receive a message of client annoucing calendar update
1816   void CContext::recvUpdateCalendar(CEventServer& event)
1817   TRY
1818   {
1819      CBufferIn* buffer=event.subEvents.begin()->buffer;
1820      getCurrent()->recvUpdateCalendar(*buffer);
1821   }
1822   CATCH
1823
1824   //! Server side: Receive a message of client annoucing calendar update
1825   void CContext::recvUpdateCalendar(CBufferIn& buffer)
1826   TRY
1827   {
1828      int step;
1829      buffer>>step;
1830      updateCalendar(step);
1831      if (serviceType_==CServicesManager::GATHERER)
1832      {       
1833        sendUpdateCalendar(step);
1834      }
1835   }
1836   CATCH_DUMP_ATTR
1837
1838   //! Client side: Send a message to create header part of netcdf file
1839   void CContext::sendCreateFileHeader(void)
1840   TRY
1841   {
1842     int nbSrvPools ;
1843     if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
1844     else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
1845     else nbSrvPools = 0 ;
1846     CContextClient* contextClientTmp ;
1847
1848     for (int i = 0; i < nbSrvPools; ++i)
1849     {
1850       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
1851       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
1852       CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
1853
1854       if (contextClientTmp->isServerLeader())
1855       {
1856         CMessage msg;
1857         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1858         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1859           event.push(*itRank,1,msg) ;
1860         contextClientTmp->sendEvent(event);
1861       }
1862       else contextClientTmp->sendEvent(event);
1863     }
1864   }
1865   CATCH_DUMP_ATTR
1866
1867   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1868   void CContext::recvCreateFileHeader(CEventServer& event)
1869   TRY
1870   {
1871      CBufferIn* buffer=event.subEvents.begin()->buffer;
1872      getCurrent()->recvCreateFileHeader(*buffer);
1873   }
1874   CATCH
1875
1876   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1877   void CContext::recvCreateFileHeader(CBufferIn& buffer)
1878   TRY
1879   {
1880      if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 
1881        createFileHeader();
1882   }
1883   CATCH_DUMP_ATTR
1884
1885   void CContext::createCouplerInterCommunicator(void)
1886   TRY
1887   {
1888      int rank=this->getIntraCommRank() ;
1889      map<string,list<CCouplerOut*>> listCouplerOut ; 
1890      map<string,list<CCouplerIn*>> listCouplerIn ; 
1891
1892      for(auto couplerOut : enabledCouplerOut) listCouplerOut[couplerOut->getCouplingContextId()].push_back(couplerOut) ;
1893      for(auto couplerIn : enabledCouplerIn) listCouplerIn[couplerIn->getCouplingContextId()].push_back(couplerIn) ;
1894
1895      CCouplerManager* couplerManager = CXios::getCouplerManager() ;
1896      if (rank==0)
1897      {
1898        for(auto couplerOut : listCouplerOut) couplerManager->registerCoupling(this->getContextId(),couplerOut.first) ;
1899        for(auto couplerIn : listCouplerIn) couplerManager->registerCoupling(couplerIn.first,this->getContextId()) ;
1900      }
1901
1902      do
1903      {
1904        for(auto couplerOut : listCouplerOut) 
1905        {
1906          bool isNextCoupling ;
1907          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(this->getContextId(),couplerOut.first) ;
1908          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
1909          if (isNextCoupling) 
1910          {
1911            addCouplingChanel(couplerOut.first, true) ;
1912            listCouplerOut.erase(couplerOut.first) ;
1913            break ;
1914          }           
1915        }
1916        for(auto couplerIn : listCouplerIn) 
1917        {
1918          bool isNextCoupling ;
1919          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(couplerIn.first,this->getContextId());
1920          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
1921          if (isNextCoupling) 
1922          {
1923            addCouplingChanel(couplerIn.first, false) ;
1924            listCouplerIn.erase(couplerIn.first) ;
1925            break ;
1926          }           
1927        }
1928
1929      } while (!listCouplerOut.empty() || !listCouplerIn.empty()) ;
1930
1931   }
1932   CATCH_DUMP_ATTR
1933
1934 
1935     //! Client side: Send infomation of active files (files are enabled to write out)
1936   void CContext::sendEnabledFiles(const std::vector<CFile*>& activeFiles)
1937   TRY
1938   {
1939     int size = activeFiles.size();
1940
1941     // In a context, each type has a root definition, e.g: axis, domain, field.
1942     // Every object must be a child of one of these root definition. In this case
1943     // all new file objects created on server must be children of the root "file_definition"
1944     StdString fileDefRoot("file_definition");
1945     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1946
1947     for (int i = 0; i < size; ++i)
1948     {
1949       CFile* f = activeFiles[i];
1950       cfgrpPtr->sendCreateChild(f->getId(),f->getContextClient());
1951       f->sendAllAttributesToServer(f->getContextClient());
1952       f->sendAddAllVariables(f->getContextClient());
1953     }
1954   }
1955   CATCH_DUMP_ATTR
1956
1957   //! Client side: Send information of active fields (ones are written onto files)
1958   void CContext::sendEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
1959   TRY
1960   {
1961     int size = activeFiles.size();
1962     for (int i = 0; i < size; ++i)
1963     {
1964       activeFiles[i]->sendEnabledFields(activeFiles[i]->getContextClient());
1965     }
1966   }
1967   CATCH_DUMP_ATTR
1968
1969 
1970   //! Client side: Prepare the timeseries by adding the necessary files
1971   void CContext::prepareTimeseries()
1972   TRY
1973   {
1974     const std::vector<CFile*> allFiles = CFile::getAll();
1975     for (size_t i = 0; i < allFiles.size(); i++)
1976     {
1977       CFile* file = allFiles[i];
1978
1979       std::vector<CVariable*> fileVars, fieldVars, vars = file->getAllVariables();
1980       for (size_t k = 0; k < vars.size(); k++)
1981       {
1982         CVariable* var = vars[k];
1983
1984         if (var->ts_target.isEmpty()
1985              || var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both)
1986           fileVars.push_back(var);
1987
1988         if (!var->ts_target.isEmpty()
1989              && (var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both))
1990           fieldVars.push_back(var);
1991       }
1992
1993       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1994       {
1995         StdString fileNameStr("%file_name%") ;
1996         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : fileNameStr ;
1997         
1998         StdString fileName=file->getFileOutputName();
1999         size_t pos=tsPrefix.find(fileNameStr) ;
2000         while (pos!=std::string::npos)
2001         {
2002           tsPrefix=tsPrefix.replace(pos,fileNameStr.size(),fileName) ;
2003           pos=tsPrefix.find(fileNameStr) ;
2004         }
2005       
2006         const std::vector<CField*> allFields = file->getAllFields();
2007         for (size_t j = 0; j < allFields.size(); j++)
2008         {
2009           CField* field = allFields[j];
2010
2011           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
2012           {
2013             CFile* tsFile = CFile::create();
2014             tsFile->duplicateAttributes(file);
2015
2016             // Add variables originating from file and targeted to timeserie file
2017             for (size_t k = 0; k < fileVars.size(); k++)
2018               tsFile->getVirtualVariableGroup()->addChild(fileVars[k]);
2019
2020           
2021             tsFile->name = tsPrefix + "_";
2022             if (!field->name.isEmpty())
2023               tsFile->name.get() += field->name;
2024             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
2025               tsFile->name.get() += field->field_ref;
2026             else
2027               tsFile->name.get() += field->getId();
2028
2029             if (!field->ts_split_freq.isEmpty())
2030               tsFile->split_freq = field->ts_split_freq;
2031
2032             CField* tsField = tsFile->addField();
2033             tsField->field_ref = field->getId();
2034
2035             // Add variables originating from file and targeted to timeserie field
2036             for (size_t k = 0; k < fieldVars.size(); k++)
2037               tsField->getVirtualVariableGroup()->addChild(fieldVars[k]);
2038
2039             vars = field->getAllVariables();
2040             for (size_t k = 0; k < vars.size(); k++)
2041             {
2042               CVariable* var = vars[k];
2043
2044               // Add variables originating from field and targeted to timeserie field
2045               if (var->ts_target.isEmpty()
2046                    || var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both)
2047                 tsField->getVirtualVariableGroup()->addChild(var);
2048
2049               // Add variables originating from field and targeted to timeserie file
2050               if (!var->ts_target.isEmpty()
2051                    && (var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both))
2052                 tsFile->getVirtualVariableGroup()->addChild(var);
2053             }
2054
2055             tsFile->solveFieldRefInheritance(true);
2056
2057             if (file->timeseries == CFile::timeseries_attr::exclusive)
2058               field->enabled = false;
2059           }
2060         }
2061
2062         // Finally disable the original file is need be
2063         if (file->timeseries == CFile::timeseries_attr::only)
2064          file->enabled = false;
2065       }
2066     }
2067   }
2068   CATCH_DUMP_ATTR
2069
2070 
2071   //! Client side: Send information of reference domain, axis and scalar of active fields
2072   void CContext::sendRefDomainsAxisScalars(const std::vector<CFile*>& activeFiles)
2073   TRY
2074   {
2075     std::set<pair<StdString,CContextClient*>> domainIds, axisIds, scalarIds;
2076
2077     // Find all reference domain and axis of all active fields
2078     int numEnabledFiles = activeFiles.size();
2079     for (int i = 0; i < numEnabledFiles; ++i)
2080     {
2081       std::vector<CField*> enabledFields = activeFiles[i]->getEnabledFields();
2082       int numEnabledFields = enabledFields.size();
2083       for (int j = 0; j < numEnabledFields; ++j)
2084       {
2085         CContextClient* contextClient=enabledFields[j]->getContextClient() ;
2086         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
2087         if ("" != prDomAxisScalarId[0]) domainIds.insert(make_pair(prDomAxisScalarId[0],contextClient));
2088         if ("" != prDomAxisScalarId[1]) axisIds.insert(make_pair(prDomAxisScalarId[1],contextClient));
2089         if ("" != prDomAxisScalarId[2]) scalarIds.insert(make_pair(prDomAxisScalarId[2],contextClient));
2090       }
2091     }
2092
2093     // Create all reference axis on server side
2094     std::set<StdString>::iterator itDom, itAxis, itScalar;
2095     std::set<StdString>::const_iterator itE;
2096
2097     StdString scalarDefRoot("scalar_definition");
2098     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
2099     
2100     for (auto itScalar = scalarIds.begin(); itScalar != scalarIds.end(); ++itScalar)
2101     {
2102       if (!itScalar->first.empty())
2103       {
2104         scalarPtr->sendCreateChild(itScalar->first,itScalar->second);
2105         CScalar::get(itScalar->first)->sendAllAttributesToServer(itScalar->second);
2106       }
2107     }
2108
2109     StdString axiDefRoot("axis_definition");
2110     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
2111     
2112     for (auto itAxis = axisIds.begin(); itAxis != axisIds.end(); ++itAxis)
2113     {
2114       if (!itAxis->first.empty())
2115       {
2116         axisPtr->sendCreateChild(itAxis->first, itAxis->second);
2117         CAxis::get(itAxis->first)->sendAllAttributesToServer(itAxis->second);
2118       }
2119     }
2120
2121     // Create all reference domains on server side
2122     StdString domDefRoot("domain_definition");
2123     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
2124     
2125     for (auto itDom = domainIds.begin(); itDom != domainIds.end(); ++itDom)
2126     {
2127       if (!itDom->first.empty()) {
2128          domPtr->sendCreateChild(itDom->first, itDom->second);
2129          CDomain::get(itDom->first)->sendAllAttributesToServer(itDom->second);
2130       }
2131     }
2132   }
2133   CATCH_DUMP_ATTR
2134
2135   void CContext::triggerLateFields(void)
2136   TRY
2137   {
2138    for(auto& field : fileInFields_) field->triggerLateField() ;
2139    for(auto& field : couplerInFields_) field->triggerLateField() ;
2140   }
2141   CATCH_DUMP_ATTR
2142
2143   //! Update calendar in each time step
2144   void CContext::updateCalendar(int step)
2145   TRY
2146   {
2147      int prevStep = calendar->getStep();
2148
2149      if (prevStep < step)
2150      {
2151        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2152        {
2153          triggerLateFields();
2154        }
2155
2156        info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
2157        calendar->update(step);
2158        info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
2159  #ifdef XIOS_MEMTRACK_LIGHT
2160        info(50) << " Current memory used by XIOS : "<<  MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte, at timestep "<<step<<" of context "<<this->getId()<<endl ;
2161  #endif
2162
2163        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2164        {
2165          doPostTimestepOperationsForEnabledReadModeFiles();
2166          garbageCollector.invalidate(calendar->getCurrentDate());
2167        }
2168      }
2169      else if (prevStep == step)
2170        info(50) << "updateCalendar: already at step " << step << ", no operation done." << endl;
2171      else // if (prevStep > step)
2172        ERROR("void CContext::updateCalendar(int step)",
2173              << "Illegal calendar update: previous step was " << prevStep << ", new step " << step << "is in the past!")
2174   }
2175   CATCH_DUMP_ATTR
2176
2177   void CContext::initReadFiles(void)
2178   TRY
2179   {
2180      vector<CFile*>::const_iterator it;
2181
2182      for (it=enabledReadModeFiles.begin(); it != enabledReadModeFiles.end(); it++)
2183      {
2184         (*it)->initRead();
2185      }
2186   }
2187   CATCH_DUMP_ATTR
2188
2189   //! Server side: Create header of netcdf file
2190   void CContext::createFileHeader(void)
2191   TRY
2192   {
2193      vector<CFile*>::const_iterator it;
2194
2195      //for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
2196      for (it=enabledWriteModeFiles.begin(); it != enabledWriteModeFiles.end(); it++)
2197      {
2198         (*it)->initWrite();
2199      }
2200   }
2201   CATCH_DUMP_ATTR
2202
2203   //! Get current context
2204   CContext* CContext::getCurrent(void)
2205   TRY
2206   {
2207     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
2208   }
2209   CATCH
2210
2211   /*!
2212   \brief Set context with an id be the current context
2213   \param [in] id identity of context to be set to current
2214   */
2215   void CContext::setCurrent(const string& id)
2216   TRY
2217   {
2218     CObjectFactory::SetCurrentContextId(id);
2219     CGroupFactory::SetCurrentContextId(id);
2220   }
2221   CATCH
2222
2223  /*!
2224  \brief Create a context with specific id
2225  \param [in] id identity of new context
2226  \return pointer to the new context or already-existed one with identity id
2227  */
2228  CContext* CContext::create(const StdString& id)
2229  TRY
2230  {
2231    CContext::setCurrent(id);
2232
2233    bool hasctxt = CContext::has(id);
2234    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
2235    getRoot();
2236    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
2237
2238#define DECLARE_NODE(Name_, name_) \
2239    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
2240#define DECLARE_NODE_PAR(Name_, name_)
2241#include "node_type.conf"
2242
2243    return (context);
2244  }
2245  CATCH
2246
2247     //! Server side: Receive a message to do some post processing
2248  void CContext::recvRegistry(CEventServer& event)
2249  TRY
2250  {
2251    CBufferIn* buffer=event.subEvents.begin()->buffer;
2252    getCurrent()->recvRegistry(*buffer);
2253  }
2254  CATCH
2255
2256  void CContext::recvRegistry(CBufferIn& buffer)
2257  TRY
2258  {
2259    if (server->intraCommRank==0)
2260    {
2261      CRegistry registry(server->intraComm) ;
2262      registry.fromBuffer(buffer) ;
2263      registryOut->mergeRegistry(registry) ;
2264    }
2265  }
2266  CATCH_DUMP_ATTR
2267
2268  void CContext::sendRegistry(void)
2269  TRY
2270  {
2271    registryOut->hierarchicalGatherRegistry() ;
2272
2273    int nbSrvPools ;
2274    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
2275    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
2276    else nbSrvPools = 0 ;
2277    CContextClient* contextClientTmp ;
2278
2279    for (int i = 0; i < nbSrvPools; ++i)
2280    {
2281      if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
2282      else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
2283
2284      CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
2285      if (contextClientTmp->isServerLeader())
2286      {
2287        CMessage msg ;
2288        if (contextClientTmp->clientRank==0) msg<<*registryOut ;
2289        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
2290        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2291             event.push(*itRank,1,msg);
2292        contextClientTmp->sendEvent(event);
2293      }
2294      else contextClientTmp->sendEvent(event);
2295    }
2296  }
2297  CATCH_DUMP_ATTR
2298
2299 
2300  void CContext::sendFinalizeClient(CContextClient* contextClient, const string& contextClientId)
2301  TRY
2302  {
2303    CEventClient event(getType(),EVENT_ID_CONTEXT_FINALIZE_CLIENT);
2304    if (contextClient->isServerLeader())
2305    {
2306      CMessage msg;
2307      msg<<contextClientId ;
2308      const std::list<int>& ranks = contextClient->getRanksServerLeader();
2309      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2310           event.push(*itRank,1,msg);
2311      contextClient->sendEvent(event);
2312    }
2313    else contextClient->sendEvent(event);
2314  }
2315  CATCH_DUMP_ATTR
2316
2317 
2318  void CContext::recvFinalizeClient(CEventServer& event)
2319  TRY
2320  {
2321    CBufferIn* buffer=event.subEvents.begin()->buffer;
2322    string id;
2323    *buffer>>id;
2324    get(id)->recvFinalizeClient(*buffer);
2325  }
2326  CATCH
2327
2328  void CContext::recvFinalizeClient(CBufferIn& buffer)
2329  TRY
2330  {
2331    countChildContextFinalized_++ ;
2332  }
2333  CATCH_DUMP_ATTR
2334
2335
2336
2337
2338 //! Client side: Send a message  announcing that context can receive grid definition from coupling
2339   void CContext::sendCouplerInReady(CContextClient* client)
2340   TRY
2341   {
2342      if (sendCouplerInReady_done_.count(client)!=0) return ;
2343      else sendCouplerInReady_done_.insert(client) ;
2344
2345      CEventClient event(getType(),EVENT_ID_COUPLER_IN_READY);
2346
2347      if (client->isServerLeader())
2348      {
2349        CMessage msg;
2350        msg<<this->getId();
2351        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2352        client->sendEvent(event);
2353      }
2354      else client->sendEvent(event);
2355   }
2356   CATCH_DUMP_ATTR
2357
2358   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2359   void CContext::recvCouplerInReady(CEventServer& event)
2360   TRY
2361   {
2362      CBufferIn* buffer=event.subEvents.begin()->buffer;
2363      getCurrent()->recvCouplerInReady(*buffer);
2364   }
2365   CATCH
2366
2367   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2368   void CContext::recvCouplerInReady(CBufferIn& buffer)
2369   TRY
2370   {
2371      string contextId ;
2372      buffer>>contextId;
2373      couplerInReady_.insert(getCouplerOutClient(contextId)) ;
2374   }
2375   CATCH_DUMP_ATTR
2376
2377
2378
2379
2380
2381 //! Client side: Send a message  announcing that a coupling context have done it closeDefinition, so data can be sent now.
2382   void CContext::sendCouplerInCloseDefinition(CContextClient* client)
2383   TRY
2384   {
2385      if (sendCouplerInCloseDefinition_done_.count(client)!=0) return ;
2386      else sendCouplerInCloseDefinition_done_.insert(client) ;
2387
2388      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CLOSE_DEFINITION);
2389
2390      if (client->isServerLeader())
2391      {
2392        CMessage msg;
2393        msg<<this->getId();
2394        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2395        client->sendEvent(event);
2396      }
2397      else client->sendEvent(event);
2398   }
2399   CATCH_DUMP_ATTR
2400
2401   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2402   void CContext::recvCouplerInCloseDefinition(CEventServer& event)
2403   TRY
2404   {
2405      CBufferIn* buffer=event.subEvents.begin()->buffer;
2406      getCurrent()->recvCouplerInCloseDefinition(*buffer);
2407   }
2408   CATCH
2409
2410   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2411   void CContext::recvCouplerInCloseDefinition(CBufferIn& buffer)
2412   TRY
2413   {
2414      string contextId ;
2415      buffer>>contextId;
2416      couplerInCloseDefinition_.insert(getCouplerOutClient(contextId)) ;
2417   }
2418   CATCH_DUMP_ATTR
2419
2420
2421
2422
2423//! Client side: Send a message  announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2424   void CContext::sendCouplerInContextFinalized(CContextClient* client)
2425   TRY
2426   {
2427      if (sendCouplerInContextFinalized_done_.count(client)!=0) return ;
2428      else sendCouplerInContextFinalized_done_.insert(client) ;
2429
2430      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED);
2431
2432      if (client->isServerLeader())
2433      {
2434        CMessage msg;
2435        msg<<this->getId();
2436        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2437        client->sendEvent(event);
2438      }
2439      else client->sendEvent(event);
2440   }
2441   CATCH_DUMP_ATTR
2442
2443   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2444   void CContext::recvCouplerInContextFinalized(CEventServer& event)
2445   TRY
2446   {
2447      CBufferIn* buffer=event.subEvents.begin()->buffer;
2448      getCurrent()->recvCouplerInContextFinalized(*buffer);
2449   }
2450   CATCH
2451
2452   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2453   void CContext::recvCouplerInContextFinalized(CBufferIn& buffer)
2454   TRY
2455   {
2456      string contextId ;
2457      buffer>>contextId;
2458      couplerInContextFinalized_.insert(getCouplerOutClient(contextId)) ;
2459   }
2460   CATCH_DUMP_ATTR
2461
2462
2463
2464
2465  /*!
2466  * \fn bool CContext::isFinalized(void)
2467  * Context is finalized if it received context post finalize event.
2468  */
2469  bool CContext::isFinalized(void)
2470  TRY
2471  {
2472    return finalized;
2473  }
2474  CATCH_DUMP_ATTR
2475  ///--------------------------------------------------------------
2476  StdString CContext::dumpClassAttributes(void)
2477  {
2478    StdString str;
2479    str.append("enabled files=\"");
2480    int size = this->enabledFiles.size();
2481    for (int i = 0; i < size; ++i)
2482    {
2483      str.append(enabledFiles[i]->getId());
2484      str.append(" ");
2485    }
2486    str.append("\"");
2487    return str;
2488  }
2489
2490} // namespace xios
Note: See TracBrowser for help on using the repository browser.