Chunk Class Reference

#include <Allocator.h>

Collaboration diagram for Chunk:

Collaboration graph
[legend]

Public Member Functions

void setSize (size_t size)
size_t getSize ()
void setChunkID (unsigned int id)
int getChunkID ()
void setAllocType (AllocType type)
AllocType getAllocType ()
PageInfogetPageInfo (Database *db, void *ptr)
void * allocate (Database *db, DbRetVal *status=NULL)
void * allocate (Database *db, size_t size, DbRetVal *status=NULL)
void free (Database *db, void *ptr)
ChunkIterator getIterator ()
void print ()
long getTotalDataNodes ()
int totalPages ()
int compact ()

Friends

class Database
class DatabaseManagerImpl

Detailed Description

Definition at line 95 of file Allocator.h.


Member Function Documentation

void * Chunk::allocate ( Database db,
size_t  size,
DbRetVal status = NULL 
)

Definition at line 355 of file Chunk.cxx.

References os::align(), ErrLockTimeOut, ErrNoMemory, PAGE_SIZE, printError, and Database::procSlot.

00356 {
00357     if (0 == size) return NULL;
00358     //check if the size is more than PAGE_SIZE
00359     //if it is more than the PAGE_SIZE, then allocate new
00360     //page using database and then link the curPage to the
00361     //newly allocated page
00362     //if it is less than PAGE_SIZE, then check the curpage for
00363     //free memory of specified size
00364     //if not available, then scan from the firstPage for the free
00365     //space
00366 
00367     //TODO::During the scan, merge nearby nodes if both are free
00368     //if not available then allocate new page
00369 
00370     size_t alignedSize = os::align(size);
00371     void *data = NULL;
00372     int ret = getChunkMutex(db->procSlot);
00373     if (ret != 0)
00374     {
00375         printError(ErrLockTimeOut,"Unable to acquire chunk Mutex");
00376         *status = ErrLockTimeOut;
00377         return NULL;
00378     }
00379     if (alignedSize > PAGE_SIZE)
00380     {
00381         data =  allocateForLargeDataSize(db, alignedSize);
00382     }
00383     else
00384     {
00385         data = allocateFromCurPageForVarSize(alignedSize);
00386         if (NULL == data) {
00387             //No available spaces in the current page.
00388             //allocate new page
00389             data= allocFromNewPageForVarSize(db, alignedSize);
00390             if (NULL == data) {
00391                 printError(ErrNoMemory, "No memory in any of the pages:Increase db size");
00392                 if (status != NULL) *status = ErrNoMemory;
00393             }
00394         }
00395     }
00396     releaseChunkMutex(db->procSlot);
00397     return data;
00398 }

Here is the call graph for this function:

void * Chunk::allocate ( Database db,
DbRetVal status = NULL 
)

Definition at line 163 of file Chunk.cxx.

References DM_Alloc, ErrLockTimeOut, ErrNoMemory, os::floor(), PageInfo::hasFreeSpace_, LockTableId, PAGE_SIZE, printDebug, printError, Database::procSlot, and TransHasTableId.

Referenced by Database::allocLockHashBuckets(), Transaction::createUndoLog(), CatalogTableUSER::insert(), CatalogTableINDEXFIELD::insert(), CatalogTableINDEX::insert(), CatalogTableFIELD::insert(), CatalogTableTABLE::insert(), BucketList::insert(), and Transaction::insertIntoHasList().

