source: XIOS3/dev/XIOS_ATTACHED/src/node/context.cpp @ 2482

Last change on this file since 2482 was 2482, checked in by ymipsl, 15 months ago

First guess in supression of attached mode replaced by online reader and write filters

YM

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