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

Last change on this file since 540 was 540, checked in by mhnguyen, 10 years ago

Reorganizing structure of grid

+) Grid doesn't have domain_ref and axis_ref anymore.
All domain and axis of a grid must be inside grid (These domain and axis can be defined or refer to others)
+) Grid contains list of domain and axis
+) Reorder some functions to make sure new functionlities work

Test
+) On Curie
+) Mode attached and detached
+) Only test_new_features
+) Passed

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
File size: 31.0 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), isPostProcessed(false), dataSize_(), idServer_()
26   { /* Ne rien faire de plus */ }
27
28   CContext::CContext(const StdString & id)
29      : CObjectTemplate<CContext>(id), CContextAttributes()
30      , calendar(),hasClient(false),hasServer(false), isPostProcessed(false), dataSize_(), idServer_()
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   //! Get name of context
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   \brief Get context group (context root)
48   \return Context root
49   */
50   CContextGroup* CContext::getRoot(void)
51   {
52      if (root.get()==NULL) root=shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName())) ;
53      return root.get();
54   }
55
56
57   //----------------------------------------------------------------
58   /*!
59   \brief Get calendar of a context
60   \return Calendar
61   */
62   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
63   {
64      return (this->calendar);
65   }
66
67   //----------------------------------------------------------------
68   /*!
69   \brief Set a context with a calendar
70   \param[in] newCalendar new calendar
71   */
72   void CContext::setCalendar(boost::shared_ptr<CCalendar> newCalendar)
73   {
74      this->calendar = newCalendar;
75      calendar_type.fromString(this->calendar->getId());
76      start_date.setValue(this->calendar->getInitDate());
77   }
78
79   //----------------------------------------------------------------
80   //! Process all information of calendar
81   void CContext::solveCalendar(void)
82   {
83      if (this->calendar.get() != NULL) return;
84      if (calendar_type.isEmpty())
85         ERROR(" CContext::solveCalendar(void)",
86               << "[ context id = " << this->getId() << " ] "
87               << "Impossible to define a calendar: the calendar type is missing.");
88      if (start_date.isEmpty())
89         ERROR(" CContext::solveCalendar(void)",
90               << "[ context id = " << this->getId() << " ] "
91               << "Impossible to define a calendar: the start date is missing.");
92      if (timestep.isEmpty())
93         ERROR(" CContext::solveCalendar(void)",
94               << "[ context id = " << this->getId() << " ] "
95               << "Impossible to define a calendar: the timestep is missing.");
96
97#define DECLARE_CALENDAR(MType, eType)                                             \
98  if (calendar_type.getValue() == eType)                                           \
99  {                                                                                \
100    if (time_origin.isEmpty())                                                     \
101      this->calendar = boost::shared_ptr<CCalendar>                                \
102          (new C##MType##Calendar(start_date.getValue()));                         \
103    else this->calendar = boost::shared_ptr<CCalendar>                             \
104          (new C##MType##Calendar(start_date.getValue(), time_origin.getValue())); \
105                                                                                   \
106    if (!start_date.getValue().setRelCalendar(*this->calendar))                    \
107      ERROR("CContext::solveCalendar(void)",                                       \
108            "start_date: Bad format or date not conform to the calendar");         \
109    if (!time_origin.getValue().setRelCalendar(*this->calendar))                   \
110      ERROR("CContext::solveCalendar(void)",                                       \
111            "time_origin: Bad format or date not conform to the calendar");        \
112                                                                                   \
113    this->calendar->setTimeStep(this->timestep.getValue());                        \
114                                                                                   \
115    return;                                                                        \
116  }
117#include "calendar_type.conf"
118#undef DECLARE_CALENDAR
119
120      ERROR("CContext::solveCalendar(void)",
121            << "[ calendar_type = " << calendar_type.getStringValue() << " ] "
122            << "The calendar is not properly handled!");
123   }
124
125   //----------------------------------------------------------------
126   /*!
127   \brief Parse xml file and write information into context object
128   \param [in] node xmld node corresponding in xml file
129   */
130   void CContext::parse(xml::CXMLNode & node)
131   {
132      CContext::SuperClass::parse(node);
133
134      // PARSING POUR GESTION DES ENFANTS
135      xml::THashAttributes attributes = node.getAttributes();
136
137      if (attributes.end() != attributes.find("src"))
138      {
139         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
140         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
141            ERROR("void CContext::parse(xml::CXMLNode & node)",
142                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
143         if (!ifs.good())
144            ERROR("CContext::parse(xml::CXMLNode & node)",
145                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
146         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
147      }
148
149      if (node.getElementName().compare(CContext::GetName()))
150         DEBUG("Le noeud is wrong defined but will be considered as a context !");
151
152      if (!(node.goToChildElement()))
153      {
154         DEBUG("Le context ne contient pas d'enfant !");
155      }
156      else
157      {
158         do { // Parcours des contextes pour traitement.
159
160            StdString name = node.getElementName();
161            attributes.clear();
162            attributes = node.getAttributes();
163
164            if (attributes.end() != attributes.find("id"))
165            {
166              DEBUG(<< "Definition node has an id,"
167                    << "it will not be taking account !");
168            }
169
170#define DECLARE_NODE(Name_, name_)    \
171   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
172   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node) ; continue; }
173#define DECLARE_NODE_PAR(Name_, name_)
174#include "node_type.conf"
175
176            DEBUG(<< "The element \'"     << name
177                  << "\' in the context \'" << CContext::getCurrent()->getId()
178                  << "\' is not a definition !");
179
180         } while (node.goToNextElement());
181
182         node.goToParentElement(); // Retour au parent
183      }
184   }
185
186   //----------------------------------------------------------------
187   //! Show tree structure of context
188   void CContext::ShowTree(StdOStream & out)
189   {
190      StdString currentContextId = CContext::getCurrent() -> getId() ;
191      std::vector<CContext*> def_vector =
192         CContext::getRoot()->getChildList();
193      std::vector<CContext*>::iterator
194         it = def_vector.begin(), end = def_vector.end();
195
196      out << "<? xml version=\"1.0\" ?>" << std::endl;
197      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
198
199      for (; it != end; it++)
200      {
201         CContext* context = *it;
202         CContext::setCurrent(context->getId());
203         out << *context << std::endl;
204      }
205
206      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
207      CContext::setCurrent(currentContextId);
208   }
209
210
211   //----------------------------------------------------------------
212
213   //! Convert context object into string (to print)
214   StdString CContext::toString(void) const
215   {
216      StdOStringStream oss;
217      oss << "<" << CContext::GetName()
218          << " id=\"" << this->getId() << "\" "
219          << SuperClassAttribute::toString() << ">" << std::endl;
220      if (!this->hasChild())
221      {
222         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
223      }
224      else
225      {
226
227#define DECLARE_NODE(Name_, name_)    \
228   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
229   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
230#define DECLARE_NODE_PAR(Name_, name_)
231#include "node_type.conf"
232
233      }
234
235      oss << "</" << CContext::GetName() << " >";
236
237      return (oss.str());
238   }
239
240   //----------------------------------------------------------------
241
242   /*!
243   \brief Find all inheritace among objects in a context.
244   \param [in] apply (true) write attributes of parent into ones of child if they are empty
245                     (false) write attributes of parent into a new container of child
246   \param [in] parent unused
247   */
248   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
249   {
250#define DECLARE_NODE(Name_, name_)    \
251   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
252     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
253#define DECLARE_NODE_PAR(Name_, name_)
254#include "node_type.conf"
255   }
256
257   //----------------------------------------------------------------
258
259   //! Verify if all root definition in the context have child.
260   bool CContext::hasChild(void) const
261   {
262      return (
263#define DECLARE_NODE(Name_, name_)    \
264   C##Name_##Definition::has(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(bool apply)
273//   {
274//      if (!this->hasId()) return;
275//      vector<CField*> allField = CField::getAll() ;
276////              = CObjectTemplate<CField>::GetAllVectobject(this->getId());
277//      std::vector<CField*>::iterator
278//         it = allField.begin(), end = allField.end();
279//
280//      for (; it != end; it++)
281//      {
282//         CField* field = *it;
283//         field->solveRefInheritance(apply);
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   //! Initialize client side
298   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer)
299   {
300     hasClient=true ;
301     client = new CContextClient(this,intraComm, interComm, cxtServer) ;
302   }
303
304   void CContext::setClientServerBuffer()
305   {
306     if (hasClient)
307     {
308       client->setBufferSize(getDataSize());
309     }
310   }
311
312   //! Verify whether a context is initialized
313   bool CContext::isInitialized(void)
314   {
315     return hasClient ;
316   }
317
318   //! Initialize server
319   void CContext::initServer(MPI_Comm intraComm,MPI_Comm interComm)
320   {
321     hasServer=true ;
322     server = new CContextServer(this,intraComm,interComm) ;
323   }
324
325   //! Server side: Put server into a loop in order to listen message from client
326   bool CContext::eventLoop(void)
327   {
328     return server->eventLoop() ;
329   }
330
331   //! Terminate a context
332   void CContext::finalize(void)
333   {
334      if (hasClient && !hasServer)
335      {
336         client->finalize() ;
337      }
338      if (hasServer)
339      {
340        closeAllFile() ;
341      }
342   }
343
344   /*!
345   \brief Close all the context defintion and do processing data
346      After everything is well defined on client side, they will be processed and sent to server
347   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
348   all necessary information to server, from which each server can build its own database.
349   Because the role of server is to write out field data on a specific netcdf file,
350   the only information that it needs is the enabled files
351   and the active fields (fields will be written onto active files)
352   */
353   void CContext::closeDefinition(void)
354   {
355
356     if (hasClient)
357     {
358       std::cout << "Current context " << *this << std::endl;
359       // After xml is parsed, there are some more works with post processing
360       postProcessing();
361//
362       setClientServerBuffer();
363     }
364
365     if (hasClient && !hasServer)
366     {
367       // After xml is parsed, there are some more works with post processing
368//       postProcessing();
369
370//       setClientServerBuffer();
371
372      // Send all attributes of current context to server
373      this->sendAllAttributesToServer();
374
375      // We have enough information to send to server
376      // First of all, send all enabled files
377       sendEnabledFiles();
378
379      // Then, send all enabled fields
380       sendEnabledFields();
381
382      // At last, we have all info of domain and axis, then send them
383       sendRefDomainsAxis();
384
385      // After that, send all grid (if any)
386       sendRefGrid();
387
388
389    }
390
391    // Now tell server that it can process all messages from client
392    if (hasClient && !hasServer) this->sendCloseDefinition();
393
394    // We have a xml tree on the server side and now, it should be also processed
395    if (hasClient && !hasServer) sendPostProcessing();
396
397    // There are some processings that should be done after all of above. For example: check mask or index
398//    if (hasClient && !hasServer)
399    if (hasClient)
400    {
401      this->solveAllRefOfEnabledFields(true);
402      this->buildAllExpressionOfEnabledFields();
403    }
404
405
406
407//      if (hasClient)
408//      {
409//        //solveCalendar();
410//
411//        // Résolution des héritages pour le context actuel.
412////        this->solveAllInheritance();
413//
414//
415////        //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
416////        this->findEnabledFiles();
417//
418//        this->processEnabledFiles() ;
419//
420//        this->solveAllGridRef();
421//      }
422
423
424
425
426//      solveCalendar();
427//
428//      // Résolution des héritages pour le context actuel.
429//      this->solveAllInheritance();
430//
431//      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
432//      this->findEnabledFiles();
433//
434//
435//      this->processEnabledFiles() ;
436
437/*
438      //Recherche des champs à sortir (enable à true + niveau de sortie correct)
439      // pour chaque fichier précédemment listé.
440      this->findAllEnabledFields();
441
442      // Résolution des références de grilles pour chacun des champs.
443      this->solveAllGridRef();
444
445      // Traitement des opérations.
446      this->solveAllOperation();
447
448      // Traitement des expressions.
449      this->solveAllExpression();
450*/
451      // Nettoyage de l'arborescence
452      if (hasClient && !hasServer) CleanTree(); // Only on client side??
453//      if (hasClient) CleanTree();
454      if (hasClient) sendCreateFileHeader() ;
455   }
456
457   void CContext::findAllEnabledFields(void)
458   {
459     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
460     (void)this->enabledFiles[i]->getEnabledFields();
461   }
462
463//    void CContext::processEnabledFiles(void)
464//   {
465//     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
466//     this->enabledFiles[i]->processEnabledFile();
467//   }
468
469
470   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
471   {
472     int size = this->enabledFiles.size();
473     for (int i = 0; i < size; ++i)
474     {
475       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
476     }
477   }
478
479   void CContext::buildAllExpressionOfEnabledFields()
480   {
481     int size = this->enabledFiles.size();
482     for (int i = 0; i < size; ++i)
483     {
484       this->enabledFiles[i]->buildAllExpressionOfEnabledFields();
485     }
486   }
487
488//   void CContext::solveAllGridRef(void)
489//   {
490//     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
491//     this->enabledFiles[i]->solveEFGridRef();
492//   }
493//
494//   void CContext::solveAllOperation(void)
495//   {
496//      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
497//      this->enabledFiles[i]->solveEFOperation();
498//   }
499//
500//   void CContext::solveAllExpression(void)
501//   {
502//      for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
503//      this->enabledFiles[i]->solveEFExpression();
504//   }
505
506   void CContext::solveAllInheritance(bool apply)
507   {
508     // Résolution des héritages descendants (càd des héritages de groupes)
509     // pour chacun des contextes.
510      solveDescInheritance(apply);
511
512     // Résolution des héritages par référence au niveau des fichiers.
513      const vector<CFile*> allFiles=CFile::getAll() ;
514      const vector<CGrid*> allGrids= CGrid::getAll();
515
516     //if (hasClient && !hasServer)
517      if (hasClient)
518      {
519        for (unsigned int i = 0; i < allFiles.size(); i++)
520          allFiles[i]->solveFieldRefInheritance(apply);
521      }
522
523      unsigned int vecSize = allGrids.size();
524      unsigned int i = 0;
525      for (i = 0; i < vecSize; ++i)
526        allGrids[i]->solveDomainAxisRefInheritance(apply);
527
528   }
529
530   void CContext::findEnabledFiles(void)
531   {
532      const std::vector<CFile*> allFiles = CFile::getAll();
533
534      for (unsigned int i = 0; i < allFiles.size(); i++)
535         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
536         {
537            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
538               enabledFiles.push_back(allFiles[i]);
539         }
540         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
541
542
543      if (enabledFiles.size() == 0)
544         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
545               << getId() << "\" !");
546   }
547
548   void CContext::closeAllFile(void)
549   {
550     std::vector<CFile*>::const_iterator
551            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
552
553     for (; it != end; it++)
554     {
555       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
556       (*it)->close();
557     }
558   }
559
560   /*!
561   \brief Dispatch event received from client
562      Whenever a message is received in buffer of server, it will be processed depending on
563   its event type. A new event type should be added in the switch list to make sure
564   it processed on server side.
565   \param [in] event: Received message
566   */
567   bool CContext::dispatchEvent(CEventServer& event)
568   {
569
570      if (SuperClass::dispatchEvent(event)) return true ;
571      else
572      {
573        switch(event.type)
574        {
575           case EVENT_ID_CLOSE_DEFINITION :
576             recvCloseDefinition(event) ;
577             return true ;
578             break ;
579           case EVENT_ID_UPDATE_CALENDAR :
580             recvUpdateCalendar(event) ;
581             return true ;
582             break ;
583           case EVENT_ID_CREATE_FILE_HEADER :
584             recvCreateFileHeader(event) ;
585             return true ;
586             break ;
587           case EVENT_ID_POST_PROCESS:
588             recvPostProcessing(event) ;
589             return true ;
590             break ;
591           default :
592             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
593                    <<"Unknown Event") ;
594           return false ;
595         }
596      }
597   }
598
599   //! Client side: Send a message to server to make it close
600   void CContext::sendCloseDefinition(void)
601   {
602     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION) ;
603     if (client->isServerLeader())
604     {
605       CMessage msg ;
606       msg<<this->getIdServer() ;
607       event.push(client->getServerLeader(),1,msg) ;
608       client->sendEvent(event) ;
609     }
610     else client->sendEvent(event) ;
611   }
612
613   //! Server side: Receive a message of client announcing a context close
614   void CContext::recvCloseDefinition(CEventServer& event)
615   {
616
617      CBufferIn* buffer=event.subEvents.begin()->buffer;
618      string id;
619      *buffer>>id ;
620      get(id)->closeDefinition();
621   }
622
623   //! Client side: Send a message to update calendar in each time step
624   void CContext::sendUpdateCalendar(int step)
625   {
626     if (!hasServer)
627     {
628       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR) ;
629       if (client->isServerLeader())
630       {
631         CMessage msg ;
632         msg<<this->getIdServer()<<step ;
633         event.push(client->getServerLeader(),1,msg) ;
634         client->sendEvent(event) ;
635       }
636       else client->sendEvent(event) ;
637     }
638   }
639
640   //! Server side: Receive a message of client annoucing calendar update
641   void CContext::recvUpdateCalendar(CEventServer& event)
642   {
643
644      CBufferIn* buffer=event.subEvents.begin()->buffer;
645      string id;
646      *buffer>>id ;
647      get(id)->recvUpdateCalendar(*buffer) ;
648   }
649
650   //! Server side: Receive a message of client annoucing calendar update
651   void CContext::recvUpdateCalendar(CBufferIn& buffer)
652   {
653      int step ;
654      buffer>>step ;
655      updateCalendar(step) ;
656   }
657
658   //! Client side: Send a message to create header part of netcdf file
659   void CContext::sendCreateFileHeader(void)
660   {
661     CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER) ;
662     if (client->isServerLeader())
663     {
664       CMessage msg ;
665       msg<<this->getIdServer() ;
666       event.push(client->getServerLeader(),1,msg) ;
667       client->sendEvent(event) ;
668     }
669     else client->sendEvent(event) ;
670   }
671
672   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
673   void CContext::recvCreateFileHeader(CEventServer& event)
674   {
675      CBufferIn* buffer=event.subEvents.begin()->buffer;
676      string id;
677      *buffer>>id ;
678      get(id)->recvCreateFileHeader(*buffer) ;
679   }
680
681   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
682   void CContext::recvCreateFileHeader(CBufferIn& buffer)
683   {
684      createFileHeader() ;
685   }
686
687   //! Client side: Send a message to do some post processing on server
688   void CContext::sendPostProcessing()
689   {
690     if (!hasServer)
691     {
692       CEventClient event(getType(),EVENT_ID_POST_PROCESS) ;
693       if (client->isServerLeader())
694       {
695         CMessage msg ;
696         msg<<this->getIdServer();
697         event.push(client->getServerLeader(),1,msg) ;
698         client->sendEvent(event) ;
699       }
700       else client->sendEvent(event) ;
701     }
702   }
703
704   //! Server side: Receive a message to do some post processing
705   void CContext::recvPostProcessing(CEventServer& event)
706   {
707      CBufferIn* buffer=event.subEvents.begin()->buffer;
708      string id;
709      *buffer>>id;
710      get(id)->recvPostProcessing(*buffer);
711   }
712
713   //! Server side: Receive a message to do some post processing
714   void CContext::recvPostProcessing(CBufferIn& buffer)
715   {
716      postProcessing();
717      std::cout << "server context " << *this << std::endl;
718   }
719
720   const StdString& CContext::getIdServer()
721   {
722      if (hasClient)
723      {
724        idServer_ = this->getId();
725        idServer_ += "_server";
726        return idServer_;
727      }
728      if (hasServer) return (this->getId());
729   }
730
731   /*!
732   \brief Do some simple post processings after parsing xml file
733      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
734   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
735   which will be written out into netcdf files, are processed
736   */
737   void CContext::postProcessing()
738   {
739     if (isPostProcessed) return;
740
741     // Solve calendar for both side: client and server
742      this->solveCalendar();
743
744      // Find all inheritance in xml structure
745      this->solveAllInheritance();
746
747      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
748      this->findEnabledFiles();
749
750      // Find all enabled fields of each file
751      this->findAllEnabledFields();
752
753      // Search and rebuild all reference object of enabled fields
754      this->solveAllRefOfEnabledFields(false);
755      isPostProcessed = true;
756   }
757
758   std::map<int, StdSize>& CContext::getDataSize()
759   {
760     std::set<StdString> domainIds;
761
762     // Find all reference domain and axis of all active fields
763     int numEnabledFiles = this->enabledFiles.size();
764     for (int i = 0; i < numEnabledFiles; ++i)
765     {
766       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
767       int numEnabledFields = enabledFields.size();
768       for (int j = 0; j < numEnabledFields; ++j)
769       {
770         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
771         const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataSize();
772         if (dataSize_.empty())
773         {
774           dataSize_ = mapSize;
775           domainIds.insert(prDomAxisId.first);
776         }
777         else
778         {
779           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
780           if (domainIds.find(prDomAxisId.first) == domainIds.end())
781           {
782             for (; it != itE; ++it)
783             {
784               if (0 < dataSize_.count(it->first)) dataSize_[it->first] += it->second;
785               else dataSize_.insert(make_pair(it->first, it->second));
786             }
787           } else
788           {
789             for (; it != itE; ++it)
790             {
791               if (0 < dataSize_.count(it->first))
792                if (CXios::isOptPerformance) dataSize_[it->first] += it->second;
793                else
794                {
795                  if (dataSize_[it->first] < it->second) dataSize_[it->first] = it->second;
796                }
797               else dataSize_.insert(make_pair(it->first, it->second));
798             }
799           }
800         }
801       }
802     }
803
804     return dataSize_;
805   }
806
807   //! Client side: Send infomation of active files (files are enabled to write out)
808   void CContext::sendEnabledFiles()
809   {
810     int size = this->enabledFiles.size();
811
812     // In a context, each type has a root definition, e.g: axis, domain, field.
813     // Every object must be a child of one of these root definition. In this case
814     // all new file objects created on server must be children of the root "file_definition"
815     StdString fileDefRoot("file_definition");
816     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
817
818     for (int i = 0; i < size; ++i)
819     {
820       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId());
821       this->enabledFiles[i]->sendAllAttributesToServer();
822       this->enabledFiles[i]->sendAddAllVariables();
823     }
824   }
825
826   //! Client side: Send information of active fields (ones are written onto files)
827   void CContext::sendEnabledFields()
828   {
829     int size = this->enabledFiles.size();
830     for (int i = 0; i < size; ++i)
831     {
832       this->enabledFiles[i]->sendEnabledFields();
833     }
834   }
835
836   //! Client side: Send information of reference grid of active fields
837   void CContext::sendRefGrid()
838   {
839     std::set<StdString> gridIds;
840     int sizeFile = this->enabledFiles.size();
841     CFile* filePtr(NULL);
842
843     // Firstly, find all reference grids of all active fields
844     for (int i = 0; i < sizeFile; ++i)
845     {
846       filePtr = this->enabledFiles[i];
847       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
848       int sizeField = enabledFields.size();
849       for (int numField = 0; numField < sizeField; ++numField)
850       {
851         if (0 != enabledFields[numField]->getRelGrid())
852           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
853       }
854     }
855
856     // Create all reference grids on server side
857     StdString gridDefRoot("grid_definition");
858     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
859     std::set<StdString>::const_iterator it, itE = gridIds.end();
860     for (it = gridIds.begin(); it != itE; ++it)
861     {
862       gridPtr->sendCreateChild(*it);
863       CGrid::get(*it)->sendAllAttributesToServer();
864       CGrid::get(*it)->sendAllDomains();
865       CGrid::get(*it)->sendAllAxis();
866     }
867   }
868
869
870   //! Client side: Send information of reference domain and axis of active fields
871   void CContext::sendRefDomainsAxis()
872   {
873     std::set<StdString> domainIds;
874     std::set<StdString> axisIds;
875
876     // Find all reference domain and axis of all active fields
877     int numEnabledFiles = this->enabledFiles.size();
878     for (int i = 0; i < numEnabledFiles; ++i)
879     {
880       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
881       int numEnabledFields = enabledFields.size();
882       for (int j = 0; j < numEnabledFields; ++j)
883       {
884         const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getDomainAxisIds();
885         domainIds.insert(prDomAxisId.first);
886         axisIds.insert(prDomAxisId.second);
887       }
888     }
889
890     // Create all reference axis on server side
891     std::set<StdString>::iterator itDom, itAxis;
892     std::set<StdString>::const_iterator itE;
893
894     StdString axiDefRoot("axis_definition");
895     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
896     itE = axisIds.end();
897     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
898     {
899       if (!itAxis->empty())
900       {
901         axisPtr->sendCreateChild(*itAxis);
902         CAxis::get(*itAxis)->sendAllAttributesToServer();
903       }
904     }
905
906     // Create all reference domains on server side
907     StdString domDefRoot("domain_definition");
908     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
909     itE = domainIds.end();
910     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
911     {
912       if (!itDom->empty()) {
913          domPtr->sendCreateChild(*itDom);
914          CDomain::get(*itDom)->sendAllAttributesToServer();
915       }
916     }
917   }
918
919   //! Update calendar in each time step
920   void CContext::updateCalendar(int step)
921   {
922      info(50)<<"updateCalendar : before : "<<calendar->getCurrentDate()<<endl ;
923      calendar->update(step) ;
924      info(50)<<"updateCalendar : after : "<<calendar->getCurrentDate()<<endl ;
925   }
926
927   //! Server side: Create header of netcdf file
928   void CContext::createFileHeader(void )
929   {
930      vector<CFile*>::const_iterator it ;
931
932      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
933      {
934         (*it)->initFile();
935      }
936   }
937
938   //! Get current context
939   CContext* CContext::getCurrent(void)
940   {
941     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get() ;
942   }
943
944   /*!
945   \brief Set context with an id be the current context
946   \param [in] id identity of context to be set to current
947   */
948   void CContext::setCurrent(const string& id)
949   {
950     CObjectFactory::SetCurrentContextId(id);
951     CGroupFactory::SetCurrentContextId(id);
952   }
953
954  /*!
955  \brief Create a context with specific id
956  \param [in] id identity of new context
957  \return pointer to the new context or already-existed one with identity id
958  */
959  CContext* CContext::create(const StdString& id)
960  {
961    CContext::setCurrent(id) ;
962
963    bool hasctxt = CContext::has(id);
964    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
965    getRoot() ;
966    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
967
968#define DECLARE_NODE(Name_, name_) \
969    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
970#define DECLARE_NODE_PAR(Name_, name_)
971#include "node_type.conf"
972
973    return (context);
974  }
975} // namespace xios
Note: See TracBrowser for help on using the repository browser.