OmniSciDB  340b00dbf6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 device_id, const size_t max_buffer_size, const size_t min_slab_size, const size_t max_slab_size, const size_t page_size, AbstractBufferMgr *parent_mgr=0)
 Constructs a BufferMgr object that allocates memSize bytes. More...
 
 ~BufferMgr () override
 Destructor. More...
 
void reinit ()
 
void clear ()
 
std::string printSlab (size_t slab_num)
 
std::string printSlabs () override
 
void clearSlabs () override
 
std::string printMap ()
 
void printSegs ()
 
std::string printSeg (BufferList::iterator &seg_it)
 
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 page_size=0, const size_t initial_size=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 &key_prefix, const bool purge=true) override
 
AbstractBuffergetBuffer (const ChunkKey &key, const size_t num_bytes=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 *dest_buffer, const size_t num_bytes=0) override
 
AbstractBufferputBuffer (const ChunkKey &key, AbstractBuffer *d, const size_t num_bytes=0) override
 
void checkpoint () override
 
void checkpoint (const int db_id, const int tb_id) override
 
void removeTableRelatedDS (const int db_id, const int table_id) override
 
AbstractBufferalloc (const size_t num_bytes=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 &seg_it, const size_t num_bytes)
 
void getChunkMetadataVecForKeyPrefix (ChunkMetadataVector &chunk_metadata_vec, const ChunkKey &key_prefix) override
 

Protected Attributes

const size_t max_buffer_pool_size_
 
const size_t min_slab_size_
 max number of bytes allocated for the buffer pool More...
 
const size_t max_slab_size_
 
const size_t page_size_
 
std::vector< int8_t * > slabs_
 
std::vector< BufferListslab_segments_
 

Private Member Functions

 BufferMgr (const BufferMgr &)
 
BufferMgroperator= (const BufferMgr &)
 
void removeSegment (BufferList::iterator &seg_it)
 
BufferList::iterator findFreeBufferInSlab (const size_t slab_num, const size_t num_pages_requested)
 
int getBufferId ()
 
virtual void addSlab (const size_t slab_size)=0
 
virtual void freeAllMem ()=0
 
virtual void allocateBuffer (BufferList::iterator seg_it, const size_t page_size, const size_t num_bytes)=0
 
BufferList::iterator evict (BufferList::iterator &evict_start, const size_t num_pages_requested, const int slab_num)
 
BufferList::iterator findFreeBuffer (size_t num_bytes)
 Gets a buffer of required size and returns an iterator to it. More...
 

Private Attributes

std::mutex chunk_index_mutex_
 
std::mutex sized_segs_mutex_
 
std::mutex unsized_segs_mutex_
 
std::mutex buffer_id_mutex_
 
std::mutex global_mutex_
 
std::map< ChunkKey,
BufferList::iterator > 
chunk_index_
 
size_t max_buffer_pool_num_pages_
 
size_t num_pages_allocated_
 
size_t min_num_pages_per_slab_
 
size_t max_num_pages_per_slab_
 
size_t current_max_slab_page_size_
 
bool allocations_capped_
 
AbstractBufferMgrparent_mgr_
 
int max_buffer_id_
 
unsigned int buffer_epoch_
 
BufferList unsized_segs_
 

Detailed Description

Note(s): Forbid Copying Idiom 4.1.

Definition at line 97 of file BufferMgr.h.

Constructor & Destructor Documentation

