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

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

Implementing a grid formed by only one axis or group of axis

+) Add several new attributes to axis. From now on, each axis can be distributed on client side
+) Modify mask of grid to make it more flexible to different dimension
+) Fix some bugs relating to calculation of local data index on client
+) Clean some redundant codes

Test
+) On Curie, only test_new_features.f90
+) Test cases:

  • Grid composed of: 1 domain and 1 axis, 3 axis, 1 axis
  • Mode: Attached and connected
  • No of client-server: 6-2(Connected), 2 (Attached)

+) All tests passed and results are correct

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