New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
context.cpp in vendors/XIOS/current/src/node – NEMO

source: vendors/XIOS/current/src/node/context.cpp @ 3408

Last change on this file since 3408 was 3408, checked in by rblod, 12 years ago

importing initial XIOS vendor drop

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 17.4 KB
Line 
1#include "context.hpp"
2#include "attribute_template_impl.hpp"
3#include "object_template_impl.hpp"
4#include "group_template_impl.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
14namespace xios {
15 
16  shared_ptr<CContextGroup> CContext::root ;
17   
18   /// ////////////////////// Définitions ////////////////////// ///
19
20   CContext::CContext(void)
21      : CObjectTemplate<CContext>(), CContextAttributes()
22      , calendar(),hasClient(false),hasServer(false)
23   { /* Ne rien faire de plus */ }
24
25   CContext::CContext(const StdString & id)
26      : CObjectTemplate<CContext>(id), CContextAttributes()
27      , calendar(),hasClient(false),hasServer(false)
28   { /* Ne rien faire de plus */ }
29
30   CContext::~CContext(void)
31   { 
32     if (hasClient) delete client ;
33     if (hasServer) delete server ;
34   }
35
36   //----------------------------------------------------------------
37
38   StdString CContext::GetName(void)   { return (StdString("context")); }
39   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
40   ENodeType CContext::GetType(void)   { return (eContext); }
41
42   //----------------------------------------------------------------
43
44   CContextGroup* CContext::getRoot(void)
45   { 
46      if (root.get()==NULL) root=shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName())) ;
47      return root.get(); 
48   }
49   
50
51   //----------------------------------------------------------------
52
53   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
54   {
55      return (this->calendar);
56   }
57   
58   //----------------------------------------------------------------
59   
60   void CContext::setCalendar(boost::shared_ptr<CCalendar> newCalendar)
61   {
62      this->calendar = newCalendar;
63      calendar_type.setValue(this->calendar->getId());
64      start_date.setValue(this->calendar->getInitDate().toString());
65   }
66   
67   //----------------------------------------------------------------
68
69   void CContext::solveCalendar(void)
70   {
71      if (this->calendar.get() != NULL) return;
72      if (calendar_type.isEmpty() || start_date.isEmpty())
73         ERROR(" CContext::solveCalendar(void)",
74               << "[ context id = " << this->getId() << " ] "
75               << "Impossible de définir un calendrier (un attribut est manquant).");
76
77#define DECLARE_CALENDAR(MType  , mtype)                              \
78   if (calendar_type.getValue().compare(#mtype) == 0)                 \
79   {                                                                  \
80      if (time_origin.isEmpty())                                       \
81        this->calendar =  boost::shared_ptr<CCalendar>          \
82           (new C##MType##Calendar(start_date.getValue()));     \
83      else this->calendar =  boost::shared_ptr<CCalendar>       \
84           (new C##MType##Calendar(start_date.getValue(),time_origin.getValue()));     \
85      if (!this->timestep.isEmpty())                                  \
86       this->calendar->setTimeStep                                    \
87          (CDuration::FromString(this->timestep.getValue()));   \
88      return;                                                         \
89   }
90#include "calendar_type.conf"
91
92      ERROR("CContext::solveCalendar(void)",
93            << "[ calendar_type = " << calendar_type.getValue() << " ] "
94            << "Le calendrier n'est pas définie dans le code !");
95   }
96   
97   //----------------------------------------------------------------
98
99   void CContext::parse(xml::CXMLNode & node)
100   {
101      CContext::SuperClass::parse(node);
102
103      // PARSING POUR GESTION DES ENFANTS
104      xml::THashAttributes attributes = node.getAttributes();
105
106      if (attributes.end() != attributes.find("src"))
107      {
108         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
109         if (!ifs.good())
110            ERROR("CContext::parse(xml::CXMLNode & node)",
111                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
112         xml::CXMLParser::ParseInclude(ifs, *this);
113      }
114
115      if (node.getElementName().compare(CContext::GetName()))
116         DEBUG("Le noeud est mal nommé mais sera traité comme un contexte !");
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            { DEBUG(<< "Le noeud de définition possède un identifiant,"
132                    << " ce dernier ne sera pas pris en compte lors du traitement !"); }
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(<< "L'élément nommé \'"     << name
141                  << "\' dans le contexte \'" << CContext::getCurrent()->getId()
142                  << "\' ne représente pas une définition !");
143
144         } while (node.goToNextElement());
145
146         node.goToParentElement(); // Retour au parent
147      }
148   }
149
150   //----------------------------------------------------------------
151
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   void CContext::toBinary(StdOStream & os) const
177   {
178      SuperClass::toBinary(os);
179
180#define DECLARE_NODE(Name_, name_)                                         \
181   {                                                                       \
182      ENodeType renum = C##Name_##Definition::GetType();                   \
183      bool val = C##Name_##Definition::has(C##Name_##Definition::GetDefName()); \
184      os.write (reinterpret_cast<const char*>(&renum), sizeof(ENodeType)); \
185      os.write (reinterpret_cast<const char*>(&val), sizeof(bool));        \
186      if (val) C##Name_##Definition::get(C##Name_##Definition::GetDefName())->toBinary(os);   \
187   }   
188#define DECLARE_NODE_PAR(Name_, name_)
189#include "node_type.conf"
190   }
191   
192   //----------------------------------------------------------------
193   
194   void CContext::fromBinary(StdIStream & is)
195   {
196      SuperClass::fromBinary(is);
197#define DECLARE_NODE(Name_, name_)                                         \
198   {                                                                       \
199      bool val = false;                                                    \
200      ENodeType renum = Unknown;                                           \
201      is.read (reinterpret_cast<char*>(&renum), sizeof(ENodeType));        \
202      is.read (reinterpret_cast<char*>(&val), sizeof(bool));               \
203      if (renum != C##Name_##Definition::GetType())                        \
204         ERROR("CContext::fromBinary(StdIStream & is)",                    \
205               << "[ renum = " << renum << "] Bad type !");                \
206      if (val) C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> fromBinary(is); \
207   }   
208#define DECLARE_NODE_PAR(Name_, name_)
209#include "node_type.conf"
210     
211   }
212   
213   
214   //----------------------------------------------------------------
215
216   StdString CContext::toString(void) const
217   {
218      StdOStringStream oss;
219      oss << "<" << CContext::GetName()
220          << " id=\"" << this->getId() << "\" "
221          << SuperClassAttribute::toString() << ">" << std::endl;
222      if (!this->hasChild())
223      {
224         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
225      }
226      else
227      {
228
229#define DECLARE_NODE(Name_, name_)    \
230   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
231   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
232#define DECLARE_NODE_PAR(Name_, name_)
233#include "node_type.conf"
234
235      }
236
237      oss << "</" << CContext::GetName() << " >";
238
239      return (oss.str());
240   }
241
242   //----------------------------------------------------------------
243
244   void CContext::solveDescInheritance(const CAttributeMap * const UNUSED(parent))
245   {
246#define DECLARE_NODE(Name_, name_)    \
247   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
248     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance();
249#define DECLARE_NODE_PAR(Name_, name_)
250#include "node_type.conf"
251   }
252
253   //----------------------------------------------------------------
254
255   bool CContext::hasChild(void) const
256   {
257      return (
258#define DECLARE_NODE(Name_, name_)    \
259   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
260#define DECLARE_NODE_PAR(Name_, name_)
261#include "node_type.conf"
262      false);
263}
264
265   //----------------------------------------------------------------
266
267   void CContext::solveFieldRefInheritance(void)
268   {
269      if (!this->hasId()) return;
270      vector<CField*> allField = CField::getAll() ;
271//              = CObjectTemplate<CField>::GetAllVectobject(this->getId());
272      std::vector<CField*>::iterator
273         it = allField.begin(), end = allField.end();
274           
275      for (; it != end; it++)
276      {
277         CField* field = *it;
278         field->solveRefInheritance();
279      }
280   }
281
282   //----------------------------------------------------------------
283
284   void CContext::CleanTree(void)
285   {
286#define DECLARE_NODE(Name_, name_) C##Name_##Group::ClearAllAttributes();
287#define DECLARE_NODE_PAR(Name_, name_)
288#include "node_type.conf"
289   }
290   ///---------------------------------------------------------------
291   
292   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm)
293   {
294     hasClient=true ;
295     client = new CContextClient(this,intraComm, interComm) ;
296   } 
297
298   void CContext::initServer(MPI_Comm intraComm,MPI_Comm interComm)
299   {
300     hasServer=true ;
301     server = new CContextServer(this,intraComm,interComm) ;
302   } 
303
304   bool CContext::eventLoop(void)
305   {
306     return server->eventLoop() ;
307   } 
308   
309   void CContext::finalize(void)
310   {
311      if (hasClient && !hasServer)
312      {
313         client->finalize() ;
314      }
315      if (hasServer)
316      {
317        closeAllFile() ;
318      }
319   }
320       
321       
322 
323   
324   void CContext::closeDefinition(void)
325   {
326      if (hasClient && !hasServer) sendCloseDefinition() ;
327     
328      solveCalendar();         
329         
330      // Résolution des héritages pour le context actuel.
331      this->solveAllInheritance();
332
333      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
334      this->findEnabledFiles();
335
336      //Recherche des champs à sortir (enable à true + niveau de sortie correct)
337      // pour chaque fichier précédemment listé.
338      this->findAllEnabledFields();
339
340      // Résolution des références de grilles pour chacun des champs.
341      this->solveAllGridRef();
342
343      // Traitement des opérations.
344      this->solveAllOperation();
345
346      // Nettoyage de l'arborescence
347      CleanTree();
348      if (hasClient) sendCreateFileHeader() ;
349   }
350   
351   void CContext::findAllEnabledFields(void)
352   {
353     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
354     (void)this->enabledFiles[i]->getEnabledFields();
355   }
356
357   void CContext::solveAllGridRef(void)
358   {
359     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
360     this->enabledFiles[i]->solveEFGridRef();
361   }
362
363   void CContext::solveAllOperation(void)
364   {
365      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
366      this->enabledFiles[i]->solveEFOperation();
367   }
368
369   void CContext::solveAllInheritance(void)
370   {
371     // Résolution des héritages descendants (càd des héritages de groupes)
372     // pour chacun des contextes.
373      solveDescInheritance();
374
375     // Résolution des héritages par référence au niveau des fichiers.
376      const vector<CFile*> allFiles=CFile::getAll() ;
377
378      for (unsigned int i = 0; i < allFiles.size(); i++)
379         allFiles[i]->solveFieldRefInheritance();
380   }
381
382   void CContext::findEnabledFiles(void)
383   {
384      const std::vector<CFile*> allFiles = CFile::getAll();
385
386      for (unsigned int i = 0; i < allFiles.size(); i++)
387         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
388            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
389               enabledFiles.push_back(allFiles[i]);
390
391      if (enabledFiles.size() == 0)
392         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
393               << getId() << "\" !");
394   }
395
396   void CContext::closeAllFile(void)
397   {
398     std::vector<CFile*>::const_iterator
399            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
400         
401     for (; it != end; it++)
402     {
403       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
404       (*it)->close();
405     }
406   }
407   
408   bool CContext::dispatchEvent(CEventServer& event)
409   {
410     
411      if (SuperClass::dispatchEvent(event)) return true ;
412      else
413      {
414        switch(event.type)
415        {
416           case EVENT_ID_CLOSE_DEFINITION :
417             recvCloseDefinition(event) ;
418             return true ;
419             break ;
420           case EVENT_ID_UPDATE_CALENDAR :
421             recvUpdateCalendar(event) ;
422             return true ;
423             break ;
424           case EVENT_ID_CREATE_FILE_HEADER :
425             recvCreateFileHeader(event) ;
426             return true ;
427             break ;
428           default :
429             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
430                    <<"Unknown Event") ;
431           return false ;
432         }
433      }
434   }
435   
436   void CContext::sendCloseDefinition(void)
437   {
438
439     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION) ;   
440     if (client->isServerLeader())
441     {
442       CMessage msg ;
443       msg<<this->getId() ;
444       event.push(client->getServerLeader(),1,msg) ;
445       client->sendEvent(event) ;
446     }
447     else client->sendEvent(event) ;
448   }
449   
450   void CContext::recvCloseDefinition(CEventServer& event)
451   {
452     
453      CBufferIn* buffer=event.subEvents.begin()->buffer;
454      string id;
455      *buffer>>id ;
456      get(id)->closeDefinition() ;
457   }
458   
459   void CContext::sendUpdateCalendar(int step)
460   {
461     if (!hasServer)
462     {
463       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR) ;   
464       if (client->isServerLeader())
465       {
466         CMessage msg ;
467         msg<<this->getId()<<step ;
468         event.push(client->getServerLeader(),1,msg) ;
469         client->sendEvent(event) ;
470       }
471       else client->sendEvent(event) ;
472     }
473   }
474   
475   void CContext::recvUpdateCalendar(CEventServer& event)
476   {
477     
478      CBufferIn* buffer=event.subEvents.begin()->buffer;
479      string id;
480      *buffer>>id ;
481      get(id)->recvUpdateCalendar(*buffer) ;
482   }
483   
484   void CContext::recvUpdateCalendar(CBufferIn& buffer)
485   {
486      int step ;
487      buffer>>step ;
488      updateCalendar(step) ;
489   }
490   
491   void CContext::sendCreateFileHeader(void)
492   {
493
494     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER) ;   
495     if (client->isServerLeader())
496     {
497       CMessage msg ;
498       msg<<this->getId() ;
499       event.push(client->getServerLeader(),1,msg) ;
500       client->sendEvent(event) ;
501     }
502     else client->sendEvent(event) ;
503   }
504   
505   void CContext::recvCreateFileHeader(CEventServer& event)
506   {
507     
508      CBufferIn* buffer=event.subEvents.begin()->buffer;
509      string id;
510      *buffer>>id ;
511      get(id)->recvCreateFileHeader(*buffer) ;
512   }
513   
514   void CContext::recvCreateFileHeader(CBufferIn& buffer)
515   {
516      createFileHeader() ;
517   }
518   
519   void CContext::updateCalendar(int step)
520   {
521      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl ;
522      calendar->update(step) ;
523      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl ;
524   }
525 
526   void CContext::createFileHeader(void )
527   {
528      vector<CFile*>::const_iterator it ;
529         
530      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
531      {
532         (*it)->initFile();
533      }
534   } 
535   
536   CContext* CContext::getCurrent(void)
537   {
538     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get() ;
539   }
540   
541   void CContext::setCurrent(const string& id)
542   {
543     CObjectFactory::SetCurrentContextId(id);
544     CGroupFactory::SetCurrentContextId(id);
545   }
546   
547  CContext* CContext::create(const StdString& id)
548  {
549    CContext::setCurrent(id) ;
550 
551    bool hasctxt = CContext::has(id);
552    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
553    getRoot() ;
554    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
555
556#define DECLARE_NODE(Name_, name_) \
557    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
558#define DECLARE_NODE_PAR(Name_, name_)
559#include "node_type.conf"
560
561    return (context);
562  }
563} // namespace xios
Note: See TracBrowser for help on using the repository browser.