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

Last change on this file since 2458 was 2458, checked in by ymipsl, 17 months ago

Merge XIOS_FILE_SERVICE dev branch into trunk

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