Buffer_Namespace::BufferMgr::BufferMgr ( const int  device_id,
const size_t  max_buffer_size,
const size_t  min_slab_size,
const size_t  max_slab_size,
const size_t  page_size,
AbstractBufferMgr parent_mgr = 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 47 of file BufferMgr.cpp.

References CHECK, current_max_slab_page_size_, max_buffer_pool_num_pages_, max_buffer_pool_size_, max_num_pages_per_slab_, max_slab_size_, min_num_pages_per_slab_, min_slab_size_, and page_size_.

53  : AbstractBufferMgr(device_id)
54  , max_buffer_pool_size_(max_buffer_pool_size)
55  , min_slab_size_(min_slab_size)
56  , max_slab_size_(max_slab_size)
57  , page_size_(page_size)
59  , allocations_capped_(false)
60  , parent_mgr_(parent_mgr)
61  , max_buffer_id_(0)
62  , buffer_epoch_(0) {
64  CHECK(page_size_ > 0);
65  // TODO change checks on run-time configurable slab size variables to exceptions
66  CHECK(min_slab_size_ > 0);
67  CHECK(max_slab_size_ > 0);
71 
76  max_num_pages_per_slab_; // current_max_slab_page_size_ will drop as allocations
77  // fail - this is the high water mark
78 }
AbstractBufferMgr * parent_mgr_
Definition: BufferMgr.h:210
const size_t max_buffer_pool_size_
Definition: BufferMgr.h:175
unsigned int buffer_epoch_
Definition: BufferMgr.h:212
const size_t min_slab_size_
max number of bytes allocated for the buffer pool
Definition: BufferMgr.h:176
#define CHECK(condition)
Definition: Logger.h:197
const size_t max_slab_size_
Definition: BufferMgr.h:178
Buffer_Namespace::BufferMgr::~BufferMgr ( )
override

Destructor.

Frees the heap-allocated buffer pool memory.

Definition at line 81 of file BufferMgr.cpp.

References clear().

81  {
82  clear();
83 }

+ Here is the call graph for this function:

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

Member Function Documentation

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

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

Referenced by findFreeBuffer().

+ Here is the caller graph for this function:

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

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

Definition at line 831 of file BufferMgr.cpp.

References createBuffer(), getBufferId(), global_mutex_, and page_size_.

831  {
832  std::lock_guard<std::mutex> lock(global_mutex_);
833  ChunkKey chunk_key = {-1, getBufferId()};
834  return createBuffer(chunk_key, page_size_, num_bytes);
835 }
std::vector< int > ChunkKey
Definition: types.h:37
AbstractBuffer * createBuffer(const ChunkKey &key, const size_t page_size=0, const size_t initial_size=0) override
Creates a chunk with the specified key and page size.
Definition: BufferMgr.cpp:109

+ Here is the call graph for this function:

virtual void Buffer_Namespace::BufferMgr::allocateBuffer ( BufferList::iterator  seg_it,
const size_t  page_size,
const size_t  num_bytes 
)
privatepure virtual

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

Referenced by createBuffer().

+ Here is the caller graph for this function:

void Buffer_Namespace::BufferMgr::checkpoint ( )
override

Definition at line 669 of file BufferMgr.cpp.

References chunk_index_, chunk_index_mutex_, global_mutex_, and parent_mgr_.

669  {
670  std::lock_guard<std::mutex> lock(global_mutex_); // granular lock
671  std::lock_guard<std::mutex> chunkIndexLock(chunk_index_mutex_);
672 
673  for (auto& chunk_itr : chunk_index_) {
674  // checks that buffer is actual chunk (not just buffer) and is dirty
675  auto& buffer_itr = chunk_itr.second;
676  if (buffer_itr->chunk_key[0] != -1 && buffer_itr->buffer->isDirty()) {
677  parent_mgr_->putBuffer(buffer_itr->chunk_key, buffer_itr->buffer);
678  buffer_itr->buffer->clearDirtyBits();
679  }
680  }
681 }
AbstractBufferMgr * parent_mgr_
Definition: BufferMgr.h:210
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
void Buffer_Namespace::BufferMgr::checkpoint ( const int  db_id,
const int  tb_id 
)
override

Definition at line 683 of file BufferMgr.cpp.

References chunk_index_, chunk_index_mutex_, global_mutex_, and parent_mgr_.

683  {
684  std::lock_guard<std::mutex> lock(global_mutex_); // granular lock
685  std::lock_guard<std::mutex> chunk_index_lock(chunk_index_mutex_);
686 
687  ChunkKey key_prefix;
688  key_prefix.push_back(db_id);
689  key_prefix.push_back(tb_id);
690  auto start_chunk_it = chunk_index_.lower_bound(key_prefix);
691  if (start_chunk_it == chunk_index_.end()) {
692  return;
693  }
694 
695  auto buffer_it = start_chunk_it;
696  while (buffer_it != chunk_index_.end() &&
697  std::search(buffer_it->first.begin(),
698  buffer_it->first.begin() + key_prefix.size(),
699  key_prefix.begin(),
700  key_prefix.end()) != buffer_it->first.begin() + key_prefix.size()) {
701  if (buffer_it->second->chunk_key[0] != -1 &&
702  buffer_it->second->buffer->isDirty()) { // checks that buffer is actual chunk
703  // (not just buffer) and is dirty
704 
705  parent_mgr_->putBuffer(buffer_it->second->chunk_key, buffer_it->second->buffer);
706  buffer_it->second->buffer->clearDirtyBits();
707  }
708  buffer_it++;
709  }
710 }
AbstractBufferMgr * parent_mgr_
Definition: BufferMgr.h:210
std::vector< int > ChunkKey
Definition: types.h:37
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
void Buffer_Namespace::BufferMgr::clear ( )

Definition at line 93 of file BufferMgr.cpp.

References buffer_epoch_, chunk_index_, chunk_index_mutex_, sized_segs_mutex_, slab_segments_, slabs_, unsized_segs_, and unsized_segs_mutex_.

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

93  {
94  std::lock_guard<std::mutex> sized_segs_lock(sized_segs_mutex_);
95  std::lock_guard<std::mutex> chunk_index_lock(chunk_index_mutex_);
96  std::lock_guard<std::mutex> unsized_segs_lock(unsized_segs_mutex_);
97  for (auto& buf : chunk_index_) {
98  delete buf.second->buffer;
99  }
100 
101  chunk_index_.clear();
102  slabs_.clear();
103  slab_segments_.clear();
104  unsized_segs_.clear();
105  buffer_epoch_ = 0;
106 }
unsigned int buffer_epoch_
Definition: BufferMgr.h:212
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
std::mutex unsized_segs_mutex_
Definition: BufferMgr.h:199
std::vector< int8_t * > slabs_
Definition: BufferMgr.h:181

+ Here is the caller graph for this function:

void Buffer_Namespace::BufferMgr::clearSlabs ( )
override

Definition at line 466 of file BufferMgr.cpp.

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

466  {
467  bool pinned_exists = false;
468  for (auto& segment_list : slab_segments_) {
469  for (auto& segment : segment_list) {
470  if (segment.mem_status == FREE) {
471  // no need to free
472  } else if (segment.buffer->getPinCount() < 1) {
473  deleteBuffer(segment.chunk_key, true);
474  } else {
475  pinned_exists = true;
476  }
477  }
478  }
479  if (!pinned_exists) {
480  // lets actually clear the buffer from memory
481  freeAllMem();
482  clear();
483  reinit();
484  }
485 }
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183
void deleteBuffer(const ChunkKey &key, const bool purge=true) override
Deletes the chunk with the specified key.
Definition: BufferMgr.cpp:591
virtual void freeAllMem()=0

+ Here is the call graph for this function:

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

Creates a chunk with the specified key and page size.

Throws a runtime_error if the Chunk already exists.

Definition at line 109 of file BufferMgr.cpp.

References allocateBuffer(), CHECK, chunk_index_, chunk_index_mutex_, deleteBuffer(), page_size_, unsized_segs_, unsized_segs_mutex_, and Buffer_Namespace::USED.

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

111  {
112  // LOG(INFO) << printMap();
113  size_t actual_chunk_page_size = chunk_page_size;
114  if (actual_chunk_page_size == 0) {
115  actual_chunk_page_size = page_size_;
116  }
117 
118  // chunk_page_size is just for recording dirty pages
119  {
120  std::lock_guard<std::mutex> lock(chunk_index_mutex_);
121  CHECK(chunk_index_.find(chunk_key) == chunk_index_.end());
122  BufferSeg buffer_seg(BufferSeg(-1, 0, USED));
123  buffer_seg.chunk_key = chunk_key;
124  std::lock_guard<std::mutex> unsizedSegsLock(unsized_segs_mutex_);
125  unsized_segs_.push_back(buffer_seg); // race condition?
126  chunk_index_[chunk_key] =
127  std::prev(unsized_segs_.end(),
128  1); // need to do this before allocating Buffer because doing so could
129  // change the segment used
130  }
131  // following should be safe outside the lock b/c first thing Buffer
132  // constructor does is pin (and its still in unsized segs at this point
133  // so can't be evicted)
134  try {
135  allocateBuffer(chunk_index_[chunk_key], actual_chunk_page_size, initial_size);
136  } catch (const OutOfMemory&) {
137  auto buffer_it = chunk_index_.find(chunk_key);
138  CHECK(buffer_it != chunk_index_.end());
139  buffer_it->second->buffer =
140  nullptr; // constructor failed for the buffer object so make sure to mark it null
141  // so deleteBuffer doesn't try to delete it
142  deleteBuffer(chunk_key);
143  throw;
144  }
145  CHECK(initial_size == 0 || chunk_index_[chunk_key]->buffer->getMemoryPtr());
146  // chunk_index_[chunk_key]->buffer->pin();
147  std::lock_guard<std::mutex> lock(chunk_index_mutex_);
148  return chunk_index_[chunk_key]->buffer;
149 }
virtual void allocateBuffer(BufferList::iterator seg_it, const size_t page_size, const size_t num_bytes)=0
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
std::mutex unsized_segs_mutex_
Definition: BufferMgr.h:199
#define CHECK(condition)
Definition: Logger.h:197
void deleteBuffer(const ChunkKey &key, const bool purge=true) override
Deletes the chunk with the specified key.
Definition: BufferMgr.cpp:591

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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 591 of file BufferMgr.cpp.

References CHECK, chunk_index_, chunk_index_mutex_, removeSegment(), and sized_segs_mutex_.

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

591  {
592  // Note: purge is unused
593  std::unique_lock<std::mutex> chunk_index_lock(chunk_index_mutex_);
594 
595  // lookup the buffer for the Chunk in chunk_index_
596  auto buffer_it = chunk_index_.find(key);
597  CHECK(buffer_it != chunk_index_.end());
598  auto seg_it = buffer_it->second;
599  chunk_index_.erase(buffer_it);
600  chunk_index_lock.unlock();
601  std::lock_guard<std::mutex> sized_segs_lock(sized_segs_mutex_);
602  if (seg_it->buffer) {
603  delete seg_it->buffer; // Delete Buffer for segment
604  seg_it->buffer = 0;
605  }
606  removeSegment(seg_it);
607 }
void removeSegment(BufferList::iterator &seg_it)
Definition: BufferMgr.cpp:638
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
#define CHECK(condition)
Definition: Logger.h:197

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 609 of file BufferMgr.cpp.

References chunk_index_, chunk_index_mutex_, removeSegment(), and sized_segs_mutex_.

609  {
610  // Note: purge is unused
611  // lookup the buffer for the Chunk in chunk_index_
612  std::lock_guard<std::mutex> sized_segs_lock(
613  sized_segs_mutex_); // Take this lock early to prevent deadlock with
614  // reserveBuffer which needs segs_mutex_ and then
615  // chunk_index_mutex_
616  std::lock_guard<std::mutex> chunk_index_lock(chunk_index_mutex_);
617  auto startChunkIt = chunk_index_.lower_bound(key_prefix);
618  if (startChunkIt == chunk_index_.end()) {
619  return;
620  }
621 
622  auto buffer_it = startChunkIt;
623  while (buffer_it != chunk_index_.end() &&
624  std::search(buffer_it->first.begin(),
625  buffer_it->first.begin() + key_prefix.size(),
626  key_prefix.begin(),
627  key_prefix.end()) != buffer_it->first.begin() + key_prefix.size()) {
628  auto seg_it = buffer_it->second;
629  if (seg_it->buffer) {
630  delete seg_it->buffer; // Delete Buffer for segment
631  seg_it->buffer = 0;
632  }
633  removeSegment(seg_it);
634  chunk_index_.erase(buffer_it++);
635  }
636 }
void removeSegment(BufferList::iterator &seg_it)
Definition: BufferMgr.cpp:638
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203

+ Here is the call graph for this function:

BufferList::iterator Buffer_Namespace::BufferMgr::evict ( BufferList::iterator &  evict_start,
const size_t  num_pages_requested,
const int  slab_num 
)
private

Definition at line 151 of file BufferMgr.cpp.

References buffer_epoch_, CHECK, chunk_index_, Buffer_Namespace::FREE, Buffer_Namespace::BufferSeg::slab_num, slab_segments_, and Buffer_Namespace::USED.

Referenced by findFreeBuffer().

153  {
154  // We can assume here that buffer for evictStart either doesn't exist
155  // (evictStart is first buffer) or was not free, so don't need ot merge
156  // it
157  auto evict_it = evict_start;
158  size_t num_pages = 0;
159  size_t start_page = evict_start->start_page;
160  while (num_pages < num_pages_requested) {
161  if (evict_it->mem_status == USED) {
162  CHECK(evict_it->buffer->getPinCount() < 1);
163  }
164  num_pages += evict_it->num_pages;
165  if (evict_it->mem_status == USED && evict_it->chunk_key.size() > 0) {
166  chunk_index_.erase(evict_it->chunk_key);
167  }
168  evict_it = slab_segments_[slab_num].erase(
169  evict_it); // erase operations returns next iterator - safe if we ever move
170  // to a vector (as opposed to erase(evict_it++)
171  }
172  BufferSeg data_seg(
173  start_page, num_pages_requested, USED, buffer_epoch_++); // until we can
174  // data_seg.pinCount++;
175  data_seg.slab_num = slab_num;
176  auto data_seg_it =
177  slab_segments_[slab_num].insert(evict_it, data_seg); // Will insert before evict_it
178  if (num_pages_requested < num_pages) {
179  size_t excess_pages = num_pages - num_pages_requested;
180  if (evict_it != slab_segments_[slab_num].end() &&
181  evict_it->mem_status == FREE) { // need to merge with current page
182  evict_it->start_page = start_page + num_pages_requested;
183  evict_it->num_pages += excess_pages;
184  } else { // need to insert a free seg before evict_it for excess_pages
185  BufferSeg free_seg(start_page + num_pages_requested, excess_pages, FREE);
186  slab_segments_[slab_num].insert(evict_it, free_seg);
187  }
188  }
189  return data_seg_it;
190 }
unsigned int buffer_epoch_
Definition: BufferMgr.h:212
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
#define CHECK(condition)
Definition: Logger.h:197

+ Here is the caller graph for this function:

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

Definition at line 749 of file BufferMgr.cpp.

References CHECK, chunk_index_, chunk_index_mutex_, Data_Namespace::AbstractBuffer::copyTo(), createBuffer(), logger::FATAL, global_mutex_, keyToString(), LOG, page_size_, parent_mgr_, Data_Namespace::AbstractBuffer::pin(), Data_Namespace::AbstractBuffer::size(), sized_segs_mutex_, and Data_Namespace::AbstractBuffer::unPin().

751  {
752  std::unique_lock<std::mutex> lock(global_mutex_); // granular lock
753  std::unique_lock<std::mutex> sized_segs_lock(sized_segs_mutex_);
754  std::unique_lock<std::mutex> chunk_index_lock(chunk_index_mutex_);
755 
756  auto buffer_it = chunk_index_.find(key);
757  bool found_buffer = buffer_it != chunk_index_.end();
758  chunk_index_lock.unlock();
759  AbstractBuffer* buffer;
760  if (!found_buffer) {
761  sized_segs_lock.unlock();
762  CHECK(parent_mgr_ != 0);
763  buffer = createBuffer(key, page_size_, num_bytes); // will pin buffer
764  try {
765  parent_mgr_->fetchBuffer(key, buffer, num_bytes);
766  } catch (std::runtime_error& error) {
767  LOG(FATAL) << "Could not fetch parent buffer " << keyToString(key);
768  }
769  } else {
770  buffer = buffer_it->second->buffer;
771  buffer->pin();
772  if (num_bytes > buffer->size()) {
773  try {
774  parent_mgr_->fetchBuffer(key, buffer, num_bytes);
775  } catch (std::runtime_error& error) {
776  LOG(FATAL) << "Could not fetch parent buffer " << keyToString(key);
777  }
778  }
779  sized_segs_lock.unlock();
780  }
781  lock.unlock();
782  buffer->copyTo(dest_buffer, num_bytes);
783  buffer->unPin();
784 }
AbstractBufferMgr * parent_mgr_
Definition: BufferMgr.h:210
AbstractBuffer * createBuffer(const ChunkKey &key, const size_t page_size=0, const size_t initial_size=0) override
Creates a chunk with the specified key and page size.
Definition: BufferMgr.cpp:109
#define LOG(tag)
Definition: Logger.h:188
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
An AbstractBuffer is a unit of data management for a data manager.
void copyTo(AbstractBuffer *destination_buffer, const size_t num_bytes=0)
#define CHECK(condition)
Definition: Logger.h:197
std::string keyToString(const ChunkKey &key)
Definition: BufferMgr.cpp:36

+ Here is the call graph for this function:

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

Gets a buffer of required size and returns an iterator to it.

If possible, this function will just select a free buffer of sufficient size and use that. If not, it will evict as many non-pinned but used buffers as needed to have enough space for the buffer

Returns
An iterator to the reserved buffer. We guarantee that this buffer won't be evicted by PINNING it - caller should change this to USED if applicable

Definition at line 275 of file BufferMgr.cpp.

References addSlab(), allocations_capped_, current_max_slab_page_size_, logger::ERROR, evict(), measure< TimeT >::execution(), findFreeBufferInSlab(), logger::INFO, LOG, max_buffer_pool_num_pages_, max_num_pages_per_slab_, min_num_pages_per_slab_, num_pages_allocated_, page_size_, printSlabs(), slab_segments_, Buffer_Namespace::USED, and VLOG.

Referenced by reserveBuffer().

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

BufferList::iterator Buffer_Namespace::BufferMgr::findFreeBufferInSlab ( const size_t  slab_num,
const size_t  num_pages_requested 
)
private

Definition at line 247 of file BufferMgr.cpp.

References buffer_epoch_, Buffer_Namespace::FREE, slab_segments_, and Buffer_Namespace::USED.

Referenced by findFreeBuffer().

248  {
249  for (auto buffer_it = slab_segments_[slab_num].begin();
250  buffer_it != slab_segments_[slab_num].end();
251  ++buffer_it) {
252  if (buffer_it->mem_status == FREE && buffer_it->num_pages >= num_pages_requested) {
253  // startPage doesn't change
254  size_t excess_pages = buffer_it->num_pages - num_pages_requested;
255  buffer_it->num_pages = num_pages_requested;
256  buffer_it->mem_status = USED;
257  buffer_it->last_touched = buffer_epoch_++;
258  buffer_it->slab_num = slab_num;
259  if (excess_pages > 0) {
260  BufferSeg free_seg(
261  buffer_it->start_page + num_pages_requested, excess_pages, FREE);
262  auto temp_it = buffer_it; // this should make a copy and not be a reference
263  // - as we do not want to increment buffer_it
264  temp_it++;
265  slab_segments_[slab_num].insert(temp_it, free_seg);
266  }
267  return buffer_it;
268  }
269  }
270  // If here then we did not find a free buffer of sufficient size in this slab,
271  // return the end iterator
272  return slab_segments_[slab_num].end();
273 }
unsigned int buffer_epoch_
Definition: BufferMgr.h:212
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183

+ Here is the caller graph for this function:

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

Definition at line 837 of file BufferMgr.cpp.

References deleteBuffer(), logger::FATAL, global_mutex_, LOG, and Buffer_Namespace::Buffer::seg_it_.

837  {
838  std::lock_guard<std::mutex> lock(global_mutex_); // hack for now
839  Buffer* casted_buffer = dynamic_cast<Buffer*>(buffer);
840  if (casted_buffer == 0) {
841  LOG(FATAL) << "Wrong buffer type - expects base class pointer to Buffer type.";
842  }
843  deleteBuffer(casted_buffer->seg_it_->chunk_key);
844 }
#define LOG(tag)
Definition: Logger.h:188
void deleteBuffer(const ChunkKey &key, const bool purge=true) override
Deletes the chunk with the specified key.
Definition: BufferMgr.cpp:591

+ Here is the call graph for this function:

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:

size_t Buffer_Namespace::BufferMgr::getAllocated ( )
override

Definition at line 493 of file BufferMgr.cpp.

References num_pages_allocated_, and page_size_.

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

493  {
495 }

+ Here is the caller graph for this function:

AbstractBuffer * Buffer_Namespace::BufferMgr::getBuffer ( const ChunkKey key,
const size_t  num_bytes = 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 714 of file BufferMgr.cpp.

References buffer_epoch_, CHECK, chunk_index_, chunk_index_mutex_, createBuffer(), logger::FATAL, global_mutex_, keyToString(), LOG, page_size_, parent_mgr_, and sized_segs_mutex_.

714  {
715  std::lock_guard<std::mutex> lock(global_mutex_); // granular lock
716 
717  std::unique_lock<std::mutex> sized_segs_lock(sized_segs_mutex_);
718  std::unique_lock<std::mutex> chunk_index_lock(chunk_index_mutex_);
719  auto buffer_it = chunk_index_.find(key);
720  bool found_buffer = buffer_it != chunk_index_.end();
721  chunk_index_lock.unlock();
722  if (found_buffer) {
723  CHECK(buffer_it->second->buffer);
724  buffer_it->second->buffer->pin();
725  sized_segs_lock.unlock();
726 
727  buffer_it->second->last_touched = buffer_epoch_++; // race
728 
729  if (buffer_it->second->buffer->size() < num_bytes) {
730  // need to fetch part of buffer we don't have - up to numBytes
731  parent_mgr_->fetchBuffer(key, buffer_it->second->buffer, num_bytes);
732  }
733  return buffer_it->second->buffer;
734  } else { // If wasn't in pool then we need to fetch it
735  sized_segs_lock.unlock();
736  // createChunk pins for us
737  AbstractBuffer* buffer = createBuffer(key, page_size_, num_bytes);
738  try {
739  parent_mgr_->fetchBuffer(
740  key, buffer, num_bytes); // this should put buffer in a BufferSegment
741  } catch (std::runtime_error& error) {
742  LOG(FATAL) << "Get chunk - Could not find chunk " << keyToString(key)
743  << " in buffer pool or parent buffer pools. Error was " << error.what();
744  }
745  return buffer;
746  }
747 }
AbstractBufferMgr * parent_mgr_
Definition: BufferMgr.h:210
AbstractBuffer * createBuffer(const ChunkKey &key, const size_t page_size=0, const size_t initial_size=0) override
Creates a chunk with the specified key and page size.
Definition: BufferMgr.cpp:109
#define LOG(tag)
Definition: Logger.h:188
unsigned int buffer_epoch_
Definition: BufferMgr.h:212
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
An AbstractBuffer is a unit of data management for a data manager.
#define CHECK(condition)
Definition: Logger.h:197
std::string keyToString(const ChunkKey &key)
Definition: BufferMgr.cpp:36

+ Here is the call graph for this function:

int Buffer_Namespace::BufferMgr::getBufferId ( )
private

Definition at line 825 of file BufferMgr.cpp.

References buffer_id_mutex_, and max_buffer_id_.

Referenced by alloc().

825  {
826  std::lock_guard<std::mutex> lock(buffer_id_mutex_);
827  return max_buffer_id_++;
828 }

+ Here is the caller graph for this function:

void Buffer_Namespace::BufferMgr::getChunkMetadataVecForKeyPrefix ( ChunkMetadataVector chunk_metadata_vec,
const ChunkKey key_prefix 
)
override

Definition at line 863 of file BufferMgr.cpp.

References logger::FATAL, and LOG.

864  {
865  LOG(FATAL) << "getChunkMetadataVecForPrefix not supported for BufferMgr.";
866 }
#define LOG(tag)
Definition: Logger.h:188
size_t Buffer_Namespace::BufferMgr::getInUseSize ( )
override

Definition at line 507 of file BufferMgr.cpp.

References Buffer_Namespace::FREE, page_size_, and slab_segments_.

507  {
508  size_t in_use = 0;
509  for (auto& segment_list : slab_segments_) {
510  for (auto& segment : segment_list) {
511  if (segment.mem_status != FREE) {
512  in_use += segment.num_pages * page_size_;
513  }
514  }
515  }
516  return in_use;
517 }
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183
size_t Buffer_Namespace::BufferMgr::getMaxBufferSize ( )

Definition at line 855 of file BufferMgr.cpp.

References max_buffer_pool_size_.

855  {
856  return max_buffer_pool_size_;
857 }
const size_t max_buffer_pool_size_
Definition: BufferMgr.h:175
size_t Buffer_Namespace::BufferMgr::getMaxSize ( )
override

Definition at line 488 of file BufferMgr.cpp.

References max_buffer_pool_num_pages_, and page_size_.

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

488  {
490 }

+ Here is the caller graph for this function:

size_t Buffer_Namespace::BufferMgr::getMaxSlabSize ( )

Definition at line 859 of file BufferMgr.cpp.

References max_slab_size_.

859  {
860  return max_slab_size_;
861 }
const size_t max_slab_size_
Definition: BufferMgr.h:178
size_t Buffer_Namespace::BufferMgr::getNumChunks ( )
override

Definition at line 846 of file BufferMgr.cpp.

References chunk_index_, and chunk_index_mutex_.

846  {
847  std::lock_guard<std::mutex> chunk_index_lock(chunk_index_mutex_);
848  return chunk_index_.size();
849 }
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
size_t Buffer_Namespace::BufferMgr::getPageSize ( )

Definition at line 502 of file BufferMgr.cpp.

References page_size_.

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

502  {
503  return page_size_;
504 }

+ Here is the caller graph for this function:

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

Definition at line 868 of file BufferMgr.cpp.

References slab_segments_.

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

868  {
869  return slab_segments_;
870 }
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183

+ Here is the caller graph for this function:

bool Buffer_Namespace::BufferMgr::isAllocationCapped ( )
override

Definition at line 498 of file BufferMgr.cpp.

References allocations_capped_.

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

498  {
499  return allocations_capped_;
500 }

+ Here is the caller graph for this function:

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 581 of file BufferMgr.cpp.

References chunk_index_, and chunk_index_mutex_.

581  {
582  std::lock_guard<std::mutex> chunkIndexLock(chunk_index_mutex_);
583  if (chunk_index_.find(key) == chunk_index_.end()) {
584  return false;
585  } else {
586  return true;
587  }
588 }
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
std::string Buffer_Namespace::BufferMgr::keyToString ( const ChunkKey key)

Definition at line 36 of file BufferMgr.cpp.

Referenced by fetchBuffer(), and getBuffer().

36  {
37  std::ostringstream oss;
38 
39  oss << " key: ";
40  for (auto sub_key : key) {
41  oss << sub_key << ",";
42  }
43  return oss.str();
44 }

+ Here is the caller graph for this function:

BufferMgr& Buffer_Namespace::BufferMgr::operator= ( const BufferMgr )
private
std::string Buffer_Namespace::BufferMgr::printMap ( )

Definition at line 540 of file BufferMgr.cpp.

References chunk_index_, chunk_index_mutex_, and printSeg().

540  {
541  std::ostringstream tss;
542  int seg_num = 1;
543  tss << std::endl
544  << "Map Contents: "
545  << " " << getStringMgrType() << ":" << device_id_ << std::endl;
546  std::lock_guard<std::mutex> chunk_index_lock(chunk_index_mutex_);
547  for (auto seg_it = chunk_index_.begin(); seg_it != chunk_index_.end();
548  ++seg_it, ++seg_num) {
549  // tss << "Map Entry " << seg_num << ": ";
550  // for (auto vec_it = seg_it->first.begin(); vec_it != seg_it->first.end();
551  // ++vec_it)
552  // {
553  // tss << *vec_it << ",";
554  // }
555  // tss << " " << std::endl;
556  tss << printSeg(seg_it->second);
557  }
558  tss << "--------------------" << std::endl;
559  return tss.str();
560 }
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
std::string printSeg(BufferList::iterator &seg_it)
Definition: BufferMgr.cpp:519

+ Here is the call graph for this function:

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

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) << seg_it->slab_num;
522  tss << " SP: " << setfill(' ') << setw(7) << seg_it->start_page;
523  tss << " NP: " << setfill(' ') << setw(7) << seg_it->num_pages;
524  tss << " LT: " << setfill(' ') << setw(7) << seg_it->last_touched;
525  tss << " PC: " << setfill(' ') << setw(2) << seg_it->buffer->getPinCount();
526  if (seg_it->mem_status == FREE) {
527  tss << " FREE"
528  << " ";
529  } else {
530  tss << " USED - Chunk: ";
531  for (auto vec_it = seg_it->chunk_key.begin(); vec_it != seg_it->chunk_key.end();
532  ++vec_it) {
533  tss << *vec_it << ",";
534  }
535  tss << std::endl;
536  }
537  return tss.str();
538 }

