source: XIOS/trunk/src/context_server.cpp @ 549

Last change on this file since 549 was 549, checked in by rlacroix, 9 years ago

Revised calendar functionalities:

  • the calendar is now configured from a specific calendar child node of the context in the XML configuration file. Example: <calendar type="Gregorian" start_date="2012-03-01 15:00:00" time_origin="2012-02-29 15:00:00" timestep="1h" />
  • the calendar type should now be configured when defining the start time and/or the time origin.
  • the start time and the time origin are now optional, 0000-01-01 00:00:00 will be used by default. It is also possible to define them partially. For example, 2015 and 2014-12 are valid dates corresponding respectively to 2015-01-01 00:00:00 and 2014-12-01 00:00:00.
  • an optional duration offset can be added to the start date and time origin. For example, it's possible to define the date 2015-01-12 12:00:00 as 2015-01-11 + 36h or 2015-01-11 12:00:00 + 1d. The duration format is the same as the time step. Being that the date is optional, it is possible to only use a duration (for example + 42s is the same as 0000-01-01 00:00:00 + 42s). An error will be raised if a duration based on the time step is used before the time step was configured. For example, the following would cause an error: <calendar type="Gregorian" start_date="+ 1ts" /> but <calendar type="Gregorian" start_date="+ 1ts" timestep="0.5h" /> would not.
  • new Fortran interface to define the calendar:
    • xios_define_calendar(type[, timestep, start_date, time_origin]) will create a calendar when none had previously been defined. Only the type argument is mandatory, the rest is optional. Calendar operations on dates and durations are possible as soon as the calendar is created (either using this procedure or directly from the XML configuration file).
    • the following getter and setter procedures are available: xios_set_timestep, xios_set_start_date, xios_set_time_origin, xios_get_calendar_type, xios_get_timestep, xios_get_start_date, xios_get_time_origin.
  • new Fortran interface to interact with the calendar: xios_update_calendar, xios_get_current_date, xios_get_year_length_in_seconds, xios_get_day_length_in_seconds.
  • new Fortran interface for date conversion: xios_date_get_second_of_year, xios_date_get_day_of_year, xios_date_get_fraction_of_year, xios_date_get_second_of_day, xios_date_get_fraction_of_day.
  • two new placeholders are available to format the file name when splitting the output (split_freq_format attribute):
    • %S the number of seconds since the time origin
    • %D the integral number of days since the time origin
  • 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:eol-style set to native
