00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include<Database.h>
00017 #include<os.h>
00018 #include<CatalogTables.h>
00019 #include<Transaction.h>
00020 #include<Lock.h>
00021 #include<Debug.h>
00022 #include<Config.h>
00023 #include<Process.h>
00024
00025 const char* Database::getName()
00026 {
00027 return metaData_->dbName_;
00028 }
00029
00030 int Database::getDatabaseID()
00031 {
00032 return metaData_->dbID_;
00033 }
00034
00035 long Database::getMaxSize()
00036 {
00037 return metaData_->maxSize_;
00038 }
00039
00040 long Database::getCurrentSize()
00041 {
00042 return metaData_->curSize_;
00043
00044 }
00045 Page* Database::getCurrentPage()
00046 {
00047 return metaData_->curPage_;
00048
00049 }
00050 Page* Database::getFirstPage()
00051 {
00052 return metaData_->firstPage_;
00053
00054 }
00055 int Database::getNoOfChunks()
00056 {
00057 return metaData_->noOfChunks_;
00058 }
00059 Chunk* Database::getHashIndexChunk()
00060 {
00061 return metaData_->hashIndexChunk_;
00062 }
00063
00064 void Database::setDatabaseID(int id)
00065 {
00066 metaData_->dbID_ = id;
00067 }
00068 void Database::setName(const char *name)
00069 {
00070 strcpy(metaData_->dbName_ , name);
00071 }
00072 void Database::setCurrentSize(long size)
00073 {
00074 metaData_->curSize_ = size;
00075 }
00076 void Database::setCurrentPage(Page *page)
00077 {
00078 metaData_->curPage_ = page;
00079 }
00080 void Database::setFirstPage(Page *page)
00081 {
00082 metaData_->firstPage_ = page;
00083 }
00084 void Database::setMaxSize(long size)
00085 {
00086 metaData_->maxSize_ = size;
00087 }
00088 void Database::setNoOfChunks(int chunks)
00089 {
00090 metaData_->noOfChunks_ = chunks;
00091 }
00092 void Database::setHashIndexChunk(Chunk *ch)
00093 {
00094 metaData_->hashIndexChunk_ = ch;
00095 }
00096
00097
00098 int Database::initAllocDatabaseMutex()
00099 {
00100 return metaData_->dbAllocMutex_.init("allocdb");
00101 }
00102 DbRetVal Database::getAllocDatabaseMutex(bool procAccount)
00103 {
00104 int ret= metaData_->dbAllocMutex_.getLock(procAccount);
00105 if (ret) return ErrLockTimeOut; else return OK;
00106 }
00107 DbRetVal Database::releaseAllocDatabaseMutex(bool procAccount)
00108 {
00109 metaData_->dbAllocMutex_.releaseLock(procAccount);
00110 return OK;
00111 }
00112
00113
00114
00115 int Database::initTransTableMutex()
00116 {
00117 return metaData_->dbTransTableMutex_.init("transtable");
00118 }
00119 DbRetVal Database::getTransTableMutex()
00120 {
00121 int ret = metaData_->dbTransTableMutex_.getLock(procSlot);
00122 if (ret) return ErrLockTimeOut; else return OK;
00123 }
00124 DbRetVal Database::releaseTransTableMutex()
00125 {
00126 metaData_->dbTransTableMutex_.releaseLock(procSlot);
00127 return OK;
00128 }
00129
00130
00131
00132 int Database::initProcessTableMutex()
00133 {
00134 return metaData_->dbProcTableMutex_.init("proctable");
00135 }
00136 DbRetVal Database::getProcessTableMutex(bool procAccount)
00137 {
00138 int ret = metaData_->dbProcTableMutex_.getLock(-1, procAccount);
00139 if (ret) return ErrLockTimeOut; else return OK;
00140 }
00141 DbRetVal Database::releaseProcessTableMutex(bool procAccount)
00142 {
00143 metaData_->dbProcTableMutex_.releaseLock(-1, procAccount);
00144 return OK;
00145 }
00146
00147
00148
00149 int Database::initDatabaseMutex()
00150 {
00151 return metaData_->dbMutex_.init("db");
00152 }
00153 DbRetVal Database::getDatabaseMutex(bool procAccount)
00154 {
00155 int ret = metaData_->dbMutex_.getLock(procSlot, procAccount);
00156 if (ret) return ErrLockTimeOut; else return OK;
00157 }
00158 DbRetVal Database::releaseDatabaseMutex(bool procAccount)
00159 {
00160 metaData_->dbMutex_.releaseLock(procSlot, procAccount);
00161 return OK;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 Page* Database::getFreePage()
00176 {
00177
00178 Page* page = getCurrentPage();
00179
00180 printDebug(DM_Alloc, "Database::getFreePage currentpage:%x",page);
00181 PageInfo* pageInfo = ((PageInfo*)page);
00182 char* endAddr = ((char*)getMetaDataPtr()) + getMaxSize();
00183 int pageSize = PAGE_SIZE;
00184 while( 1 == pageInfo->isUsed_)
00185 {
00186
00187
00188 if ( pageInfo->nextPageAfterMerge_ == NULL) {
00189 pageInfo = (PageInfo*)((char*)pageInfo + pageSize);
00190 printDebug(DM_Alloc,"Normal Page:Moving to page:%x",pageInfo);
00191 }
00192 else {
00193 pageInfo = (PageInfo*)pageInfo->nextPageAfterMerge_;
00194 printDebug(DM_Alloc,"Merged Page:Moving to page:%x",pageInfo);
00195 }
00196 if ((char*)pageInfo >= endAddr)
00197 {
00198
00199 return NULL;
00200 }
00201
00202 }
00203 if (!isValidAddress(((char*) pageInfo) + pageSize))
00204 {
00205 printError(ErrSysInternal, "Invalid address %x",((char*) pageInfo) + pageSize);
00206 return NULL;
00207 }
00208 setCurrentPage((Page*) pageInfo);
00209 printDebug(DM_Alloc,"Database::getFreePage returning page:%x",pageInfo);
00210 return (Page*) pageInfo ;
00211 }
00212
00213
00214
00215 Page* Database::getFreePage(size_t size)
00216 {
00217 Page* page = getFirstPage();
00218 PageInfo* pageInfo = ((PageInfo*)page);
00219 int multiple = size / PAGE_SIZE;
00220 int offset = ((multiple + 1) * PAGE_SIZE);
00221 printDebug(DM_Alloc, "Database::getFreePage firstPage:%x size:%ld",page, size);
00222 char* endAddr = ((char*)getMetaDataPtr()) + getMaxSize();
00223 int pageSize = PAGE_SIZE;
00224 while(true){
00225 while( 1 == pageInfo->isUsed_)
00226 {
00227
00228
00229 if ( pageInfo->nextPageAfterMerge_ == NULL) {
00230 pageInfo = (PageInfo*)((char*)pageInfo + pageSize);
00231 printDebug(DM_Alloc,"Normal Page:Moving to page:%x",pageInfo);
00232 }
00233 else {
00234 pageInfo = (PageInfo*)pageInfo->nextPageAfterMerge_;
00235 printDebug(DM_Alloc,"Merged Page:Moving to page:%x",pageInfo);
00236 }
00237 }
00238 int i = 0;
00239 PageInfo *pInfo = pageInfo;
00240 if ((((char*)pInfo) + offset) >= endAddr)
00241 {
00242 printError(ErrSysInternal,"Invalid address %x",((char*)pInfo) + offset);
00243 return NULL;
00244 }
00245 for (i = 0; i< multiple + 1; i++)
00246 {
00247 if (1 == pInfo->isUsed_) break;
00248 pInfo = (PageInfo*)((char*)pInfo + pageSize);
00249 }
00250 if ( i == (multiple + 1)) break;
00251 }
00252
00253 printDebug(DM_Alloc,"Database::getFreePage returning page:%x",pageInfo);
00254 setCurrentPage((Page*) pageInfo);
00255 return (Page*) pageInfo ;
00256 }
00257
00258 void Database::printStatistics()
00259 {
00260 Page* page = getFirstPage();
00261 PageInfo* pageInfo = ((PageInfo*)page);
00262 int usedPageCount =0, usedMergedPageCount =0, totalPages=0;
00263 printf("<DatabaseStatistics>\n");
00264 printf(" <Database Name> %s </Database Name>\n", getName());
00265 printf(" <Max Size> %ld </Max Size>\n", getMaxSize());
00266 printf(" <First Page> %x </First Page>\n", getFirstPage());
00267 while(isValidAddress((char*) pageInfo))
00268 {
00269 if (pageInfo == NULL) break;
00270 if (1 == pageInfo->isUsed_) {
00271 if ( pageInfo->nextPageAfterMerge_ == NULL) {
00272 pageInfo = (PageInfo*)((char*)pageInfo + PAGE_SIZE);
00273 usedPageCount++; totalPages++;
00274 printDebug(DM_Alloc, "Normal Page:Moving to page:%x\n",pageInfo);
00275 continue;
00276 }
00277 else {
00278 pageInfo = (PageInfo*)pageInfo->nextPageAfterMerge_;
00279 usedMergedPageCount++; totalPages++;
00280 printDebug(DM_Alloc,"Merged Page:Moving to page:%x\n",pageInfo);
00281 continue;
00282 }
00283 }
00284 pageInfo = (PageInfo*)((char*)pageInfo + PAGE_SIZE);
00285 printDebug(DM_Alloc,"Normal Page not used:Moving to page:%x\n",pageInfo);
00286 totalPages++;
00287 }
00288 printf(" <Total Pages> %d </Total Pages>\n", totalPages);
00289 printf(" <Used Normal Pages> %d </Used Normal Pages>\n", usedPageCount);
00290 printf(" <Used Merged Pages> %d </Used Merged Pages>\n", usedMergedPageCount);
00291 printf(" <Chunks Used> %d </Chunks Used>\n", getNoOfChunks());
00292 printf("</DatabaseStatistics>\n");
00293
00294 return ;
00295 }
00296
00297
00298
00299
00300 DbRetVal Database::createSystemDatabaseChunk(AllocType type, size_t size, int id)
00301 {
00302
00303 Chunk *chunk;
00304 if (-1 == id )
00305 {
00306 printError(ErrSysFatal, "Database ID corrupted");
00307 return ErrSysFatal;
00308 }
00309 chunk = getSystemDatabaseChunk(id);
00310
00311 if (FixedSizeAllocator == type) chunk->setSize(size);
00312
00313 if (chunk->allocSize_ > PAGE_SIZE)
00314 chunk->curPage_ = getFreePage(chunk->allocSize_);
00315 else
00316 chunk->curPage_ = getFreePage();
00317 if ( chunk->curPage_ == NULL)
00318 {
00319
00320 printError(ErrNoMemory, "No free pages in database: Database full");
00321 return ErrNoMemory;
00322 }
00323
00324 chunk->firstPage_ = chunk->curPage_;
00325 PageInfo* firstPageInfo = ((PageInfo*)chunk->firstPage_);
00326 firstPageInfo->setFirstPageAsUsed();
00327 chunk->setChunkID(id);
00328 chunk->setAllocType(type);
00329 printDebug(DM_Database, "Creating System Database Chunk:%d Size:%d",id, chunk->allocSize_);
00330 if (chunk->allocSize_ > PAGE_SIZE)
00331 {
00332 int multiple = os::floor(chunk->allocSize_ / PAGE_SIZE);
00333 int offset = ((multiple + 1) * PAGE_SIZE);
00334 firstPageInfo->nextPageAfterMerge_ = ((char*)firstPageInfo)+ offset;
00335 }
00336
00337 if (0 == size)
00338 {
00339 VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)firstPageInfo) + sizeof(PageInfo));
00340 varInfo->isUsed_ = 0;
00341 varInfo->size_ = PAGE_SIZE - sizeof(PageInfo) - sizeof(VarSizeInfo);
00342
00343 }
00344 incrementChunk();
00345
00346 return OK;
00347 }
00348
00349
00350 DbRetVal Database::deleteSystemDatabaseChunk(int id)
00351 {
00352
00353 Chunk *chunk = getSystemDatabaseChunk(id);
00354 chunk->setChunkID(-1);
00355 chunk->setSize(0);
00356 chunk->setAllocType(UnknownAllocator);
00357
00358
00359
00360
00361
00362 chunk->firstPage_ = NULL;
00363 chunk->curPage_ = NULL;
00364 decrementChunk();
00365 return OK;
00366 }
00367
00368
00369 void Database::createAllCatalogTables()
00370 {
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 createSystemTables();
00384 createMetaDataTables();
00385 }
00386 void Database::createSystemTables()
00387 {
00388 createSystemDatabaseChunk(FixedSizeAllocator,
00389 sizeof(Chunk), UserChunkTableId);
00390 createSystemDatabaseChunk(FixedSizeAllocator,
00391 sizeof(Bucket) * LOCK_BUCKET_SIZE,
00392 LockTableHashBucketId);
00393 createSystemDatabaseChunk(FixedSizeAllocator,
00394 sizeof(Mutex)* LOCK_BUCKET_SIZE,
00395 LockTableMutexId);
00396 createSystemDatabaseChunk(FixedSizeAllocator,
00397 sizeof(LockHashNode), LockTableId);
00398 createSystemDatabaseChunk(FixedSizeAllocator,
00399 sizeof(TransHasNode), TransHasTableId);
00400
00401 createSystemDatabaseChunk(VariableSizeAllocator,
00402 0, UndoLogTableID);
00403 }
00404 void Database::createMetaDataTables()
00405 {
00406 createSystemDatabaseChunk(FixedSizeAllocator,
00407 sizeof(DATABASEFILE), DatabaseTableId);
00408 createSystemDatabaseChunk(FixedSizeAllocator,
00409 sizeof(USER), UserTableId);
00410 createSystemDatabaseChunk(FixedSizeAllocator,
00411 sizeof(TABLE), TableTableId);
00412 createSystemDatabaseChunk(FixedSizeAllocator,
00413 sizeof(FIELD), FieldTableId);
00414 createSystemDatabaseChunk(FixedSizeAllocator,
00415 sizeof(ACCESS), AccessTableId);
00416 createSystemDatabaseChunk(FixedSizeAllocator,
00417 sizeof(INDEX), IndexTableId);
00418 createSystemDatabaseChunk(FixedSizeAllocator,
00419 sizeof(INDEXFIELD), IndexFieldTableId);
00420 }
00421
00422
00423 Chunk* Database::getSystemDatabaseChunk(int id)
00424 {
00425 size_t offset = os::alignLong(sizeof (DatabaseMetaData)) +
00426 id * sizeof (Chunk);
00427 return (Chunk*)(((char*) metaData_) + offset);
00428 }
00429
00430
00431
00432 Transaction* Database::getSystemDatabaseTrans(int slot)
00433 {
00434 size_t offset = os::alignLong(sizeof (DatabaseMetaData)) +
00435 os::alignLong(MAX_CHUNKS * sizeof (Chunk)) +
00436 slot * sizeof (Transaction);
00437 return (Transaction*)(((char*) metaData_) + offset);
00438 }
00439
00440
00441 ThreadInfo* Database::getThreadInfo(int slot)
00442 {
00443
00444
00445
00446
00447
00448
00449
00450 static size_t offset = os::alignLong(sizeof (DatabaseMetaData)) +
00451 os::alignLong( MAX_CHUNKS * sizeof (Chunk)) +
00452 os::alignLong( Conf::config.getMaxProcs()*sizeof(Transaction));
00453
00454 size_t off = offset + slot * sizeof (ThreadInfo);
00455 return (ThreadInfo*)(((char*) metaData_) + off);
00456
00457 }
00458
00459 bool Database::isValidAddress(void* addr)
00460 {
00461 if ((char*) addr >= ((char*)getMetaDataPtr()) + getMaxSize())
00462 return false;
00463 else
00464 return true;
00465 }
00466
00467
00468 void* Database::allocLockHashBuckets()
00469 {
00470 Chunk *chunk = getSystemDatabaseChunk(LockTableHashBucketId);
00471 void *ptr = chunk->allocate(this);
00472 if (NULL == ptr)
00473 {
00474 printError(ErrNoMemory, "Chunk Allocation failed for lock hash bucket catalog table");
00475 }
00476 return ptr;
00477 }
00478
00479 Bucket* Database::getLockHashBuckets()
00480 {
00481 Chunk *tChunk = getSystemDatabaseChunk(LockTableHashBucketId);
00482 ChunkIterator iter = tChunk->getIterator();
00483 return (Bucket*)iter.nextElement();
00484 }
00485