+ Here is the caller graph for this function:

void Buffer_Namespace::BufferMgr::printSegs ( )

Definition at line 562 of file BufferMgr.cpp.

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

562  {
563  int seg_num = 1;
564  int slab_num = 1;
565  LOG(INFO) << std::endl << " " << getStringMgrType() << ":" << device_id_;
566  for (auto slab_it = slab_segments_.begin(); slab_it != slab_segments_.end();
567  ++slab_it, ++slab_num) {
568  LOG(INFO) << "Slab Num: " << slab_num << " " << getStringMgrType() << ":"
569  << device_id_;
570  for (auto seg_it = slab_it->begin(); seg_it != slab_it->end(); ++seg_it, ++seg_num) {
571  LOG(INFO) << "Segment: " << seg_num << " " << getStringMgrType() << ":"
572  << device_id_;
573  printSeg(seg_it);
574  LOG(INFO) << " " << getStringMgrType() << ":" << device_id_;
575  }
576  LOG(INFO) << "--------------------"
577  << " " << getStringMgrType() << ":" << device_id_;
578  }
579 }
#define LOG(tag)
Definition: Logger.h:188
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183
std::string printSeg(BufferList::iterator &seg_it)
Definition: BufferMgr.cpp:519

+ Here is the call graph for this function:

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

