source: XIOS/dev/common/src/node/context.cpp @ 1293

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

nouvelle version de developpement de xios

  • nouvelle interface fortran
  • recodage complet de la couche de communication
  • et bien d'autres choses...

YM

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