source: XIOS3/trunk/src/node/context.cpp @ 2564

Last change on this file since 2564 was 2564, checked in by jderouillat, 10 months ago

Clean memory leaks

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