Definition at line 424 of file BufferMgr.cpp.

References Buffer_Namespace::FREE, and slab_segments_.

Referenced by printSlabs().

424  {
425  std::ostringstream tss;
426  // size_t lastEnd = 0;
427  tss << "Slab St.Page Pages Touch" << std::endl;
428  for (auto segment : slab_segments_[slab_num]) {
429  tss << setfill(' ') << setw(4) << slab_num;
430  // tss << " BSN: " << setfill(' ') << setw(2) << segment.slab_num;
431  tss << setfill(' ') << setw(8) << segment.start_page;
432  tss << setfill(' ') << setw(8) << segment.num_pages;
433  // tss << " GAP: " << setfill(' ') << setw(7) << segment.start_page - lastEnd;
434  // lastEnd = segment.start_page + segment.num_pages;
435  tss << setfill(' ') << setw(7) << segment.last_touched;
436  // tss << " PC: " << setfill(' ') << setw(2) << segment.buffer->getPinCount();
437  if (segment.mem_status == FREE) {
438  tss << " FREE"
439  << " ";
440  } else {
441  tss << " PC: " << setfill(' ') << setw(2) << segment.buffer->getPinCount();
442  tss << " USED - Chunk: ";
443 
444  for (auto&& key_elem : segment.chunk_key) {
445  tss << key_elem << ",";
446  }
447  }
448  tss << std::endl;
449  }
450  return tss.str();
451 }
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183