00164 {
00165     PageInfo* pageInfo = ((PageInfo*)curPage_);
00166 
00167     int noOfDataNodes=os::floor((PAGE_SIZE - sizeof(PageInfo))/allocSize_);
00168     char *data = ((char*)curPage_) + sizeof(PageInfo);
00169     printDebug(DM_Alloc, "Chunk::allocate id:%d curPage:%x noOfDataNodes:%d",
00170                          chunkID_, curPage_, noOfDataNodes);
00171     
00172     //1.scan through data list and find if any is free to use in current page
00173     //2.If there is none then
00174     //    a) get new free page from db. set the prev->next to point
00175     //       to this new page
00176     //4.  b) initialize the free page to zero and get first data ptr.
00177     //5.If there is one, return that
00178 
00179     //For allocation more than PAGE_SIZE
00180     if (0 == noOfDataNodes)
00181     {
00182         data = (char*) allocateForLargeDataSize(db);
00183         return data;
00184     }
00185 
00186     int ret = getChunkMutex(db->procSlot);
00187     if (ret != 0)
00188     {
00189         if (status != NULL) *status = ErrLockTimeOut;
00190         printError(ErrLockTimeOut,"Unable to acquire chunk Mutex");
00191         return NULL;
00192     }
00193     int i = noOfDataNodes;
00194     if (pageInfo->hasFreeSpace_ == 1)
00195     {
00196         for (i = 1; i< noOfDataNodes; i++)
00197         {
00198             if (*((int*)data) == 1) data = data + allocSize_;
00199             else break;
00200         }
00201 
00202     }
00203     printDebug(DM_Alloc, "ChunkID:%d Node which might be free is %d",
00204                                                         chunkID_, i);
00205     //It comes here if the pageInfo->hasFreeSpace ==0
00206     //or there are no free data space in this page
00207     if (i == noOfDataNodes && *((int*)data) == 1)
00208     {
00209 
00210         printDebug(DM_Alloc, "ChunkID:%d curPage does not have free nodes.", chunkID_);
00211         //there are no free data space in this page
00212         pageInfo->hasFreeSpace_ = 0;
00213         if (chunkID_ == LockTableId || chunkID_ == TransHasTableId) 
00214         {
00215            data = (char*) allocateFromFirstPage(db, noOfDataNodes);
00216            if (NULL == data)
00217            {
00218               data = (char*) allocateFromNewPage(db);
00219               if (data == NULL)
00220               {
00221                 printError(ErrNoMemory, "No memory in any of the pages:Increase db size");
00222                 if (status != NULL) *status = ErrNoMemory;
00223               }
00224            }
00225         } 
00226         else 
00227         {
00228            data = (char*) allocateFromNewPage(db);
00229            if (NULL == data)
00230            {
00231               data = (char*) allocateFromFirstPage(db, noOfDataNodes);
00232               if (data == NULL)
00233               {
00234                 printError(ErrNoMemory, "No memory in any of the pages:Increase db size");
00235                 if (status != NULL) *status = ErrNoMemory;
00236               }
00237            }
00238         }
00239         releaseChunkMutex(db->procSlot);
00240         return data;
00241     }
00242     *((int*)data) = 1;
00243     releaseChunkMutex(db->procSlot);
00244     return data + sizeof(int);
00245 }

Here is the call graph for this function:

Here is the caller graph for this function:

int Chunk::compact (  ) 

Definition at line 594 of file Chunk.cxx.

References DM_Alloc, DM_VarAlloc, os::floor(), PageInfo::isUsed_, VarSizeInfo::isUsed_, PageInfo::nextPage_, PAGE_SIZE, printDebug, and VarSizeInfo::size_.

