source: XIOS/trunk/src/node/file.cpp @ 591

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

Remove leftovers from the XMLIO age.

  • 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: 28.3 KB
Line 
1#include "file.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6#include "object_factory.hpp"
7#include "data_output.hpp"
8#include "context.hpp"
9#include "context_server.hpp"
10#include "nc4_data_output.hpp"
11#include "calendar_util.hpp"
12#include "date.hpp"
13#include "message.hpp"
14#include "type.hpp"
15#include "xios_spl.hpp"
16#include "context_client.hpp"
17#include "mpi.hpp"
18
19namespace xios {
20
21   /// ////////////////////// Définitions ////////////////////// ///
22
23   CFile::CFile(void)
24      : CObjectTemplate<CFile>(), CFileAttributes()
25      , vFieldGroup(), data_out(), enabledFields(), fileComm(MPI_COMM_NULL)
26   {
27     setVirtualFieldGroup() ;
28     setVirtualVariableGroup() ;
29   }
30
31   CFile::CFile(const StdString & id)
32      : CObjectTemplate<CFile>(id), CFileAttributes()
33      , vFieldGroup(), data_out(), enabledFields(), fileComm(MPI_COMM_NULL)
34    {
35      setVirtualFieldGroup() ;
36      setVirtualVariableGroup() ;
37    }
38
39   CFile::~CFile(void)
40   { /* Ne rien faire de plus */ }
41
42   ///---------------------------------------------------------------
43  //! Get name of file
44   StdString CFile::GetName(void)   { return (StdString("file")); }
45   StdString CFile::GetDefName(void){ return (CFile::GetName()); }
46   ENodeType CFile::GetType(void)   { return (eFile); }
47
48   //----------------------------------------------------------------
49   /*!
50   \brief Get data that will be written out.
51   Each enabled file in xml represents a physical netcdf file.
52   This function allows to access to data to be written out into netcdf file
53   \return data written out.
54   */
55   boost::shared_ptr<CDataOutput> CFile::getDataOutput(void) const
56   {
57      return (data_out);
58   }
59
60   /*!
61   \brief Get virtual field group
62      In each file, there always exists a field group which is the ancestor of all
63   fields in the file. This is considered be virtual because it is created automatically during
64   file initialization and it normally doesn't appear on xml file
65   \return Pointer to field group
66   */
67   CFieldGroup* CFile::getVirtualFieldGroup(void) const
68   {
69      return (this->vFieldGroup);
70   }
71
72   /*!
73   \brief Get virtual variable group
74      In each file, there always exists a variable group which is the ancestor of all
75   variable in the file. This is considered be virtual because it is created automatically during
76   file initialization and it normally doesn't appear on xml file
77   \return Pointer to variable group
78   */
79   CVariableGroup* CFile::getVirtualVariableGroup(void) const
80   {
81      return (this->vVariableGroup);
82   }
83
84   //! Get all fields of a file
85   std::vector<CField*> CFile::getAllFields(void) const
86   {
87      return (this->vFieldGroup->getAllChildren());
88   }
89
90   //! Get all variables of a file
91   std::vector<CVariable*> CFile::getAllVariables(void) const
92   {
93      return (this->vVariableGroup->getAllChildren());
94   }
95
96   //----------------------------------------------------------------
97   /*!
98   \brief Get all enabled fields of file
99      A field is considered to be enabled if it fullfil these conditions: it is enabled, inside a enabled file
100   and its own level is not larger than file output level.
101   \param [in] default_outputlevel default value output level of file
102   \param [in] default_level default value level of field
103   \param [in] default_enabled flag determine by default if field is enabled
104   \return Vector of pointers of enabled fields
105   */
106   std::vector<CField*> CFile::getEnabledFields(int default_outputlevel,
107                                                int default_level,
108                                                bool default_enabled)
109   {
110      if (!this->enabledFields.empty())
111         return (this->enabledFields);
112
113      const int _outputlevel =
114         (!output_level.isEmpty()) ? output_level.getValue() : default_outputlevel;
115      std::vector<CField*>::iterator it;
116      this->enabledFields = this->getAllFields();
117
118      std::vector<CField*> newEnabledFields;
119
120      for ( it = this->enabledFields.begin() ; it != this->enabledFields.end(); it++ )
121      {
122         if (!(*it)->enabled.isEmpty()) // Si l'attribut 'enabled' est défini ...
123         {
124            if (! (*it)->enabled.getValue()) continue;
125//            { it--; this->enabledFields.erase(it+1); continue; }
126         }
127         else // Si l'attribut 'enabled' n'est pas défini ...
128         {
129            if (!default_enabled) continue ;
130//            { it--; this->enabledFields.erase(it+1); continue; }
131         }
132
133         if (!(*it)->level.isEmpty()) // Si l'attribut 'level' est défini ...
134         {
135            if ((*it)->level.getValue() > _outputlevel) continue ;
136//            { it--; this->enabledFields.erase(it+1); continue; }
137         }
138         else // Si l'attribut 'level' n'est pas défini ...
139         {
140            if (default_level > _outputlevel) continue ;
141//            { it--; this->enabledFields.erase(it+1); continue; }
142         }
143
144//         CField* field_tmp=(*it).get() ;
145//         shared_ptr<CField> sptfield=*it ;
146//         field_tmp->refObject.push_back(sptfield) ;
147         newEnabledFields.push_back(*it) ;
148         // Le champ est finalement actif, on y ajoute sa propre reference.
149//         (*it)->refObject.push_back(*it);
150         // Le champ est finalement actif, on y ajoute la référence au champ de base.
151         (*it)->setRelFile(CFile::get(this));
152//         (*it)->baseRefObject->refObject.push_back(*it);
153         // A faire, ajouter les references intermediaires...
154      }
155      enabledFields=newEnabledFields ;
156
157      return (this->enabledFields);
158   }
159
160   //----------------------------------------------------------------
161   //! Change virtual field group to a new one
162   void CFile::setVirtualFieldGroup(CFieldGroup* newVFieldGroup)
163   {
164      this->vFieldGroup = newVFieldGroup;
165   }
166
167   //! Change virtual variable group to new one
168   void CFile::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
169   {
170      this->vVariableGroup = newVVariableGroup;
171   }
172
173   //----------------------------------------------------------------
174   //! Create virtual field group, which is done normally on initializing file
175   void CFile::setVirtualFieldGroup(void)
176   {
177      this->setVirtualFieldGroup(CFieldGroup::create());
178   }
179
180   //! Create virtual variable group, which is done normally on initializing file
181   void CFile::setVirtualVariableGroup(void)
182   {
183      this->setVirtualVariableGroup(CVariableGroup::create());
184   }
185
186   //----------------------------------------------------------------
187   bool CFile::isSyncTime(void)
188   {
189     CContext* context = CContext::getCurrent() ;
190     const CDate& currentDate = context->calendar->getCurrentDate() ;
191     if (!sync_freq.isEmpty())
192     {
193       if (*lastSync + sync_freq.getValue() < currentDate)
194       {
195         *lastSync=currentDate ;
196         return true ;
197        }
198      }
199      return false ;
200    }
201
202   //! Initialize a file in order to write into it
203   void CFile::initFile(void)
204   {
205      CContext* context = CContext::getCurrent() ;
206      const CDate& currentDate = context->calendar->getCurrentDate() ;
207      CContextServer* server=context->server ;
208
209      lastSync=new CDate(currentDate) ;
210      lastSplit=new CDate(currentDate) ;
211      isOpen=false ;
212
213      allDomainEmpty=true ;
214
215      set<CDomain*> setDomain ;
216
217      std::vector<CField*>::iterator it, end = this->enabledFields.end();
218      for (it = this->enabledFields.begin() ;it != end; it++)
219      {
220         CField* field = *it;
221//         allDomainEmpty&=field->grid->domain->isEmpty() ;
222         allDomainEmpty&=(!field->grid->doGridHaveDataToWrite());
223         std::vector<CDomain*> vecDomain = field->grid->getDomains();
224         for (int i = 0; i < vecDomain.size(); ++i)
225            setDomain.insert(vecDomain[i]);
226//            setDomain.insert(field->grid->domain) ;
227      }
228      nbDomain=setDomain.size() ;
229
230      // create sub communicator for file
231      int color=allDomainEmpty?0:1 ;
232      MPI_Comm_split(server->intraComm,color,server->intraCommRank,&fileComm) ;
233      if (allDomainEmpty) MPI_Comm_free(&fileComm) ;
234      //
235
236    }
237
238    //! Verify state of a file
239    void CFile::checkFile(void)
240    {
241      if (!isOpen) createHeader() ;
242      checkSync() ;
243      checkSplit() ;
244    }
245
246
247    /*!
248    \brief Verify if synchronisation should be done
249        If syn option is enabled, syn frequence and current time will be used to
250    calculate the moment to syn file(s)
251    \return True if it is the moment to synchronize file, otherwise false
252    */
253   bool CFile::checkSync(void)
254   {
255     CContext* context = CContext::getCurrent() ;
256     const CDate& currentDate = context->calendar->getCurrentDate() ;
257     if (!sync_freq.isEmpty())
258     {
259       if (*lastSync + sync_freq.getValue() <= currentDate)
260       {
261         *lastSync=currentDate ;
262         data_out->syncFile() ;
263         return true ;
264        }
265      }
266      return false ;
267    }
268
269    /*!
270    \brief Verify if splitting should be done
271        If split option is enabled, split frequence and current time will be used to
272    calculate the moment to split file
273    \return True if it is the moment to split file, otherwise false
274    */
275    bool CFile::checkSplit(void)
276    {
277      CContext* context = CContext::getCurrent() ;
278      const CDate& currentDate = context->calendar->getCurrentDate() ;
279      if (!split_freq.isEmpty())
280      {
281        if (currentDate > *lastSplit + split_freq.getValue())
282        {
283          *lastSplit = *lastSplit + split_freq.getValue();
284          std::vector<CField*>::iterator it, end = this->enabledFields.end();
285          for (it = this->enabledFields.begin() ;it != end; it++)  (*it)->resetNStep() ;
286          createHeader() ;
287          return true ;
288        }
289      }
290      return false ;
291    }
292
293   /*!
294   \brief Create header of netcdf file
295   There are some information to fill in header of each netcdf.
296   */
297   void CFile::createHeader(void)
298   {
299      CContext* context = CContext::getCurrent() ;
300      CContextServer* server=context->server ;
301
302      if (!allDomainEmpty)
303      {
304         StdString filename = (!name.isEmpty()) ?   name.getValue() : getId();
305         StdOStringStream oss;
306         oss << filename;
307         if (!name_suffix.isEmpty()) oss << name_suffix.getValue();
308
309         if (!split_freq.isEmpty())
310         {
311           string splitFormat ;
312           if (split_freq_format.isEmpty())
313           {
314             if (split_freq.getValue().second != 0) splitFormat = "%y%mo%d%h%mi%s";
315             else if (split_freq.getValue().minute != 0) splitFormat = "%y%mo%d%h%mi";
316             else if (split_freq.getValue().hour != 0) splitFormat = "%y%mo%d%h";
317             else if (split_freq.getValue().day != 0) splitFormat = "%y%mo%d";
318             else if (split_freq.getValue().month != 0) splitFormat = "%y%mo";
319             else splitFormat = "%y";
320           }
321           else splitFormat=split_freq_format ;
322           oss << "_" << lastSplit->getStr(splitFormat)
323               << "-" << (*lastSplit + split_freq.getValue() - 1 * Second).getStr(splitFormat);
324         }
325
326        bool append = !this->append.isEmpty() && this->append.getValue();
327
328         bool useClassicFormat = !format.isEmpty() && format == format_attr::netcdf4_classic;
329
330         bool multifile=true ;
331         if (!type.isEmpty())
332         {
333           if (type==type_attr::one_file) multifile=false ;
334           else if (type==type_attr::multiple_file) multifile=true ;
335
336         }
337#ifndef USING_NETCDF_PAR
338         if (!multifile)
339         {
340            info(0)<<"!!! Warning -> Using non parallel version of netcdf, switching in multiple_file mode for file : "<<filename<<" ..."<<endl ;
341            multifile=true ;
342          }
343#endif
344         if (multifile)
345         {
346            int commSize, commRank ;
347            MPI_Comm_size(fileComm,&commSize) ;
348            MPI_Comm_rank(fileComm,&commRank) ;
349
350            if (server->intraCommSize > 1)
351            {
352              oss << "_"  ;
353              int width=0 ; int n=commSize-1 ;
354              while(n != 0) { n=n/10 ; width++ ;}
355              if (!min_digits.isEmpty())
356                if (width<min_digits) width=min_digits ;
357              oss.width(width) ;
358              oss.fill('0') ;
359              oss<<right<< commRank;
360            }
361         }
362         oss << ".nc";
363
364         bool isCollective = par_access.isEmpty() ||  par_access == par_access_attr::collective;
365
366         if (isOpen) data_out->closeFile();
367
368        data_out = shared_ptr<CDataOutput>(new CNc4DataOutput(oss.str(), append, useClassicFormat,
369                                                              fileComm, multifile, isCollective));
370        isOpen = true;
371
372        data_out->writeFile(CFile::get(this));
373
374        // Do not recreate the file structure if opening an existing file
375        if (!data_out->IsInAppendMode())
376        {
377          std::vector<CField*>::iterator it, end = this->enabledFields.end();
378          for (it = this->enabledFields.begin(); it != end; it++)
379          {
380            CField* field = *it;
381            this->data_out->writeFieldGrid(field);
382          }
383          this->data_out->writeTimeDimension();
384
385          for (it = this->enabledFields.begin(); it != end; it++)
386          {
387            CField* field = *it;
388            this->data_out->writeField(field);
389          }
390
391          vector<CVariable*> listVars = getAllVariables() ;
392          for (vector<CVariable*>::iterator it = listVars.begin(); it != listVars.end(); it++)
393            this->data_out->writeAttribute(*it);
394
395          this->data_out->definition_end();
396        }
397      }
398   }
399
400   //! Close file
401   void CFile::close(void)
402   {
403     delete lastSync ;
404     delete lastSplit ;
405     if (!allDomainEmpty)
406       if (isOpen)
407       {
408         this->data_out->closeFile();
409       }
410      if (fileComm != MPI_COMM_NULL) MPI_Comm_free(&fileComm) ;
411   }
412   //----------------------------------------------------------------
413
414   /*!
415   \brief Parse xml file and write information into file object
416   \param [in] node xmld node corresponding in xml file
417   */
418   void CFile::parse(xml::CXMLNode & node)
419   {
420      SuperClass::parse(node);
421
422      if (node.goToChildElement())
423      {
424        do
425        {
426           if (node.getElementName()=="field" || node.getElementName()=="field_group") this->getVirtualFieldGroup()->parseChild(node);
427           else if (node.getElementName()=="variable" || node.getElementName()=="variable_group") this->getVirtualVariableGroup()->parseChild(node);
428        } while (node.goToNextElement()) ;
429        node.goToParentElement();
430      }
431
432   }
433   //----------------------------------------------------------------
434
435   /*!
436   \brief Represent a file in form of string with all its info
437   \return String
438   */
439   StdString CFile::toString(void) const
440   {
441      StdOStringStream oss;
442
443      oss << "<" << CFile::GetName() << " ";
444      if (this->hasId())
445         oss << " id=\"" << this->getId() << "\" ";
446      oss << SuperClassAttribute::toString() << ">" << std::endl;
447      if (this->getVirtualFieldGroup() != NULL)
448         oss << *this->getVirtualFieldGroup() << std::endl;
449      oss << "</" << CFile::GetName() << " >";
450      return (oss.str());
451   }
452
453   //----------------------------------------------------------------
454
455   /*!
456   \brief Find all inheritace among objects in a file.
457   \param [in] apply (true) write attributes of parent into ones of child if they are empty
458                     (false) write attributes of parent into a new container of child
459   \param [in] parent
460   */
461   void CFile::solveDescInheritance(bool apply, const CAttributeMap * const parent)
462   {
463      SuperClassAttribute::setAttributes(parent,apply);
464      this->getVirtualFieldGroup()->solveDescInheritance(apply, NULL);
465      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
466   }
467
468   //----------------------------------------------------------------
469
470//   void CFile::processEnabledFile(void)
471//   {
472//     if (output_freq.isEmpty()) ERROR("void CFile::processEnabledFile(void)",
473//                                       <<"File attribute <<output_freq>> is undefined");
474//     solveFieldRefInheritance(true) ;
475//     getEnabledFields() ;
476//     processEnabledFields() ;
477//   }
478
479//   void CFile::processEnabledFields(void)
480//   {
481//      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
482//      {
483//        this->enabledFields[i]->processEnabledField() ;
484//      }
485//   }
486
487   /*!
488   \brief Resolve all reference of active fields.
489      In order to know exactly which data each active field has, a search for all its
490   reference to find its parents or/and its base reference object must be done. Moreover
491   during this search, there are some information that can only be sent to server AFTER
492   all information of active fields are created on server side, e.g: checking mask or index
493   \param [in] sendToServer: Send all info to server (true) or only a part of it (false)
494   */
495   void CFile::solveAllRefOfEnabledFields(bool sendToServer)
496   {
497     int size = this->enabledFields.size();
498     for (int i = 0; i < size; ++i)
499     {
500       this->enabledFields[i]->solveAllReferenceEnabledField(sendToServer);
501     }
502   }
503
504   /*!
505   \brief Contruct all expression related to active fields.
506      Each field can do some expressions which appear on the xml file, and itself can be
507   a result of an expression among some other fields. This function builds all possible expression
508   relating to active fields.
509   */
510   void CFile::buildAllExpressionOfEnabledFields()
511   {
512     int size = this->enabledFields.size();
513     for (int i = 0; i < size; ++i)
514     {
515       this->enabledFields[i]->buildAllExpressionEnabledField();
516     }
517   }
518
519   void CFile::solveFieldRefInheritance(bool apply)
520   {
521      // Résolution des héritages par référence de chacun des champs contenus dans le fichier.
522      std::vector<CField*> allF = this->getAllFields();
523      for (unsigned int i = 0; i < allF.size(); i++)
524         allF[i]->solveRefInheritance(apply);
525   }
526
527   //----------------------------------------------------------------
528
529   void CFile::solveEFGridRef(void)
530   {
531      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
532         this->enabledFields[i]->solveGridReference();
533   }
534
535   //----------------------------------------------------------------
536
537   void CFile::solveEFOperation(void)
538   {
539      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
540         this->enabledFields[i]->solveOperation();
541   }
542
543   void CFile::solveEFExpression(void)
544   {
545      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
546         this->enabledFields[i]->buildExpression();
547   }
548
549   /*!
550   \brief Add a field into file.
551      A field is added into file and it will be written out if the file is enabled and
552   level of this field is smaller than level_output. A new field won't be created if one
553   with id has already existed
554   \param [in] id String identity of new field
555   \return Pointer to added (or already existed) field
556   */
557   CField* CFile::addField(const string& id)
558   {
559     return vFieldGroup->createChild(id) ;
560   }
561
562   /*!
563   \brief Add a field group into file.
564      A field group is added into file and it will play a role as parents for fields.
565   A new field group won't be created if one with id has already existed
566   \param [in] id String identity of new field group
567   \return Pointer to added (or already existed) field group
568   */
569   CFieldGroup* CFile::addFieldGroup(const string& id)
570   {
571     return vFieldGroup->createChildGroup(id) ;
572   }
573
574   /*!
575   \brief Add a variable into file.
576      A variable is added into file and if one with id has already existed, pointer to
577   it will be returned.
578      Variable as long as attributes are information container of file.
579   However, whereas attributes are "fixed" information, variables provides a more flexible way to user
580   to fill in (extra) information for a file.
581   \param [in] id String identity of new variable
582   \return Pointer to added (or already existed) variable
583   */
584   CVariable* CFile::addVariable(const string& id)
585   {
586     return vVariableGroup->createChild(id) ;
587   }
588
589   /*!
590   \brief Add a variable group into file.
591      A variable group is added into file and it will play a role as parents for variables.
592   A new variable group won't be created if one with id has already existed
593   \param [in] id String identity of new variable group
594   \return Pointer to added (or already existed) variable group
595   */
596   CVariableGroup* CFile::addVariableGroup(const string& id)
597   {
598     return vVariableGroup->createChildGroup(id) ;
599   }
600
601   /*!
602   \brief Send a message to create a field on server side
603   \param[in] id String identity of field that will be created on server
604   */
605   void CFile::sendAddField(const string& id)
606   {
607    CContext* context=CContext::getCurrent() ;
608
609    if (! context->hasServer )
610    {
611       CContextClient* client=context->client ;
612
613       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD) ;
614       if (client->isServerLeader())
615       {
616         CMessage msg ;
617         msg<<this->getId() ;
618         msg<<id ;
619         event.push(client->getServerLeader(),1,msg) ;
620         client->sendEvent(event) ;
621       }
622       else client->sendEvent(event) ;
623    }
624
625   }
626
627   /*!
628   \brief Send a message to create a field group on server side
629   \param[in] id String identity of field group that will be created on server
630   */
631   void CFile::sendAddFieldGroup(const string& id)
632   {
633    CContext* context=CContext::getCurrent() ;
634    if (! context->hasServer )
635    {
636       CContextClient* client=context->client ;
637
638       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD_GROUP) ;
639       if (client->isServerLeader())
640       {
641         CMessage msg ;
642         msg<<this->getId() ;
643         msg<<id ;
644         event.push(client->getServerLeader(),1,msg) ;
645         client->sendEvent(event) ;
646       }
647       else client->sendEvent(event) ;
648    }
649
650   }
651
652   /*!
653   \brief Receive a message annoucing the creation of a field on server side
654   \param[in] event Received event
655   */
656   void CFile::recvAddField(CEventServer& event)
657   {
658
659      CBufferIn* buffer=event.subEvents.begin()->buffer;
660      string id;
661      *buffer>>id ;
662      get(id)->recvAddField(*buffer) ;
663   }
664
665   /*!
666   \brief Receive a message annoucing the creation of a field on server side
667   \param[in] buffer Buffer containing message
668   */
669   void CFile::recvAddField(CBufferIn& buffer)
670   {
671      string id ;
672      buffer>>id ;
673      addField(id) ;
674   }
675
676   /*!
677   \brief Receive a message annoucing the creation of a field group on server side
678   \param[in] event Received event
679   */
680   void CFile::recvAddFieldGroup(CEventServer& event)
681   {
682
683      CBufferIn* buffer=event.subEvents.begin()->buffer;
684      string id;
685      *buffer>>id ;
686      get(id)->recvAddFieldGroup(*buffer) ;
687   }
688
689   /*!
690   \brief Receive a message annoucing the creation of a field group on server side
691   \param[in] buffer Buffer containing message
692   */
693   void CFile::recvAddFieldGroup(CBufferIn& buffer)
694   {
695      string id ;
696      buffer>>id ;
697      addFieldGroup(id) ;
698   }
699
700   /*!
701   \brief Send messages to duplicate all variables on server side
702      Because each variable has also its attributes. So first thing to do is replicate
703   all these attributes on server side. Because variable can have a value, the second thing
704   is to duplicate this value on server, too.
705   */
706   void CFile::sendAddAllVariables()
707   {
708     if (!getAllVariables().empty())
709     {
710       // Firstly, it's necessary to add virtual variable group
711       sendAddVariableGroup(getVirtualVariableGroup()->getId());
712
713       // Okie, now we can add to this variable group
714       std::vector<CVariable*> allVar = getAllVariables();
715       std::vector<CVariable*>::const_iterator it = allVar.begin();
716       std::vector<CVariable*>::const_iterator itE = allVar.end();
717
718       for (; it != itE; ++it)
719       {
720         this->sendAddVariable((*it)->getId());
721         (*it)->sendAllAttributesToServer();
722         (*it)->sendValue();
723       }
724     }
725   }
726
727   /*!
728   \brief Send a message to create a variable on server side
729      A variable always belongs to a variable group
730   \param[in] id String identity of variable that will be created on server
731   */
732   void CFile::sendAddVariable(const string& id)
733   {
734    CContext* context=CContext::getCurrent() ;
735
736    if (! context->hasServer )
737    {
738       CContextClient* client=context->client ;
739
740       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE) ;
741       if (client->isServerLeader())
742       {
743         CMessage msg ;
744         msg<<this->getId() ;
745         msg<<id ;
746         event.push(client->getServerLeader(),1,msg) ;
747         client->sendEvent(event) ;
748       }
749       else client->sendEvent(event) ;
750    }
751
752   }
753
754   /*!
755   \brief Send a message to create a variable group on server side
756   \param[in] id String identity of variable group that will be created on server
757   */
758   void CFile::sendAddVariableGroup(const string& id)
759   {
760    CContext* context=CContext::getCurrent() ;
761    if (! context->hasServer )
762    {
763       CContextClient* client=context->client ;
764
765       CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP) ;
766       if (client->isServerLeader())
767       {
768         CMessage msg ;
769         msg<<this->getId() ;
770         msg<<id ;
771         event.push(client->getServerLeader(),1,msg) ;
772         client->sendEvent(event) ;
773       }
774       else client->sendEvent(event) ;
775    }
776
777   }
778
779   /*!
780   \brief Receive a message annoucing the creation of a variable on server side
781   \param[in] event Received event
782   */
783   void CFile::recvAddVariable(CEventServer& event)
784   {
785
786      CBufferIn* buffer=event.subEvents.begin()->buffer;
787      string id;
788      *buffer>>id ;
789      get(id)->recvAddVariable(*buffer) ;
790   }
791
792   /*!
793   \brief Receive a message annoucing the creation of a variable on server side
794   \param[in] buffer Buffer containing message
795   */
796   void CFile::recvAddVariable(CBufferIn& buffer)
797   {
798      string id ;
799      buffer>>id ;
800      addVariable(id) ;
801   }
802
803   /*!
804   \brief Receive a message annoucing the creation of a variable group on server side
805   \param[in] event Received event
806   */
807   void CFile::recvAddVariableGroup(CEventServer& event)
808   {
809
810      CBufferIn* buffer=event.subEvents.begin()->buffer;
811      string id;
812      *buffer>>id ;
813      get(id)->recvAddVariableGroup(*buffer) ;
814   }
815
816   /*!
817   \brief Receive a message annoucing the creation of a variable group on server side
818   \param[in] buffer Buffer containing message
819   */
820   void CFile::recvAddVariableGroup(CBufferIn& buffer)
821   {
822      string id ;
823      buffer>>id ;
824      addVariableGroup(id) ;
825   }
826
827   /*!
828     \brief Sending all active (enabled) fields from client to server.
829   Each field is identified uniquely by its string identity. Not only should we
830   send the id to server but also we need to send ids of reference domain and reference axis.
831   With these two id, it's easier to make reference to grid where all data should be written.
832   Remark: This function must be called AFTER all active (enabled) files have been created on the server side
833   */
834   void CFile::sendEnabledFields()
835   {
836     int size = this->enabledFields.size();
837     CField* fieldPtr(0);
838     for (int i = 0; i < size; ++i)
839     {
840       fieldPtr = this->enabledFields[i];
841       if (fieldPtr->name.isEmpty()) fieldPtr->name.setValue(fieldPtr->getBaseFieldReference()->getId());
842       this->sendAddField(fieldPtr->getId());
843       fieldPtr->sendAllAttributesToServer();
844       fieldPtr->sendAddAllVariables();
845     }
846   }
847
848   /*!
849   \brief Dispatch event received from client
850      Whenever a message is received in buffer of server, it will be processed depending on
851   its event type. A new event type should be added in the switch list to make sure
852   it processed on server side.
853   \param [in] event: Received message
854   */
855   bool CFile::dispatchEvent(CEventServer& event)
856   {
857      if (SuperClass::dispatchEvent(event)) return true ;
858      else
859      {
860        switch(event.type)
861        {
862           case EVENT_ID_ADD_FIELD :
863             recvAddField(event) ;
864             return true ;
865             break ;
866
867           case EVENT_ID_ADD_FIELD_GROUP :
868             recvAddFieldGroup(event) ;
869             return true ;
870             break ;
871
872            case EVENT_ID_ADD_VARIABLE :
873             recvAddVariable(event) ;
874             return true ;
875             break ;
876
877           case EVENT_ID_ADD_VARIABLE_GROUP :
878             recvAddVariableGroup(event) ;
879             return true ;
880             break ;
881           default :
882              ERROR("bool CFile::dispatchEvent(CEventServer& event)", <<"Unknown Event") ;
883           return false ;
884        }
885      }
886   }
887
888
889
890
891   ///---------------------------------------------------------------
892
893} // namespace xios
Note: See TracBrowser for help on using the repository browser.