+ Here is the caller graph for this function:

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

Definition at line 453 of file BufferMgr.cpp.

References printSlab(), and slab_segments_.

Referenced by findFreeBuffer().

453  {
454  std::ostringstream tss;
455  tss << std::endl
456  << "Slabs Contents: "
457  << " " << getStringMgrType() << ":" << device_id_ << std::endl;
458  size_t num_slabs = slab_segments_.size();
459  for (size_t slab_num = 0; slab_num != num_slabs; ++slab_num) {
460  tss << printSlab(slab_num);
461  }
462  tss << "--------------------" << std::endl;
463  return tss.str();
464 }
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183
std::string printSlab(size_t slab_num)
Definition: BufferMgr.cpp:424

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Definition at line 786 of file BufferMgr.cpp.

References Data_Namespace::AbstractBuffer::append(), CHECK, chunk_index_, chunk_index_mutex_, 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(), page_size_, Data_Namespace::AbstractBuffer::size(), Data_Namespace::AbstractBuffer::syncEncoder(), UNREACHABLE, and Data_Namespace::AbstractBuffer::write().

788  {
789  std::unique_lock<std::mutex> chunk_index_lock(chunk_index_mutex_);
790  auto buffer_it = chunk_index_.find(key);
791  bool found_buffer = buffer_it != chunk_index_.end();
792  chunk_index_lock.unlock();
793  AbstractBuffer* buffer;
794  if (!found_buffer) {
795  buffer = createBuffer(key, page_size_);
796  } else {
797  buffer = buffer_it->second->buffer;
798  }
799  size_t old_buffer_size = buffer->size();
800  size_t new_buffer_size = num_bytes == 0 ? src_buffer->size() : num_bytes;
801  CHECK(!buffer->isDirty());
802 
803  if (src_buffer->isUpdated()) {
804  //@todo use dirty flags to only flush pages of chunk that need to
805  // be flushed
806  buffer->write((int8_t*)src_buffer->getMemoryPtr(),
807  new_buffer_size,
808  0,
809  src_buffer->getType(),
810  src_buffer->getDeviceId());
811  } else if (src_buffer->isAppended()) {
812  CHECK(old_buffer_size < new_buffer_size);
813  buffer->append((int8_t*)src_buffer->getMemoryPtr() + old_buffer_size,
814  new_buffer_size - old_buffer_size,
815  src_buffer->getType(),
816  src_buffer->getDeviceId());
817  } else {
818  UNREACHABLE();
819  }
820  src_buffer->clearDirtyBits();
821  buffer->syncEncoder(src_buffer);
822  return buffer;
823 }
AbstractBuffer * createBuffer(const ChunkKey &key, const size_t page_size=0, const size_t initial_size=0) override
Creates a chunk with the specified key and page size.
Definition: BufferMgr.cpp:109
void syncEncoder(const AbstractBuffer *src_buffer)
#define UNREACHABLE()
Definition: Logger.h:241
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
An AbstractBuffer is a unit of data management for a data manager.
virtual void write(int8_t *src, const size_t num_bytes, const size_t offset=0, const MemoryLevel src_buffer_type=CPU_LEVEL, const int src_device_id=-1)=0
virtual void append(int8_t *src, const size_t num_bytes, const MemoryLevel src_buffer_type=CPU_LEVEL, const int device_id=-1)=0
#define CHECK(condition)
Definition: Logger.h:197

