source: XIOS/trunk/src/node/context.cpp @ 421

Last change on this file since 421 was 421, checked in by ymipsl, 9 years ago

suppress warning due to french accents -> english traduction of error messages

YM

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