ADTF
fileringbuffer.h
Go to the documentation of this file.
1 
7 #ifndef _DISK_RING_BUFFER_H
8 #define _DISK_RING_BUFFER_H
9 
10 namespace A_UTILS_NS
11 {
12 
27 template <typename ADDITIONAL_DATA = tUInt8, tUInt8 ALIGNMENT = 1>
29 {
30  public:
34  struct tItem
35  {
36  tItem(): nFilePos(-1), nSize(0) {}
39  ADDITIONAL_DATA xAdditional;
40  };
41 
46  {
47  public:
55  virtual tResult OnDrop(const tItem& sDroppedItem, const tItem& sNextItem) = 0;
56  };
57 
61  struct tItemPiece
62  {
63  const tVoid* pData;
65  };
66 
68  typedef std::deque<tItem> tItems;
70  typedef typename tItems::const_iterator const_iterator;
71 
72  private:
73  tItems m_oItems;
74  cFile* m_pFile;
75  tFilePos m_nStartOffset;
76  tFilePos m_nCurrentPos;
77  tFileSize m_nCurrentSize;
78  tFileSize m_nMaxSize;
79  tBool m_bBookkeeping;
80  IDropCallback* m_pCallback;
81  cMemoryBlock m_oAlignmentBuffer;
82  tItem m_sRearItem;
83 
84  public:
93  cFileRingBuffer(cFile* pFile, tFilePos nStartOffset = 0,
94  tFileSize nMaxSize = 0, IDropCallback* pDropCallback = nullptr):
95  m_pFile(pFile),
96  m_nStartOffset(nStartOffset),
97  m_nCurrentSize(0),
98  m_nMaxSize(nMaxSize),
99  m_bBookkeeping(tTrue),
100  m_pCallback(pDropCallback)
101  {
102  pFile->SetFilePos(nStartOffset, cFile::FP_Begin);
103  m_nCurrentPos = nStartOffset;
104 
105  if (ALIGNMENT > 1)
106  {
107  m_oAlignmentBuffer.Alloc(ALIGNMENT - 1);
108  cMemoryBlock::MemZero(m_oAlignmentBuffer.GetPtr(), m_oAlignmentBuffer.GetSize());
109  }
110 
112  }
113 
119  {
120  return m_nCurrentSize;
121  }
122 
128  {
129  if (!m_bBookkeeping)
130  {
131  RETURN_ERROR(ERR_INVALID_STATE);
132  }
133 
134  m_nMaxSize = m_nCurrentSize;
136  }
137 
146  tResult StartAppending(tItem* pRearDataItem = NULL, tItem* pLastDataItem = NULL)
147  {
148  if (!m_bBookkeeping)
149  {
150  RETURN_ERROR(ERR_INVALID_STATE);
151  }
152 
153  m_nMaxSize = 0;
154  m_pFile->SetFilePos(0, cFile::FP_End);
155  m_nCurrentPos = m_pFile->GetFilePos();
156  m_bBookkeeping = tFalse;
157 
158  if (m_sRearItem.nFilePos == -1 && !m_oItems.empty())
159  {
160  // we never wrapped around.
161  m_sRearItem = m_oItems.back();
162  }
163 
164  if (pRearDataItem)
165  {
166  *pRearDataItem = m_sRearItem;
167  }
168 
169  if (pLastDataItem)
170  {
171  if (!m_oItems.empty())
172  {
173  *pLastDataItem = m_oItems.back();
174  }
175  else
176  {
177  *pLastDataItem = tItem();
178  }
179  }
180 
182  }
183 
192  tResult AppendItem(const tVoid* pData, tSize nDataSize,
193  const ADDITIONAL_DATA& xAdditional, tFilePos* pFilePos = nullptr)
194  {
195  tItemPiece sItem;
196  sItem.pData = pData;
197  sItem.nDataSize = nDataSize;
198  return AppendItem(&sItem, 1, xAdditional, pFilePos);
199  }
200 
209  tResult AppendItem(const tItemPiece* pPieces, tSize nCount,
210  const ADDITIONAL_DATA& xAdditional, tFilePos* pFilePos = nullptr)
211  {
212  tSize nDataSize = 0;
213  for (tSize nPiece = 0; nPiece < nCount; ++nPiece)
214  {
215  nDataSize += pPieces[nPiece].nDataSize;
216  }
217 
218  if (m_nMaxSize && !m_oItems.empty())
219  {
220  if (m_nCurrentPos + nDataSize > m_nMaxSize)
221  {
222  // in this case we need to wrap around
223  RETURN_IF_FAILED(m_pFile->Truncate(m_nCurrentPos));
224  m_nCurrentSize = m_nCurrentPos;
225 
226  m_sRearItem = m_oItems.back();
227 
228  //we need remove all items following this postion
229  while (m_oItems.front().nFilePos >= m_nCurrentPos)
230  {
232  }
233 
234  m_nCurrentPos = m_oItems.front().nFilePos; // this should be equal to the data offset
235  if (m_pFile->SetFilePos(m_nCurrentPos, cFile::FP_Begin) == -1)
236  {
237  RETURN_ERROR(ERR_UNEXPECTED);
238  }
239  }
240  }
241 
242  if (pFilePos)
243  {
244  *pFilePos = m_nCurrentPos;
245  }
246 
247  tFilePos nWritePos = m_nCurrentPos;
248 
249  for (tSize nPiece = 0; nPiece < nCount; ++nPiece)
250  {
251  RETURN_IF_FAILED(m_pFile->WriteAll(pPieces[nPiece].pData, static_cast<tInt>(pPieces[nPiece].nDataSize)));
252  }
253 
254  m_nCurrentPos += nDataSize;
255 
257 
258  if (m_nCurrentPos > m_nCurrentSize)
259  {
260  m_nCurrentSize = m_nCurrentPos;
261  }
262 
263  if (m_bBookkeeping)
264  {
265  tItem sItem;
266  sItem.nFilePos = nWritePos;
267  sItem.nSize = nDataSize;
268  sItem.xAdditional = xAdditional;
269 
270  m_oItems.push_back(sItem);
271 
272  tFilePos nStart = sItem.nFilePos;
273  tFilePos nEnd = m_nCurrentPos;
274 
275  while (m_oItems.size() > 1 &&
276  m_oItems.front().nFilePos >= nStart &&
277  m_oItems.front().nFilePos < nEnd)
278  {
280  }
281 
282  if (m_sRearItem.nFilePos != -1)
283  {
284  // we did wrap around at least once
285  // check if this item did overwrite the current rear item
286  if (m_sRearItem.nFilePos < nEnd)
287  {
288  // it has been overwritten by the current one
289  // and was alread removed from the queue in the while loop above
290  // so the current item is the new rear item.
291  m_sRearItem = m_oItems.back();
292  // make sure that the file ends after the current item
293  RETURN_IF_FAILED(m_pFile->Truncate(m_nCurrentPos));
294  m_nCurrentSize = m_nCurrentPos;
295  }
296  }
297  }
298 
300  }
301 
307  {
308  return m_oItems.begin();
309  }
310 
316  {
317  return m_oItems.end();
318  }
319 
320  protected:
327  {
328  tFilePos nMod = m_nCurrentPos % ALIGNMENT;
329  if (nMod)
330  {
331  tFilePos nFill = ALIGNMENT - nMod;
332  RETURN_IF_FAILED(m_pFile->WriteAll(m_oAlignmentBuffer.GetPtr(),
333  static_cast<tInt>(nFill)));
334  m_nCurrentPos += nFill;
335  }
336 
338  }
339 
345  {
346  if (m_pCallback)
347  {
348  static tItem s_sDummy;
349 
350  tItem& sItem = m_oItems.front();
351  tItem* pNext = &s_sDummy;
352  if (m_oItems.size() > 1)
353  {
354  pNext = &m_oItems[1];
355  }
356  RETURN_IF_FAILED(m_pCallback->OnDrop(sItem, *pNext));
357  }
358  m_oItems.pop_front();
360  }
361 };
362 
363 }
364 
365 #endif
tInt64 tFileSize
type definition for a file or stream size value (platform and compiler independent type).
tInt64 tFilePos
type definition for a file or stream position value (platform and compiler independent type).
void tVoid
The tVoid is always the definition for the void (non-type).
int tInt
type definition for signed integer value (platform and compiler dependent type).
bool tBool
The tBool defines the type for the Values tTrue and tFalse (platform and compiler dependent).
size_t tSize
type definition for a array size values, map size values etc.
#define RETURN_IF_FAILED(s)
Return if expression is failed, which requires the calling function's return type to be tResult.
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
#define RETURN_ERROR(code)
Return specific error code, which requires the calling function's return type to be tResult.
File class.
Definition: file.h:26
tFilePos SetFilePos(tFilePos nOffset, tFilePosRef MoveMode)
This function moves the file pointer.
@ FP_Begin
offsets are measured from the beginning of the file
Definition: file.h:85
@ FP_End
offsets are measured from the end of the file
Definition: file.h:91
tResult Truncate(tFilePos nSize)
This method truncates the file at the given size.
tResult WriteAll(const tVoid *pvBuffer, tInt nBufferSize)
This function writes data from a buffer to the file associated with the cFile object.
tFilePos GetFilePos() const
This function retrieves the file pointer offset.
Callback interface for dropped items.
virtual tResult OnDrop(const tItem &sDroppedItem, const tItem &sNextItem)=0
Called whenever an item is removed from the head of the buffer.
File-based ring buffer.
tResult AppendItem(const tItemPiece *pPieces, tSize nCount, const ADDITIONAL_DATA &xAdditional, tFilePos *pFilePos=nullptr)
Adds a new item that is made up by multiple data buffers at the end of the buffer.
const_iterator begin() const
Retunrs an iterator to the beginning of the buffer.
tResult StartAppending(tItem *pRearDataItem=NULL, tItem *pLastDataItem=NULL)
After a call to this method, data will be appended after the ring buffer.
cFileRingBuffer(cFile *pFile, tFilePos nStartOffset=0, tFileSize nMaxSize=0, IDropCallback *pDropCallback=nullptr)
Constructor.
tResult StartWrappingAround()
Limits the size of the buffer by the current size.
tResult AppendItem(const tVoid *pData, tSize nDataSize, const ADDITIONAL_DATA &xAdditional, tFilePos *pFilePos=nullptr)
Adds a new item at the end of the buffer.
std::deque< tItem > tItems
Typedef for convienient access.
tItems::const_iterator const_iterator
An const iterator in the buffer.
const tFileSize & GetCurrentSize()
Returns the current size of the buffer.
const_iterator end() const
Retuns an iterator to the end of the buffer.
tResult FillForAlignment()
Writes data to the file until a field position is reached that satisfies the alignment requirement.
tResult PopFront()
Removes the first item in the buffer.
Memory block class.
Definition: memoryblock.h:20
tResult Alloc(tSize nSize)
(Re)allocates memory
static tVoid MemZero(tVoid *pDest, tSize nCount)
Sets the data of a buffer to zero.
tVoid * GetPtr() const
Get a pointer to the allocated memory.
tSize GetSize() const
Get the amount of allocated memory in bytes.
#define tFalse
Value for tBool.
Definition: constants.h:60
#define tTrue
Value for tBool.
Definition: constants.h:62
ADTF A_UTIL Namespace - Within adtf this is used as adtf::util or adtf_util.
Definition: d_ptr.h:11
This struct store information about an item in the buffer.
ADDITIONAL_DATA xAdditional
additional bookkeeping data
tSize nSize
The size of the items data.
tFilePos nFilePos
The file position of the items data.
Helper struct to store an item that is made up by multiple data buffers.
const tVoid * pData
The data of the piece.
tSize nDataSize
The size of the piece.