source: XIOS/dev/dev_olga/src/node/context.cpp @ 1077

Last change on this file since 1077 was 1077, checked in by oabramkina, 7 years ago

dev: Intermediate commit

Done:
Registries: ok with two server levels

To do (on a single server level):
test_complete
reading

  • 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: 52.4 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
17#include "server.hpp"
18
19namespace xios {
20
21  shared_ptr<CContextGroup> CContext::root;
22
23   /// ////////////////////// Définitions ////////////////////// ///
24
25   CContext::CContext(void)
26      : CObjectTemplate<CContext>(), CContextAttributes()
27      , calendar(), hasClient(false), hasServer(false)
28      , isPostProcessed(false), finalized(false)
29      , idServer_(), client(0), server(0)
30      , allProcessed(false)
31   { /* Ne rien faire de plus */ }
32
33   CContext::CContext(const StdString & id)
34      : CObjectTemplate<CContext>(id), CContextAttributes()
35      , calendar(), hasClient(false), hasServer(false)
36      , isPostProcessed(false), finalized(false)
37      , idServer_(), client(0), server(0)
38      , allProcessed(false)
39   { /* Ne rien faire de plus */ }
40
41   CContext::~CContext(void)
42   {
43     delete client;
44     delete server;
45     for (std::vector<CContextClient*>::iterator it = clientPrimServer.begin(); it != clientPrimServer.end(); it++)  delete *it;
46     for (std::vector<CContextServer*>::iterator it = serverPrimServer.begin(); it != serverPrimServer.end(); it++)  delete *it;
47   }
48
49   //----------------------------------------------------------------
50   //! Get name of context
51   StdString CContext::GetName(void)   { return (StdString("context")); }
52   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
53   ENodeType CContext::GetType(void)   { return (eContext); }
54
55   //----------------------------------------------------------------
56
57   /*!
58   \brief Get context group (context root)
59   \return Context root
60   */
61   CContextGroup* CContext::getRoot(void)
62   {
63      if (root.get()==NULL) root=shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName()));
64      return root.get();
65   }
66
67   //----------------------------------------------------------------
68
69   /*!
70   \brief Get calendar of a context
71   \return Calendar
72   */
73   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
74   {
75      return (this->calendar);
76   }
77
78   //----------------------------------------------------------------
79
80   /*!
81   \brief Set a context with a calendar
82   \param[in] newCalendar new calendar
83   */
84   void CContext::setCalendar(boost::shared_ptr<CCalendar> newCalendar)
85   {
86      this->calendar = newCalendar;
87   }
88
89   //----------------------------------------------------------------
90   /*!
91   \brief Parse xml file and write information into context object
92   \param [in] node xmld node corresponding in xml file
93   */
94   void CContext::parse(xml::CXMLNode & node)
95   {
96      CContext::SuperClass::parse(node);
97
98      // PARSING POUR GESTION DES ENFANTS
99      xml::THashAttributes attributes = node.getAttributes();
100
101      if (attributes.end() != attributes.find("src"))
102      {
103         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
104         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
105            ERROR("void CContext::parse(xml::CXMLNode & node)",
106                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
107         if (!ifs.good())
108            ERROR("CContext::parse(xml::CXMLNode & node)",
109                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
110         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
111      }
112
113      if (node.getElementName().compare(CContext::GetName()))
114         DEBUG("Le noeud is wrong defined but will be considered as a context !");
115
116      if (!(node.goToChildElement()))
117      {
118         DEBUG("Le context ne contient pas d'enfant !");
119      }
120      else
121      {
122         do { // Parcours des contextes pour traitement.
123
124            StdString name = node.getElementName();
125            attributes.clear();
126            attributes = node.getAttributes();
127
128            if (attributes.end() != attributes.find("id"))
129            {
130              DEBUG(<< "Definition node has an id,"
131                    << "it will not be taking account !");
132            }
133
134#define DECLARE_NODE(Name_, name_)    \
135   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
136   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node); continue; }
137#define DECLARE_NODE_PAR(Name_, name_)
138#include "node_type.conf"
139
140            DEBUG(<< "The element \'"     << name
141                  << "\' in the context \'" << CContext::getCurrent()->getId()
142                  << "\' is not a definition !");
143
144         } while (node.goToNextElement());
145
146         node.goToParentElement(); // Retour au parent
147      }
148   }
149
150   //----------------------------------------------------------------
151   //! Show tree structure of context
152   void CContext::ShowTree(StdOStream & out)
153   {
154      StdString currentContextId = CContext::getCurrent() -> getId();
155      std::vector<CContext*> def_vector =
156         CContext::getRoot()->getChildList();
157      std::vector<CContext*>::iterator
158         it = def_vector.begin(), end = def_vector.end();
159
160      out << "<? xml version=\"1.0\" ?>" << std::endl;
161      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
162
163      for (; it != end; it++)
164      {
165         CContext* context = *it;
166         CContext::setCurrent(context->getId());
167         out << *context << std::endl;
168      }
169
170      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
171      CContext::setCurrent(currentContextId);
172   }
173
174
175   //----------------------------------------------------------------
176
177   //! Convert context object into string (to print)
178   StdString CContext::toString(void) const
179   {
180      StdOStringStream oss;
181      oss << "<" << CContext::GetName()
182          << " id=\"" << this->getId() << "\" "
183          << SuperClassAttribute::toString() << ">" << std::endl;
184      if (!this->hasChild())
185      {
186         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
187      }
188      else
189      {
190
191#define DECLARE_NODE(Name_, name_)    \
192   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
193   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
194#define DECLARE_NODE_PAR(Name_, name_)
195#include "node_type.conf"
196
197      }
198
199      oss << "</" << CContext::GetName() << " >";
200
201      return (oss.str());
202   }
203
204   //----------------------------------------------------------------
205
206   /*!
207   \brief Find all inheritace among objects in a context.
208   \param [in] apply (true) write attributes of parent into ones of child if they are empty
209                     (false) write attributes of parent into a new container of child
210   \param [in] parent unused
211   */
212   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
213   {
214#define DECLARE_NODE(Name_, name_)    \
215   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
216     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
217#define DECLARE_NODE_PAR(Name_, name_)
218#include "node_type.conf"
219   }
220
221   //----------------------------------------------------------------
222
223   //! Verify if all root definition in the context have child.
224   bool CContext::hasChild(void) const
225   {
226      return (
227#define DECLARE_NODE(Name_, name_)    \
228   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
229#define DECLARE_NODE_PAR(Name_, name_)
230#include "node_type.conf"
231      false);
232}
233
234   //----------------------------------------------------------------
235
236   void CContext::CleanTree(void)
237   {
238#define DECLARE_NODE(Name_, name_) C##Name_##Definition::ClearAllAttributes();
239#define DECLARE_NODE_PAR(Name_, name_)
240#include "node_type.conf"
241   }
242   ///---------------------------------------------------------------
243
244   //! Initialize client side
245   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer /*= 0*/)
246   {
247
248     hasClient = true;
249     MPI_Comm intraCommServer, interCommServer;
250
251     if (CServer::serverLevel != 1)
252      // initClient is called by client
253     {
254       client = new CContextClient(this, intraComm, interComm, cxtServer);
255       if (cxtServer) // Attached mode
256       {
257         intraCommServer = intraComm;
258         interCommServer = interComm;
259       }
260       else
261       {
262         MPI_Comm_dup(intraComm, &intraCommServer);
263         comms.push_back(intraCommServer);
264         MPI_Comm_dup(interComm, &interCommServer);
265         comms.push_back(interCommServer);
266       }
267       registryIn=new CRegistry(intraComm);
268       registryIn->setPath(getId()) ;
269       if (client->clientRank==0) registryIn->fromFile("xios_registry.bin") ;
270       registryIn->bcastRegistry() ;
271       registryOut=new CRegistry(intraComm) ;
272       registryOut->setPath(getId()) ;
273
274       server = new CContextServer(this, intraCommServer, interCommServer);
275     }
276     else
277     // initClient is called by primary server
278     {
279       clientPrimServer.push_back(new CContextClient(this, intraComm, interComm));
280       MPI_Comm_dup(intraComm, &intraCommServer);
281       comms.push_back(intraCommServer);
282       MPI_Comm_dup(interComm, &interCommServer);
283       comms.push_back(interCommServer);
284       serverPrimServer.push_back(new CContextServer(this, intraCommServer, interCommServer));
285     }
286   }
287
288   void CContext::setClientServerBuffer()
289   {
290     size_t minBufferSize = CXios::minBufferSize;
291#define DECLARE_NODE(Name_, name_)    \
292     if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
293#define DECLARE_NODE_PAR(Name_, name_)
294#include "node_type.conf"
295#undef DECLARE_NODE
296#undef DECLARE_NODE_PAR
297
298     std::map<int, StdSize> maxEventSize;
299     std::map<int, StdSize> bufferSize = getAttributesBufferSize(maxEventSize);
300     std::map<int, StdSize> dataBufferSize = getDataBufferSize(maxEventSize);
301
302     std::map<int, StdSize>::iterator it, ite = dataBufferSize.end();
303     for (it = dataBufferSize.begin(); it != ite; ++it)
304       if (it->second > bufferSize[it->first]) bufferSize[it->first] = it->second;
305
306     ite = bufferSize.end();
307     for (it = bufferSize.begin(); it != ite; ++it)
308     {
309       it->second *= CXios::bufferSizeFactor;
310       if (it->second < minBufferSize) it->second = minBufferSize;
311     }
312
313     // We consider that the minimum buffer size is also the minimum event size
314     ite = maxEventSize.end();
315     for (it = maxEventSize.begin(); it != ite; ++it)
316       if (it->second < minBufferSize) it->second = minBufferSize;
317
318     if (client->isServerLeader())
319     {
320       const std::list<int>& ranks = client->getRanksServerLeader();
321       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
322         if (!bufferSize.count(*itRank)) bufferSize[*itRank] = maxEventSize[*itRank] = minBufferSize;
323     }
324     client->setBufferSize(bufferSize, maxEventSize);
325
326     // If it is primary server pool, also set buffer for clientPrimServer.
327     if (hasClient && hasServer)
328     {
329       for (int i = 0; i < clientPrimServer.size(); ++i)
330       {
331         if (clientPrimServer[i]->isServerLeader())
332         {
333           const std::list<int>& ranks = clientPrimServer[i]->getRanksServerLeader();
334           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
335             if (!bufferSize.count(*itRank)) bufferSize[*itRank] = maxEventSize[*itRank] = minBufferSize;
336         }
337         clientPrimServer[i]->setBufferSize(bufferSize, maxEventSize);
338       }
339     }
340   }
341
342   //! Verify whether a context is initialized
343   bool CContext::isInitialized(void)
344   {
345     return hasClient;
346   }
347
348   void CContext::initServer(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtClient /*= 0*/)
349   {
350     hasServer=true;
351     server = new CContextServer(this,intraComm,interComm);
352//     client = new CContextClient(this,intraComm,interComm, cxtClient);
353
354     registryIn=new CRegistry(intraComm);
355     registryIn->setPath(getId()) ;
356     if (server->intraCommRank==0) registryIn->fromFile("xios_registry.bin") ;
357     registryIn->bcastRegistry() ;
358     registryOut=new CRegistry(intraComm) ;
359     registryOut->setPath(getId()) ;
360
361     MPI_Comm intraCommClient, interCommClient;
362     if (cxtClient) // Attached mode
363     {
364       intraCommClient = intraComm;
365       interCommClient = interComm;
366     }
367     else
368     {
369       MPI_Comm_dup(intraComm, &intraCommClient);
370       comms.push_back(intraCommClient);
371       MPI_Comm_dup(interComm, &interCommClient);
372       comms.push_back(interCommClient);
373     }
374     client = new CContextClient(this,intraCommClient,interCommClient);
375
376   }
377
378   //! Try to send the buffers and receive possible answers
379   bool CContext::checkBuffersAndListen(void)
380   {
381     if (CServer::serverLevel == 0)
382     {
383       client->checkBuffers();
384       bool hasTmpBufferedEvent = client->hasTemporarilyBufferedEvent();
385       if (hasTmpBufferedEvent)
386         hasTmpBufferedEvent = !client->sendTemporarilyBufferedEvent();
387       // Don't process events if there is a temporarily buffered event
388       return server->eventLoop(!hasTmpBufferedEvent);
389     }
390
391     else if (CServer::serverLevel == 1)
392     {
393       client->checkBuffers();
394       bool hasTmpBufferedEvent = client->hasTemporarilyBufferedEvent();
395       if (hasTmpBufferedEvent)
396         hasTmpBufferedEvent = !client->sendTemporarilyBufferedEvent();
397       bool serverFinished = server->eventLoop(!hasTmpBufferedEvent);
398
399       bool serverPrimFinished = true;
400       for (int i = 0; i < clientPrimServer.size(); ++i)
401       {
402         clientPrimServer[i]->checkBuffers();
403         bool hasTmpBufferedEventPrim = clientPrimServer[i]->hasTemporarilyBufferedEvent();
404         if (hasTmpBufferedEventPrim)
405           hasTmpBufferedEventPrim = !clientPrimServer[i]->sendTemporarilyBufferedEvent();
406//         serverPrimFinished *= serverPrimServer[i]->eventLoop(!hasTmpBufferedEventPrim);
407         serverPrimFinished *= serverPrimServer[i]->eventLoop();
408       }
409       return ( serverFinished && serverPrimFinished);
410     }
411
412     else if (CServer::serverLevel == 2)
413     {
414       client->checkBuffers();
415       bool hasTmpBufferedEvent = client->hasTemporarilyBufferedEvent();
416//       if (hasTmpBufferedEvent)
417//         hasTmpBufferedEvent = !client->sendTemporarilyBufferedEvent();
418//       return server->eventLoop(!hasTmpBufferedEvent);
419       return server->eventLoop();
420      }
421   }
422
423   //! Terminate a context
424   void CContext::finalize(void)
425   {
426     if (!finalized)
427     {
428       finalized = true;
429
430       if (hasClient) sendRegistry() ;
431
432       if ((hasClient) && (hasServer))
433       {
434         for (int i = 0; i < clientPrimServer.size(); ++i)
435           clientPrimServer[i]->finalize();
436
437         for (int i = 0; i < serverPrimServer.size(); ++i)
438         {
439           while (!serverPrimServer[i]->hasFinished())
440           {
441             serverPrimServer[i]->eventLoop();
442             CServer::eventScheduler->checkEvent() ;
443           }
444         }
445       }
446       client->finalize();
447       while (!server->hasFinished())
448       {
449         server->eventLoop();
450       }
451
452       info(20)<<"Server Side context <"<<getId()<<"> finalized"<<endl;
453       report(0)<< " Memory report : Context <"<<getId()<<"> : server side : total memory used for buffers "<<CContextServer::getTotalBuf()<<" bytes"<<endl;
454
455//       if (hasServer)
456       if (hasServer && !hasClient)
457       {
458         closeAllFile();
459         registryOut->hierarchicalGatherRegistry() ;
460         if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
461       }
462      }
463   }
464
465   //! Free internally allocated communicators
466   void CContext::freeComms(void)
467   {
468     for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
469       MPI_Comm_free(&(*it));
470     comms.clear();
471   }
472
473   void CContext::postProcessingGlobalAttributes()
474   {
475     if (allProcessed) return;
476     
477     if (hasClient)
478     {
479       // After xml is parsed, there are some more works with post processing
480       postProcessing();
481     }
482
483     setClientServerBuffer();
484
485     if (hasClient)
486     {
487      // Send all attributes of current context to server
488      this->sendAllAttributesToServer();
489
490      // Send all attributes of current calendar
491      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer();
492
493      // We have enough information to send to server
494      // First of all, send all enabled files
495      sendEnabledFiles();
496
497      // Then, send all enabled fields
498      sendEnabledFields();
499
500      // At last, we have all info of domain and axis, then send them
501       sendRefDomainsAxis();
502
503       // After that, send all grid (if any)
504       sendRefGrid();
505
506       // We have a xml tree on the server side and now, it should be also processed
507       sendPostProcessing();
508     }
509     allProcessed = true;
510   }
511
512   void CContext::sendPostProcessingGlobalAttributes()
513   {
514      // Use correct context client to send message
515     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
516    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
517     for (int i = 0; i < nbSrvPools; ++i)
518     {
519       CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
520       CEventClient event(getType(),EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES);
521
522       if (contextClientTmp->isServerLeader())
523       {
524         CMessage msg;
525         msg<<this->getIdServer();
526         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
527         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
528           event.push(*itRank,1,msg);
529         contextClientTmp->sendEvent(event);
530       }
531       else contextClientTmp->sendEvent(event);
532     }
533   }
534
535   void CContext::recvPostProcessingGlobalAttributes(CEventServer& event)
536   {
537      CBufferIn* buffer=event.subEvents.begin()->buffer;
538      string id;
539      *buffer>>id;
540      // get(id)->recvPostProcessingGlobalAttributes(*buffer);
541   }
542
543   void CContext::recvPostProcessingGlobalAttributes(CBufferIn& buffer)
544   {
545      // CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
546      postProcessingGlobalAttributes();
547   }
548
549   /*!
550   \brief Close all the context defintion and do processing data
551      After everything is well defined on client side, they will be processed and sent to server
552   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
553   all necessary information to server, from which each server can build its own database.
554   Because the role of server is to write out field data on a specific netcdf file,
555   the only information that it needs is the enabled files
556   and the active fields (fields will be written onto active files)
557   */
558   void CContext::closeDefinition(void)
559   {
560    postProcessingGlobalAttributes();
561
562    if (hasClient) sendPostProcessingGlobalAttributes();
563
564    // There are some processings that should be done after all of above. For example: check mask or index
565    this->buildFilterGraphOfEnabledFields();
566   
567     if (hasClient && !hasServer)
568    {
569      buildFilterGraphOfFieldsWithReadAccess();
570    }
571
572    // if (hasClient) this->solveAllRefOfEnabledFields(true);
573    this->processGridEnabledFields();
574    if (hasClient) this->sendProcessingGridOfEnabledFields();
575    if (hasClient) this->sendCloseDefinition();
576
577    // Nettoyage de l'arborescence
578    if (hasClient) CleanTree(); // Only on client side??
579
580    if (hasClient)
581    {
582      sendCreateFileHeader();
583      if (!hasServer) startPrefetchingOfEnabledReadModeFiles();
584    }
585   }
586
587   void CContext::findAllEnabledFields(void)
588   {
589     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
590     (void)this->enabledFiles[i]->getEnabledFields();
591   }
592
593   void CContext::findAllEnabledFieldsInReadModeFiles(void)
594   {
595     for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
596     (void)this->enabledReadModeFiles[i]->getEnabledFields();
597   }
598
599   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
600   {
601      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
602        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
603   }
604
605   void CContext::solveAllEnabledFields()
606   {
607     int size = this->enabledFiles.size();
608     for (int i = 0; i < size; ++i)
609     {
610       this->enabledFiles[i]->solveOnlyRefOfEnabledFields(false);
611     }
612
613     for (int i = 0; i < size; ++i)
614     {
615       this->enabledFiles[i]->generateNewTransformationGridDest();
616     }
617   }
618
619   void CContext::processGridEnabledFields()
620   {
621     int size = this->enabledFiles.size();
622     for (int i = 0; i < size; ++i)
623     {
624       this->enabledFiles[i]->checkGridOfEnabledFields();
625       this->enabledFiles[i]->sendGridOfEnabledFields();
626     }
627   }
628
629
630
631   void CContext::solveOnlyRefOfEnabledFields(bool sendToServer)
632   {
633     int size = this->enabledFiles.size();
634     for (int i = 0; i < size; ++i)
635     {
636       this->enabledFiles[i]->solveOnlyRefOfEnabledFields(sendToServer);
637     }
638
639     for (int i = 0; i < size; ++i)
640     {
641       this->enabledFiles[i]->generateNewTransformationGridDest();
642     }
643
644     for (int i = 0; i < size; ++i)
645     {
646       //this->enabledFiles[i]->checkGridOfEnabledFields();
647     }
648   }
649
650   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
651   {
652     int size = this->enabledFiles.size();
653     for (int i = 0; i < size; ++i)
654     {
655       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
656     }
657   }
658
659   void CContext::buildFilterGraphOfEnabledFields()
660   {
661     int size = this->enabledFiles.size();
662     for (int i = 0; i < size; ++i)
663     {
664       this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);
665     }
666   }
667
668   void CContext::startPrefetchingOfEnabledReadModeFiles()
669   {
670     int size = enabledReadModeFiles.size();
671     for (int i = 0; i < size; ++i)
672     {
673        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
674     }
675   }
676
677   void CContext::checkPrefetchingOfEnabledReadModeFiles()
678   {
679     int size = enabledReadModeFiles.size();
680     for (int i = 0; i < size; ++i)
681     {
682        enabledReadModeFiles[i]->prefetchEnabledReadModeFieldsIfNeeded();
683     }
684   }
685
686  void CContext::findFieldsWithReadAccess(void)
687  {
688    fieldsWithReadAccess.clear();
689    const vector<CField*> allFields = CField::getAll();
690    for (size_t i = 0; i < allFields.size(); ++i)
691    {
692      CField* field = allFields[i];
693
694      if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)
695        field->read_access = true;
696      else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
697        fieldsWithReadAccess.push_back(field);
698    }
699  }
700
701  void CContext::solveAllRefOfFieldsWithReadAccess()
702  {
703    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
704      fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false);
705  }
706
707  void CContext::buildFilterGraphOfFieldsWithReadAccess()
708  {
709    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
710      fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true);
711  }
712
713   void CContext::solveAllInheritance(bool apply)
714   {
715     // Résolution des héritages descendants (càd des héritages de groupes)
716     // pour chacun des contextes.
717      solveDescInheritance(apply);
718
719     // Résolution des héritages par référence au niveau des fichiers.
720      const vector<CFile*> allFiles=CFile::getAll();
721      const vector<CGrid*> allGrids= CGrid::getAll();
722
723      if (hasClient && !hasServer)
724      //if (hasClient)
725      {
726        for (unsigned int i = 0; i < allFiles.size(); i++)
727          allFiles[i]->solveFieldRefInheritance(apply);
728      }
729
730      unsigned int vecSize = allGrids.size();
731      unsigned int i = 0;
732      for (i = 0; i < vecSize; ++i)
733        allGrids[i]->solveDomainAxisRefInheritance(apply);
734
735   }
736
737   void CContext::findEnabledFiles(void)
738   {
739      const std::vector<CFile*> allFiles = CFile::getAll();
740
741      for (unsigned int i = 0; i < allFiles.size(); i++)
742         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
743         {
744            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
745               enabledFiles.push_back(allFiles[i]);
746         }
747         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
748
749
750      if (enabledFiles.size() == 0)
751         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
752               << getId() << "\" !");
753
754      // Assigning contextClient to each enabled file
755      if (hasClient)
756      {
757        for (int i = 0; i < enabledFiles.size(); ++i)
758        {
759          if (hasServer)
760          {
761            int srvId = i % clientPrimServer.size();
762            enabledFiles[i]->setContextClient(clientPrimServer[srvId]);
763          }
764          else
765            enabledFiles[i]->setContextClient(client);
766        }
767      }
768   }
769
770   void CContext::findEnabledReadModeFiles(void)
771   {
772     int size = this->enabledFiles.size();
773     for (int i = 0; i < size; ++i)
774     {
775       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
776        enabledReadModeFiles.push_back(enabledFiles[i]);
777     }
778   }
779
780   void CContext::closeAllFile(void)
781   {
782     std::vector<CFile*>::const_iterator
783            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
784
785     for (; it != end; it++)
786     {
787       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
788       (*it)->close();
789     }
790   }
791
792   /*!
793   \brief Dispatch event received from client
794      Whenever a message is received in buffer of server, it will be processed depending on
795   its event type. A new event type should be added in the switch list to make sure
796   it processed on server side.
797   \param [in] event: Received message
798   */
799   bool CContext::dispatchEvent(CEventServer& event)
800   {
801
802      if (SuperClass::dispatchEvent(event)) return true;
803      else
804      {
805        switch(event.type)
806        {
807           case EVENT_ID_CLOSE_DEFINITION :
808             recvCloseDefinition(event);
809             return true;
810             break;
811           case EVENT_ID_UPDATE_CALENDAR:
812             recvUpdateCalendar(event);
813             return true;
814             break;
815           case EVENT_ID_CREATE_FILE_HEADER :
816             recvCreateFileHeader(event);
817             return true;
818             break;
819           case EVENT_ID_POST_PROCESS:
820             recvPostProcessing(event);
821             return true;
822            case EVENT_ID_SEND_REGISTRY:
823             recvRegistry(event);
824             return true;
825             break;
826            case EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES:
827             recvPostProcessingGlobalAttributes(event);
828             return true;
829             break;
830            case EVENT_ID_PROCESS_GRID_ENABLED_FIELDS:
831             recvProcessingGridOfEnabledFields(event);
832             return true;
833             break;
834           default :
835             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
836                    <<"Unknown Event");
837           return false;
838         }
839      }
840   }
841
842//   // Only send close definition from process having hasClient
843//   void CContext::sendCloseDefinitionToServer(void)
844//   {
845//     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
846//   }
847
848   //! Client side: Send a message to server to make it close
849   void CContext::sendCloseDefinition(void)
850   {
851     // Use correct context client to send message
852     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
853     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
854     for (int i = 0; i < nbSrvPools; ++i)
855     {
856       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
857       CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
858       if (contextClientTmp->isServerLeader())
859       {
860         CMessage msg;
861         if (hasServer)
862           msg<<this->getIdServer(i);
863         else
864           msg<<this->getIdServer();
865         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
866         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
867           event.push(*itRank,1,msg);
868         contextClientTmp->sendEvent(event);
869       }
870       else contextClientTmp->sendEvent(event);
871     }
872   }
873
874   //! Server side: Receive a message of client announcing a context close
875   void CContext::recvCloseDefinition(CEventServer& event)
876   {
877      CBufferIn* buffer=event.subEvents.begin()->buffer;
878      string id;
879      *buffer>>id;
880      get(id)->closeDefinition();
881   }
882
883   //! Client side: Send a message to update calendar in each time step
884   void CContext::sendUpdateCalendar(int step)
885   {
886     // Use correct context client to send message
887//     CContextClient* contextClientTmp = (0 != clientPrimServer) ? clientPrimServer : client;
888     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
889    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
890     for (int i = 0; i < nbSrvPools; ++i)
891     {
892       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
893       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
894
895         if (contextClientTmp->isServerLeader())
896         {
897           CMessage msg;
898           if (hasServer)
899             msg<<this->getIdServer(i)<<step;
900           else
901             msg<<this->getIdServer()<<step;
902           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
903           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
904             event.push(*itRank,1,msg);
905           contextClientTmp->sendEvent(event);
906         }
907         else contextClientTmp->sendEvent(event);
908     }
909   }
910
911   //! Server side: Receive a message of client annoucing calendar update
912   void CContext::recvUpdateCalendar(CEventServer& event)
913   {
914      CBufferIn* buffer=event.subEvents.begin()->buffer;
915      string id;
916      *buffer>>id;
917      get(id)->recvUpdateCalendar(*buffer);
918   }
919
920   //! Server side: Receive a message of client annoucing calendar update
921   void CContext::recvUpdateCalendar(CBufferIn& buffer)
922   {
923      int step;
924      buffer>>step;
925      updateCalendar(step);
926      if (hasClient && hasServer)
927      {       
928        sendUpdateCalendar(step);
929      }
930   }
931
932   //! Client side: Send a message to create header part of netcdf file
933   void CContext::sendCreateFileHeader(void)
934   {
935     // Use correct context client to send message
936     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
937     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
938     for (int i = 0; i < nbSrvPools; ++i)
939     {
940       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
941       CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
942
943       if (contextClientTmp->isServerLeader())
944       {
945         CMessage msg;
946         if (hasServer)
947           msg<<this->getIdServer(i);
948         else
949           msg<<this->getIdServer();
950         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
951         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
952           event.push(*itRank,1,msg) ;
953         contextClientTmp->sendEvent(event);
954       }
955       else contextClientTmp->sendEvent(event);
956     }
957   }
958
959   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
960   void CContext::recvCreateFileHeader(CEventServer& event)
961   {
962      CBufferIn* buffer=event.subEvents.begin()->buffer;
963      string id;
964      *buffer>>id;
965      get(id)->recvCreateFileHeader(*buffer);
966   }
967
968   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
969   void CContext::recvCreateFileHeader(CBufferIn& buffer)
970   {
971     // The creation of header file should be delegated to server2, for now
972      // if (hasClient && hasServer)
973      // {       
974      //   sendCreateFileHeader();
975      // }
976     
977      if (!hasClient && hasServer) 
978        createFileHeader();
979   }
980
981   //! Client side: Send a message to do some post processing on server
982   void CContext::sendProcessingGridOfEnabledFields()
983   {
984      // Use correct context client to send message
985     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
986     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
987     for (int i = 0; i < nbSrvPools; ++i)
988     {
989       CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
990       CEventClient event(getType(),EVENT_ID_PROCESS_GRID_ENABLED_FIELDS);
991
992       if (contextClientTmp->isServerLeader())
993       {
994         CMessage msg;
995         msg<<this->getIdServer();
996         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
997         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
998           event.push(*itRank,1,msg);
999         contextClientTmp->sendEvent(event);
1000       }
1001       else contextClientTmp->sendEvent(event);
1002     }
1003   }
1004
1005   //! Server side: Receive a message to do some post processing
1006   void CContext::recvProcessingGridOfEnabledFields(CEventServer& event)
1007   {
1008      CBufferIn* buffer=event.subEvents.begin()->buffer;
1009      string id;
1010      *buffer>>id;
1011      // get(id)->processGridEnabledFields();
1012   }
1013
1014   //! Client side: Send a message to do some post processing on server
1015   void CContext::sendPostProcessing()
1016   {
1017      // Use correct context client to send message
1018     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
1019     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1020     for (int i = 0; i < nbSrvPools; ++i)
1021     {
1022       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1023       CEventClient event(getType(),EVENT_ID_POST_PROCESS);
1024       if (contextClientTmp->isServerLeader())
1025       {
1026         CMessage msg;
1027         if (hasServer)
1028           msg<<this->getIdServer(i);
1029         else
1030           msg<<this->getIdServer();
1031         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1032         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1033         event.push(*itRank,1,msg);
1034         contextClientTmp->sendEvent(event);
1035       }
1036       else contextClientTmp->sendEvent(event);
1037     }
1038   }
1039
1040   //! Server side: Receive a message to do some post processing
1041   void CContext::recvPostProcessing(CEventServer& event)
1042   {
1043      CBufferIn* buffer=event.subEvents.begin()->buffer;
1044      string id;
1045      *buffer>>id;
1046      get(id)->recvPostProcessing(*buffer);
1047   }
1048
1049   //! Server side: Receive a message to do some post processing
1050   void CContext::recvPostProcessing(CBufferIn& buffer)
1051   {
1052      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
1053      postProcessing();
1054   }
1055
1056   const StdString& CContext::getIdServer()
1057   {
1058      if (hasClient)
1059      {
1060        idServer_ = this->getId();
1061        idServer_ += "_server";
1062        return idServer_;
1063      }
1064      if (hasServer) return (this->getId());
1065   }
1066
1067   const StdString& CContext::getIdServer(const int i)
1068   {
1069     idServer_ = this->getId();
1070     idServer_ += "_server_";
1071     idServer_ += boost::lexical_cast<string>(i);
1072     return idServer_;
1073   }
1074
1075
1076   /*!
1077   \brief Do some simple post processings after parsing xml file
1078      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
1079   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
1080   which will be written out into netcdf files, are processed
1081   */
1082   void CContext::postProcessing()
1083   {
1084     if (isPostProcessed) return;
1085
1086      // Make sure the calendar was correctly created
1087      if (!calendar)
1088        ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
1089      else if (calendar->getTimeStep() == NoneDu)
1090        ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
1091      // Calendar first update to set the current date equals to the start date
1092      calendar->update(0);
1093
1094      // Find all inheritance in xml structure
1095      this->solveAllInheritance();
1096
1097//      ShowTree(info(10));
1098
1099      // Check if some axis, domains or grids are eligible to for compressed indexed output.
1100      // Warning: This must be done after solving the inheritance and before the rest of post-processing
1101      checkAxisDomainsGridsEligibilityForCompressedOutput();     
1102
1103      // Check if some automatic time series should be generated
1104      // Warning: This must be done after solving the inheritance and before the rest of post-processing
1105      // prepareTimeseries();
1106
1107      // The timeseries should only be prepared in client
1108      if (hasClient && !hasServer) prepareTimeseries();
1109
1110      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
1111      this->findEnabledFiles();
1112      // this->findEnabledReadModeFiles();
1113      // For now, only read files with client and only one level server
1114      if (hasClient && !hasServer) this->findEnabledReadModeFiles();
1115
1116
1117      // Find all enabled fields of each file
1118      this->findAllEnabledFields();
1119      // this->findAllEnabledFieldsInReadModeFiles();
1120      // For now, only read files with client and only one level server
1121      if (hasClient && !hasServer) this->findAllEnabledFieldsInReadModeFiles();
1122
1123//     if (hasClient)
1124     if (hasClient && !hasServer)
1125     {
1126      // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis)
1127      this->readAttributesOfEnabledFieldsInReadModeFiles();
1128     }
1129
1130      // // Only search and rebuild all reference objects of enable fields, don't transform
1131      // this->solveOnlyRefOfEnabledFields(false);
1132
1133      // // Search and rebuild all reference object of enabled fields
1134      // this->solveAllRefOfEnabledFields(false);
1135
1136      // // Find all fields with read access from the public API
1137      // findFieldsWithReadAccess();
1138      // // and solve the all reference for them
1139      // solveAllRefOfFieldsWithReadAccess();
1140
1141      // Only search and rebuild all reference objects of enable fields, don't transform
1142      if (hasClient) this->solveOnlyRefOfEnabledFields(false);
1143
1144      // Search and rebuild all reference object of enabled fields
1145      // if (hasClient) this->solveAllRefOfEnabledFields(false);
1146
1147      // Find all fields with read access from the public API
1148      if (hasClient && !hasServer) findFieldsWithReadAccess();
1149      // and solve the all reference for them
1150      if (hasClient && !hasServer) solveAllRefOfFieldsWithReadAccess();
1151
1152      isPostProcessed = true;
1153   }
1154
1155   /*!
1156    * Compute the required buffer size to send the attributes (mostly those grid related).
1157    *
1158    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1159    */
1160   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize)
1161   {
1162     std::map<int, StdSize> attributesSize;
1163
1164     if (hasClient)
1165     {
1166       size_t numEnabledFiles = this->enabledFiles.size();
1167       for (size_t i = 0; i < numEnabledFiles; ++i)
1168       {
1169         CFile* file = this->enabledFiles[i];
1170
1171         std::vector<CField*> enabledFields = file->getEnabledFields();
1172         size_t numEnabledFields = enabledFields.size();
1173         for (size_t j = 0; j < numEnabledFields; ++j)
1174         {
1175           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize();
1176           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1177           for (; it != itE; ++it)
1178           {
1179             // If attributesSize[it->first] does not exist, it will be zero-initialized
1180             // so we can use it safely without checking for its existance
1181             if (attributesSize[it->first] < it->second)
1182               attributesSize[it->first] = it->second;
1183
1184             if (maxEventSize[it->first] < it->second)
1185               maxEventSize[it->first] = it->second;
1186           }
1187         }
1188       }
1189     }
1190
1191     return attributesSize;
1192   }
1193
1194   /*!
1195    * Compute the required buffer size to send the fields data.
1196    *
1197    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1198    */
1199   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize)
1200   {
1201     CFile::mode_attr::t_enum mode = hasClient ? CFile::mode_attr::write : CFile::mode_attr::read;
1202
1203     std::map<int, StdSize> dataSize;
1204
1205     // Find all reference domain and axis of all active fields
1206     size_t numEnabledFiles = this->enabledFiles.size();
1207     for (size_t i = 0; i < numEnabledFiles; ++i)
1208     {
1209       CFile* file = this->enabledFiles[i];
1210       CFile::mode_attr::t_enum fileMode = file->mode.isEmpty() ? CFile::mode_attr::write : file->mode.getValue();
1211
1212       if (fileMode == mode)
1213       {
1214         std::vector<CField*> enabledFields = file->getEnabledFields();
1215         size_t numEnabledFields = enabledFields.size();
1216         for (size_t j = 0; j < numEnabledFields; ++j)
1217         {
1218           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize();
1219           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1220           for (; it != itE; ++it)
1221           {
1222             // If dataSize[it->first] does not exist, it will be zero-initialized
1223             // so we can use it safely without checking for its existance
1224             if (CXios::isOptPerformance)
1225               dataSize[it->first] += it->second;
1226             else if (dataSize[it->first] < it->second)
1227               dataSize[it->first] = it->second;
1228
1229             if (maxEventSize[it->first] < it->second)
1230               maxEventSize[it->first] = it->second;
1231           }
1232         }
1233       }
1234     }
1235
1236     return dataSize;
1237   }
1238
1239   //! Client side: Send infomation of active files (files are enabled to write out)
1240   void CContext::sendEnabledFiles()
1241   {
1242     int size = this->enabledFiles.size();
1243
1244     // In a context, each type has a root definition, e.g: axis, domain, field.
1245     // Every object must be a child of one of these root definition. In this case
1246     // all new file objects created on server must be children of the root "file_definition"
1247     StdString fileDefRoot("file_definition");
1248     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1249     for (int i = 0; i < size; ++i)
1250     {
1251       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId(),enabledFiles[i]->getContextClient());
1252       this->enabledFiles[i]->sendAllAttributesToServer(enabledFiles[i]->getContextClient());
1253       this->enabledFiles[i]->sendAddAllVariables(enabledFiles[i]->getContextClient());
1254     }
1255   }
1256
1257   //! Client side: Send information of active fields (ones are written onto files)
1258   void CContext::sendEnabledFields()
1259   {
1260     int size = this->enabledFiles.size();
1261     for (int i = 0; i < size; ++i)
1262     {
1263       this->enabledFiles[i]->sendEnabledFields(enabledFiles[i]->getContextClient());
1264     }
1265   }
1266
1267   //! Client side: Check if the defined axis, domains and grids are eligible for compressed indexed output
1268   void CContext::checkAxisDomainsGridsEligibilityForCompressedOutput()
1269   {
1270     if (!hasClient) return;
1271
1272     const vector<CAxis*> allAxis = CAxis::getAll();
1273     for (vector<CAxis*>::const_iterator it = allAxis.begin(); it != allAxis.end(); it++)
1274       (*it)->checkEligibilityForCompressedOutput();
1275
1276     const vector<CDomain*> allDomains = CDomain::getAll();
1277     for (vector<CDomain*>::const_iterator it = allDomains.begin(); it != allDomains.end(); it++)
1278       (*it)->checkEligibilityForCompressedOutput();
1279
1280     const vector<CGrid*> allGrids = CGrid::getAll();
1281     for (vector<CGrid*>::const_iterator it = allGrids.begin(); it != allGrids.end(); it++)
1282       (*it)->checkEligibilityForCompressedOutput();
1283   }
1284
1285   //! Client side: Prepare the timeseries by adding the necessary files
1286   void CContext::prepareTimeseries()
1287   {
1288     if (!hasClient) return;
1289
1290     const std::vector<CFile*> allFiles = CFile::getAll();
1291     for (size_t i = 0; i < allFiles.size(); i++)
1292     {
1293       CFile* file = allFiles[i];
1294
1295       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1296       {
1297         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : file->getFileOutputName();
1298
1299         const std::vector<CField*> allFields = file->getAllFields();
1300         for (size_t j = 0; j < allFields.size(); j++)
1301         {
1302           CField* field = allFields[j];
1303
1304           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
1305           {
1306             CFile* tsFile = CFile::create();
1307             tsFile->duplicateAttributes(file);
1308             tsFile->setVirtualVariableGroup(file->getVirtualVariableGroup());
1309
1310             tsFile->name = tsPrefix + "_";
1311             if (!field->name.isEmpty())
1312               tsFile->name.get() += field->name;
1313             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
1314               tsFile->name.get() += field->field_ref;
1315             else
1316               tsFile->name.get() += field->getId();
1317
1318             if (!field->ts_split_freq.isEmpty())
1319               tsFile->split_freq = field->ts_split_freq;
1320
1321             CField* tsField = tsFile->addField();
1322             tsField->field_ref = field->getId();
1323             tsField->setVirtualVariableGroup(field->getVirtualVariableGroup());
1324
1325             tsFile->solveFieldRefInheritance(true);
1326
1327             if (file->timeseries == CFile::timeseries_attr::exclusive)
1328               field->enabled = false;
1329           }
1330         }
1331
1332         // Finally disable the original file is need be
1333         if (file->timeseries == CFile::timeseries_attr::only)
1334          file->enabled = false;
1335       }
1336     }
1337   }
1338
1339   //! Client side: Send information of reference grid of active fields
1340   void CContext::sendRefGrid()
1341   {
1342     std::set<StdString> gridIds;
1343     int sizeFile = this->enabledFiles.size();
1344     CFile* filePtr(NULL);
1345
1346     // Firstly, find all reference grids of all active fields
1347     for (int i = 0; i < sizeFile; ++i)
1348     {
1349       filePtr = this->enabledFiles[i];
1350       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
1351       int sizeField = enabledFields.size();
1352       for (int numField = 0; numField < sizeField; ++numField)
1353       {
1354         if (0 != enabledFields[numField]->getRelGrid())
1355           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
1356       }
1357     }
1358
1359     // Create all reference grids on server side
1360     StdString gridDefRoot("grid_definition");
1361     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
1362     std::set<StdString>::const_iterator it, itE = gridIds.end();
1363     for (it = gridIds.begin(); it != itE; ++it)
1364     {
1365       gridPtr->sendCreateChild(*it);
1366       CGrid::get(*it)->sendAllAttributesToServer();
1367       CGrid::get(*it)->sendAllDomains();
1368       CGrid::get(*it)->sendAllAxis();
1369       CGrid::get(*it)->sendAllScalars();
1370     }
1371   }
1372
1373
1374   //! Client side: Send information of reference domain and axis of active fields
1375   void CContext::sendRefDomainsAxis()
1376   {
1377     std::set<StdString> domainIds, axisIds, scalarIds;
1378
1379     // Find all reference domain and axis of all active fields
1380     int numEnabledFiles = this->enabledFiles.size();
1381     for (int i = 0; i < numEnabledFiles; ++i)
1382     {
1383       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
1384       int numEnabledFields = enabledFields.size();
1385       for (int j = 0; j < numEnabledFields; ++j)
1386       {
1387         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
1388         if ("" != prDomAxisScalarId[0]) domainIds.insert(prDomAxisScalarId[0]);
1389         if ("" != prDomAxisScalarId[1]) axisIds.insert(prDomAxisScalarId[1]);
1390         if ("" != prDomAxisScalarId[2]) scalarIds.insert(prDomAxisScalarId[2]);
1391       }
1392     }
1393
1394     // Create all reference axis on server side
1395     std::set<StdString>::iterator itDom, itAxis, itScalar;
1396     std::set<StdString>::const_iterator itE;
1397
1398     StdString scalarDefRoot("scalar_definition");
1399     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
1400     itE = scalarIds.end();
1401     for (itScalar = scalarIds.begin(); itScalar != itE; ++itScalar)
1402     {
1403       if (!itScalar->empty())
1404       {
1405         scalarPtr->sendCreateChild(*itScalar);
1406         CScalar::get(*itScalar)->sendAllAttributesToServer();
1407       }
1408     }
1409
1410     StdString axiDefRoot("axis_definition");
1411     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
1412     itE = axisIds.end();
1413     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
1414     {
1415       if (!itAxis->empty())
1416       {
1417         axisPtr->sendCreateChild(*itAxis);
1418         CAxis::get(*itAxis)->sendAllAttributesToServer();
1419       }
1420     }
1421
1422     // Create all reference domains on server side
1423     StdString domDefRoot("domain_definition");
1424     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
1425     itE = domainIds.end();
1426     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
1427     {
1428       if (!itDom->empty()) {
1429          domPtr->sendCreateChild(*itDom);
1430          CDomain::get(*itDom)->sendAllAttributesToServer();
1431       }
1432     }
1433   }
1434
1435   //! Update calendar in each time step
1436   void CContext::updateCalendar(int step)
1437   {
1438      info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
1439      calendar->update(step);
1440      info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
1441
1442      if (hasClient)
1443      {
1444        checkPrefetchingOfEnabledReadModeFiles();
1445        garbageCollector.invalidate(calendar->getCurrentDate());
1446      }
1447   }
1448
1449   //! Server side: Create header of netcdf file
1450   void CContext::createFileHeader(void )
1451   {
1452      vector<CFile*>::const_iterator it;
1453
1454      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
1455      {
1456         (*it)->initFile();
1457      }
1458   }
1459
1460   //! Get current context
1461   CContext* CContext::getCurrent(void)
1462   {
1463     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
1464   }
1465
1466   /*!
1467   \brief Set context with an id be the current context
1468   \param [in] id identity of context to be set to current
1469   */
1470   void CContext::setCurrent(const string& id)
1471   {
1472     CObjectFactory::SetCurrentContextId(id);
1473     CGroupFactory::SetCurrentContextId(id);
1474   }
1475
1476  /*!
1477  \brief Create a context with specific id
1478  \param [in] id identity of new context
1479  \return pointer to the new context or already-existed one with identity id
1480  */
1481  CContext* CContext::create(const StdString& id)
1482  {
1483    CContext::setCurrent(id);
1484
1485    bool hasctxt = CContext::has(id);
1486    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
1487    getRoot();
1488    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
1489
1490#define DECLARE_NODE(Name_, name_) \
1491    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
1492#define DECLARE_NODE_PAR(Name_, name_)
1493#include "node_type.conf"
1494
1495    return (context);
1496  }
1497
1498
1499     //! Server side: Receive a message to do some post processing
1500  void CContext::recvRegistry(CEventServer& event)
1501  {
1502    CBufferIn* buffer=event.subEvents.begin()->buffer;
1503    string id;
1504    *buffer>>id;
1505    get(id)->recvRegistry(*buffer);
1506  }
1507
1508  void CContext::recvRegistry(CBufferIn& buffer)
1509  {
1510    if (server->intraCommRank==0)
1511    {
1512      CRegistry registry(server->intraComm) ;
1513      registry.fromBuffer(buffer) ;
1514      registryOut->mergeRegistry(registry) ;
1515    }
1516  }
1517
1518  void CContext::sendRegistry(void)
1519  {   
1520    registryOut->hierarchicalGatherRegistry() ;
1521
1522    // Use correct context client to send message
1523    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1524    for (int i = 0; i < nbSrvPools; ++i)
1525    {
1526      CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1527      CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
1528        if (contextClientTmp->isServerLeader())
1529        {
1530           CMessage msg ;
1531           if (hasServer)
1532             msg<<this->getIdServer(i);
1533           else
1534             msg<<this->getIdServer();
1535           if (contextClientTmp->clientRank==0) msg<<*registryOut ;
1536           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1537           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1538             event.push(*itRank,1,msg);
1539           contextClientTmp->sendEvent(event);
1540         }
1541         else contextClientTmp->sendEvent(event);
1542    }
1543  }
1544
1545  bool CContext::isFinalized(void)
1546  {
1547    return finalized;
1548  }
1549
1550} // namespace xios
Note: See TracBrowser for help on using the repository browser.