source: XIOS/dev/dev_ym/XIOS_SERVICES/src/node/context.cpp @ 1765

Last change on this file since 1765 was 1765, checked in by ymipsl, 3 years ago

Some cleaning On XIOS services branch

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