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

Last change on this file since 318 was 318, checked in by ymipsl, 12 years ago
  • Adding new file attribut : sync_freq : flush file for a given frequency
  • Now, when a file has a single domain, domain id is not anymore appended to the coordinate name.

YM

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