src/server/DatabaseManagerImpl.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<Database.h>
00017 #include<DatabaseManager.h>
00018 #include<DatabaseManagerImpl.h>
00019 #include<os.h>
00020 #include<Table.h>
00021 #include<TableImpl.h>
00022 #include<Transaction.h>
00023 #include<CatalogTables.h>
00024 #include<Index.h>
00025 #include<Lock.h>
00026 #include<Debug.h>
00027 #include<Config.h>
00028 #include<Process.h>
00029 
00030 
00031 DatabaseManagerImpl::~DatabaseManagerImpl()
00032 {
00033     //Note:Databases are closed by the session interface
00034     delete tMgr_;
00035     delete lMgr_;
00036 }
00037 
00038 void DatabaseManagerImpl::createLockManager()
00039 {
00040     lMgr_ = new LockManager(systemDatabase_);
00041     return;
00042 }
00043 
00044 void DatabaseManagerImpl::createTransactionManager()
00045 {
00046 
00047     tMgr_ = new TransactionManager();
00048     tMgr_->setFirstTrans(systemDatabase_->getSystemDatabaseTrans(0));
00049     return;
00050 }
00051 void DatabaseManagerImpl::setProcSlot()
00052 {
00053 systemDatabase_->setProcSlot(procSlot);
00054 db_->setProcSlot(procSlot);
00055 }
00056 DbRetVal DatabaseManagerImpl::openSystemDatabase()
00057 {
00058     DbRetVal rv = openDatabase(SYSTEMDB);
00059     if (rv != OK) return rv;
00060     systemDatabase_ = db_;
00061     db_ = NULL;
00062     printDebug(DM_Database, "Opened system database");
00063     logFinest(logger, "Opened system database");
00064     return OK;
00065 }
00066 
00067 DbRetVal DatabaseManagerImpl::closeSystemDatabase()
00068 {
00069     Database *db  = db_;
00070     //make them to point to system database file descriptor
00071     //and database pointer
00072     db_ = systemDatabase_;
00073     closeDatabase();
00074     db_ = db;
00075     printDebug(DM_Database, "Closed system database");
00076     logFinest(logger, "Closed System database");
00077     return OK;
00078 }
00079 
00084 DbRetVal DatabaseManagerImpl::createDatabase(const char *name, size_t size)
00085 {
00086     if (NULL != db_ )
00087     {
00088         printError(ErrAlready, "Database is already created");
00089         return ErrAlready;
00090     }
00091     caddr_t rtnAddr = (caddr_t) NULL;
00092     shared_memory_id shm_id = 0;
00093 
00094     char *startaddr = (char*)Conf::config.getMapAddress();
00095     shared_memory_key key = 0;
00096     if (0 == strcmp(name, SYSTEMDB))
00097     {
00098         
00099         key = Conf::config.getSysDbKey();
00100     }
00101     else
00102     {
00103         startaddr = startaddr + Conf::config.getMaxSysDbSize();
00104         key = Conf::config.getUserDbKey();
00105     }
00106     shm_id = os::shm_create(key, size, 0666);
00107     if (-1 == shm_id)
00108     {
00109                 if (errno == EEXIST) {
00110                         printError(ErrOS, "Shared Memory already exists");
00111                 }
00112         printError(ErrOS, "Shared memory create failed");
00113         return ErrOS;
00114     }
00115 
00116     void *shm_ptr = os::shm_attach(shm_id, startaddr, SHM_RND);
00117     rtnAddr  = (caddr_t) shm_ptr;
00118     if (rtnAddr < 0 || shm_ptr == (char*)0xffffffff)
00119     {
00120         printError(ErrOS, "Shared memory attach returned -ve value %d", rtnAddr);
00121         return ErrOS;
00122     }
00123     memset(shm_ptr, 0, size );
00124     db_ = new Database();
00125     printDebug(DM_Database, "Creating database:%s",name);
00126 
00127     //TODO:for user database do not have transtable and processtable mutex
00128     db_->setMetaDataPtr((DatabaseMetaData*)rtnAddr);
00129     db_->setDatabaseID(1);
00130     db_->setName(name);
00131     db_->setMaxSize(size);
00132     db_->setNoOfChunks(0);
00133     db_->initAllocDatabaseMutex();
00134     db_->initTransTableMutex();
00135     db_->initDatabaseMutex();
00136     db_->initProcessTableMutex();
00137 
00138     //compute the first page after book keeping information
00139     size_t offset = os::alignLong(sizeof (DatabaseMetaData));
00140     //Only for system db chunk array, trans array and proc array will be there
00141     if (0 == strcmp(name, SYSTEMDB))
00142     {
00143         offset = offset + os::alignLong( MAX_CHUNKS  * sizeof (Chunk));
00144         offset = offset + os::alignLong( Conf::config.getMaxProcs()   * sizeof(Transaction));
00145         offset = offset + os::alignLong( Conf::config.getMaxProcs() * sizeof(ThreadInfo));
00146     }
00147     int multiple = os::floor(offset / PAGE_SIZE);
00148     char *curPage = (((char*)rtnAddr) + ((multiple + 1) * PAGE_SIZE));
00149 
00150     db_->setCurrentPage(curPage);
00151     db_->setFirstPage(curPage);
00152 
00153     if (0 == strcmp(name, SYSTEMDB)) return OK;
00154 
00155     /*Allocate new chunk to store hash index nodes
00156     Chunk *chunkInfo = createUserChunk(sizeof(HashIndexNode));
00157     if (NULL == chunkInfo)
00158     {
00159         printError(ErrSysInternal, "Failed to allocate hash index nodes chunk");
00160         return ErrSysInternal;
00161     }
00162     printDebug(DM_Database, "Creating Chunk for storing Hash index nodes %x",
00163                                                                   chunkInfo);
00164 
00165     db_->setHashIndexChunk(chunkInfo);*/
00166     logFinest(logger, "Created database %s" , name);
00167 
00168     return OK;
00169 }
00175 DbRetVal DatabaseManagerImpl::deleteDatabase(const char *name)
00176 {
00177     shared_memory_id shm_id = 0;
00178     if (0 == strcmp(name, SYSTEMDB))
00179     {
00180         shm_id = os::shm_open(Conf::config.getSysDbKey(), 100, 0666);
00181         os::shmctl(shm_id, IPC_RMID);
00182                 delete systemDatabase_;
00183                 systemDatabase_ = NULL;
00184     } else {
00185         shm_id = os::shm_open(Conf::config.getUserDbKey(), 100, 0666);
00186         os::shmctl(shm_id, IPC_RMID);
00187                 delete db_;
00188                 db_ = NULL;
00189     }
00190     logFinest(logger, "Deleted database %s" , name);
00191     return OK;
00192 }
00193 
00198 DbRetVal DatabaseManagerImpl::openDatabase(const char *name)
00199 {
00200     long size = Conf::config.getMaxSysDbSize();
00201     char *startaddr = (char*)Conf::config.getMapAddress();
00202     if (0 == strcmp(name , SYSTEMDB))
00203     {
00204         if (NULL !=systemDatabase_)
00205         {
00206             printError(ErrAlready, "System Database already open");
00207             return ErrAlready;
00208         }
00209     }
00210     else
00211     {
00212         if (NULL ==systemDatabase_)
00213         {
00214             printError(ErrNotOpen, "System Database not open");
00215             return ErrNotOpen;
00216         }
00217         size = Conf::config.getMaxDbSize();
00218         startaddr = startaddr +  Conf::config.getMaxSysDbSize();
00219     }
00220     if (NULL != db_)
00221     {
00222         printError(ErrAlready, "User Database already open");
00223         return ErrAlready;
00224     }
00225     //system db should be opened before user database files 
00226     caddr_t rtnAddr = (caddr_t) NULL;
00227 
00228     shared_memory_id shm_id = 0;
00229     shared_memory_key key = 0;
00230 
00231     if (0 == strcmp(name, SYSTEMDB))
00232         key = Conf::config.getSysDbKey();
00233     else
00234        key = Conf::config.getUserDbKey();
00235 
00236 
00237     int ret = ProcessManager::mutex.getLock(-1, false);
00238     //If you are not getting lock ret !=0, it means somebody else is there.
00239     //he will close the database.
00240     if (ret != 0)
00241     {
00242         printError(ErrSysInternal, "Another thread calling open:Wait and then Retry\n");
00243         return ErrSysInternal;
00244     }
00245     void *shm_ptr = NULL;
00246     bool firstThread = false;
00247     //printf("PRABA::DEBUG:: opendb %d %s\n", ProcessManager::noThreads, name);
00248     if (ProcessManager::noThreads == 0 && 0 == strcmp(name, SYSTEMDB)
00249        || ProcessManager::noThreads == 1 && 0 != strcmp(name, SYSTEMDB) ) {
00250        shm_id = os::shm_open(key, size, 0666);
00251        if (shm_id == -1 )
00252        {
00253            printError(ErrOS, "Shared memory open failed");
00254            ProcessManager::mutex.releaseLock(-1, false);
00255            return ErrOS;
00256        }
00257        shm_ptr = os::shm_attach(shm_id, startaddr, SHM_RND);
00258        if (0 == strcmp(name, SYSTEMDB))
00259        {
00260              firstThread = true;
00261              ProcessManager::sysAddr = (char*) shm_ptr;
00262        }
00263        else
00264        {
00265               ProcessManager::usrAddr = (char*) shm_ptr;
00266        }
00267     } else {
00268         if (0 == strcmp(name, SYSTEMDB))
00269               shm_ptr = ProcessManager::sysAddr;
00270         else
00271               shm_ptr = ProcessManager::usrAddr;
00272     }
00273     ProcessManager::mutex.releaseLock(-1, false);
00274 
00275 
00276     rtnAddr  = (caddr_t) shm_ptr;
00277 
00278     if (rtnAddr < 0 || shm_ptr == (char*)0xffffffff)
00279     {
00280         printError(ErrOS, "Shared memory attach returned -ve value %x %d", shm_ptr, errno);
00281         return ErrOS;
00282     } 
00283     db_ = new Database();
00284     db_->setMetaDataPtr((DatabaseMetaData*)rtnAddr);
00285 
00286     if (firstThread) ProcessManager::systemDatabase = db_;
00287 
00288     printDebug(DM_Database, "Opening database: %s", name);
00289     logFinest(logger, "Opened database %s" , name);
00290     return OK;
00291 }
00292 
00293 DbRetVal DatabaseManagerImpl::closeDatabase()
00294 {
00295 
00296     if (NULL == db_) 
00297     {
00298         //Database is already closed
00299         return OK;
00300     }
00301     printDebug(DM_Database, "Closing database: %s",(char*)db_->getName());
00302     //check if this is the last thread to be deregistered
00303     int ret = ProcessManager::mutex.getLock(-1, false);
00304     //If you are not getting lock ret !=0, it means somebody else is there.
00305     //he will close the database.
00306     if (ret == 0) {
00307     //printf("PRABA::FOR DEBUG closedb %d %s\n", ProcessManager::noThreads, (char*)db_->getName());
00308     if (ProcessManager::noThreads == 0 && 0 == strcmp((char*)db_->getName(), SYSTEMDB)
00309        || ProcessManager::noThreads == 1 && 0 != strcmp((char*)db_->getName(),  SYSTEMDB) )  {
00310                 os::shm_detach((char*)db_->getMetaDataPtr());
00311             }
00312     }
00313     ProcessManager::mutex.releaseLock(-1, false);
00314     logFinest(logger, "Closed database");
00315     delete db_;
00316     db_ = NULL;
00317     return OK;
00318 }
00319 //Assumes that system database mutex is taken before calling this.
00320 Chunk* DatabaseManagerImpl::createUserChunk(size_t size)
00321 {
00322     //Allocate new node in system database to store
00323     Chunk *chunk = getSystemTableChunk(UserChunkTableId);
00324     DbRetVal rv = OK;
00325     void *ptr = chunk->allocate(systemDatabase_, &rv);
00326     if (NULL == ptr)
00327     {
00328          printError(rv, "Allocation failed for User chunk catalog table");
00329          return NULL;
00330     }
00331     Chunk *chunkInfo = (Chunk*)ptr;
00332     chunkInfo->initMutex();
00333     if (0 != size) chunkInfo->setSize(size);
00334     if (chunkInfo->allocSize_ > PAGE_SIZE)
00335         chunkInfo->curPage_ = db_->getFreePage(chunkInfo->allocSize_);
00336     else
00337         chunkInfo->curPage_ = db_->getFreePage();
00338     if ( NULL == chunkInfo->curPage_)
00339     {
00340         chunkInfo->destroyMutex();
00341         chunk->free(db_, ptr);
00342         printError(ErrNoMemory, "Database full: No space to allocate from database");
00343         return NULL;
00344     }
00345     PageInfo* firstPageInfo = ((PageInfo*)chunkInfo->curPage_);
00346     if (chunkInfo->allocSize_ > PAGE_SIZE)
00347     {
00348         int multiple = os::floor(chunkInfo->allocSize_ / PAGE_SIZE);
00349         int offset = ((multiple + 1) * PAGE_SIZE);
00350         firstPageInfo->setPageAsUsed(offset);
00351     }
00352     else
00353     {
00354         firstPageInfo->setPageAsUsed(chunkInfo->allocSize_);
00355         char *data = ((char*)firstPageInfo) + sizeof(PageInfo);
00356         *(int*)data =0;
00357     }
00358     if (0 == size)
00359     {
00360         VarSizeInfo *varInfo = (VarSizeInfo*)(((char*)firstPageInfo) + sizeof(PageInfo));
00361         varInfo->isUsed_ = 0;
00362         varInfo->size_ = PAGE_SIZE - sizeof(PageInfo) - sizeof(VarSizeInfo);
00363 
00364     }
00365     chunkInfo->firstPage_ = chunkInfo->curPage_;
00366 
00367     if (0 == size)
00368         chunkInfo->setAllocType(VariableSizeAllocator);
00369     else
00370         chunkInfo->setAllocType(FixedSizeAllocator);
00371 
00372     //TODO::Generate chunkid::use tableid
00373     chunkInfo->setChunkID(-1);
00374     db_->incrementChunk();
00375     printDebug(DM_Database, "Creating new User chunk chunkID:%d size: %d firstPage:%x",
00376                                -1, chunkInfo->allocSize_, firstPageInfo);
00377 
00378     return chunkInfo;
00379 }
00380 
00381 //Assumes that system database mutex is taken before calling this.
00382 DbRetVal DatabaseManagerImpl::deleteUserChunk(Chunk *chunk)
00383 {
00384     //Go to the pages and set them to notUsed
00385     Page *page = chunk->firstPage_;
00386     PageInfo* pageInfo = ((PageInfo*)page);
00387     //Here...sure that atleast one page will be there even no tuples
00388     //are inserted.so not checking if pageInfo == NULL
00389     while( pageInfo->nextPage_ != NULL)
00390     {
00391         PageInfo *prev = pageInfo;
00392         pageInfo = (PageInfo*)(pageInfo->nextPage_);
00393         //sets pageInfo->isUsed_ = 0 and pageInfo->hasFreeSpace_ = 0
00394         //and initializes the page content to zero
00395         if(NULL == pageInfo->nextPageAfterMerge_)
00396             os::memset(prev, 0, PAGE_SIZE);
00397         else
00398         {
00399             int size = (char*) pageInfo->nextPageAfterMerge_ - (char*) pageInfo;
00400             os::memset(prev, 0, size);
00401         }
00402         printDebug(DM_Database,"deleting user chunk:%x clearing page %x",chunk, prev);
00403     }
00404     //The above loop wont execute for the last page
00405     //and for the case where table has only one page
00406     if(NULL == pageInfo->nextPageAfterMerge_)
00407         os::memset(pageInfo, 0, PAGE_SIZE);
00408     else
00409     {
00410         int size = (char*) pageInfo->nextPageAfterMerge_ - (char*) pageInfo;
00411         os::memset(pageInfo, 0, size);
00412     }
00413     printDebug(DM_Database,"deleting user chunk:%x clearing page %x",chunk, pageInfo);
00414     chunk->chunkID_ = -1;
00415     chunk->allocSize_ = 0;
00416     chunk->curPage_ = NULL;
00417     chunk->firstPage_ = NULL;
00418     chunk->destroyMutex();
00419     db_->decrementChunk();
00420     printDebug(DM_Database,"deleting user chunk:%x",chunk);
00421     return OK;
00422 }
00423 
00424 //-1 -> Unable to create chunk. No memory
00425 //-2 -> Unable to update the catalog tables
00426 DbRetVal DatabaseManagerImpl::createTable(const char *name, TableDef &def)
00427 {
00428     DbRetVal rv = OK;
00429     int fldCount = def.getFieldCount();
00430     //If total field count is less than 32, then 1 integer is used to store all null
00431     //information, if it is more then 1 char is used to store null information 
00432     //of each field
00433     //This is to done to reduce cpu cycles for small tables
00434     int addSize = 0;
00435     if (fldCount < 31) addSize = 4; else addSize = os::align(fldCount);
00436     size_t sizeofTuple = os::align(def.getTupleSize())+addSize;
00437 
00438     rv = systemDatabase_->getDatabaseMutex();
00439     if (OK != rv ) {
00440         printError(rv, "Unable to get Database mutex");
00441         return rv;
00442     }
00443 
00444     void *tptr =NULL;
00445     void *chunk = NULL;
00446 
00447     //check whether table already exists
00448     CatalogTableTABLE cTable(systemDatabase_);
00449     cTable.getChunkAndTblPtr(name, chunk, tptr);
00450     if (NULL != tptr)
00451     {
00452         systemDatabase_->releaseDatabaseMutex();
00453         printError(ErrAlready, "Table %s already exists", name);
00454         return ErrAlready;
00455     }
00456 
00457     //create a chunk to store the tuples
00458     Chunk *ptr = createUserChunk(sizeofTuple);
00459     if (NULL  == ptr)
00460     {
00461         systemDatabase_->releaseDatabaseMutex();
00462         printError(ErrNoResource, "Unable to create user chunk");
00463         return ErrNoResource;
00464     }
00465     printDebug(DM_Database,"Created UserChunk:%x", ptr);
00466 
00467     //add row to TABLE
00468     int tblID = ((Chunk*)ptr)->getChunkID();
00469     rv = cTable.insert(name, tblID, sizeofTuple,
00470                                    def.getFieldCount(), ptr, tptr);
00471     if (OK != rv)
00472     {
00473         deleteUserChunk(ptr);
00474         systemDatabase_->releaseDatabaseMutex();
00475         printError(ErrSysInternal, "Unable to update catalog table TABLE");
00476         return ErrSysInternal;
00477     }
00478     printDebug(DM_Database,"Inserted into TABLE:%s",name);
00479     //add rows to FIELD
00480     FieldIterator iter = def.getFieldIterator();
00481     CatalogTableFIELD cField(systemDatabase_);
00482     rv = cField.insert(iter, tblID ,tptr);
00483     if (OK != rv)
00484     {
00485         deleteUserChunk(ptr);
00486         void *cptr, *ttptr;//Dummy as remove below needs both these OUT params
00487         cTable.remove(name, cptr, ttptr);
00488         systemDatabase_->releaseDatabaseMutex();
00489         printError(ErrSysInternal, "Unable to update catalog table FIELD");
00490         return ErrSysInternal;
00491     }
00492     printDebug(DM_Database,"Inserted into FIELD:%s",name);
00493     systemDatabase_->releaseDatabaseMutex();
00494     printDebug(DM_Database,"Table Created:%s",name);
00495     logFinest(logger, "Table Created %s" , name);
00496     return OK;
00497 }
00498 
00499 //TODO::If any operation fails in between, then we may have some 
00500 //dangling tuples, say we have have rows in INDEX table 
00501 //which will not have any corresponding entries in TABLE 
00502 //CHANGE the sequence so that it deletes from the bottom as 
00503 //opposed to start from top as is written now
00504 DbRetVal DatabaseManagerImpl::dropTable(const char *name)
00505 {
00506     void *chunk = NULL;
00507     void *tptr =NULL;
00508     DbRetVal rv = systemDatabase_->getDatabaseMutex();
00509     if (OK != rv) {
00510         printError(ErrSysInternal, "Unable to get database mutex");
00511         return ErrSysInternal;
00512     }
00513 
00514     //remove the entry in TABLE
00515     CatalogTableTABLE cTable(systemDatabase_);
00516     rv = cTable.getChunkAndTblPtr(name, chunk, tptr);
00517     if (OK != rv) {
00518         systemDatabase_->releaseDatabaseMutex();
00519         printError(ErrSysInternal, "Table %s does not exist", name);
00520         return ErrSysInternal;
00521     }
00522     rv = lMgr_->getExclusiveLock(chunk, NULL);
00523     if (rv !=OK)
00524     {
00525         systemDatabase_->releaseDatabaseMutex();
00526         printError(ErrLockTimeOut, "Unable to acquire exclusive lock on the table\n");
00527         return rv;
00528     }
00529 
00530     rv = cTable.remove(name, chunk, tptr);
00531     if (OK != rv) {
00532         systemDatabase_->releaseDatabaseMutex();
00533         printError(ErrSysInternal, "Unable to update catalog table TABLE");
00534         return ErrSysInternal;
00535     }
00536     printDebug(DM_Database,"Deleted from TABLE:%s",name);
00537 
00538     //remove the entries in the FIELD table
00539     CatalogTableFIELD cField(systemDatabase_);
00540     rv = cField.remove(tptr);
00541     if (OK != rv) {
00542         systemDatabase_->releaseDatabaseMutex();
00543         printError(ErrSysInternal, "Unable to update catalog table FIELD");
00544         return ErrSysInternal;
00545     }
00546     printDebug(DM_Database,"Deleted from FIELD:%s",name);
00547 
00548     rv = deleteUserChunk((Chunk*)chunk);
00549     if (OK != rv) {
00550         systemDatabase_->releaseDatabaseMutex();
00551         printError(rv, "Unable to delete the chunk");
00552         return rv;
00553     }
00554     printDebug(DM_Database,"Deleted UserChunk:%x", chunk);
00555 
00556     //TODO::check whether indexes are available and drop that also.
00557     CatalogTableINDEX cIndex(systemDatabase_);
00558     int noIndexes = cIndex.getNumIndexes(tptr);
00559     for (int i =1 ; i<= noIndexes; i++) {
00560         char *idxName = cIndex.getIndexName(tptr, 1);
00561         dropIndexInt(idxName, false);
00562     }
00563     Chunk *chunkNode = systemDatabase_->getSystemDatabaseChunk(UserChunkTableId);
00564     chunkNode->free(systemDatabase_, (Chunk *) chunk);
00565     systemDatabase_->releaseDatabaseMutex();
00566     printDebug(DM_Database, "Deleted Table %s" , name);
00567     logFinest(logger, "Deleted Table %s" , name);
00568     rv = lMgr_->releaseLock(chunk);
00569     if (rv !=OK)
00570     {
00571         printError(ErrLockTimeOut, "Unable to release exclusive lock on the table\n");
00572         return rv;
00573     }
00574     return OK;
00575 }
00576 
00577 //Return values: NULL for table not found
00578 Table* DatabaseManagerImpl::openTable(const char *name)
00579 {
00580     DbRetVal ret = OK;
00581     //TODO::store table handles in list so that if it is
00582     //not closed by the application. destructor shall close it.
00583     TableImpl *table = new TableImpl();
00584     table->setDB(db_);
00585     table->setSystemDB(systemDatabase_);
00586     table->setLockManager(lMgr_);
00587     table->setTrans(ProcessManager::getThreadTransAddr(systemDatabase_->procSlot));
00588 
00589     //to store the chunk pointer of table
00590     void *chunk = NULL;
00591 
00592     //to store the tuple pointer of the table
00593     void *tptr =NULL;
00594 
00595     //TODO::need to take shared lock on the table so that
00596     //all ddl operation will be denied on that table
00597     //which includes index creation, alter table
00598 
00599     DbRetVal rv = systemDatabase_->getDatabaseMutex();
00600     if (OK != rv) {
00601         printError(ErrSysInternal, "Unable to get database mutex");
00602         delete table;
00603         return NULL;
00604     }
00605     CatalogTableTABLE cTable(systemDatabase_);
00606     ret = cTable.getChunkAndTblPtr(name, chunk, tptr);
00607     if ( OK != ret)
00608     {
00609         systemDatabase_->releaseDatabaseMutex();
00610         delete table;
00611         printError(ErrNotExists, "Table not exists %s", name);
00612         return NULL;
00613     }
00614     TABLE *tTuple = (TABLE*)tptr;
00615     table->setTableInfo(tTuple->tblName_, tTuple->tblID_, tTuple->length_,
00616                         tTuple->numFlds_, tTuple->numIndexes_, tTuple->chunkPtr_);
00617     /*rv = table->lock(true); //take shared lock
00618     if (rv !=OK)
00619     {
00620         printError(ErrLockTimeOut, "Unable to acquire shared lock on the table\n");
00621         systemDatabase_->releaseDatabaseMutex();
00622         delete table;
00623         return NULL;
00624     }*/
00625 
00626 
00627     if (tTuple->numFlds_ < 31) 
00628     { 
00629         table->isIntUsedForNULL = true;
00630         table->iNullInfo = 0;
00631         table->iNotNullInfo =0;
00632     }
00633     else
00634     {
00635         table->isIntUsedForNULL = false;
00636         int noFields = os::align(tTuple->numFlds_);
00637         table->cNullInfo = (char*) malloc(noFields);
00638         table->cNotNullInfo = (char*) malloc(noFields);
00639         for (int i =0 ; i < noFields; i++) table->cNullInfo[i] =0;
00640         for (int i =0 ; i < noFields; i++) table->cNotNullInfo[i] =0;
00641 
00642     }
00643 
00644     //get field information from FIELD table
00645     CatalogTableFIELD cField(systemDatabase_);
00646     cField.getFieldInfo(tptr, table->fldList_);
00647 
00648     //populate the notnull info
00649     FieldIterator fIter = table->fldList_.getIterator();
00650     int fldpos=1;
00651     while (fIter.hasElement())
00652     {
00653         FieldDef def = fIter.nextElement();
00654         if (table->isIntUsedForNULL) {
00655             if (def.isNull_) SETBIT(table->iNotNullInfo, fldpos);
00656         }
00657         else {
00658             if (def.isNull_) table->cNotNullInfo[fldpos-1] = 1;
00659         }
00660         fldpos++;
00661    } 
00662 
00663     //get the number of indexes on this table
00664     //and populate the indexPtr array
00665     CatalogTableINDEX cIndex(systemDatabase_);
00666     table->numIndexes_ = cIndex.getNumIndexes(tptr);
00667     if (table->numIndexes_) {
00668         table->indexPtr_ = new char*[table->numIndexes_];
00669         table->idxInfo = new IndexInfo*[table->numIndexes_];
00670     }
00671     else
00672     {
00673         table->indexPtr_ = NULL;
00674     }
00675     cIndex.getIndexPtrs(tptr, table->indexPtr_);
00676     for (int i =0 ; i < table->numIndexes_; i++ )
00677     {
00678         SingleFieldHashIndexInfo *hIdxInfo = new SingleFieldHashIndexInfo();
00679         CatalogTableINDEXFIELD cIndexField(systemDatabase_);
00680         cIndexField.getFieldNameAndType(table->indexPtr_[i], hIdxInfo->fldName,
00681                                                       hIdxInfo->type);
00682         ChunkIterator citer = CatalogTableINDEX::getIterator(table->indexPtr_[i]);
00683         hIdxInfo->noOfBuckets = CatalogTableINDEX::getNoOfBuckets(table->indexPtr_[i]);
00684         hIdxInfo->isUnique = CatalogTableINDEX::getUnique(table->indexPtr_[i]);
00685         hIdxInfo->buckets = (Bucket*)citer.nextElement();
00686         hIdxInfo->offset = table->fldList_.getFieldOffset(hIdxInfo->fldName);
00687         hIdxInfo->length = table->fldList_.getFieldLength(hIdxInfo->fldName);
00688         table->idxInfo[i] = (IndexInfo*) hIdxInfo;
00689     }
00690     systemDatabase_->releaseDatabaseMutex();
00691    // lMgr->  tTuple->chunkPtr_
00692     printDebug(DM_Database,"Opening table handle name:%s chunk:%x numIndex:%d",
00693                                          name, chunk, table->numIndexes_);
00694     logFinest(logger, "Opening Table %s" , name);
00695 
00696         
00697     return table;
00698 }
00699 
00700 
00701 
00702 List DatabaseManagerImpl::getAllTableNames()
00703 {
00704     DbRetVal ret = OK;
00705     //to store the tuple pointer of the table
00706     void *tptr =NULL;
00707 
00708     DbRetVal rv = systemDatabase_->getDatabaseMutex();
00709     if (OK != rv) {
00710         printError(ErrSysInternal, "Unable to get database mutex");
00711         List tableList;
00712         return tableList;
00713     }
00714     CatalogTableTABLE cTable(systemDatabase_);
00715     List tableList = cTable.getTableList();
00716     systemDatabase_->releaseDatabaseMutex();
00717     return tableList;
00718 }
00719 
00720 
00721 
00722 
00723 //Return values: -1 for table not found
00724 void DatabaseManagerImpl::closeTable(Table *table)
00725 {
00726     printDebug(DM_Database,"Closing table handle: %x", table);
00727     if (NULL == table) return;
00728     //table->unlock();
00729     delete table;
00730     logFinest(logger, "Closing Table");
00731 }
00732 
00733 DbRetVal DatabaseManagerImpl::createIndex(const char *indName, IndexInitInfo *info)
00734 {
00735     DbRetVal rv = OK;
00736     if (!info->isUnique && info->isPrimary) 
00737     {
00738         printError(ErrBadCall, "Primary key cannot be non unique\n");
00739         return ErrBadCall;
00740     }
00741     if (info->indType == hashIndex)
00742     {
00743         //Assumes info is of type HashIndexInitInfo
00744         HashIndexInitInfo *hInfo = (HashIndexInitInfo*) info;
00745         rv = createHashIndex(indName, info->tableName, info->list, hInfo->bucketSize,
00746                              info->isUnique, info->isPrimary);
00747     }
00748     else if (info->indType == treeIndex)
00749     {
00750         //TODO::tree index
00751         printError(ErrNotYet, "Tree Index not supported\n");
00752         return ErrNotYet;
00753     }else {
00754         printError(ErrBadCall, "Index type not supported\n");
00755         return ErrBadCall;
00756     }
00757     return rv;
00758 }
00759 
00760 
00761 //-1 -> Table does not exists
00762 //-2 -> Field does not exists
00763 //-3 -> bucketSize is not valid
00764 DbRetVal DatabaseManagerImpl::createHashIndex(const char *indName, const char *tblName,
00765                       FieldNameList &fldList, int bucketSize, bool isUnique, bool isPrimary)
00766 {
00767     //validate the bucket size
00768     if (bucketSize < 100 || bucketSize > 200000)
00769     {
00770         printError(ErrBadRange, "Index Bucket size %d not in range 100-200000",
00771                                  bucketSize);
00772         return ErrBadRange;
00773     }
00774     int totFlds = fldList.size();
00775     if (totFlds == 0) 
00776     {
00777         printError(ErrBadCall, "No Field name specified");
00778         return ErrBadCall;
00779     }else if (totFlds >1) {
00780         printError(ErrNotYet, "Composite keys not supported");
00781         return ErrNotYet;
00782     }
00783     void *tptr =NULL;
00784     void *chunk = NULL;
00785     DbRetVal rv = systemDatabase_->getDatabaseMutex();
00786     if (OK != rv)
00787     {
00788         printError(ErrSysInternal, "Unable to get database mutex");
00789         return ErrSysInternal;
00790     }
00791 
00792     //check whether table exists
00793     CatalogTableTABLE cTable(systemDatabase_);
00794     cTable.getChunkAndTblPtr(tblName, chunk, tptr);
00795     if (NULL == tptr)
00796     {
00797         systemDatabase_->releaseDatabaseMutex();
00798         printError(ErrNotExists, "Table does not exist %s", tblName);
00799         return ErrNotExists;
00800     }
00801 
00802     //check whether field exists
00803     char **fptr = new char* [totFlds];
00804     CatalogTableFIELD cField(systemDatabase_);
00805     rv = cField.getFieldPtrs(fldList, tptr, fptr);
00806     if (OK != rv)
00807     {
00808         delete[] fptr;
00809         systemDatabase_->releaseDatabaseMutex();
00810         //TODO::check test cases of dbapi/Index, they give wrong results
00811         //if (rv == ErrBadCall) {
00813         //} else {
00814         //printError(ErrNotExists, "Field does not exist");
00815         //} 
00816         //return ErrBadCall;
00817         if (rv != ErrBadCall) {
00818             printError(ErrNotExists, "Field does not exist");
00819             return ErrNotExists;
00820         }
00821     }
00822     for (int i=0; i <totFlds; i++)
00823     {
00824         FIELD* fInfo = (FIELD*)fptr[i];
00825         if (fInfo->type_ == typeFloat || fInfo->type_ == typeDouble || fInfo->type_ == typeTimeStamp) 
00826         {
00827             printError(ErrBadArg, "HashIndex cannot be created for float or double or timestamp type");
00828             delete[] fptr;
00829             systemDatabase_->releaseDatabaseMutex();
00830             return ErrBadArg;
00831         }
00832         if (!fInfo->isNull_ && isPrimary ) 
00833         {
00834             printError(ErrBadArg, "Primary Index cannot be created on field without NOTNULL constraint");
00835             delete[] fptr;
00836             systemDatabase_->releaseDatabaseMutex();
00837             return ErrBadArg;
00838         }
00839     }
00840     //create chunk to store the meta data of the index created
00841     //for latches and bucket pointers
00842     printDebug(DM_HashIndex, "Creating chunk for storing hash buckets of size %d\n", 
00843                              bucketSize * sizeof(Bucket));
00844     Chunk* chunkInfo = createUserChunk(bucketSize * sizeof(Bucket));
00845     if (NULL == chunkInfo)
00846     {
00847         delete[] fptr;
00848         systemDatabase_->releaseDatabaseMutex();
00849         printError(ErrSysInternal, "Unable to create chunk");
00850         return ErrSysInternal;
00851     }
00852     //create memory for holding the bucket pointers
00853     void *buckets = chunkInfo->allocate(db_, &rv);
00854     if (NULL == buckets)
00855     {
00856         delete[] fptr;
00857         deleteUserChunk(chunkInfo);
00858         systemDatabase_->releaseDatabaseMutex();
00859         printError(rv, "Unable to allocate memory for bucket");
00860         return rv;
00861     }
00862     Bucket *buck = (Bucket*) buckets;
00863     initHashBuckets(buck, bucketSize);
00864 
00865     //create chunk to store the hash index nodes
00866     Chunk* hChunk = createUserChunk(sizeof(HashIndexNode));
00867     if (NULL == hChunk)
00868     {
00869         delete[] fptr;
00870         deleteUserChunk(chunkInfo);
00871         systemDatabase_->releaseDatabaseMutex();
00872         printError(ErrSysInternal, "Unable to create chunk for storing hash index nodes");
00873         return ErrSysInternal;
00874     }
00875 
00876 
00877     //add row to INDEX
00878     void *tupleptr = NULL;
00879     CatalogTableINDEX cIndex(systemDatabase_);
00880     rv = cIndex.insert(indName, tptr, fldList.size(), isUnique,
00881                         chunkInfo, bucketSize, hChunk, tupleptr);
00882     if (OK != rv)
00883     {
00884         delete[] fptr;
00885         deleteUserChunk(hChunk);
00886         deleteUserChunk(chunkInfo);
00887         systemDatabase_->releaseDatabaseMutex();
00888         printError(ErrSysInternal, "Catalog table updation failed in INDEX table");
00889         return ErrSysInternal;
00890     }
00891     //add rows to INDEXFIELD
00892     CatalogTableINDEXFIELD cIndexField(systemDatabase_);
00893     rv = cIndexField.insert(fldList, tupleptr, tptr, fptr);
00894 
00895     if (OK != rv)
00896     {
00897         delete[] fptr;
00898         cIndex.remove(indName, (void *&)chunkInfo, (void *&)hChunk, (void *&)tupleptr);
00899         deleteUserChunk(hChunk);
00900         deleteUserChunk(chunkInfo);
00901         systemDatabase_->releaseDatabaseMutex();
00902         printError(ErrSysInternal, "Catalog table updation failed in INDEXFIELD table");
00903         return ErrSysInternal;
00904     }
00905     delete[] fptr;
00906     //TODO::If tuples present in this table, then
00907     //create hash index nodes and store it
00908     //Take table lock
00909     systemDatabase_->releaseDatabaseMutex();
00910     printDebug(DM_Database, "Creating Hash Index Name:%s tblname:%s buckets:%x",
00911                                    indName, tblName, buckets);
00912     logFinest(logger, "Creating HashIndex %s on %s with bucket size %d", 
00913                                    indName, tblName, buckets);
00914     return OK;
00915 }
00916 
00917 void DatabaseManagerImpl::initHashBuckets(Bucket *buck, int bucketSize)
00918 {
00919     os::memset((void*)buck, 0, bucketSize * sizeof(Bucket));
00920 
00921     for (int i=0; i < bucketSize ; i++)
00922     {
00923         buck[i].mutex_.init("Bucket");
00924     }
00925     return;
00926 }
00927 
00928 DbRetVal DatabaseManagerImpl::dropIndex(const char *name)
00929 {
00930     return dropIndexInt(name, true);
00931 }
00932 
00933 DbRetVal DatabaseManagerImpl::dropIndexInt(const char *name, bool takeLock)
00934 {
00935     DbRetVal rv = OK;
00936     void *chunk = NULL, *hchunk = NULL;
00937     void *tptr =NULL;
00938     int ret = 0;
00939     if (takeLock) {
00940         rv = systemDatabase_->getDatabaseMutex();
00941         if (OK != rv)
00942         {
00943             printError(ErrSysInternal, "Unable to get database mutex");
00944             return ErrSysInternal;
00945         }
00946     }
00947 
00948     //remove the entry in INDEX
00949     CatalogTableINDEX cIndex(systemDatabase_);
00950     rv = cIndex.remove(name, chunk, hchunk, tptr);
00951     if (OK != rv)
00952     {
00953         if (takeLock) systemDatabase_->releaseDatabaseMutex();
00954         printError(ErrSysInternal, "Catalog table updation failed for INDEX table");
00955         return ErrSysInternal;
00956     }
00957     printDebug(DM_Database, "Removing from INDEX %s",name);
00958     //remove the entries in the INDEXFIELD table
00959     CatalogTableINDEXFIELD cIndexField(systemDatabase_);
00960     rv = cIndexField.remove(tptr);
00961     if (OK != rv)
00962     {
00963         if (takeLock) systemDatabase_->releaseDatabaseMutex();
00964         printError(ErrSysInternal, "Catalog table updation failed for INDEX table");
00965         return ErrSysInternal;
00966     }
00967     printDebug(DM_Database, "Removing from INDEXFIELD %s",name);
00968 
00969     //delete the index chunk
00970     rv = deleteUserChunk((Chunk*)chunk);
00971     if (OK != rv)
00972     {
00973         if (takeLock) systemDatabase_->releaseDatabaseMutex();
00974         printError(ErrSysInternal, "Unable to delete the index chunk");
00975         return ErrSysInternal;
00976     }
00977     //delete the index hash node chunk
00978     rv = deleteUserChunk((Chunk*)hchunk);
00979     if (OK != rv)
00980     {
00981         if (takeLock) systemDatabase_->releaseDatabaseMutex();
00982         printError(ErrSysInternal, "Unable to delete the index hash node chunk");
00983         return ErrSysInternal;
00984     }
00985     if (takeLock) systemDatabase_->releaseDatabaseMutex();
00986     Chunk *chunkNode = systemDatabase_->getSystemDatabaseChunk(UserChunkTableId);
00987     chunkNode->free(systemDatabase_, (Chunk *) chunk);
00988     chunkNode->free(systemDatabase_, (Chunk *) hchunk);
00989 
00990     //TODO::If tuples present in this table, then
00991     //free all hash index nodes for this table.
00992     //free all nodes in list of all buckets
00993     //Take table lock
00994 
00995     printDebug(DM_Database, "Dropped hash index %s",name);
00996     logFinest(logger, "Deleted Index %s", name);
00997     return OK;
00998 }
00999 DbRetVal DatabaseManagerImpl::printIndexInfo(char *name)
01000 {
01001     CatalogTableINDEX cIndex(systemDatabase_);
01002     DbRetVal rv = OK;
01003     void *chunk = NULL, *hchunk = NULL;
01004     void *tptr =NULL;
01005     rv = cIndex.get(name, chunk, hchunk, tptr);
01006     if (OK != rv) return rv;
01007     printf("<IndexName> %s </IndexName>\n", name);
01008     printf("<Unique> %d </Unique>\n", CatalogTableINDEX::getUnique(tptr));
01009     Chunk *ch = (Chunk*) chunk;
01010     printf("<HashBucket>\n");
01011     printf("  <TotalPages> %d </TotalPages>\n", ch->totalPages());
01012     printf("  <TotalBuckets> %d </TotalBuckets> \n", CatalogTableINDEX::getNoOfBuckets(tptr));
01013     printf("</HashBucket>\n");
01014 
01015     ch = (Chunk*) hchunk;
01016     printf("<IndexNodes>\n");
01017     printf("  <TotalPages> %d </TotalPages>\n", ch->totalPages());
01018     printf("  <TotalNodes> %d </TotalNodes>\n", ch->getTotalDataNodes());
01019     printf("<IndexNodes>\n");
01020     return OK;
01021 }
01022 
01023 DbRetVal DatabaseManagerImpl::registerThread()
01024 {
01025     DbRetVal rv = OK;
01026     if (pMgr_ != NULL) 
01027     {
01028         printError(ErrAlready, "Process already registered\n");
01029         return ErrAlready;
01030     }
01031     pMgr_ = new ProcessManager();
01032     rv = pMgr_->registerThread();
01033     if (rv ==OK) { procSlot = pMgr_->getProcSlot();
01034         printDebug(DM_Process, "Process registed with slot %d\n", procSlot);
01035     }
01036     return rv;
01037 }
01038 
01039 DbRetVal DatabaseManagerImpl::deregisterThread()
01040 {
01041     DbRetVal rv = OK;
01042     if (pMgr_ != NULL) 
01043     {
01044         rv = pMgr_->deregisterThread(procSlot);
01045         delete pMgr_;
01046         pMgr_ = NULL;
01047     }
01048     return rv;
01049 }
01050 
01051 bool DatabaseManagerImpl::isAnyOneRegistered()
01052 {
01053     if (pMgr_ != NULL) return pMgr_->isAnyOneRegistered();
01054     return true;
01055 }
01056 
01057 
01058 void DatabaseManagerImpl::printUsageStatistics()
01059 {
01060     pMgr_->printUsageStatistics();
01061     tMgr_->printUsageStatistics();
01062     lMgr_->printUsageStatistics();
01063 }
01064 
01065 void DatabaseManagerImpl::printDebugLockInfo()
01066 {
01067     lMgr_->printDebugInfo();
01068 }
01069 
01070 void DatabaseManagerImpl::printDebugTransInfo()
01071 {
01072     tMgr_->printDebugInfo(systemDatabase_);
01073 }
01074 void DatabaseManagerImpl::printDebugProcInfo()
01075 {
01076     pMgr_->printDebugInfo();
01077 }
01078 void DatabaseManagerImpl::printDebugChunkInfo()
01079 {
01080     printf("<NotYetImplemented> </NotYetImplemented>\n");
01081 }
01082 ChunkIterator DatabaseManagerImpl::getSystemTableIterator(CatalogTableID id)
01083 {
01084     Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(id);
01085     return fChunk->getIterator();
01086 }
01087 
01088 Chunk* DatabaseManagerImpl::getSystemTableChunk(CatalogTableID id)
01089 {
01090     return systemDatabase_->getSystemDatabaseChunk(id);
01091 }

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