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

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

Allow using more servers than clients.

This will be useful later when implementing server to client communications.

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