src/server/Chunk.cxx

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007 by www.databasecache.com                           *
00003  *   Contact: praba_tuty@databasecache.com                                 *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015   ***************************************************************************/
00016 #include<Allocator.h>
00017 #include<Database.h>
00018 #include<os.h>
00019 #include<Debug.h>
00020 #include<Config.h>
00021 #include<CatalogTables.h>
00022 
00023 // sets the size of the Chunk allocator for fixed size
00024 // allocator
00025 // we need one integer to store book keeping information
00026 // whether the storage allocation unit is used of not
00027 // when it is deleted this flag is only set to unused
00028 void Chunk::setSize(size_t size)
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 }
00039 
00040 void* Chunk::allocateForLargeDataSize(Database *db)
00041 {
00042     PageInfo* pageInfo = ((PageInfo*)curPage_);
00043     DbRetVal ret = db->getAllocDatabaseMutex();
00044     if (ret != 0)
00045     {
00046         printError(ErrLockTimeOut,"Unable to acquire alloc database Mutex");
00047         return NULL;
00048     }
00049 
00050     //check whether we have space in curPage 
00051     if (pageInfo->hasFreeSpace_ == 1)
00052     {
00053         char *data = ((char*)curPage_) + sizeof(PageInfo);
00054         pageInfo->hasFreeSpace_ =0;
00055         *((int*)data) = 1;
00056         db->releaseAllocDatabaseMutex();
00057         return data + sizeof(int);
00058     }
00059 
00060 
00061     //no space in curpage , get new page from database 
00062     pageInfo = (PageInfo*)db->getFreePage(allocSize_);
00063     if (NULL == pageInfo)
00064     {
00065         db->releaseAllocDatabaseMutex();
00066         printError(ErrNoMemory,"No more free pages in the database");
00067         return NULL;
00068     }
00069     printDebug(DM_Alloc, "Chunk ID:%d Large Data Item newPage:%x",
00070                                        chunkID_, pageInfo);
00071     int multiple = os::floor(allocSize_ / PAGE_SIZE);
00072     int offset = ((multiple + 1) * PAGE_SIZE);
00073 
00074     pageInfo->setPageAsUsed(offset);
00075 
00076     //create the link
00077    ((PageInfo*)curPage_)->nextPage_ = (Page*) pageInfo;
00078     //Make this as current page
00079     curPage_ = (Page*) pageInfo;
00080     char* data = ((char*)curPage_) + sizeof(PageInfo);
00081     //TODO::check whether it is locked
00082     *((int*)data) = 1;
00083     db->releaseAllocDatabaseMutex();
00084     return data + sizeof(int);
00085 
00086 }
00087 
00088 void* Chunk::allocateFromFirstPage(Database *db, int noOfDataNodes)
00089 {
00090     PageInfo *pageIter = ((PageInfo*)firstPage_);
00091     printDebug(DM_Alloc, "Chunk ID:%d. No free page in database",
00092                                                        chunkID_);
00093     printDebug(DM_Alloc, "Scan from firstPage:%x for free nodes",
00094                                                      firstPage_);
00095     char *data = NULL;
00096     int i = 0;
00097     //scan from first page to locate a free node available
00098     while(NULL != pageIter)
00099     {
00100         data = ((char*)pageIter) + sizeof(PageInfo);
00101         if (pageIter->hasFreeSpace_ == 1)
00102         {
00103             for (i = 0; i< noOfDataNodes -1; i++)
00104             {
00105                 if (1 == *((int*)data))
00106                     data = data + allocSize_;
00107                 else break;
00108             }
00109             if (i != noOfDataNodes -1) break;
00110         }
00111         printDebug(DM_Alloc, "Chunk ID: %d Page :%x does not have free nodes",
00112                                                            chunkID_, pageIter);
00113         pageIter = (PageInfo*)((PageInfo*) pageIter)->nextPage_;
00114     }
00115     if (NULL == pageIter) return NULL;
00116     printDebug(DM_Alloc,"ChunkID:%d Scan for free node End:Page :%x",
00117                                                   chunkID_, pageIter);
00118     *((int*)data) = 1;
00119     return data + sizeof(int);
00120 
00121 }
00122 
00123 void* Chunk::allocateFromNewPage(Database *db)
00124 {
00125     DbRetVal ret = db->getAllocDatabaseMutex();
00126     if (ret != 0)
00127     {
00128         printError(ErrLockTimeOut,"Unable to acquire alloc database Mutex");
00129         return NULL;
00130     }
00131     //get a new page from db
00132     Page *page = db->getFreePage();
00133     if (page == NULL)
00134     {
00135         db->releaseAllocDatabaseMutex();
00136         return NULL;
00137     }
00138     printDebug(DM_Alloc, "ChunkID:%d Normal Data Item newPage:%x",
00139                                                   chunkID_, page);
00140     //Initialize pageInfo for this new page
00141     PageInfo *pInfo = (PageInfo*)page;
00142     pInfo->setPageAsUsed(0);
00143 
00144     //create the link between old page and the newly created page
00145     PageInfo* pageInfo = ((PageInfo*)curPage_);
00146     pageInfo->nextPage_ = page;
00147 
00148     //make this new page as the current page
00149     curPage_ = page;
00150 
00151     char* data = ((char*)page) + sizeof(PageInfo);
00152     *((int*)data) = 1;
00153     db->releaseAllocDatabaseMutex();
00154     return data + sizeof(int);
00155 }
00156 
00157 //Allocates memory to store data
00158 //TODO::check whether it is locked before allocating.
00159 //delete tuple will set the usedflag to true, but locks will be held
00160 //till commit and it shall be rolledback.So make sure that it does not
00161 //allocate deleted tuple which is yet to be commited.
00162 
00163 void* Chunk::allocate(Database *db, DbRetVal *status)
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 }
00246 
00247 
00248 void* Chunk::allocateForLargeDataSize(Database *db, size_t size)
00249 {
00250     //no need to take chunk mutexes for this, as we are taking alloc database mutex
00251     int multiple = os::floor(size / PAGE_SIZE);
00252     int offset = ((multiple + 1) * PAGE_SIZE);
00253     PageInfo* pageInfo = ((PageInfo*)curPage_);
00254     DbRetVal ret = db->getAllocDatabaseMutex();
00255     if (ret != 0)
00256     {
00257         printError(ErrLockTimeOut,"Unable to acquire alloc database Mutex");
00258         return NULL;
00259     }
00260     pageInfo = (PageInfo*)db->getFreePage(allocSize_);
00261     if (NULL == pageInfo)
00262     {
00263         db->releaseAllocDatabaseMutex();
00264         printError(ErrNoMemory,"No more free pages in the database:Increase db size");
00265         return NULL;
00266     }
00267     printDebug(DM_VarAlloc,"Chunk::allocate Large Data Item id:%d Size:%d curPage:%x ",
00268                                             chunkID_, size, curPage_);
00269     //TODO:: logic pending
00270 
00271 
00272     //REDESIGN MAY BE REQUIRED:Lets us live with this for now.
00273     //what happens to the space lets say 10000 bytes is allocated
00274     //it needs 2 pages,= 16000 bytes, 6000 bytes should not be wasted
00275     //in this case.So need to take of this.
00276     //Will be coded at later stage as this is developed to support
00277     //undo logging and currently we shall assume that the logs generated
00278     //wont be greater than PAGE_SIZE.
00279     db->releaseAllocDatabaseMutex();
00280     return NULL;
00281 
00282 }
00283 
00284 
00285 
00286 void* Chunk::allocFromNewPageForVarSize(Database *db, size_t size)
00287 {
00288     //Should be called only for data items <PAGE_SIZE
00289     DbRetVal ret = db->getAllocDatabaseMutex();
00290     if (ret != 0)
00291     {
00292         printError(ErrLockTimeOut,"Unable to acquire alloc database Mutex");
00293         return NULL;
00294     }
00295 
00296     void *vnode = varSizeFirstFitAllocate(size);
00297     if (vnode != NULL)
00298     {
00299        db->releaseAllocDatabaseMutex();
00300        return vnode;
00301     }
00302 
00303     Page *newPage = db->getFreePage();
00304     db->releaseAllocDatabaseMutex();
00305     if (NULL == newPage)
00306     {
00307         return NULL;
00308     }
00309 
00310     printDebug(DM_VarAlloc, "ChunkID:%d New Page: %x ", chunkID_, newPage);
00311     PageInfo *pInfo = (PageInfo*) newPage;
00312     pInfo->setPageAsUsed(0);
00313     createDataBucket(newPage, PAGE_SIZE, size);
00314 
00315     ((PageInfo*)curPage_)->nextPage_ = newPage;
00316     curPage_ = newPage;
00317     char *data= ((char*)newPage) + sizeof(PageInfo) + sizeof(VarSizeInfo);
00318     return data;
00319 }
00320 
00321 //Allocates from the current page of the chunk.
00322 //Scans through the VarSizeInfo objects in the page and gets the free slot
00323 void* Chunk::allocateFromCurPageForVarSize(size_t size)
00324 {
00325     //Should be called only for data items <PAGE_SIZE
00326     Page *page = ((PageInfo*)curPage_);
00327     printDebug(DM_VarAlloc, "Chunk::allocate Normal Data Item id:%d Size:%d curPage:%x ",
00328                                                chunkID_, size, curPage_);
00329     VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)page) +
00330                                                 sizeof(PageInfo));
00331     while ((char*) varInfo < ((char*)page + PAGE_SIZE))
00332     {
00333         if (0 == varInfo->isUsed_)
00334         {
00335             if( size + sizeof(VarSizeInfo) < varInfo->size_)
00336             {
00337                 splitDataBucket(varInfo, size);
00338                 printDebug(DM_VarAlloc, "Chunkid:%d splitDataBucket: Size: %d Item:%x ",
00339                                                          chunkID_, size, varInfo);
00340                 return (char*)varInfo + sizeof(VarSizeInfo);
00341             }
00342             else if (size == varInfo->size_) {
00343                 varInfo->isUsed_ = 1;
00344                 return (char *) varInfo + sizeof(VarSizeInfo);
00345             }
00346 
00347         }
00348         varInfo = (VarSizeInfo*)((char*)varInfo + sizeof(VarSizeInfo)
00349                                     +varInfo->size_);
00350     }
00351     return NULL;
00352 }
00353 
00354 //Allocates memory to store data of variable size
00355 void* Chunk::allocate(Database *db, size_t size, DbRetVal *status)
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 }
00399 
00400 //Assumes chunk mutex is already taken, before calling this
00401 void* Chunk::varSizeFirstFitAllocate(size_t size)
00402 {
00403     printDebug(DM_VarAlloc, "Chunk::varSizeFirstFitAllocate size:%d firstPage:%x",
00404                                                size, firstPage_);
00405 
00406     Page *page = ((PageInfo*)firstPage_);
00407     size_t alignedSize = os::align(size);
00408     while(NULL != page)
00409     {
00410         VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)page) + sizeof(PageInfo));
00411         while ((char*) varInfo < ((char*)page + PAGE_SIZE))
00412         {
00413             if (0 == varInfo->isUsed_)
00414             {
00415                 if( alignedSize +sizeof(VarSizeInfo) < varInfo->size_)
00416                 {
00417                     splitDataBucket(varInfo, alignedSize);
00418                     return ((char*)varInfo) + sizeof(VarSizeInfo);
00419                 }
00420                 else if (alignedSize == varInfo->size_) {
00421                     varInfo->isUsed_ = 1;
00422                     printDebug(DM_VarAlloc, "VarSizeFirstFitAllocate returning %x", ((char*)varInfo) +sizeof(VarSizeInfo));
00423                     return ((char *) varInfo) + sizeof(VarSizeInfo);
00424                 }
00425             }
00426             varInfo = (VarSizeInfo*)((char*)varInfo + sizeof(VarSizeInfo)
00427                                     +varInfo->size_);
00428         }
00429         printDebug(DM_VarAlloc, "Chunk:This page does not have free data nodes page:%x", page);
00430         page = ((PageInfo*) page)->nextPage_;
00431     }
00432     return NULL;
00433 }
00434 
00435 void Chunk::freeForVarSizeAllocator(void *ptr, int pslot)
00436 {
00437     int ret = getChunkMutex(pslot);
00438     if (ret != 0)
00439     {
00440         printError(ErrLockTimeOut,"Unable to acquire chunk Mutex");
00441         return;
00442     }
00443     VarSizeInfo *varInfo = (VarSizeInfo*)((char*)ptr- sizeof(VarSizeInfo));
00444     varInfo->isUsed_ = 0;
00445     printDebug(DM_VarAlloc,"chunkID:%d Unset isUsed for %x", chunkID_, varInfo);
00446     releaseChunkMutex(pslot);
00447     return;
00448 
00449 }
00450 
00451 void Chunk::freeForLargeAllocator(void *ptr, int pslot)
00452 {
00453     //There will be max only one data element in a page.
00454     //PageInfo is stored just before the data.
00455     int ret = getChunkMutex(pslot);
00456     if (ret != 0)
00457     {
00458         printError(ErrLockTimeOut,"Unable to acquire chunk Mutex");
00459         return;
00460     }
00461     PageInfo *pageInfo = (PageInfo*)(((char*)
00462                          ptr) - (sizeof(PageInfo) + sizeof(int)));
00463     PageInfo *pInfo = (PageInfo*)firstPage_, *prev = (PageInfo*)firstPage_;
00464     bool found = false;
00465     while(!found)
00466     {
00467         if (pInfo == pageInfo) {found = true;  break; }
00468         prev = pInfo;
00469         pInfo = (PageInfo*)pInfo->nextPage_;
00470     }
00471     if (!found)
00472     {
00473         printError(ErrSysFatal,"Page %x not found in page list:Logical error", pageInfo );
00474         releaseChunkMutex(pslot);
00475         return ;
00476     }
00477     prev->nextPage_ = pageInfo->nextPage_;
00478     pageInfo->nextPageAfterMerge_ = NULL;
00479     pageInfo->isUsed_ = 0;
00480     os::memset(pageInfo,  0 , allocSize_);
00481     pageInfo->hasFreeSpace_ = 1;
00482     releaseChunkMutex(pslot);
00483     return;
00484 }
00485 
00486 //Frees the memory pointed by ptr
00487 void Chunk::free(Database *db, void *ptr)
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 }
00524 
00525 //returns the pageInfo of the page where this ptr points
00526 //This works only if the data size is less than PAGE_SIZE
00527 //If ptr points to data which is more than PAGE_SIZE,then
00528 //calling this might lead to memory corruption
00529 //Note:IMPORTANT::assumes db lock is taken before calling this
00530 PageInfo* Chunk::getPageInfo(Database *db, void *ptr)
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 }
00549 
00550 //If called on chunk used to store tuples, it returns the total number of rows
00551 //present in the table
00552 long Chunk::getTotalDataNodes()
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 }
00592 
00593 //TODO::for other type of allocators
00594 int Chunk::compact()
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 }
00649 
00650 int Chunk::totalPages()
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 }
00662 
00663 int Chunk::initMutex()
00664 {
00665     return chunkMutex_.init("Chunk");
00666 }
00667 int Chunk::getChunkMutex(int procSlot)
00668 {
00669     return chunkMutex_.getLock(procSlot);
00670 }
00671 int Chunk::releaseChunkMutex(int procSlot)
00672 {
00673     return chunkMutex_.releaseLock(procSlot);
00674 }
00675 int Chunk::destroyMutex()
00676 {
00677     return chunkMutex_.destroy();
00678 }
00679 void Chunk::splitDataBucket(VarSizeInfo *varInfo, size_t needSize)
00680 {
00681     int remSpace = varInfo->size_ - sizeof(VarSizeInfo) - needSize;
00682     varInfo->isUsed_ = 1;
00683     varInfo->size_ = needSize;
00684     varInfo = (VarSizeInfo*)((char*)varInfo +
00685                sizeof(VarSizeInfo) +  varInfo->size_);
00686     varInfo->isUsed_ = 0;
00687     varInfo->size_  = remSpace;
00688     printDebug(DM_VarAlloc, "Remaining space is %d\n", remSpace);
00689     return;
00690 }
00691 
00692 
00693 void Chunk::createDataBucket(Page *page, size_t totalSize, size_t needSize)
00694 {
00695     VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)page) + sizeof(PageInfo));
00696     varInfo->isUsed_ = 0;
00697     varInfo->size_ = PAGE_SIZE - sizeof(PageInfo) - sizeof(VarSizeInfo);
00698     splitDataBucket(varInfo, needSize);
00699     return;
00700 }
00701 
00702 
00703 

Generated on Mon Jun 9 22:37:15 2008 for csql by  doxygen 1.4.7