00595 {
00596     PageInfo* pageInfo = ((PageInfo*)firstPage_);
00597     PageInfo* prevPage = pageInfo;
00598     if (NULL == pageInfo) 
00599     {
00600         return 0;
00601     }
00602     pageInfo = (PageInfo*)pageInfo->nextPage_;
00603     if (0 == allocSize_) 
00604     {
00605       while( pageInfo != NULL )
00606       {
00607         bool flag = false;
00608         VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)pageInfo) +
00609                                             sizeof(PageInfo));
00610         while ((char*) varInfo < ((char*)pageInfo + PAGE_SIZE))
00611         {
00612             if (1 == varInfo->isUsed_) {flag=true; break;}
00613             varInfo = (VarSizeInfo*)((char*)varInfo + sizeof(VarSizeInfo)
00614                                    +varInfo->size_);
00615         }
00616         if (!flag) {
00617             printDebug(DM_VarAlloc,"Freeing unused page in varsize allocator %x\n", pageInfo);
00618             prevPage->nextPage_ = pageInfo->nextPage_;
00619             pageInfo->isUsed_ = 0;
00620         }
00621         prevPage = pageInfo;
00622         pageInfo = (PageInfo*)(((PageInfo*)pageInfo)->nextPage_) ;
00623         printDebug(DM_VarAlloc,"compact iter %x\n", pageInfo);
00624       }
00625     }else if (allocSize_ < PAGE_SIZE)
00626     {
00627       while( pageInfo != NULL )
00628       {
00629         bool flag = false;
00630         int noOfDataNodes=os::floor((PAGE_SIZE - sizeof(PageInfo))/allocSize_);
00631         char *data = ((char*)pageInfo) + sizeof(PageInfo);
00632         for (int i = 0; i< noOfDataNodes -1; i++)
00633         {
00634             if (1 == *((int*)data)) { flag = true; break; }
00635             data = data +allocSize_;
00636         }
00637         if (!flag) {
00638             printDebug(DM_Alloc,"Freeing unused page in fixed allocator %x\n", pageInfo);
00639             prevPage->nextPage_ = pageInfo->nextPage_;
00640             pageInfo->isUsed_ = 0;
00641         }
00642         prevPage = pageInfo;
00643         pageInfo = (PageInfo*)(((PageInfo*)pageInfo)->nextPage_) ;
00644         printDebug(DM_Alloc,"compact iter %x\n", pageInfo);
00645       }
00646     }
00647     return 0;
00648 }

Here is the call graph for this function:

void Chunk::free ( Database db,
void *  ptr 
)

Definition at line 487 of file Chunk.cxx.

References ErrLockTimeOut, ErrSysFatal, os::floor(), getPageInfo(), PageInfo::hasFreeSpace_, PAGE_SIZE, printError, and Database::procSlot.

Referenced by Transaction::applyUndoLogs(), DatabaseManagerImpl::dropTable(), Transaction::releaseAllLocks(), CatalogTableUSER::remove(), CatalogTableINDEXFIELD::remove(), CatalogTableINDEX::remove(), CatalogTableFIELD::remove(), CatalogTableTABLE::remove(), BucketList::remove(), Transaction::removeFromHasList(), and Transaction::removeUndoLogs().

00488 {
00489     if (0 == allocSize_)
00490     {
00491         freeForVarSizeAllocator(ptr, db->procSlot);
00492         return;
00493     }
00494     int noOfDataNodes =os::floor((PAGE_SIZE - sizeof(PageInfo)) / allocSize_);
00495 
00496     if (0 == noOfDataNodes)
00497     {
00498         freeForLargeAllocator(ptr, db->procSlot);
00499         return;
00500     }
00501     int ret = getChunkMutex(db->procSlot);
00502     if (ret != 0)
00503     {
00504         printError(ErrLockTimeOut,"Unable to acquire chunk Mutex");
00505         return;
00506     }
00507      //below is the code for freeing in fixed size allocator
00508 
00509      //unset the used flag
00510     *((int*)ptr -1 ) = 0;
00511     PageInfo *pageInfo;
00512     pageInfo = getPageInfo(db, ptr);
00513     if (NULL == pageInfo)
00514     {
00515         printError(ErrSysFatal,"Probable Data corruption: pageInfo is NULL", pageInfo );
00516         releaseChunkMutex(db->procSlot);
00517         return;
00518     }
00519     //set the pageinfo where this ptr points
00520     pageInfo->hasFreeSpace_ = 1;
00521     releaseChunkMutex(db->procSlot);
00522     return;
00523 }

Here is the call graph for this function:

