source: XIOS3/trunk/src/node/file.cpp @ 2458

Last change on this file since 2458 was 2458, checked in by ymipsl, 16 months ago

Merge XIOS_FILE_SERVICE dev branch into trunk

YM

  • 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: 46.0 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 "context.hpp"
8#include "context_server.hpp"
9#include "nc4_data_output.hpp"
10#include "nc4_data_input.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#include "timer.hpp"
19#include "server.hpp"
20
21namespace xios {
22
23   /// ////////////////////// Dfinitions ////////////////////// ///
24
25   CFile::CFile(void)
26      : CObjectTemplate<CFile>(), CFileAttributes()
27      , vFieldGroup(), data_out(), enabledFields(), fileComm(MPI_COMM_NULL)
28      , isOpen(false),  checkRead(false), allZoneEmpty(false)
29   {
30     setVirtualFieldGroup(CFieldGroup::create(getId() + "_virtual_field_group"));
31     setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group"));
32   }
33
34   CFile::CFile(const StdString & id)
35      : CObjectTemplate<CFile>(id), CFileAttributes()
36      , vFieldGroup(), data_out(), enabledFields(), fileComm(MPI_COMM_NULL)
37      , isOpen(false), checkRead(false), allZoneEmpty(false)
38    {
39      setVirtualFieldGroup(CFieldGroup::create(getId() + "_virtual_field_group"));
40      setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group"));
41    }
42
43   CFile::~CFile(void)
44   { /* Ne rien faire de plus */ }
45
46   ///---------------------------------------------------------------
47  //! Get name of file
48   StdString CFile::GetName(void)   { return (StdString("file")); }
49   StdString CFile::GetDefName(void){ return (CFile::GetName()); }
50   ENodeType CFile::GetType(void)   { return (eFile); }
51
52   //----------------------------------------------------------------
53
54   const StdString CFile::getFileOutputName(void) const
55   TRY
56   {
57     return (name.isEmpty() ? getId() : name) + (name_suffix.isEmpty() ? StdString("") :  name_suffix.getValue());
58   }
59   CATCH
60
61   //----------------------------------------------------------------
62   /*!
63   \brief Get data writer object.
64   Each enabled file in xml represents a physical netcdf file.
65   This function allows to access the data writer object.
66   \return data writer object.
67   */
68   std::shared_ptr<CDataOutput> CFile::getDataOutput(void) const
69   TRY
70   {
71      return data_out;
72   }
73   CATCH
74
75   /*!
76   \brief Get data reader object.
77   Each enabled file in xml represents a physical netcdf file.
78   This function allows to access the data reader object.
79   \return data reader object.
80   */
81   std::shared_ptr<CDataInput> CFile::getDataInput(void) const
82   TRY
83   {
84      return data_in;
85   }
86   CATCH
87
88   /*!
89   \brief Get virtual field group
90      In each file, there always exists a field group which is the ancestor of all
91   fields in the file. This is considered be virtual because it is created automatically during
92   file initialization and it normally doesn't appear on xml file
93   \return Pointer to field group
94   */
95   CFieldGroup* CFile::getVirtualFieldGroup(void) const
96   TRY
97   {
98      return (this->vFieldGroup);
99   }
100   CATCH
101
102   /*!
103   \brief Get virtual variable group
104      In each file, there always exists a variable group which is the ancestor of all
105   variable in the file. This is considered be virtual because it is created automatically during
106   file initialization and it normally doesn't appear on xml file
107   \return Pointer to variable group
108   */
109   CVariableGroup* CFile::getVirtualVariableGroup(void) const
110   TRY
111   {
112      return (this->vVariableGroup);
113   }
114   CATCH
115
116   //! Get all fields of a file
117   std::vector<CField*> CFile::getAllFields(void) const
118   TRY
119   {
120      return (this->vFieldGroup->getAllChildren());
121   }
122   CATCH
123
124   //! Get all variables of a file
125   std::vector<CVariable*> CFile::getAllVariables(void) const
126   TRY
127   {
128      return (this->vVariableGroup->getAllChildren());
129   }
130   CATCH
131
132   //----------------------------------------------------------------
133   /*!
134   \brief Get all enabled fields of file
135      A field is considered to be enabled if it fullfil these conditions: it is enabled, inside a enabled file
136   and its own level is not larger than file output level.
137   \param [in] default_outputlevel default value output level of file
138   \param [in] default_level default value level of field
139   \param [in] default_enabled flag determine by default if field is enabled
140   \return Vector of pointers of enabled fields
141   */
142   std::vector<CField*> CFile::getEnabledFields(int default_outputlevel,
143                                                int default_level,
144                                                bool default_enabled)
145   TRY
146   {
147      if (!this->enabledFields.empty()) return (this->enabledFields);
148
149      const int _outputlevel = (!output_level.isEmpty()) ? output_level.getValue() : default_outputlevel;
150      std::vector<CField*>::iterator it;
151      this->enabledFields = this->getAllFields();
152
153      std::vector<CField*> newEnabledFields;
154
155      for ( it = this->enabledFields.begin(); it != this->enabledFields.end(); it++ )
156      {
157         if (!(*it)->enabled.isEmpty()) // Si l'attribut 'enabled' est dfini ...
158         {
159            if (! (*it)->enabled.getValue()) continue;
160         }
161         else // Si l'attribut 'enabled' n'est pas dfini ...
162         {
163            if (!default_enabled) continue;
164         }
165
166         if (!(*it)->level.isEmpty()) // Si l'attribut 'level' est dfini ...
167         {
168            if ((*it)->level.getValue() > _outputlevel) continue;
169         }
170         else // Si l'attribut 'level' n'est pas dfini ...
171         {
172            if (default_level > _outputlevel) continue;
173         }
174
175         newEnabledFields.push_back(*it);
176      }
177      enabledFields = newEnabledFields;
178
179      return (this->enabledFields);
180   }
181   CATCH_DUMP_ATTR
182
183   //----------------------------------------------------------------
184   //! Change virtual field group to a new one
185   void CFile::setVirtualFieldGroup(CFieldGroup* newVFieldGroup)
186   TRY
187   {
188      this->vFieldGroup = newVFieldGroup;
189   }
190   CATCH_DUMP_ATTR
191
192   //! Change virtual variable group to new one
193   void CFile::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
194   TRY
195   {
196      this->vVariableGroup = newVVariableGroup;
197   }
198   CATCH_DUMP_ATTR
199
200   //----------------------------------------------------------------
201   bool CFile::isSyncTime(void)
202   TRY
203   {
204     CContext* context = CContext::getCurrent();
205     const CDate& currentDate = context->calendar->getCurrentDate();
206     if (!sync_freq.isEmpty())
207     {
208       if (lastSync + sync_freq.getValue() < currentDate)
209       {
210         lastSync = currentDate;
211         return true;
212        }
213      }
214      return false;
215    }
216    CATCH_DUMP_ATTR
217
218   //! Initialize a file in order to write into it
219   void CFile::initWrite(void)
220   TRY
221   {
222      CContext* context = CContext::getCurrent();
223      const CDate& currentDate = context->calendar->getCurrentDate();
224
225      lastSync  = currentDate;
226      lastSplit = currentDate;
227      if (!split_freq.isEmpty())
228      {
229        StdString keySuffix("CFile::"+getFileOutputName()+"::") ; 
230        if (context->registryIn->foundKey(keySuffix+"splitStart") && context->registryIn->foundKey(keySuffix+"splitEnd"))
231        {
232          CDate savedSplitStart(*context->getCalendar()), savedSplitEnd(*context->getCalendar());
233          context->registryIn->getKey(keySuffix+"splitStart", savedSplitStart);
234          context->registryIn->getKey(keySuffix+"splitEnd",   savedSplitEnd);
235
236          if (savedSplitStart <= lastSplit && lastSplit <= savedSplitEnd)
237            lastSplit = savedSplitStart;
238        }
239      }
240      isOpen = false;     
241
242      set<StdString> setAxis;
243      set<StdString> setDomains;
244
245      std::vector<CField*>::iterator it, end = this->enabledFields.end();
246      for (it = this->enabledFields.begin(); it != end; it++)
247      {
248         CField* field = *it;         
249         std::vector<CAxis*> vecAxis = field->getGrid()->getAxis();
250         for (size_t i = 0; i < vecAxis.size(); ++i)
251           setAxis.insert(vecAxis[i]->getAxisOutputName());
252         std::vector<CDomain*> vecDomains = field->getGrid()->getDomains();
253         for (size_t i = 0; i < vecDomains.size(); ++i)
254           setDomains.insert(vecDomains[i]->getDomainOutputName());
255      }
256      nbAxis = setAxis.size();
257      nbDomains = setDomains.size();
258
259      // create sub communicator for file
260      if (type == CFile::type_attr::multiple_file)
261      {
262        createSubComFile();
263      }
264      else
265      {
266        // NetCDF runs now write of null data
267        MPI_Comm_dup(context->intraComm_, &fileComm) ;
268      }
269
270      if (time_counter_name.isEmpty()) time_counter_name = "time_counter";
271    }
272    CATCH_DUMP_ATTR
273
274    //! Initialize a file in order to write into it
275    void CFile::initRead(void)
276    TRY
277    {
278      CContext* context = CContext::getCurrent();
279      if (checkRead) return;
280      //createSubComFile();
281      allZoneEmpty = false; 
282      MPI_Comm_dup(context->intraComm_, &fileComm) ;
283      checkRead = true;
284    }
285    CATCH_DUMP_ATTR
286
287    /*!
288      Create a sub communicator in which processes participate in reading/opening file
289      Seems to be deprecated (allZoneEmpty too, which is always false)
290    */
291    void CFile::createSubComFile()
292    TRY
293    {
294      CContext* context = CContext::getCurrent();
295
296      // create sub communicator for file
297      allZoneEmpty = true;     
298      std::vector<CField*>::iterator it, end = this->enabledFields.end();
299      for (it = this->enabledFields.begin(); it != end; it++)
300      {
301         CField* field = *it;
302         bool nullGrid = (nullptr == field->getGrid());
303         allZoneEmpty &= nullGrid ? false : !field->getGrid()->doGridHaveDataToWrite();
304      }
305
306      int color = allZoneEmpty ? 0 : 1;
307      MPI_Comm_split(context->intraComm_, color, context->intraCommRank_, &fileComm);
308      if (allZoneEmpty) MPI_Comm_free(&fileComm);
309    }
310    CATCH_DUMP_ATTR
311
312    /*
313       Check condition to write into a file
314       For now, we only use the level-2 server to write files (if this mode is activated)
315       or classical server to do this job.
316    */
317    void CFile::checkWriteFile(void)
318    TRY
319    {
320      CContext* context = CContext::getCurrent();
321
322      if (mode.isEmpty() || mode.getValue() == mode_attr::write)
323      {
324        CTimer::get("Files : create headers").resume();
325        if (!isOpen) createHeader();
326        CTimer::get("Files : create headers").suspend();
327        checkSync();
328      }       
329      checkSplit(); 
330    }
331    CATCH_DUMP_ATTR
332
333    /*
334       Check condition to read from a file
335       For now, we only use the level-1 server to write files (if this mode is activated)
336       or classical server to do this job.
337       This function can be used by client for reading metadata
338    */
339    void CFile::checkReadFile(void)
340    TRY
341    {
342      CContext* context = CContext::getCurrent();
343      // Done by classical server or secondary server
344      // TODO: This condition should be changed soon. It only works with maximum number of level as 2
345
346//ym      if (CServer::serverLevel == 0 || CServer::serverLevel == 1)
347// ym client must doing it also
348//      if (context->getServiceType()==CServicesManager::IO_SERVER || context->getServiceType()==CServicesManager::GATHERER)
349//      {
350        if (!mode.isEmpty() && mode.getValue() == mode_attr::read)
351        {
352          CTimer::get("Files : open headers").resume();
353         
354          if (!isOpen) openInReadMode();
355
356          CTimer::get("Files : open headers").suspend();
357        }
358        //checkSplit(); // Really need for reading?
359 //     }
360    }
361    CATCH_DUMP_ATTR
362
363    /*!
364      Verify if a process participates in an opening-file communicator
365      \return true if the process doesn't participate in opening file
366    */
367    bool CFile::isEmptyZone()
368    TRY
369    {
370      return allZoneEmpty;
371    }
372    CATCH_DUMP_ATTR
373
374    /*!
375    \brief Verify if synchronisation should be done
376        If syn option is enabled, syn frequence and current time will be used to
377    calculate the moment to syn file(s)
378    \return True if it is the moment to synchronize file, otherwise false
379    */
380   bool CFile::checkSync(void)
381   TRY
382   {
383     CContext* context = CContext::getCurrent();
384     const CDate& currentDate = context->calendar->getCurrentDate();
385     if (!sync_freq.isEmpty())
386     {
387       if (lastSync + sync_freq.getValue() <= currentDate)
388       {
389         lastSync = currentDate;
390         data_out->syncFile();
391         return true;
392        }
393      }
394      return false;
395    }
396   CATCH_DUMP_ATTR
397
398    /*!
399    \brief Verify if splitting should be done
400        If split option is enabled, split frequence and current time will be used to
401    calculate the moment to split file
402    \return True if it is the moment to split file, otherwise false
403    */
404    bool CFile::checkSplit(void)
405    TRY
406    {
407      CContext* context = CContext::getCurrent();
408      const CDate& currentDate = context->calendar->getCurrentDate();
409      if (!split_freq.isEmpty())
410      {
411        if (currentDate > lastSplit + split_freq.getValue())
412        {
413          lastSplit = lastSplit + split_freq.getValue();
414          std::vector<CField*>::iterator it, end = this->enabledFields.end();
415/*          for (it = this->enabledFields.begin(); it != end; it++)
416          {
417            (*it)->resetNStep();
418            (*it)->resetNStepMax();
419          }*/
420          if (mode.isEmpty() || mode.getValue() == mode_attr::write)
421            createHeader();
422          else
423            openInReadMode();
424          return true;
425        }
426      }
427      return false;
428    }
429    CATCH_DUMP_ATTR
430
431
432   /*!
433   \brief Create header of netcdf file
434   There are some information to fill in header of each netcdf.
435   */
436   void CFile::createHeader(void)
437   TRY
438   {
439      CContext* context = CContext::getCurrent();
440     
441      if (!allZoneEmpty)
442      {
443         StdString filename = getFileOutputName();
444
445// determine splitting format in the file name  : firstPart%start_date%middlePart%end_date%lastPart
446
447         std::string strStartDate="%start_date%" ;
448         std::string strEndDate="%end_date%" ;
449
450         std::string firstPart ;
451         std::string middlePart ;
452         std::string lastPart ;
453         size_t pos1, pos2 ;
454         bool hasStartDate=false ;
455         bool hasEndDate=false ;
456         bool hasSplit = (!split_freq.isEmpty());
457                 
458         pos1=filename.find(strStartDate) ;
459         if (pos1!=std::string::npos)
460         {
461           firstPart=filename.substr(0,pos1) ;
462           pos1+=strStartDate.size() ;
463           hasStartDate=true ;
464         }
465         else pos1=0 ;
466
467         pos2=filename.find(strEndDate,pos1) ;
468         if (pos2!=std::string::npos)
469         {
470           middlePart=filename.substr(pos1,pos2-pos1) ;
471           pos2+=strEndDate.size() ;
472           lastPart=filename.substr(pos2,filename.size()-pos2) ;
473           hasEndDate=true ;
474         }
475         else middlePart=filename.substr(pos1,filename.size()) ;
476
477         if (!hasStartDate && !hasEndDate)
478         {
479           hasStartDate=true ;
480           hasEndDate=true;
481           firstPart=middlePart ;
482           if (hasSplit) firstPart +="_";
483           middlePart="-" ;
484         }
485   
486         StdOStringStream oss;
487
488         if (!split_freq.isEmpty())
489         {
490           CDate split_start ;
491           CDate splitEnd ;
492           if (!split_start_offset.isEmpty()) split_start=lastSplit + split_start_offset ;
493           else split_start=lastSplit ;
494
495           splitEnd = lastSplit + split_freq ;
496           if (!split_last_date.isEmpty())
497           {
498             CDate splitLastDate=CDate::FromString(split_last_date,*CContext::getCurrent()->getCalendar()) ;
499             if( splitLastDate < splitEnd)  splitEnd=splitLastDate ;
500           }
501           
502           if (!split_end_offset.isEmpty()) splitEnd = splitEnd + split_end_offset;
503           else splitEnd = splitEnd - 1 * Second;
504
505           string splitFormat;
506           if (split_freq_format.isEmpty())
507           {
508             CDuration splitFreq = split_freq.getValue();
509             splitFreq.solveTimeStep(*CContext::getCurrent()->getCalendar());
510             if (splitFreq.second != 0) splitFormat = "%y%mo%d%h%mi%s";
511             else if (splitFreq.minute != 0) splitFormat = "%y%mo%d%h%mi";
512             else if (splitFreq.hour != 0) splitFormat = "%y%mo%d%h";
513             else if (splitFreq.day != 0) splitFormat = "%y%mo%d";
514             else if (splitFreq.month != 0) splitFormat = "%y%mo";
515             else splitFormat = "%y";
516           }
517           else splitFormat = split_freq_format;
518
519           oss << firstPart ;
520           if (hasStartDate) oss << split_start.getStr(splitFormat) ;
521           oss << middlePart ;
522           if (hasEndDate) oss << splitEnd.getStr(splitFormat);
523           oss << lastPart ;
524
525           StdString keySuffix("CFile::"+getFileOutputName()+"::") ; 
526           context->registryOut->setKey(keySuffix+"splitStart", lastSplit);
527           context->registryOut->setKey(keySuffix+"splitEnd",   splitEnd);
528         }
529         else oss<<firstPart<<lastPart ;
530
531        bool append = !this->append.isEmpty() && this->append.getValue();
532
533         bool useClassicFormat = !format.isEmpty() && format == format_attr::netcdf4_classic;
534         bool useCFConvention = convention.isEmpty() || convention == convention_attr::CF;
535
536         bool multifile = true;
537         if (!type.isEmpty())
538         {
539           if (type == type_attr::one_file) multifile = false;
540           else if (type == type_attr::multiple_file) multifile = true;
541
542         }
543#ifndef USING_NETCDF_PAR
544         if (!multifile)
545         {
546            info(0) << "!!! Warning -> Using non parallel version of netcdf, switching in multiple_file mode for file : " << filename << " ..." << endl;
547            multifile = true;
548          }
549#endif
550         if (multifile)
551         {
552            int commSize, commRank;
553            MPI_Comm_size(fileComm, &commSize);
554            MPI_Comm_rank(fileComm, &commRank);
555
556            if (context->intraCommSize_ > 1)
557            {
558              oss << "_" ;
559              int width=0; int n = commSize-1;
560              while (n != 0) { n = n / 10; width++;}
561              if (!min_digits.isEmpty())
562                if (width < min_digits) width = min_digits;
563              oss.width(width);
564              oss.fill('0');
565              oss << right << commRank;
566            }
567         }
568         oss << ".nc";
569
570         bool isCollective = par_access.isEmpty() ||  par_access == par_access_attr::collective;
571
572         if (isOpen) data_out->closeFile();
573
574        data_out = std::shared_ptr<CDataOutput>(new CNc4DataOutput(this, oss.str(), append, useClassicFormat, useCFConvention,
575                                                              fileComm, multifile, isCollective, time_counter_name));
576        isOpen = true;
577
578        data_out->writeFile(CFile::get(this));
579
580        if (!useCFConvention) sortEnabledFieldsForUgrid();
581
582        // Do not recreate the file structure if opening an existing file
583        if (!data_out->IsInAppendMode())
584        {
585          std::vector<CField*>::iterator it, end = this->enabledFields.end();
586          for (it = this->enabledFields.begin(); it != end; it++)
587          {
588            CField* field = *it;
589            this->data_out->writeFieldGrid(field);
590          }
591          this->data_out->writeTimeDimension();
592
593          for (it = this->enabledFields.begin(); it != end; it++)
594          {
595            CField* field = *it;
596            this->data_out->writeFieldTimeAxis(field);
597          }
598         
599          for (it = this->enabledFields.begin(); it != end; it++)
600          {
601            CField* field = *it;
602            this->data_out->writeField(field);
603          }
604
605          vector<CVariable*> listVars = getAllVariables();
606          for (vector<CVariable*>::iterator it = listVars.begin(); it != listVars.end(); it++)
607            this->data_out->writeAttribute(*it);
608
609          this->data_out->definition_end();
610        }
611        else
612        {
613          // check time axis even in append mode
614          std::vector<CField*>::iterator it, end = this->enabledFields.end();
615          for (it = this->enabledFields.begin(); it != end; it++)
616          {
617            CField* field = *it;
618            this->data_out->writeFieldTimeAxis(field);
619          }
620        }
621      }
622   }
623   CATCH_DUMP_ATTR
624
625  /*!
626  \brief Open an existing NetCDF file in read-only mode
627  */
628  void CFile::openInReadMode()
629  TRY
630  {
631    CContext* context = CContext::getCurrent();
632    MPI_Comm readComm = this->fileComm;
633
634    if (!allZoneEmpty)
635    {
636      StdString filename = getFileOutputName();
637      StdOStringStream oss;
638      oss << filename;
639
640      if (!split_freq.isEmpty())
641      {
642        string splitFormat;
643        if (split_freq_format.isEmpty())
644        {
645          CDuration splitFreq = split_freq.getValue();
646          splitFreq.solveTimeStep(*CContext::getCurrent()->getCalendar());
647          if (splitFreq.second != 0) splitFormat = "%y%mo%d%h%mi%s";
648          else if (splitFreq.minute != 0) splitFormat = "%y%mo%d%h%mi";
649          else if (splitFreq.hour != 0) splitFormat = "%y%mo%d%h";
650          else if (splitFreq.day != 0) splitFormat = "%y%mo%d";
651          else if (splitFreq.month != 0) splitFormat = "%y%mo";
652          else splitFormat = "%y";
653        }
654        else splitFormat = split_freq_format;
655        oss << "_" << lastSplit.getStr(splitFormat)
656        << "-" << (lastSplit + split_freq.getValue() - 1 * Second).getStr(splitFormat);
657      }
658
659      bool multifile = true;
660      if (!type.isEmpty())
661      {
662        if (type == type_attr::one_file) multifile = false;
663        else if (type == type_attr::multiple_file) multifile = true;
664      }
665  #ifndef USING_NETCDF_PAR
666      if (!multifile)
667      {
668        info(0) << "!!! Warning -> Using non parallel version of netcdf, switching in multiple_file mode for file : " << filename << " ..." << endl;
669        multifile = true;
670      }
671  #endif
672      if (multifile)
673      {
674        int commSize, commRank;
675        MPI_Comm_size(readComm, &commSize);
676        MPI_Comm_rank(readComm, &commRank);
677
678        if (context->intraCommSize_ > 1)
679        {
680          oss << "_";
681          int width = 0, n = commSize - 1;
682          while (n != 0) { n = n / 10; width++; }
683          if (!min_digits.isEmpty() && width < min_digits)
684            width = min_digits;
685          oss.width(width);
686          oss.fill('0');
687          oss << right << commRank;
688        }
689      }
690      oss << ".nc";
691
692      bool isCollective = par_access.isEmpty() || par_access == par_access_attr::collective;
693      bool readMetaDataPar = true;
694      if (context->getServiceType()==CServicesManager::CLIENT) readMetaDataPar = (read_metadata_par.isEmpty()) ? false : read_metadata_par;
695
696      if (isOpen) data_out->closeFile();
697      bool ugridConvention = !convention.isEmpty() ? (convention == convention_attr::UGRID) : false;
698      if (time_counter_name.isEmpty())
699        data_in = std::shared_ptr<CDataInput>(new CNc4DataInput(oss.str(), readComm, multifile, isCollective, readMetaDataPar, ugridConvention));
700      else
701        data_in = std::shared_ptr<CDataInput>(new CNc4DataInput(oss.str(), readComm, multifile, isCollective, readMetaDataPar, ugridConvention, time_counter_name));
702      isOpen = true;
703    }
704  }
705  CATCH_DUMP_ATTR
706
707   //! Close file
708   void CFile::close(void)
709   TRY
710   {
711     if (!allZoneEmpty)
712       if (isOpen)
713       {
714         if (mode.isEmpty() || mode.getValue() == mode_attr::write)
715          this->data_out->closeFile();
716         else
717          this->data_in->closeFile();
718        isOpen = false;
719       }
720      if (fileComm != MPI_COMM_NULL) MPI_Comm_free(&fileComm);
721   }
722   CATCH_DUMP_ATTR
723
724   //----------------------------------------------------------------
725
726   void CFile::readAttributesOfEnabledFieldsInReadMode()
727   TRY
728   {
729     if (enabledFields.empty()) return;
730
731     // Just check file and try to open it
732     if (time_counter_name.isEmpty()) time_counter_name = "time_counter";
733
734     checkReadFile();
735
736     for (int idx = 0; idx < enabledFields.size(); ++idx)
737     {
738        // First of all, find out which domain and axis associated with this field
739        enabledFields[idx]->solveGridReference();
740
741        // Read attributes of domain and axis from this file
742        this->data_in->readFieldAttributesMetaData(enabledFields[idx]);
743
744        // Now complete domain and axis associated with this field
745       
746       //ym => this a problem in wich order are done the grid generation. Probably metadata are read in file and after the grid is ditributed by the filter
747       // => must be checked in detail. But solveGenerated grid is not existing any more with new transformation framework
748       // enabledFields[idx]->solveGenerateGrid();
749
750        // Read necessary value from file
751        this->data_in->readFieldAttributesValues(enabledFields[idx]);
752
753        // Fill attributes for base reference
754        enabledFields[idx]->solveGridDomainAxisBaseRef();
755     }
756
757     // Now everything is ok, close it
758     close();
759   }
760   CATCH_DUMP_ATTR
761
762   void CFile::readFieldAttributesMetaData(CField* field)
763   {
764     this->data_in->readFieldAttributesMetaData(field);
765   }
766
767   void CFile::readFieldAttributesValues(CField* field)
768   {
769     this->data_in->readFieldAttributesValues(field);
770   }
771   /*!
772   \brief Parse xml file and write information into file object
773   \param [in] node xmld node corresponding in xml file
774   */
775   void CFile::parse(xml::CXMLNode & node)
776   TRY
777   {
778      SuperClass::parse(node);
779
780      if (node.goToChildElement())
781      {
782        do
783        {
784           if (node.getElementName()=="field" || node.getElementName()=="field_group") this->getVirtualFieldGroup()->parseChild(node);
785           else if (node.getElementName()=="variable" || node.getElementName()=="variable_group") this->getVirtualVariableGroup()->parseChild(node);
786        } while (node.goToNextElement());
787        node.goToParentElement();
788      }
789   }
790   CATCH_DUMP_ATTR
791
792   //----------------------------------------------------------------
793
794   /*!
795   \brief Represent a file in form of string with all its info
796   \return String
797   */
798   StdString CFile::toString(void) const
799   TRY
800   {
801      StdOStringStream oss;
802
803      oss << "<" << CFile::GetName() << " ";
804      if (this->hasId())
805         oss << " id=\"" << this->getId() << "\" ";
806      oss << SuperClassAttribute::toString() << ">" << std::endl;
807      if (this->getVirtualFieldGroup() != NULL)
808         oss << *this->getVirtualFieldGroup() << std::endl;
809      oss << "</" << CFile::GetName() << " >";
810      return (oss.str());
811   }
812   CATCH
813
814   //----------------------------------------------------------------
815
816   /*!
817   \brief Find all inheritace among objects in a file.
818   \param [in] apply (true) write attributes of parent into ones of child if they are empty
819                     (false) write attributes of parent into a new container of child
820   \param [in] parent
821   */
822   void CFile::solveDescInheritance(bool apply, const CAttributeMap * const parent)
823   TRY
824   {
825      SuperClassAttribute::setAttributes(parent,apply);
826      this->getVirtualFieldGroup()->solveDescInheritance(apply, NULL);
827      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
828   }
829   CATCH_DUMP_ATTR
830
831   //----------------------------------------------------------------
832
833   void CFile::checkGridOfEnabledFields()
834   TRY
835   { 
836     int size = this->enabledFields.size();
837     for (int i = 0; i < size; ++i)
838     {
839       this->enabledFields[i]->checkGridOfEnabledFields();
840     }
841   }
842   CATCH_DUMP_ATTR
843
844   void CFile::sendGridComponentOfEnabledFields()
845   TRY
846   { 
847     int size = this->enabledFields.size();
848     for (int i = 0; i < size; ++i)
849     {
850       this->enabledFields[i]->sendGridComponentOfEnabledFields();
851     }
852   }
853   CATCH_DUMP_ATTR
854
855   /*!
856   \brief Sorting domains with the same name (= describing the same mesh) in the decreasing order of nvertex for UGRID files.
857   This insures that the domain with the highest nvertex is written first and thus all known mesh connectivity is generated at once by this domain.
858   */
859   void CFile::sortEnabledFieldsForUgrid()
860   TRY
861   {
862     int size = this->enabledFields.size();
863     std::vector<int> domainNvertices;
864     std::vector<StdString> domainNames;
865     std::map<string, tuple<set<CDomain*>,set<CDomain*>,set<CDomain*>>> registeredDomains ;
866
867     for (int i = 0; i < size; ++i)
868     {
869       std::vector<CDomain*> domain = this->enabledFields[i]->getRelGrid()->getDomains();
870       if (domain.size() != 1)
871       {
872         ERROR("void CFile::sortEnabledFieldsForUgrid()",
873               "A domain, and only one, should be defined for grid "<< this->enabledFields[i]->getRelGrid()->getId() << ".");
874       }
875       StdString domainName = domain[0]->getDomainOutputName();
876       int nvertex;
877       if (domain[0]->nvertex.isEmpty())
878       {
879         ERROR("void CFile::sortEnabledFieldsForUgrid()",
880               "Attributes nvertex must be defined for domain "<< domain[0]->getDomainOutputName() << ".");
881       }
882       else
883         nvertex = domain[0]->nvertex;
884
885       for (int j = 0; j < i; ++j)
886       {
887         if (domainName == domainNames[j] && nvertex > domainNvertices[j])
888         {
889           CField* tmpSwap = this->enabledFields[j];
890           this->enabledFields[j] = this->enabledFields[i];
891           this->enabledFields[i] = tmpSwap;
892           domainNames.push_back(domainNames[j]);
893           domainNames[j] = domainName;
894           domainNvertices.push_back(domainNvertices[j]);
895           domainNvertices[j] = nvertex;
896         }
897         else
898         {
899           domainNames.push_back(domainName);
900           domainNvertices.push_back(nvertex);
901         }
902       }
903       if (i==0)
904       {
905         domainNames.push_back(domainName);
906         domainNvertices.push_back(nvertex);
907       }
908
909       if (nvertex==1)  std::get<0>(registeredDomains[domainName]).insert(domain[0]) ;
910       else if (nvertex==2) std::get<1>(registeredDomains[domainName]).insert(domain[0]) ;
911       else  std::get<2>(registeredDomains[domainName]).insert(domain[0]) ;
912     }
913
914     for(auto& it:registeredDomains)
915     {
916       list<CDomain*> domains ;
917       string domainName=it.first ;
918
919       for(auto& domain : std::get<0>(it.second) ) domains.push_back(domain) ;
920       for(auto& domain : std::get<1>(it.second) ) domains.push_back(domain) ;
921       for(auto& domain : std::get<2>(it.second) ) domains.push_back(domain) ;
922       
923       // for each component of a given mesh (i.e. domains with same name but different number of vertices)
924       // associate the UGRID mesh in increasing order
925       for(auto& domain : domains )
926       {
927         //domain-> computeWrittenIndex();
928         //CArray<int, 1>& indexToWrite = domain->localIndexToWriteOnServer;
929         CArray<int, 1> indexToWrite = domain->getLocalView(CElementView::WORKFLOW)->getIndex();
930         int nbWritten = indexToWrite.numElements();
931
932         CArray<double,1> writtenLat, writtenLon;
933         CArray<double,2> writtenBndsLat, writtenBndsLon;
934
935         writtenLat.resize(nbWritten);
936         writtenLon.resize(nbWritten);
937         for (int idx = 0; idx < nbWritten; ++idx)
938         {
939           writtenLat(idx) = domain->latvalue(indexToWrite(idx));
940           writtenLon(idx) = domain->lonvalue(indexToWrite(idx));
941         }
942   
943         int nvertex = domain->nvertex, idx;
944        if (nvertex>1)
945         {
946           writtenBndsLat.resize(nvertex, nbWritten);
947           writtenBndsLon.resize(nvertex, nbWritten);
948           CArray<double,2>& boundslat = domain->bounds_latvalue;
949           CArray<double,2>& boundslon = domain->bounds_lonvalue;
950           for (idx = 0; idx < nbWritten; ++idx)
951             for (int nv = 0; nv < nvertex; ++nv)
952             {
953                writtenBndsLat(nv, idx) = boundslat(nv, int(indexToWrite(idx)));
954                writtenBndsLon(nv, idx) = boundslon(nv, int(indexToWrite(idx)));
955             }
956         }
957         domain->assignMesh(domainName, domain->nvertex);
958         //CContextServer* server=CContext::getCurrent()->server ;
959         //domain->mesh->createMeshEpsilon(server->intraComm, writtenLon, writtenLat, writtenBndsLon, writtenBndsLat);
960         MPI_Comm intraComm =CContext::getCurrent()->getIntraComm() ;
961         domain->mesh->createMeshEpsilon(intraComm, writtenLon, writtenLat, writtenBndsLon, writtenBndsLat);
962       }
963
964     }
965   }
966   CATCH_DUMP_ATTR
967
968   void CFile::sendGridOfEnabledFields()
969   TRY
970   { 
971     int size = this->enabledFields.size();
972     for (int i = 0; i < size; ++i)
973     {
974       this->enabledFields[i]->sendGridOfEnabledFields();
975     }
976   }
977   CATCH_DUMP_ATTR
978
979
980   /*!
981    * Post-process the filter graph for each active field.
982    */
983   void CFile::postProcessFilterGraph()
984   TRY
985   {
986     int size = this->enabledFields.size();
987     for (int i = 0; i < size; ++i)
988     {
989       this->enabledFields[i]->checkIfMustAutoTrigger();
990     }
991   }
992   CATCH_DUMP_ATTR
993
994   /*!
995     Prefetching the data for enabled fields read from file.
996   */
997   void CFile::prefetchEnabledReadModeFields(void)
998   TRY
999   {
1000     if (mode.isEmpty() || mode.getValue() != mode_attr::read)
1001       return;
1002
1003     int size = this->enabledFields.size();
1004     for (int i = 0; i < size; ++i)
1005       this->enabledFields[i]->sendReadDataRequest(CContext::getCurrent()->getCalendar()->getCurrentDate());
1006   }
1007   CATCH_DUMP_ATTR
1008
1009   /*!
1010     Do all pre timestep operations for enabled fields in read mode:
1011      - Check that the data excepted from server has been received
1012      - Check if some filters must auto-trigger
1013   */
1014   void CFile::doPreTimestepOperationsForEnabledReadModeFields(void)
1015   TRY
1016   {
1017     if (mode.isEmpty() || mode.getValue() != mode_attr::read)
1018       return;
1019
1020     int size = this->enabledFields.size();
1021     for (int i = 0; i < size; ++i)
1022     {
1023       this->enabledFields[i]->checkForLateDataFromServer();
1024       this->enabledFields[i]->autoTriggerIfNeeded();
1025     }
1026   }
1027   CATCH_DUMP_ATTR
1028
1029   /*!
1030     Do all post timestep operations for enabled fields in read mode:
1031      - Prefetch the data read from file when needed
1032   */
1033   void CFile::doPostTimestepOperationsForEnabledReadModeFields(void)
1034   TRY
1035   {
1036     if (mode.isEmpty() || mode.getValue() != mode_attr::read)
1037       return;
1038
1039     int size = this->enabledFields.size();
1040     for (int i = 0; i < size; ++i)
1041     {
1042       this->enabledFields[i]->sendReadDataRequestIfNeeded();
1043     }
1044   }
1045   CATCH_DUMP_ATTR
1046
1047   void CFile::solveFieldRefInheritance(bool apply)
1048   TRY
1049   {
1050      // Rsolution des hritages par rfrence de chacun des champs contenus dans le fichier.
1051      std::vector<CField*> allF = this->getAllFields();
1052      for (unsigned int i = 0; i < allF.size(); i++)
1053         allF[i]->solveRefInheritance(apply);
1054   }
1055   CATCH_DUMP_ATTR
1056
1057   //----------------------------------------------------------------
1058
1059   /*!
1060   \brief Add a field into file.
1061      A field is added into file and it will be written out if the file is enabled and
1062   level of this field is smaller than level_output. A new field won't be created if one
1063   with id has already existed
1064   \param [in] id String identity of new field
1065   \return Pointer to added (or already existed) field
1066   */
1067   CField* CFile::addField(const string& id)
1068   TRY
1069   {
1070     return vFieldGroup->createChild(id);
1071   }
1072   CATCH_DUMP_ATTR
1073
1074   /*!
1075   \brief Add a field group into file.
1076      A field group is added into file and it will play a role as parents for fields.
1077   A new field group won't be created if one with id has already existed
1078   \param [in] id String identity of new field group
1079   \return Pointer to added (or already existed) field group
1080   */
1081   CFieldGroup* CFile::addFieldGroup(const string& id)
1082   TRY
1083   {
1084     return vFieldGroup->createChildGroup(id);
1085   }
1086   CATCH_DUMP_ATTR
1087
1088   /*!
1089   \brief Add a variable into file.
1090      A variable is added into file and if one with id has already existed, pointer to
1091   it will be returned.
1092      Variable as long as attributes are information container of file.
1093   However, whereas attributes are "fixed" information, variables provides a more flexible way to user
1094   to fill in (extra) information for a file.
1095   \param [in] id String identity of new variable
1096   \return Pointer to added (or already existed) variable
1097   */
1098   CVariable* CFile::addVariable(const string& id)
1099   TRY
1100   {
1101     return vVariableGroup->createChild(id);
1102   }
1103   CATCH_DUMP_ATTR
1104
1105   /*!
1106   \brief Add a variable group into file.
1107      A variable group is added into file and it will play a role as parents for variables.
1108   A new variable group won't be created if one with id has already existed
1109   \param [in] id String identity of new variable group
1110   \return Pointer to added (or already existed) variable group
1111   */
1112   CVariableGroup* CFile::addVariableGroup(const string& id)
1113   TRY
1114   {
1115     return vVariableGroup->createChildGroup(id);
1116   }
1117   CATCH_DUMP_ATTR
1118
1119   void CFile::getWriterServicesId(bool defaultUsingServer2_, const string& defaultPoolWriterId_, const string& defaultWriterId_, const string& defaultPoolGathererId_, const string& defaultGathererId_,
1120                                   bool& usingServer2, string& poolWriterId, string& writerId, string& poolGathererId, string& gathererId)
1121   {
1122     usingServer2 = defaultUsingServer2_ ;
1123     poolWriterId = defaultPoolWriterId_ ;
1124     writerId = defaultWriterId_ ;
1125     poolGathererId = defaultPoolGathererId_ ;
1126     gathererId = defaultGathererId_ ;
1127
1128     if (!using_server2.isEmpty()) usingServer2 = using_server2;
1129     if (!pool_writer.isEmpty()) poolWriterId = pool_writer ;
1130     if (!writer.isEmpty()) writerId = writer;
1131     if (!pool_gatherer.isEmpty()) poolGathererId = pool_gatherer;
1132     if (!gatherer.isEmpty()) gathererId = gatherer;
1133   }
1134
1135   void CFile::getReaderServicesId(const string& defaultPoolReaderId_, const string& defaultReaderId_, string& poolReaderId, string& readerId)
1136   {
1137     poolReaderId = defaultPoolReaderId_ ;
1138     readerId = defaultReaderId_ ;
1139   
1140     if (!pool_reader.isEmpty()) poolReaderId = pool_reader ;
1141     if (!reader.isEmpty()) readerId = reader;
1142   }
1143
1144   void CFile::setContextClient(const string& defaultPoolId, const string& defaultServiceId, int partitionId)
1145   TRY
1146   {
1147     CContext* context = CContext::getCurrent();
1148     vector<CContextClient*> clients = context->getContextClient(defaultPoolId, defaultServiceId) ;
1149     setContextClient(clients[partitionId]) ;
1150   }
1151   CATCH_DUMP_ATTR
1152
1153
1154   void CFile::setContextClient(CContextClient* newContextClient)
1155   TRY
1156   {
1157     client = newContextClient;
1158     size_t size = this->enabledFields.size();
1159     for (size_t i = 0; i < size; ++i)
1160     {
1161       this->enabledFields[i]->setContextClient(newContextClient);
1162     }
1163   }
1164   CATCH_DUMP_ATTR
1165
1166   CContextClient* CFile::getContextClient()
1167   TRY
1168   {
1169     return client;
1170   }
1171   CATCH_DUMP_ATTR
1172
1173   
1174   /*!
1175   \brief Send a message to create a field on server side
1176   \param[in] id String identity of field that will be created on server
1177   */
1178   void CFile::sendAddField(const string& id, CContextClient* client)
1179   TRY
1180   {
1181      sendAddItem(id, EVENT_ID_ADD_FIELD, client);
1182   }
1183   CATCH_DUMP_ATTR
1184
1185   /*!
1186   \brief Send a message to create a field group on server side
1187   \param[in] id String identity of field group that will be created on server
1188   */
1189   void CFile::sendAddFieldGroup(const string& id, CContextClient* client)
1190   TRY
1191   {
1192      sendAddItem(id, (int)EVENT_ID_ADD_FIELD_GROUP, client);
1193   }
1194   CATCH_DUMP_ATTR
1195
1196   /*!
1197   \brief Receive a message annoucing the creation of a field on server side
1198   \param[in] event Received event
1199   */
1200   void CFile::recvAddField(CEventServer& event)
1201   TRY
1202   {
1203
1204      CBufferIn* buffer = event.subEvents.begin()->buffer;
1205      string id;
1206      *buffer>>id;
1207      get(id)->recvAddField(*buffer);
1208   }
1209   CATCH
1210
1211   /*!
1212   \brief Receive a message annoucing the creation of a field on server side
1213   \param[in] buffer Buffer containing message
1214   */
1215   void CFile::recvAddField(CBufferIn& buffer)
1216   TRY
1217   {
1218      string id;
1219      buffer>>id;
1220      addField(id);
1221   }
1222   CATCH_DUMP_ATTR
1223
1224   /*!
1225   \brief Receive a message annoucing the creation of a field group on server side
1226   \param[in] event Received event
1227   */
1228   void CFile::recvAddFieldGroup(CEventServer& event)
1229   TRY
1230   {
1231
1232      CBufferIn* buffer = event.subEvents.begin()->buffer;
1233      string id;
1234      *buffer>>id;
1235      get(id)->recvAddFieldGroup(*buffer);
1236   }
1237   CATCH
1238
1239   /*!
1240   \brief Receive a message annoucing the creation of a field group on server side
1241   \param[in] buffer Buffer containing message
1242   */
1243   void CFile::recvAddFieldGroup(CBufferIn& buffer)
1244   TRY
1245   {
1246      string id;
1247      buffer>>id;
1248      addFieldGroup(id);
1249   }
1250   CATCH_DUMP_ATTR
1251
1252   /*!
1253   \brief Send messages to duplicate all variables on server side
1254      Because each variable has also its attributes. So first thing to do is replicate
1255   all these attributes on server side. Because variable can have a value, the second thing
1256   is to duplicate this value on server, too.
1257   */
1258   void CFile::sendAddAllVariables(CContextClient* client)
1259   TRY
1260   {
1261     std::vector<CVariable*> allVar = getAllVariables();
1262     std::vector<CVariable*>::const_iterator it = allVar.begin();
1263     std::vector<CVariable*>::const_iterator itE = allVar.end();
1264
1265     for (; it != itE; ++it)
1266     {
1267       this->sendAddVariable((*it)->getId(), client);
1268       (*it)->sendAllAttributesToServer(client);
1269       (*it)->sendValue(client);
1270     }
1271   }
1272   CATCH_DUMP_ATTR
1273
1274   /*!
1275   \brief Send a message to create a variable group on server side
1276   \param[in] id String identity of variable group that will be created on server
1277   \param [in] client client to which we will send this adding action
1278   */
1279   void CFile::sendAddVariableGroup(const string& id, CContextClient* client)
1280   TRY
1281   {
1282      sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE_GROUP, client);
1283   }
1284   CATCH_DUMP_ATTR
1285
1286   /*
1287     Send message to add a variable into a file within a certain client
1288     \param [in] id String identity of a variable
1289     \param [in] client client to which we will send this adding action
1290   */
1291   void CFile::sendAddVariable(const string& id, CContextClient* client)
1292   TRY
1293   {
1294      sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE, client);
1295   }
1296   CATCH_DUMP_ATTR
1297
1298   /*!
1299   \brief Receive a message annoucing the creation of a variable on server side
1300   \param[in] event Received event
1301   */
1302   void CFile::recvAddVariable(CEventServer& event)
1303   TRY
1304   {
1305      CBufferIn* buffer = event.subEvents.begin()->buffer;
1306      string id;
1307      *buffer>>id;
1308      get(id)->recvAddVariable(*buffer);
1309   }
1310   CATCH
1311
1312   /*!
1313   \brief Receive a message annoucing the creation of a variable on server side
1314   \param[in] buffer Buffer containing message
1315   */
1316   void CFile::recvAddVariable(CBufferIn& buffer)
1317   TRY
1318   {
1319      string id;
1320      buffer>>id;
1321      addVariable(id);
1322   }
1323   CATCH_DUMP_ATTR
1324
1325   /*!
1326   \brief Receive a message annoucing the creation of a variable group on server side
1327   \param[in] event Received event
1328   */
1329   void CFile::recvAddVariableGroup(CEventServer& event)
1330   TRY
1331   {
1332
1333      CBufferIn* buffer = event.subEvents.begin()->buffer;
1334      string id;
1335      *buffer>>id;
1336      get(id)->recvAddVariableGroup(*buffer);
1337   }
1338   CATCH
1339
1340   /*!
1341   \brief Receive a message annoucing the creation of a variable group on server side
1342   \param[in] buffer Buffer containing message
1343   */
1344   void CFile::recvAddVariableGroup(CBufferIn& buffer)
1345   TRY
1346   {
1347      string id;
1348      buffer>>id;
1349      addVariableGroup(id);
1350   }
1351   CATCH_DUMP_ATTR
1352
1353   /*!
1354     \brief Sending all active (enabled) fields from client to server.
1355   Each field is identified uniquely by its string identity. Not only should we
1356   send the id to server but also we need to send ids of reference domain and reference axis.
1357   With these two id, it's easier to make reference to grid where all data should be written.
1358   Remark: This function must be called AFTER all active (enabled) files have been created on the server side
1359   */
1360   void CFile::sendEnabledFields(CContextClient* client)
1361   TRY
1362   {
1363     size_t size = this->enabledFields.size();
1364     for (size_t i = 0; i < size; ++i)
1365     {
1366       CField* field = this->enabledFields[i];
1367       this->sendAddField(field->getId(), client);
1368       field->checkTimeAttributes();
1369       field->sendAllAttributesToServer(client);
1370       field->sendAddAllVariables(client);
1371     }
1372   }
1373   CATCH_DUMP_ATTR
1374
1375
1376 
1377   /*!
1378    * Send file attribute, related variable and chield field tree to a given file server.
1379    * \param[in] client : the context client where to send file
1380    */
1381   void CFile::sendFileToFileServer(CContextClient* client)
1382   TRY
1383   {
1384     if (sendFileToFileServer_done_.count(client)!=0) return ;
1385     else sendFileToFileServer_done_.insert(client) ;
1386     
1387     StdString fileDefRoot("file_definition");
1388     CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot);
1389     cfgrpPtr->sendCreateChild(this->getId(), client);
1390     this->sendAllAttributesToServer(client);
1391     this->sendAddAllVariables(client);
1392     for(auto field : enabledFields) this->sendAddField(field->getId(), client);
1393   }
1394   CATCH_DUMP_ATTR
1395   /*!
1396   \brief Dispatch event received from client
1397      Whenever a message is received in buffer of server, it will be processed depending on
1398   its event type. A new event type should be added in the switch list to make sure
1399   it processed on server side.
1400   \param [in] event: Received message
1401   */
1402   bool CFile::dispatchEvent(CEventServer& event)
1403   TRY
1404   {
1405      if (SuperClass::dispatchEvent(event)) return true;
1406      else
1407      {
1408        switch(event.type)
1409        {
1410           case EVENT_ID_ADD_FIELD :
1411             recvAddField(event);
1412             return true;
1413             break;
1414
1415           case EVENT_ID_ADD_FIELD_GROUP :
1416             recvAddFieldGroup(event);
1417             return true;
1418             break;
1419
1420            case EVENT_ID_ADD_VARIABLE :
1421             recvAddVariable(event);
1422             return true;
1423             break;
1424
1425           case EVENT_ID_ADD_VARIABLE_GROUP :
1426             recvAddVariableGroup(event);
1427             return true;
1428             break;
1429           default :
1430              ERROR("bool CFile::dispatchEvent(CEventServer& event)", << "Unknown Event");
1431           return false;
1432        }
1433      }
1434   }
1435   CATCH
1436
1437   ///--------------------------------------------------------------
1438   /*!
1439   */
1440   StdString CFile::dumpClassAttributes(void)
1441   {
1442     StdString str;
1443     CContext* context = CContext::getCurrent();
1444     str.append("context=\"");
1445     str.append(context->getId());
1446     str.append("\"");
1447     str.append(" enabled fields=\"");
1448     int size = this->enabledFields.size();
1449     for (int i = 0; i < size; ++i)
1450     {
1451       str.append(this->enabledFields[i]->getId());
1452       str.append(" ");
1453     }
1454     str.append("\"");
1455     return str;
1456   }
1457
1458   ///---------------------------------------------------------------
1459
1460} // namespace xios
Note: See TracBrowser for help on using the repository browser.