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

Last change on this file since 2605 was 2605, checked in by jderouillat, 7 months ago

Reader finalization (p2p) requires ContextClient? and ContextServer? to be active

  • 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.7 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::map<StdString,CContext*> def_map =
225         CContext::getRoot()->getChildMap();
226      std::map<StdString,CContext*>::iterator
227         it = def_map.begin(), end = def_map.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->second;
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    xios::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, false)) 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      xios::MPI_Comm_dup(intraComm_, &intraCommServer) ;
601      CXios::getMpiGarbageCollector().registerCommunicator(intraCommServer) ;
602
603      CContextClient* client = CContextClient::getNew(this, intraCommClient, interCommClient) ;
604      CContextServer* server = CContextServer::getNew(this, intraCommServer, interCommServer) ;
605      client->setAssociatedServer(server) ;
606      server->setAssociatedClient(client) ;
607     
608      clientServers.push_back({fullServerId,{client,server}}) ;
609      clientsId_[client] = fullServerId ;
610      serversId_[server] = fullServerId ;
611    }
612    setCurrent(getId()) ; // Back on main context
613  }
614  CATCH_DUMP_ATTR
615 
616 
617  // obsolete
618  void CContext::createServerInterComm(void) 
619  TRY
620  {
621    vector<pair<string, pair<CContextClient*,CContextServer*>>> clientServers ;
622
623    if (serviceType_ == CServicesManager::CLIENT)
624    {
625      if (CXios::usingServer2) createServerInterComm(CXios::defaultPoolId, CXios::defaultGathererId, clientServers) ;
626      else createServerInterComm(CXios::defaultPoolId, CXios::defaultWriterId, clientServers) ;
627     
628      writerClientOut_.push_back(clientServers[0].second.first) ; 
629      writerServerOut_.push_back(clientServers[0].second.second) ;
630
631      clientServers.clear() ;
632   
633      createServerInterComm(CXios::defaultPoolId, CXios::defaultReaderId, clientServers) ;
634      readerClientOut_.push_back(clientServers[0].second.first) ; 
635      readerServerOut_.push_back(clientServers[0].second.second) ;
636
637
638    }
639    else if (serviceType_ == CServicesManager::GATHERER)
640    {
641      createServerInterComm(CXios::defaultPoolId, CXios::defaultWriterId, clientServers) ;
642      for(auto& clientServer : clientServers)
643      {
644        writerClientOut_.push_back(clientServer.second.first) ; 
645        writerServerOut_.push_back(clientServer.second.second) ;
646      }
647    }
648
649  }
650  CATCH_DUMP_ATTR
651
652 
653  void CContext::getServerInterComm(const string& poolId, const string& serviceId,  vector<pair<CContextClient*,CContextServer*>>& clientServers)
654  {
655    vector<pair<string, pair<CContextClient*,CContextServer*>>> retClientServers ;
656
657    auto it=serversMap_.find(make_pair(poolId,serviceId)) ;
658    if (it!=serversMap_.end()) clientServers=it->second ;
659    else
660    {
661      createServerInterComm(poolId, serviceId, retClientServers) ;
662      for(auto& retClientServer : retClientServers)  clientServers.push_back(retClientServer.second) ;
663     
664      int serviceType ;
665      if (intraCommRank_==0) while(!CXios::getServicesManager()->getServiceType(poolId, serviceId, 0, serviceType)) yield(); 
666      synchronize() ;
667      MPI_Bcast(&serviceType,1,MPI_INT,0,intraComm_) ;
668     
669      for(auto& clientServer : clientServers)     
670      {
671        if (serviceType==CServicesManager::WRITER) { writerClientOut_.push_back(clientServer.first)      ; writerServerOut_.push_back(clientServer.second) ; }
672        else if (serviceType==CServicesManager::READER) { readerClientOut_.push_back(clientServer.first) ; readerServerOut_.push_back(clientServer.second) ; }
673        else if (serviceType==CServicesManager::GATHERER) { writerClientOut_.push_back(clientServer.first) ; writerServerOut_.push_back(clientServer.second) ; }
674      }
675      serversMap_.insert(make_pair(make_pair(poolId,serviceId),clientServers)) ;
676    }
677
678  }
679
680  vector<CContextClient*> CContext::getContextClient(const string& poolId, const string& serviceId)
681  {
682     vector<CContextClient*> ret ;
683   
684    if (serviceId=="attached") ret.push_back(onlineContextClient_) ;
685    else
686    {
687      vector<pair<CContextClient*,CContextServer*>> clientServers ;
688      getServerInterComm(poolId, serviceId, clientServers ) ;
689      for(auto& clientServer : clientServers) ret.push_back(clientServer.first) ;
690    }
691    return ret ;
692  }
693
694
695  void CContext::globalEventLoop(void)
696  {
697    if (CThreadManager::isUsingThreads()) CThreadManager::yield();
698    else
699    {
700      lockContext() ;
701      CXios::getDaemonsManager()->eventLoop() ;
702      unlockContext() ;
703      setCurrent(getId()) ;
704    }
705  }
706
707  void CContext::yield(void)
708  {
709    if (CThreadManager::isUsingThreads()) 
710    {
711      CThreadManager::yield();
712      setCurrent(getId()) ;
713    }
714    else
715    {
716      lockContext() ;
717      CXios::getDaemonsManager()->eventLoop() ;
718      unlockContext() ;
719      setCurrent(getId()) ;
720    }
721  }
722
723  void CContext::synchronize(void)
724  {
725    bool out, finished; 
726    size_t timeLine=timeLine_ ;
727     
728    timeLine_++ ;
729    eventScheduler_->registerEvent(timeLine, hashId_) ;
730     
731    out = eventScheduler_->queryEvent(timeLine,hashId_) ;
732    if (out) eventScheduler_->popEvent() ;
733    while (!out)
734    {
735      yield() ;
736      out = eventScheduler_->queryEvent(timeLine,hashId_) ;
737      if (out) eventScheduler_->popEvent() ;
738    }
739  }
740 
741  bool CContext::scheduledEventLoop(bool enableEventsProcessing) 
742  {
743    bool out, finished; 
744    size_t timeLine=timeLine_ ;
745    if (serviceType_==CServicesManager::CLIENT)
746    {
747      timeLine_++ ;
748      eventScheduler_->registerEvent(timeLine, hashId_) ;
749    }
750
751    do
752    { 
753      finished=eventLoop(enableEventsProcessing) ;
754      if (serviceType_==CServicesManager::CLIENT) 
755      { 
756        out = eventScheduler_->queryEvent(timeLine,hashId_) ;
757        if (out) eventScheduler_->popEvent() ;
758      }
759
760      else out=true ;
761    }  while(!out) ;
762   
763    return finished ;
764  }
765
766  bool CContext::eventLoop(bool enableEventsProcessing)
767  {
768    bool  finished(true); 
769    if (isLockedContext()) enableEventsProcessing=false;
770   
771    setCurrent(getId()) ;
772
773    if (!finalized)
774    {
775      for(auto client : writerClientOut_) client->eventLoop();
776      for(auto server : writerServerOut_) finished &= server->eventLoop(enableEventsProcessing);
777      for(auto client : writerClientIn_) client->eventLoop();
778      for(auto server : writerServerIn_) finished &= server->eventLoop(enableEventsProcessing);
779      for(auto client : readerClientOut_) client->eventLoop();
780      for(auto server : readerServerOut_) finished &= server->eventLoop(enableEventsProcessing);
781      for(auto client : readerClientIn_) client->eventLoop();
782      for(auto server : readerServerIn_) finished &= server->eventLoop(enableEventsProcessing);
783      for(auto couplerOut : couplerOutClient_) couplerOut.second->eventLoop();
784      for(auto couplerIn : couplerInClient_) couplerIn.second->eventLoop();
785      //for(auto couplerOut : couplerOutServer_) couplerOut.second->eventLoop(enableEventsProcessing);
786      //for(auto couplerIn : couplerInServer_) couplerIn.second->eventLoop(enableEventsProcessing);
787      for(auto couplerOut : couplerOutServer_) couplerOut.second->eventLoop();
788      for(auto couplerIn : couplerInServer_) couplerIn.second->eventLoop();
789    }
790    setCurrent(getId()) ;
791    return finalized && finished ;
792  }
793
794  void CContext::addCouplingChanel(const std::string& fullContextId, bool out)
795  {
796     int contextLeader ;
797     
798     if (out)
799     { 
800       if (couplerOutClient_.find(fullContextId)==couplerOutClient_.end()) 
801       {
802         while(!CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm())) yield();
803         synchronize() ;
804     
805         MPI_Comm interComm, interCommClient, interCommServer  ;
806         MPI_Comm intraCommClient, intraCommServer ;
807
808         xios::MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
809
810        xios::MPI_Comm_dup(intraComm_, &intraCommClient) ;
811        xios::MPI_Comm_dup(intraComm_, &intraCommServer) ;
812        xios::MPI_Comm_dup(interComm, &interCommClient) ;
813        xios::MPI_Comm_dup(interComm, &interCommServer) ;
814        CContextClient* client = CContextClient::getNew(this, intraCommClient, interCommClient);
815             
816        CContextServer* server = CContextServer::getNew(this, intraCommServer, interCommServer);
817        client->setAssociatedServer(server) ;
818        server->setAssociatedClient(client) ;
819        xios::MPI_Comm_free(&interComm) ;
820        couplerOutClient_[fullContextId] = client ;
821        couplerOutServer_[fullContextId] = server ;
822      }
823    }
824    else if (couplerInClient_.find(fullContextId)==couplerInClient_.end())
825    {
826      while(!CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm())) yield() ;
827      synchronize() ;
828     
829       MPI_Comm interComm, interCommClient, interCommServer  ;
830       MPI_Comm intraCommClient, intraCommServer ;
831
832       xios::MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
833
834       xios::MPI_Comm_dup(intraComm_, &intraCommClient) ;
835       xios::MPI_Comm_dup(intraComm_, &intraCommServer) ;
836       xios::MPI_Comm_dup(interComm, &interCommServer) ;
837       xios::MPI_Comm_dup(interComm, &interCommClient) ;
838       CContextServer* server = CContextServer::getNew(this, intraCommServer, interCommServer);
839       CContextClient* client = CContextClient::getNew(this, intraCommClient, interCommClient);
840       client->setAssociatedServer(server) ;
841       server->setAssociatedClient(client) ;
842       xios::MPI_Comm_free(&interComm) ;
843
844       couplerInClient_[fullContextId] = client ;
845       couplerInServer_[fullContextId] = server ;       
846    }
847  }
848 
849   void CContext::finalize(void)
850   TRY
851   {
852      registryOut->hierarchicalGatherRegistry() ;
853      if (intraCommRank_==0) CXios::getRegistryManager()->merge(*registryOut) ;
854
855      if (serviceType_==CServicesManager::CLIENT)
856      {
857        triggerLateFields() ;
858
859        // inform couplerIn that I am finished
860        for(auto& couplerInClient : couplerInClient_) sendCouplerInContextFinalized(couplerInClient.second) ;
861
862        // wait until received message from couplerOut that they have finished
863        bool couplersInFinalized ;
864        do
865        {
866          couplersInFinalized=true ;
867          for(auto& couplerOutClient : couplerOutClient_) couplersInFinalized &= isCouplerInContextFinalized(couplerOutClient.second) ; 
868          if (CThreadManager::isUsingThreads()) yield() ;
869          else globalEventLoop() ;
870        } while (!couplersInFinalized) ;
871
872        CContextClient* client ;
873        CContextServer* server ;
874
875        /*
876        if (writerClientOut_.size()!=0)
877        {
878          client=writerClientOut_[0] ;
879          server=writerServerOut_[0] ;
880
881          info(100)<<"DEBUG: context "<<getId()<<" Send client finalize to writer"<<endl ;
882          client->finalize();
883          info(100)<<"DEBUG: context "<<getId()<<" Client finalize sent to writer"<<endl ;
884          while (client->havePendingRequests()) client->eventLoop();
885          info(100)<<"DEBUG: context "<<getId()<<" no pending request on writer ok"<<endl ;
886          bool notifiedFinalized=false ;
887          do
888          {
889            notifiedFinalized = client->isNotifiedFinalized() ;
890          } while (!notifiedFinalized) ;
891
892          server->releaseBuffers();
893          client->releaseBuffers();
894          info(100)<<"DEBUG: context "<<getId()<<" release client writer ok"<<endl ;
895        }
896        */
897
898        for(int n=0; n<writerClientOut_.size() ; n++)
899        {
900          client=writerClientOut_[n] ;
901          server=writerServerOut_[n] ;
902
903          info(100)<<"DEBUG: context "<<getId()<<" Send client finalize to writer"<<endl ;
904          client->finalize();
905          info(100)<<"DEBUG: context "<<getId()<<" Client finalize sent to writer"<<endl ;
906          bool bufferReleased;
907          do
908          {
909            client->eventLoop();
910            bufferReleased = !client->havePendingRequests();
911          } while (!bufferReleased);
912          info(100)<<"DEBUG: context "<<getId()<<" no pending request on writer ok"<<endl ;
913
914          bool notifiedFinalized=false ;
915          do
916          {
917            notifiedFinalized=client->isNotifiedFinalized() ;
918          } while (!notifiedFinalized) ;
919          server->releaseBuffers();
920          client->releaseBuffers();
921          info(100)<<"DEBUG: context "<<getId()<<" release client writer ok"<<endl ;
922        }
923       
924
925        if (readerClientOut_.size()!=0)
926        {
927          client=readerClientOut_[0] ;
928          server=readerServerOut_[0] ;
929
930          info(100)<<"DEBUG: context "<<getId()<<" Send client finalize to reader"<<endl ;
931          client->finalize();
932          info(100)<<"DEBUG: context "<<getId()<<" Client finalize sent to reader"<<endl ;
933          while (client->havePendingRequests()) client->eventLoop();
934          info(100)<<"DEBUG: context "<<getId()<<" no pending request on reader ok"<<endl ;
935          bool notifiedFinalized=false ;
936         do
937         {
938            client->eventLoop();
939            server-> eventLoop();
940            notifiedFinalized = client->isNotifiedFinalized() ;
941         }   while (!notifiedFinalized) ;
942         bool pendingEvent=true;
943         do
944         {
945            server-> eventLoop();
946            pendingEvent = server->hasPendingEvent() ;
947         }   while (pendingEvent) ;
948
949          server->releaseBuffers();
950          client->releaseBuffers();
951          info(100)<<"DEBUG: context "<<getId()<<" release client reader ok"<<endl ;
952        }
953        closeAllFile() ;
954      }
955      else if (serviceType_==CServicesManager::GATHERER)
956      {
957        CContextClient* client ;
958        CContextServer* server ;
959       
960        for(int n=0; n<writerClientOut_.size() ; n++)
961        {
962          client=writerClientOut_[n] ;
963          server=writerServerOut_[n] ;
964       
965          client->finalize();
966          bool bufferReleased;
967          do
968          {
969            client->eventLoop();
970            bufferReleased = !client->havePendingRequests();
971          } while (!bufferReleased);
972           
973          bool notifiedFinalized=false ;
974          do
975          {
976            notifiedFinalized=client->isNotifiedFinalized() ;
977          } while (!notifiedFinalized) ;
978          server->releaseBuffers();
979          client->releaseBuffers();
980         }
981         closeAllFile();
982         writerClientIn_[0]->releaseBuffers();
983         writerServerIn_[0]->releaseBuffers();         
984         //ym writerClientIn & writerServerIn not released here ==> to check !!
985      }
986      else if (serviceType_==CServicesManager::WRITER)
987      {
988        closeAllFile();
989        writerClientIn_[0]->releaseBuffers();
990        writerServerIn_[0]->releaseBuffers();
991      }
992      else if (serviceType_==CServicesManager::READER)
993      {
994        closeAllFile();
995        readerClientIn_[0]->releaseBuffers();
996        readerServerIn_[0]->releaseBuffers();
997      }
998
999      freeComms() ;
1000       
1001      parentServerContext_->freeComm() ;
1002      finalized = true;
1003      info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl;
1004   }
1005   CATCH_DUMP_ATTR
1006
1007   //! Free internally allocated communicators
1008   void CContext::freeComms(void)
1009   TRY
1010   {
1011     for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
1012       xios::MPI_Comm_free(&(*it));
1013     comms.clear();
1014   }
1015   CATCH_DUMP_ATTR
1016
1017   
1018   void CContext::setDefaultServices(void)
1019   {
1020     if (!CXios::isUsingServer())
1021     {
1022       defaultPoolWriterId_ = CXios::defaultPoolId ;
1023       defaultPoolReaderId_ = CXios::defaultPoolId ;
1024       defaultPoolGathererId_ = CXios::defaultPoolId ;
1025       defaultWriterId_ = "attached" ;
1026       defaultReaderId_ = "attached" ;
1027       defaultGathererId_ =  "attached" ;
1028       defaultUsingServer2_ = false;
1029     }
1030     else
1031     {
1032       defaultPoolWriterId_ = CXios::defaultPoolId ;
1033       defaultPoolReaderId_ = CXios::defaultPoolId ;
1034       defaultPoolGathererId_ = CXios::defaultPoolId ;
1035       defaultWriterId_ = CXios::defaultWriterId ;
1036       defaultReaderId_ = CXios::defaultReaderId ;
1037       defaultGathererId_ = CXios::defaultGathererId ;
1038       defaultUsingServer2_ = CXios::usingServer2 ;
1039     
1040       if (!default_pool.isEmpty())  defaultPoolWriterId_ = defaultPoolReaderId_= defaultPoolGathererId_= default_pool ;
1041       if (!default_pool_writer.isEmpty()) defaultPoolWriterId_ = default_pool_writer ;
1042       if (!default_pool_reader.isEmpty()) defaultPoolReaderId_ = default_pool_reader ;
1043       if (!default_pool_gatherer.isEmpty()) defaultPoolGathererId_ = default_pool_gatherer ;
1044       if (!default_writer.isEmpty()) defaultWriterId_ = default_writer ;
1045       if (!default_reader.isEmpty()) defaultWriterId_ = default_reader ;
1046       if (!default_gatherer.isEmpty()) defaultGathererId_ = default_gatherer ;
1047       if (!default_using_server2.isEmpty()) defaultUsingServer2_ = default_using_server2 ;
1048     }
1049   }
1050
1051   /*!
1052   \brief Close all the context defintion and do processing data
1053      After everything is well defined on client side, they will be processed and sent to server
1054   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
1055   all necessary information to server, from which each server can build its own database.
1056   Because the role of server is to write out field data on a specific netcdf file,
1057   the only information that it needs is the enabled files
1058   and the active fields (fields will be written onto active files)
1059   */
1060  void CContext::closeDefinition(void)
1061   TRY
1062   {
1063     CMemChecker::logMem( "CContext::closeDefinition" );
1064
1065     CTimer::get("Context : close definition").resume() ;
1066
1067     onlineContextClient_=CContextClient::getNew<CContextClient::online>(this,intraComm_, intraComm_);
1068         
1069     // create intercommunicator with servers.
1070     // not sure it is the good place to be called here
1071     //createServerInterComm() ;
1072
1073
1074     // After xml is parsed, there are some more works with post processing
1075//     postProcessing();
1076
1077   
1078    // Make sure the calendar was correctly created
1079    if (serviceType_!=CServicesManager::CLIENT) CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
1080    if (!calendar)
1081      ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
1082    else if (calendar->getTimeStep() == NoneDu)
1083      ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
1084    // Calendar first update to set the current date equals to the start date
1085    calendar->update(0);
1086
1087    // Résolution des héritages descendants (càd des héritages de groupes)
1088    // pour chacun des contextes.
1089    solveDescInheritance(true);
1090    setDefaultServices() ;
1091    // Check if some axis, domains or grids are eligible to for compressed indexed output.
1092    // Warning: This must be done after solving the inheritance and before the rest of post-processing
1093    // --> later ????    checkAxisDomainsGridsEligibilityForCompressedOutput();     
1094
1095      // Check if some automatic time series should be generated
1096      // Warning: This must be done after solving the inheritance and before the rest of post-processing     
1097
1098    // The timeseries should only be prepared in client
1099    prepareTimeseries();
1100
1101    //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
1102    findEnabledFiles();
1103
1104    // Solve inheritance for field to know if enabled or not.
1105    for (auto field : CField::getAll()) field->solveRefInheritance();
1106
1107    findEnabledWriteModeFiles();
1108    findEnabledReadModeFiles();
1109    findEnabledCouplerIn();
1110    findEnabledCouplerOut();
1111    createCouplerInterCommunicator() ;
1112
1113    // Find all enabled fields of each file     
1114    vector<CField*>&& fileOutField = findAllEnabledFieldsInFileOut(this->enabledWriteModeFiles);
1115    vector<CField*>&& fileInField = findAllEnabledFieldsInFileIn(this->enabledReadModeFiles);
1116    vector<CField*>&& couplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut);
1117    vector<CField*>&& couplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn);
1118    findFieldsWithReadAccess();
1119    vector<CField*>& fieldWithReadAccess = fieldsWithReadAccess_ ;
1120    vector<CField*> fieldModelIn ; // fields potentially from model
1121
1122    // define if files are on clientSied or serverSide
1123    if (serviceType_==CServicesManager::CLIENT)
1124    {
1125      for (auto& file : enabledWriteModeFiles) file->setClientSide() ;
1126      for (auto& file : enabledReadModeFiles) file->setClientSide() ;
1127    }
1128    else
1129    {
1130      for (auto& file : enabledWriteModeFiles) file->setServerSide() ;
1131      for (auto& file : enabledReadModeFiles) file->setServerSide() ;
1132    }
1133
1134   
1135    for (auto& field : couplerInField)
1136    {
1137      field->unsetGridCompleted() ;
1138    }
1139// find all field potentially at workflow end
1140    vector<CField*> endWorkflowFields ;
1141    endWorkflowFields.reserve(fileOutField.size()+couplerOutField.size()+fieldWithReadAccess.size()) ;
1142    endWorkflowFields.insert(endWorkflowFields.end(),fileOutField.begin(), fileOutField.end()) ;
1143    endWorkflowFields.insert(endWorkflowFields.end(),couplerOutField.begin(), couplerOutField.end()) ;
1144    endWorkflowFields.insert(endWorkflowFields.end(),fieldWithReadAccess.begin(), fieldWithReadAccess.end()) ;
1145
1146    bool workflowGraphIsCompleted ;
1147   
1148    bool first=true ;
1149   
1150    do
1151    {
1152      workflowGraphIsCompleted=true; 
1153      for(auto endWorkflowField : endWorkflowFields) 
1154      {
1155        workflowGraphIsCompleted &= endWorkflowField->buildWorkflowGraph(garbageCollector) ;
1156      }
1157   
1158      for(auto couplerIn : enabledCouplerIn) couplerIn->assignContext() ;
1159      for(auto field : couplerInField) field->makeGridAliasForCoupling();
1160      for(auto field : couplerInField) this->sendCouplerInReady(field->getContextClient()) ;
1161   
1162
1163      // assign context to coupler out and related fields
1164      for(auto couplerOut : enabledCouplerOut) couplerOut->assignContext() ;
1165      // for now supose that all coupling out endpoint are succesfull. The difficultie is client/server buffer evaluation
1166      for(auto field : couplerOutField) 
1167      {
1168        // connect to couplerOut -> to do
1169      }
1170
1171      bool couplersReady ;
1172      do 
1173      {
1174        couplersReady=true ;
1175        for(auto field : couplerOutField)
1176        {
1177          bool ready = isCouplerInReady(field->getContextClient()) ; 
1178          if (ready) field->sendFieldToCouplerOut() ;
1179          couplersReady &= ready ;
1180        }
1181        this->scheduledEventLoop() ;
1182
1183      } while (!couplersReady) ;
1184     
1185      first=false ;
1186      this->scheduledEventLoop() ;
1187
1188    } while (!workflowGraphIsCompleted) ;
1189
1190
1191    for( auto field : couplerInField) couplerInFields_.push_back(field) ;
1192
1193    // get all field coming potentially from model
1194    for (auto field : CField::getAll() ) if (field->getModelIn()) fieldModelIn.push_back(field) ;
1195
1196    // Distribute files between secondary servers according to the data size => assign a context to a file and then to fields
1197   
1198    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) distributeFiles(this->enabledWriteModeFiles) ;
1199    /*
1200    if (serviceType_==CServicesManager::CLIENT )
1201    {   
1202      if (CXios::usingServer2) distributeFiles(this->enabledWriteModeFiles, defaultPoolGathererId_, defaultGathererId_);
1203      else distributeFiles(this->enabledWriteModeFiles, defaultPoolWriterId_, defaultWriterId_);
1204    }
1205    if (serviceType_==CServicesManager::GATHERER ) distributeFiles(this->enabledWriteModeFiles, defaultPoolWriterId_, defaultWriterId_);
1206    */
1207
1208    // client side, assign context for file reading
1209//    if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledReadModeFiles) file->setContextClient(readerClientOut_[0]) ;
1210    if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledReadModeFiles) 
1211    {
1212      string poolReaderId ;
1213      string readerId ;
1214      file->getReaderServicesId(defaultPoolReaderId_, defaultReaderId_, poolReaderId, readerId) ;
1215      file->setContextClient(poolReaderId, readerId, 0) ;
1216    }
1217
1218    // server side, assign context where to send file data read
1219    if (serviceType_==CServicesManager::READER) for(auto file : this->enabledReadModeFiles) file->setContextClient(readerClientIn_[0]) ;
1220   
1221
1222    // workflow startpoint => data from server on client side
1223    // important : sendFieldToInputFileServer must be done prior sendFieldToFileServer because for the first case the grid remoteConnectorIn
1224    //             and grid remoteConnectorOut will be computed, and in the second case only the remoteConnectorOut.
1225    if (serviceType_==CServicesManager::CLIENT)
1226    {
1227      for(auto field : fileInField) 
1228        if (field->getContextClient()->getType() != CContextClient::online) field->sendFieldToInputFileServer() ;
1229
1230      for(auto field : fileInField) 
1231      {
1232        if (field->getContextClient()->getType() == CContextClient::online) field->connectToOnlineReader(garbageCollector) ;
1233        else field->connectToServerInput(garbageCollector) ; // connect the field to server filter
1234        fileInFields_.push_back(field) ;
1235      }
1236    }
1237
1238    // workflow endpoint => sent to IO/SERVER
1239    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER)
1240    {
1241      for(auto field : fileOutField) 
1242      {
1243        if (field->getContextClient()->getType() == CContextClient::online)  field->connectToOnlineWriter(garbageCollector) ;
1244        else  field->connectToFileServer(garbageCollector) ; // connect the field to server filter
1245      }
1246      for(auto field : fileOutField) 
1247        if (field->getContextClient()->getType() != CContextClient::online) field->sendFieldToFileServer() ;
1248    }
1249
1250    // workflow endpoint => write to file
1251    if (serviceType_==CServicesManager::WRITER)
1252    {
1253      for(auto field : fileOutField) 
1254      {
1255        field->connectToFileWriter(garbageCollector) ; // connect the field to server filter
1256      }
1257    }
1258   
1259    // workflow endpoint => Send data from server to client
1260    if (serviceType_==CServicesManager::READER || serviceType_==CServicesManager::GATHERER)
1261    {
1262      for(auto field : fileInField) 
1263      {
1264        if (field->getContextClient()->getType() == CContextClient::online) field->connectToOnlineReader(garbageCollector) ;
1265        else field->connectToServerToClient(garbageCollector) ;
1266      }
1267    }
1268
1269    // workflow endpoint => sent to model on client side
1270    if (serviceType_==CServicesManager::CLIENT)
1271    {
1272      for(auto field : fieldWithReadAccess) field->connectToModelOutput(garbageCollector) ;
1273    }
1274
1275
1276    // workflow startpoint => data from model
1277    if (serviceType_==CServicesManager::CLIENT)
1278    {
1279      for(auto field : fieldModelIn) 
1280      {
1281        field->connectToModelInput(garbageCollector) ; // connect the field to server filter
1282        // grid index will be computed on the fly
1283      }
1284    }
1285   
1286    // workflow startpoint => data from client on server side
1287    if (serviceType_==CServicesManager::WRITER || serviceType_==CServicesManager::GATHERER)
1288    {
1289      for(auto field : fieldModelIn) 
1290      {
1291        field->connectToClientInput(garbageCollector) ; // connect the field to server filter
1292      }
1293    }
1294
1295   
1296    for(auto field : couplerInField) 
1297    {
1298      field->connectToCouplerIn(garbageCollector) ; // connect the field to server filter
1299    }
1300   
1301   
1302    for(auto field : couplerOutField) 
1303    {
1304      field->connectToCouplerOut(garbageCollector) ; // for now the same kind of filter that for file server
1305    }
1306
1307    // workflow startpoint => data read from file on server side
1308    if (serviceType_==CServicesManager::READER)
1309    {
1310      for(auto field : fileInField) 
1311      {
1312        field->connectToFileReader(garbageCollector) ;
1313      }
1314    }
1315   
1316    // construct slave server list
1317    map<string, CContextClient*> slaves ; // need an ordered list ;
1318    if (serviceType_==CServicesManager::CLIENT) 
1319    {
1320      for(auto field : fileOutField)
1321        if (field->getContextClient()->getType()!=CContextClient::online)  slaves[clientsId_[field->getContextClient()]] = field->getContextClient() ; 
1322      for(auto field : fileInField) 
1323        if (field->getContextClient()->getType()!=CContextClient::online)  slaves[clientsId_[field->getContextClient()]] = field->getContextClient() ; 
1324    }
1325    else if (serviceType_==CServicesManager::GATHERER) 
1326      for(auto field : fileOutField) slaves[clientsId_[field->getContextClient()]] = field->getContextClient() ;
1327    for(auto& slave : slaves) slaveServers_.push_back(slave.second) ;   
1328
1329
1330    for(auto& slaveServer : slaveServers_) sendCloseDefinition(slaveServer) ;
1331
1332    createFileHeader();
1333   
1334    //if (serviceType_==CServicesManager::CLIENT) startPrefetchingOfEnabledReadModeFiles();
1335    if (serviceType_==CServicesManager::CLIENT) 
1336       for(auto field : fileInField) field->sendReadDataRequest(getCalendar()->getCurrentDate()); 
1337   
1338    // send signal to couplerIn context that definition phasis is done
1339
1340    for(auto& couplerInClient : couplerInClient_) sendCouplerInCloseDefinition(couplerInClient.second) ;
1341
1342    // wait until all couplerIn signal that closeDefition is done.
1343    bool ok;
1344    do
1345    {
1346      ok = true ;
1347      for(auto& couplerOutClient : couplerOutClient_) ok &= isCouplerInCloseDefinition(couplerOutClient.second) ;
1348      this->scheduledEventLoop() ;
1349    } while (!ok) ;
1350
1351    // Now evaluate the size of the context client buffers
1352    map<CContextClient*,map<int,size_t>> fieldBufferEvaluation ;
1353    for(auto field : fileOutField) field->evaluateBufferSize(fieldBufferEvaluation, CXios::isOptPerformance) ; // output to server
1354    for(auto field : couplerOutField) field->evaluateBufferSize(fieldBufferEvaluation, CXios::isOptPerformance) ; // output to coupler
1355    for(auto field : fileInField) field->evaluateBufferSize(fieldBufferEvaluation, CXios::isOptPerformance) ; // server to client (for io servers)
1356   
1357    // fix size for each context client
1358    for(auto& it : fieldBufferEvaluation) it.first->setBufferSize(it.second) ;
1359
1360
1361     CTimer::get("Context : close definition").suspend() ;
1362     CMemChecker::logMem( "CContext::closeDefinition_END" );
1363  }
1364  CATCH_DUMP_ATTR
1365
1366
1367  vector<CField*> CContext::findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles)
1368   TRY
1369   {
1370     vector<CField*> fields ;
1371     for(auto file : activeFiles)
1372     {
1373        const vector<CField*>&& fieldList=file->getEnabledFields() ;
1374        for(auto field : fieldList) field->setFileOut(file) ;
1375        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1376     }
1377     return fields ;
1378   }
1379   CATCH_DUMP_ATTR
1380
1381   vector<CField*> CContext::findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles)
1382   TRY
1383   {
1384     vector<CField*> fields ;
1385     for(auto file : activeFiles)
1386     {
1387        const vector<CField*>&& fieldList=file->getEnabledFields() ;
1388        for(auto field : fieldList) field->setFileIn(file) ;
1389        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1390     }
1391     return fields ;
1392   }
1393   CATCH_DUMP_ATTR
1394
1395   vector<CField*> CContext::findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut)
1396   TRY
1397   {
1398     vector<CField*> fields ;
1399     for (auto couplerOut :activeCouplerOut)
1400     {
1401        const vector<CField*>&& fieldList=couplerOut->getEnabledFields() ;
1402        for(auto field : fieldList) field->setCouplerOut(couplerOut) ;
1403        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1404     }
1405     return fields ;
1406   }
1407   CATCH_DUMP_ATTR
1408
1409   vector<CField*> CContext::findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn)
1410   TRY
1411   {
1412     vector<CField*> fields ;
1413     for (auto couplerIn :activeCouplerIn)
1414     {
1415        const vector<CField*>&& fieldList=couplerIn->getEnabledFields() ;
1416        for(auto field : fieldList) field->setCouplerIn(couplerIn) ;
1417        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
1418     }
1419     return fields ;
1420   }
1421   CATCH_DUMP_ATTR
1422
1423 /*!
1424  * Send context attribute and calendar to file server, it must be done once by context file server
1425  * \param[in] client : context client to send   
1426  */ 
1427  void CContext::sendContextToFileServer(CContextClient* client)
1428  {
1429    if (sendToFileServer_done_.count(client)!=0) return ;
1430    else sendToFileServer_done_.insert(client) ;
1431   
1432    this->sendAllAttributesToServer(client); // Send all attributes of current context to server
1433    CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(client); // Send all attributes of current cale
1434  }
1435
1436 
1437   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
1438   TRY
1439   {
1440      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
1441        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
1442   }
1443   CATCH_DUMP_ATTR
1444
1445   void CContext::startPrefetchingOfEnabledReadModeFiles()
1446   TRY
1447   {
1448     int size = enabledReadModeFiles.size();
1449     for (int i = 0; i < size; ++i)
1450     {
1451        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
1452     }
1453   }
1454   CATCH_DUMP_ATTR
1455
1456   void CContext::doPostTimestepOperationsForEnabledReadModeFiles()
1457   TRY
1458   {
1459     int size = enabledReadModeFiles.size();
1460     for (int i = 0; i < size; ++i)
1461     {
1462        enabledReadModeFiles[i]->doPostTimestepOperationsForEnabledReadModeFields();
1463     }
1464   }
1465   CATCH_DUMP_ATTR
1466
1467  void CContext::findFieldsWithReadAccess(void)
1468  TRY
1469  {
1470    fieldsWithReadAccess_.clear();
1471    const vector<CField*> allFields = CField::getAll();
1472    for (size_t i = 0; i < allFields.size(); ++i)
1473    {
1474      CField* field = allFields[i];
1475      if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
1476      {
1477        fieldsWithReadAccess_.push_back(field);
1478        field->setModelOut() ;
1479      }
1480    }
1481  }
1482  CATCH_DUMP_ATTR
1483
1484 
1485   void CContext::solveAllInheritance(bool apply)
1486   TRY
1487   {
1488     // Résolution des héritages descendants (càd des héritages de groupes)
1489     // pour chacun des contextes.
1490      solveDescInheritance(apply);
1491
1492     // Résolution des héritages par référence au niveau des fichiers.
1493      const vector<CFile*> allFiles=CFile::getAll();
1494      const vector<CCouplerIn*> allCouplerIn=CCouplerIn::getAll();
1495      const vector<CCouplerOut*> allCouplerOut=CCouplerOut::getAll();
1496      const vector<CGrid*> allGrids= CGrid::getAll();
1497
1498      if (serviceType_==CServicesManager::CLIENT)
1499      {
1500        for (unsigned int i = 0; i < allFiles.size(); i++)
1501          allFiles[i]->solveFieldRefInheritance(apply);
1502
1503        for (unsigned int i = 0; i < allCouplerIn.size(); i++)
1504          allCouplerIn[i]->solveFieldRefInheritance(apply);
1505
1506        for (unsigned int i = 0; i < allCouplerOut.size(); i++)
1507          allCouplerOut[i]->solveFieldRefInheritance(apply);
1508      }
1509
1510      unsigned int vecSize = allGrids.size();
1511      unsigned int i = 0;
1512      for (i = 0; i < vecSize; ++i)
1513        allGrids[i]->solveElementsRefInheritance(apply);
1514
1515   }
1516  CATCH_DUMP_ATTR
1517
1518   void CContext::findEnabledFiles(void)
1519   TRY
1520   {
1521      const std::vector<CFile*> allFiles = CFile::getAll();
1522      const CDate& initDate = calendar->getInitDate();
1523
1524      for (unsigned int i = 0; i < allFiles.size(); i++)
1525         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
1526         {
1527            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
1528            {
1529              if (allFiles[i]->output_freq.isEmpty())
1530              {
1531                 ERROR("CContext::findEnabledFiles()",
1532                     << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1533                     <<" \".")
1534              }
1535              if ((initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1536              {
1537                error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1538                    << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1539                    <<"\" is less than the time step. File will not be written."<<endl;
1540              }
1541              else
1542               enabledFiles.push_back(allFiles[i]);
1543            }
1544            else // Si l'attribut 'enabled' est fixé à faux.
1545            {
1546              // disabled all fields contained in file (used in findFieldsWithReadAccess through field_ref dependencies)
1547              const vector<CField*>&& fieldList=allFiles[i]->getEnabledFields() ;
1548              for(auto field : fieldList) field->enabled.setValue(false);
1549            }
1550         }
1551         else
1552         {
1553           if (allFiles[i]->output_freq.isEmpty())
1554           {
1555              ERROR("CContext::findEnabledFiles()",
1556                  << "Mandatory attribute output_freq must be defined for file \""<<allFiles[i]->getFileOutputName()
1557                  <<" \".")
1558           }
1559           if ( (initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep()))
1560           {
1561             error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl
1562                 << "Output frequency in file \""<<allFiles[i]->getFileOutputName()
1563                 <<"\" is less than the time step. File will not be written."<<endl;
1564           }
1565           else
1566             enabledFiles.push_back(allFiles[i]); // otherwise true by default
1567         }
1568
1569      if (enabledFiles.size() == 0)
1570         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
1571               << getId() << "\" !");
1572
1573   }
1574   CATCH_DUMP_ATTR
1575
1576   void CContext::findEnabledCouplerIn(void)
1577   TRY
1578   {
1579      const std::vector<CCouplerIn*> allCouplerIn = CCouplerIn::getAll();
1580      bool enabled ;
1581      for (size_t i = 0; i < allCouplerIn.size(); i++)
1582      {
1583        if (allCouplerIn[i]->enabled.isEmpty()) enabled=true ;
1584        else enabled=allCouplerIn[i]->enabled ;
1585        if (enabled) enabledCouplerIn.push_back(allCouplerIn[i]) ;
1586      }
1587   }
1588   CATCH_DUMP_ATTR
1589
1590   void CContext::findEnabledCouplerOut(void)
1591   TRY
1592   {
1593      const std::vector<CCouplerOut*> allCouplerOut = CCouplerOut::getAll();
1594      bool enabled ;
1595      for (size_t i = 0; i < allCouplerOut.size(); i++)
1596      {
1597        if (allCouplerOut[i]->enabled.isEmpty()) enabled=true ;
1598        else enabled=allCouplerOut[i]->enabled ;
1599        if (enabled) enabledCouplerOut.push_back(allCouplerOut[i]) ;
1600      }
1601   }
1602   CATCH_DUMP_ATTR
1603
1604
1605
1606
1607   void CContext::distributeFiles(const vector<CFile*>& files)
1608   TRY
1609   {
1610     map< pair<string,string>, vector<CFile*>> fileMaps ;
1611     for(auto& file : files)
1612     {
1613       string poolWriterId ;
1614       string poolGathererId ;
1615       string writerId  ;
1616       string gathererId  ;
1617       bool usingServer2 ;
1618
1619       file->getWriterServicesId(defaultUsingServer2_, defaultPoolWriterId_, defaultWriterId_, defaultPoolGathererId_, defaultGathererId_,
1620                                 usingServer2, poolWriterId, writerId, poolGathererId, gathererId) ;
1621       if (serviceType_==CServicesManager::CLIENT && usingServer2) fileMaps[make_pair(poolGathererId,gathererId)].push_back(file) ;
1622       else fileMaps[make_pair(poolWriterId,writerId)].push_back(file) ;
1623     }
1624     for(auto& it : fileMaps) distributeFilesOnSameService(it.second, it.first.first, it.first.second) ;
1625   }
1626   CATCH_DUMP_ATTR
1627
1628
1629   void CContext::distributeFilesOnSameService(const vector<CFile*>& files, const string& poolId, const string& serviceId)
1630   TRY
1631   {
1632     bool distFileMemory=false ;
1633     distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory);
1634
1635     auto writers = getContextClient(poolId, serviceId) ;
1636     int  nbPools = writers.size() ;
1637     
1638     if (nbPools==1) distributeFileOverOne(files, poolId, serviceId) ;
1639     else if (distFileMemory) distributeFileOverMemoryBandwith(files, poolId, serviceId) ;
1640     else distributeFileOverBandwith(files, poolId, serviceId) ;
1641   }
1642   CATCH_DUMP_ATTR
1643
1644   void CContext::distributeFileOverOne(const vector<CFile*>& files, const string& poolId, const string& serviceId)
1645   TRY
1646   {
1647     for(auto& file : files) file->setContextClient(poolId, serviceId,0) ;
1648   }
1649   CATCH_DUMP_ATTR
1650
1651   void CContext::distributeFileOverBandwith(const vector<CFile*>& files, const string& poolId, const string& serviceId)
1652   TRY
1653   {
1654     double eps=std::numeric_limits<double>::epsilon()*10 ;
1655     
1656     std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out);
1657     auto writers = getContextClient(poolId, serviceId) ;
1658     int nbPools = writers.size();
1659     //int nbPools = writerClientOut_.size();
1660
1661     // (1) Find all enabled files in write mode
1662     // for (int i = 0; i < this->enabledFiles.size(); ++i)
1663     // {
1664     //   if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1665     //    enabledWriteModeFiles.push_back(enabledFiles[i]);
1666     // }
1667
1668     // (2) Estimate the data volume for each file
1669     int size = files.size();
1670     std::vector<std::pair<double, CFile*> > dataSizeMap;
1671     double dataPerPool = 0;
1672     int nfield=0 ;
1673     ofs<<size<<endl ;
1674     for (size_t i = 0; i < size; ++i)
1675     {
1676       CFile* file = files[i];
1677       ofs<<file->getId()<<endl ;
1678       StdSize dataSize=0;
1679       std::vector<CField*> enabledFields = file->getEnabledFields();
1680       size_t numEnabledFields = enabledFields.size();
1681       ofs<<numEnabledFields<<endl ;
1682       for (size_t j = 0; j < numEnabledFields; ++j)
1683       {
1684         dataSize += enabledFields[j]->getGlobalWrittenSize() ;
1685         ofs<<enabledFields[j]->getGrid()->getId()<<endl ;
1686         ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ;
1687       }
1688       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1689       double dataSizeSec= dataSize/ outFreqSec;
1690       ofs<<dataSizeSec<<endl ;
1691       nfield++ ;
1692// add epsilon*nField to dataSizeSec in order to  preserve reproductive ordering when sorting
1693       dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file));
1694       dataPerPool += dataSizeSec;
1695     }
1696     dataPerPool /= nbPools;
1697     std::sort(dataSizeMap.begin(), dataSizeMap.end());
1698
1699     // (3) Assign contextClient to each enabled file
1700
1701     std::multimap<double,int> poolDataSize ;
1702// multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11
1703
1704     int j;
1705     double dataSize ;
1706     for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ; 
1707             
1708     for (int i = dataSizeMap.size()-1; i >= 0; --i)
1709     {
1710       dataSize=(*poolDataSize.begin()).first ;
1711       j=(*poolDataSize.begin()).second ;
1712       dataSizeMap[i].second->setContextClient(poolId, serviceId, j);
1713       dataSize+=dataSizeMap[i].first;
1714       poolDataSize.erase(poolDataSize.begin()) ;
1715       poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 
1716     }
1717
1718     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 ;
1719   }
1720   CATCH_DUMP_ATTR
1721
1722   void CContext::distributeFileOverMemoryBandwith(const vector<CFile*>& filesList, const string& poolId, const string& serviceId)
1723   TRY
1724   {
1725     auto writers = getContextClient(poolId, serviceId) ;
1726     int nbPools = writers.size();
1727   
1728     double ratio=0.5 ;
1729     ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio);
1730
1731     int nFiles = filesList.size();
1732     vector<SDistFile> files(nFiles);
1733     vector<SDistGrid> grids;
1734     map<string,int> gridMap ;
1735     string gridId; 
1736     int gridIndex=0 ;
1737
1738     for (size_t i = 0; i < nFiles; ++i)
1739     {
1740       StdSize dataSize=0;
1741       CFile* file = filesList[i];
1742       std::vector<CField*> enabledFields = file->getEnabledFields();
1743       size_t numEnabledFields = enabledFields.size();
1744
1745       files[i].id_=file->getId() ;
1746       files[i].nbGrids_=numEnabledFields;
1747       files[i].assignedGrid_ = new int[files[i].nbGrids_] ;
1748         
1749       for (size_t j = 0; j < numEnabledFields; ++j)
1750       {
1751         gridId=enabledFields[j]->getGrid()->getId() ;
1752         if (gridMap.find(gridId)==gridMap.end())
1753         {
1754            gridMap[gridId]=gridIndex  ;
1755            SDistGrid newGrid; 
1756            grids.push_back(newGrid) ;
1757            gridIndex++ ;
1758         }
1759         files[i].assignedGrid_[j]=gridMap[gridId] ;
1760         grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ;
1761         dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull
1762       }
1763       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
1764       files[i].bandwith_= dataSize/ outFreqSec ;
1765     }
1766
1767     double bandwith=0 ;
1768     double memory=0 ;
1769   
1770     for(int i=0; i<nFiles; i++)  bandwith+=files[i].bandwith_ ;
1771     for(int i=0; i<nFiles; i++)  files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ;
1772
1773     for(int i=0; i<grids.size(); i++)  memory+=grids[i].size_ ;
1774     for(int i=0; i<grids.size(); i++)  grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ;
1775       
1776     distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ;
1777
1778     vector<double> memorySize(nbPools,0.) ;
1779     vector< set<int> > serverGrids(nbPools) ;
1780     vector<double> bandwithSize(nbPools,0.) ;
1781       
1782     for (size_t i = 0; i < nFiles; ++i)
1783     {
1784       bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ;
1785       for(int j=0 ; j<files[i].nbGrids_;j++)
1786       {
1787         if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end())
1788         {
1789           memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio);
1790           serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ;
1791         }
1792       }
1793       filesList[i]->setContextClient(poolId, serviceId, files[i].assignedServer_) ;
1794       delete [] files[i].assignedGrid_ ;
1795     }
1796
1797     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 ;
1798     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ;
1799
1800   }
1801   CATCH_DUMP_ATTR
1802
1803   /*!
1804      Find all files in write mode
1805   */
1806   void CContext::findEnabledWriteModeFiles(void)
1807   TRY
1808   {
1809     int size = this->enabledFiles.size();
1810     for (int i = 0; i < size; ++i)
1811     {
1812       if (enabledFiles[i]->mode.isEmpty() || 
1813          (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
1814        enabledWriteModeFiles.push_back(enabledFiles[i]);
1815     }
1816   }
1817   CATCH_DUMP_ATTR
1818
1819   /*!
1820      Find all files in read mode
1821   */
1822   void CContext::findEnabledReadModeFiles(void)
1823   TRY
1824   {
1825     int size = this->enabledFiles.size();
1826     for (int i = 0; i < size; ++i)
1827     {
1828       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
1829        enabledReadModeFiles.push_back(enabledFiles[i]);
1830     }
1831   }
1832   CATCH_DUMP_ATTR
1833
1834   void CContext::closeAllFile(void)
1835   TRY
1836   {
1837     std::vector<CFile*>::const_iterator
1838            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
1839
1840     for (; it != end; it++)
1841     {
1842       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
1843       (*it)->close();
1844     }
1845   }
1846   CATCH_DUMP_ATTR
1847
1848   /*!
1849   \brief Dispatch event received from client
1850      Whenever a message is received in buffer of server, it will be processed depending on
1851   its event type. A new event type should be added in the switch list to make sure
1852   it processed on server side.
1853   \param [in] event: Received message
1854   */
1855   bool CContext::dispatchEvent(CEventServer& event)
1856   TRY
1857   {
1858
1859      if (SuperClass::dispatchEvent(event)) return true;
1860      else
1861      {
1862        switch(event.type)
1863        {
1864           case EVENT_ID_CLOSE_DEFINITION :
1865             recvCloseDefinition(event);
1866             return true;
1867             break;
1868           case EVENT_ID_UPDATE_CALENDAR:
1869             recvUpdateCalendar(event);
1870             return true;
1871             break;
1872           case EVENT_ID_COUPLER_IN_READY:
1873             recvCouplerInReady(event);
1874             return true;
1875             break;
1876           case EVENT_ID_COUPLER_IN_CLOSE_DEFINITION:
1877             recvCouplerInCloseDefinition(event);
1878             return true;
1879             break;
1880           case EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED:
1881             recvCouplerInContextFinalized(event);
1882             return true;
1883             break; 
1884           default :
1885             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
1886                    <<"Unknown Event");
1887           return false;
1888         }
1889      }
1890   }
1891   CATCH
1892
1893   //  ! Client side: Send a message to server to make it close
1894   void CContext::sendCloseDefinition(CContextClient* client)
1895   TRY
1896   {
1897      if (sendCloseDefinition_done_.count(client)!=0) return ;
1898      else sendCloseDefinition_done_.insert(client) ;
1899
1900      CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
1901      if (client->isServerLeader())
1902      {
1903        CMessage msg;
1904        for(auto rank : client->getRanksServerLeader()) event.push(rank,1,msg);
1905        client->sendEvent(event);
1906      }
1907     else client->sendEvent(event);
1908   }
1909   CATCH_DUMP_ATTR
1910
1911   //! Server side: Receive a message of client announcing a context close
1912   void CContext::recvCloseDefinition(CEventServer& event)
1913   TRY
1914   {
1915      CBufferIn* buffer=event.subEvents.begin()->buffer;
1916      getCurrent()->closeDefinition();
1917   }
1918   CATCH
1919
1920   //! Client side: Send a message to update calendar in each time step
1921   void CContext::sendUpdateCalendar(int step)
1922   TRY
1923   {
1924     for(auto client : slaveServers_) 
1925     {
1926       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
1927       if (client->isServerLeader())
1928       {
1929         CMessage msg;
1930         msg<<step;
1931         for (auto& rank : client->getRanksServerLeader() ) event.push(rank,1,msg);
1932         client->sendEvent(event);
1933       }
1934       else client->sendEvent(event);
1935     }
1936   }
1937   CATCH_DUMP_ATTR
1938
1939   //! Server side: Receive a message of client annoucing calendar update
1940   void CContext::recvUpdateCalendar(CEventServer& event)
1941   TRY
1942   {
1943      CBufferIn* buffer=event.subEvents.begin()->buffer;
1944      getCurrent()->recvUpdateCalendar(*buffer);
1945   }
1946   CATCH
1947
1948   //! Server side: Receive a message of client annoucing calendar update
1949   void CContext::recvUpdateCalendar(CBufferIn& buffer)
1950   TRY
1951   {
1952      int step;
1953      buffer>>step;
1954      updateCalendar(step);
1955      if (serviceType_==CServicesManager::GATHERER)
1956      {       
1957        sendUpdateCalendar(step);
1958      }
1959   }
1960   CATCH_DUMP_ATTR
1961
1962
1963   void CContext::createCouplerInterCommunicator(void)
1964   TRY
1965   {
1966      int rank=this->getIntraCommRank() ;
1967      map<string,list<CCouplerOut*>> listCouplerOut ; 
1968      map<string,list<CCouplerIn*>> listCouplerIn ; 
1969
1970      for(auto couplerOut : enabledCouplerOut) listCouplerOut[couplerOut->getCouplingContextId()].push_back(couplerOut) ;
1971      for(auto couplerIn : enabledCouplerIn) listCouplerIn[couplerIn->getCouplingContextId()].push_back(couplerIn) ;
1972
1973      CCouplerManager* couplerManager = CXios::getCouplerManager() ;
1974      if (rank==0)
1975      {
1976        for(auto couplerOut : listCouplerOut) couplerManager->registerCoupling(this->getContextId(),couplerOut.first) ;
1977        for(auto couplerIn : listCouplerIn) couplerManager->registerCoupling(couplerIn.first,this->getContextId()) ;
1978      }
1979
1980      do
1981      {
1982        for(auto couplerOut : listCouplerOut) 
1983        {
1984          bool isNextCoupling ;
1985          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(this->getContextId(),couplerOut.first) ;
1986          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
1987          if (isNextCoupling) 
1988          {
1989            addCouplingChanel(couplerOut.first, true) ;
1990            listCouplerOut.erase(couplerOut.first) ;
1991            break ;
1992          }           
1993        }
1994        for(auto couplerIn : listCouplerIn) 
1995        {
1996          bool isNextCoupling ;
1997          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(couplerIn.first,this->getContextId());
1998          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
1999          if (isNextCoupling) 
2000          {
2001            addCouplingChanel(couplerIn.first, false) ;
2002            listCouplerIn.erase(couplerIn.first) ;
2003            break ;
2004          }           
2005        }
2006
2007      } while (!listCouplerOut.empty() || !listCouplerIn.empty()) ;
2008
2009   }
2010   CATCH_DUMP_ATTR
2011
2012 
2013     //! Client side: Send infomation of active files (files are enabled to write out)
2014   void CContext::sendEnabledFiles(const std::vector<CFile*>& activeFiles)
2015   TRY
2016   {
2017     int size = activeFiles.size();
2018
2019     // In a context, each type has a root definition, e.g: axis, domain, field.
2020     // Every object must be a child of one of these root definition. In this case
2021     // all new file objects created on server must be children of the root "file_definition"
2022     StdString fileDefRoot("file_definition");
2023     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
2024
2025     for (int i = 0; i < size; ++i)
2026     {
2027       CFile* f = activeFiles[i];
2028       cfgrpPtr->sendCreateChild(f->getId(),f->getContextClient());
2029       f->sendAllAttributesToServer(f->getContextClient());
2030       f->sendAddAllVariables(f->getContextClient());
2031     }
2032   }
2033   CATCH_DUMP_ATTR
2034
2035   //! Client side: Send information of active fields (ones are written onto files)
2036   void CContext::sendEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
2037   TRY
2038   {
2039     int size = activeFiles.size();
2040     for (int i = 0; i < size; ++i)
2041     {
2042       activeFiles[i]->sendEnabledFields(activeFiles[i]->getContextClient());
2043     }
2044   }
2045   CATCH_DUMP_ATTR
2046
2047 
2048   //! Client side: Prepare the timeseries by adding the necessary files
2049   void CContext::prepareTimeseries()
2050   TRY
2051   {
2052     const std::vector<CFile*> allFiles = CFile::getAll();
2053     for (size_t i = 0; i < allFiles.size(); i++)
2054     {
2055       CFile* file = allFiles[i];
2056
2057       std::vector<CVariable*> fileVars, fieldVars, vars = file->getAllVariables();
2058       for (size_t k = 0; k < vars.size(); k++)
2059       {
2060         CVariable* var = vars[k];
2061
2062         if (var->ts_target.isEmpty()
2063              || var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both)
2064           fileVars.push_back(var);
2065
2066         if (!var->ts_target.isEmpty()
2067              && (var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both))
2068           fieldVars.push_back(var);
2069       }
2070
2071       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
2072       {
2073         StdString fileNameStr("%file_name%") ;
2074         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : fileNameStr ;
2075         
2076         StdString fileName=file->getFileOutputName();
2077         size_t pos=tsPrefix.find(fileNameStr) ;
2078         while (pos!=std::string::npos)
2079         {
2080           tsPrefix=tsPrefix.replace(pos,fileNameStr.size(),fileName) ;
2081           pos=tsPrefix.find(fileNameStr) ;
2082         }
2083       
2084         const std::vector<CField*> allFields = file->getAllFields();
2085         for (size_t j = 0; j < allFields.size(); j++)
2086         {
2087           CField* field = allFields[j];
2088
2089           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
2090           {
2091             CFile* tsFile = CFile::create();
2092             tsFile->duplicateAttributes(file);
2093
2094             // Add variables originating from file and targeted to timeserie file
2095             for (size_t k = 0; k < fileVars.size(); k++)
2096               tsFile->getVirtualVariableGroup()->addChild(fileVars[k]);
2097
2098           
2099             tsFile->name = tsPrefix + "_";
2100             if (!field->name.isEmpty())
2101               tsFile->name.get() += field->name;
2102             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
2103               tsFile->name.get() += field->field_ref;
2104             else
2105               tsFile->name.get() += field->getId();
2106
2107             if (!field->ts_split_freq.isEmpty())
2108               tsFile->split_freq = field->ts_split_freq;
2109
2110             CField* tsField = tsFile->addField();
2111             tsField->field_ref = field->getId();
2112
2113             // Add variables originating from file and targeted to timeserie field
2114             for (size_t k = 0; k < fieldVars.size(); k++)
2115               tsField->getVirtualVariableGroup()->addChild(fieldVars[k]);
2116
2117             vars = field->getAllVariables();
2118             for (size_t k = 0; k < vars.size(); k++)
2119             {
2120               CVariable* var = vars[k];
2121
2122               // Add variables originating from field and targeted to timeserie field
2123               if (var->ts_target.isEmpty()
2124                    || var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both)
2125                 tsField->getVirtualVariableGroup()->addChild(var);
2126
2127               // Add variables originating from field and targeted to timeserie file
2128               if (!var->ts_target.isEmpty()
2129                    && (var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both))
2130                 tsFile->getVirtualVariableGroup()->addChild(var);
2131             }
2132
2133             tsFile->solveFieldRefInheritance(true);
2134
2135             if (file->timeseries == CFile::timeseries_attr::exclusive)
2136               field->enabled = false;
2137           }
2138         }
2139
2140         // Finally disable the original file is need be
2141         if (file->timeseries == CFile::timeseries_attr::only)
2142          file->enabled = false;
2143       }
2144     }
2145   }
2146   CATCH_DUMP_ATTR
2147
2148 
2149   //! Client side: Send information of reference domain, axis and scalar of active fields
2150   void CContext::sendRefDomainsAxisScalars(const std::vector<CFile*>& activeFiles)
2151   TRY
2152   {
2153     std::set<pair<StdString,CContextClient*>> domainIds, axisIds, scalarIds;
2154
2155     // Find all reference domain and axis of all active fields
2156     int numEnabledFiles = activeFiles.size();
2157     for (int i = 0; i < numEnabledFiles; ++i)
2158     {
2159       std::vector<CField*> enabledFields = activeFiles[i]->getEnabledFields();
2160       int numEnabledFields = enabledFields.size();
2161       for (int j = 0; j < numEnabledFields; ++j)
2162       {
2163         CContextClient* contextClient=enabledFields[j]->getContextClient() ;
2164         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
2165         if ("" != prDomAxisScalarId[0]) domainIds.insert(make_pair(prDomAxisScalarId[0],contextClient));
2166         if ("" != prDomAxisScalarId[1]) axisIds.insert(make_pair(prDomAxisScalarId[1],contextClient));
2167         if ("" != prDomAxisScalarId[2]) scalarIds.insert(make_pair(prDomAxisScalarId[2],contextClient));
2168       }
2169     }
2170
2171     // Create all reference axis on server side
2172     std::set<StdString>::iterator itDom, itAxis, itScalar;
2173     std::set<StdString>::const_iterator itE;
2174
2175     StdString scalarDefRoot("scalar_definition");
2176     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
2177     
2178     for (auto itScalar = scalarIds.begin(); itScalar != scalarIds.end(); ++itScalar)
2179     {
2180       if (!itScalar->first.empty())
2181       {
2182         scalarPtr->sendCreateChild(itScalar->first,itScalar->second);
2183         CScalar::get(itScalar->first)->sendAllAttributesToServer(itScalar->second);
2184       }
2185     }
2186
2187     StdString axiDefRoot("axis_definition");
2188     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
2189     
2190     for (auto itAxis = axisIds.begin(); itAxis != axisIds.end(); ++itAxis)
2191     {
2192       if (!itAxis->first.empty())
2193       {
2194         axisPtr->sendCreateChild(itAxis->first, itAxis->second);
2195         CAxis::get(itAxis->first)->sendAllAttributesToServer(itAxis->second);
2196       }
2197     }
2198
2199     // Create all reference domains on server side
2200     StdString domDefRoot("domain_definition");
2201     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
2202     
2203     for (auto itDom = domainIds.begin(); itDom != domainIds.end(); ++itDom)
2204     {
2205       if (!itDom->first.empty()) {
2206          domPtr->sendCreateChild(itDom->first, itDom->second);
2207          CDomain::get(itDom->first)->sendAllAttributesToServer(itDom->second);
2208       }
2209     }
2210   }
2211   CATCH_DUMP_ATTR
2212
2213   void CContext::triggerLateFields(void)
2214   TRY
2215   {
2216    for(auto& field : fileInFields_) field->triggerLateField() ;
2217    for(auto& field : couplerInFields_) field->triggerLateField() ;
2218   }
2219   CATCH_DUMP_ATTR
2220
2221   //! Update calendar in each time step
2222   void CContext::updateCalendar(int step)
2223   TRY
2224   {
2225      int prevStep = calendar->getStep();
2226
2227      if (prevStep < step)
2228      {
2229        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2230        {
2231          triggerLateFields();
2232        }
2233
2234        info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
2235        calendar->update(step);
2236        info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
2237  #ifdef XIOS_MEMTRACK_LIGHT
2238        info(50) << " Current memory used by XIOS : "<<  MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte, at timestep "<<step<<" of context "<<this->getId()<<endl ;
2239  #endif
2240
2241        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
2242        {
2243         // doPostTimestepOperationsForEnabledReadModeFiles();
2244          for(auto& field : fileInFields_) field->sendReadDataRequestIfNeeded() ;
2245          garbageCollector.invalidate(calendar->getCurrentDate());
2246        }
2247        CMemChecker::logMem( "CContext::updateCalendar_"+std::to_string(step) );
2248      }
2249      else if (prevStep == step)
2250        info(50) << "updateCalendar: already at step " << step << ", no operation done." << endl;
2251      else // if (prevStep > step)
2252        ERROR("void CContext::updateCalendar(int step)",
2253              << "Illegal calendar update: previous step was " << prevStep << ", new step " << step << "is in the past!")
2254   }
2255   CATCH_DUMP_ATTR
2256
2257   void CContext::initReadFiles(void)
2258   TRY
2259   {
2260      vector<CFile*>::const_iterator it;
2261
2262      for (it=enabledReadModeFiles.begin(); it != enabledReadModeFiles.end(); it++)
2263      {
2264         (*it)->initRead();
2265      }
2266   }
2267   CATCH_DUMP_ATTR
2268
2269   //! Create header of netcdf file
2270   void CContext::createFileHeader(void)
2271   TRY
2272   {
2273      for(auto& file : filesToWrite_) file->initWrite();
2274   }
2275   CATCH_DUMP_ATTR
2276
2277   //! Get current context
2278   CContext* CContext::getCurrent(void)
2279   TRY
2280   {
2281     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
2282   }
2283   CATCH
2284
2285   /*!
2286   \brief Set context with an id be the current context
2287   \param [in] id identity of context to be set to current
2288   */
2289   void CContext::setCurrent(const string& id)
2290   TRY
2291   {
2292     CObjectFactory::SetCurrentContextId(id);
2293     CGroupFactory::SetCurrentContextId(id);
2294   }
2295   CATCH
2296
2297  /*!
2298  \brief Create a context with specific id
2299  \param [in] id identity of new context
2300  \return pointer to the new context or already-existed one with identity id
2301  */
2302  CContext* CContext::create(const StdString& id)
2303  TRY
2304  {
2305    CContext::setCurrent(id);
2306
2307    bool hasctxt = CContext::has(id);
2308    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
2309    getRoot();
2310    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
2311
2312#define DECLARE_NODE(Name_, name_) \
2313    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
2314#define DECLARE_NODE_PAR(Name_, name_)
2315#include "node_type.conf"
2316
2317    return (context);
2318  }
2319  CATCH
2320
2321 
2322  void CContext::sendFinalizeClient(CContextClient* contextClient, const string& contextClientId)
2323  TRY
2324  {
2325    CEventClient event(getType(),EVENT_ID_CONTEXT_FINALIZE_CLIENT);
2326    if (contextClient->isServerLeader())
2327    {
2328      CMessage msg;
2329      msg<<contextClientId ;
2330      const std::list<int>& ranks = contextClient->getRanksServerLeader();
2331      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
2332           event.push(*itRank,1,msg);
2333      contextClient->sendEvent(event);
2334    }
2335    else contextClient->sendEvent(event);
2336  }
2337  CATCH_DUMP_ATTR
2338
2339 
2340  void CContext::recvFinalizeClient(CEventServer& event)
2341  TRY
2342  {
2343    CBufferIn* buffer=event.subEvents.begin()->buffer;
2344    string id;
2345    *buffer>>id;
2346    get(id)->recvFinalizeClient(*buffer);
2347  }
2348  CATCH
2349
2350  void CContext::recvFinalizeClient(CBufferIn& buffer)
2351  TRY
2352  {
2353    countChildContextFinalized_++ ;
2354  }
2355  CATCH_DUMP_ATTR
2356
2357
2358
2359
2360 //! Client side: Send a message  announcing that context can receive grid definition from coupling
2361   void CContext::sendCouplerInReady(CContextClient* client)
2362   TRY
2363   {
2364      if (sendCouplerInReady_done_.count(client)!=0) return ;
2365      else sendCouplerInReady_done_.insert(client) ;
2366
2367      CEventClient event(getType(),EVENT_ID_COUPLER_IN_READY);
2368
2369      if (client->isServerLeader())
2370      {
2371        CMessage msg;
2372        msg<<this->getId();
2373        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2374        client->sendEvent(event);
2375      }
2376      else client->sendEvent(event);
2377   }
2378   CATCH_DUMP_ATTR
2379
2380   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2381   void CContext::recvCouplerInReady(CEventServer& event)
2382   TRY
2383   {
2384      CBufferIn* buffer=event.subEvents.begin()->buffer;
2385      getCurrent()->recvCouplerInReady(*buffer);
2386   }
2387   CATCH
2388
2389   //! Server side: Receive a message announcing that context can send grid definition for context coupling
2390   void CContext::recvCouplerInReady(CBufferIn& buffer)
2391   TRY
2392   {
2393      string contextId ;
2394      buffer>>contextId;
2395      couplerInReady_.insert(getCouplerOutClient(contextId)) ;
2396   }
2397   CATCH_DUMP_ATTR
2398
2399
2400
2401
2402
2403 //! Client side: Send a message  announcing that a coupling context have done it closeDefinition, so data can be sent now.
2404   void CContext::sendCouplerInCloseDefinition(CContextClient* client)
2405   TRY
2406   {
2407      if (sendCouplerInCloseDefinition_done_.count(client)!=0) return ;
2408      else sendCouplerInCloseDefinition_done_.insert(client) ;
2409
2410      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CLOSE_DEFINITION);
2411
2412      if (client->isServerLeader())
2413      {
2414        CMessage msg;
2415        msg<<this->getId();
2416        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2417        client->sendEvent(event);
2418      }
2419      else client->sendEvent(event);
2420   }
2421   CATCH_DUMP_ATTR
2422
2423   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2424   void CContext::recvCouplerInCloseDefinition(CEventServer& event)
2425   TRY
2426   {
2427      CBufferIn* buffer=event.subEvents.begin()->buffer;
2428      getCurrent()->recvCouplerInCloseDefinition(*buffer);
2429   }
2430   CATCH
2431
2432   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
2433   void CContext::recvCouplerInCloseDefinition(CBufferIn& buffer)
2434   TRY
2435   {
2436      string contextId ;
2437      buffer>>contextId;
2438      couplerInCloseDefinition_.insert(getCouplerOutClient(contextId)) ;
2439   }
2440   CATCH_DUMP_ATTR
2441
2442
2443
2444
2445//! Client side: Send a message  announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2446   void CContext::sendCouplerInContextFinalized(CContextClient* client)
2447   TRY
2448   {
2449      if (sendCouplerInContextFinalized_done_.count(client)!=0) return ;
2450      else sendCouplerInContextFinalized_done_.insert(client) ;
2451
2452      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED);
2453
2454      if (client->isServerLeader())
2455      {
2456        CMessage msg;
2457        msg<<this->getId();
2458        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
2459        client->sendEvent(event);
2460      }
2461      else client->sendEvent(event);
2462   }
2463   CATCH_DUMP_ATTR
2464
2465   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2466   void CContext::recvCouplerInContextFinalized(CEventServer& event)
2467   TRY
2468   {
2469      CBufferIn* buffer=event.subEvents.begin()->buffer;
2470      getCurrent()->recvCouplerInContextFinalized(*buffer);
2471   }
2472   CATCH
2473
2474   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
2475   void CContext::recvCouplerInContextFinalized(CBufferIn& buffer)
2476   TRY
2477   {
2478      string contextId ;
2479      buffer>>contextId;
2480      couplerInContextFinalized_.insert(getCouplerOutClient(contextId)) ;
2481   }
2482   CATCH_DUMP_ATTR
2483
2484
2485
2486
2487  /*!
2488  * \fn bool CContext::isFinalized(void)
2489  * Context is finalized if it received context post finalize event.
2490  */
2491  bool CContext::isFinalized(void)
2492  TRY
2493  {
2494    return finalized;
2495  }
2496  CATCH_DUMP_ATTR
2497  ///--------------------------------------------------------------
2498  StdString CContext::dumpClassAttributes(void)
2499  {
2500    StdString str;
2501    str.append("enabled files=\"");
2502    int size = this->enabledFiles.size();
2503    for (int i = 0; i < size; ++i)
2504    {
2505      str.append(enabledFiles[i]->getId());
2506      str.append(" ");
2507    }
2508    str.append("\"");
2509    return str;
2510  }
2511
2512} // namespace xios
Note: See TracBrowser for help on using the repository browser.