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

Last change on this file since 344 was 344, checked in by ymipsl, 11 years ago

remove obsolete method and member in context class

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