Skip to main content

Buffer Layer Stub Code

StaticBuffer.cpp

StaticBuffer::StaticBuffer(){
// copy Block Allocation Map blocks from disk to blockAllocMap using Disk::readBlock()

//initialize metaInfo of all the buffer blocks with free:true, dirty:false, blockNum:-1 and timeStamp:-1.
}


StaticBuffer::~StaticBuffer(){
// copy blockAllocMap to Block Allocation Map blocks in the disk using Disk::writeBlock().

/* iterate through all the metaInfo entries,
write back buffer blocks with meta-info as free:false,dirty:true using Disk::writeBlock().*/
}


int StaticBuffer::getStaticBlockType(int blockNum){
// Check if blockNum is valid (non zero and less than number of disk blocks)
// and return E_OUTOFBOUND if not valid.

// Access the entry in block allocation map corresponding to the blockNum argument
// and return the block type after type casting to integer.
}


int StaticBuffer::setDirtyBit(int blockNum){
// find the buffer index corresponding to the block using getBufferNum().

// if block is not present in the buffer (bufferNum = E_BLOCKNOTINBUFFER)
// return E_BLOCKNOTINBUFFER

// if blockNum is out of bound (bufferNum = E_OUTOFBOUND)
// return E_OUTOFBOUND

// else
// (the bufferNum is valid)
// set the dirty bit of that buffer to true in metainfo

// return SUCCESS
}


int StaticBuffer::getBufferNum(int blockNum){
// Check if blockNum is valid (non zero and less than number of disk blocks)
// and return E_OUTOFBOUND if not valid.

// traverse through the metaInfo array and
// find the buffer number of the buffer to which the block is loaded.

// if found return buffer number

// if block not found in buffer return E_BLOCKNOTINBUFFER
}


int StaticBuffer::getBufferNum(int blockNum){
// Check if blockNum is valid (non zero and less than number of disk blocks)
// and return E_OUTOFBOUND if not valid.

// traverse through the metaInfo array and
// find the buffer number of the buffer to which the block is loaded.

// if found return buffer number

// if block not found in buffer return E_BLOCKNOTINBUFFER
}

BlockBuffer.cpp

BlockBuffer::BlockBuffer(char blockType){
// allocate a block on the disk and a buffer in memory to hold the new block of
// given type using getFreeBlock function and get the return error codes if any.

// set the blockNum field of the object to that of the allocated block
// number if the method returned a valid block number,
// otherwise set the error code returned as the block number.

// (The caller must check if the constructor allocatted block successfully
// by checking the value of block number field.)
}


BlockBuffer::BlockBuffer(int blockNum){

// set the blockNum field of the object to input argument.
}


int BlockBuffer::getBlockNum(){

//return corresponding block number.
}


int BlockBuffer::getHeader(struct HeadInfo *head){

unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block
using loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// cast bufferPtr to type HeadInfo*
struct HeadInfo *bufferHeader = (struct HeadInfo *)bufferPtr;

// copy all the values except reserved in the header (from bufferHeader)
// to the argument `head`
// (hint: head->numEntries = bufferHeader->numEntries)

// return SUCCESS
}


int BlockBuffer::setHeader(struct HeadInfo *head){

unsigned char *bufferPtr;
// get the starting address of the buffer containing the block using
// loadBlockAndGetBufferPtr(&bufferPtr).

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// cast bufferPtr to type HeadInfo*
struct HeadInfo *bufferHeader = (struct HeadInfo *)bufferPtr;

// copy the fields of the HeadInfo pointed to by head (except reserved) to
// the header of the block (pointed to by bufferHeader)
//(hint: bufferHeader->numSlots = head->numSlots )

// update dirty bit by calling StaticBuffer::setDirtyBit()
// if setDirtyBit() failed, return the error code

// return SUCCESS;
}


void BlockBuffer::releaseBlock(){

// if blockNum is INVALID_BLOCK (-1), or it is invalidated already, do nothing

// else
/* get the buffer number of the buffer assigned to the block
using StaticBuffer::getBufferNum().
(this function return E_BLOCKNOTINBUFFER if the block is not
currently loaded in the buffer)
*/

// if the block is present in the buffer, free the buffer
// by setting the free flag of its StaticBuffer::tableMetaInfo entry
// to true.

// free the block in disk by setting the data type of the entry
// corresponding to the block number in StaticBuffer::blockAllocMap
// to UNUSED_BLK.

// set the object's blockNum to INVALID_BLOCK (-1)
}


