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

Last change on this file since 526 was 526, checked in by rlacroix, 9 years ago

Convert some attributes to enumerations:

  • file: par_access
  • context: calendar_type

Those changes should have no effect on existing XML configuration files and ensure that a proper error message is always displayed during parsing if the value is not supported.

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