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

Last change on this file since 345 was 345, checked in by ymipsl, 12 years ago

removed "tree" namespace

YM

File size: 17.4 KB
Line 
1#include "context.hpp"
2#include "tree_manager.hpp"
3
4#include "attribute_template_impl.hpp"
5#include "object_template_impl.hpp"
6#include "group_template_impl.hpp"
7
8#include "calendar_type.hpp"
9#include "duration.hpp"
10
11#include "context_client.hpp"
12#include "context_server.hpp"
13#include "nc4_data_output.hpp"
14
15namespace xios {
16   
17   /// ////////////////////// Définitions ////////////////////// ///
18
19   CContext::CContext(void)
20      : CObjectTemplate<CContext>(), CContextAttributes()
21      , calendar(),hasClient(false),hasServer(false)
22   { /* Ne rien faire de plus */ }
23
24   CContext::CContext(const StdString & id)
25      : CObjectTemplate<CContext>(id), CContextAttributes()
26      , calendar(),hasClient(false),hasServer(false)
27   { /* Ne rien faire de plus */ }
28
29   CContext::~CContext(void)
30   { 
31     if (hasClient) delete client ;
32     if (hasServer) delete server ;
33   }
34
35   //----------------------------------------------------------------
36
37   StdString CContext::GetName(void)   { return (StdString("context")); }
38   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
39   ENodeType CContext::GetType(void)   { return (eContext); }
40
41   //----------------------------------------------------------------
42
43   boost::shared_ptr<CContextGroup> CContext::GetContextGroup(void)
44   { 
45      static boost::shared_ptr<CContextGroup> group_context
46                          (new CContextGroup(xml::CXMLNode::GetRootName()));
47      return (group_context); 
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   { CObjectFactory::CreateObject<C##Name_##Definition>(C##Name_##Definition::GetDefName()) -> parse(node); \
137   continue; }
138#define DECLARE_NODE_PAR(Name_, name_)
139#include "node_type.conf"
140
141            DEBUG(<< "L'élément nommé \'"     << name
142                  << "\' dans le contexte \'" << CObjectFactory::GetCurrentContextId()
143                  << "\' ne représente pas une définition !");
144
145         } while (node.goToNextElement());
146
147         node.goToParentElement(); // Retour au parent
148      }
149   }
150
151   //----------------------------------------------------------------
152
153   void CContext::ShowTree(StdOStream & out)
154   {
155      StdString currentContextId =
156         CObjectFactory::GetCurrentContextId();
157      std::vector<boost::shared_ptr<CContext> > def_vector =
158         CContext::GetContextGroup()->getChildList();
159      std::vector<boost::shared_ptr<CContext> >::iterator
160         it = def_vector.begin(), end = def_vector.end();
161
162      out << "<? xml version=\"1.0\" ?>" << std::endl;
163      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
164     
165      for (; it != end; it++)
166      {
167         boost::shared_ptr<CContext> context = *it;         
168         CTreeManager::SetCurrentContextId(context->getId());         
169         out << *context << std::endl;
170      }
171     
172      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
173      CTreeManager::SetCurrentContextId(currentContextId); 
174   }
175   
176   //----------------------------------------------------------------
177   
178   void CContext::toBinary(StdOStream & os) const
179   {
180      SuperClass::toBinary(os);
181       
182#define DECLARE_NODE(Name_, name_)                                         \
183   {                                                                       \
184      ENodeType renum = C##Name_##Definition::GetType();                   \
185      bool val = CObjectFactory::HasObject<C##Name_##Definition>           \
186                     (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) CObjectFactory::GetObject<C##Name_##Definition>             \
190                     (C##Name_##Definition::GetDefName())->toBinary(os);   \
191   }   
192#define DECLARE_NODE_PAR(Name_, name_)
193#include "node_type.conf"
194   }
195   
196   //----------------------------------------------------------------
197   
198   void CContext::fromBinary(StdIStream & is)
199   {
200      SuperClass::fromBinary(is);
201#define DECLARE_NODE(Name_, name_)                                         \
202   {                                                                       \
203      bool val = false;                                                    \
204      ENodeType renum = Unknown;                                           \
205      is.read (reinterpret_cast<char*>(&renum), sizeof(ENodeType));        \
206      is.read (reinterpret_cast<char*>(&val), sizeof(bool));               \
207      if (renum != C##Name_##Definition::GetType())                        \
208         ERROR("CContext::fromBinary(StdIStream & is)",                    \
209               << "[ renum = " << renum << "] Bad type !");                \
210      if (val) CObjectFactory::CreateObject<C##Name_##Definition>          \
211                   (C##Name_##Definition::GetDefName()) -> fromBinary(is); \
212   }   
213#define DECLARE_NODE_PAR(Name_, name_)
214#include "node_type.conf"
215     
216   }
217   
218   
219   //----------------------------------------------------------------
220
221   StdString CContext::toString(void) const
222   {
223      StdOStringStream oss;
224      oss << "<" << CContext::GetName()
225          << " id=\"" << this->getId() << "\" "
226          << SuperClassAttribute::toString() << ">" << std::endl;
227      if (!this->hasChild())
228      {
229         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
230      }
231      else
232      {
233
234#define DECLARE_NODE(Name_, name_)    \
235   if (CObjectFactory::HasObject<C##Name_##Definition>(C##Name_##Definition::GetDefName())) \
236   oss << *CObjectFactory::GetObject<C##Name_##Definition>(C##Name_##Definition::GetDefName()) << std::endl;
237#define DECLARE_NODE_PAR(Name_, name_)
238#include "node_type.conf"
239
240      }
241
242      oss << "</" << CContext::GetName() << " >";
243
244      return (oss.str());
245   }
246
247   //----------------------------------------------------------------
248
249   void CContext::solveDescInheritance(const CAttributeMap * const UNUSED(parent))
250   {
251#define DECLARE_NODE(Name_, name_)    \
252   if (CObjectFactory::HasObject<C##Name_##Definition>(C##Name_##Definition::GetDefName())) \
253   CObjectFactory::GetObject<C##Name_##Definition>(C##Name_##Definition::GetDefName())->solveDescInheritance();
254#define DECLARE_NODE_PAR(Name_, name_)
255#include "node_type.conf"
256   }
257
258   //----------------------------------------------------------------
259
260   bool CContext::hasChild(void) const
261   {
262      return (
263#define DECLARE_NODE(Name_, name_)    \
264   CObjectFactory::HasObject<C##Name_##Definition>  (C##Name_##Definition::GetDefName())   ||
265#define DECLARE_NODE_PAR(Name_, name_)
266#include "node_type.conf"
267      false);
268}
269
270   //----------------------------------------------------------------
271
272   void CContext::solveFieldRefInheritance(void)
273   {
274      if (!this->hasId()) return;
275      std::vector<boost::shared_ptr<CField> > allField
276               = CObjectTemplate<CField>::GetAllVectobject(this->getId());
277      std::vector<boost::shared_ptr<CField> >::iterator
278         it = allField.begin(), end = allField.end();
279           
280      for (; it != end; it++)
281      {
282         boost::shared_ptr<CField> field = *it;
283         field->solveRefInheritance();
284      }
285   }
286
287   //----------------------------------------------------------------
288
289   void CContext::CleanTree(void)
290   {
291#define DECLARE_NODE(Name_, name_) C##Name_##Group::ClearAllAttributes();
292#define DECLARE_NODE_PAR(Name_, name_)
293#include "node_type.conf"
294   }
295   ///---------------------------------------------------------------
296   
297   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm)
298   {
299     hasClient=true ;
300     client = new CContextClient(this,intraComm, interComm) ;
301   } 
302
303   void CContext::initServer(MPI_Comm intraComm,MPI_Comm interComm)
304   {
305     hasServer=true ;
306     server = new CContextServer(this,intraComm,interComm) ;
307   } 
308
309   bool CContext::eventLoop(void)
310   {
311     return server->eventLoop() ;
312   } 
313   
314   void CContext::finalize(void)
315   {
316      if (hasClient && !hasServer)
317      {
318         client->finalize() ;
319      }
320      if (hasServer)
321      {
322        closeAllFile() ;
323      }
324   }
325       
326       
327 
328   
329   void CContext::closeDefinition(void)
330   {
331      if (hasClient && !hasServer) sendCloseDefinition() ;
332     
333      solveCalendar();         
334         
335      // Résolution des héritages pour le context actuel.
336      this->solveAllInheritance();
337
338      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
339      this->findEnabledFiles();
340
341      //Recherche des champs à sortir (enable à true + niveau de sortie correct)
342      // pour chaque fichier précédemment listé.
343      this->findAllEnabledFields();
344
345      // Résolution des références de grilles pour chacun des champs.
346      this->solveAllGridRef();
347
348      // Traitement des opérations.
349      this->solveAllOperation();
350
351      // Nettoyage de l'arborescence
352      CleanTree();
353      if (hasClient) sendCreateFileHeader() ;
354   }
355   
356   void CContext::findAllEnabledFields(void)
357   {
358     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
359     (void)this->enabledFiles[i]->getEnabledFields();
360   }
361
362   void CContext::solveAllGridRef(void)
363   {
364     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
365     this->enabledFiles[i]->solveEFGridRef();
366   }
367
368   void CContext::solveAllOperation(void)
369   {
370      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
371      this->enabledFiles[i]->solveEFOperation();
372   }
373
374   void CContext::solveAllInheritance(void)
375   {
376     // Résolution des héritages descendants (càd des héritages de groupes)
377     // pour chacun des contextes.
378      solveDescInheritance();
379
380     // Résolution des héritages par référence au niveau des fichiers.
381      const std::vector<boost::shared_ptr<CFile> > & allFiles
382             = CObjectFactory::GetObjectVector<CFile>();
383
384      for (unsigned int i = 0; i < allFiles.size(); i++)
385         allFiles[i]->solveFieldRefInheritance();
386   }
387
388   void CContext::findEnabledFiles(void)
389   {
390      const std::vector<boost::shared_ptr<CFile> > & allFiles
391          = CObjectFactory::GetObjectVector<CFile>();
392
393      for (unsigned int i = 0; i < allFiles.size(); i++)
394         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
395            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
396               enabledFiles.push_back(allFiles[i]);
397
398      if (enabledFiles.size() == 0)
399         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
400               << getId() << "\" !");
401   }
402
403   void CContext::closeAllFile(void)
404   {
405     std::vector<boost::shared_ptr<CFile> >::const_iterator
406            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
407         
408     for (; it != end; it++)
409     {
410       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
411       (*it)->close();
412     }
413   }
414   
415   bool CContext::dispatchEvent(CEventServer& event)
416   {
417     
418      if (SuperClass::dispatchEvent(event)) return true ;
419      else
420      {
421        switch(event.type)
422        {
423           case EVENT_ID_CLOSE_DEFINITION :
424             recvCloseDefinition(event) ;
425             return true ;
426             break ;
427           case EVENT_ID_UPDATE_CALENDAR :
428             recvUpdateCalendar(event) ;
429             return true ;
430             break ;
431           case EVENT_ID_CREATE_FILE_HEADER :
432             recvCreateFileHeader(event) ;
433             return true ;
434             break ;
435           default :
436             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
437                    <<"Unknown Event") ;
438           return false ;
439         }
440      }
441   }
442   
443   void CContext::sendCloseDefinition(void)
444   {
445
446     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION) ;   
447     if (client->isServerLeader())
448     {
449       CMessage msg ;
450       msg<<this->getId() ;
451       event.push(client->getServerLeader(),1,msg) ;
452       client->sendEvent(event) ;
453     }
454     else client->sendEvent(event) ;
455   }
456   
457   void CContext::recvCloseDefinition(CEventServer& event)
458   {
459     
460      CBufferIn* buffer=event.subEvents.begin()->buffer;
461      string id;
462      *buffer>>id ;
463      get(id)->closeDefinition() ;
464   }
465   
466   void CContext::sendUpdateCalendar(int step)
467   {
468     if (!hasServer)
469     {
470       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR) ;   
471       if (client->isServerLeader())
472       {
473         CMessage msg ;
474         msg<<this->getId()<<step ;
475         event.push(client->getServerLeader(),1,msg) ;
476         client->sendEvent(event) ;
477       }
478       else client->sendEvent(event) ;
479     }
480   }
481   
482   void CContext::recvUpdateCalendar(CEventServer& event)
483   {
484     
485      CBufferIn* buffer=event.subEvents.begin()->buffer;
486      string id;
487      *buffer>>id ;
488      get(id)->recvUpdateCalendar(*buffer) ;
489   }
490   
491   void CContext::recvUpdateCalendar(CBufferIn& buffer)
492   {
493      int step ;
494      buffer>>step ;
495      updateCalendar(step) ;
496   }
497   
498   void CContext::sendCreateFileHeader(void)
499   {
500
501     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER) ;   
502     if (client->isServerLeader())
503     {
504       CMessage msg ;
505       msg<<this->getId() ;
506       event.push(client->getServerLeader(),1,msg) ;
507       client->sendEvent(event) ;
508     }
509     else client->sendEvent(event) ;
510   }
511   
512   void CContext::recvCreateFileHeader(CEventServer& event)
513   {
514     
515      CBufferIn* buffer=event.subEvents.begin()->buffer;
516      string id;
517      *buffer>>id ;
518      get(id)->recvCreateFileHeader(*buffer) ;
519   }
520   
521   void CContext::recvCreateFileHeader(CBufferIn& buffer)
522   {
523      createFileHeader() ;
524   }
525   
526   void CContext::updateCalendar(int step)
527   {
528      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl ;
529      calendar->update(step) ;
530      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl ;
531   }
532 
533   void CContext::createFileHeader(void )
534   {
535      vector<shared_ptr<CFile> >::const_iterator it ;
536         
537      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
538      {
539         (*it)->initFile();
540      }
541   } 
542   
543   shared_ptr<CContext> CContext::current(void)
544   {
545     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()) ;
546   }
547   
548} // namespace xios
Note: See TracBrowser for help on using the repository browser.