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

Last change on this file since 511 was 511, checked in by mhnguyen, 9 years ago

Seperating database of context on "client" side and "server" side

+) Add one more context in contex client in case of attached mode
+) Do some minor changements to make sure everything fine in case of attached mode
+) Replace buffer group with the new options

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