+ Here is the call graph for this function:

void Buffer_Namespace::BufferMgr::reinit ( )

Definition at line 85 of file BufferMgr.cpp.

References allocations_capped_, current_max_slab_page_size_, max_num_pages_per_slab_, and num_pages_allocated_.

Referenced by clearSlabs().

85  {
88  max_num_pages_per_slab_; // current_max_slab_page_size_ will drop as allocations
89  // fail - this is the high water mark
90  allocations_capped_ = false;
91 }

+ Here is the caller graph for this function:

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

Definition at line 638 of file BufferMgr.cpp.

References Buffer_Namespace::FREE, slab_segments_, unsized_segs_, and unsized_segs_mutex_.

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

638  {
639  // Note: does not delete buffer as this may be moved somewhere else
640  int slab_num = seg_it->slab_num;
641  // cout << "Slab num: " << slabNum << endl;
642  if (slab_num < 0) {
643  std::lock_guard<std::mutex> unsized_segs_lock(unsized_segs_mutex_);
644  unsized_segs_.erase(seg_it);
645  } else {
646  if (seg_it != slab_segments_[slab_num].begin()) {
647  auto prev_it = std::prev(seg_it);
648  // LOG(INFO) << "PrevIt: " << " " << getStringMgrType() << ":" << device_id_;
649  // printSeg(prev_it);
650  if (prev_it->mem_status == FREE) {
651  seg_it->start_page = prev_it->start_page;
652  seg_it->num_pages += prev_it->num_pages;
653  slab_segments_[slab_num].erase(prev_it);
654  }
655  }
656  auto next_it = std::next(seg_it);
657  if (next_it != slab_segments_[slab_num].end()) {
658  if (next_it->mem_status == FREE) {
659  seg_it->num_pages += next_it->num_pages;
660  slab_segments_[slab_num].erase(next_it);
661  }
662  }
663  seg_it->mem_status = FREE;
664  // seg_it->pinCount = 0;
665  seg_it->buffer = 0;
666  }
667 }
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183
std::mutex unsized_segs_mutex_
Definition: BufferMgr.h:199

