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

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

XIOS coupling branch
Adopt infrastructure based on filter for reading data on server side and sending it to the client, in a similar way on what is done for other case.

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