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

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

First working version with compression by secondary servers.

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