Here is the caller graph for this function:

AllocType Chunk::getAllocType (  )  [inline]

Definition at line 123 of file Allocator.h.

00123 { return allocType_; }

int Chunk::getChunkID (  )  [inline]

Definition at line 121 of file Allocator.h.

00121 { return chunkID_; }

ChunkIterator Chunk::getIterator (  ) 

Definition at line 23 of file ChunkIterator.cxx.

References ChunkIterator::allocSize_, ChunkIterator::allocType_, ChunkIterator::chunkID_, os::floor(), ChunkIterator::iterPage_, ChunkIterator::nodeOffset_, ChunkIterator::noOfNodes_, and PAGE_SIZE.

Referenced by CatalogTableUSER::authenticate(), CatalogTableUSER::changePass(), CatalogTableINDEX::get(), CatalogTableTABLE::getChunkAndTblPtr(), CatalogTableFIELD::getFieldInfo(), CatalogTableINDEXFIELD::getFieldNameAndType(), CatalogTableFIELD::getFieldPtrs(), CatalogTableINDEX::getIndexName(), CatalogTableINDEX::getIndexPtrs(), Database::getLockHashBuckets(), CatalogTableINDEX::getNumIndexes(), CatalogTableTABLE::getTableList(), CatalogTableINDEXFIELD::insert(), CatalogTableINDEX::insert(), CatalogTableUSER::remove(), CatalogTableINDEXFIELD::remove(), CatalogTableINDEX::remove(), CatalogTableFIELD::remove(), and CatalogTableTABLE::remove().

00024 {
00025     ChunkIterator iter;
00026     iter.chunkID_ = chunkID_;
00027     iter.allocSize_ = allocSize_;
00028     iter.allocType_ = allocType_;
00029     iter.iterPage_ = firstPage_;
00030     iter.nodeOffset_ = 0;
00031     iter.noOfNodes_ = os::floor((PAGE_SIZE - sizeof(PageInfo)) / allocSize_);
00032     return iter;
00033 }

Here is the call graph for this function:

Here is the caller graph for this function:

PageInfo * Chunk::getPageInfo ( Database db,
void *  ptr 
)

Definition at line 530 of file Chunk.cxx.

References PageInfo::nextPage_, PageInfo::nextPageAfterMerge_, and PAGE_SIZE.

Referenced by free().

00531 {
00532     if (allocSize_ < PAGE_SIZE - sizeof(PageInfo)) { 
00533        int rem = (long) ptr % 8192;
00534        return (PageInfo*)(((char*)ptr) - rem);
00535     } else {
00536         //large size allocator
00537         char *inPtr = (char*)ptr;
00538         PageInfo* pageInfo = ((PageInfo*)firstPage_);
00539 
00540         while( pageInfo != NULL )
00541         {
00542           if (inPtr > (char*) pageInfo && pageInfo->nextPageAfterMerge_ >inPtr)
00543             return pageInfo;
00544         pageInfo = (PageInfo*)pageInfo->nextPage_ ;
00545         }
00546     }
00547     return NULL;
00548 }

Here is the caller graph for this function:

size_t Chunk::getSize (  )  [inline]

Definition at line 119 of file Allocator.h.

Referenced by TableImpl::spaceUsed().

00119 { return allocSize_; }

Here is the caller graph for this function:

long Chunk::getTotalDataNodes (  ) 

Definition at line 552 of file Chunk.cxx.

References os::floor(), VarSizeInfo::isUsed_, PAGE_SIZE, and VarSizeInfo::size_.

Referenced by DatabaseManagerImpl::printIndexInfo(), and TableImpl::spaceUsed().

