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

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

Intermeadiate version for merging with new server functionalities.

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
  • Property svn:executable set to *
File size: 48.7 KB
Line 
1#include "field.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6
7#include "node_type.hpp"
8#include "calendar_util.hpp"
9#include "message.hpp"
10#include "xios_spl.hpp"
11#include "type.hpp"
12#include "timer.hpp"
13#include "context_client.hpp"
14#include "context_server.hpp"
15#include <set>
16#include "garbage_collector.hpp"
17#include "source_filter.hpp"
18#include "store_filter.hpp"
19#include "file_writer_filter.hpp"
20#include "pass_through_filter.hpp"
21#include "filter_expr_node.hpp"
22#include "lex_parser.hpp"
23#include "temporal_filter.hpp"
24#include "spatial_transform_filter.hpp"
25
26namespace xios{
27
28   /// ////////////////////// Définitions ////////////////////// ///
29
30   CField::CField(void)
31      : CObjectTemplate<CField>(), CFieldAttributes()
32      , grid(), file()
33      , written(false)
34      , nstep(0), nstepMax(0)
35      , hasOutputFile(false)
36      , domAxisScalarIds_(vector<StdString>(3,"")), areAllReferenceSolved(false), isReferenceSolved(false)
37      , useCompressedOutput(false)
38      , wasDataAlreadyReceivedFromServer(false)
39   { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); }
40
41   CField::CField(const StdString& id)
42      : CObjectTemplate<CField>(id), CFieldAttributes()
43      , grid(), file()
44      , written(false)
45      , nstep(0), nstepMax(0)
46      , hasOutputFile(false)
47      , domAxisScalarIds_(vector<StdString>(3,"")), areAllReferenceSolved(false), isReferenceSolved(false)
48      , useCompressedOutput(false)
49      , wasDataAlreadyReceivedFromServer(false)
50   { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); }
51
52   CField::~CField(void)
53   {}
54
55  //----------------------------------------------------------------
56
57   void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup)
58   {
59      this->vVariableGroup = newVVariableGroup;
60   }
61
62   CVariableGroup* CField::getVirtualVariableGroup(void) const
63   {
64      return this->vVariableGroup;
65   }
66
67   std::vector<CVariable*> CField::getAllVariables(void) const
68   {
69      return this->vVariableGroup->getAllChildren();
70   }
71
72   void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent)
73   {
74      SuperClassAttribute::setAttributes(parent, apply);
75      this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL);
76   }
77
78  //----------------------------------------------------------------
79
80  bool CField::dispatchEvent(CEventServer& event)
81  {
82    if (SuperClass::dispatchEvent(event)) return true;
83    else
84    {
85      switch(event.type)
86      {
87        case EVENT_ID_UPDATE_DATA :
88          recvUpdateData(event);
89          return true;
90          break;
91
92        case EVENT_ID_READ_DATA :
93          recvReadDataRequest(event);
94          return true;
95          break;
96
97        case EVENT_ID_READ_DATA_READY :
98          recvReadDataReady(event);
99          return true;
100          break;
101
102        case EVENT_ID_ADD_VARIABLE :
103          recvAddVariable(event);
104          return true;
105          break;
106
107        case EVENT_ID_ADD_VARIABLE_GROUP :
108          recvAddVariableGroup(event);
109          return true;
110          break;
111
112        default :
113          ERROR("bool CField::dispatchEvent(CEventServer& event)", << "Unknown Event");
114          return false;
115      }
116    }
117  }
118
119  void CField::sendUpdateData(const CArray<double,1>& data)
120  {
121    CTimer::get("XIOS Send Data").resume();
122
123    CContext* context = CContext::getCurrent();
124//    CContextClient* client = context->client;
125    int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
126    for (int i = 0; i < nbSrvPools; ++i)
127    {
128      CContextClient* client = (!context->hasServer) ? context->client : context->clientPrimServer[i];
129
130      CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
131
132      map<int, CArray<int,1> >::iterator it;
133      list<CMessage> list_msg;
134      list<CArray<double,1> > list_data;
135
136      if (!grid->doGridHaveDataDistributed())
137      {
138         if (client->isServerLeader())
139         {
140            for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
141            {
142              int rank = it->first;
143              CArray<int,1>& index = it->second;
144
145              list_msg.push_back(CMessage());
146              list_data.push_back(CArray<double,1>(index.numElements()));
147
148              CArray<double,1>& data_tmp = list_data.back();
149              for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
150
151              list_msg.back() << getId() << data_tmp;
152              event.push(rank, 1, list_msg.back());
153            }
154            client->sendEvent(event);
155         }
156         else client->sendEvent(event);
157      }
158      else
159      {
160        for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
161        {
162          int rank = it->first;
163          CArray<int,1>& index = it->second;
164
165          list_msg.push_back(CMessage());
166          list_data.push_back(CArray<double,1>(index.numElements()));
167
168          CArray<double,1>& data_tmp = list_data.back();
169          for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
170
171          list_msg.back() << getId() << data_tmp;
172          event.push(rank, grid->nbSenders[rank], list_msg.back());
173        }
174        client->sendEvent(event);
175      }
176    }
177
178    CTimer::get("XIOS Send Data").suspend();
179  }
180
181  void CField::sendUpdateData(const CArray<double,1>& data, CContextClient* client)
182  {
183    CTimer::get("XIOS Send Data").resume();
184
185    CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
186
187    map<int, CArray<int,1> >::iterator it;
188    list<CMessage> list_msg;
189    list<CArray<double,1> > list_data;
190
191    if (!grid->doGridHaveDataDistributed())
192    {
193       if (client->isServerLeader())
194       {
195          for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
196          {
197            int rank = it->first;
198            CArray<int,1>& index = it->second;
199
200            list_msg.push_back(CMessage());
201            list_data.push_back(CArray<double,1>(index.numElements()));
202
203            CArray<double,1>& data_tmp = list_data.back();
204            for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
205
206            list_msg.back() << getId() << data_tmp;
207            event.push(rank, 1, list_msg.back());
208          }
209          client->sendEvent(event);
210       }
211       else client->sendEvent(event);
212    }
213    else
214    {
215      for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
216      {
217        int rank = it->first;
218        CArray<int,1>& index = it->second;
219
220        list_msg.push_back(CMessage());
221        list_data.push_back(CArray<double,1>(index.numElements()));
222
223        CArray<double,1>& data_tmp = list_data.back();
224        for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
225
226        list_msg.back() << getId() << data_tmp;
227        event.push(rank, grid->nbSenders[rank], list_msg.back());
228      }
229      client->sendEvent(event);
230    }
231    CTimer::get("XIOS Send Data").suspend();
232  }
233
234  void CField::recvUpdateData(CEventServer& event)
235  {
236    vector<int> ranks;
237    vector<CBufferIn*> buffers;
238
239    list<CEventServer::SSubEvent>::iterator it;
240    string fieldId;
241
242    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
243    {
244      int rank = it->rank;
245      CBufferIn* buffer = it->buffer;
246      *buffer >> fieldId;
247      ranks.push_back(rank);
248      buffers.push_back(buffer);
249    }
250    get(fieldId)->recvUpdateData(ranks,buffers);
251  }
252
253  void  CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)
254  {
255    CContext* context = CContext::getCurrent();
256
257    if (data_srv.empty())
258    {
259      for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
260      {
261        int rank = it->first;
262        data_srv.insert(std::make_pair(rank, CArray<double,1>(it->second.numElements())));
263        foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(data_srv[rank]))));
264      }
265    }
266
267    const CDate& currDate = context->getCalendar()->getCurrentDate();
268    const CDate opeDate      = last_operation_srv +freq_op + freq_operation_srv - freq_op;
269    const CDate writeDate    = last_Write_srv     + freq_write_srv;
270
271    if (opeDate <= currDate)
272    {
273      for (int n = 0; n < ranks.size(); n++)
274      {
275        CArray<double,1> data_tmp;
276        *buffers[n] >> data_tmp;
277        (*foperation_srv[ranks[n]])(data_tmp);
278      }
279      last_operation_srv = currDate;
280    }
281
282    if (writeDate < (currDate + freq_operation_srv))
283    {
284      for (int n = 0; n < ranks.size(); n++)
285      {
286        this->foperation_srv[ranks[n]]->final();
287      }
288
289      last_Write_srv = writeDate;
290    }
291
292    if (context->hasClient && context->hasServer)
293    {
294      size_t writtenSize;
295//      if (field->getUseCompressedOutput())
296//        writtenSize = grid->getNumberWrittenIndexes();
297//      else
298        writtenSize = grid->getWrittenDataSize();
299
300      CArray<double,1> fieldData(writtenSize);
301//      if (!field->default_value.isEmpty()) fieldData = field->default_value;
302
303//      if (field->getUseCompressedOutput())
304//        field->outputCompressedField(fieldData);
305//      else
306        this->outputField(fieldData);
307//        sendUpdateData(fieldData);
308        // Redirecting data to the correct secondary server
309        int fileIdx = std::find(context->enabledFiles.begin(), context->enabledFiles.end(), this->file) - context->enabledFiles.begin();
310        int srvId = fileIdx % context->clientPrimServer.size();
311        sendUpdateData(fieldData, context->clientPrimServer[srvId]);
312    }
313    if (!context->hasClient && context->hasServer)
314    {
315//      size_t writtenSize;
316//      if (this->getUseCompressedOutput())
317//        writtenSize = grid->getNumberWrittenIndexes();
318//      else
319//        writtenSize = grid->getWrittenDataSize();
320//
321//      CArray<double,1> fieldData(writtenSize);
322
323//      if (this->getUseCompressedOutput())
324//        this->outputCompressedField(fieldData);
325//      else
326//        this->outputField(fieldData);
327      writeField();
328    }
329
330    lastlast_Write_srv = last_Write_srv;
331
332  }
333
334  void CField::writeField(void)
335  {
336    if (!getRelFile()->allDomainEmpty)
337    {
338      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
339      {
340        getRelFile()->checkFile();
341        this->incrementNStep();
342        getRelFile()->getDataOutput()->writeFieldData(CField::get(this));
343      }
344    }
345  }
346
347  void CField::sendReadDataRequest(const CDate& tsDataRequested)
348  {
349    CContext* context = CContext::getCurrent();
350    CContextClient* client = context->client;
351
352    lastDataRequestedFromServer = tsDataRequested;
353
354    CEventClient event(getType(), EVENT_ID_READ_DATA);
355    if (client->isServerLeader())
356    {
357      CMessage msg;
358      msg << getId();
359      const std::list<int>& ranks = client->getRanksServerLeader();
360      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
361        event.push(*itRank, 1, msg);
362      client->sendEvent(event);
363    }
364    else client->sendEvent(event);
365  }
366
367  /*!
368  Send request new data read from file if need be, that is the current data is out-of-date.
369  \return true if and only if some data was requested
370  */
371  bool CField::sendReadDataRequestIfNeeded(void)
372  {
373    const CDate& currentDate = CContext::getCurrent()->getCalendar()->getCurrentDate();
374
375    bool dataRequested = false;
376    while (currentDate >= lastDataRequestedFromServer)
377    {
378      info(20) << "currentDate : " << currentDate << endl ;
379      info(20) << "lastDataRequestedFromServer : " << lastDataRequestedFromServer << endl ;
380      info(20) << "file->output_freq.getValue() : " << file->output_freq.getValue() << endl ;
381      info(20) << "lastDataRequestedFromServer + file->output_freq.getValue() : " << lastDataRequestedFromServer + file->output_freq << endl ;
382
383      sendReadDataRequest(lastDataRequestedFromServer + file->output_freq);
384
385      dataRequested = true;
386    }
387    return dataRequested;
388  }
389
390  void CField::recvReadDataRequest(CEventServer& event)
391  {
392    CBufferIn* buffer = event.subEvents.begin()->buffer;
393    StdString fieldId;
394    *buffer >> fieldId;
395    get(fieldId)->recvReadDataRequest();
396  }
397
398  void CField::recvReadDataRequest(void)
399  {
400    CContext* context = CContext::getCurrent();
401    CContextClient* client = context->client;
402
403    CEventClient event(getType(), EVENT_ID_READ_DATA_READY);
404    std::list<CMessage> msgs;
405
406    bool hasData = readField();
407
408    map<int, CArray<double,1> >::iterator it;
409//    for (it = data_srv.begin(); it != data_srv.end(); it++)
410//    {
411//      msgs.push_back(CMessage());
412//      CMessage& msg = msgs.back();
413//      msg << getId();
414//      if (hasData)
415//        msg << getNStep() - 1 << it->second;
416//      else
417//        msg << int(-1);
418//      event.push(it->first, grid->nbSenders[it->first], msg);
419//    }
420//    client->sendEvent(event);
421    if (!grid->doGridHaveDataDistributed())
422    {
423       if (client->isServerLeader())
424       {
425          if (!data_srv.empty())
426          {
427            it = data_srv.begin();
428            const std::list<int>& ranks = client->getRanksServerLeader();
429            for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
430            {
431              msgs.push_back(CMessage());
432              CMessage& msg = msgs.back();
433              msg << getId();
434              if (hasData)
435                msg << getNStep() - 1 << it->second;
436              else
437                msg << int(-1);
438              event.push(*itRank, 1, msg);
439            }
440          }
441          client->sendEvent(event);
442       }
443       else
444       {
445          // if (!data_srv.empty())
446          // {
447          //   it = data_srv.begin();
448          //   const std::list<int>& ranks = client->getRanksServerNotLeader();
449          //   for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
450          //   {
451          //     msgs.push_back(CMessage());
452          //     CMessage& msg = msgs.back();
453          //     msg << getId();
454          //     if (hasData)
455          //       msg << getNStep() - 1 << it->second;
456          //     else
457          //       msg << int(-1);
458          //     event.push(*itRank, 1, msg);
459          //   }
460          // }
461          client->sendEvent(event);
462       }
463    }
464    else
465    {
466      for (it = data_srv.begin(); it != data_srv.end(); it++)
467      {
468        msgs.push_back(CMessage());
469        CMessage& msg = msgs.back();
470        msg << getId();
471        if (hasData)
472          msg << getNStep() - 1 << it->second;
473        else
474          msg << int(-1);
475        event.push(it->first, grid->nbSenders[it->first], msg);
476      }
477      client->sendEvent(event);
478    }
479  }
480
481  bool CField::readField(void)
482  {
483    if (!getRelFile()->allDomainEmpty)
484    {
485      if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)
486      {
487        if (data_srv.empty())
488        {
489          for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
490            data_srv.insert(std::make_pair(it->first, CArray<double,1>(it->second.numElements())));
491        }
492
493        getRelFile()->checkFile();
494        if (!nstepMax)
495        {
496          nstepMax = getRelFile()->getDataInput()->getFieldNbRecords(CField::get(this));
497        }
498
499        this->incrementNStep();
500
501
502
503        if (getNStep() > nstepMax && (getRelFile()->cyclic.isEmpty() || !getRelFile()->cyclic) )
504          return false;
505
506        getRelFile()->getDataInput()->readFieldData(CField::get(this));
507      }
508    }
509
510    return true;
511  }
512
513  void CField::recvReadDataReady(CEventServer& event)
514  {
515    string fieldId;
516    vector<int> ranks;
517    vector<CBufferIn*> buffers;
518
519    list<CEventServer::SSubEvent>::iterator it;
520    for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it)
521    {
522      ranks.push_back(it->rank);
523      CBufferIn* buffer = it->buffer;
524      *buffer >> fieldId;
525      buffers.push_back(buffer);
526    }
527    get(fieldId)->recvReadDataReady(ranks, buffers);
528  }
529
530  void CField::recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers)
531  {
532    CContext* context = CContext::getCurrent();
533    int record;
534    std::map<int, CArray<double,1> > data;
535
536    bool isEOF = false;
537
538    for (int i = 0; i < ranks.size(); i++)
539    {
540      int rank = ranks[i];
541      *buffers[i] >> record;
542      isEOF = (record == int(-1));
543
544      if (!isEOF)
545        *buffers[i] >> data[rank];
546      else
547        break;
548    }
549
550    if (wasDataAlreadyReceivedFromServer)
551      lastDataReceivedFromServer = lastDataReceivedFromServer + file->output_freq;
552    else
553    {
554      lastDataReceivedFromServer = context->getCalendar()->getInitDate();
555      wasDataAlreadyReceivedFromServer = true;
556    }
557
558    if (isEOF)
559      serverSourceFilter->signalEndOfStream(lastDataReceivedFromServer);
560    else
561      serverSourceFilter->streamDataFromServer(lastDataReceivedFromServer, data);
562  }
563
564   //----------------------------------------------------------------
565
566   void CField::setRelFile(CFile* _file)
567   {
568      this->file = _file;
569      hasOutputFile = true;
570   }
571
572   //----------------------------------------------------------------
573
574   StdString CField::GetName(void)    { return StdString("field"); }
575   StdString CField::GetDefName(void) { return CField::GetName(); }
576   ENodeType CField::GetType(void)    { return eField; }
577
578   //----------------------------------------------------------------
579
580   CGrid* CField::getRelGrid(void) const
581   {
582      return this->grid;
583   }
584
585   //----------------------------------------------------------------
586
587   CFile* CField::getRelFile(void) const
588   {
589      return this->file;
590   }
591
592   int CField::getNStep(void) const
593   {
594      return this->nstep;
595   }
596
597   func::CFunctor::ETimeType CField::getOperationTimeType() const
598   {
599     return operationTimeType;
600   }
601
602   //----------------------------------------------------------------
603
604   void CField::incrementNStep(void)
605   {
606      this->nstep++;
607   }
608
609   void CField::resetNStep(int nstep /*= 0*/)
610   {
611      this->nstep = nstep;
612   }
613
614   void CField::resetNStepMax(void)
615   {
616      this->nstepMax = 0;
617   }
618
619   //----------------------------------------------------------------
620
621   bool CField::isActive(void) const
622   {
623      return (instantDataFilter != NULL);
624   }
625
626   //----------------------------------------------------------------
627
628   bool CField::wasWritten() const
629   {
630     return written;
631   }
632
633   void CField::setWritten()
634   {
635     written = true;
636   }
637
638   //----------------------------------------------------------------
639
640   bool CField::getUseCompressedOutput() const
641   {
642     return useCompressedOutput;
643   }
644
645   void CField::setUseCompressedOutput()
646   {
647     useCompressedOutput = true;
648   }
649
650   //----------------------------------------------------------------
651
652   boost::shared_ptr<COutputPin> CField::getInstantDataFilter()
653   {
654     return instantDataFilter;
655   }
656
657   //----------------------------------------------------------------
658
659   void CField::solveOnlyReferenceEnabledField(bool doSending2Server)
660   {
661     CContext* context = CContext::getCurrent();
662     if (!isReferenceSolved)
663     {
664        isReferenceSolved = true;
665
666        if (context->hasClient && !context->hasServer)
667//        if (context->hasClient)
668        {
669          solveRefInheritance(true);
670          if (hasDirectFieldReference()) getDirectFieldReference()->solveOnlyReferenceEnabledField(false);
671        }
672//        else if (context->hasServer)
673        if (context->hasServer)
674          solveServerOperation();
675
676        solveGridReference();
677
678        if (context->hasClient && !context->hasServer)
679//       if (context->hasClient)
680       {
681         solveGenerateGrid();
682         buildGridTransformationGraph();
683       }
684     }
685   }
686
687   /*!
688     Build up graph of grids which plays role of destination and source in grid transformation
689     This function should be called before \func solveGridReference()
690   */
691   void CField::buildGridTransformationGraph()
692   {
693     CContext* context = CContext::getCurrent();
694     if (context->hasClient && !context->hasServer)
695//     if (context->hasClient)
696     {
697       if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid)
698       {
699         grid->addTransGridSource(getDirectFieldReference()->grid);
700       }
701     }
702   }
703
704   /*!
705     Generate a new grid destination if there are more than one grid source pointing to a same grid destination
706   */
707   void CField::generateNewTransformationGridDest()
708   {
709     CContext* context = CContext::getCurrent();
710     if (context->hasClient && !context->hasServer)
711//     if (context->hasClient)
712     {
713       std::map<CGrid*,std::pair<bool,StdString> >& gridSrcMap = grid->getTransGridSource();
714       if (1 < gridSrcMap.size())
715       {
716         // Search for grid source
717         CGrid* gridSrc = grid;
718         CField* currField = this;
719         std::vector<CField*> hieraField;
720
721         while (currField->hasDirectFieldReference() && (gridSrc == grid))
722         {
723           hieraField.push_back(currField);
724           CField* tmp = currField->getDirectFieldReference();
725           currField = tmp;
726           gridSrc = currField->grid;
727         }
728
729         if (gridSrcMap.end() != gridSrcMap.find(gridSrc))
730         {
731           CGrid* gridTmp;
732           std::pair<bool,StdString> newGridDest = gridSrcMap[gridSrc];
733           if (newGridDest.first)
734           {
735             StdString newIdGridDest = newGridDest.second;
736             if (!CGrid::has(newIdGridDest))
737             {
738                ERROR("CGrid* CGrid::generateNewTransformationGridDest()",
739                  << " Something wrong happened! Grid whose id " << newIdGridDest
740                  << "should exist ");
741             }
742             gridTmp = CGrid::get(newIdGridDest);
743           }
744           else
745           {
746             StdString newIdGridDest = CGrid::generateId(gridSrc, grid);
747             gridTmp = CGrid::cloneGrid(newIdGridDest, grid);
748
749             (gridSrcMap[gridSrc]).first = true;
750             (gridSrcMap[gridSrc]).second = newIdGridDest;
751           }
752
753           // Update all descendants
754           for (std::vector<CField*>::iterator it = hieraField.begin(); it != hieraField.end(); ++it)
755           {
756             (*it)->grid = gridTmp;
757             (*it)->updateRef((*it)->grid);
758           }
759         }
760       }
761     }
762   }
763
764   void CField::updateRef(CGrid* grid)
765   {
766     if (!grid_ref.isEmpty()) grid_ref.setValue(grid->getId());
767     else
768     {
769       std::vector<CAxis*> axisTmp = grid->getAxis();
770       std::vector<CDomain*> domainTmp = grid->getDomains();
771       if ((1<axisTmp.size()) || (1<domainTmp.size()))
772         ERROR("void CField::updateRef(CGrid* grid)",
773           << "More than one domain or axis is available for domain_ref/axis_ref of field " << this->getId());
774
775       if ((!domain_ref.isEmpty()) && (domainTmp.empty()))
776         ERROR("void CField::updateRef(CGrid* grid)",
777           << "Incoherent between available domain and domain_ref of field " << this->getId());
778       if ((!axis_ref.isEmpty()) && (axisTmp.empty()))
779         ERROR("void CField::updateRef(CGrid* grid)",
780           << "Incoherent between available axis and axis_ref of field " << this->getId());
781
782       if (!domain_ref.isEmpty()) domain_ref.setValue(domainTmp[0]->getId());
783       if (!axis_ref.isEmpty()) axis_ref.setValue(axisTmp[0]->getId());
784     }
785   }
786
787   void CField::solveAllReferenceEnabledField(bool doSending2Server)
788   {
789     CContext* context = CContext::getCurrent();
790     solveOnlyReferenceEnabledField(doSending2Server);
791
792     if (!areAllReferenceSolved)
793     {
794        areAllReferenceSolved = true;
795
796//        if (context->hasClient)
797        if (context->hasClient && !context->hasServer)
798        {
799          solveRefInheritance(true);
800          if (hasDirectFieldReference()) getDirectFieldReference()->solveAllReferenceEnabledField(false);
801        }
802//        else if (context->hasServer)
803        if (context->hasServer && !context->hasClient)
804          solveServerOperation();
805
806        solveGridReference();
807     }
808
809     solveGridDomainAxisRef(doSending2Server);
810
811     if (context->hasClient && !context->hasServer)
812     {
813       solveTransformedGrid();
814     }
815
816     solveCheckMaskIndex(doSending2Server);
817   }
818
819   std::map<int, StdSize> CField::getGridAttributesBufferSize()
820   {
821     return grid->getAttributesBufferSize();
822   }
823
824   std::map<int, StdSize> CField::getGridDataBufferSize()
825   {
826     return grid->getDataBufferSize(getId());
827   }
828
829   //----------------------------------------------------------------
830
831   void CField::solveServerOperation(void)
832   {
833      CContext* context = CContext::getCurrent();
834
835      if (!context->hasServer || !hasOutputFile) return;
836
837      if (freq_op.isEmpty())
838        freq_op.setValue(TimeStep);
839
840      if (freq_offset.isEmpty())
841        freq_offset.setValue(NoneDu);
842
843      freq_operation_srv = file->output_freq.getValue();
844      freq_write_srv     = file->output_freq.getValue();
845
846      lastlast_Write_srv = context->getCalendar()->getInitDate();
847      last_Write_srv     = context->getCalendar()->getInitDate();
848      last_operation_srv = context->getCalendar()->getInitDate();
849
850      const CDuration toffset = freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep();
851      last_operation_srv     = last_operation_srv - toffset;
852
853      if (operation.isEmpty())
854        ERROR("void CField::solveServerOperation(void)",
855              << "An operation must be defined for field \"" << getId() << "\".");
856
857      boost::shared_ptr<func::CFunctor> functor;
858      CArray<double, 1> dummyData;
859
860#define DECLARE_FUNCTOR(MType, mtype) \
861      if (operation.getValue().compare(#mtype) == 0) \
862      { \
863        functor.reset(new func::C##MType(dummyData)); \
864      }
865
866#include "functor_type.conf"
867
868      if (!functor)
869        ERROR("void CField::solveServerOperation(void)",
870              << "\"" << operation << "\" is not a valid operation.");
871
872      operationTimeType = functor->timeType();
873   }
874
875   //----------------------------------------------------------------
876
877   /*!
878    * Constructs the graph filter for the field, enabling or not the data output.
879    * This method should not be called more than once with enableOutput equal to true.
880    *
881    * \param gc the garbage collector to use when building the filter graph
882    * \param enableOutput must be true when the field data is to be
883    *                     read by the client or/and written to a file
884    */
885   void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput)
886   {
887     if (!areAllReferenceSolved) solveAllReferenceEnabledField(false);
888
889     // Start by building a filter which can provide the field's instant data
890     if (!instantDataFilter)
891     {
892       // Check if we have an expression to parse
893       if (hasExpression())
894       {
895         boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0'));
896         boost::shared_ptr<COutputPin> filter = expr->reduce(gc, *this);
897
898         // Check if a spatial transformation is needed
899         if (!field_ref.isEmpty())
900         {
901           CGrid* gridRef = CField::get(field_ref)->grid;
902
903           if (grid && grid != gridRef && grid->hasTransform())
904           {
905             double defaultValue = !default_value.isEmpty() ? default_value : 0.0;
906             std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid, defaultValue);
907
908             filter->connectOutput(filters.first, 0);
909             filter = filters.second;
910           }
911         }
912
913         instantDataFilter = filter;
914       }
915       // Check if we have a reference on another field
916       else if (!field_ref.isEmpty())
917         instantDataFilter = getFieldReference(gc);
918       // Check if the data is to be read from a file
919       else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read)
920         instantDataFilter = serverSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid,
921                                                                                                     freq_offset.isEmpty() ? NoneDu : freq_offset,
922                                                                                                     true));
923       else // The data might be passed from the model
924         instantDataFilter = clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid));
925     }
926
927     // If the field data is to be read by the client or/and written to a file
928     if (enableOutput && !storeFilter && !fileWriterFilter)
929     {
930       if (!read_access.isEmpty() && read_access)
931       {
932         storeFilter = boost::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid));
933         instantDataFilter->connectOutput(storeFilter, 0);
934       }
935
936       if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write))
937       {
938         fileWriterFilter = boost::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this));
939         getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0);
940       }
941     }
942   }
943
944
945   /*!
946    * Returns the filter needed to handle the field reference.
947    * This method should only be called when building the filter graph corresponding to the field.
948    *
949    * \param gc the garbage collector to use
950    * \return the output pin corresponding to the field reference
951    */
952     boost::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc)
953     {
954       if (instantDataFilter || field_ref.isEmpty())
955         ERROR("COutputPin* CField::getFieldReference(CGarbageCollector& gc)",
956               "Impossible to get the field reference for a field which has already been parsed or which does not have a field_ref.");
957
958       CField* fieldRef = CField::get(field_ref);
959       fieldRef->buildFilterGraph(gc, false);
960
961       std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters;
962       // Check if a spatial transformation is needed
963       if (grid && grid != fieldRef->grid && grid->hasTransform())
964       {
965         double defaultValue = !default_value.isEmpty() ? default_value : 0.0;
966         filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid, grid, defaultValue);
967       }
968       else
969         filters.first = filters.second = boost::shared_ptr<CFilter>(new CPassThroughFilter(gc));
970
971       fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0);
972
973       return filters.second;
974     }
975
976   /*!
977    * Returns the filter needed to handle a self reference in the field's expression.
978    * If the needed filter does not exist, it is created, otherwise it is reused.
979    * This method should only be called when building the filter graph corresponding
980    * to the field's expression.
981    *
982    * \param gc the garbage collector to use
983    * \return the output pin corresponding to a self reference
984    */
985   boost::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc)
986   {
987     if (instantDataFilter || !hasExpression())
988       ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)",
989             "Impossible to add a self reference to a field which has already been parsed or which does not have an expression.");
990
991     if (!selfReferenceFilter)
992     {
993       if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read)
994       {
995         if (!serverSourceFilter)
996           serverSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid,
997                                                                                   freq_offset.isEmpty() ? NoneDu : freq_offset,
998                                                                                   true));
999         selfReferenceFilter = serverSourceFilter;
1000       }
1001       else if (!field_ref.isEmpty())
1002       {
1003         CField* fieldRef = CField::get(field_ref);
1004         fieldRef->buildFilterGraph(gc, false);
1005         selfReferenceFilter = fieldRef->getInstantDataFilter();
1006       }
1007       else
1008       {
1009         if (!clientSourceFilter)
1010           clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid));
1011
1012         selfReferenceFilter = clientSourceFilter;
1013       }
1014     }
1015
1016     return selfReferenceFilter;
1017   }
1018
1019   /*!
1020    * Returns the temporal filter corresponding to the field's temporal operation
1021    * for the specified operation frequency. The filter is created if it does not
1022    * exist, otherwise it is reused.
1023    *
1024    * \param gc the garbage collector to use
1025    * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed
1026    * \return the output pin corresponding to the requested temporal filter
1027    */
1028   boost::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)
1029   {
1030     std::map<CDuration, boost::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq);
1031
1032     if (it == temporalDataFilters.end())
1033     {
1034       if (operation.isEmpty())
1035         ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)",
1036               << "An operation must be defined for field \"" << getId() << "\".");
1037
1038       if (freq_op.isEmpty())
1039         freq_op.setValue(TimeStep);
1040       if (freq_offset.isEmpty())
1041         freq_offset.setValue(NoneDu);
1042
1043       const bool ignoreMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true);
1044
1045       boost::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation,
1046                                                                             CContext::getCurrent()->getCalendar()->getInitDate(),
1047                                                                             freq_op, freq_offset, outFreq,
1048                                                                             ignoreMissingValue, ignoreMissingValue ? default_value : 0.0));
1049       instantDataFilter->connectOutput(temporalFilter, 0);
1050
1051       it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first;
1052     }
1053
1054     return it->second;
1055   }
1056
1057   //----------------------------------------------------------------
1058/*
1059   void CField::fromBinary(StdIStream& is)
1060   {
1061      SuperClass::fromBinary(is);
1062#define CLEAR_ATT(name_)\
1063      SuperClassAttribute::operator[](#name_)->reset()
1064
1065         CLEAR_ATT(domain_ref);
1066         CLEAR_ATT(axis_ref);
1067#undef CLEAR_ATT
1068
1069   }
1070*/
1071   //----------------------------------------------------------------
1072
1073   void CField::solveGridReference(void)
1074   {
1075      if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty() && scalar_ref.isEmpty())
1076      {
1077        ERROR("CField::solveGridReference(void)",
1078              << "A grid must be defined for field '" << getFieldOutputName() << "' .");
1079      }
1080      else if (!grid_ref.isEmpty() && (!domain_ref.isEmpty() || !axis_ref.isEmpty() || !scalar_ref.isEmpty()))
1081      {
1082        ERROR("CField::solveGridReference(void)",
1083              << "Field '" << getFieldOutputName() << "' has both a grid and a domain/axis/scalar." << std::endl
1084              << "Please define either 'grid_ref' or 'domain_ref'/'axis_ref'/'scalar_ref'.");
1085      }
1086
1087      if (grid_ref.isEmpty())
1088      {
1089        std::vector<CDomain*> vecDom;
1090        std::vector<CAxis*> vecAxis;
1091        std::vector<CScalar*> vecScalar;
1092        std::vector<int> axisDomainOrderTmp;
1093       
1094        if (!domain_ref.isEmpty())
1095        {
1096          StdString tmp = domain_ref.getValue();
1097          if (CDomain::has(domain_ref))
1098          {
1099            vecDom.push_back(CDomain::get(domain_ref));
1100            axisDomainOrderTmp.push_back(2);
1101          }
1102          else
1103            ERROR("CField::solveGridReference(void)",
1104                  << "Invalid reference to domain '" << domain_ref.getValue() << "'.");
1105        }
1106
1107        if (!axis_ref.isEmpty())
1108        {
1109          if (CAxis::has(axis_ref))
1110          {
1111            vecAxis.push_back(CAxis::get(axis_ref));
1112            axisDomainOrderTmp.push_back(1);
1113          }
1114          else
1115            ERROR("CField::solveGridReference(void)",
1116                  << "Invalid reference to axis '" << axis_ref.getValue() << "'.");
1117        }
1118
1119        if (!scalar_ref.isEmpty())
1120        {
1121          if (CScalar::has(scalar_ref))
1122          {
1123            vecScalar.push_back(CScalar::get(scalar_ref));
1124            axisDomainOrderTmp.push_back(0);
1125          }
1126          else
1127            ERROR("CField::solveGridReference(void)",
1128                  << "Invalid reference to scalar '" << scalar_ref.getValue() << "'.");
1129        }
1130       
1131        CArray<int,1> axisDomainOrder(axisDomainOrderTmp.size());
1132        for (int idx = 0; idx < axisDomainOrderTmp.size(); ++idx)
1133        {
1134          axisDomainOrder(idx) = axisDomainOrderTmp[idx];
1135        }
1136
1137        // Warning: the gridId shouldn't be set as the grid_ref since it could be inherited
1138        StdString gridId = CGrid::generateId(vecDom, vecAxis, vecScalar,axisDomainOrder);
1139        if (CGrid::has(gridId))
1140          this->grid = CGrid::get(gridId);
1141        else
1142          this->grid = CGrid::createGrid(gridId, vecDom, vecAxis, vecScalar,axisDomainOrder);
1143      }
1144      else
1145      {
1146        if (CGrid::has(grid_ref))
1147          this->grid = CGrid::get(grid_ref);
1148        else
1149          ERROR("CField::solveGridReference(void)",
1150                << "Invalid reference to grid '" << grid_ref.getValue() << "'.");
1151      }
1152   }
1153
1154   void CField::solveGridDomainAxisRef(bool checkAtt)
1155   {
1156     grid->solveDomainAxisRef(checkAtt);
1157   }
1158
1159   void CField::solveCheckMaskIndex(bool doSendingIndex)
1160   {
1161     grid->checkMaskIndex(doSendingIndex);
1162   }
1163
1164   void CField::solveTransformedGrid()
1165   {
1166     if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid)
1167     {
1168       std::vector<CGrid*> grids;
1169       // Source grid
1170       grids.push_back(getDirectFieldReference()->grid);
1171       // Intermediate grids
1172       if (!grid_path.isEmpty())
1173       {
1174         std::string gridId;
1175         size_t start = 0, end;
1176
1177         do
1178         {
1179           end = grid_path.getValue().find(',', start);
1180           if (end != std::string::npos)
1181           {
1182             gridId = grid_path.getValue().substr(start, end - start);
1183             start = end + 1;
1184           }
1185           else
1186             gridId = grid_path.getValue().substr(start);
1187
1188           if (!CGrid::has(gridId))
1189             ERROR("void CField::solveTransformedGrid()",
1190                   << "Invalid grid_path, the grid '" << gridId << "' does not exist.");
1191
1192           grids.push_back(CGrid::get(gridId));
1193         }
1194         while (end != std::string::npos);
1195       }
1196       // Destination grid
1197       grids.push_back(grid);
1198
1199       for (size_t i = 0, count = grids.size() - 1; i < count; ++i)
1200       {
1201         CGrid *gridSrc  = grids[i];
1202         CGrid *gridDest = grids[i + 1];
1203         if (!gridDest->isTransformed())
1204           gridDest->transformGrid(gridSrc);
1205       }
1206     }
1207     else if (grid && grid->hasTransform() && !grid->isTransformed())
1208     {
1209       // Temporarily deactivate the self-transformation of grid
1210       //grid->transformGrid(grid);
1211     }
1212   }
1213
1214   void CField::solveGenerateGrid()
1215   {
1216     if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid)
1217       grid->completeGrid(getDirectFieldReference()->grid);
1218     else
1219       grid->completeGrid();
1220   }
1221
1222   void CField::solveGridDomainAxisBaseRef()
1223   {
1224     grid->solveDomainAxisRef(false);
1225     grid->solveDomainAxisBaseRef();
1226   }
1227
1228   ///-------------------------------------------------------------------
1229
1230   template <>
1231   void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)
1232   {
1233      if (this->group_ref.isEmpty()) return;
1234      StdString gref = this->group_ref.getValue();
1235
1236      if (!CFieldGroup::has(gref))
1237         ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)",
1238               << "[ gref = " << gref << "]"
1239               << " invalid group name !");
1240
1241      CFieldGroup* group = CFieldGroup::get(gref);
1242      CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this));
1243
1244      std::vector<CField*> allChildren  = group->getAllChildren();
1245      std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end();
1246
1247      for (; it != end; it++)
1248      {
1249         CField* child = *it;
1250         if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId());
1251
1252      }
1253   }
1254
1255   void CField::scaleFactorAddOffset(double scaleFactor, double addOffset)
1256   {
1257     map<int, CArray<double,1> >::iterator it;
1258     for (it = data_srv.begin(); it != data_srv.end(); it++) it->second = (it->second - addOffset) / scaleFactor;
1259   }
1260
1261   void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset)
1262   {
1263     map<int, CArray<double,1> >::iterator it;
1264     for (it = data_srv.begin(); it != data_srv.end(); it++) it->second = it->second * scaleFactor + addOffset;
1265   }
1266
1267   void CField::outputField(CArray<double,3>& fieldOut)
1268   {
1269      map<int, CArray<double,1> >::iterator it;
1270      for (it = data_srv.begin(); it != data_srv.end(); it++)
1271      {
1272        grid->outputField(it->first, it->second, fieldOut.dataFirst());
1273      }
1274   }
1275
1276   void CField::outputField(CArray<double,2>& fieldOut)
1277   {
1278      map<int, CArray<double,1> >::iterator it;
1279      for(it=data_srv.begin();it!=data_srv.end();it++)
1280      {
1281         grid->outputField(it->first, it->second, fieldOut.dataFirst());
1282      }
1283   }
1284
1285   void CField::outputField(CArray<double,1>& fieldOut)
1286   {
1287      map<int, CArray<double,1> >::iterator it;
1288
1289      for (it = data_srv.begin(); it != data_srv.end(); it++)
1290      {
1291         grid->outputField(it->first, it->second, fieldOut.dataFirst());
1292      }
1293   }
1294
1295   void CField::inputField(CArray<double,3>& fieldOut)
1296   {
1297      map<int, CArray<double,1> >::iterator it;
1298      for (it = data_srv.begin(); it != data_srv.end(); it++)
1299      {
1300        grid->inputField(it->first, fieldOut.dataFirst(), it->second);
1301      }
1302   }
1303
1304   void CField::inputField(CArray<double,2>& fieldOut)
1305   {
1306      map<int, CArray<double,1> >::iterator it;
1307      for(it = data_srv.begin(); it != data_srv.end(); it++)
1308      {
1309         grid->inputField(it->first, fieldOut.dataFirst(), it->second);
1310      }
1311   }
1312
1313   void CField::inputField(CArray<double,1>& fieldOut)
1314   {
1315      map<int, CArray<double,1> >::iterator it;
1316      for (it = data_srv.begin(); it != data_srv.end(); it++)
1317      {
1318         grid->inputField(it->first, fieldOut.dataFirst(), it->second);
1319      }
1320   }
1321
1322   void CField::outputCompressedField(CArray<double,1>& fieldOut)
1323   {
1324      map<int, CArray<double,1> >::iterator it;
1325
1326      for (it = data_srv.begin(); it != data_srv.end(); it++)
1327      {
1328         grid->outputCompressedField(it->first, it->second, fieldOut.dataFirst());
1329      }
1330   }
1331
1332   ///-------------------------------------------------------------------
1333
1334   void CField::parse(xml::CXMLNode& node)
1335   {
1336      SuperClass::parse(node);
1337      if (!node.getContent(this->content))
1338      {
1339        if (node.goToChildElement())
1340        {
1341          do
1342          {
1343            if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node);
1344          } while (node.goToNextElement());
1345          node.goToParentElement();
1346        }
1347      }
1348    }
1349
1350   /*!
1351     This function retrieves Id of corresponding domain_ref and axis_ref (if any)
1352   of a field. In some cases, only domain exists but axis doesn't
1353   \return pair of Domain and Axis id
1354   */
1355   const std::vector<StdString>& CField::getRefDomainAxisIds()
1356   {
1357     CGrid* cgPtr = getRelGrid();
1358     if (NULL != cgPtr)
1359     {
1360       std::vector<StdString>::iterator it;
1361       if (!domain_ref.isEmpty())
1362       {
1363         std::vector<StdString> domainList = cgPtr->getDomainList();
1364         it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());
1365         if (domainList.end() != it) domAxisScalarIds_[0] = *it;
1366       }
1367
1368       if (!axis_ref.isEmpty())
1369       {
1370         std::vector<StdString> axisList = cgPtr->getAxisList();
1371         it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());
1372         if (axisList.end() != it) domAxisScalarIds_[1] = *it;
1373       }
1374
1375       if (!scalar_ref.isEmpty())
1376       {
1377         std::vector<StdString> scalarList = cgPtr->getScalarList();
1378         it = std::find(scalarList.begin(), scalarList.end(), scalar_ref.getValue());
1379         if (scalarList.end() != it) domAxisScalarIds_[2] = *it;
1380       }
1381     }
1382     return (domAxisScalarIds_);
1383   }
1384
1385   CVariable* CField::addVariable(const string& id)
1386   {
1387     return vVariableGroup->createChild(id);
1388   }
1389
1390   CVariableGroup* CField::addVariableGroup(const string& id)
1391   {
1392     return vVariableGroup->createChildGroup(id);
1393   }
1394
1395   void CField::sendAddAllVariables()
1396   {
1397     std::vector<CVariable*> allVar = getAllVariables();
1398     std::vector<CVariable*>::const_iterator it = allVar.begin();
1399     std::vector<CVariable*>::const_iterator itE = allVar.end();
1400
1401     for (; it != itE; ++it)
1402     {
1403       this->sendAddVariable((*it)->getId());
1404       (*it)->sendAllAttributesToServer();
1405       (*it)->sendValue();
1406     }
1407   }
1408
1409   void CField::sendAddAllVariables(CContextClient* client)
1410   {
1411     std::vector<CVariable*> allVar = getAllVariables();
1412     std::vector<CVariable*>::const_iterator it = allVar.begin();
1413     std::vector<CVariable*>::const_iterator itE = allVar.end();
1414
1415     for (; it != itE; ++it)
1416     {
1417       this->sendAddVariable((*it)->getId(), client);
1418       (*it)->sendAllAttributesToServer(client);
1419       (*it)->sendValue(client);
1420     }
1421   }
1422
1423   void CField::sendAddVariable(const string& id)
1424   {
1425      sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE);
1426    // CContext* context = CContext::getCurrent();
1427
1428    // if (!context->hasServer)
1429    // {
1430    //    CContextClient* client = context->client;
1431
1432    //    CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
1433    //    if (client->isServerLeader())
1434    //    {
1435    //      CMessage msg;
1436    //      msg << this->getId();
1437    //      msg << id;
1438    //      const std::list<int>& ranks = client->getRanksServerLeader();
1439    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1440    //        event.push(*itRank,1,msg);
1441    //      client->sendEvent(event);
1442    //    }
1443    //    else client->sendEvent(event);
1444    // }
1445   }
1446
1447   void CField::sendAddVariable(const string& id, CContextClient* client)
1448   {
1449      sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE, client);
1450    // CContext* context = CContext::getCurrent();
1451
1452    // if (!context->hasServer)
1453    // {
1454    //    CContextClient* client = context->client;
1455
1456    //    CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE);
1457    //    if (client->isServerLeader())
1458    //    {
1459    //      CMessage msg;
1460    //      msg << this->getId();
1461    //      msg << id;
1462    //      const std::list<int>& ranks = client->getRanksServerLeader();
1463    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1464    //        event.push(*itRank,1,msg);
1465    //      client->sendEvent(event);
1466    //    }
1467    //    else client->sendEvent(event);
1468    // }
1469   }
1470
1471   void CField::sendAddVariableGroup(const string& id)
1472   {
1473      sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE_GROUP);
1474    // CContext* context = CContext::getCurrent();
1475    // if (!context->hasServer)
1476    // {
1477    //    CContextClient* client = context->client;
1478
1479    //    CEventClient event(this->getType(),EVENT_ID_ADD_VARIABLE_GROUP);
1480    //    if (client->isServerLeader())
1481    //    {
1482    //      CMessage msg;
1483    //      msg << this->getId();
1484    //      msg << id;
1485    //      const std::list<int>& ranks = client->getRanksServerLeader();
1486    //      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
1487    //        event.push(*itRank,1,msg);
1488    //      client->sendEvent(event);
1489    //    }
1490    //    else client->sendEvent(event);
1491    // }
1492   }
1493
1494   void CField::recvAddVariable(CEventServer& event)
1495   {
1496
1497      CBufferIn* buffer = event.subEvents.begin()->buffer;
1498      string id;
1499      *buffer >> id;
1500      get(id)->recvAddVariable(*buffer);
1501   }
1502
1503   void CField::recvAddVariable(CBufferIn& buffer)
1504   {
1505      string id;
1506      buffer >> id;
1507      addVariable(id);
1508   }
1509
1510   void CField::recvAddVariableGroup(CEventServer& event)
1511   {
1512
1513      CBufferIn* buffer = event.subEvents.begin()->buffer;
1514      string id;
1515      *buffer >> id;
1516      get(id)->recvAddVariableGroup(*buffer);
1517   }
1518
1519   void CField::recvAddVariableGroup(CBufferIn& buffer)
1520   {
1521      string id;
1522      buffer >> id;
1523      addVariableGroup(id);
1524   }
1525
1526   /*!
1527    * Returns string arithmetic expression associated to the field.
1528    * \return if content is defined return content string, otherwise, if "expr" attribute is defined, return expr string.
1529    */
1530   const string& CField::getExpression(void)
1531   {
1532     if (!expr.isEmpty() && content.empty())
1533     {
1534       content = expr;
1535       expr.reset();
1536     }
1537
1538     return content;
1539   }
1540
1541   bool CField::hasExpression(void) const
1542   {
1543     return (!expr.isEmpty() || !content.empty());
1544   }
1545
1546
1547   DEFINE_REF_FUNC(Field,field)
1548} // namespace xios
Note: See TracBrowser for help on using the repository browser.