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

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

Cleanup: Remove now deprecated code.

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