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

Last change on this file since 2547 was 2547, checked in by ymipsl, 9 months ago

Major update :

  • New method to lock and unlock one-sided windows (window_dynamic) to avoid network overhead
  • Introducing multithreading on server sided to manage more efficiently dead-lock occuring (similar to co-routine which will be available and implemented in futur c++ standard), based on c++ threads
  • Suprression of old "attached mode" which is replaced by online writer and reder filters

YM

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