+ Here is the caller graph for this function:

void Buffer_Namespace::BufferMgr::removeTableRelatedDS ( const int  db_id,
const int  table_id 
)
override

Definition at line 872 of file BufferMgr.cpp.

References UNREACHABLE.

872  {
873  UNREACHABLE();
874 }
#define UNREACHABLE()
Definition: Logger.h:241
BufferList::iterator Buffer_Namespace::BufferMgr::reserveBuffer ( BufferList::iterator &  seg_it,
const size_t  num_bytes 
)

Definition at line 192 of file BufferMgr.cpp.

References chunk_index_, chunk_index_mutex_, findFreeBuffer(), Buffer_Namespace::FREE, page_size_, removeSegment(), slab_segments_, and slabs_.

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

194  { // assumes buffer is already pinned
195 
196  size_t num_pages_requested = (num_bytes + page_size_ - 1) / page_size_;
197  size_t num_pages_extra_needed = num_pages_requested - seg_it->num_pages;
198 
199  if (num_pages_requested < seg_it->num_pages) {
200  // We already have enough pages in existing segment
201  return seg_it;
202  }
203  // First check for free segment after seg_it
204  int slab_num = seg_it->slab_num;
205  if (slab_num >= 0) { // not dummy page
206  BufferList::iterator next_it = std::next(seg_it);
207  if (next_it != slab_segments_[slab_num].end() && next_it->mem_status == FREE &&
208  next_it->num_pages >= num_pages_extra_needed) {
209  // Then we can just use the next BufferSeg which happens to be free
210  size_t leftover_pages = next_it->num_pages - num_pages_extra_needed;
211  seg_it->num_pages = num_pages_requested;
212  next_it->num_pages = leftover_pages;
213  next_it->start_page = seg_it->start_page + seg_it->num_pages;
214  return seg_it;
215  }
216  }
217  // If we're here then we couldn't keep buffer in existing slot
218  // need to find new segment, copy data over, and then delete old
219  auto new_seg_it = findFreeBuffer(num_bytes);
220 
221  // Below should be in copy constructor for BufferSeg?
222  new_seg_it->buffer = seg_it->buffer;
223  new_seg_it->chunk_key = seg_it->chunk_key;
224  int8_t* old_mem = new_seg_it->buffer->mem_;
225  new_seg_it->buffer->mem_ =
226  slabs_[new_seg_it->slab_num] + new_seg_it->start_page * page_size_;
227 
228  // now need to copy over memory
229  // only do this if the old segment is valid (i.e. not new w/ unallocated buffer
230  if (seg_it->start_page >= 0 && seg_it->buffer->mem_ != 0) {
231  new_seg_it->buffer->writeData(old_mem,
232  new_seg_it->buffer->size(),
233  0,
234  new_seg_it->buffer->getType(),
235  device_id_);
236  }
237  // Decrement pin count to reverse effect above
238  removeSegment(seg_it);
239  {
240  std::lock_guard<std::mutex> lock(chunk_index_mutex_);
241  chunk_index_[new_seg_it->chunk_key] = new_seg_it;
242  }
243 
244  return new_seg_it;
245 }
BufferList::iterator findFreeBuffer(size_t num_bytes)
Gets a buffer of required size and returns an iterator to it.
Definition: BufferMgr.cpp:275
void removeSegment(BufferList::iterator &seg_it)
Definition: BufferMgr.cpp:638
std::vector< BufferList > slab_segments_
Definition: BufferMgr.h:183
std::map< ChunkKey, BufferList::iterator > chunk_index_
Definition: BufferMgr.h:203
std::vector< int8_t * > slabs_
Definition: BufferMgr.h:181

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

