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

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

Replace the childList (not updated) usage by a childMap usage to get a Context from a string

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