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

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

dev: intermediate commit.

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