source: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/file.cpp @ 2022

Last change on this file since 2022 was 2002, checked in by ymipsl, 3 years ago

Some cleaning of old transformation dead code

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