size_t Buffer_Namespace::BufferMgr::size ( )

Returns the total number of bytes allocated.

Definition at line 851 of file BufferMgr.cpp.

References num_pages_allocated_.

851  {
852  return num_pages_allocated_;
853 }

Member Data Documentation

bool Buffer_Namespace::BufferMgr::allocations_capped_
private

Definition at line 209 of file BufferMgr.h.

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

unsigned int Buffer_Namespace::BufferMgr::buffer_epoch_
private

Definition at line 212 of file BufferMgr.h.

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

std::mutex Buffer_Namespace::BufferMgr::buffer_id_mutex_
private

Definition at line 200 of file BufferMgr.h.

Referenced by getBufferId().

std::map<ChunkKey, BufferList::iterator> Buffer_Namespace::BufferMgr::chunk_index_
private
std::mutex Buffer_Namespace::BufferMgr::chunk_index_mutex_
private
size_t Buffer_Namespace::BufferMgr::current_max_slab_page_size_
private

Definition at line 208 of file BufferMgr.h.

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

std::mutex Buffer_Namespace::BufferMgr::global_mutex_
private

Definition at line 201 of file BufferMgr.h.

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

int Buffer_Namespace::BufferMgr::max_buffer_id_
private

Definition at line 211 of file BufferMgr.h.

Referenced by getBufferId().

size_t Buffer_Namespace::BufferMgr::max_buffer_pool_num_pages_
private

Definition at line 204 of file BufferMgr.h.

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

const size_t Buffer_Namespace::BufferMgr::max_buffer_pool_size_
protected

Definition at line 175 of file BufferMgr.h.

Referenced by BufferMgr(), and getMaxBufferSize().

size_t Buffer_Namespace::BufferMgr::max_num_pages_per_slab_
private

Definition at line 207 of file BufferMgr.h.

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

const size_t Buffer_Namespace::BufferMgr::max_slab_size_
protected

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

Definition at line 178 of file BufferMgr.h.

Referenced by BufferMgr(), Buffer_Namespace::CpuBufferMgr::freeAllMem(), and getMaxSlabSize().

size_t Buffer_Namespace::BufferMgr::min_num_pages_per_slab_
private

Definition at line 206 of file BufferMgr.h.

Referenced by BufferMgr(), and findFreeBuffer().

const size_t Buffer_Namespace::BufferMgr::min_slab_size_
protected

max number of bytes allocated for the buffer pool

Definition at line 176 of file BufferMgr.h.

Referenced by BufferMgr().

size_t Buffer_Namespace::BufferMgr::num_pages_allocated_
private

Definition at line 205 of file BufferMgr.h.

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

const size_t Buffer_Namespace::BufferMgr::page_size_
protected

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

Definition at line 180 of file BufferMgr.h.

Referenced by Buffer_Namespace::GpuCudaBufferMgr::addSlab(), Buffer_Namespace::CpuBufferMgr::addSlab(), alloc(), BufferMgr(), createBuffer(), fetchBuffer(), findFreeBuffer(), getAllocated(), getBuffer(), getInUseSize(), getMaxSize(), getPageSize(), putBuffer(), and reserveBuffer().

AbstractBufferMgr* Buffer_Namespace::BufferMgr::parent_mgr_
private

Definition at line 210 of file BufferMgr.h.

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

std::mutex Buffer_Namespace::BufferMgr::sized_segs_mutex_
private

Definition at line 198 of file BufferMgr.h.

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

std::vector<BufferList> Buffer_Namespace::BufferMgr::slab_segments_
protected
std::vector<int8_t*> Buffer_Namespace::BufferMgr::slabs_
protected
BufferList Buffer_Namespace::BufferMgr::unsized_segs_
private

Definition at line 214 of file BufferMgr.h.

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

std::mutex Buffer_Namespace::BufferMgr::unsized_segs_mutex_
private

Definition at line 199 of file BufferMgr.h.

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


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