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

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

dev: intermediate commit.

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