26 #ifndef _MMAPSTOREBUFFER_H_ 27 #define _MMAPSTOREBUFFER_H_ 33 #include <sys/types.h> 65 size_t initialSize_ = AMPS_MEMORYBUFFER_DEFAULT_LENGTH,
66 size_t sizeAlignment_ = 1,
67 bool useStoredSizeAlignment_ =
false)
69 , _sizeAlignment(sizeAlignment_ ? sizeAlignment_ : 1)
70 , _mapFile(INVALID_HANDLE_VALUE), _file(INVALID_HANDLE_VALUE)
74 if (initialSize_ == 0)
76 initialSize_ = AMPS_MEMORYBUFFER_DEFAULT_LENGTH;
78 _file = CreateFileA(fileName_.c_str(), GENERIC_READ | GENERIC_WRITE, 0,
79 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
80 if ( _file == INVALID_HANDLE_VALUE )
82 std::ostringstream os;
83 os <<
"Failed to create file " << fileName_ <<
" for MMapStoreBuffer";
86 LARGE_INTEGER liFileSize;
87 if (GetFileSizeEx(_file, &liFileSize) == 0)
89 std::ostringstream os;
90 os <<
"Failure getting file size of " << fileName_ <<
" for MMapStoreBuffer";
94 size_t fileSize = liFileSize.QuadPart;
96 size_t fileSize = liFileSize.LowPart;
98 setStoredSizeAlignment(fileName_, fileSize,
99 useStoredSizeAlignment_);
100 _setSize( initialSize_ > fileSize ?
101 initialSize_ : fileSize);
105 closeOnConstructionError();
111 size_t initialSize_ = AMPS_MEMORYBUFFER_DEFAULT_LENGTH,
112 size_t sizeAlignment_ = 1,
113 bool useStoredSizeAlignment_ =
false)
115 , _sizeAlignment(sizeAlignment_ ? sizeAlignment_ : 1)
120 if (initialSize_ == 0)
122 initialSize_ = AMPS_MEMORYBUFFER_DEFAULT_LENGTH;
124 _fd = ::open(fileName_.c_str(), O_CREAT | O_RDWR, (mode_t)0644);
126 memset(&statBuf, 0,
sizeof(statBuf));
127 if (fstat(_fd, &statBuf) == -1)
129 std::ostringstream os;
130 os <<
"Failed to stat file " << fileName_ <<
" for MMapStoreBuffer";
133 bool recovery = (size_t)statBuf.st_size >= initialSize_;
134 setStoredSizeAlignment(fileName_, (
size_t)statBuf.st_size,
135 useStoredSizeAlignment_);
136 _setSize(recovery ? (
size_t)statBuf.st_size
142 closeOnConstructionError();
160 FlushFileBuffers(_file);
161 UnmapViewOfFile(_buffer);
162 CloseHandle(_mapFile);
164 _mapFile = INVALID_HANDLE_VALUE;
165 _file = INVALID_HANDLE_VALUE;
167 munmap(_buffer, _bufferLen);
177 if (_buffer != NULL && _bufferLen)
180 if (!FlushViewOfFile(_buffer, _bufferPos))
182 if (msync(_buffer, _bufferPos, MS_ASYNC) != 0)
185 std::ostringstream os;
186 os <<
"Failed to sync mapped memory; buffer: " << (size_t)_buffer
187 <<
" pos: " << _bufferPos;
202 const size_t alignment = sizeAlignment_ ? sizeAlignment_ : 1;
203 if (_sizeAlignment == alignment)
207 const size_t alignedSize = getMappedSize(_bufferLen, alignment);
208 _sizeAlignment = alignment;
209 if (_bufferLen && alignedSize != _bufferLen)
211 _setSize(alignedSize);
215 void _setSize(
size_t newSize_,
bool recovery_ =
false)
223 size_t sz = getMappedSize(newSize_);
225 if (_mapFile != INVALID_HANDLE_VALUE && _mapFile != NULL)
227 FlushFileBuffers(_file);
228 UnmapViewOfFile(_buffer);
229 CloseHandle(_mapFile);
232 _mapFile = CreateFileMapping( _file, NULL, PAGE_READWRITE, (DWORD)((sz >> 32) & 0xffffffff), (DWORD)sz, NULL);
234 _mapFile = CreateFileMapping( _file, NULL, PAGE_READWRITE, 0, (DWORD)sz, NULL);
236 if (_mapFile == INVALID_HANDLE_VALUE || _mapFile == NULL)
240 error(
"Failed to create map of log file");
244 _buffer = (
char*)MapViewOfFile(_mapFile, FILE_MAP_ALL_ACCESS, 0, 0, sz);
247 std::ostringstream os;
248 os <<
"Failed to map log file to memory; buffer: " << (size_t)_buffer <<
" length: " << sz <<
" previous size: " << _bufferLen;
258 if (lseek(_fd, (off_t)sz - 1, SEEK_SET) == -1)
260 std::ostringstream os;
261 os <<
"Seek failed for buffer extension; buffer: " << (size_t)_buffer
262 <<
" length: " << _bufferLen <<
" pos: " << _bufferPos
263 <<
" requested new size: " << newSize_;
266 if (!recovery_ || sz > newSize_)
268 if (::write(_fd,
"", 1) == -1)
270 std::ostringstream os;
271 os <<
"Failed to grow buffer; buffer: " << (size_t)_buffer <<
" length: " 272 << _bufferLen <<
" pos: " << _bufferPos <<
" requested new size: " 282 result = mmap(0, sz, PROT_WRITE | PROT_READ, MAP_SHARED, _fd, 0);
284 else if (_bufferLen < sz)
287 result = mremap(_buffer, _bufferLen, sz, MREMAP_MAYMOVE);
289 munmap(_buffer, _bufferLen);
290 result = mmap(0, sz, PROT_WRITE | PROT_READ, MAP_SHARED, _fd, 0);
293 if (result == MAP_FAILED || result == NULL)
295 std::ostringstream os;
296 os <<
"Failed to map log file to memory; buffer: " 297 << (size_t)_buffer <<
" length: " << sz
298 <<
" previous size: " << _bufferLen;
305 _buffer = (
char*)result;
315 void setStoredSizeAlignment(
const std::string& fileName_,
size_t fileSize_,
316 bool useStoredSizeAlignment_)
318 if (!useStoredSizeAlignment_
319 || fileSize_ <
sizeof(amps_uint32_t))
323 amps_uint32_t storedSizeAlignment = 0;
325 LARGE_INTEGER beginning;
326 beginning.QuadPart = 0;
328 const DWORD alignmentSize = (DWORD)
sizeof(storedSizeAlignment);
329 bool readFailed = !SetFilePointerEx(_file, beginning, NULL, FILE_BEGIN)
330 || !ReadFile(_file, &storedSizeAlignment,
331 alignmentSize, &bytesRead, NULL)
332 || bytesRead != alignmentSize;
334 bool readFailed = pread(_fd, &storedSizeAlignment,
335 sizeof(storedSizeAlignment), 0)
336 != (ssize_t)
sizeof(storedSizeAlignment);
340 std::ostringstream os;
341 os <<
"Failure reading size alignment from " << fileName_
342 <<
" for MMapStoreBuffer";
345 if (storedSizeAlignment > 1)
347 if ((
size_t)storedSizeAlignment > fileSize_)
349 throw StoreException(
350 "MMapStoreBuffer contains an invalid size alignment.");
352 _sizeAlignment = storedSizeAlignment;
356 void closeOnConstructionError()
361 UnmapViewOfFile(_buffer);
363 if (_mapFile != INVALID_HANDLE_VALUE && _mapFile != NULL)
365 CloseHandle(_mapFile);
367 if (_file != INVALID_HANDLE_VALUE)
371 _mapFile = INVALID_HANDLE_VALUE;
372 _file = INVALID_HANDLE_VALUE;
376 munmap(_buffer, _bufferLen);
388 size_t getMappedSize(
size_t requestedSize_)
const 390 return getMappedSize(requestedSize_, _sizeAlignment);
393 size_t getMappedSize(
size_t requestedSize_,
size_t sizeAlignment_)
const 395 const size_t alignment = sizeAlignment_ > 1
396 ? sizeAlignment_ : getPageSize();
397 if (requestedSize_ > (std::numeric_limits<size_t>::max)()
400 throw StoreException(
"MMapStoreBuffer size overflow.");
402 return (requestedSize_ + alignment - 1) / alignment * alignment;
405 void error(
const std::string & message)
407 std::ostringstream os;
409 const size_t errorBufferSize = 1024;
410 char errorBuffer[errorBufferSize];
411 memset(errorBuffer, 0, errorBufferSize);
412 strerror_s(errorBuffer, errorBufferSize, errno);
413 os << message <<
". Error is " << errorBuffer;
415 os << message <<
". Error is " << strerror(errno);
417 throw StoreException(os.str());
420 size_t _sizeAlignment;
427 static size_t getPageSize()
429 static const size_t pageSize = queryPageSize();
433 static size_t queryPageSize()
437 SYSTEM_INFO SYS_INFO;
438 GetSystemInfo(&SYS_INFO);
439 pageSize = SYS_INFO.dwPageSize;
441 pageSize = (size_t)sysconf(_SC_PAGESIZE);
443 if (pageSize == (
size_t)-1)
455 #endif //_MMAPSTOREBUFFER_H_ virtual void setSize(size_t newSize_)
Set the size for the buffer.
Definition: MMapStoreBuffer.hpp:193
A Buffer implementation that uses memory for storage.
Definition: MemoryStoreBuffer.hpp:50
void setSizeAlignment(size_t sizeAlignment_)
Set the allocation-unit alignment for logical buffer sizes.
Definition: MMapStoreBuffer.hpp:200
Core type, function, and class declarations for the AMPS C++ client.
A Buffer implementation that uses a memory mapped file as its storage.
Definition: MMapStoreBuffer.hpp:50
Provides AMPS::MemoryStoreBuffer, used by an AMPS::HAClient to store messages in memory.
MMapStoreBuffer(const std::string &fileName_, size_t initialSize_=AMPS_MEMORYBUFFER_DEFAULT_LENGTH, size_t sizeAlignment_=1, bool useStoredSizeAlignment_=false)
Create an MMapStoreBuffer using fileName_ as the name of the memory mapped file used for storage...
Definition: MMapStoreBuffer.hpp:110
Definition: AMPSException.hpp:32