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

Last change on this file since 1025 was 1025, checked in by mhnguyen, 7 years ago

Merging working version of coupler

+) Add some changes of domain and axis: Retransfer the atttributes in a generic ways for each level of client (or server)
+) Remove some spoiled files from the previous commits

Test
+) No test

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