00553 {
00554     long totalNodes =0;
00555     if (0 == allocSize_) //->variable size allocator
00556     {
00557         Page *page = ((PageInfo*)firstPage_);
00558         while(NULL != page)
00559         {
00560             VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)page) + sizeof(PageInfo));
00561             while ((char*) varInfo < ((char*)page + PAGE_SIZE))
00562             {
00563                 if (1 == varInfo->isUsed_) totalNodes++;
00564                 varInfo = (VarSizeInfo*)((char*)varInfo + sizeof(VarSizeInfo)
00565                                     +varInfo->size_);
00566             }
00567             page = ((PageInfo*) page)->nextPage_;
00568         }
00569         return totalNodes;
00570     }
00571 
00572     //TODO::for large size allocator
00573     if (allocSize_ >PAGE_SIZE)//->each page has only one data node
00574         return 0;
00575 
00576     int noOfDataNodes=os::floor((PAGE_SIZE - sizeof(PageInfo))/allocSize_);
00577     PageInfo* pageInfo = ((PageInfo*)firstPage_);
00578     char *data = ((char*)firstPage_) + sizeof(PageInfo);
00579     int i=0;
00580     while( pageInfo != NULL )
00581     {
00582         data = ((char*)pageInfo) + sizeof(PageInfo);
00583         for (i = 0; i< noOfDataNodes; i++)
00584         {
00585             if (*((int*)data) == 1) { totalNodes++;}
00586             data = data + allocSize_;
00587         }
00588         pageInfo = (PageInfo*)(((PageInfo*)pageInfo)->nextPage_) ;
00589     }
00590     return totalNodes;
00591 }

Here is the call graph for this function:

Here is the caller graph for this function:

void Chunk::print (  )  [inline]

Definition at line 133 of file Allocator.h.

00133 {}

void Chunk::setAllocType ( AllocType  type  )  [inline]

Definition at line 122 of file Allocator.h.

Referenced by Database::createSystemDatabaseChunk(), and Database::deleteSystemDatabaseChunk().

00122 { allocType_ = type; }

Here is the caller graph for this function:

void Chunk::setChunkID ( unsigned int  id  )  [inline]

Definition at line 120 of file Allocator.h.

Referenced by Database::createSystemDatabaseChunk(), and Database::deleteSystemDatabaseChunk().

00120 { chunkID_ = id; }

Here is the caller graph for this function:

void Chunk::setSize ( size_t  size  ) 

Definition at line 28 of file Chunk.cxx.

References os::floor().

Referenced by Database::createSystemDatabaseChunk(), and Database::deleteSystemDatabaseChunk().

00029 {
00030 
00031     size_t needSize = size + sizeof(int);
00032     size_t multiple = (size_t) os::floor(needSize / sizeof(size_t));
00033     size_t rem = needSize % sizeof(size_t);
00034     if (0 == rem)
00035         allocSize_ = needSize;
00036     else
00037         allocSize_  = (multiple + 1) * sizeof(size_t);
00038 }

Here is the call graph for this function:

Here is the caller graph for this function:

int Chunk::totalPages (  ) 

Definition at line 650 of file Chunk.cxx.

Referenced by TableImpl::pagesUsed(), TransactionManager::printDebugInfo(), Transaction::printDebugInfo(), LockManager::printDebugInfo(), DatabaseManagerImpl::printIndexInfo(), and TableImpl::spaceUsed().

00651 {
00652     //logic is same for variable size and for large data node allocator. 
00653     PageInfo* pageInfo = ((PageInfo*)firstPage_);
00654     int totPages=0;
00655     while( pageInfo != NULL )
00656     {
00657         totPages++;
00658         pageInfo = (PageInfo*)(((PageInfo*)pageInfo)->nextPage_) ;
00659     }
00660     return totPages;
00661 }

Here is the caller graph for this function:


Friends And Related Function Documentation

friend class Database [friend]

Definition at line 160 of file Allocator.h.

friend class DatabaseManagerImpl [friend]

Definition at line 161 of file Allocator.h.


The documentation for this class was generated from the following files:
Generated on Mon Jun 9 22:44:28 2008 for csql by  doxygen 1.4.7