source: vendor/nemo/current/NEMOGCM/EXTERNAL/XIOS/src/node/file.cpp @ 44

Last change on this file since 44 was 44, checked in by cholod, 12 years ago

Load NEMO_TMP into vendor/nemo/current.

File size: 14.9 KB
Line 
1#include "file.hpp"
2
3#include "attribute_template.hpp"
4#include "object_template.hpp"
5#include "group_template.hpp"
6#include "object_factory.hpp"
7#include "data_output.hpp"
8#include "context.hpp"
9#include "context_server.hpp"
10#include "nc4_data_output.hpp"
11#include "calendar_util.hpp"
12#include "date.hpp"
13#include "message.hpp"
14#include "type.hpp"
15#include "xmlioserver_spl.hpp"
16#include "context_client.hpp"
17
18namespace xios {
19   
20   /// ////////////////////// Définitions ////////////////////// ///
21
22   CFile::CFile(void)
23      : CObjectTemplate<CFile>(), CFileAttributes()
24      , vFieldGroup(), data_out(), enabledFields()
25   { setVirtualFieldGroup() ;}
26
27   CFile::CFile(const StdString & id)
28      : CObjectTemplate<CFile>(id), CFileAttributes()
29      , vFieldGroup(), data_out(), enabledFields()
30   { setVirtualFieldGroup() ;}
31
32   CFile::~CFile(void)
33   { /* Ne rien faire de plus */ }
34
35   ///---------------------------------------------------------------
36
37   StdString CFile::GetName(void)   { return (StdString("file")); }
38   StdString CFile::GetDefName(void){ return (CFile::GetName()); }
39   ENodeType CFile::GetType(void)   { return (eFile); }
40
41   //----------------------------------------------------------------
42
43   boost::shared_ptr<CDataOutput> CFile::getDataOutput(void) const
44   {
45      return (data_out);
46   }
47
48   CFieldGroup* CFile::getVirtualFieldGroup(void) const
49   {
50      return (this->vFieldGroup);
51   }
52
53   std::vector<CField*> CFile::getAllFields(void) const
54   {
55      return (this->vFieldGroup->getAllChildren());
56   }
57
58   //----------------------------------------------------------------
59
60   std::vector<CField*> CFile::getEnabledFields(int default_outputlevel, 
61                                                int default_level,
62                                                bool default_enabled)
63   {
64      if (!this->enabledFields.empty())
65         return (this->enabledFields);
66
67      const int _outputlevel =
68         (!output_level.isEmpty()) ? output_level.getValue() : default_outputlevel;
69      std::vector<CField*>::iterator it;
70      this->enabledFields = this->getAllFields();
71
72      std::vector<CField*> newEnabledFields;
73     
74      for ( it = this->enabledFields.begin() ; it != this->enabledFields.end(); it++ )
75      {
76         if (!(*it)->enabled.isEmpty()) // Si l'attribut 'enabled' est défini ...
77         {
78            if (! (*it)->enabled.getValue()) continue;
79//            { it--; this->enabledFields.erase(it+1); continue; }
80         }
81         else // Si l'attribut 'enabled' n'est pas défini ...
82         {
83            if (!default_enabled) continue ;
84//            { it--; this->enabledFields.erase(it+1); continue; }
85         }
86
87         if (!(*it)->level.isEmpty()) // Si l'attribut 'level' est défini ...
88         {
89            if ((*it)->level.getValue() > _outputlevel) continue ;
90//            { it--; this->enabledFields.erase(it+1); continue; }
91         }
92         else // Si l'attribut 'level' n'est pas défini ...
93         {
94            if (default_level > _outputlevel) continue ;
95//            { it--; this->enabledFields.erase(it+1); continue; }
96         }
97 
98//         CField* field_tmp=(*it).get() ;
99//         shared_ptr<CField> sptfield=*it ;
100//         field_tmp->refObject.push_back(sptfield) ;
101         newEnabledFields.push_back(*it) ;
102         // Le champ est finalement actif, on y ajoute sa propre reference.
103         (*it)->refObject.push_back(*it);
104         // Le champ est finalement actif, on y ajoute la référence au champ de base.
105         (*it)->setRelFile(CFile::get(this));
106         (*it)->baseRefObject->refObject.push_back(*it);
107         // A faire, ajouter les references intermediaires...
108      }
109      enabledFields=newEnabledFields ;
110
111      return (this->enabledFields);
112   }
113
114   //----------------------------------------------------------------
115
116   void CFile::setVirtualFieldGroup(CFieldGroup* newVFieldGroup)
117   { 
118      this->vFieldGroup = newVFieldGroup; 
119   }
120
121   //----------------------------------------------------------------
122
123   void CFile::setVirtualFieldGroup(void)
124   {
125      this->setVirtualFieldGroup(CFieldGroup::create());
126   }
127
128   //----------------------------------------------------------------
129   bool CFile::isSyncTime(void)
130   {
131     CContext* context = CContext::getCurrent() ;
132     CDate& currentDate=context->calendar->getCurrentDate() ;
133     if (! sync_freq.isEmpty())
134     {
135       if (*lastSync+syncFreq < currentDate)
136       {
137         *lastSync=currentDate ;
138         return true ;
139        }
140      }
141      return false ;
142    }
143   
144   void CFile::initFile(void)
145   {
146      CContext* context = CContext::getCurrent() ;
147      CDate& currentDate=context->calendar->getCurrentDate() ;
148     
149      if (! sync_freq.isEmpty()) syncFreq = CDuration::FromString(sync_freq.getValue());
150      if (! split_freq.isEmpty()) splitFreq = CDuration::FromString(split_freq.getValue());
151      if (! output_freq.isEmpty()) outputFreq = CDuration::FromString(output_freq.getValue());
152      lastSync=new CDate(currentDate) ;
153      lastSplit=new CDate(currentDate) ;
154      isOpen=false ;
155    }
156   
157    void CFile::checkFile(void)
158    {
159      if (!isOpen) createHeader() ;
160      checkSync() ;
161      checkSplit() ;
162    }
163     
164     
165   bool CFile::checkSync(void)
166   {
167     CContext* context = CContext::getCurrent() ;
168     CDate& currentDate=context->calendar->getCurrentDate() ;
169     if (! sync_freq.isEmpty())
170     {
171       if (*lastSync+syncFreq < currentDate)
172       {
173         *lastSync=currentDate ;
174         data_out->syncFile() ;
175         return true ;
176        }
177      }
178      return false ;
179    }
180   
181   
182    bool CFile::checkSplit(void)
183    {
184      CContext* context = CContext::getCurrent() ;
185      CDate& currentDate=context->calendar->getCurrentDate() ;
186      if (! split_freq.isEmpty())
187      {
188        if (*lastSplit+splitFreq < currentDate)
189        {
190          *lastSplit=currentDate-outputFreq ;
191       
192          std::vector<CField*>::iterator it, end = this->enabledFields.end();
193          for (it = this->enabledFields.begin() ;it != end; it++)  (*it)->resetNStep() ;
194          createHeader() ;
195          return true ;
196        }
197      }
198      return false ;
199    }
200   
201   void CFile::createHeader(void)
202   {
203      CContext* context = CContext::getCurrent() ;
204      CDate& currentDate=context->calendar->getCurrentDate() ;
205     
206      std::vector<CField*>::iterator it, end = this->enabledFields.end();
207
208      AllDomainEmpty=true ;
209      set<CDomain*> setDomain ;
210      for (it = this->enabledFields.begin() ;it != end; it++)
211      {
212         CField* field = *it;
213         AllDomainEmpty&=field->grid->domain->isEmpty() ;
214         setDomain.insert(field->grid->domain) ;
215      }
216      nbDomain=setDomain.size() ;
217
218      if (!AllDomainEmpty ||  type.getValue()=="one_file")
219      {
220         StdString filename = (!name.isEmpty()) ?   name.getValue() : getId();
221         StdOStringStream oss;
222//         if (! output_dir.isEmpty()) oss << output_dir.getValue();
223         oss << filename;
224         if (!name_suffix.isEmpty()) oss << name_suffix.getValue();
225//         if (!split_freq.isEmpty()) oss<<"-["<<currentDate.toString()<<"]" ;
226         if (!split_freq.isEmpty()) oss<<"_"<<lastSplit->getStryyyymmdd()<<"-"<< (*lastSplit+(splitFreq-1*Second)).getStryyyymmdd();
227         bool multifile=true ;
228         if (!type.isEmpty())
229         {
230           if (type.getValue()=="one_file") multifile=false ;
231           else if (type.getValue()=="multi_file") multifile=true ;
232           else ERROR("void Context::createDataOutput(void)",
233                      "incorrect file <type> attribut : must be <multi_file> or <one_file>, "
234                      <<"having : <"<<type.getValue()<<">") ;
235         } 
236         
237         CContextServer* server=context->server ;
238
239         if (multifile) 
240         {
241            if (server->intraCommSize > 1) oss << "_" << server->intraCommRank;
242         }
243         oss << ".nc";
244
245         if (isOpen) data_out->closeFile() ;
246         bool isCollective=true ;
247         if (!par_access.isEmpty())
248         {
249           if (par_access.getValue()=="independent") isCollective=false ;
250           else if (par_access.getValue()=="collective") isCollective=true ;
251           else 
252           {
253             ERROR("void Context::createDataOutput(void)",
254                        "incorrect file <par_access> attribut : must be <collective> or <indepedent>, "
255                        <<"having : <"<<type.getValue()<<">") ;
256           }
257         }
258         data_out=shared_ptr<CDataOutput>(new CNc4DataOutput(oss.str(), false,server->intraComm,multifile, isCollective));
259         isOpen=true ;
260
261         data_out->writeFile(CFile::get(this));
262         for (it = this->enabledFields.begin() ;it != end; it++)
263         {
264            CField* field = *it;
265            this->data_out->writeFieldGrid(field);
266         }
267         
268         for (it = this->enabledFields.begin() ;it != end; it++)
269         {
270            CField* field = *it;
271            this->data_out->writeField(field);
272         }
273         
274         this->data_out->definition_end();
275      }
276   }
277
278   void CFile::close(void)
279   {
280     delete lastSync ;
281     delete lastSplit ;
282     if (!AllDomainEmpty ||  type.getValue()=="one_file")
283       if (isOpen) 
284       {
285         this->data_out->closeFile();
286       }
287   }
288   //----------------------------------------------------------------
289
290   void CFile::parse(xml::CXMLNode & node)
291   {
292      SuperClass::parse(node);
293      if (node.goToChildElement() & this->hasId())
294      { // Si la définition du fichier intégre des champs et si le fichier est identifié.
295         node.goToParentElement();
296//         this->setVirtualFieldGroup(this->getId());
297         this->getVirtualFieldGroup()->parse(node, false);
298      }
299   }
300   //----------------------------------------------------------------
301
302   StdString CFile::toString(void) const
303   {
304      StdOStringStream oss;
305
306      oss << "<" << CFile::GetName() << " ";
307      if (this->hasId())
308         oss << " id=\"" << this->getId() << "\" ";
309      oss << SuperClassAttribute::toString() << ">" << std::endl;
310      if (this->getVirtualFieldGroup() != NULL)
311         oss << *this->getVirtualFieldGroup() << std::endl;
312      oss << "</" << CFile::GetName() << " >";
313      return (oss.str());
314   }
315
316   //----------------------------------------------------------------
317   
318   void CFile::solveDescInheritance(const CAttributeMap * const parent)
319   {
320      SuperClassAttribute::setAttributes(parent);
321      this->getVirtualFieldGroup()->solveDescInheritance(NULL);
322   }
323
324   //----------------------------------------------------------------
325
326   void CFile::solveFieldRefInheritance(void)
327   {
328      // Résolution des héritages par référence de chacun des champs contenus dans le fichier.
329      std::vector<CField*> allF = this->getAllFields();
330      for (unsigned int i = 0; i < allF.size(); i++)
331         allF[i]->solveRefInheritance();
332   }
333
334   //----------------------------------------------------------------
335
336   void CFile::solveEFGridRef(void)
337   {
338      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
339         this->enabledFields[i]->solveGridReference();
340   }
341
342   //----------------------------------------------------------------
343
344   void CFile::solveEFOperation(void)
345   {
346      for (unsigned int i = 0; i < this->enabledFields.size(); i++)
347         this->enabledFields[i]->solveOperation();
348   }
349   
350   //---------------------------------------------------------------
351   
352   void CFile::toBinary  (StdOStream & os) const
353   {
354      ENodeType genum = CFileGroup::GetType();
355      bool hasVFG = (this->getVirtualFieldGroup() != NULL);
356      SuperClass::toBinary(os);
357     
358      os.write (reinterpret_cast<const char*>(&genum) , sizeof(ENodeType));
359      os.write (reinterpret_cast<const char*>(&hasVFG) , sizeof(bool));
360     
361      if (hasVFG)this->getVirtualFieldGroup()->toBinary(os);
362         
363   }
364   
365   //----------------------------------------------------------------
366   
367   void CFile::fromBinary(StdIStream & is)
368   {
369      ENodeType renum = Unknown;
370      bool hasVFG = false;
371      SuperClass::fromBinary(is);
372     
373      is.read (reinterpret_cast<char*>(&renum), sizeof(ENodeType));
374      is.read (reinterpret_cast<char*>(&hasVFG), sizeof(bool));
375     
376      if (renum != CFileGroup::GetType())
377         ERROR("CFile::fromBinary(StdIStream & is)",
378               << "[ renum = " << renum << "] Bad type !");
379     
380//      this->setVirtualFieldGroup(this->getId());
381      if (hasVFG)this->getVirtualFieldGroup()->fromBinary(is);
382     
383   }
384   
385   CField* CFile::addField(const string& id)
386   {
387     return vFieldGroup->createChild(id) ;
388   }
389
390   CFieldGroup* CFile::addFieldGroup(const string& id)
391   {
392     return vFieldGroup->createChildGroup(id) ;
393   }
394   
395 
396   void CFile::sendAddField(const string& id)
397   {
398    CContext* context=CContext::getCurrent() ;
399   
400    if (! context->hasServer )
401    {
402       CContextClient* client=context->client ;
403
404       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD) ;   
405       if (client->isServerLeader())
406       {
407         CMessage msg ;
408         msg<<this->getId() ;
409         msg<<id ;
410         event.push(client->getServerLeader(),1,msg) ;
411         client->sendEvent(event) ;
412       }
413       else client->sendEvent(event) ;
414    }
415     
416   }
417   
418   void CFile::sendAddFieldGroup(const string& id)
419   {
420    CContext* context=CContext::getCurrent() ;
421    if (! context->hasServer )
422    {
423       CContextClient* client=context->client ;
424
425       CEventClient event(this->getType(),EVENT_ID_ADD_FIELD_GROUP) ;   
426       if (client->isServerLeader())
427       {
428         CMessage msg ;
429         msg<<this->getId() ;
430         msg<<id ;
431         event.push(client->getServerLeader(),1,msg) ;
432         client->sendEvent(event) ;
433       }
434       else client->sendEvent(event) ;
435    }
436     
437   }
438   
439   void CFile::recvAddField(CEventServer& event)
440   {
441     
442      CBufferIn* buffer=event.subEvents.begin()->buffer;
443      string id;
444      *buffer>>id ;
445      get(id)->recvAddField(*buffer) ;
446   }
447   
448   
449   void CFile::recvAddField(CBufferIn& buffer)
450   {
451      string id ;
452      buffer>>id ;
453      addField(id) ;
454   }
455
456   void CFile::recvAddFieldGroup(CEventServer& event)
457   {
458     
459      CBufferIn* buffer=event.subEvents.begin()->buffer;
460      string id;
461      *buffer>>id ;
462      get(id)->recvAddFieldGroup(*buffer) ;
463   }
464   
465   
466   void CFile::recvAddFieldGroup(CBufferIn& buffer)
467   {
468      string id ;
469      buffer>>id ;
470      addFieldGroup(id) ;
471   }
472   
473
474   bool CFile::dispatchEvent(CEventServer& event)
475   {
476      if (SuperClass::dispatchEvent(event)) return true ;
477      else
478      {
479        switch(event.type)
480        {
481           case EVENT_ID_ADD_FIELD :
482             recvAddField(event) ;
483             return true ;
484             break ;
485         
486           case EVENT_ID_ADD_FIELD_GROUP :
487             recvAddFieldGroup(event) ;
488             return true ;
489             break ;       
490         
491           default :
492              ERROR("bool CFile::dispatchEvent(CEventServer& event)", <<"Unknown Event") ;
493           return false ;
494        }
495      }
496   }
497   
498   
499   
500   
501   ///---------------------------------------------------------------
502
503} // namespace xios
Note: See TracBrowser for help on using the repository browser.