OmniSciDB  04ee39c94c
Buffer_Namespace::BufferMgr Class Referenceabstract

Note(s): Forbid Copying Idiom 4.1. More...

#include <BufferMgr.h>

+ Inheritance diagram for Buffer_Namespace::BufferMgr:
+ Collaboration diagram for Buffer_Namespace::BufferMgr:

Public Member Functions

 BufferMgr (const int deviceId, const size_t maxBufferSize, const size_t maxSlabSize=2147483648, const size_t pageSize=512, AbstractBufferMgr *parentMgr=0)
 Constructs a BufferMgr object that allocates memSize bytes. More...
 
 ~BufferMgr () override
 Destructor. More...
 
void reinit ()
 
void clear ()
 
std::string printSlab (size_t slabNum)
 
std::string printSlabs () override
 
void clearSlabs () override
 
std::string printMap ()
 
void printSegs ()
 
std::string printSeg (BufferList::iterator &segIt)
 
std::string keyToString (const ChunkKey &key)
 
size_t getInUseSize () override
 
size_t getMaxSize () override
 
size_t getAllocated () override
 
size_t getMaxBufferSize ()
 
size_t getMaxSlabSize ()
 
size_t getPageSize ()
 
bool isAllocationCapped () override
 
const std::vector< BufferList > & getSlabSegments ()
 
AbstractBuffercreateBuffer (const ChunkKey &key, const size_t pageSize=0, const size_t initialSize=0) override
 Creates a chunk with the specified key and page size. More...
 
void deleteBuffer (const ChunkKey &key, const bool purge=true) override
 Deletes the chunk with the specified key. More...
 
void deleteBuffersWithPrefix (const ChunkKey &keyPrefix, const bool purge=true) override
 
AbstractBuffergetBuffer (const ChunkKey &key, const size_t numBytes=0) override
 Returns the a pointer to the chunk with the specified key. More...
 
bool isBufferOnDevice (const ChunkKey &key) override
 Puts the contents of d into the Buffer with ChunkKey key. More...
 
void fetchBuffer (const ChunkKey &key, AbstractBuffer *destBuffer, const size_t numBytes=0) override
 
AbstractBufferputBuffer (const ChunkKey &key, AbstractBuffer *d, const size_t numBytes=0) override
 
void checkpoint () override
 
void checkpoint (const int db_id, const int tb_id) override
 
AbstractBufferalloc (const size_t numBytes=0) override
 client is responsible for deleting memory allocated for b->mem_ More...
 
void free (AbstractBuffer *buffer) override
 
size_t size ()
 Returns the total number of bytes allocated. More...
 
size_t getNumChunks () override
 
BufferList::iterator reserveBuffer (BufferList::iterator &segIt, const size_t numBytes)
 
void getChunkMetadataVec (std::vector< std::pair< ChunkKey, ChunkMetadata >> &chunkMetadataVec) override
 
void getChunkMetadataVecForKeyPrefix (std::vector< std::pair< ChunkKey, ChunkMetadata >> &chunkMetadataVec, const ChunkKey &keyPrefix) override
 

Protected Attributes

std::vector< int8_t * > slabs_
 
std::vector< BufferListslabSegments_
 
size_t pageSize_
 

Private Member Functions

 BufferMgr (const BufferMgr &)
 
BufferMgroperator= (const BufferMgr &)
 
void removeSegment (BufferList::iterator &segIt)
 
BufferList::iterator findFreeBufferInSlab (const size_t slabNum, const size_t numPagesRequested)
 
int getBufferId ()
 
virtual void addSlab (const size_t slabSize)=0
 
virtual void freeAllMem ()=0
 
virtual void allocateBuffer (BufferList::iterator segIt, const size_t pageSize, const size_t numBytes)=0
 
BufferList::iterator evict (BufferList::iterator &evictStart, const size_t numPagesRequested, const int slabNum)
 
BufferList::iterator findFreeBuffer (size_t numBytes)
 

Private Attributes

std::mutex chunkIndexMutex_
 
std::mutex sizedSegsMutex_
 
std::mutex unsizedSegsMutex_
 
std::mutex bufferIdMutex_
 
std::mutex globalMutex_
 
std::map< ChunkKey, BufferList::iterator > chunkIndex_
 
size_t maxBufferSize_
 
size_t maxNumPages_
 max number of bytes allocated for the buffer pool More...
 
size_t numPagesAllocated_
 
size_t maxNumPagesPerSlab_
 
size_t currentMaxSlabPageSize_
 
size_t maxSlabSize_
 
bool allocationsCapped_
 
AbstractBufferMgrparentMgr_
 
int maxBufferId_
 
unsigned int bufferEpoch_
 
BufferList unsizedSegs_
 Maps sizes of free memory areas to host buffer pool memory addresses. More...
 

Detailed Description

Note(s): Forbid Copying Idiom 4.1.

Definition at line 96 of file BufferMgr.h.

Constructor & Destructor Documentation

◆ BufferMgr() [1/2]

Buffer_Namespace::BufferMgr::BufferMgr ( const int  deviceId,
const size_t  maxBufferSize,
const size_t  maxSlabSize = 2147483648,
const size_t  pageSize = 512,
AbstractBufferMgr parentMgr = 0 
)

Constructs a BufferMgr object that allocates memSize bytes.

Allocates memSize bytes for the buffer pool and initializes the free memory map.

Definition at line 46 of file BufferMgr.cpp.

References CHECK, currentMaxSlabPageSize_, maxBufferSize_, maxNumPages_, maxNumPagesPerSlab_, maxSlabSize_, and pageSize_.

51  : AbstractBufferMgr(deviceId)
52  , pageSize_(pageSize)
53  , maxBufferSize_(maxBufferSize)
55  , maxSlabSize_(maxSlabSize)
56  , allocationsCapped_(false)
57  , parentMgr_(parentMgr)
58  , maxBufferId_(0)
59  , bufferEpoch_(0) {
60  CHECK(maxBufferSize_ > 0 && maxSlabSize_ > 0 && pageSize_ > 0 &&
61  maxSlabSize_ % pageSize_ == 0);
65  maxNumPagesPerSlab_; // currentMaxSlabPageSize_ will drop as allocations fail -
66  // this is the high water mark
67 }
AbstractBufferMgr * parentMgr_
Definition: BufferMgr.h:208
size_t maxNumPages_
max number of bytes allocated for the buffer pool
Definition: BufferMgr.h:201
#define CHECK(condition)
Definition: Logger.h:187

◆ ~BufferMgr()

Buffer_Namespace::BufferMgr::~BufferMgr ( )
override

Destructor.

Frees the heap-allocated buffer pool memory.

Definition at line 70 of file BufferMgr.cpp.

References clear().

70  {
71  clear();
72 }
+ Here is the call graph for this function:

◆ BufferMgr() [2/2]

Buffer_Namespace::BufferMgr::BufferMgr ( const BufferMgr )
private

Member Function Documentation

◆ addSlab()

virtual void Buffer_Namespace::BufferMgr::addSlab ( const size_t  slabSize)
privatepure virtual

Implemented in Buffer_Namespace::CpuBufferMgr, and Buffer_Namespace::GpuCudaBufferMgr.

Referenced by findFreeBuffer().

+ Here is the caller graph for this function:

◆ alloc()

AbstractBuffer * Buffer_Namespace::BufferMgr::alloc ( const size_t  numBytes = 0)
override

client is responsible for deleting memory allocated for b->mem_

Definition at line 839 of file BufferMgr.cpp.

References createBuffer(), getBufferId(), globalMutex_, and pageSize_.

839  {
840  std::lock_guard<std::mutex> lock(globalMutex_);
841  ChunkKey chunkKey = {-1, getBufferId()};
842  return createBuffer(chunkKey, pageSize_, numBytes);
843 }
AbstractBuffer * createBuffer(const ChunkKey &key, const size_t pageSize=0, const size_t initialSize=0) override
Creates a chunk with the specified key and page size.
Definition: BufferMgr.cpp:97
std::vector< int > ChunkKey
Definition: types.h:35
+ Here is the call graph for this function:

◆ allocateBuffer()

virtual void Buffer_Namespace::BufferMgr::allocateBuffer ( BufferList::iterator  segIt,
const size_t  pageSize,
const size_t  numBytes 
)
privatepure virtual

