source: XIOS/trunk/src/buffer_client.cpp @ 934

Last change on this file since 934 was 917, checked in by rlacroix, 8 years ago

Fix the client/server communication protocol.

In the some extreme cases a deadlock could occur. To fix this, the number of buffered events must be properly limited.

If you noticed decreased performance due to this commit, please let us know about it.

Fixes ticket #91.

  • 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: 2.5 KB
Line 
1#include "xios_spl.hpp"
2#include "exception.hpp"
3#include "log.hpp"
4#include "buffer_out.hpp"
5#include "buffer_client.hpp"
6#include "cxios.hpp"
7#include "mpi.hpp"
8#include "tracer.hpp"
9
10namespace xios
11{
12  size_t CClientBuffer::maxRequestSize = 0;
13
14  CClientBuffer::CClientBuffer(MPI_Comm interComm, int serverRank, StdSize bufferSize, StdSize maxBufferedEvents)
15    : interComm(interComm)
16    , serverRank(serverRank)
17    , bufferSize(bufferSize)
18    , current(0)
19    , count(0)
20    , bufferedEvents(0)
21    , maxBufferedEvents(maxBufferedEvents)
22    , pending(false)
23  {
24    buffer[0] = new char[bufferSize]; // transform it with MPI_ALLOC_MEM later
25    buffer[1] = new char[bufferSize];
26    retBuffer = new CBufferOut(buffer[current], bufferSize);
27    info(10) << "CClientBuffer: allocated 2 x " << bufferSize << " bytes for server " << serverRank << " with a maximum of " << maxBufferedEvents << " buffered events" << endl;
28  }
29
30  CClientBuffer::~CClientBuffer()
31  {
32   delete [] buffer[0];
33   delete [] buffer[1];
34   delete retBuffer;
35  }
36
37  int CClientBuffer::remain(void)
38  {
39    return bufferSize - count;
40  }
41
42  bool CClientBuffer::isBufferFree(int size)
43  {
44    if (size > maxRequestSize) maxRequestSize = size;
45
46    if (size > bufferSize)
47      ERROR("bool CClientBuffer::isBufferFree(int size)",
48            << "The requested size (" << size << " bytes) is too big to fit the buffer (" << bufferSize << " bytes), please increase the client buffer size." << endl);
49
50    return (size <= remain() && bufferedEvents < maxBufferedEvents);
51  }
52
53
54  CBufferOut* CClientBuffer::getBuffer(int size)
55  {
56    if (size <= remain())
57    {
58      retBuffer->realloc(buffer[current] + count, size);
59      count += size;
60      bufferedEvents++;
61      return retBuffer;
62    }
63    else
64    {
65      ERROR("CBufferOut* CClientBuffer::getBuffer(int size)",
66            << "Not enough space in buffer, this should not have happened...");
67      return NULL;
68    }
69  }
70
71  bool CClientBuffer::checkBuffer(void)
72  {
73    MPI_Status status;
74    int flag;
75
76    if (pending)
77    {
78      traceOff();
79      MPI_Test(&request, &flag, &status);
80      traceOn();
81      if (flag == true) pending = false;
82    }
83
84    if (!pending)
85    {
86      if (count > 0)
87      {
88        MPI_Issend(buffer[current], count, MPI_CHAR, serverRank, 20, interComm, &request);
89        pending = true;
90        if (current == 1) current = 0;
91        else current = 1;
92        count = 0;
93        bufferedEvents = 0;
94      }
95    }
96
97    return pending;
98  }
99
100  bool CClientBuffer::hasPendingRequest(void)
101  {
102    return (pending || count > 0);
103  }
104}
Note: See TracBrowser for help on using the repository browser.