20 : m_writeBufferSize(50), m_writeBufferUsed(0), m_nObjectsToWrite(0), m_free(), m_free_bySize(m_free.get<1>()),
32 : m_writeBufferSize(m_writeBufferSize), m_writeBufferUsed(0), m_nObjectsToWrite(0), m_free(),
33 m_free_bySize(m_free.get<1>()), m_fileLength(0) {
55 std::unique_lock<std::mutex> uniqueLock(
m_mutex);
63 std::lock_guard<std::mutex> lock(
m_mutex);
86 std::unique_lock<std::mutex> uniqueLock(
m_mutex);
110 std::lock_guard<std::mutex> _lock(
m_mutex);
112 std::list<ISaveable *> couldNotWrite;
113 size_t objectsNotWritten(0);
114 size_t memoryNotWritten(0);
122 for (; it != it_end; ++it) {
124 if (!
obj->isBusy()) {
126 uint64_t fileIndexStart;
127 if (!
obj->wasSaved()) {
128 fileIndexStart = this->
allocate(NumObjEvents);
131 obj->saveAt(fileIndexStart, NumObjEvents);
133 uint64_t NumFileEvents =
obj->getFileSize();
134 if (NumObjEvents != NumFileEvents) {
140 obj->saveAt(fileIndexStart, NumObjEvents);
145 if (
obj->isDataChanged()) {
146 fileIndexStart =
obj->getFilePosition();
149 obj->saveAt(fileIndexStart, NumObjEvents);
155 obj->clearDataFromMemory();
159 obj->clearBufferState();
163 couldNotWrite.emplace_back(
obj);
168 memoryNotWritten +=
obj->setBufferPosition(--couldNotWrite.end());
205 if (size == 0 || size == std::numeric_limits<uint64_t>::max())
212 std::pair<freeSpace_t::iterator, bool> p =
m_free.insert(newBlock);
217 if (!p.second ||
m_free.size() <= 1) {
222 freeSpace_t::iterator it = p.first;
223 if (it !=
m_free.begin()) {
224 freeSpace_t::iterator it_before = it;
231 m_free.replace(it_before, block_before);
235 newBlock = block_before;
240 freeSpace_t::iterator it_after = it;
243 if (it_after !=
m_free.end()) {
247 m_free.replace(it, newBlock);
262 freeSpace_t::iterator it =
m_free.begin();
266 while (it !=
m_free.end()) {
268 freeSpace_t::iterator it_after = it;
274 m_free.replace(it, thisBlock);
294 std::unique_lock<std::mutex> uniqueLock(
m_freeMutex);
297 freeSpace_bySize_t::iterator it;
298 bool putAtFileEnd =
true;
315 uint64_t foundPos = it->getFilePosition();
316 uint64_t foundSize = it->getSize();
321 if (foundSize > newSize) {
322 this->
freeBlock(foundPos + newSize, foundSize - newSize);
352 free.reserve(
m_free.size() * 2);
353 freeSpace_bySize_t::const_iterator it =
m_free_bySize.begin();
354 freeSpace_bySize_t::const_iterator it_end =
m_free_bySize.end();
355 for (; it != it_end; ++it) {
356 free.emplace_back(it->getFilePosition());
357 free.emplace_back(it->getSize());
366 if (free.size() % 2 != 0)
367 throw std::length_error(
"Free vector size is not a factor of 2.");
369 for (
auto it = free.begin(); it != free.end(); it += 2) {
370 auto it_next = std::next(it);
372 if (*it == 0 && *it_next == 0) {
383 std::ostringstream mess;
double obj
the value of the quadratic function
std::mutex m_freeMutex
Mutex for modifying the free space list.
void freeBlock(uint64_t const pos, uint64_t const size)
This method is called by this->relocate when object that has shrunk and so has left a bit of free spa...
uint64_t relocate(uint64_t const oldPos, uint64_t const oldSize, const uint64_t newSize)
This method is called by an ISaveable object that has outgrown its space allocated on file and needs ...
std::list< ISaveable * > m_toWriteBuffer
A forward list for the buffer of "toWrite" objects.
uint64_t allocate(uint64_t const newSize)
Allocate a block of the given size in a free spot in the file, or at the end of the file if there is ...
void toWrite(ISaveable *item)
Call this method when an object is ready to be written out to disk.
uint64_t m_fileLength
Length of the file. This is where new blocks that don't fit get placed.
size_t m_writeBufferUsed
Total amount of memory in the "toWrite" buffer.
void defragFreeBlocks()
Method that defrags free blocks by combining adjacent ones together NOTE: This is not necessary to ru...
void flushCache()
Flush out all the data in the memory; and writes out everything in the to-write cache.
size_t m_nObjectsToWrite
number of objects stored in to write buffer list
void getFreeSpaceVector(std::vector< uint64_t > &free) const
Returns a vector with two entries per free block: position and size.
void setFreeSpaceVector(std::vector< uint64_t > const &free)
Sets the free space map.
void objectDeleted(ISaveable *item)
Call this method when an object that might be in the cache is getting deleted.
freeSpace_bySize_t & m_free_bySize
Index into m_free, but indexed by block size.
size_t m_writeBufferSize
Do we use the write buffer? Always now.
void writeOldObjects()
Method to write out the old objects that have been stored in the "toWrite" buffer.
std::string getMemoryStr() const
std::mutex m_mutex
Mutex for modifying the toWrite buffer.
freeSpace_t m_free
Map of the free blocks in the file.
FreeBlock: a simple class that holds the position and size of block of free space in a file.
static bool merge(FreeBlock &first, const FreeBlock &second)
Attempt to merge an adjacent block into this one.
An interface for objects that can be cached or saved to disk.
void clearBufferState()
clears the state of the object, and indicate that it is not stored in buffer any more
void setBufferSize(size_t newSize)
virtual uint64_t getFilePosition() const
size_t setBufferPosition(std::list< ISaveable * >::iterator bufPosition)
sets the iterator pointing to the location of this object in the memory buffer to write later
uint64_t getFileSize() const
Return the number of units this block occipies on file.
std::optional< std::list< ISaveable * >::iterator > & getBufPostion()
returns the iterator pointing to the position of this object within the memory to-write buffer
virtual uint64_t getTotalDataSize() const =0
size_t getBufferSize() const
return the amount of memory, this object had when it was stored in buffer last time;
virtual size_t getDataMemorySize() const =0
the data size kept in memory