source: XIOS/dev/dev_olga/src/node/context.cpp @ 1021

Last change on this file since 1021 was 1021, checked in by oabramkina, 7 years ago

Intermeadiate version for merging with new server functionalities.

  • 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: 51.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
17#include "server.hpp"
18
19namespace xios {
20
21  shared_ptr<CContextGroup> CContext::root;
22
23   /// ////////////////////// Définitions ////////////////////// ///
24
25   CContext::CContext(void)
26      : CObjectTemplate<CContext>(), CContextAttributes()
27      , calendar(), hasClient(false), hasServer(false)
28      , isPostProcessed(false), finalized(false)
29      , idServer_(), client(0), server(0)
30//        , clientPrimServer(0), serverPrimServer(0)
31   { /* Ne rien faire de plus */ }
32
33   CContext::CContext(const StdString & id)
34      : CObjectTemplate<CContext>(id), CContextAttributes()
35      , calendar(), hasClient(false), hasServer(false)
36      , isPostProcessed(false), finalized(false)
37      , idServer_(), client(0), server(0)
38//        , clientPrimServer(0), serverPrimServer(0)
39   { /* Ne rien faire de plus */ }
40
41   CContext::~CContext(void)
42   {
43     delete client;
44     delete server;
45//     delete clientPrimServer;
46//     delete serverPrimServer;
47   }
48
49   //----------------------------------------------------------------
50   //! Get name of context
51   StdString CContext::GetName(void)   { return (StdString("context")); }
52   StdString CContext::GetDefName(void){ return (CContext::GetName()); }
53   ENodeType CContext::GetType(void)   { return (eContext); }
54
55   //----------------------------------------------------------------
56
57   /*!
58   \brief Get context group (context root)
59   \return Context root
60   */
61   CContextGroup* CContext::getRoot(void)
62   {
63      if (root.get()==NULL) root=shared_ptr<CContextGroup>(new CContextGroup(xml::CXMLNode::GetRootName()));
64      return root.get();
65   }
66
67   //----------------------------------------------------------------
68
69   /*!
70   \brief Get calendar of a context
71   \return Calendar
72   */
73   boost::shared_ptr<CCalendar> CContext::getCalendar(void) const
74   {
75      return (this->calendar);
76   }
77
78   //----------------------------------------------------------------
79
80   /*!
81   \brief Set a context with a calendar
82   \param[in] newCalendar new calendar
83   */
84   void CContext::setCalendar(boost::shared_ptr<CCalendar> newCalendar)
85   {
86      this->calendar = newCalendar;
87   }
88
89   //----------------------------------------------------------------
90   /*!
91   \brief Parse xml file and write information into context object
92   \param [in] node xmld node corresponding in xml file
93   */
94   void CContext::parse(xml::CXMLNode & node)
95   {
96      CContext::SuperClass::parse(node);
97
98      // PARSING POUR GESTION DES ENFANTS
99      xml::THashAttributes attributes = node.getAttributes();
100
101      if (attributes.end() != attributes.find("src"))
102      {
103         StdIFStream ifs ( attributes["src"].c_str() , StdIFStream::in );
104         if ( (ifs.rdstate() & std::ifstream::failbit ) != 0 )
105            ERROR("void CContext::parse(xml::CXMLNode & node)",
106                  <<endl<< "Can not open <"<<attributes["src"].c_str()<<"> file" );
107         if (!ifs.good())
108            ERROR("CContext::parse(xml::CXMLNode & node)",
109                  << "[ filename = " << attributes["src"] << " ] Bad xml stream !");
110         xml::CXMLParser::ParseInclude(ifs, attributes["src"], *this);
111      }
112
113      if (node.getElementName().compare(CContext::GetName()))
114         DEBUG("Le noeud is wrong defined but will be considered as a context !");
115
116      if (!(node.goToChildElement()))
117      {
118         DEBUG("Le context ne contient pas d'enfant !");
119      }
120      else
121      {
122         do { // Parcours des contextes pour traitement.
123
124            StdString name = node.getElementName();
125            attributes.clear();
126            attributes = node.getAttributes();
127
128            if (attributes.end() != attributes.find("id"))
129            {
130              DEBUG(<< "Definition node has an id,"
131                    << "it will not be taking account !");
132            }
133
134#define DECLARE_NODE(Name_, name_)    \
135   if (name.compare(C##Name_##Definition::GetDefName()) == 0) \
136   { C##Name_##Definition::create(C##Name_##Definition::GetDefName()) -> parse(node); continue; }
137#define DECLARE_NODE_PAR(Name_, name_)
138#include "node_type.conf"
139
140            DEBUG(<< "The element \'"     << name
141                  << "\' in the context \'" << CContext::getCurrent()->getId()
142                  << "\' is not a definition !");
143
144         } while (node.goToNextElement());
145
146         node.goToParentElement(); // Retour au parent
147      }
148   }
149
150   //----------------------------------------------------------------
151   //! Show tree structure of context
152   void CContext::ShowTree(StdOStream & out)
153   {
154      StdString currentContextId = CContext::getCurrent() -> getId();
155      std::vector<CContext*> def_vector =
156         CContext::getRoot()->getChildList();
157      std::vector<CContext*>::iterator
158         it = def_vector.begin(), end = def_vector.end();
159
160      out << "<? xml version=\"1.0\" ?>" << std::endl;
161      out << "<"  << xml::CXMLNode::GetRootName() << " >" << std::endl;
162
163      for (; it != end; it++)
164      {
165         CContext* context = *it;
166         CContext::setCurrent(context->getId());
167         out << *context << std::endl;
168      }
169
170      out << "</" << xml::CXMLNode::GetRootName() << " >" << std::endl;
171      CContext::setCurrent(currentContextId);
172   }
173
174
175   //----------------------------------------------------------------
176
177   //! Convert context object into string (to print)
178   StdString CContext::toString(void) const
179   {
180      StdOStringStream oss;
181      oss << "<" << CContext::GetName()
182          << " id=\"" << this->getId() << "\" "
183          << SuperClassAttribute::toString() << ">" << std::endl;
184      if (!this->hasChild())
185      {
186         //oss << "<!-- No definition -->" << std::endl; // fait planter l'incrémentation
187      }
188      else
189      {
190
191#define DECLARE_NODE(Name_, name_)    \
192   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
193   oss << * C##Name_##Definition::get(C##Name_##Definition::GetDefName()) << std::endl;
194#define DECLARE_NODE_PAR(Name_, name_)
195#include "node_type.conf"
196
197      }
198
199      oss << "</" << CContext::GetName() << " >";
200
201      return (oss.str());
202   }
203
204   //----------------------------------------------------------------
205
206   /*!
207   \brief Find all inheritace among objects in a context.
208   \param [in] apply (true) write attributes of parent into ones of child if they are empty
209                     (false) write attributes of parent into a new container of child
210   \param [in] parent unused
211   */
212   void CContext::solveDescInheritance(bool apply, const CAttributeMap * const UNUSED(parent))
213   {
214#define DECLARE_NODE(Name_, name_)    \
215   if (C##Name_##Definition::has(C##Name_##Definition::GetDefName())) \
216     C##Name_##Definition::get(C##Name_##Definition::GetDefName())->solveDescInheritance(apply);
217#define DECLARE_NODE_PAR(Name_, name_)
218#include "node_type.conf"
219   }
220
221   //----------------------------------------------------------------
222
223   //! Verify if all root definition in the context have child.
224   bool CContext::hasChild(void) const
225   {
226      return (
227#define DECLARE_NODE(Name_, name_)    \
228   C##Name_##Definition::has(C##Name_##Definition::GetDefName())   ||
229#define DECLARE_NODE_PAR(Name_, name_)
230#include "node_type.conf"
231      false);
232}
233
234   //----------------------------------------------------------------
235
236   void CContext::CleanTree(void)
237   {
238#define DECLARE_NODE(Name_, name_) C##Name_##Definition::ClearAllAttributes();
239#define DECLARE_NODE_PAR(Name_, name_)
240#include "node_type.conf"
241   }
242   ///---------------------------------------------------------------
243
244   //! Initialize client side
245   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer /*= 0*/)
246   {
247
248     hasClient = true;
249     if (CServer::serverLevel != 1)
250//     if (CXios::serverLevel != 1)
251     // initClient is called by client pool
252     {
253       client = new CContextClient(this, intraComm, interComm, cxtServer);
254       server = new CContextServer(this, intraComm, interComm);
255     }
256     else
257     // initClient is called by primary server pool
258     {
259       clientPrimServer.push_back(new CContextClient(this, intraComm, interComm));
260       serverPrimServer.push_back(new CContextServer(this, intraComm, interComm));
261     }
262
263     registryIn=new CRegistry(intraComm);
264     registryIn->setPath(getId()) ;
265     if (client->clientRank==0) registryIn->fromFile("xios_registry.bin") ;
266     registryIn->bcastRegistry() ;
267
268     registryOut=new CRegistry(intraComm) ;
269     registryOut->setPath(getId()) ;
270
271     MPI_Comm intraCommServer, interCommServer;
272     if (cxtServer) // Attached mode
273     {
274       intraCommServer = intraComm;
275       interCommServer = interComm;
276     }
277     else
278     {
279       MPI_Comm_dup(intraComm, &intraCommServer);
280       comms.push_back(intraCommServer);
281       MPI_Comm_dup(interComm, &interCommServer);
282       comms.push_back(interCommServer);
283     }
284   }
285
286   void CContext::setClientServerBuffer()
287   {
288     size_t minBufferSize = CXios::minBufferSize;
289#define DECLARE_NODE(Name_, name_)    \
290     if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
291#define DECLARE_NODE_PAR(Name_, name_)
292#include "node_type.conf"
293#undef DECLARE_NODE
294#undef DECLARE_NODE_PAR
295
296     std::map<int, StdSize> maxEventSize;
297     std::map<int, StdSize> bufferSize = getAttributesBufferSize(maxEventSize);
298     std::map<int, StdSize> dataBufferSize = getDataBufferSize(maxEventSize);
299
300     std::map<int, StdSize>::iterator it, ite = dataBufferSize.end();
301     for (it = dataBufferSize.begin(); it != ite; ++it)
302       if (it->second > bufferSize[it->first]) bufferSize[it->first] = it->second;
303
304     ite = bufferSize.end();
305     for (it = bufferSize.begin(); it != ite; ++it)
306     {
307       it->second *= CXios::bufferSizeFactor;
308       if (it->second < minBufferSize) it->second = minBufferSize;
309     }
310
311     // We consider that the minimum buffer size is also the minimum event size
312     ite = maxEventSize.end();
313     for (it = maxEventSize.begin(); it != ite; ++it)
314       if (it->second < minBufferSize) it->second = minBufferSize;
315
316     if (client->isServerLeader())
317     {
318       const std::list<int>& ranks = client->getRanksServerLeader();
319       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
320         if (!bufferSize.count(*itRank)) bufferSize[*itRank] = maxEventSize[*itRank] = minBufferSize;
321     }
322     client->setBufferSize(bufferSize, maxEventSize);
323
324     // If it is primary server pool, also set buffer for clientPrimServer.
325     if (hasClient && hasServer)
326     {
327       for (int i = 0; i < clientPrimServer.size(); ++i)
328       {
329         if (clientPrimServer[i]->isServerLeader())
330         {
331           const std::list<int>& ranks = clientPrimServer[i]->getRanksServerLeader();
332           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
333             if (!bufferSize.count(*itRank)) bufferSize[*itRank] = maxEventSize[*itRank] = minBufferSize;
334         }
335         clientPrimServer[i]->setBufferSize(bufferSize, maxEventSize);
336       }
337     }
338   }
339
340   //! Verify whether a context is initialized
341   bool CContext::isInitialized(void)
342   {
343     return hasClient;
344   }
345
346   void CContext::initServer(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtClient /*= 0*/)
347   {
348     hasServer=true;
349     server = new CContextServer(this,intraComm,interComm);
350     client = new CContextClient(this,intraComm,interComm);
351//     client = new CContextClient(this,intraComm,interComm, cxtClient);
352
353     registryIn=new CRegistry(intraComm);
354     registryIn->setPath(getId()) ;
355     if (server->intraCommRank==0) registryIn->fromFile("xios_registry.bin") ;
356     registryIn->bcastRegistry() ;
357     registryOut=new CRegistry(intraComm) ;
358     registryOut->setPath(getId()) ;
359
360     MPI_Comm intraCommClient, interCommClient;
361     if (cxtClient) // Attached mode
362     {
363       intraCommClient = intraComm;
364       interCommClient = interComm;
365     }
366     else
367     {
368       MPI_Comm_dup(intraComm, &intraCommClient);
369       comms.push_back(intraCommClient);
370       MPI_Comm_dup(interComm, &interCommClient);
371       comms.push_back(interCommClient);
372     }
373
374   }
375
376   //! Server side: Put server into a loop in order to listen message from client
377   bool CContext::eventLoop(void)
378   {
379     if (CServer::serverLevel == 0)
380     {
381       return server->eventLoop();
382     }
383     else if (CServer::serverLevel == 1)
384     {
385       bool serverFinished = server->eventLoop();
386       bool serverPrimFinished = true;
387       for (int i = 0; i < serverPrimServer.size(); ++i)
388       {
389         serverPrimFinished *= serverPrimServer[i]->eventLoop();
390       }
391       return ( serverFinished && serverPrimFinished);
392     }
393     else
394     {
395       return server->eventLoop();
396     }
397   }
398
399   //! Try to send the buffers and receive possible answers
400   bool CContext::checkBuffersAndListen(void)
401   {
402     if (CServer::serverLevel == 0)
403     {
404       client->checkBuffers();
405       return server->eventLoop();
406     }
407     else if (CServer::serverLevel == 1)
408     {
409       client->checkBuffers();
410       for (int i = 0; i < clientPrimServer.size(); ++i)
411         clientPrimServer[i]->checkBuffers();
412       bool serverFinished = server->eventLoop();
413       bool serverPrimFinished = true;
414       for (int i = 0; i < serverPrimServer.size(); ++i)
415       {
416         serverPrimFinished *= serverPrimServer[i]->eventLoop();
417       }
418       return ( serverFinished && serverPrimFinished);
419     }
420     else if (CServer::serverLevel == 2)
421     {
422       client->checkBuffers();
423       return server->eventLoop();
424     }
425   }
426
427   //! Terminate a context
428   void CContext::finalize(void)
429   {
430     if (!finalized)
431     {
432       finalized = true;
433       if (hasClient) sendRegistry() ;
434
435       if ((hasClient) && (hasServer))
436       {
437         for (int i = 0; i < clientPrimServer.size(); ++i)
438           clientPrimServer[i]->finalize();
439
440         for (int i = 0; i < serverPrimServer.size(); ++i)
441         {
442           while (!serverPrimServer[i]->hasFinished())
443           {
444             serverPrimServer[i]->eventLoop();
445             CServer::eventScheduler->checkEvent() ;
446           }
447         }
448       }
449
450       client->finalize();
451       while (!server->hasFinished())
452       {
453         server->eventLoop();
454       }
455
456       if (hasServer)
457       {
458         closeAllFile();
459         registryOut->hierarchicalGatherRegistry() ;
460         if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
461       }
462
463       for (std::vector<CContextClient*>::iterator it = clientPrimServer.begin(); it != clientPrimServer.end(); it++)
464         delete *it;
465
466       for (std::vector<CContextServer*>::iterator it = serverPrimServer.begin(); it != serverPrimServer.end(); it++)
467         delete *it;
468
469       for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
470         MPI_Comm_free(&(*it));
471       comms.clear();
472
473
474      }
475   }
476
477   /*!
478   \brief Close all the context defintion and do processing data
479      After everything is well defined on client side, they will be processed and sent to server
480   From the version 2.0, sever and client work no more on the same database. Moreover, client(s) will send
481   all necessary information to server, from which each server can build its own database.
482   Because the role of server is to write out field data on a specific netcdf file,
483   the only information that it needs is the enabled files
484   and the active fields (fields will be written onto active files)
485   */
486   void CContext::closeDefinition(void)
487   {
488     // There is nothing client need to send to server
489     if (hasClient)
490     {
491       // After xml is parsed, there are some more works with post processing
492       postProcessing();
493     }
494
495     setClientServerBuffer();
496
497     if (hasClient)
498     {
499      // Send all attributes of current context to server
500      this->sendAllAttributesToServer();
501
502      // Send all attributes of current calendar
503      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer();
504
505      // We have enough information to send to server
506      // First of all, send all enabled files
507      sendEnabledFiles();
508
509      // Then, send all enabled fields
510      sendEnabledFields();
511
512      // At last, we have all info of domain and axis, then send them
513       sendRefDomainsAxis();
514
515       // After that, send all grid (if any)
516       sendRefGrid();
517
518       // We have a xml tree on the server side and now, it should be also processed
519       sendPostProcessing();
520     }
521
522
523     // Now tell server that it can process all messages from client
524     if (hasClient) this->sendCloseDefinition();
525
526    // There are some processings that should be done after all of above. For example: check mask or index
527     if (hasClient && !hasServer)
528    {
529      this->buildFilterGraphOfEnabledFields();  // references are resolved here (access xml file)
530      buildFilterGraphOfFieldsWithReadAccess();
531      this->solveAllRefOfEnabledFields(true);
532    }
533
534//    // Now tell server that it can process all messages from client
535////    if (hasClient && !hasServer) this->sendCloseDefinition();
536//    if (hasClient) this->sendCloseDefinition();
537
538    // Nettoyage de l'arborescence
539//    if (hasClient && !hasServer) CleanTree(); // Only on client side??
540    if (hasClient) CleanTree(); // Only on client side??
541
542    if (hasClient)
543    {
544      sendCreateFileHeader();
545      if (!hasServer) startPrefetchingOfEnabledReadModeFiles();
546    }
547   }
548
549   void CContext::findAllEnabledFields(void)
550   {
551     for (unsigned int i = 0; i < this->enabledFiles.size(); i++)
552     (void)this->enabledFiles[i]->getEnabledFields();
553   }
554
555   void CContext::findAllEnabledFieldsInReadModeFiles(void)
556   {
557     for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
558     (void)this->enabledReadModeFiles[i]->getEnabledFields();
559   }
560
561   void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
562   {
563      for (unsigned int i = 0; i < this->enabledReadModeFiles.size(); ++i)
564        (void)this->enabledReadModeFiles[i]->readAttributesOfEnabledFieldsInReadMode();
565   }
566
567   void CContext::solveOnlyRefOfEnabledFields(bool sendToServer)
568   {
569     int size = this->enabledFiles.size();
570     for (int i = 0; i < size; ++i)
571     {
572       this->enabledFiles[i]->solveOnlyRefOfEnabledFields(sendToServer);
573     }
574
575     for (int i = 0; i < size; ++i)
576     {
577       this->enabledFiles[i]->generateNewTransformationGridDest();
578     }
579   }
580
581   void CContext::solveAllRefOfEnabledFields(bool sendToServer)
582   {
583     int size = this->enabledFiles.size();
584     for (int i = 0; i < size; ++i)
585     {
586       this->enabledFiles[i]->solveAllRefOfEnabledFields(sendToServer);
587     }
588   }
589
590   void CContext::buildFilterGraphOfEnabledFields()
591   {
592     int size = this->enabledFiles.size();
593     for (int i = 0; i < size; ++i)
594     {
595       this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);
596     }
597   }
598
599   void CContext::startPrefetchingOfEnabledReadModeFiles()
600   {
601     int size = enabledReadModeFiles.size();
602     for (int i = 0; i < size; ++i)
603     {
604        enabledReadModeFiles[i]->prefetchEnabledReadModeFields();
605     }
606   }
607
608   void CContext::checkPrefetchingOfEnabledReadModeFiles()
609   {
610     int size = enabledReadModeFiles.size();
611     for (int i = 0; i < size; ++i)
612     {
613        enabledReadModeFiles[i]->prefetchEnabledReadModeFieldsIfNeeded();
614     }
615   }
616
617  void CContext::findFieldsWithReadAccess(void)
618  {
619    fieldsWithReadAccess.clear();
620    const vector<CField*> allFields = CField::getAll();
621    for (size_t i = 0; i < allFields.size(); ++i)
622    {
623      CField* field = allFields[i];
624
625      if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)
626        field->read_access = true;
627      else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
628        fieldsWithReadAccess.push_back(field);
629    }
630  }
631
632  void CContext::solveAllRefOfFieldsWithReadAccess()
633  {
634    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
635      fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false);
636  }
637
638  void CContext::buildFilterGraphOfFieldsWithReadAccess()
639  {
640    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
641      fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true);
642  }
643
644   void CContext::solveAllInheritance(bool apply)
645   {
646     // Résolution des héritages descendants (càd des héritages de groupes)
647     // pour chacun des contextes.
648      solveDescInheritance(apply);
649
650     // Résolution des héritages par référence au niveau des fichiers.
651      const vector<CFile*> allFiles=CFile::getAll();
652      const vector<CGrid*> allGrids= CGrid::getAll();
653
654      if (hasClient && !hasServer)
655      //if (hasClient)
656      {
657        for (unsigned int i = 0; i < allFiles.size(); i++)
658          allFiles[i]->solveFieldRefInheritance(apply);
659      }
660
661      unsigned int vecSize = allGrids.size();
662      unsigned int i = 0;
663      for (i = 0; i < vecSize; ++i)
664        allGrids[i]->solveDomainAxisRefInheritance(apply);
665
666   }
667
668   void CContext::findEnabledFiles(void)
669   {
670      const std::vector<CFile*> allFiles = CFile::getAll();
671
672      for (unsigned int i = 0; i < allFiles.size(); i++)
673         if (!allFiles[i]->enabled.isEmpty()) // Si l'attribut 'enabled' est défini.
674         {
675            if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai.
676               enabledFiles.push_back(allFiles[i]);
677         }
678         else enabledFiles.push_back(allFiles[i]); // otherwise true by default
679
680
681      if (enabledFiles.size() == 0)
682         DEBUG(<<"Aucun fichier ne va être sorti dans le contexte nommé \""
683               << getId() << "\" !");
684
685      // Assigning contextClient to each enabled file
686      if (hasClient)
687      {
688        for (int i = 0; i < enabledFiles.size(); ++i)
689        {
690          if (hasServer)
691          {
692            int srvId = i % clientPrimServer.size();
693            enabledFiles[i]->setContextClient(clientPrimServer[srvId]);
694          }
695          else
696            enabledFiles[i]->setContextClient(client);
697        }
698      }
699   }
700
701   void CContext::findEnabledReadModeFiles(void)
702   {
703     int size = this->enabledFiles.size();
704     for (int i = 0; i < size; ++i)
705     {
706       if (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::read)
707        enabledReadModeFiles.push_back(enabledFiles[i]);
708     }
709   }
710
711   void CContext::closeAllFile(void)
712   {
713     std::vector<CFile*>::const_iterator
714            it = this->enabledFiles.begin(), end = this->enabledFiles.end();
715
716     for (; it != end; it++)
717     {
718       info(30)<<"Closing File : "<<(*it)->getId()<<endl;
719       (*it)->close();
720     }
721   }
722
723   /*!
724   \brief Dispatch event received from client
725      Whenever a message is received in buffer of server, it will be processed depending on
726   its event type. A new event type should be added in the switch list to make sure
727   it processed on server side.
728   \param [in] event: Received message
729   */
730   bool CContext::dispatchEvent(CEventServer& event)
731   {
732
733      if (SuperClass::dispatchEvent(event)) return true;
734      else
735      {
736        switch(event.type)
737        {
738           case EVENT_ID_CLOSE_DEFINITION :
739             recvCloseDefinition(event);
740             return true;
741             break;
742           case EVENT_ID_UPDATE_CALENDAR:
743             recvUpdateCalendar(event);
744             return true;
745             break;
746           case EVENT_ID_CREATE_FILE_HEADER :
747             recvCreateFileHeader(event);
748             return true;
749             break;
750           case EVENT_ID_POST_PROCESS:
751             recvPostProcessing(event);
752             return true;
753            case EVENT_ID_SEND_REGISTRY:
754             recvRegistry(event);
755             return true;
756            break;
757
758           default :
759             ERROR("bool CContext::dispatchEvent(CEventServer& event)",
760                    <<"Unknown Event");
761           return false;
762         }
763      }
764   }
765
766//   // Only send close definition from process having hasClient
767//   void CContext::sendCloseDefinitionToServer(void)
768//   {
769//     CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
770//   }
771
772   //! Client side: Send a message to server to make it close
773   void CContext::sendCloseDefinition(void)
774   {
775     // Use correct context client to send message
776     int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
777     for (int i = 0; i < nbSrvPools; ++i)
778     {
779       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
780       CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
781       if (contextClientTmp->isServerLeader())
782       {
783         CMessage msg;
784         if (hasServer)
785           msg<<this->getIdServer(i);
786         else
787           msg<<this->getIdServer();
788         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
789         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
790           event.push(*itRank,1,msg);
791         contextClientTmp->sendEvent(event);
792       }
793       else contextClientTmp->sendEvent(event);
794     }
795   }
796
797   //! Server side: Receive a message of client announcing a context close
798   void CContext::recvCloseDefinition(CEventServer& event)
799   {
800      CBufferIn* buffer=event.subEvents.begin()->buffer;
801      string id;
802      *buffer>>id;
803      get(id)->closeDefinition();
804      if (get(id)->hasClient && get(id)->hasServer)
805      {       
806        get(id)->sendCloseDefinition();
807      }
808   }
809
810   //! Client side: Send a message to update calendar in each time step
811   void CContext::sendUpdateCalendar(int step)
812   {
813     // Use correct context client to send message
814//     CContextClient* contextClientTmp = (0 != clientPrimServer) ? clientPrimServer : client;
815     int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
816     for (int i = 0; i < nbSrvPools; ++i)
817     {
818       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
819       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
820
821         if (contextClientTmp->isServerLeader())
822         {
823           CMessage msg;
824           if (hasServer)
825             msg<<this->getIdServer(i)<<step;
826           else
827             msg<<this->getIdServer()<<step;
828           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
829           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
830             event.push(*itRank,1,msg);
831           contextClientTmp->sendEvent(event);
832         }
833         else contextClientTmp->sendEvent(event);
834     }
835
836     // if (!hasServer)
837     // {
838     //   if (client->isServerLeader())
839     //   {
840     //     CMessage msg;
841     //     msg<<this->getIdServer()<<step;
842     //     const std::list<int>& ranks = client->getRanksServerLeader();
843     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
844     //       event.push(*itRank,1,msg);
845     //     client->sendEvent(event);
846     //   }
847     //   else client->sendEvent(event);
848     // }
849     // else
850     // {
851     //   if (clientPrimServer->isServerLeader())
852     //   {
853     //     CMessage msg;
854     //     msg<<this->getIdServer()<<step;
855     //     const std::list<int>& ranks = clientPrimServer->getRanksServerLeader();
856     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
857     //       event.push(*itRank,1,msg);
858     //     clientPrimServer->sendEvent(event);
859     //   }
860     //   else clientPrimServer->sendEvent(event);
861     // }
862   }
863
864   //! Server side: Receive a message of client annoucing calendar update
865   void CContext::recvUpdateCalendar(CEventServer& event)
866   {
867      CBufferIn* buffer=event.subEvents.begin()->buffer;
868      string id;
869      *buffer>>id;
870      get(id)->recvUpdateCalendar(*buffer);
871   }
872
873   //! Server side: Receive a message of client annoucing calendar update
874   void CContext::recvUpdateCalendar(CBufferIn& buffer)
875   {
876      int step;
877      buffer>>step;
878      updateCalendar(step);
879      if (hasClient && hasServer)
880      {       
881        sendUpdateCalendar(step);
882      }
883   }
884
885   //! Client side: Send a message to create header part of netcdf file
886   void CContext::sendCreateFileHeader(void)
887   {
888     // Use correct context client to send message
889     int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
890     for (int i = 0; i < nbSrvPools; ++i)
891     {
892       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
893       CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
894
895       if (contextClientTmp->isServerLeader())
896       {
897         CMessage msg;
898         if (hasServer)
899           msg<<this->getIdServer(i);
900         else
901           msg<<this->getIdServer();
902         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
903         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
904           event.push(*itRank,1,msg) ;
905         contextClientTmp->sendEvent(event);
906       }
907       else contextClientTmp->sendEvent(event);
908     }
909     // if (!hasServer)
910     // {
911     //   if (client->isServerLeader())
912     //   {
913     //     CMessage msg;
914     //     msg<<this->getIdServer();
915     //     const std::list<int>& ranks = client->getRanksServerLeader();
916     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
917     //       event.push(*itRank,1,msg) ;
918     //     client->sendEvent(event);
919     //   }
920     //   else client->sendEvent(event);
921     // }
922     // else
923     // {
924     //   if (clientPrimServer->isServerLeader())
925     //   {
926     //     CMessage msg;
927     //     msg<<this->getIdServer();
928     //     const std::list<int>& ranks = clientPrimServer->getRanksServerLeader();
929     //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
930     //       event.push(*itRank,1,msg) ;
931     //     clientPrimServer->sendEvent(event);
932     //   }
933     //   else clientPrimServer->sendEvent(event);
934     // }
935   }
936
937   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
938   void CContext::recvCreateFileHeader(CEventServer& event)
939   {
940      CBufferIn* buffer=event.subEvents.begin()->buffer;
941      string id;
942      *buffer>>id;
943      get(id)->recvCreateFileHeader(*buffer);
944   }
945
946   //! Server side: Receive a message of client annoucing the creation of header part of netcdf file
947   void CContext::recvCreateFileHeader(CBufferIn& buffer)
948   {
949     // The creation of header file should be delegated to server2, for now
950      if (hasClient && hasServer)
951      {       
952        sendCreateFileHeader();
953      }
954     
955      if (!hasClient && hasServer) 
956        createFileHeader();
957   }
958
959   //! Client side: Send a message to do some post processing on server
960   void CContext::sendPostProcessing()
961   {
962      // Use correct context client to send message
963     int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
964     for (int i = 0; i < nbSrvPools; ++i)
965     {
966       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
967       CEventClient event(getType(),EVENT_ID_POST_PROCESS);
968       if (contextClientTmp->isServerLeader())
969       {
970         CMessage msg;
971         if (hasServer)
972           msg<<this->getIdServer(i);
973         else
974           msg<<this->getIdServer();
975         const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
976         for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
977         event.push(*itRank,1,msg);
978         contextClientTmp->sendEvent(event);
979       }
980       else contextClientTmp->sendEvent(event);
981     }
982
983     // if (hasClient)
984     // {
985     //   if (!hasServer)
986     //   {
987     //     CEventClient event(getType(),EVENT_ID_POST_PROCESS);
988     //     if (client->isServerLeader())
989     //     {
990     //       CMessage msg;
991     //       msg<<this->getIdServer();
992     //       const std::list<int>& ranks = client->getRanksServerLeader();
993     //       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
994     //         event.push(*itRank,1,msg);
995     //       client->sendEvent(event);
996     //     }
997     //     else client->sendEvent(event);
998     //   }
999     //   else
1000     //   {
1001     //     CEventClient event(getType(),EVENT_ID_POST_PROCESS);
1002     //     if (clientPrimServer->isServerLeader())
1003     //     {
1004     //       CMessage msg;
1005     //       msg<<this->getIdServer();
1006     //       const std::list<int>& ranks = clientPrimServer->getRanksServerLeader();
1007     //       for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1008     //         event.push(*itRank,1,msg);
1009     //       clientPrimServer->sendEvent(event);
1010     //     }
1011     //     else clientPrimServer->sendEvent(event);
1012     //   }
1013     // }
1014   }
1015
1016   //! Server side: Receive a message to do some post processing
1017   void CContext::recvPostProcessing(CEventServer& event)
1018   {
1019      CBufferIn* buffer=event.subEvents.begin()->buffer;
1020      string id;
1021      *buffer>>id;
1022      get(id)->recvPostProcessing(*buffer);
1023   }
1024
1025   //! Server side: Receive a message to do some post processing
1026   void CContext::recvPostProcessing(CBufferIn& buffer)
1027   {
1028      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
1029      postProcessing();
1030   }
1031
1032   const StdString& CContext::getIdServer()
1033   {
1034      if (hasClient)
1035      {
1036        idServer_ = this->getId();
1037        idServer_ += "_server";
1038        return idServer_;
1039      }
1040      if (hasServer) return (this->getId());
1041   }
1042
1043   const StdString& CContext::getIdServer(const int i)
1044   {
1045     idServer_ = this->getId();
1046     idServer_ += "_server_";
1047     idServer_ += boost::lexical_cast<string>(i);
1048     return idServer_;
1049   }
1050
1051
1052   /*!
1053   \brief Do some simple post processings after parsing xml file
1054      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
1055   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
1056   which will be written out into netcdf files, are processed
1057   */
1058   void CContext::postProcessing()
1059   {
1060     if (isPostProcessed) return;
1061
1062      // Make sure the calendar was correctly created
1063      if (!calendar)
1064        ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
1065      else if (calendar->getTimeStep() == NoneDu)
1066        ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
1067      // Calendar first update to set the current date equals to the start date
1068      calendar->update(0);
1069
1070      // Find all inheritance in xml structure
1071      this->solveAllInheritance();
1072
1073//      ShowTree(info(10));
1074
1075      // Check if some axis, domains or grids are eligible to for compressed indexed output.
1076      // Warning: This must be done after solving the inheritance and before the rest of post-processing
1077      checkAxisDomainsGridsEligibilityForCompressedOutput();
1078
1079      // Check if some automatic time series should be generated
1080      // Warning: This must be done after solving the inheritance and before the rest of post-processing
1081      if (!hasServer)
1082        prepareTimeseries();
1083
1084      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir.
1085      this->findEnabledFiles();
1086      this->findEnabledReadModeFiles();
1087
1088      // Find all enabled fields of each file
1089      this->findAllEnabledFields();
1090      this->findAllEnabledFieldsInReadModeFiles();
1091
1092//     if (hasClient)
1093     if (hasClient && !hasServer)
1094     {
1095      // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis)
1096      this->readAttributesOfEnabledFieldsInReadModeFiles();
1097     }
1098
1099      // Only search and rebuild all reference objects of enable fields, don't transform
1100      this->solveOnlyRefOfEnabledFields(false);
1101
1102      // Search and rebuild all reference object of enabled fields
1103      this->solveAllRefOfEnabledFields(false);
1104
1105      // Find all fields with read access from the public API
1106      findFieldsWithReadAccess();
1107      // and solve the all reference for them
1108      solveAllRefOfFieldsWithReadAccess();
1109
1110      isPostProcessed = true;
1111   }
1112
1113   /*!
1114    * Compute the required buffer size to send the attributes (mostly those grid related).
1115    *
1116    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1117    */
1118   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize)
1119   {
1120     std::map<int, StdSize> attributesSize;
1121
1122     if (hasClient)
1123     {
1124       size_t numEnabledFiles = this->enabledFiles.size();
1125       for (size_t i = 0; i < numEnabledFiles; ++i)
1126       {
1127         CFile* file = this->enabledFiles[i];
1128
1129         std::vector<CField*> enabledFields = file->getEnabledFields();
1130         size_t numEnabledFields = enabledFields.size();
1131         for (size_t j = 0; j < numEnabledFields; ++j)
1132         {
1133           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize();
1134           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1135           for (; it != itE; ++it)
1136           {
1137             // If attributesSize[it->first] does not exist, it will be zero-initialized
1138             // so we can use it safely without checking for its existance
1139             if (attributesSize[it->first] < it->second)
1140               attributesSize[it->first] = it->second;
1141
1142             if (maxEventSize[it->first] < it->second)
1143               maxEventSize[it->first] = it->second;
1144           }
1145         }
1146       }
1147     }
1148
1149     return attributesSize;
1150   }
1151
1152   /*!
1153    * Compute the required buffer size to send the fields data.
1154    *
1155    * \param maxEventSize [in/out] the size of the bigger event for each connected server
1156    */
1157   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize)
1158   {
1159     CFile::mode_attr::t_enum mode = hasClient ? CFile::mode_attr::write : CFile::mode_attr::read;
1160
1161     std::map<int, StdSize> dataSize;
1162
1163     // Find all reference domain and axis of all active fields
1164     size_t numEnabledFiles = this->enabledFiles.size();
1165     for (size_t i = 0; i < numEnabledFiles; ++i)
1166     {
1167       CFile* file = this->enabledFiles[i];
1168       CFile::mode_attr::t_enum fileMode = file->mode.isEmpty() ? CFile::mode_attr::write : file->mode.getValue();
1169
1170       if (fileMode == mode)
1171       {
1172         std::vector<CField*> enabledFields = file->getEnabledFields();
1173         size_t numEnabledFields = enabledFields.size();
1174         for (size_t j = 0; j < numEnabledFields; ++j)
1175         {
1176           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize();
1177           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
1178           for (; it != itE; ++it)
1179           {
1180             // If dataSize[it->first] does not exist, it will be zero-initialized
1181             // so we can use it safely without checking for its existance
1182             if (CXios::isOptPerformance)
1183               dataSize[it->first] += it->second;
1184             else if (dataSize[it->first] < it->second)
1185               dataSize[it->first] = it->second;
1186
1187             if (maxEventSize[it->first] < it->second)
1188               maxEventSize[it->first] = it->second;
1189           }
1190         }
1191       }
1192     }
1193
1194     return dataSize;
1195   }
1196
1197   //! Client side: Send infomation of active files (files are enabled to write out)
1198   void CContext::sendEnabledFiles()
1199   {
1200     int size = this->enabledFiles.size();
1201
1202     // In a context, each type has a root definition, e.g: axis, domain, field.
1203     // Every object must be a child of one of these root definition. In this case
1204     // all new file objects created on server must be children of the root "file_definition"
1205     StdString fileDefRoot("file_definition");
1206     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1207     for (int i = 0; i < size; ++i)
1208     {
1209       cfgrpPtr->sendCreateChild(this->enabledFiles[i]->getId(),enabledFiles[i]->getContextClient());
1210       this->enabledFiles[i]->sendAllAttributesToServer(enabledFiles[i]->getContextClient());
1211       this->enabledFiles[i]->sendAddAllVariables(enabledFiles[i]->getContextClient());
1212     }
1213   }
1214
1215   //! Client side: Send information of active fields (ones are written onto files)
1216   void CContext::sendEnabledFields()
1217   {
1218     int size = this->enabledFiles.size();
1219     for (int i = 0; i < size; ++i)
1220     {
1221       this->enabledFiles[i]->sendEnabledFields(enabledFiles[i]->getContextClient());
1222     }
1223   }
1224
1225   //! Client side: Check if the defined axis, domains and grids are eligible for compressed indexed output
1226   void CContext::checkAxisDomainsGridsEligibilityForCompressedOutput()
1227   {
1228     if (!hasClient) return;
1229
1230     const vector<CAxis*> allAxis = CAxis::getAll();
1231     for (vector<CAxis*>::const_iterator it = allAxis.begin(); it != allAxis.end(); it++)
1232       (*it)->checkEligibilityForCompressedOutput();
1233
1234     const vector<CDomain*> allDomains = CDomain::getAll();
1235     for (vector<CDomain*>::const_iterator it = allDomains.begin(); it != allDomains.end(); it++)
1236       (*it)->checkEligibilityForCompressedOutput();
1237
1238     const vector<CGrid*> allGrids = CGrid::getAll();
1239     for (vector<CGrid*>::const_iterator it = allGrids.begin(); it != allGrids.end(); it++)
1240       (*it)->checkEligibilityForCompressedOutput();
1241   }
1242
1243   //! Client side: Prepare the timeseries by adding the necessary files
1244   void CContext::prepareTimeseries()
1245   {
1246     if (!hasClient) return;
1247
1248     const std::vector<CFile*> allFiles = CFile::getAll();
1249     for (size_t i = 0; i < allFiles.size(); i++)
1250     {
1251       CFile* file = allFiles[i];
1252
1253       if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none)
1254       {
1255         StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : file->getFileOutputName();
1256
1257         const std::vector<CField*> allFields = file->getAllFields();
1258         for (size_t j = 0; j < allFields.size(); j++)
1259         {
1260           CField* field = allFields[j];
1261
1262           if (!field->ts_enabled.isEmpty() && field->ts_enabled)
1263           {
1264             CFile* tsFile = CFile::create();
1265             tsFile->duplicateAttributes(file);
1266             tsFile->setVirtualVariableGroup(file->getVirtualVariableGroup());
1267
1268             tsFile->name = tsPrefix + "_";
1269             if (!field->name.isEmpty())
1270               tsFile->name.get() += field->name;
1271             else if (field->hasDirectFieldReference()) // We cannot use getBaseFieldReference() just yet
1272               tsFile->name.get() += field->field_ref;
1273             else
1274               tsFile->name.get() += field->getId();
1275
1276             if (!field->ts_split_freq.isEmpty())
1277               tsFile->split_freq = field->ts_split_freq;
1278
1279             CField* tsField = tsFile->addField();
1280             tsField->field_ref = field->getId();
1281             tsField->setVirtualVariableGroup(field->getVirtualVariableGroup());
1282
1283             tsFile->solveFieldRefInheritance(true);
1284
1285             if (file->timeseries == CFile::timeseries_attr::exclusive)
1286               field->enabled = false;
1287           }
1288         }
1289
1290         // Finally disable the original file is need be
1291         if (file->timeseries == CFile::timeseries_attr::only)
1292          file->enabled = false;
1293       }
1294     }
1295   }
1296
1297   //! Client side: Send information of reference grid of active fields
1298   void CContext::sendRefGrid()
1299   {
1300     std::set<StdString> gridIds;
1301     int sizeFile = this->enabledFiles.size();
1302     CFile* filePtr(NULL);
1303
1304     // Firstly, find all reference grids of all active fields
1305     for (int i = 0; i < sizeFile; ++i)
1306     {
1307       filePtr = this->enabledFiles[i];
1308       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
1309       int sizeField = enabledFields.size();
1310       for (int numField = 0; numField < sizeField; ++numField)
1311       {
1312         if (0 != enabledFields[numField]->getRelGrid())
1313           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
1314       }
1315     }
1316
1317     // Create all reference grids on server side
1318     StdString gridDefRoot("grid_definition");
1319     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
1320     std::set<StdString>::const_iterator it, itE = gridIds.end();
1321     for (it = gridIds.begin(); it != itE; ++it)
1322     {
1323       gridPtr->sendCreateChild(*it);
1324       CGrid::get(*it)->sendAllAttributesToServer();
1325       CGrid::get(*it)->sendAllDomains();
1326       CGrid::get(*it)->sendAllAxis();
1327       CGrid::get(*it)->sendAllScalars();
1328     }
1329   }
1330
1331
1332   //! Client side: Send information of reference domain and axis of active fields
1333   void CContext::sendRefDomainsAxis()
1334   {
1335     std::set<StdString> domainIds, axisIds, scalarIds;
1336
1337     // Find all reference domain and axis of all active fields
1338     int numEnabledFiles = this->enabledFiles.size();
1339     for (int i = 0; i < numEnabledFiles; ++i)
1340     {
1341       std::vector<CField*> enabledFields = this->enabledFiles[i]->getEnabledFields();
1342       int numEnabledFields = enabledFields.size();
1343       for (int j = 0; j < numEnabledFields; ++j)
1344       {
1345         const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
1346         if ("" != prDomAxisScalarId[0]) domainIds.insert(prDomAxisScalarId[0]);
1347         if ("" != prDomAxisScalarId[1]) axisIds.insert(prDomAxisScalarId[1]);
1348         if ("" != prDomAxisScalarId[2]) scalarIds.insert(prDomAxisScalarId[2]);
1349       }
1350     }
1351
1352     // Create all reference axis on server side
1353     std::set<StdString>::iterator itDom, itAxis, itScalar;
1354     std::set<StdString>::const_iterator itE;
1355
1356     StdString scalarDefRoot("scalar_definition");
1357     CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
1358     itE = scalarIds.end();
1359     for (itScalar = scalarIds.begin(); itScalar != itE; ++itScalar)
1360     {
1361       if (!itScalar->empty())
1362       {
1363         scalarPtr->sendCreateChild(*itScalar);
1364         CScalar::get(*itScalar)->sendAllAttributesToServer();
1365       }
1366     }
1367
1368     StdString axiDefRoot("axis_definition");
1369     CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
1370     itE = axisIds.end();
1371     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
1372     {
1373       if (!itAxis->empty())
1374       {
1375         axisPtr->sendCreateChild(*itAxis);
1376         CAxis::get(*itAxis)->sendAllAttributesToServer();
1377       }
1378     }
1379
1380     // Create all reference domains on server side
1381     StdString domDefRoot("domain_definition");
1382     CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
1383     itE = domainIds.end();
1384     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
1385     {
1386       if (!itDom->empty()) {
1387          domPtr->sendCreateChild(*itDom);
1388          CDomain::get(*itDom)->sendAllAttributesToServer();
1389       }
1390     }
1391   }
1392
1393   //! Update calendar in each time step
1394   void CContext::updateCalendar(int step)
1395   {
1396      info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl;
1397      calendar->update(step);
1398      info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl;
1399
1400      if (hasClient)
1401      {
1402        checkPrefetchingOfEnabledReadModeFiles();
1403        garbageCollector.invalidate(calendar->getCurrentDate());
1404      }
1405   }
1406
1407   //! Server side: Create header of netcdf file
1408   void CContext::createFileHeader(void )
1409   {
1410      vector<CFile*>::const_iterator it;
1411
1412      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
1413      {
1414         (*it)->initFile();
1415      }
1416   }
1417
1418   //! Get current context
1419   CContext* CContext::getCurrent(void)
1420   {
1421     return CObjectFactory::GetObject<CContext>(CObjectFactory::GetCurrentContextId()).get();
1422   }
1423
1424   /*!
1425   \brief Set context with an id be the current context
1426   \param [in] id identity of context to be set to current
1427   */
1428   void CContext::setCurrent(const string& id)
1429   {
1430     CObjectFactory::SetCurrentContextId(id);
1431     CGroupFactory::SetCurrentContextId(id);
1432   }
1433
1434  /*!
1435  \brief Create a context with specific id
1436  \param [in] id identity of new context
1437  \return pointer to the new context or already-existed one with identity id
1438  */
1439  CContext* CContext::create(const StdString& id)
1440  {
1441    CContext::setCurrent(id);
1442
1443    bool hasctxt = CContext::has(id);
1444    CContext* context = CObjectFactory::CreateObject<CContext>(id).get();
1445    getRoot();
1446    if (!hasctxt) CGroupFactory::AddChild(root, context->getShared());
1447
1448#define DECLARE_NODE(Name_, name_) \
1449    C##Name_##Definition::create(C##Name_##Definition::GetDefName());
1450#define DECLARE_NODE_PAR(Name_, name_)
1451#include "node_type.conf"
1452
1453    return (context);
1454  }
1455
1456
1457     //! Server side: Receive a message to do some post processing
1458  void CContext::recvRegistry(CEventServer& event)
1459  {
1460    CBufferIn* buffer=event.subEvents.begin()->buffer;
1461    string id;
1462    *buffer>>id;
1463    get(id)->recvRegistry(*buffer);
1464  }
1465
1466  void CContext::recvRegistry(CBufferIn& buffer)
1467  {
1468    if (server->intraCommRank==0)
1469    {
1470      CRegistry registry(server->intraComm) ;
1471      registry.fromBuffer(buffer) ;
1472      registryOut->mergeRegistry(registry) ;
1473    }
1474  }
1475
1476  void CContext::sendRegistry(void)
1477  {   
1478    registryOut->hierarchicalGatherRegistry() ;
1479
1480    // Use correct context client to send message
1481    int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
1482    for (int i = 0; i < nbSrvPools; ++i)
1483    {
1484      CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
1485      CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
1486        if (contextClientTmp->isServerLeader())
1487        {
1488           CMessage msg ;
1489           if (hasServer)
1490             msg<<this->getIdServer(i);
1491           else
1492             msg<<this->getIdServer();
1493           if (contextClientTmp->clientRank==0) msg<<*registryOut ;
1494           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
1495           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1496             event.push(*itRank,1,msg);
1497           contextClientTmp->sendEvent(event);
1498         }
1499         else contextClientTmp->sendEvent(event);
1500    }
1501
1502    // if (!hasServer)
1503    // {
1504    //   if (client->isServerLeader())
1505    //   {
1506    //      CMessage msg ;
1507    //      msg<<this->getIdServer();
1508    //      if (client->clientRank==0) msg<<*registryOut ;
1509    //      const std::list<int>& ranks = client->getRanksServerLeader();
1510    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1511    //        event.push(*itRank,1,msg);
1512    //      client->sendEvent(event);
1513    //    }
1514    //    else client->sendEvent(event);
1515    // }
1516    // else
1517    // {
1518    //   if (clientPrimServer->isServerLeader())
1519    //   {
1520    //      CMessage msg ;
1521    //      msg<<this->getIdServer();
1522    //      if (clientPrimServer->clientRank==0) msg<<*registryOut ;
1523    //      const std::list<int>& ranks = clientPrimServer->getRanksServerLeader();
1524    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1525    //        event.push(*itRank,1,msg);
1526    //      clientPrimServer->sendEvent(event);
1527    //    }
1528    //    else clientPrimServer->sendEvent(event);
1529    // }
1530  }
1531
1532} // namespace xios
Note: See TracBrowser for help on using the repository browser.