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

Last change on this file since 597 was 597, checked in by rlacroix, 10 years ago

Add basic infrastructure for servers to clients communication.

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