File size: 7.1 KB
RevLine 
[300]1#include "context_server.hpp"
2#include "buffer_in.hpp"
3#include "type.hpp"
4#include "context.hpp"
[352]5#include "object_template.hpp"
6#include "group_template.hpp"
7#include "attribute_template.hpp"
[300]8#include "domain.hpp"
[352]9#include "field.hpp"
10#include "file.hpp"
11#include "grid.hpp"
[382]12#include "mpi.hpp"
[347]13#include "tracer.hpp"
14#include "timer.hpp"
[401]15#include "cxios.hpp"
[492]16#include "event_scheduler.hpp"
17#include "server.hpp"
18#include <boost/functional/hash.hpp>
[300]19
20
21
[335]22namespace xios
[300]23{
24
[345]25  CContextServer::CContextServer(CContext* parent,MPI_Comm intraComm_,MPI_Comm interComm_)
[300]26  {
[549]27    context=parent;
28    intraComm=intraComm_;
29    MPI_Comm_size(intraComm,&intraCommSize);
30    MPI_Comm_rank(intraComm,&intraCommRank);
31    interComm=interComm_;
32    int flag;
33    MPI_Comm_test_inter(interComm,&flag);
[300]34    if (flag) MPI_Comm_remote_size(interComm,&commSize);
[549]35    else  MPI_Comm_size(interComm,&commSize);
36    currentTimeLine=0;
37    scheduled=false;
38    finished=false;
[509]39
[549]40    boost::hash<string> hashString;
41    hashId=hashString(context->getId());
[492]42
[300]43  }
44  void CContextServer::setPendingEvent(void)
45  {
[549]46    pendingEvent=true;
[300]47  }
[489]48
[300]49  bool CContextServer::hasPendingEvent(void)
50  {
[549]51    return pendingEvent;
[300]52  }
[489]53
[300]54  bool CContextServer::eventLoop(void)
55  {
[549]56    listen();
57    checkPendingRequest();
58    processEvents();
59    return finished;
[300]60  }
61
62  void CContextServer::listen(void)
63  {
64    int rank;
[549]65    int flag;
66    int count;
67    char * addr;
[489]68    MPI_Status status;
[300]69    map<int,CServerBuffer*>::iterator it;
[489]70
[300]71    for(rank=0;rank<commSize;rank++)
72    {
73      if (pendingRequest.find(rank)==pendingRequest.end())
74      {
[549]75        traceOff();
[489]76        MPI_Iprobe(rank,20,interComm,&flag,&status);
[549]77        traceOn();
[300]78        if (flag==true)
79        {
[549]80          it=buffers.find(rank);
[489]81          if (it==buffers.end())
[300]82          {
[509]83            StdSize buffSize = 0;
84            MPI_Recv(&buffSize, 1, MPI_LONG, rank, 20, interComm, &status);
[511]85            mapBufferSize_.insert(std::make_pair(rank, buffSize));
[549]86            it=(buffers.insert(pair<int,CServerBuffer*>(rank,new CServerBuffer(buffSize)))).first;
[300]87          }
[509]88          else
89          {
[549]90            MPI_Get_count(&status,MPI_CHAR,&count);
[509]91            if (it->second->isBufferFree(count))
92            {
[549]93              addr=(char*)it->second->getBuffer(count);
94              MPI_Irecv(addr,count,MPI_CHAR,rank,20,interComm,&pendingRequest[rank]);
95              bufferRequest[rank]=addr;
[509]96            }
97          }
[300]98        }
99      }
100    }
101  }
[489]102
[300]103  void CContextServer::checkPendingRequest(void)
104  {
105    map<int,MPI_Request>::iterator it;
[549]106    list<int> recvRequest;
[300]107    list<int>::iterator itRecv;
[549]108    int rank;
109    int flag;
110    int count;
111    MPI_Status status;
[489]112
[300]113    for(it=pendingRequest.begin();it!=pendingRequest.end();it++)
114    {
[549]115      rank=it->first;
116      traceOff();
117      MPI_Test(& it->second, &flag, &status);
118      traceOn();
[300]119      if (flag==true)
120      {
[549]121        recvRequest.push_back(rank);
122        MPI_Get_count(&status,MPI_CHAR,&count);
123        processRequest(rank,bufferRequest[rank],count);
[300]124      }
125    }
[489]126
127    for(itRecv=recvRequest.begin();itRecv!=recvRequest.end();itRecv++)
[300]128    {
[549]129      pendingRequest.erase(*itRecv);
130      bufferRequest.erase(*itRecv);
[300]131    }
132  }
[489]133
[300]134  void CContextServer::processRequest(int rank, char* buff,int count)
135  {
[489]136
[549]137    CBufferIn buffer(buff,count);
138    char* startBuffer,endBuffer;
139    int size, offset;
140    size_t timeLine;
141    map<size_t,CEventServer*>::iterator it;
[489]142
[300]143    while(count>0)
144    {
[549]145      char* startBuffer=(char*)buffer.ptr();
146      CBufferIn newBuffer(startBuffer,buffer.remain());
147      newBuffer>>size>>timeLine;
[300]148
[549]149      it=events.find(timeLine);
150      if (it==events.end()) it=events.insert(pair<int,CEventServer*>(timeLine,new CEventServer)).first;
151      it->second->push(rank,buffers[rank],startBuffer,size);
[300]152
[549]153      buffer.advance(size);
154      count=buffer.remain();
[489]155    }
156
[300]157  }
[489]158
[300]159  void CContextServer::processEvents(void)
160  {
[549]161    map<size_t,CEventServer*>::iterator it;
162    CEventServer* event;
[489]163
[549]164    it=events.find(currentTimeLine);
[489]165    if (it!=events.end())
[300]166    {
[549]167      event=it->second;
[509]168
[300]169      if (event->isFull())
170      {
[492]171        if (!scheduled && !CXios::isServer)
172        {
[549]173          CServer::eventScheduler->registerEvent(currentTimeLine,hashId);
174          scheduled=true;
[492]175        }
[509]176        else if (CXios::isServer || CServer::eventScheduler->queryEvent(currentTimeLine,hashId) )
[492]177        {
[549]178         CTimer::get("Process events").resume();
179         dispatchEvent(*event);
180         CTimer::get("Process events").suspend();
181         pendingEvent=false;
182         delete event;
183         events.erase(it);
184         currentTimeLine++;
185         scheduled = false;
[492]186        }
187      }
188    }
189  }
[489]190
[300]191  CContextServer::~CContextServer()
192  {
[549]193    map<int,CServerBuffer*>::iterator it;
194    for(it=buffers.begin();it!=buffers.end();++it) delete it->second;
[489]195  }
[300]196
197
198  void CContextServer::dispatchEvent(CEventServer& event)
199  {
[549]200    string contextName;
201    string buff;
202    int MsgSize;
203    int rank;
204    list<CEventServer::SSubEvent>::iterator it;
205    CContext::setCurrent(context->getId());
[489]206
[300]207    if (event.classId==CContext::GetType() && event.type==CContext::EVENT_ID_CONTEXT_FINALIZE)
208    {
[549]209      info(20)<<"Server Side context <"<<context->getId()<<"> finalized"<<endl;
[511]210      std::map<int, StdSize>::const_iterator itbMap = mapBufferSize_.begin(),
211                                             iteMap = mapBufferSize_.end(), itMap;
212      StdSize totalBuf = 0;
213      for (itMap = itbMap; itMap != iteMap; ++itMap)
214      {
215        report(10)<< " Memory report : Context <"<<context->getId()<<"> : server side : memory used for buffer of each connection to client" << endl
216                  << "  +) With client of rank " << itMap->first << " : " << itMap->second << " bytes " << endl;
217        totalBuf += itMap->second;
218      }
[549]219      context->finalize();
220      finished=true;
221      report(0)<< " Memory report : Context <"<<context->getId()<<"> : server side : total memory used for buffer "<<totalBuf<<" bytes"<<endl;
[300]222    }
[549]223    else if (event.classId==CContext::GetType()) CContext::dispatchEvent(event);
224    else if (event.classId==CContextGroup::GetType()) CContextGroup::dispatchEvent(event);
225    else if (event.classId==CCalendarWrapper::GetType()) CCalendarWrapper::dispatchEvent(event);
226    else if (event.classId==CDomain::GetType()) CDomain::dispatchEvent(event);
227    else if (event.classId==CDomainGroup::GetType()) CDomainGroup::dispatchEvent(event);
228    else if (event.classId==CAxis::GetType()) CAxis::dispatchEvent(event);
229    else if (event.classId==CAxisGroup::GetType()) CAxisGroup::dispatchEvent(event);
230    else if (event.classId==CGrid::GetType()) CGrid::dispatchEvent(event);
231    else if (event.classId==CGridGroup::GetType()) CGridGroup::dispatchEvent(event);
232    else if (event.classId==CField::GetType()) CField::dispatchEvent(event);
233    else if (event.classId==CFieldGroup::GetType()) CFieldGroup::dispatchEvent(event);
234    else if (event.classId==CFile::GetType()) CFile::dispatchEvent(event);
235    else if (event.classId==CFileGroup::GetType()) CFileGroup::dispatchEvent(event);
236    else if (event.classId==CVariable::GetType()) CVariable::dispatchEvent(event);
[300]237    else
238    {
[549]239      ERROR("void CContextServer::dispatchEvent(CEventServer& event)",<<" Bad event class Id"<<endl);
[300]240    }
241  }
242}
Note: See TracBrowser for help on using the repository browser.