int BlockBuffer::loadBlockAndGetBufferPtr(unsigned char ** buffPtr) {
/* check whether the block is already present in the buffer
using StaticBuffer.getBufferNum() */
int bufferNum = StaticBuffer::getBufferNum(this->blockNum);

// if present (!=E_BLOCKNOTINBUFFER),
// set the timestamp of the corresponding buffer to 0 and increment the
// timestamps of all other occupied buffers in BufferMetaInfo.

// else
// get a free buffer using StaticBuffer.getFreeBuffer()

// if the call returns E_OUTOFBOUND, return E_OUTOFBOUND here as
// the blockNum is invalid

// Read the block into the free buffer using readBlock()

// store the pointer to this buffer (blocks[bufferNum]) in *buffPtr

// return SUCCESS;
}


int BlockBuffer::getFreeBlock(int blockType){

// iterate through the StaticBuffer::blockAllocMap and find the block number
// of a free block in the disk.

// if no block is free, return E_DISKFULL.

// set the object's blockNum to the block number of the free block.

// find a free buffer using StaticBuffer::getFreeBuffer() .

// initialize the header of the block passing a struct HeadInfo with values
// pblock: -1, lblock: -1, rblock: -1, numEntries: 0, numAttrs: 0, numSlots: 0
// to the setHeader() function.

// update the block type of the block to the input block type using setBlockType().

// return block number of the free block.
}


int BlockBuffer::setBlockType(int blockType){

unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block
using loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// store the input block type in the first 4 bytes of the buffer.
// (hint: cast bufferPtr to int32_t* and then assign it)
// *((int32_t *)bufferPtr) = blockType;

// update the StaticBuffer::blockAllocMap entry corresponding to the
// object's block number to `blockType`.

// update dirty bit by calling StaticBuffer::setDirtyBit()
// if setDirtyBit() failed
// return the returned value from the call

// return SUCCESS
}


RecBuffer::RecBuffer() : BlockBuffer('R'){}

RecBuffer::RecBuffer(int blockNum) : BlockBuffer(blockNum){}


int RecBuffer::getSlotMap(unsigned char *slotMap) {
unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block using
loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// get the header of the block using the getHeader() function

int numSlots = /* the number of slots in the block */;

// the slotmap starts at bufferPtr + HEADER_SIZE. Copy the contents of the
// slotmap in the buffer to the argument `slotMap`.
// Note that size of slotmap is `numSlots`

// return SUCCESS
}


int RecBuffer::setSlotMap(unsigned char *slotMap) {
unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block using
loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// get the header of the block using the getHeader() function

int numSlots = /* the number of slots in the block */;

// the slotmap starts at bufferPtr + HEADER_SIZE. Copy the contents of the
// argument `slotMap` to the buffer replacing the existing slotmap.
// Note that size of slotmap is `numSlots`

// update dirty bit using StaticBuffer::setDirtyBit
// if setDirtyBit failed, return the value returned by the call

// return SUCCESS
}


int RecBuffer::getRecord(union Attribute *rec, int slotNum) {
unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block
using loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// get the header using the getHeader() function

// get number of attributes in the block.

// get the number of slots in the block.

// if input slotNum is not in the permitted range return E_OUTOFBOUND

// if slot corresponding to input slotNum is free return E_FREESLOT

/* offset bufferPtr to point to the beginning of the record at required
slot. the block contains the header, the slotmap, followed by all
the records. so, for example,
record at slot x will be at bufferPtr + HEADER_SIZE + (x*recordSize)
copy the record from buffer to `rec` using memcpy
(hint: a record will be of size ATTR_SIZE * numAttrs)
*/

// return SUCCESS
}


int RecBuffer::setRecord(union Attribute *rec, int slotNum) {
unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block
using loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

/* get the header of the block using the getHeader() function */

// get number of attributes in the block.

// get the number of slots in the block.

// if input slotNum is not in the permitted range return E_OUTOFBOUND.

/* offset bufferPtr to point to the beginning of the record at required
slot. the block contains the header, the slotmap, followed by all
the records. so, for example,
record at slot x will be at bufferPtr + HEADER_SIZE + (x*recordSize)
copy the record from `rec` to buffer using memcpy
(hint: a record will be of size ATTR_SIZE * numAttrs)
*/

// update dirty bit using setDirtyBit()

/* (the above function call should not fail since the block is already
in buffer and the blockNum is valid. If the call does fail, there
exists some other issue in the code) */

// return SUCCESS
}


IndBuffer::IndBuffer(char blockType) : BlockBuffer(blockType){}

IndBuffer::IndBuffer(int blockNum) : BlockBuffer(blockNum){}

