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

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

dev: test for secondary servers added.

  • 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: 54.3 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//       for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
464//         MPI_Comm_free(&(*it));
465//       comms.clear();
466
467      }
468   }
469   //! Free internally allocated communicators
470   void CContext::freeComms(void)
471   {
472     for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
473       MPI_Comm_free(&(*it));
474     comms.clear();
475   }
476
477   void CContext::postProcessingGlobalAttributes()
478   {
479     if (allProcessed) return;
480     
481     if (hasClient)
482     {
483       // After xml is parsed, there are some more works with post processing
484       postProcessing();
485     }
486
487     setClientServerBuffer();
488
489     if (hasClient)
490     {
491      // Send all attributes of current context to server
492      this->sendAllAttributesToServer();
493
494      // Send all attributes of current calendar
495      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer();
496
497      // We have enough information to send to server
498      // First of all, send all enabled files
499      sendEnabledFiles();
500
501      // Then, send all enabled fields
502      sendEnabledFields();
503
504      // At last, we have all info of domain and axis, then send them
505       sendRefDomainsAxis();
506
507       // After that, send all grid (if any)
508       sendRefGrid();
509
510       // We have a xml tree on the server side and now, it should be also processed
511       sendPostProcessing();
512     }
513     allProcessed = true;
514   }
515
516   void CContext::sendPostProcessingGlobalAttributes()
517   {
518      // Use correct context client to send message
519     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
520    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
521     for (int i = 0; i < nbSrvPools; ++i)
522     {
523       CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
524       CEventClient event(getType(),EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES);
525
526       if (contextClientTmp->isServerLeader())
527       {
528         CMessage msg;
529         msg<<this->getIdServer();
530         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
531         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
532           event.push(*itRank,1,msg);
533         contextClientTmp->sendEvent(event);
534       }
535       else contextClientTmp->sendEvent(event);
536     }
537   }
538
539   void CContext::recvPostProcessingGlobalAttributes(CEventServer& event)
540   {
541      CBufferIn* buffer=event.subEvents.begin()->buffer;
542      string id;
543      *buffer>>id;
544      // get(id)->recvPostProcessingGlobalAttributes(*buffer);
545   }
546
547   void CContext::recvPostProcessingGlobalAttributes(CBufferIn& buffer)
548   {
549      // CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
550      postProcessingGlobalAttributes();
551   }
552
553   /*!
554   \brief Close all the context defintion and do processing data
555      After everything is well defined on client side, they will be processed and sent to server
556   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
557   all necessary information to server, from which each server can build its own database.
558   Because the role of server is to write out field data on a specific netcdf file,
559   the only information that it needs is the enabled files
560   and the active fields (fields will be written onto active files)
561   */
562   void CContext::closeDefinition(void)
563   {
564     // There is nothing client need to send to server
565//      if (hasClient)
566//     if (hasClient && !hasServer)
567//      if (hasClient)
568//      {
569//        // After xml is parsed, there are some more works with post processing
570//        postProcessing();
571//      }
572
573//      setClientServerBuffer();
574
575// //     if (hasClient && !hasServer)
576//      if (hasClient)
577//      {
578//       // Send all attributes of current context to server
579//       this->sendAllAttributesToServer();
580
581//       // Send all attributes of current calendar
582//       CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer();
583
584//       // We have enough information to send to server
585//       // First of all, send all enabled files
586//        sendEnabledFiles();
587
588//       // Then, send all enabled fields
589//        sendEnabledFields();
590
591//       // At last, we have all info of domain and axis, then send them
592//        sendRefDomainsAxis();
593
594//       // After that, send all grid (if any)
595//        sendRefGrid();
596
597//        // // We have a xml tree on the server side and now, it should be also processed
598//        sendPostProcessing();
599//      }
600
601
602     // Now tell server that it can process all messages from client
603     // if (hasClient) this->sendCloseDefinition();
604    postProcessingGlobalAttributes();
605
606    if (hasClient) sendPostProcessingGlobalAttributes();
607
608    // There are some processings that should be done after all of above. For example: check mask or index
609    this->buildFilterGraphOfEnabledFields();
610   
611     if (hasClient && !hasServer)
612    {
613      // this->buildFilterGraphOfEnabledFields();  // references are resolved here (access xml file)
614      buildFilterGraphOfFieldsWithReadAccess();
615      // this->solveAllRefOfEnabledFields(true);
616    }
617
618    // if (hasClient) this->solveAllRefOfEnabledFields(true);
619    this->processGridEnabledFields();
620    if (hasClient) this->sendProcessingGridOfEnabledFields();
621    // if (hasClient)        // We have a xml tree on the server side and now, it should be also processed
622    //    sendPostProcessing();
623//    // Now tell server that it can process all messages from client
624////    if (hasClient && !hasServer) this->sendCloseDefinition();
625   if (hasClient) this->sendCloseDefinition();
626
627    // Nettoyage de l'arborescence
628//    if (hasClient && !hasServer) CleanTree(); // Only on client side??
629    if (hasClient) CleanTree(); // Only on client side??
630
631    if (hasClient)
632    {
633      sendCreateFileHeader();
634      if (!hasServer) startPrefetchingOfEnabledReadModeFiles();
635    }
636   }
637
638   void CContext::findAllEnabledFields(void)
639   {
640     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
641     (void)this->enabledFiles[i]->getEnabledFields();
642   }
643
644   void CContext::findAllEnabledFieldsInReadModeFiles(void)
645   {
646     for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
647     (void)this->enabledReadModeFiles[i]->getEnabledFields();
648   }
649
650   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
651   {
652      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
653        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
654   }
655
656   void CContext::solveAllEnabledFields()
657   {
658     int size = this->enabledFiles.size();
659     for (int i = 0; i < size; ++i)
660     {
661       this->enabledFiles[i]->solveOnlyRefOfEnabledFields(false);
662     }
663
664     for (int i = 0; i < size; ++i)
665     {
666       this->enabledFiles[i]->generateNewTransformationGridDest();
667     }
668   }
669
670   void CContext::processGridEnabledFields()
671   {
672     int size = this->enabledFiles.size();
673     for (int i = 0; i < size; ++i)
674     {
675       this->enabledFiles[i]->checkGridOfEnabledFields();
676       this->enabledFiles[i]->sendGridOfEnabledFields();
677     }
678   }
679
680
681
682   void CContext::solveOnlyRefOfEnabledFields(bool sendToServer)
683   {
684     int size = this->enabledFiles.size();
685     for (int i = 0; i < size; ++i)
686     {
687       this->enabledFiles[i]->solveOnlyRefOfEnabledFields(sendToServer);
688     }
689
690     for (int i = 0; i < size; ++i)
691     {
692       this->enabledFiles[i]->generateNewTransformationGridDest();
693     }
694
695     for (int i = 0; i < size; ++i)
696     {
697       //this->enabledFiles[i]->checkGridOfEnabledFields();
698     }
699   }
700
701   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
702   {
703     int size = this->enabledFiles.size();
704     for (int i = 0; i < size; ++i)
705     {
706       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
707     }
708   }
709
710   void CContext::buildFilterGraphOfEnabledFields()
711   {
712     int size = this->enabledFiles.size();
713     for (int i = 0; i < size; ++i)
714     {
715       this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);
716     }
717   }
718
719   void CContext::startPrefetchingOfEnabledReadModeFiles()
720   {
721     int size = enabledReadModeFiles.size();
722     for (int i = 0; i < size; ++i)
723     {
724        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
725     }
726   }
727
728   void CContext::checkPrefetchingOfEnabledReadModeFiles()
729   {
730     int size = enabledReadModeFiles.size();
731     for (int i = 0; i < size; ++i)
732     {
733        enabledReadModeFiles[i]->prefetchEnabledReadModeFieldsIfNeeded();
734     }
735   }
736
737  void CContext::findFieldsWithReadAccess(void)
738  {
739    fieldsWithReadAccess.clear();
740    const vector<CField*> allFields = CField::getAll();
741    for (size_t i = 0; i < allFields.size(); ++i)
742    {
743      CField* field = allFields[i];
744
745      if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)
746        field->read_access = true;
747      else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
748        fieldsWithReadAccess.push_back(field);
749    }
750  }
751
752  void CContext::solveAllRefOfFieldsWithReadAccess()
753  {
754    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
755      fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false);
756  }
757
758  void CContext::buildFilterGraphOfFieldsWithReadAccess()
759  {
760    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
761      fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true);
762  }
763
764   void CContext::solveAllInheritance(bool apply)
765   {
766     // Résolution des héritages descendants (càd des héritages de groupes)
767     // pour chacun des contextes.
768      solveDescInheritance(apply);
769
770     // Résolution des héritages par référence au niveau des fichiers.
771      const vector<CFile*> allFiles=CFile::getAll();
772      const vector<CGrid*> allGrids= CGrid::getAll();
773
774      if (hasClient && !hasServer)
775      //if (hasClient)
776      {
777        for (unsigned int i = 0; i < allFiles.size(); i++)
778          allFiles[i]->solveFieldRefInheritance(apply);
779      }
780
781      unsigned int vecSize = allGrids.size();
782      unsigned int i = 0;
783      for (i = 0; i < vecSize; ++i)
784        allGrids[i]->solveDomainAxisRefInheritance(apply);
785
786   }
787
788   void CContext::findEnabledFiles(void)
789   {
790      const std::vector<CFile*> allFiles = CFile::getAll();
791
792      for (unsigned int i = 0; i < allFiles.size(); i++)
793         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
794         {
795            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
796               enabledFiles.push_back(allFiles[i]);
797         }
798         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
799
800
801      if (enabledFiles.size() == 0)
802         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
803               << getId() << "\" !");
804
805      // Assigning contextClient to each enabled file
806      if (hasClient)
807      {
808        for (int i = 0; i < enabledFiles.size(); ++i)
809        {
810          if (hasServer)
811          {
812            int srvId = i % clientPrimServer.size();
813            enabledFiles[i]->setContextClient(clientPrimServer[srvId]);
814          }
815          else
816            enabledFiles[i]->setContextClient(client);
817        }
818      }
819   }
820
821   void CContext::findEnabledReadModeFiles(void)
822   {
823     int size = this->enabledFiles.size();
824     for (int i = 0; i < size; ++i)
825     {
826       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
827        enabledReadModeFiles.push_back(enabledFiles[i]);
828     }
829   }
830
831   void CContext::closeAllFile(void)
832   {
833     std::vector<CFile*>::const_iterator
834            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
835
836     for (; it != end; it++)
837     {
838       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
839       (*it)->close();
840     }
841   }
842
843   /*!
844   \brief Dispatch event received from client
845      Whenever a message is received in buffer of server, it will be processed depending on
846   its event type. A new event type should be added in the switch list to make sure
847   it processed on server side.
848   \param [in] event: Received message
849   */
850   bool CContext::dispatchEvent(CEventServer& event)
851   {
852
853      if (SuperClass::dispatchEvent(event)) return true;
854      else
855      {
856        switch(event.type)
857        {
858           case EVENT_ID_CLOSE_DEFINITION :
859             recvCloseDefinition(event);
860             return true;
861             break;
862           case EVENT_ID_UPDATE_CALENDAR:
863             recvUpdateCalendar(event);
864             return true;
865             break;
866           case EVENT_ID_CREATE_FILE_HEADER :
867             recvCreateFileHeader(event);
868             return true;
869             break;
870           case EVENT_ID_POST_PROCESS:
871             recvPostProcessing(event);
872             return true;
873            case EVENT_ID_SEND_REGISTRY:
874             recvRegistry(event);
875             return true;
876             break;
877            case EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES:
878             recvPostProcessingGlobalAttributes(event);
879             return true;
880             break;
881            case EVENT_ID_PROCESS_GRID_ENABLED_FIELDS:
882             recvProcessingGridOfEnabledFields(event);
883             return true;
884             break;
885           default :
886             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
887                    <<"Unknown Event");
888           return false;
889         }
890      }
891   }
892
893//   // Only send close definition from process having hasClient
894//   void CContext::sendCloseDefinitionToServer(void)
895//   {
896//     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
897//   }
898
899   //! Client side: Send a message to server to make it close
900   void CContext::sendCloseDefinition(void)
901   {
902     // Use correct context client to send message
903     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
904     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
905     for (int i = 0; i < nbSrvPools; ++i)
906     {
907       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
908       CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
909       if (contextClientTmp->isServerLeader())
910       {
911         CMessage msg;
912         if (hasServer)
913           msg<<this->getIdServer(i);
914         else
915           msg<<this->getIdServer();
916         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
917         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
918           event.push(*itRank,1,msg);
919         contextClientTmp->sendEvent(event);
920       }
921       else contextClientTmp->sendEvent(event);
922     }
923   }
924
925   //! Server side: Receive a message of client announcing a context close
926   void CContext::recvCloseDefinition(CEventServer& event)
927   {
928      CBufferIn* buffer=event.subEvents.begin()->buffer;
929      string id;
930      *buffer>>id;
931      get(id)->closeDefinition();
932   }
933
934   //! Client side: Send a message to update calendar in each time step
935   void CContext::sendUpdateCalendar(int step)
936   {
937     // Use correct context client to send message
938//     CContextClient* contextClientTmp = (0 != clientPrimServer) ? clientPrimServer : client;
939     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
940    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
941     for (int i = 0; i < nbSrvPools; ++i)
942     {
943       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
944       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
945
946         if (contextClientTmp->isServerLeader())
947         {
948           CMessage msg;
949           if (hasServer)
950             msg<<this->getIdServer(i)<<step;
951           else
952             msg<<this->getIdServer()<<step;
953           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
954           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
955             event.push(*itRank,1,msg);
956           contextClientTmp->sendEvent(event);
957         }
958         else contextClientTmp->sendEvent(event);
959     }
960   }
961
962   //! Server side: Receive a message of client annoucing calendar update
963   void CContext::recvUpdateCalendar(CEventServer& event)
964   {
965      CBufferIn* buffer=event.subEvents.begin()->buffer;
966      string id;
967      *buffer>>id;
968      get(id)->recvUpdateCalendar(*buffer);
969   }
970
971   //! Server side: Receive a message of client annoucing calendar update
972   void CContext::recvUpdateCalendar(CBufferIn& buffer)
973   {
974      int step;
975      buffer>>step;
976      updateCalendar(step);
977      if (hasClient && hasServer)
978      {       
979        sendUpdateCalendar(step);
980      }
981   }
982
983   //! Client side: Send a message to create header part of netcdf file
984   void CContext::sendCreateFileHeader(void)
985   {
986     // Use correct context client to send message
987     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
988     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
989     for (int i = 0; i < nbSrvPools; ++i)
990     {
991       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
992       CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
993
994       if (contextClientTmp->isServerLeader())
995       {
996         CMessage msg;
997         if (hasServer)
998           msg<<this->getIdServer(i);
999         else
1000           msg<<this->getIdServer();
1001         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1002         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1003           event.push(*itRank,1,msg) ;
1004         contextClientTmp->sendEvent(event);
1005       }
1006       else contextClientTmp->sendEvent(event);
1007     }
1008   }
1009
1010   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1011   void CContext::recvCreateFileHeader(CEventServer& event)
1012   {
1013      CBufferIn* buffer=event.subEvents.begin()->buffer;
1014      string id;
1015      *buffer>>id;
1016      get(id)->recvCreateFileHeader(*buffer);
1017   }
1018
1019   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
1020   void CContext::recvCreateFileHeader(CBufferIn& buffer)
1021   {
1022     // The creation of header file should be delegated to server2, for now
1023      // if (hasClient && hasServer)
1024      // {       
1025      //   sendCreateFileHeader();
1026      // }
1027     
1028      if (!hasClient && hasServer) 
1029        createFileHeader();
1030   }
1031
1032   //! Client side: Send a message to do some post processing on server
1033   void CContext::sendProcessingGridOfEnabledFields()
1034   {
1035      // Use correct context client to send message
1036     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
1037     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1038     for (int i = 0; i < nbSrvPools; ++i)
1039     {
1040       CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
1041       CEventClient event(getType(),EVENT_ID_PROCESS_GRID_ENABLED_FIELDS);
1042
1043       if (contextClientTmp->isServerLeader())
1044       {
1045         CMessage msg;
1046         msg<<this->getIdServer();
1047         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1048         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1049           event.push(*itRank,1,msg);
1050         contextClientTmp->sendEvent(event);
1051       }
1052       else contextClientTmp->sendEvent(event);
1053     }
1054   }
1055
1056   //! Server side: Receive a message to do some post processing
1057   void CContext::recvProcessingGridOfEnabledFields(CEventServer& event)
1058   {
1059      CBufferIn* buffer=event.subEvents.begin()->buffer;
1060      string id;
1061      *buffer>>id;
1062      // get(id)->processGridEnabledFields();
1063   }
1064
1065   //! Client side: Send a message to do some post processing on server
1066   void CContext::sendPostProcessing()
1067   {
1068      // Use correct context client to send message
1069     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
1070     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1071     for (int i = 0; i < nbSrvPools; ++i)
1072     {
1073       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1074       CEventClient event(getType(),EVENT_ID_POST_PROCESS);
1075       if (contextClientTmp->isServerLeader())
1076       {
1077         CMessage msg;
1078         if (hasServer)
1079           msg<<this->getIdServer(i);
1080         else
1081           msg<<this->getIdServer();
1082         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1083         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1084         event.push(*itRank,1,msg);
1085         contextClientTmp->sendEvent(event);
1086       }
1087       else contextClientTmp->sendEvent(event);
1088     }
1089   }
1090
1091   //! Server side: Receive a message to do some post processing
1092   void CContext::recvPostProcessing(CEventServer& event)
1093   {
1094      CBufferIn* buffer=event.subEvents.begin()->buffer;
1095      string id;
1096      *buffer>>id;
1097      get(id)->recvPostProcessing(*buffer);
1098   }
1099
1100   //! Server side: Receive a message to do some post processing
1101   void CContext::recvPostProcessing(CBufferIn& buffer)
1102   {
1103      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
1104      postProcessing();
1105   }
1106
1107   const StdString& CContext::getIdServer()
1108   {
1109      if (hasClient)
1110      {
1111        idServer_ = this->getId();
1112        idServer_ += "_server";
1113        return idServer_;
1114      }
1115      if (hasServer) return (this->getId());
1116   }
1117
1118   const StdString& CContext::getIdServer(const int i)
1119   {
1120     idServer_ = this->getId();
1121     idServer_ += "_server_";
1122     idServer_ += boost::lexical_cast<string>(i);
1123     return idServer_;
1124   }
1125
1126
1127   /*!
1128   \brief Do some simple post processings after parsing xml file
1129      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
1130   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
1131   which will be written out into netcdf files, are processed
1132   */
1133   void CContext::postProcessing()
1134   {
1135     if (isPostProcessed) return;
1136
1137      // Make sure the calendar was correctly created
1138      if (!calendar)
1139        ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
1140      else if (calendar->getTimeStep() == NoneDu)
1141        ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
1142      // Calendar first update to set the current date equals to the start date
1143      calendar->update(0);
1144
1145      // Find all inheritance in xml structure
1146      this->solveAllInheritance();
1147
1148//      ShowTree(info(10));
1149
1150      // Check if some axis, domains or grids are eligible to for compressed indexed output.
1151      // Warning: This must be done after solving the inheritance and before the rest of post-processing
1152      checkAxisDomainsGridsEligibilityForCompressedOutput();     
1153
1154      // Check if some automatic time series should be generated
1155      // Warning: This must be done after solving the inheritance and before the rest of post-processing
1156      // prepareTimeseries();
1157
1158      // The timeseries should only be prepared in client
1159      if (hasClient && !hasServer) prepareTimeseries();
1160
1161      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
1162      this->findEnabledFiles();
1163      // this->findEnabledReadModeFiles();
1164      // For now, only read files with client and only one level server
1165      if (hasClient && !hasServer) this->findEnabledReadModeFiles();
1166
1167
1168      // Find all enabled fields of each file
1169      this->findAllEnabledFields();
1170      // this->findAllEnabledFieldsInReadModeFiles();
1171      // For now, only read files with client and only one level server
1172      if (hasClient && !hasServer) this->findAllEnabledFieldsInReadModeFiles();
1173
1174//     if (hasClient)
1175     if (hasClient && !hasServer)
1176     {
1177      // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis)
1178      this->readAttributesOfEnabledFieldsInReadModeFiles();
1179     }
1180
1181      // // Only search and rebuild all reference objects of enable fields, don't transform
1182      // this->solveOnlyRefOfEnabledFields(false);
1183
1184      // // Search and rebuild all reference object of enabled fields
1185      // this->solveAllRefOfEnabledFields(false);
1186
1187      // // Find all fields with read access from the public API
1188      // findFieldsWithReadAccess();
1189      // // and solve the all reference for them
1190      // solveAllRefOfFieldsWithReadAccess();
1191
1192      // Only search and rebuild all reference objects of enable fields, don't transform
1193      if (hasClient) this->solveOnlyRefOfEnabledFields(false);
1194
1195      // Search and rebuild all reference object of enabled fields
1196      // if (hasClient) this->solveAllRefOfEnabledFields(false);
1197
1198      // Find all fields with read access from the public API
1199      if (hasClient && !hasServer) findFieldsWithReadAccess();
1200      // and solve the all reference for them
1201      if (hasClient && !hasServer) solveAllRefOfFieldsWithReadAccess();
1202
1203      isPostProcessed = true;
1204   }
1205
1206   /*!
1207    * Compute the required buffer size to send the attributes (mostly those grid related).
1208    *
1209    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1210    */
1211   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize)
1212   {
1213     std::map<int, StdSize> attributesSize;
1214
1215     if (hasClient)
1216     {
1217       size_t numEnabledFiles = this->enabledFiles.size();
1218       for (size_t i = 0; i < numEnabledFiles; ++i)
1219       {
1220         CFile* file = this->enabledFiles[i];
1221
1222         std::vector<CField*> enabledFields = file->getEnabledFields();
1223         size_t numEnabledFields = enabledFields.size();
1224         for (size_t j = 0; j < numEnabledFields; ++j)
1225         {
1226           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize();
1227           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1228           for (; it != itE; ++it)
1229           {
1230             // If attributesSize[it->first] does not exist, it will be zero-initialized
1231             // so we can use it safely without checking for its existance
1232             if (attributesSize[it->first] < it->second)
1233               attributesSize[it->first] = it->second;
1234
1235             if (maxEventSize[it->first] < it->second)
1236               maxEventSize[it->first] = it->second;
1237           }
1238         }
1239       }
1240     }
1241
1242     return attributesSize;
1243   }
1244
1245   /*!
1246    * Compute the required buffer size to send the fields data.
1247    *
1248    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1249    */
1250   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize)
1251   {
1252     CFile::mode_attr::t_enum mode = hasClient ? CFile::mode_attr::write : CFile::mode_attr::read;
1253
1254     std::map<int, StdSize> dataSize;
1255
1256     // Find all reference domain and axis of all active fields
1257     size_t numEnabledFiles = this->enabledFiles.size();
1258     for (size_t i = 0; i < numEnabledFiles; ++i)
1259     {
1260       CFile* file = this->enabledFiles[i];
1261       CFile::mode_attr::t_enum fileMode = file->mode.isEmpty() ? CFile::mode_attr::write : file->mode.getValue();
1262
1263       if (fileMode == mode)
1264       {
1265         std::vector<CField*> enabledFields = file->getEnabledFields();
1266         size_t numEnabledFields = enabledFields.size();
1267         for (size_t j = 0; j < numEnabledFields; ++j)
1268         {
1269           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize();
1270           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1271           for (; it != itE; ++it)
1272           {
1273             // If dataSize[it->first] does not exist, it will be zero-initialized
1274             // so we can use it safely without checking for its existance
1275             if (CXios::isOptPerformance)
1276               dataSize[it->first] += it->second;
1277             else if (dataSize[it->first] < it->second)
1278               dataSize[it->first] = it->second;
1279
1280             if (maxEventSize[it->first] < it->second)
1281               maxEventSize[it->first] = it->second;
1282           }
1283         }
1284       }
1285     }
1286
1287     return dataSize;
1288   }
1289
1290   //! Client side: Send infomation of active files (files are enabled to write out)
1291   void CContext::sendEnabledFiles()
1292   {
1293     int size = this->enabledFiles.size();
1294
1295     // In a context, each type has a root definition, e.g: axis, domain, field.
1296     // Every object must be a child of one of these root definition. In this case
1297     // all new file objects created on server must be children of the root "file_definition"
1298     StdString fileDefRoot("file_definition");
1299     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1300     for (int i = 0; i < size; ++i)
1301     {
1302       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId(),enabledFiles[i]->getContextClient());
1303       this->enabledFiles[i]->sendAllAttributesToServer(enabledFiles[i]->getContextClient());
1304       this->enabledFiles[i]->sendAddAllVariables(enabledFiles[i]->getContextClient());
1305     }
1306   }
1307
1308   //! Client side: Send information of active fields (ones are written onto files)
1309   void CContext::sendEnabledFields()
1310   {
1311     int size = this->enabledFiles.size();
1312     for (int i = 0; i < size; ++i)
1313     {
1314       this->enabledFiles[i]->sendEnabledFields(enabledFiles[i]->getContextClient());
1315     }
1316   }
1317
1318   //! Client side: Check if the defined axis, domains and grids are eligible for compressed indexed output
1319   void CContext::checkAxisDomainsGridsEligibilityForCompressedOutput()
1320   {
1321     if (!hasClient) return;
1322
1323     const vector<CAxis*> allAxis = CAxis::getAll();
1324     for (vector<CAxis*>::const_iterator it = allAxis.begin(); it != allAxis.end(); it++)
1325       (*it)->checkEligibilityForCompressedOutput();
1326
1327     const vector<CDomain*> allDomains = CDomain::getAll();
1328     for (vector<CDomain*>::const_iterator it = allDomains.begin(); it != allDomains.end(); it++)
1329       (*it)->checkEligibilityForCompressedOutput();
1330
1331     const vector<CGrid*> allGrids = CGrid::getAll();
1332     for (vector<CGrid*>::const_iterator it = allGrids.begin(); it != allGrids.end(); it++)
1333       (*it)->checkEligibilityForCompressedOutput();
1334   }
1335
1336   //! Client side: Prepare the timeseries by adding the necessary files
1337   void CContext::prepareTimeseries()
1338   {
1339     if (!hasClient) return;
1340
1341     const std::vector<CFile*> allFiles = CFile::getAll();
1342     for (size_t i = 0; i < allFiles.size(); i++)
1343     {
1344       CFile* file = allFiles[i];
1345
1346       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1347       {
1348         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : file->getFileOutputName();
1349
1350         const std::vector<CField*> allFields = file->getAllFields();
1351         for (size_t j = 0; j < allFields.size(); j++)
1352         {
1353           CField* field = allFields[j];
1354
1355           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
1356           {
1357             CFile* tsFile = CFile::create();
1358             tsFile->duplicateAttributes(file);
1359             tsFile->setVirtualVariableGroup(file->getVirtualVariableGroup());
1360
1361             tsFile->name = tsPrefix + "_";
1362             if (!field->name.isEmpty())
1363               tsFile->name.get() += field->name;
1364             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
1365               tsFile->name.get() += field->field_ref;
1366             else
1367               tsFile->name.get() += field->getId();
1368
1369             if (!field->ts_split_freq.isEmpty())
1370               tsFile->split_freq = field->ts_split_freq;
1371
1372             CField* tsField = tsFile->addField();
1373             tsField->field_ref = field->getId();
1374             tsField->setVirtualVariableGroup(field->getVirtualVariableGroup());
1375
1376             tsFile->solveFieldRefInheritance(true);
1377
1378             if (file->timeseries == CFile::timeseries_attr::exclusive)
1379               field->enabled = false;
1380           }
1381         }
1382
1383         // Finally disable the original file is need be
1384         if (file->timeseries == CFile::timeseries_attr::only)
1385          file->enabled = false;
1386       }
1387     }
1388   }
1389
1390   //! Client side: Send information of reference grid of active fields
1391   void CContext::sendRefGrid()
1392   {
1393     std::set<StdString> gridIds;
1394     int sizeFile = this->enabledFiles.size();
1395     CFile* filePtr(NULL);
1396
1397     // Firstly, find all reference grids of all active fields
1398     for (int i = 0; i < sizeFile; ++i)
1399     {
1400       filePtr = this->enabledFiles[i];
1401       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
1402       int sizeField = enabledFields.size();
1403       for (int numField = 0; numField < sizeField; ++numField)
1404       {
1405         if (0 != enabledFields[numField]->getRelGrid())
1406           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
1407       }
1408     }
1409
1410     // Create all reference grids on server side
1411     StdString gridDefRoot("grid_definition");
1412     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
1413     std::set<StdString>::const_iterator it, itE = gridIds.end();
1414     for (it = gridIds.begin(); it != itE; ++it)
1415     {
1416       gridPtr->sendCreateChild(*it);
1417       CGrid::get(*it)->sendAllAttributesToServer();
1418       CGrid::get(*it)->sendAllDomains();
1419       CGrid::get(*it)->sendAllAxis();
1420       CGrid::get(*it)->sendAllScalars();
1421     }
1422   }
1423
1424
1425   //! Client side: Send information of reference domain and axis of active fields
1426   void CContext::sendRefDomainsAxis()
1427   {
1428     std::set<StdString> domainIds, axisIds, scalarIds;
1429
1430     // Find all reference domain and axis of all active fields
1431     int numEnabledFiles = this->enabledFiles.size();
1432     for (int i = 0; i < numEnabledFiles; ++i)
1433     {
1434       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
1435       int numEnabledFields = enabledFields.size();
1436       for (int j = 0; j < numEnabledFields; ++j)
1437       {
1438         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
1439         if ("" != prDomAxisScalarId[0]) domainIds.insert(prDomAxisScalarId[0]);
1440         if ("" != prDomAxisScalarId[1]) axisIds.insert(prDomAxisScalarId[1]);
1441         if ("" != prDomAxisScalarId[2]) scalarIds.insert(prDomAxisScalarId[2]);
1442       }
1443     }
1444
1445     // Create all reference axis on server side
1446     std::set<StdString>::iterator itDom, itAxis, itScalar;
1447     std::set<StdString>::const_iterator itE;
1448
1449     StdString scalarDefRoot("scalar_definition");
1450     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
1451     itE = scalarIds.end();
1452     for (itScalar = scalarIds.begin(); itScalar != itE; ++itScalar)
1453     {
1454       if (!itScalar->empty())
1455       {
1456         scalarPtr->sendCreateChild(*itScalar);
1457         CScalar::get(*itScalar)->sendAllAttributesToServer();
1458       }
1459     }
1460
1461     StdString axiDefRoot("axis_definition");
1462     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
1463     itE = axisIds.end();
1464     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
1465     {
1466       if (!itAxis->empty())
1467       {
1468         axisPtr->sendCreateChild(*itAxis);
1469         CAxis::get(*itAxis)->sendAllAttributesToServer();
1470       }
1471     }
1472
1473     // Create all reference domains on server side
1474     StdString domDefRoot("domain_definition");
1475     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
1476     itE = domainIds.end();
1477     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
1478     {
1479       if (!itDom->empty()) {
1480          domPtr->sendCreateChild(*itDom);
1481          CDomain::get(*itDom)->sendAllAttributesToServer();
1482       }
1483     }
1484   }
1485
1486   //! Update calendar in each time step
1487   void CContext::updateCalendar(int step)
1488   {
1489      info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
1490      calendar->update(step);
1491      info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
1492
1493      if (hasClient)
1494      {
1495        checkPrefetchingOfEnabledReadModeFiles();
1496        garbageCollector.invalidate(calendar->getCurrentDate());
1497      }
1498   }
1499
1500   //! Server side: Create header of netcdf file
1501   void CContext::createFileHeader(void )
1502   {
1503      vector<CFile*>::const_iterator it;
1504
1505      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
1506      {
1507         (*it)->initFile();
1508      }
1509   }
1510
1511   //! Get current context
1512   CContext* CContext::getCurrent(void)
1513   {
1514     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
1515   }
1516
1517   /*!
1518   \brief Set context with an id be the current context
1519   \param [in] id identity of context to be set to current
1520   */
1521   void CContext::setCurrent(const string& id)
1522   {
1523     CObjectFactory::SetCurrentContextId(id);
1524     CGroupFactory::SetCurrentContextId(id);
1525   }
1526
1527  /*!
1528  \brief Create a context with specific id
1529  \param [in] id identity of new context
1530  \return pointer to the new context or already-existed one with identity id
1531  */
1532  CContext* CContext::create(const StdString& id)
1533  {
1534    CContext::setCurrent(id);
1535
1536    bool hasctxt = CContext::has(id);
1537    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
1538    getRoot();
1539    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
1540
1541#define DECLARE_NODE(Name_, name_) \
1542    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
1543#define DECLARE_NODE_PAR(Name_, name_)
1544#include "node_type.conf"
1545
1546    return (context);
1547  }
1548
1549
1550     //! Server side: Receive a message to do some post processing
1551  void CContext::recvRegistry(CEventServer& event)
1552  {
1553    CBufferIn* buffer=event.subEvents.begin()->buffer;
1554    string id;
1555    *buffer>>id;
1556    get(id)->recvRegistry(*buffer);
1557  }
1558
1559  void CContext::recvRegistry(CBufferIn& buffer)
1560  {
1561    if (server->intraCommRank==0)
1562    {
1563      CRegistry registry(server->intraComm) ;
1564      registry.fromBuffer(buffer) ;
1565      registryOut->mergeRegistry(registry) ;
1566    }
1567  }
1568
1569  void CContext::sendRegistry(void)
1570  {   
1571    registryOut->hierarchicalGatherRegistry() ;
1572
1573    // Use correct context client to send message
1574    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
1575    for (int i = 0; i < nbSrvPools; ++i)
1576    {
1577      CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1578      CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
1579        if (contextClientTmp->isServerLeader())
1580        {
1581           CMessage msg ;
1582           if (hasServer)
1583             msg<<this->getIdServer(i);
1584           else
1585             msg<<this->getIdServer();
1586           if (contextClientTmp->clientRank==0) msg<<*registryOut ;
1587           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1588           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1589             event.push(*itRank,1,msg);
1590           contextClientTmp->sendEvent(event);
1591         }
1592         else contextClientTmp->sendEvent(event);
1593    }
1594  }
1595
1596  bool CContext::isFinalized(void)
1597  {
1598    return finalized;
1599  }
1600
1601} // namespace xios
Note: See TracBrowser for help on using the repository browser.