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

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

Minor modifications in the merged version of dev.

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