AMPS C/C++ Client Class Reference AMPS C/C++ Client Version 5.3.5.6

MMapStoreBuffer.hpp
Go to the documentation of this file.
1 //
3 // Copyright (c) 2010-2026 60East Technologies Inc., All Rights Reserved.
4 //
5 // This computer software is owned by 60East Technologies Inc. and is
6 // protected by U.S. copyright laws and other laws and by international
7 // treaties. This computer software is furnished by 60East Technologies
8 // Inc. pursuant to a written license agreement and may be used, copied,
9 // transmitted, and stored only in accordance with the terms of such
10 // license agreement and with the inclusion of the above copyright notice.
11 // This computer software or any other copies thereof may not be provided
12 // or otherwise made available to any other person.
13 //
14 // U.S. Government Restricted Rights. This computer software: (a) was
15 // developed at private expense and is in all respects the proprietary
16 // information of 60East Technologies Inc.; (b) was not developed with
17 // government funds; (c) is a trade secret of 60East Technologies Inc.
18 // for all purposes of the Freedom of Information Act; and (d) is a
19 // commercial item and thus, pursuant to Section 12.212 of the Federal
20 // Acquisition Regulations (FAR) and DFAR Supplement Section 227.7202,
21 // Government's use, duplication or disclosure of the computer software
22 // is subject to the restrictions set forth by 60East Technologies Inc..
23 //
25
26 #ifndef _MMAPSTOREBUFFER_H_
27 #define _MMAPSTOREBUFFER_H_
28
29 #include <amps/ampsplusplus.hpp>
30 #include <amps/MemoryStoreBuffer.hpp>
31 #include <string>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #ifdef _WIN32
36 #include <windows.h>
37 #else
38 #include <sys/mman.h>
39 #endif
40
43
44
45 namespace AMPS
46 {
49 class MMapStoreBuffer : public MemoryStoreBuffer
50 {
51 public:
58 #ifdef _WIN32
59 MMapStoreBuffer(const std::string& fileName_,
60 size_t initialSize_ = AMPS_MEMORYBUFFER_DEFAULT_LENGTH)
61 : MemoryStoreBuffer(MemoryStoreBuffer::EMPTY)
62 , _mapFile(INVALID_HANDLE_VALUE), _file(INVALID_HANDLE_VALUE)
63 {
64 _file = CreateFileA(fileName_.c_str(), GENERIC_READ | GENERIC_WRITE, 0,
65 NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
66 if ( _file == INVALID_HANDLE_VALUE )
67 {
68 std::ostringstream os;
69 os << "Failed to create file " << fileName_ << " for MMapStoreBuffer";
70 error(os.str());
71 }
72 LARGE_INTEGER liFileSize;
73 if (GetFileSizeEx(_file, &liFileSize) == 0)
74 {
75 std::ostringstream os;
76 os << "Failure getting file size of " << fileName_ << " for MMapStoreBuffer";
77 error(os.str());
78 }
79 #ifdef _WIN64
80 size_t fileSize = liFileSize.QuadPart;
81 #else
82 size_t fileSize = liFileSize.LowPart;
83 #endif
84 _setSize( initialSize_ > fileSize ?
85 initialSize_ : fileSize);
86 }
87 #else
88 MMapStoreBuffer(const std::string& fileName_,
89 size_t initialSize_ = AMPS_MEMORYBUFFER_DEFAULT_LENGTH)
90 : MemoryStoreBuffer(MemoryStoreBuffer::EMPTY)
91 {
92 _fd = ::open(fileName_.c_str(), O_CREAT | O_RDWR, (mode_t)0644);
93 struct stat statBuf;
94 memset(&statBuf, 0, sizeof(statBuf));
95 if (fstat(_fd, &statBuf) == -1)
96 {
97 std::ostringstream os;
98 os << "Failed to stat file " << fileName_ << " for MMapStoreBuffer";
99 error(os.str());
100 }
101 bool recovery = (size_t)statBuf.st_size >= initialSize_;
102 _setSize(recovery ? (size_t)statBuf.st_size
103 : initialSize_,
104 recovery);
105 }
106 #endif
107
108 ~MMapStoreBuffer()
109 {
110 if (_buffer)
111 {
112 close();
113 }
114 }
115
116 void close()
117 {
118 sync();
119 #ifdef _WIN32
120 FlushFileBuffers(_file);
121 UnmapViewOfFile(_buffer);
122 CloseHandle(_mapFile);
123 CloseHandle(_file);
124 _mapFile = INVALID_HANDLE_VALUE;
125 _file = INVALID_HANDLE_VALUE;
126 #else
127 munmap(_buffer, _bufferLen);
128 ::close(_fd);
129 _fd = 0;
130 #endif
131 _buffer = NULL;
132 _bufferLen = 0;
133 }
134
135 void sync()
136 {
137 if (_buffer != NULL && _bufferLen)
138 {
139 #ifdef _WIN32
140 if (!FlushViewOfFile(_buffer, _bufferPos))
141 #else
142 if (msync(_buffer, _bufferPos, MS_ASYNC) != 0)
143 #endif
144 {
145 std::ostringstream os;
146 os << "Failed to sync mapped memory; buffer: " << (size_t)_buffer
147 << " pos: " << _bufferPos;
148 error(os.str());
149 }
150 }
151 }
152
153 virtual void setSize(size_t newSize_)
154 {
155 _setSize(newSize_);
156 }
157
158 void _setSize(size_t newSize_, bool recovery_ = false)
159 {
160 if (_bufferLen > 0)
161 {
162 sync();
163 }
164 // Make sure we're using a multiple of page size
165 static const size_t pageSize = getPageSize(); // -V1096
166 size_t sz = (newSize_ + pageSize - 1) / pageSize * pageSize;
167 #ifdef _WIN32
168 if (_mapFile != INVALID_HANDLE_VALUE && _mapFile != NULL)
169 {
170 FlushFileBuffers(_file);
171 UnmapViewOfFile(_buffer);
172 CloseHandle(_mapFile);
173 }
174 #ifdef _WIN64
175 _mapFile = CreateFileMapping( _file, NULL, PAGE_READWRITE, (DWORD)((sz >> 32) & 0xffffffff), (DWORD)sz, NULL);
176 #else
177 _mapFile = CreateFileMapping( _file, NULL, PAGE_READWRITE, 0, (DWORD)sz, NULL);
178 #endif
179 if (_mapFile == INVALID_HANDLE_VALUE || _mapFile == NULL)
180 {
181 _buffer = 0;
182 _bufferLen = 0;
183 error("Failed to create map of log file");
184 }
185 else
186 {
187 _buffer = (char*)MapViewOfFile(_mapFile, FILE_MAP_ALL_ACCESS, 0, 0, sz);
188 if (_buffer == NULL)
189 {
190 std::ostringstream os;
191 os << "Failed to map log file to memory; buffer: " << (size_t)_buffer << " length: " << sz << " previous size: " << _bufferLen;
192 _buffer = 0;
193 _bufferLen = 0;
194 error(os.str());
195 }
196 }
197 #else
198 // If not at current size, extend the underlying file
199 if (sz > _bufferLen)
200 {
201 if (lseek(_fd, (off_t)sz - 1, SEEK_SET) == -1)
202 {
203 std::ostringstream os;
204 os << "Seek failed for buffer extension; buffer: " << (size_t)_buffer
205 << " length: " << _bufferLen << " pos: " << _bufferPos
206 << " requested new size: " << newSize_;
207 error(os.str());
208 }
209 if (!recovery_)
210 {
211 if (::write(_fd, "", 1) == -1)
212 {
213 std::ostringstream os;
214 os << "Failed to grow buffer; buffer: " << (size_t)_buffer << " length: "
215 << _bufferLen << " pos: " << _bufferPos << " requested new size: "
216 << newSize_;
217 error(os.str());
218 }
219 }
220 }
221
222 void* result = NULL;
223 if (_buffer == NULL)
224 {
225 result = mmap(0, sz, PROT_WRITE | PROT_READ, MAP_SHARED, _fd, 0);
226 }
227 else if (_bufferLen < sz)
228 {
229 #if defined(linux)
230 result = mremap(_buffer, _bufferLen, sz, MREMAP_MAYMOVE);
231 #else
232 munmap(_buffer, _bufferLen);
233 result = mmap(0, sz, PROT_WRITE | PROT_READ, MAP_SHARED, _fd, 0);
234 #endif
235 }
236 if (result == MAP_FAILED || result == NULL)
237 {
238 std::ostringstream os;
239 os << "Failed to map log file to memory; buffer: "
240 << (size_t)_buffer << " length: " << sz
241 << " previous size: " << _bufferLen;
242 _buffer = 0;
243 _bufferLen = 0;
244 error(os.str());
245 }
246 else
247 {
248 _buffer = (char*)result;
249 }
250 #endif
251 if (_buffer)
252 {
253 _bufferLen = sz;
254 }
255 }
256
257 private:
258 void error(const std::string & message)
259 {
260 std::ostringstream os;
261 #ifdef _WIN32
262 const size_t errorBufferSize = 1024;
263 char errorBuffer[errorBufferSize];
264 memset(errorBuffer, 0, errorBufferSize);
265 strerror_s(errorBuffer, errorBufferSize, errno);
266 os << message << ". Error is " << errorBuffer;
267 #else
268 os << message << ". Error is " << strerror(errno);
269 #endif
270 throw StoreException(os.str());
271 }
272
273 #ifdef _WIN32
274 HANDLE _mapFile;
275 HANDLE _file;
276 #else
277 int _fd;
278 #endif
279 static size_t getPageSize()
280 {
281 static size_t pageSize; // -V1096
282 if (pageSize == 0)
283 {
284 #ifdef _WIN32
285 SYSTEM_INFO SYS_INFO;
286 GetSystemInfo(&SYS_INFO);
287 pageSize = SYS_INFO.dwPageSize;
288 #else
289 pageSize = (size_t)sysconf(_SC_PAGESIZE);
290 #endif
291 if (pageSize == (size_t)-1)
292 {
293 // Guess
294 pageSize = 4096;
295 }
296 }
297 return pageSize;
298 }
299
300 };
301
302 } // end namespace AMPS
303
304 #endif //_MMAPSTOREBUFFER_H_
305
MemoryStoreBuffer.hpp
Provides AMPS::MemoryStoreBuffer, used by an AMPS::HAClient to store messages in memory.
ampsplusplus.hpp
Core type, function, and class declarations for the AMPS C++ client.
AMPS::MMapStoreBuffer
A Buffer implementation that uses a memory mapped file as its storage.
Definition: MMapStoreBuffer.hpp:50
AMPS::MMapStoreBuffer::setSize
virtual void setSize(size_t newSize_)
Set the size for the buffer.
Definition: MMapStoreBuffer.hpp:153
AMPS::MMapStoreBuffer::MMapStoreBuffer
MMapStoreBuffer(const std::string &fileName_, size_t initialSize_=AMPS_MEMORYBUFFER_DEFAULT_LENGTH)
Create an MMapStoreBuffer using fileName_ as the name of the memory mapped file used for storage.
Definition: MMapStoreBuffer.hpp:88
AMPS::MemoryStoreBuffer
A Buffer implementation that uses memory for storage.
Definition: MemoryStoreBuffer.hpp:51