IndInternal::IndInternal() : IndBuffer('I'){}

IndInternal::IndInternal(int blockNum) : IndBuffer(blockNum){}


int IndInternal::getEntry(void *ptr, int indexNum) {
// if the indexNum is not in the valid range of [0, MAX_KEYS_INTERNAL-1]
// return E_OUTOFBOUND.

unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block
using loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// typecast the void pointer to an internal entry pointer
struct InternalEntry *internalEntry = (struct InternalEntry *)ptr;

/*
- copy the entries from the indexNum`th entry to *internalEntry
- make sure that each field is copied individually as in the following code
- the lChild and rChild fields of InternalEntry are of type int32_t
- int32_t is a type of int that is guaranteed to be 4 bytes across every
C++ implementation. sizeof(int32_t) = 4
*/

/* the indexNum'th entry will begin at an offset of
HEADER_SIZE + (indexNum * (sizeof(int) + ATTR_SIZE) ) [why?]
from bufferPtr */
unsigned char *entryPtr = bufferPtr + HEADER_SIZE + (indexNum * 20);

memcpy(&(internalEntry->lChild), entryPtr, sizeof(int32_t));
memcpy(&(internalEntry->attrVal), entryPtr + 4, sizeof(Attribute));
memcpy(&(internalEntry->rChild), entryPtr + 20, 4);

// return SUCCESS.
}


int IndInternal::setEntry(void *ptr, int indexNum) {
// if the indexNum is not in the valid range of [0, MAX_KEYS_INTERNAL-1]
// return E_OUTOFBOUND.

unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block
using loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// typecast the void pointer to an internal entry pointer
struct InternalEntry *internalEntry = (struct InternalEntry *)ptr;

/*
- copy the entries from *internalEntry to the indexNum`th entry
- make sure that each field is copied individually as in the following code
- the lChild and rChild fields of InternalEntry are of type int32_t
- int32_t is a type of int that is guaranteed to be 4 bytes across every
C++ implementation. sizeof(int32_t) = 4
*/

/* the indexNum'th entry will begin at an offset of
HEADER_SIZE + (indexNum * (sizeof(int) + ATTR_SIZE) ) [why?]
from bufferPtr */

unsigned char *entryPtr = bufferPtr + HEADER_SIZE + (indexNum * 20);

memcpy(entryPtr, &(internalEntry->lChild), 4);
memcpy(entryPtr + 4, &(internalEntry->attrVal), ATTR_SIZE);
memcpy(entryPtr + 20, &(internalEntry->rChild), 4);


// update dirty bit using setDirtyBit()
// if setDirtyBit failed, return the value returned by the call

// return SUCCESS
}


IndLeaf::IndLeaf() : IndBuffer('L'){}

IndLeaf::IndLeaf(int blockNum) : IndBuffer(blockNum){}


int IndLeaf::getEntry(void *ptr, int indexNum) {

// if the indexNum is not in the valid range of [0, MAX_KEYS_LEAF-1]
// return E_OUTOFBOUND.

unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block
using loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// copy the indexNum'th Index entry in buffer to memory ptr using memcpy

/* the indexNum'th entry will begin at an offset of
HEADER_SIZE + (indexNum * LEAF_ENTRY_SIZE) from bufferPtr */
unsigned char *entryPtr = bufferPtr + HEADER_SIZE + (indexNum * LEAF_ENTRY_SIZE);
memcpy((struct Index *)ptr, entryPtr, LEAF_ENTRY_SIZE);

// return SUCCESS
}


int IndLeaf::setEntry(void *ptr, int indexNum) {

// if the indexNum is not in the valid range of [0, MAX_KEYS_LEAF-1]
// return E_OUTOFBOUND.

unsigned char *bufferPtr;
/* get the starting address of the buffer containing the block
using loadBlockAndGetBufferPtr(&bufferPtr). */

// if loadBlockAndGetBufferPtr(&bufferPtr) != SUCCESS
// return the value returned by the call.

// copy the Index at ptr to indexNum'th entry in the buffer using memcpy

/* the indexNum'th entry will begin at an offset of
HEADER_SIZE + (indexNum * LEAF_ENTRY_SIZE) from bufferPtr */
unsigned char *entryPtr = bufferPtr + HEADER_SIZE + (indexNum * LEAF_ENTRY_SIZE);
memcpy(entryPtr, (struct Index *)ptr, LEAF_ENTRY_SIZE);

// update dirty bit using setDirtyBit()
// if setDirtyBit failed, return the value returned by the call

//return SUCCESS
}