Implemented in Buffer_Namespace::CpuBufferMgr, and Buffer_Namespace::GpuCudaBufferMgr.

Referenced by createBuffer().

+ Here is the caller graph for this function:

◆ checkpoint() [1/2]

void Buffer_Namespace::BufferMgr::checkpoint ( )
override

Definition at line 664 of file BufferMgr.cpp.

References chunkIndex_, chunkIndexMutex_, globalMutex_, and parentMgr_.

664  {
665  std::lock_guard<std::mutex> lock(globalMutex_); // granular lock
666  std::lock_guard<std::mutex> chunkIndexLock(chunkIndexMutex_);
667 
668  for (auto bufferIt = chunkIndex_.begin(); bufferIt != chunkIndex_.end(); ++bufferIt) {
669  if (bufferIt->second->chunkKey[0] != -1 &&
670  bufferIt->second->buffer->isDirty_) { // checks that buffer is actual chunk (not
671  // just buffer) and is dirty
672 
673  parentMgr_->putBuffer(bufferIt->second->chunkKey, bufferIt->second->buffer);
674  bufferIt->second->buffer->clearDirtyBits();
675  }
676  }
677 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
AbstractBufferMgr * parentMgr_
Definition: BufferMgr.h:208

◆ checkpoint() [2/2]

void Buffer_Namespace::BufferMgr::checkpoint ( const int  db_id,
const int  tb_id 
)
override

Definition at line 679 of file BufferMgr.cpp.

References chunkIndex_, chunkIndexMutex_, globalMutex_, and parentMgr_.

679  {
680  std::lock_guard<std::mutex> lock(globalMutex_); // granular lock
681  std::lock_guard<std::mutex> chunkIndexLock(chunkIndexMutex_);
682 
683  ChunkKey keyPrefix;
684  keyPrefix.push_back(db_id);
685  keyPrefix.push_back(tb_id);
686  auto startChunkIt = chunkIndex_.lower_bound(keyPrefix);
687  if (startChunkIt == chunkIndex_.end()) {
688  return;
689  }
690 
691  auto bufferIt = startChunkIt;
692  while (bufferIt != chunkIndex_.end() &&
693  std::search(bufferIt->first.begin(),
694  bufferIt->first.begin() + keyPrefix.size(),
695  keyPrefix.begin(),
696  keyPrefix.end()) != bufferIt->first.begin() + keyPrefix.size()) {
697  if (bufferIt->second->chunkKey[0] != -1 &&
698  bufferIt->second->buffer->isDirty_) { // checks that buffer is actual chunk (not
699  // just buffer) and is dirty
700 
701  parentMgr_->putBuffer(bufferIt->second->chunkKey, bufferIt->second->buffer);
702  bufferIt->second->buffer->clearDirtyBits();
703  }
704  bufferIt++;
705  }
706 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
AbstractBufferMgr * parentMgr_
Definition: BufferMgr.h:208
std::vector< int > ChunkKey
Definition: types.h:35

◆ clear()

void Buffer_Namespace::BufferMgr::clear ( )

Definition at line 82 of file BufferMgr.cpp.

References bufferEpoch_, chunkIndex_, chunkIndexMutex_, sizedSegsMutex_, slabs_, slabSegments_, unsizedSegs_, and unsizedSegsMutex_.

Referenced by clearSlabs(), and ~BufferMgr().

82  {
83  std::lock_guard<std::mutex> sizedSegsLock(sizedSegsMutex_);
84  std::lock_guard<std::mutex> chunkIndexLock(chunkIndexMutex_);
85  std::lock_guard<std::mutex> unsizedSegsLock(unsizedSegsMutex_);
86  for (auto bufferIt = chunkIndex_.begin(); bufferIt != chunkIndex_.end(); ++bufferIt) {
87  delete bufferIt->second->buffer;
88  }
89  chunkIndex_.clear();
90  slabs_.clear();
91  slabSegments_.clear();
92  unsizedSegs_.clear();
93  bufferEpoch_ = 0;
94 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
BufferList unsizedSegs_
Maps sizes of free memory areas to host buffer pool memory addresses.
Definition: BufferMgr.h:216
std::vector< int8_t * > slabs_
Definition: BufferMgr.h:176
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
+ Here is the caller graph for this function:

◆ clearSlabs()

void Buffer_Namespace::BufferMgr::clearSlabs ( )
override

Definition at line 460 of file BufferMgr.cpp.

References clear(), deleteBuffer(), Buffer_Namespace::FREE, freeAllMem(), reinit(), and slabSegments_.

460  {
461  bool pinnedExists = false;
462  size_t numSlabs = slabSegments_.size();
463  for (size_t slabNum = 0; slabNum != numSlabs; ++slabNum) {
464  for (auto segIt = slabSegments_[slabNum].begin();
465  segIt != slabSegments_[slabNum].end();
466  ++segIt) {
467  if (segIt->memStatus == FREE) {
468  // no need to free
469  } else if (segIt->buffer->getPinCount() < 1) {
470  deleteBuffer(segIt->chunkKey, true);
471  } else {
472  pinnedExists = true;
473  }
474  }
475  }
476  if (!pinnedExists) {
477  // lets actually clear the buffer from memory
478  freeAllMem();
479  clear();
480  reinit();
481  }
482 }
void deleteBuffer(const ChunkKey &key, const bool purge=true) override
Deletes the chunk with the specified key.
Definition: BufferMgr.cpp:585
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
virtual void freeAllMem()=0
+ Here is the call graph for this function:

◆ createBuffer()

AbstractBuffer * Buffer_Namespace::BufferMgr::createBuffer ( const ChunkKey key,
const size_t  pageSize = 0,
const size_t  initialSize = 0 
)
override

Creates a chunk with the specified key and page size.

Throws a runtime_error if the Chunk already exists.

Definition at line 97 of file BufferMgr.cpp.

References allocateBuffer(), CHECK, chunkIndex_, chunkIndexMutex_, deleteBuffer(), pageSize_, unsizedSegs_, unsizedSegsMutex_, and Buffer_Namespace::USED.

Referenced by alloc(), fetchBuffer(), getBuffer(), and putBuffer().

99  {
100  // LOG(INFO) << printMap();
101  size_t actualChunkPageSize = chunkPageSize;
102  if (actualChunkPageSize == 0) {
103  actualChunkPageSize = pageSize_;
104  }
105 
106  // ChunkPageSize here is just for recording dirty pages
107  {
108  std::lock_guard<std::mutex> lock(chunkIndexMutex_);
109  CHECK(chunkIndex_.find(chunkKey) == chunkIndex_.end());
110  BufferSeg bufferSeg(BufferSeg(-1, 0, USED));
111  bufferSeg.chunkKey = chunkKey;
112  std::lock_guard<std::mutex> unsizedSegsLock(unsizedSegsMutex_);
113  unsizedSegs_.push_back(bufferSeg); // race condition?
114  chunkIndex_[chunkKey] =
115  std::prev(unsizedSegs_.end(),
116  1); // need to do this before allocating Buffer because doing so could
117  // change the segment used
118  }
119  // following should be safe outside the lock b/c first thing Buffer
120  // constructor does is pin (and its still in unsized segs at this point
121  // so can't be evicted)
122  try {
123  allocateBuffer(chunkIndex_[chunkKey], actualChunkPageSize, initialSize);
124  } catch (const OutOfMemory&) {
125  auto bufferIt = chunkIndex_.find(chunkKey);
126  CHECK(bufferIt != chunkIndex_.end());
127  bufferIt->second->buffer =
128  0; // constructor failed for the buffer object so make sure to mark it zero so
129  // deleteBuffer doesn't try to delete it
130  deleteBuffer(chunkKey);
131  throw;
132  }
133  CHECK(initialSize == 0 || chunkIndex_[chunkKey]->buffer->getMemoryPtr());
134  // chunkIndex_[chunkKey]->buffer->pin();
135  std::lock_guard<std::mutex> lock(chunkIndexMutex_);
136  return chunkIndex_[chunkKey]->buffer;
137 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
BufferList unsizedSegs_
Maps sizes of free memory areas to host buffer pool memory addresses.
Definition: BufferMgr.h:216
virtual void allocateBuffer(BufferList::iterator segIt, const size_t pageSize, const size_t numBytes)=0
#define CHECK(condition)
Definition: Logger.h:187
void deleteBuffer(const ChunkKey &key, const bool purge=true) override
Deletes the chunk with the specified key.
Definition: BufferMgr.cpp:585
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ deleteBuffer()

void Buffer_Namespace::BufferMgr::deleteBuffer ( const ChunkKey key,
const bool  purge = true 
)
override

Deletes the chunk with the specified key.

This method throws a runtime_error when deleting a Chunk that does not exist.

Definition at line 585 of file BufferMgr.cpp.

References CHECK, chunkIndex_, chunkIndexMutex_, removeSegment(), and sizedSegsMutex_.

Referenced by clearSlabs(), createBuffer(), and free().

585  {
586  std::unique_lock<std::mutex> chunkIndexLock(chunkIndexMutex_);
587  // Note: purge is currently unused
588 
589  // lookup the buffer for the Chunk in chunkIndex_
590  auto bufferIt = chunkIndex_.find(key);
591  // Buffer *buffer = bufferIt->second->buffer;
592  CHECK(bufferIt != chunkIndex_.end());
593  auto segIt = bufferIt->second;
594  chunkIndex_.erase(bufferIt);
595  chunkIndexLock.unlock();
596  std::lock_guard<std::mutex> sizedSegsLock(sizedSegsMutex_);
597  if (segIt->buffer) {
598  delete segIt->buffer; // Delete Buffer for segment
599  segIt->buffer = 0;
600  }
601  removeSegment(segIt);
602 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
void removeSegment(BufferList::iterator &segIt)
Definition: BufferMgr.cpp:633
#define CHECK(condition)
Definition: Logger.h:187
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ deleteBuffersWithPrefix()

void Buffer_Namespace::BufferMgr::deleteBuffersWithPrefix ( const ChunkKey keyPrefix,
const bool  purge = true 
)
override

Definition at line 604 of file BufferMgr.cpp.

References chunkIndex_, chunkIndexMutex_, removeSegment(), and sizedSegsMutex_.

604  {
605  // Note: purge is unused
606  // lookup the buffer for the Chunk in chunkIndex_
607  std::lock_guard<std::mutex> sizedSegsLock(
608  sizedSegsMutex_); // Take this lock early to prevent deadlock with
609  // reserveBuffer which needs segsMutex_ and then
610  // chunkIndexMutex_
611  std::lock_guard<std::mutex> chunkIndexLock(chunkIndexMutex_);
612  auto startChunkIt = chunkIndex_.lower_bound(keyPrefix);
613  if (startChunkIt == chunkIndex_.end()) {
614  return;
615  }
616 
617  auto bufferIt = startChunkIt;
618  while (bufferIt != chunkIndex_.end() &&
619  std::search(bufferIt->first.begin(),
620  bufferIt->first.begin() + keyPrefix.size(),
621  keyPrefix.begin(),
622  keyPrefix.end()) != bufferIt->first.begin() + keyPrefix.size()) {
623  auto segIt = bufferIt->second;
624  if (segIt->buffer) {
625  delete segIt->buffer; // Delete Buffer for segment
626  segIt->buffer = 0;
627  }
628  removeSegment(segIt);
629  chunkIndex_.erase(bufferIt++);
630  }
631 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
void removeSegment(BufferList::iterator &segIt)
Definition: BufferMgr.cpp:633
+ Here is the call graph for this function:

◆ evict()

BufferList::iterator Buffer_Namespace::BufferMgr::evict ( BufferList::iterator &  evictStart,
const size_t  numPagesRequested,
const int  slabNum 
)
private

Definition at line 139 of file BufferMgr.cpp.

References bufferEpoch_, CHECK, chunkIndex_, Buffer_Namespace::FREE, Buffer_Namespace::BufferSeg::slabNum, slabSegments_, and Buffer_Namespace::USED.

Referenced by findFreeBuffer().

141  {
142  // We can assume here that buffer for evictStart either doesn't exist
143  // (evictStart is first buffer) or was not free, so don't need ot merge
144  // it
145  auto evictIt = evictStart;
146  size_t numPages = 0;
147  size_t startPage = evictStart->startPage;
148  while (numPages < numPagesRequested) {
149  if (evictIt->memStatus == USED) {
150  CHECK(evictIt->buffer->getPinCount() < 1);
151  }
152  numPages += evictIt->numPages;
153  if (evictIt->memStatus == USED && evictIt->chunkKey.size() > 0) {
154  chunkIndex_.erase(evictIt->chunkKey);
155  }
156  evictIt = slabSegments_[slabNum].erase(
157  evictIt); // erase operations returns next iterator - safe if we ever move
158  // to a vector (as opposed to erase(evictIt++)
159  }
160  BufferSeg dataSeg(startPage, numPagesRequested, USED, bufferEpoch_++); // until we can
161  // dataSeg.pinCount++;
162  dataSeg.slabNum = slabNum;
163  auto dataSegIt =
164  slabSegments_[slabNum].insert(evictIt, dataSeg); // Will insert before evictIt
165  if (numPagesRequested < numPages) {
166  size_t excessPages = numPages - numPagesRequested;
167  if (evictIt != slabSegments_[slabNum].end() &&
168  evictIt->memStatus == FREE) { // need to merge with current page
169  evictIt->startPage = startPage + numPagesRequested;
170  evictIt->numPages += excessPages;
171  } else { // need to insert a free seg before evictIt for excessPages
172  BufferSeg freeSeg(startPage + numPagesRequested, excessPages, FREE);
173  slabSegments_[slabNum].insert(evictIt, freeSeg);
174  }
175  }
176  return dataSegIt;
177 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
#define CHECK(condition)
Definition: Logger.h:187
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
+ Here is the caller graph for this function:

◆ fetchBuffer()

void Buffer_Namespace::BufferMgr::fetchBuffer ( const ChunkKey key,
AbstractBuffer destBuffer,
const size_t  numBytes = 0 
)
override

Definition at line 743 of file BufferMgr.cpp.

References CHECK, chunkIndex_, chunkIndexMutex_, createBuffer(), logger::FATAL, Data_Namespace::AbstractBuffer::getDeviceId(), Data_Namespace::AbstractBuffer::getMemoryPtr(), Data_Namespace::AbstractBuffer::getType(), globalMutex_, Data_Namespace::AbstractBuffer::isUpdated(), keyToString(), LOG, pageSize_, parentMgr_, Data_Namespace::AbstractBuffer::pin(), Data_Namespace::AbstractBuffer::read(), Data_Namespace::AbstractBuffer::reserve(), Data_Namespace::AbstractBuffer::setSize(), Data_Namespace::AbstractBuffer::size(), sizedSegsMutex_, Data_Namespace::AbstractBuffer::syncEncoder(), and Data_Namespace::AbstractBuffer::unPin().

745  {
746  std::unique_lock<std::mutex> lock(globalMutex_); // granular lock
747  std::unique_lock<std::mutex> sizedSegsLock(sizedSegsMutex_);
748  std::unique_lock<std::mutex> chunkIndexLock(chunkIndexMutex_);
749 
750  auto bufferIt = chunkIndex_.find(key);
751  bool foundBuffer = bufferIt != chunkIndex_.end();
752  chunkIndexLock.unlock();
753  AbstractBuffer* buffer;
754  if (!foundBuffer) {
755  sizedSegsLock.unlock();
756  CHECK(parentMgr_ != 0);
757  buffer = createBuffer(key, pageSize_, numBytes); // will pin buffer
758  try {
759  parentMgr_->fetchBuffer(key, buffer, numBytes);
760  } catch (std::runtime_error& error) {
761  LOG(FATAL) << "Could not fetch parent buffer " << keyToString(key);
762  }
763  } else {
764  buffer = bufferIt->second->buffer;
765  buffer->pin();
766  if (numBytes > buffer->size()) {
767  try {
768  parentMgr_->fetchBuffer(key, buffer, numBytes);
769  } catch (std::runtime_error& error) {
770  LOG(FATAL) << "Could not fetch parent buffer " << keyToString(key);
771  }
772  }
773  sizedSegsLock.unlock();
774  }
775  size_t chunkSize = numBytes == 0 ? buffer->size() : numBytes;
776  lock.unlock();
777  destBuffer->reserve(chunkSize);
778  if (buffer->isUpdated()) {
779  buffer->read(destBuffer->getMemoryPtr(),
780  chunkSize,
781  0,
782  destBuffer->getType(),
783  destBuffer->getDeviceId());
784  } else {
785  buffer->read(destBuffer->getMemoryPtr() + destBuffer->size(),
786  chunkSize - destBuffer->size(),
787  destBuffer->size(),
788  destBuffer->getType(),
789  destBuffer->getDeviceId());
790  }
791  destBuffer->setSize(chunkSize);
792  destBuffer->syncEncoder(buffer);
793  buffer->unPin();
794 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
AbstractBufferMgr * parentMgr_
Definition: BufferMgr.h:208
#define LOG(tag)
Definition: Logger.h:182
virtual size_t size() const =0
virtual int8_t * getMemoryPtr()=0
virtual MemoryLevel getType() const =0
virtual void reserve(size_t numBytes)=0
An AbstractBuffer is a unit of data management for a data manager.
virtual void read(int8_t *const dst, const size_t numBytes, const size_t offset=0, const MemoryLevel dstBufferType=CPU_LEVEL, const int dstDeviceId=-1)=0
virtual int getDeviceId() const
void setSize(const size_t size)
AbstractBuffer * createBuffer(const ChunkKey &key, const size_t pageSize=0, const size_t initialSize=0) override
Creates a chunk with the specified key and page size.
Definition: BufferMgr.cpp:97
#define CHECK(condition)
Definition: Logger.h:187
void syncEncoder(const AbstractBuffer *srcBuffer)
std::string keyToString(const ChunkKey &key)
Definition: BufferMgr.cpp:35
virtual bool isUpdated() const
+ Here is the call graph for this function:

◆ findFreeBuffer()

BufferList::iterator Buffer_Namespace::BufferMgr::findFreeBuffer ( size_t  numBytes)
private

Definition at line 264 of file BufferMgr.cpp.

References addSlab(), allocationsCapped_, currentMaxSlabPageSize_, logger::ERROR, evict(), measure< TimeT >::execution(), findFreeBufferInSlab(), logger::INFO, LOG, maxNumPages_, maxNumPagesPerSlab_, numPagesAllocated_, pageSize_, printSlabs(), slabSegments_, Buffer_Namespace::USED, and VLOG.

Referenced by reserveBuffer().

264  {
265  size_t numPagesRequested = (numBytes + pageSize_ - 1) / pageSize_;
266  if (numPagesRequested > maxNumPagesPerSlab_) {
267  throw TooBigForSlab(numBytes);
268  }
269 
270  size_t numSlabs = slabSegments_.size();
271 
272  for (size_t slabNum = 0; slabNum != numSlabs; ++slabNum) {
273  auto segIt = findFreeBufferInSlab(slabNum, numPagesRequested);
274  if (segIt != slabSegments_[slabNum].end()) {
275  return segIt;
276  }
277  }
278 
279  // If we're here then we didn't find a free segment of sufficient size
280  // First we see if we can add another slab
282  try {
283  size_t pagesLeft = maxNumPages_ - numPagesAllocated_;
284  if (pagesLeft < currentMaxSlabPageSize_) {
285  currentMaxSlabPageSize_ = pagesLeft;
286  }
287  if (numPagesRequested <= currentMaxSlabPageSize_) { // don't try to allocate if the
288  // new slab won't be big enough
289  auto alloc_ms =
291  LOG(INFO) << "ALLOCATION slab of " << currentMaxSlabPageSize_ << " pages ("
292  << currentMaxSlabPageSize_ * pageSize_ << "B) created in " << alloc_ms
293  << " ms " << getStringMgrType() << ":" << deviceId_;
294  } else {
295  break;
296  }
297  // if here then addSlab succeeded
298  numPagesAllocated_ += currentMaxSlabPageSize_;
299  return findFreeBufferInSlab(
300  numSlabs,
301  numPagesRequested); // has to succeed since we made sure to request a slab big
302  // enough to accomodate request
303  } catch (std::runtime_error& error) { // failed to allocate slab
304  LOG(INFO) << "ALLOCATION Attempted slab of " << currentMaxSlabPageSize_
305  << " pages (" << currentMaxSlabPageSize_ * pageSize_ << "B) failed "
306  << getStringMgrType() << ":" << deviceId_;
307  // check if there is any point halving currentMaxSlabSize and trying again
308  // if the request wont fit in half available then let try once at full size
309  // if we have already tries at full size and failed then break as
310  // there could still be room enough for other later request but
311  // not for his current one
312  if (numPagesRequested > currentMaxSlabPageSize_ / 2 &&
313  currentMaxSlabPageSize_ != numPagesRequested) {
314  currentMaxSlabPageSize_ = numPagesRequested;
315  } else {
318  (maxNumPagesPerSlab_ / 8)) { // should be a constant
319  allocationsCapped_ = true;
320  // dump out the slabs and their sizes
321  LOG(INFO) << "ALLOCATION Capped " << currentMaxSlabPageSize_
322  << " Minimum size = " << (maxNumPagesPerSlab_ / 8) << " "
323  << getStringMgrType() << ":" << deviceId_;
324  }
325  }
326  }
327  }
328 
329  if (numPagesAllocated_ == 0 && allocationsCapped_) {
330  throw FailedToCreateFirstSlab(numBytes);
331  }
332 
333  // If here then we can't add a slab - so we need to evict
334 
335  size_t minScore = std::numeric_limits<size_t>::max();
336  // We're going for lowest score here, like golf
337  // This is because score is the sum of the lastTouched score for all
338  // pages evicted. Evicting less pages and older pages will lower the
339  // score
340  BufferList::iterator bestEvictionStart = slabSegments_[0].end();
341  int bestEvictionStartSlab = -1;
342  int slabNum = 0;
343 
344  for (auto slabIt = slabSegments_.begin(); slabIt != slabSegments_.end();
345  ++slabIt, ++slabNum) {
346  for (auto bufferIt = slabIt->begin(); bufferIt != slabIt->end(); ++bufferIt) {
347  /* Note there are some shortcuts we could take here - like we
348  * should never consider a USED buffer coming after a free buffer
349  * as we would have used the FREE buffer, but we won't worry about
350  * this for now
351  */
352 
353  // We can't evict pinned buffers - only normal used
354  // buffers
355 
356  // if (bufferIt->memStatus == FREE || bufferIt->buffer->getPinCount() == 0) {
357  size_t pageCount = 0;
358  size_t score = 0;
359  bool solutionFound = false;
360  auto evictIt = bufferIt;
361  for (; evictIt != slabSegments_[slabNum].end(); ++evictIt) {
362  // pinCount should never go up - only down because we have
363  // global lock on buffer pool and pin count only increments
364  // on getChunk
365  if (evictIt->memStatus == USED && evictIt->buffer->getPinCount() > 0) {
366  break;
367  }
368  pageCount += evictIt->numPages;
369  if (evictIt->memStatus == USED) {
370  // MAT changed from
371  // score += evictIt->lastTouched;
372  // Issue was thrashing when going from 8M fragment size chunks back to 64M
373  // basically the large chunks were being evicted prior to small as many small
374  // chunk score was larger than one large chunk so it always would evict a large
375  // chunk so under memory pressure a query would evict its own current chunks and
376  // cause reloads rather than evict several smaller unused older chunks.
377  score = std::max(score, static_cast<size_t>(evictIt->lastTouched));
378  }
379  if (pageCount >= numPagesRequested) {
380  solutionFound = true;
381  break;
382  }
383  }
384  if (solutionFound && score < minScore) {
385  minScore = score;
386  bestEvictionStart = bufferIt;
387  bestEvictionStartSlab = slabNum;
388  } else if (evictIt == slabSegments_[slabNum].end()) {
389  // this means that every segment after this will fail as
390  // well, so our search has proven futile
391  // throw std::runtime_error ("Couldn't evict chunks to get free space");
392  break;
393  // in reality we should try to rearrange the buffer to get
394  // more contiguous free space
395  }
396  // other possibility is ending at PINNED - do nothing in this
397  // case
398  //}
399  }
400  }
401  if (bestEvictionStart == slabSegments_[0].end()) {
402  LOG(ERROR) << "ALLOCATION failed to find " << numBytes << "B throwing out of memory "
403  << getStringMgrType() << ":" << deviceId_;
404  VLOG(2) << printSlabs();
405  throw OutOfMemory(numBytes);
406  }
407  LOG(INFO) << "ALLOCATION failed to find " << numBytes << "B free. Forcing Eviction."
408  << " Eviction start " << bestEvictionStart->startPage
409  << " Number pages requested " << numPagesRequested
410  << " Best Eviction Start Slab " << bestEvictionStartSlab << " "
411  << getStringMgrType() << ":" << deviceId_;
412  bestEvictionStart = evict(bestEvictionStart, numPagesRequested, bestEvictionStartSlab);
413  return bestEvictionStart;
414 }
#define LOG(tag)
Definition: Logger.h:182
virtual void addSlab(const size_t slabSize)=0
BufferList::iterator findFreeBufferInSlab(const size_t slabNum, const size_t numPagesRequested)
Definition: BufferMgr.cpp:236
std::string printSlabs() override
Definition: BufferMgr.cpp:447
size_t maxNumPages_
max number of bytes allocated for the buffer pool
Definition: BufferMgr.h:201
static TimeT::rep execution(F func, Args &&... args)
Definition: sample.cpp:29
#define VLOG(n)
Definition: Logger.h:277
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
BufferList::iterator evict(BufferList::iterator &evictStart, const size_t numPagesRequested, const int slabNum)
Definition: BufferMgr.cpp:139
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ findFreeBufferInSlab()

BufferList::iterator Buffer_Namespace::BufferMgr::findFreeBufferInSlab ( const size_t  slabNum,
const size_t  numPagesRequested 
)
private

Definition at line 236 of file BufferMgr.cpp.

References bufferEpoch_, Buffer_Namespace::FREE, slabSegments_, and Buffer_Namespace::USED.

Referenced by findFreeBuffer().

237  {
238  for (auto bufferIt = slabSegments_[slabNum].begin();
239  bufferIt != slabSegments_[slabNum].end();
240  ++bufferIt) {
241  if (bufferIt->memStatus == FREE && bufferIt->numPages >= numPagesRequested) {
242  // startPage doesn't change
243  size_t excessPages = bufferIt->numPages - numPagesRequested;
244  bufferIt->numPages = numPagesRequested;
245  bufferIt->memStatus = USED;
246  bufferIt->lastTouched = bufferEpoch_++;
247  bufferIt->slabNum = slabNum;
248  if (excessPages > 0) {
249  BufferSeg freeSeg(bufferIt->startPage + numPagesRequested, excessPages, FREE);
250  auto tempIt = bufferIt; // this should make a copy and not be a reference
251  // - as we do not want to increment bufferIt
252  tempIt++;
253  slabSegments_[slabNum].insert(tempIt, freeSeg);
254  }
255  return bufferIt;
256  }
257  }
258  // If here then we did not find a free buffer of
259  // sufficient size in
260  // this slab, return the end iterator
261  return slabSegments_[slabNum].end();
262 }
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
+ Here is the caller graph for this function:

◆ free()

void Buffer_Namespace::BufferMgr::free ( AbstractBuffer buffer)
override

Definition at line 845 of file BufferMgr.cpp.

References deleteBuffer(), logger::FATAL, globalMutex_, LOG, and Buffer_Namespace::Buffer::segIt_.

845  {
846  std::lock_guard<std::mutex> lock(globalMutex_); // hack for now
847  Buffer* castedBuffer = dynamic_cast<Buffer*>(buffer);
848  if (castedBuffer == 0) {
849  LOG(FATAL) << "Wrong buffer type - expects base class pointer to Buffer type.";
850  }
851  deleteBuffer(castedBuffer->segIt_->chunkKey);
852 }
#define LOG(tag)
Definition: Logger.h:182
void deleteBuffer(const ChunkKey &key, const bool purge=true) override
Deletes the chunk with the specified key.
Definition: BufferMgr.cpp:585
+ Here is the call graph for this function:

◆ freeAllMem()

virtual void Buffer_Namespace::BufferMgr::freeAllMem ( )
privatepure virtual

Implemented in Buffer_Namespace::CpuBufferMgr, and Buffer_Namespace::GpuCudaBufferMgr.

Referenced by clearSlabs().

+ Here is the caller graph for this function:

◆ getAllocated()

size_t Buffer_Namespace::BufferMgr::getAllocated ( )
override

Definition at line 490 of file BufferMgr.cpp.

References numPagesAllocated_, and pageSize_.

Referenced by Data_Namespace::DataMgr::getMemoryInfo().

490  {
491  return numPagesAllocated_ * pageSize_;
492 }
+ Here is the caller graph for this function:

◆ getBuffer()

AbstractBuffer * Buffer_Namespace::BufferMgr::getBuffer ( const ChunkKey key,
const size_t  numBytes = 0 
)
override

Returns the a pointer to the chunk with the specified key.

Returns a pointer to the Buffer holding the chunk, if it exists; otherwise, throws a runtime_error.

Definition at line 710 of file BufferMgr.cpp.

References bufferEpoch_, CHECK, chunkIndex_, chunkIndexMutex_, createBuffer(), logger::FATAL, globalMutex_, keyToString(), LOG, pageSize_, parentMgr_, and sizedSegsMutex_.

710  {
711  std::lock_guard<std::mutex> lock(globalMutex_); // granular lock
712 
713  std::unique_lock<std::mutex> sizedSegsLock(sizedSegsMutex_);
714  std::unique_lock<std::mutex> chunkIndexLock(chunkIndexMutex_);
715  auto bufferIt = chunkIndex_.find(key);
716  bool foundBuffer = bufferIt != chunkIndex_.end();
717  chunkIndexLock.unlock();
718  if (foundBuffer) {
719  CHECK(bufferIt->second->buffer);
720  bufferIt->second->buffer->pin();
721  sizedSegsLock.unlock();
722  bufferIt->second->lastTouched = bufferEpoch_++; // race
723  if (bufferIt->second->buffer->size() <
724  numBytes) { // need to fetch part of buffer we don't have - up to numBytes
725  parentMgr_->fetchBuffer(key, bufferIt->second->buffer, numBytes);
726  }
727  return bufferIt->second->buffer;
728  } else { // If wasn't in pool then we need to fetch it
729  sizedSegsLock.unlock();
730  AbstractBuffer* buffer =
731  createBuffer(key, pageSize_, numBytes); // createChunk pins for us
732  try {
733  parentMgr_->fetchBuffer(
734  key, buffer, numBytes); // this should put buffer in a BufferSegment
735  } catch (std::runtime_error& error) {
736  LOG(FATAL) << "Get chunk - Could not find chunk " << keyToString(key)
737  << " in buffer pool or parent buffer pools. Error was " << error.what();
738  }
739  return buffer;
740  }
741 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
AbstractBufferMgr * parentMgr_
Definition: BufferMgr.h:208
#define LOG(tag)
Definition: Logger.h:182
An AbstractBuffer is a unit of data management for a data manager.
AbstractBuffer * createBuffer(const ChunkKey &key, const size_t pageSize=0, const size_t initialSize=0) override
Creates a chunk with the specified key and page size.
Definition: BufferMgr.cpp:97
#define CHECK(condition)
Definition: Logger.h:187
std::string keyToString(const ChunkKey &key)
Definition: BufferMgr.cpp:35
+ Here is the call graph for this function:

◆ getBufferId()

int Buffer_Namespace::BufferMgr::getBufferId ( )
private

Definition at line 833 of file BufferMgr.cpp.

References bufferIdMutex_, and maxBufferId_.

Referenced by alloc().

833  {
834  std::lock_guard<std::mutex> lock(bufferIdMutex_);
835  return maxBufferId_++;
836 }
+ Here is the caller graph for this function:

◆ getChunkMetadataVec()

void Buffer_Namespace::BufferMgr::getChunkMetadataVec ( std::vector< std::pair< ChunkKey, ChunkMetadata >> &  chunkMetadataVec)
override

Definition at line 871 of file BufferMgr.cpp.

References logger::FATAL, and LOG.

872  {
873  LOG(FATAL) << "getChunkMetadataVec not supported for BufferMgr.";
874 }
#define LOG(tag)
Definition: Logger.h:182

◆ getChunkMetadataVecForKeyPrefix()

void Buffer_Namespace::BufferMgr::getChunkMetadataVecForKeyPrefix ( std::vector< std::pair< ChunkKey, ChunkMetadata >> &  chunkMetadataVec,
const ChunkKey keyPrefix 
)
override

Definition at line 876 of file BufferMgr.cpp.

References logger::FATAL, and LOG.

878  {
879  LOG(FATAL) << "getChunkMetadataVecForPrefix not supported for BufferMgr.";
880 }
#define LOG(tag)
Definition: Logger.h:182

◆ getInUseSize()

size_t Buffer_Namespace::BufferMgr::getInUseSize ( )
override

Definition at line 504 of file BufferMgr.cpp.

References Buffer_Namespace::FREE, pageSize_, and slabSegments_.

504  {
505  size_t inUse = 0;
506  size_t numSlabs = slabSegments_.size();
507  for (size_t slabNum = 0; slabNum != numSlabs; ++slabNum) {
508  for (auto segIt = slabSegments_[slabNum].begin();
509  segIt != slabSegments_[slabNum].end();
510  ++segIt) {
511  if (segIt->memStatus != FREE) {
512  inUse += segIt->numPages * pageSize_;
513  }
514  }
515  }
516  return inUse;
517 }
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178

◆ getMaxBufferSize()

size_t Buffer_Namespace::BufferMgr::getMaxBufferSize ( )

Definition at line 863 of file BufferMgr.cpp.

References maxBufferSize_.

863  {
864  return maxBufferSize_;
865 }

◆ getMaxSize()

size_t Buffer_Namespace::BufferMgr::getMaxSize ( )
override

Definition at line 485 of file BufferMgr.cpp.

References maxNumPages_, and pageSize_.

Referenced by Data_Namespace::DataMgr::getMemoryInfo().

485  {
486  return pageSize_ * maxNumPages_;
487 }
size_t maxNumPages_
max number of bytes allocated for the buffer pool
Definition: BufferMgr.h:201
+ Here is the caller graph for this function:

◆ getMaxSlabSize()

size_t Buffer_Namespace::BufferMgr::getMaxSlabSize ( )

Definition at line 867 of file BufferMgr.cpp.

References maxSlabSize_.

867  {
868  return maxSlabSize_;
869 }

◆ getNumChunks()

size_t Buffer_Namespace::BufferMgr::getNumChunks ( )
override

Definition at line 854 of file BufferMgr.cpp.

References chunkIndex_, and chunkIndexMutex_.

854  {
855  std::lock_guard<std::mutex> chunkIndexLock(chunkIndexMutex_);
856  return chunkIndex_.size();
857 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199

◆ getPageSize()

size_t Buffer_Namespace::BufferMgr::getPageSize ( )

Definition at line 499 of file BufferMgr.cpp.

References pageSize_.

Referenced by Data_Namespace::DataMgr::getMemoryInfo().

499  {
500  return pageSize_;
501 }
+ Here is the caller graph for this function:

◆ getSlabSegments()

const std::vector< BufferList > & Buffer_Namespace::BufferMgr::getSlabSegments ( )

Definition at line 882 of file BufferMgr.cpp.

References slabSegments_.

Referenced by Data_Namespace::DataMgr::getMemoryInfo().

882  {
883  return slabSegments_;
884 }
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
+ Here is the caller graph for this function:

◆ isAllocationCapped()

bool Buffer_Namespace::BufferMgr::isAllocationCapped ( )
override

Definition at line 495 of file BufferMgr.cpp.

References allocationsCapped_.

Referenced by Data_Namespace::DataMgr::getMemoryInfo().

495  {
496  return allocationsCapped_;
497 }
+ Here is the caller graph for this function:

◆ isBufferOnDevice()

bool Buffer_Namespace::BufferMgr::isBufferOnDevice ( const ChunkKey key)
override

Puts the contents of d into the Buffer with ChunkKey key.

Parameters
key- Unique identifier for a Chunk.
d- An object representing the source data for the Chunk.
Returns
AbstractBuffer*

Definition at line 575 of file BufferMgr.cpp.

References chunkIndex_, and chunkIndexMutex_.

575  {
576  std::lock_guard<std::mutex> chunkIndexLock(chunkIndexMutex_);
577  if (chunkIndex_.find(key) == chunkIndex_.end()) {
578  return false;
579  } else {
580  return true;
581  }
582 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199

◆ keyToString()

std::string Buffer_Namespace::BufferMgr::keyToString ( const ChunkKey key)

Definition at line 35 of file BufferMgr.cpp.

Referenced by fetchBuffer(), and getBuffer().

35  {
36  std::ostringstream oss;
37 
38  oss << " key: ";
39  for (auto subKey : key) {
40  oss << subKey << ",";
41  }
42  return oss.str();
43 }
+ Here is the caller graph for this function:

◆ operator=()

BufferMgr& Buffer_Namespace::BufferMgr::operator= ( const BufferMgr )
private

◆ printMap()

std::string Buffer_Namespace::BufferMgr::printMap ( )

Definition at line 539 of file BufferMgr.cpp.

References chunkIndex_, chunkIndexMutex_, and printSeg().

539  {
540  std::ostringstream tss;
541  int segNum = 1;
542  tss << std::endl
543  << "Map Contents: "
544  << " " << getStringMgrType() << ":" << deviceId_ << std::endl;
545  std::lock_guard<std::mutex> chunkIndexLock(chunkIndexMutex_);
546  for (auto segIt = chunkIndex_.begin(); segIt != chunkIndex_.end(); ++segIt, ++segNum) {
547  // tss << "Map Entry " << segNum << ": ";
548  // for (auto vecIt = segIt->first.begin(); vecIt != segIt->first.end(); ++vecIt) {
549  // tss << *vecIt << ",";
550  // }
551  // tss << " " << std::endl;
552  tss << printSeg(segIt->second);
553  }
554  tss << "--------------------" << std::endl;
555  return tss.str();
556 }
std::string printSeg(BufferList::iterator &segIt)
Definition: BufferMgr.cpp:519
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
+ Here is the call graph for this function:

◆ printSeg()

std::string Buffer_Namespace::BufferMgr::printSeg ( BufferList::iterator &  segIt)

Definition at line 519 of file BufferMgr.cpp.

References Buffer_Namespace::FREE.

Referenced by printMap(), and printSegs().

519  {
520  std::ostringstream tss;
521  tss << "SN: " << setfill(' ') << setw(2) << segIt->slabNum;
522  tss << " SP: " << setfill(' ') << setw(7) << segIt->startPage;
523  tss << " NP: " << setfill(' ') << setw(7) << segIt->numPages;
524  tss << " LT: " << setfill(' ') << setw(7) << segIt->lastTouched;
525  tss << " PC: " << setfill(' ') << setw(2) << segIt->buffer->getPinCount();
526  if (segIt->memStatus == FREE) {
527  tss << " FREE"
528  << " ";
529  } else {
530  tss << " USED - Chunk: ";
531  for (auto vecIt = segIt->chunkKey.begin(); vecIt != segIt->chunkKey.end(); ++vecIt) {
532  tss << *vecIt << ",";
533  }
534  tss << std::endl;
535  }
536  return tss.str();
537 }
+ Here is the caller graph for this function:

◆ printSegs()

void Buffer_Namespace::BufferMgr::printSegs ( )

Definition at line 558 of file BufferMgr.cpp.

References logger::INFO, LOG, printSeg(), and slabSegments_.

558  {
559  int segNum = 1;
560  int slabNum = 1;
561  LOG(INFO) << std::endl << " " << getStringMgrType() << ":" << deviceId_;
562  for (auto slabIt = slabSegments_.begin(); slabIt != slabSegments_.end();
563  ++slabIt, ++slabNum) {
564  LOG(INFO) << "Slab Num: " << slabNum << " " << getStringMgrType() << ":" << deviceId_;
565  for (auto segIt = slabIt->begin(); segIt != slabIt->end(); ++segIt, ++segNum) {
566  LOG(INFO) << "Segment: " << segNum << " " << getStringMgrType() << ":" << deviceId_;
567  printSeg(segIt);
568  LOG(INFO) << " " << getStringMgrType() << ":" << deviceId_;
569  }
570  LOG(INFO) << "--------------------"
571  << " " << getStringMgrType() << ":" << deviceId_;
572  }
573 }
std::string printSeg(BufferList::iterator &segIt)
Definition: BufferMgr.cpp:519
#define LOG(tag)
Definition: Logger.h:182
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
+ Here is the call graph for this function:

◆ printSlab()

std::string Buffer_Namespace::BufferMgr::printSlab ( size_t  slabNum)

Definition at line 416 of file BufferMgr.cpp.

References Buffer_Namespace::FREE, and slabSegments_.

Referenced by printSlabs().

416  {
417  std::ostringstream tss;
418  // size_t lastEnd = 0;
419  tss << "Slab St.Page Pages Touch" << std::endl;
420  for (auto segIt = slabSegments_[slabNum].begin(); segIt != slabSegments_[slabNum].end();
421  ++segIt) {
422  tss << setfill(' ') << setw(4) << slabNum;
423  // tss << " BSN: " << setfill(' ') << setw(2) << segIt->slabNum;
424  tss << setfill(' ') << setw(8) << segIt->startPage;
425  tss << setfill(' ') << setw(8) << segIt->numPages;
426  // tss << " GAP: " << setfill(' ') << setw(7) << segIt->startPage - lastEnd;
427  // lastEnd = segIt->startPage + segIt->numPages;
428  tss << setfill(' ') << setw(7) << segIt->lastTouched;
429  // tss << " PC: " << setfill(' ') << setw(2) << segIt->buffer->getPinCount();
430  if (segIt->memStatus == FREE) {
431  tss << " FREE"
432  << " ";
433  } else {
434  tss << " PC: " << setfill(' ') << setw(2) << segIt->buffer->getPinCount();
435  tss << " USED - Chunk: ";
436 
437  for (auto vecIt = segIt->chunkKey.begin(); vecIt != segIt->chunkKey.end();
438  ++vecIt) {
439  tss << *vecIt << ",";
440  }
441  }
442  tss << std::endl;
443  }
444  return tss.str();
445 }
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
+ Here is the caller graph for this function:

◆ printSlabs()

std::string Buffer_Namespace::BufferMgr::printSlabs ( )
override

Definition at line 447 of file BufferMgr.cpp.

References printSlab(), and slabSegments_.

Referenced by findFreeBuffer().

447  {
448  std::ostringstream tss;
449  tss << std::endl
450  << "Slabs Contents: "
451  << " " << getStringMgrType() << ":" << deviceId_ << std::endl;
452  size_t numSlabs = slabSegments_.size();
453  for (size_t slabNum = 0; slabNum != numSlabs; ++slabNum) {
454  tss << printSlab(slabNum);
455  }
456  tss << "--------------------" << std::endl;
457  return tss.str();
458 }
std::string printSlab(size_t slabNum)
Definition: BufferMgr.cpp:416
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ putBuffer()

AbstractBuffer * Buffer_Namespace::BufferMgr::putBuffer ( const ChunkKey key,
AbstractBuffer d,
const size_t  numBytes = 0 
)
override

Definition at line 796 of file BufferMgr.cpp.

References Data_Namespace::AbstractBuffer::append(), CHECK, chunkIndex_, chunkIndexMutex_, Data_Namespace::AbstractBuffer::clearDirtyBits(), createBuffer(), Data_Namespace::AbstractBuffer::getDeviceId(), Data_Namespace::AbstractBuffer::getMemoryPtr(), Data_Namespace::AbstractBuffer::getType(), Data_Namespace::AbstractBuffer::isAppended(), Data_Namespace::AbstractBuffer::isDirty(), Data_Namespace::AbstractBuffer::isUpdated(), pageSize_, Data_Namespace::AbstractBuffer::size(), Data_Namespace::AbstractBuffer::syncEncoder(), and Data_Namespace::AbstractBuffer::write().

798  {
799  std::unique_lock<std::mutex> chunkIndexLock(chunkIndexMutex_);
800  auto bufferIt = chunkIndex_.find(key);
801  bool foundBuffer = bufferIt != chunkIndex_.end();
802  chunkIndexLock.unlock();
803  AbstractBuffer* buffer;
804  if (!foundBuffer) {
805  buffer = createBuffer(key, pageSize_);
806  } else {
807  buffer = bufferIt->second->buffer;
808  }
809  size_t oldBufferSize = buffer->size();
810  size_t newBufferSize = numBytes == 0 ? srcBuffer->size() : numBytes;
811  CHECK(!buffer->isDirty());
812 
813  if (srcBuffer->isUpdated()) {
814  //@todo use dirty flags to only flush pages of chunk that need to
815  // be flushed
816  buffer->write((int8_t*)srcBuffer->getMemoryPtr(),
817  newBufferSize,
818  0,
819  srcBuffer->getType(),
820  srcBuffer->getDeviceId());
821  } else if (srcBuffer->isAppended()) {
822  CHECK(oldBufferSize < newBufferSize);
823  buffer->append((int8_t*)srcBuffer->getMemoryPtr() + oldBufferSize,
824  newBufferSize - oldBufferSize,
825  srcBuffer->getType(),
826  srcBuffer->getDeviceId());
827  }
828  srcBuffer->clearDirtyBits();
829  buffer->syncEncoder(srcBuffer);
830  return buffer;
831 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
virtual void write(int8_t *src, const size_t numBytes, const size_t offset=0, const MemoryLevel srcBufferType=CPU_LEVEL, const int srcDeviceId=-1)=0
virtual size_t size() const =0
virtual void append(int8_t *src, const size_t numBytes, const MemoryLevel srcBufferType=CPU_LEVEL, const int deviceId=-1)=0
An AbstractBuffer is a unit of data management for a data manager.
AbstractBuffer * createBuffer(const ChunkKey &key, const size_t pageSize=0, const size_t initialSize=0) override
Creates a chunk with the specified key and page size.
Definition: BufferMgr.cpp:97
#define CHECK(condition)
Definition: Logger.h:187
virtual bool isDirty() const
void syncEncoder(const AbstractBuffer *srcBuffer)
+ Here is the call graph for this function:

◆ reinit()

void Buffer_Namespace::BufferMgr::reinit ( )

Definition at line 74 of file BufferMgr.cpp.

References allocationsCapped_, currentMaxSlabPageSize_, maxNumPagesPerSlab_, and numPagesAllocated_.

Referenced by clearSlabs().

74  {
77  maxNumPagesPerSlab_; // currentMaxSlabPageSize_ will drop as allocations fail -
78  // this is the high water mark
79  allocationsCapped_ = false;
80 }
+ Here is the caller graph for this function:

◆ removeSegment()

void Buffer_Namespace::BufferMgr::removeSegment ( BufferList::iterator &  segIt)
private

Definition at line 633 of file BufferMgr.cpp.

References Buffer_Namespace::FREE, slabSegments_, unsizedSegs_, and unsizedSegsMutex_.

Referenced by deleteBuffer(), deleteBuffersWithPrefix(), and reserveBuffer().

633  {
634  // Note: does not delete buffer as this may be moved somewhere else
635  int slabNum = segIt->slabNum;
636  // cout << "Slab num: " << slabNum << endl;
637  if (slabNum < 0) {
638  std::lock_guard<std::mutex> unsizedSegsLock(unsizedSegsMutex_);
639  unsizedSegs_.erase(segIt);
640  } else {
641  if (segIt != slabSegments_[slabNum].begin()) {
642  auto prevIt = std::prev(segIt);
643  // LOG(INFO) << "PrevIt: " << " " << getStringMgrType() << ":" << deviceId_;
644  // printSeg(prevIt);
645  if (prevIt->memStatus == FREE) {
646  segIt->startPage = prevIt->startPage;
647  segIt->numPages += prevIt->numPages;
648  slabSegments_[slabNum].erase(prevIt);
649  }
650  }
651  auto nextIt = std::next(segIt);
652  if (nextIt != slabSegments_[slabNum].end()) {
653  if (nextIt->memStatus == FREE) {
654  segIt->numPages += nextIt->numPages;
655  slabSegments_[slabNum].erase(nextIt);
656  }
657  }
658  segIt->memStatus = FREE;
659  // segIt->pinCount = 0;
660  segIt->buffer = 0;
661  }
662 }
BufferList unsizedSegs_
Maps sizes of free memory areas to host buffer pool memory addresses.
Definition: BufferMgr.h:216
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
+ Here is the caller graph for this function:

◆ reserveBuffer()

BufferList::iterator Buffer_Namespace::BufferMgr::reserveBuffer ( BufferList::iterator &  segIt,
const size_t  numBytes 
)

Definition at line 179 of file BufferMgr.cpp.

References chunkIndex_, chunkIndexMutex_, findFreeBuffer(), Buffer_Namespace::FREE, pageSize_, removeSegment(), slabs_, and slabSegments_.

Referenced by Buffer_Namespace::Buffer::reserve().

181  { // assumes buffer is already pinned
182 
183  size_t numPagesRequested = (numBytes + pageSize_ - 1) / pageSize_;
184  size_t numPagesExtraNeeded = numPagesRequested - segIt->numPages;
185 
186  if (numPagesRequested <
187  segIt->numPages) { // We already have enough pages in existing segment
188  return segIt;
189  }
190  // First check for freeSeg after segIt
191  int slabNum = segIt->slabNum;
192  if (slabNum >= 0) { // not dummy page
193  BufferList::iterator nextIt = std::next(segIt);
194  if (nextIt != slabSegments_[slabNum].end() && nextIt->memStatus == FREE &&
195  nextIt->numPages >= numPagesExtraNeeded) { // Then we can just use the next
196  // BufferSeg which happens to be free
197  size_t leftoverPages = nextIt->numPages - numPagesExtraNeeded;
198  segIt->numPages = numPagesRequested;
199  nextIt->numPages = leftoverPages;
200  nextIt->startPage = segIt->startPage + segIt->numPages;
201  return segIt;
202  }
203  }
204  /* If we're here then we couldn't keep
205  * buffer in existing slot - need to find
206  * new segment, copy data over, and then
207  * delete old
208  */
209 
210  auto newSegIt = findFreeBuffer(numBytes);
211 
212  /* Below should be in copy constructor for BufferSeg?*/
213  newSegIt->buffer = segIt->buffer;
214  // newSegIt->buffer->segIt_ = newSegIt;
215  newSegIt->chunkKey = segIt->chunkKey;
216  int8_t* oldMem = newSegIt->buffer->mem_;
217  newSegIt->buffer->mem_ = slabs_[newSegIt->slabNum] + newSegIt->startPage * pageSize_;
218 
219  // now need to copy over memory
220  // only do this if the old segment is valid (i.e. not new w/
221  // unallocated buffer
222  if (segIt->startPage >= 0 && segIt->buffer->mem_ != 0) {
223  newSegIt->buffer->writeData(
224  oldMem, newSegIt->buffer->size(), 0, newSegIt->buffer->getType(), deviceId_);
225  }
226  // Deincrement pin count to reverse effect above
227  removeSegment(segIt);
228  {
229  std::lock_guard<std::mutex> lock(chunkIndexMutex_);
230  chunkIndex_[newSegIt->chunkKey] = newSegIt;
231  }
232 
233  return newSegIt;
234 }
std::map< ChunkKey, BufferList::iterator > chunkIndex_
Definition: BufferMgr.h:199
BufferList::iterator findFreeBuffer(size_t numBytes)
Definition: BufferMgr.cpp:264
void removeSegment(BufferList::iterator &segIt)
Definition: BufferMgr.cpp:633
std::vector< int8_t * > slabs_
Definition: BufferMgr.h:176
std::vector< BufferList > slabSegments_
Definition: BufferMgr.h:178
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ size()

size_t Buffer_Namespace::BufferMgr::size ( )

Returns the total number of bytes allocated.

Definition at line 859 of file BufferMgr.cpp.

References numPagesAllocated_.

859  {
860  return numPagesAllocated_;
861 }

Member Data Documentation

◆ allocationsCapped_

bool Buffer_Namespace::BufferMgr::allocationsCapped_
private

size of the individual memory allocations that compose the buffer pool (up to maxBufferSize_)

Definition at line 207 of file BufferMgr.h.

Referenced by findFreeBuffer(), isAllocationCapped(), and reinit().

◆ bufferEpoch_

unsigned int Buffer_Namespace::BufferMgr::bufferEpoch_
private

Definition at line 210 of file BufferMgr.h.

Referenced by clear(), evict(), findFreeBufferInSlab(), and getBuffer().

◆ bufferIdMutex_

std::mutex Buffer_Namespace::BufferMgr::bufferIdMutex_
private

Definition at line 196 of file BufferMgr.h.

Referenced by getBufferId().

◆ chunkIndex_

std::map<ChunkKey, BufferList::iterator> Buffer_Namespace::BufferMgr::chunkIndex_
private

◆ chunkIndexMutex_

std::mutex Buffer_Namespace::BufferMgr::chunkIndexMutex_
private

◆ currentMaxSlabPageSize_

size_t Buffer_Namespace::BufferMgr::currentMaxSlabPageSize_
private

Definition at line 204 of file BufferMgr.h.

Referenced by BufferMgr(), findFreeBuffer(), and reinit().

◆ globalMutex_

std::mutex Buffer_Namespace::BufferMgr::globalMutex_
private

Definition at line 197 of file BufferMgr.h.

Referenced by alloc(), checkpoint(), fetchBuffer(), free(), and getBuffer().

◆ maxBufferId_

int Buffer_Namespace::BufferMgr::maxBufferId_
private

Definition at line 209 of file BufferMgr.h.

Referenced by getBufferId().

◆ maxBufferSize_

size_t Buffer_Namespace::BufferMgr::maxBufferSize_
private

Definition at line 200 of file BufferMgr.h.

Referenced by BufferMgr(), and getMaxBufferSize().

◆ maxNumPages_

size_t Buffer_Namespace::BufferMgr::maxNumPages_
private

max number of bytes allocated for the buffer pool

Definition at line 201 of file BufferMgr.h.

Referenced by BufferMgr(), findFreeBuffer(), and getMaxSize().

◆ maxNumPagesPerSlab_

size_t Buffer_Namespace::BufferMgr::maxNumPagesPerSlab_
private

Definition at line 203 of file BufferMgr.h.

Referenced by BufferMgr(), findFreeBuffer(), and reinit().

◆ maxSlabSize_

size_t Buffer_Namespace::BufferMgr::maxSlabSize_
private

Definition at line 205 of file BufferMgr.h.

Referenced by BufferMgr(), and getMaxSlabSize().

◆ numPagesAllocated_

size_t Buffer_Namespace::BufferMgr::numPagesAllocated_
private

Definition at line 202 of file BufferMgr.h.

Referenced by findFreeBuffer(), getAllocated(), reinit(), and size().

◆ pageSize_

◆ parentMgr_

AbstractBufferMgr* Buffer_Namespace::BufferMgr::parentMgr_
private

Definition at line 208 of file BufferMgr.h.

Referenced by checkpoint(), fetchBuffer(), and getBuffer().

◆ sizedSegsMutex_

std::mutex Buffer_Namespace::BufferMgr::sizedSegsMutex_
private

Definition at line 194 of file BufferMgr.h.

Referenced by clear(), deleteBuffer(), deleteBuffersWithPrefix(), fetchBuffer(), and getBuffer().

◆ slabs_

◆ slabSegments_

std::vector<BufferList> Buffer_Namespace::BufferMgr::slabSegments_
protected

◆ unsizedSegs_

BufferList Buffer_Namespace::BufferMgr::unsizedSegs_
private

Maps sizes of free memory areas to host buffer pool memory addresses.

Definition at line 216 of file BufferMgr.h.

Referenced by clear(), createBuffer(), and removeSegment().

◆ unsizedSegsMutex_

std::mutex Buffer_Namespace::BufferMgr::unsizedSegsMutex_
private

Definition at line 195 of file BufferMgr.h.

Referenced by clear(), createBuffer(), and removeSegment().


The documentation for this class was generated from the following files: