1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 ***************************************************************************/
17 #include<DatabaseManager.h>
18 #include<DatabaseManagerImpl.h>
22 #include<Transaction.h>
23 #include<CatalogTables.h>
31 DatabaseManagerImpl::~DatabaseManagerImpl()
33 //Note:Databases are closed by the session interface
38 void DatabaseManagerImpl::createLockManager()
40 lMgr_
= new LockManager(systemDatabase_
);
44 void DatabaseManagerImpl::createTransactionManager()
47 tMgr_
= new TransactionManager();
48 tMgr_
->setFirstTrans(systemDatabase_
->getSystemDatabaseTrans(0));
51 void DatabaseManagerImpl::setProcSlot()
53 systemDatabase_
->setProcSlot(procSlot
);
54 db_
->setProcSlot(procSlot
);
56 DbRetVal
DatabaseManagerImpl::openSystemDatabase()
58 DbRetVal rv
= openDatabase(SYSTEMDB
);
59 if (rv
!= OK
) return rv
;
60 systemDatabase_
= db_
;
62 printDebug(DM_Database
, "Opened system database");
63 logFinest(logger
, "Opened system database");
67 DbRetVal
DatabaseManagerImpl::closeSystemDatabase()
70 //make them to point to system database file descriptor
71 //and database pointer
72 db_
= systemDatabase_
;
75 printDebug(DM_Database
, "Closed system database");
76 logFinest(logger
, "Closed System database");
80 DbRetVal
DatabaseManagerImpl::createDatabase(const char *name
, size_t size
)
84 printError(ErrAlready
, "Database is already created");
87 caddr_t rtnAddr
= (caddr_t
) NULL
;
88 shared_memory_id shm_id
= 0;
90 char *startaddr
= (char*)Conf::config
.getMapAddress();
91 shared_memory_key key
= 0;
92 if (0 == strcmp(name
, SYSTEMDB
))
95 key
= Conf::config
.getSysDbKey();
99 startaddr
= startaddr
+ Conf::config
.getMaxSysDbSize();
100 key
= Conf::config
.getUserDbKey();
102 shm_id
= os::shm_create(key
, size
, 0666);
105 if (errno
== EEXIST
) {
106 printError(ErrOS
, "Shared Memory already exists");
108 printError(ErrOS
, "Shared memory create failed");
112 void *shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
113 rtnAddr
= (caddr_t
) shm_ptr
;
114 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
116 printError(ErrOS
, "Shared memory attach returned -ve value %d", rtnAddr
);
119 memset(shm_ptr
, 0, size
);
120 db_
= new Database();
121 printDebug(DM_Database
, "Creating database:%s",name
);
123 //TODO:for user database do not have transtable and processtable mutex
124 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
125 db_
->setDatabaseID(1);
127 db_
->setMaxSize(size
);
128 db_
->setNoOfChunks(0);
129 db_
->initAllocDatabaseMutex();
130 db_
->initTransTableMutex();
131 db_
->initDatabaseMutex();
132 db_
->initProcessTableMutex();
134 //compute the first page after book keeping information
135 size_t offset
= os::alignLong(sizeof (DatabaseMetaData
));
136 //Only for system db chunk array, trans array and proc array will be there
137 if (0 == strcmp(name
, SYSTEMDB
))
139 offset
= offset
+ os::alignLong( MAX_CHUNKS
* sizeof (Chunk
));
140 offset
= offset
+ os::alignLong( Conf::config
.getMaxProcs() * sizeof(Transaction
));
141 offset
= offset
+ os::alignLong( Conf::config
.getMaxProcs() * sizeof(ThreadInfo
));
143 int multiple
= os::floor(offset
/ PAGE_SIZE
);
144 char *curPage
= (((char*)rtnAddr
) + ((multiple
+ 1) * PAGE_SIZE
));
146 db_
->setCurrentPage(curPage
);
147 db_
->setFirstPage(curPage
);
149 if (0 == strcmp(name
, SYSTEMDB
)) return OK
;
151 /*Allocate new chunk to store hash index nodes
152 Chunk *chunkInfo = createUserChunk(sizeof(HashIndexNode));
153 if (NULL == chunkInfo)
155 printError(ErrSysInternal, "Failed to allocate hash index nodes chunk");
156 return ErrSysInternal;
158 printDebug(DM_Database, "Creating Chunk for storing Hash index nodes %x",
161 db_->setHashIndexChunk(chunkInfo);*/
162 logFinest(logger
, "Created database %s" , name
);
167 DbRetVal
DatabaseManagerImpl::deleteDatabase(const char *name
)
169 shared_memory_id shm_id
= 0;
170 if (0 == strcmp(name
, SYSTEMDB
))
172 shm_id
= os::shm_open(Conf::config
.getSysDbKey(), 100, 0666);
173 os::shmctl(shm_id
, IPC_RMID
);
174 delete systemDatabase_
;
175 systemDatabase_
= NULL
;
177 shm_id
= os::shm_open(Conf::config
.getUserDbKey(), 100, 0666);
178 os::shmctl(shm_id
, IPC_RMID
);
182 logFinest(logger
, "Deleted database %s" , name
);
186 DbRetVal
DatabaseManagerImpl::openDatabase(const char *name
)
188 long size
= Conf::config
.getMaxSysDbSize();
189 char *startaddr
= (char*)Conf::config
.getMapAddress();
190 if (0 == strcmp(name
, SYSTEMDB
))
192 if (NULL
!=systemDatabase_
)
194 printError(ErrAlready
, "System Database already open");
200 if (NULL
==systemDatabase_
)
202 printError(ErrNotOpen
, "System Database not open");
205 size
= Conf::config
.getMaxDbSize();
206 startaddr
= startaddr
+ Conf::config
.getMaxSysDbSize();
210 printError(ErrAlready
, "User Database already open");
213 //system db should be opened before user database files
214 caddr_t rtnAddr
= (caddr_t
) NULL
;
216 shared_memory_id shm_id
= 0;
217 shared_memory_key key
= 0;
219 if (0 == strcmp(name
, SYSTEMDB
))
220 key
= Conf::config
.getSysDbKey();
222 key
= Conf::config
.getUserDbKey();
225 int ret
= ProcessManager::mutex
.getLock(-1, false);
226 //If you are not getting lock ret !=0, it means somebody else is there.
227 //he will close the database.
230 printError(ErrSysInternal
, "Another thread calling open:Wait and then Retry\n");
231 return ErrSysInternal
;
233 void *shm_ptr
= NULL
;
234 bool firstThread
= false;
235 //printf("PRABA::DEBUG:: opendb %d %s\n", ProcessManager::noThreads, name);
236 if (ProcessManager::noThreads
== 0 && 0 == strcmp(name
, SYSTEMDB
)
237 || ProcessManager::noThreads
== 1 && 0 != strcmp(name
, SYSTEMDB
) ) {
238 shm_id
= os::shm_open(key
, size
, 0666);
241 printError(ErrOS
, "Shared memory open failed");
242 ProcessManager::mutex
.releaseLock(-1, false);
245 shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
246 if (0 == strcmp(name
, SYSTEMDB
))
249 ProcessManager::sysAddr
= (char*) shm_ptr
;
253 ProcessManager::usrAddr
= (char*) shm_ptr
;
256 if (0 == strcmp(name
, SYSTEMDB
))
257 shm_ptr
= ProcessManager::sysAddr
;
259 shm_ptr
= ProcessManager::usrAddr
;
261 ProcessManager::mutex
.releaseLock(-1, false);
264 rtnAddr
= (caddr_t
) shm_ptr
;
266 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
268 printError(ErrOS
, "Shared memory attach returned -ve value %x %d", shm_ptr
, errno
);
271 db_
= new Database();
272 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
274 if (firstThread
) ProcessManager::systemDatabase
= db_
;
276 printDebug(DM_Database
, "Opening database: %s", name
);
277 logFinest(logger
, "Opened database %s" , name
);
281 DbRetVal
DatabaseManagerImpl::closeDatabase()
286 //Database is already closed
289 printDebug(DM_Database
, "Closing database: %s",(char*)db_
->getName());
290 //check if this is the last thread to be deregistered
291 int ret
= ProcessManager::mutex
.getLock(-1, false);
292 //If you are not getting lock ret !=0, it means somebody else is there.
293 //he will close the database.
295 //printf("PRABA::FOR DEBUG closedb %d %s\n", ProcessManager::noThreads, (char*)db_->getName());
296 if (ProcessManager::noThreads
== 0 && 0 == strcmp((char*)db_
->getName(), SYSTEMDB
)
297 || ProcessManager::noThreads
== 1 && 0 != strcmp((char*)db_
->getName(), SYSTEMDB
) ) {
298 os::shm_detach((char*)db_
->getMetaDataPtr());
301 ProcessManager::mutex
.releaseLock(-1, false);
302 logFinest(logger
, "Closed database");
307 //Assumes that system database mutex is taken before calling this.
308 Chunk
* DatabaseManagerImpl::createUserChunk(size_t size
)
310 //Allocate new node in system database to store
311 Chunk
*chunk
= getSystemTableChunk(UserChunkTableId
);
313 void *ptr
= chunk
->allocate(systemDatabase_
, &rv
);
316 printError(rv
, "Allocation failed for User chunk catalog table");
319 Chunk
*chunkInfo
= (Chunk
*)ptr
;
320 chunkInfo
->initMutex();
321 if (0 != size
) chunkInfo
->setSize(size
);
322 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
323 chunkInfo
->curPage_
= db_
->getFreePage(chunkInfo
->allocSize_
);
325 chunkInfo
->curPage_
= db_
->getFreePage();
326 if ( NULL
== chunkInfo
->curPage_
)
328 chunkInfo
->destroyMutex();
329 chunk
->free(db_
, ptr
);
330 printError(ErrNoMemory
, "Database full: No space to allocate from database");
333 PageInfo
* firstPageInfo
= ((PageInfo
*)chunkInfo
->curPage_
);
334 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
336 int multiple
= os::floor(chunkInfo
->allocSize_
/ PAGE_SIZE
);
337 int offset
= ((multiple
+ 1) * PAGE_SIZE
);
338 firstPageInfo
->setPageAsUsed(offset
);
342 firstPageInfo
->setPageAsUsed(chunkInfo
->allocSize_
);
343 char *data
= ((char*)firstPageInfo
) + sizeof(PageInfo
);
348 VarSizeInfo
*varInfo
= (VarSizeInfo
*)(((char*)firstPageInfo
) + sizeof(PageInfo
));
349 varInfo
->isUsed_
= 0;
350 varInfo
->size_
= PAGE_SIZE
- sizeof(PageInfo
) - sizeof(VarSizeInfo
);
353 chunkInfo
->firstPage_
= chunkInfo
->curPage_
;
356 chunkInfo
->setAllocType(VariableSizeAllocator
);
358 chunkInfo
->setAllocType(FixedSizeAllocator
);
360 //TODO::Generate chunkid::use tableid
361 chunkInfo
->setChunkID(-1);
362 db_
->incrementChunk();
363 printDebug(DM_Database
, "Creating new User chunk chunkID:%d size: %d firstPage:%x",
364 -1, chunkInfo
->allocSize_
, firstPageInfo
);
369 //Assumes that system database mutex is taken before calling this.
370 DbRetVal
DatabaseManagerImpl::deleteUserChunk(Chunk
*chunk
)
372 //Go to the pages and set them to notUsed
373 Page
*page
= chunk
->firstPage_
;
374 PageInfo
* pageInfo
= ((PageInfo
*)page
);
375 //Here...sure that atleast one page will be there even no tuples
376 //are inserted.so not checking if pageInfo == NULL
377 while( pageInfo
->nextPage_
!= NULL
)
379 PageInfo
*prev
= pageInfo
;
380 pageInfo
= (PageInfo
*)(pageInfo
->nextPage_
);
381 //sets pageInfo->isUsed_ = 0 and pageInfo->hasFreeSpace_ = 0
382 //and initializes the page content to zero
383 if(NULL
== pageInfo
->nextPageAfterMerge_
)
384 os::memset(prev
, 0, PAGE_SIZE
);
387 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
388 os::memset(prev
, 0, size
);
390 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, prev
);
392 //The above loop wont execute for the last page
393 //and for the case where table has only one page
394 if(NULL
== pageInfo
->nextPageAfterMerge_
)
395 os::memset(pageInfo
, 0, PAGE_SIZE
);
398 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
399 os::memset(pageInfo
, 0, size
);
401 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, pageInfo
);
402 chunk
->chunkID_
= -1;
403 chunk
->allocSize_
= 0;
404 chunk
->curPage_
= NULL
;
405 chunk
->firstPage_
= NULL
;
406 chunk
->destroyMutex();
407 db_
->decrementChunk();
408 printDebug(DM_Database
,"deleting user chunk:%x",chunk
);
412 //-1 -> Unable to create chunk. No memory
413 //-2 -> Unable to update the catalog tables
414 DbRetVal
DatabaseManagerImpl::createTable(const char *name
, TableDef
&def
)
417 int fldCount
= def
.getFieldCount();
418 //If total field count is less than 32, then 1 integer is used to store all null
419 //information, if it is more then 1 char is used to store null information
421 //This is to done to reduce cpu cycles for small tables
423 if (fldCount
< 31) addSize
= 4; else addSize
= os::align(fldCount
);
424 size_t sizeofTuple
= os::align(def
.getTupleSize())+addSize
;
426 rv
= systemDatabase_
->getDatabaseMutex();
428 printError(rv
, "Unable to get Database mutex");
435 //check whether table already exists
436 CatalogTableTABLE
cTable(systemDatabase_
);
437 cTable
.getChunkAndTblPtr(name
, chunk
, tptr
);
440 systemDatabase_
->releaseDatabaseMutex();
441 printError(ErrAlready
, "Table %s already exists", name
);
445 //create a chunk to store the tuples
446 Chunk
*ptr
= createUserChunk(sizeofTuple
);
449 systemDatabase_
->releaseDatabaseMutex();
450 printError(ErrNoResource
, "Unable to create user chunk");
451 return ErrNoResource
;
453 printDebug(DM_Database
,"Created UserChunk:%x", ptr
);
456 int tblID
= ((Chunk
*)ptr
)->getChunkID();
457 rv
= cTable
.insert(name
, tblID
, sizeofTuple
,
458 def
.getFieldCount(), ptr
, tptr
);
461 deleteUserChunk(ptr
);
462 systemDatabase_
->releaseDatabaseMutex();
463 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
464 return ErrSysInternal
;
466 printDebug(DM_Database
,"Inserted into TABLE:%s",name
);
468 FieldIterator iter
= def
.getFieldIterator();
469 CatalogTableFIELD
cField(systemDatabase_
);
470 rv
= cField
.insert(iter
, tblID
,tptr
);
473 deleteUserChunk(ptr
);
474 void *cptr
, *ttptr
;//Dummy as remove below needs both these OUT params
475 cTable
.remove(name
, cptr
, ttptr
);
476 systemDatabase_
->releaseDatabaseMutex();
477 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
478 return ErrSysInternal
;
480 printDebug(DM_Database
,"Inserted into FIELD:%s",name
);
481 systemDatabase_
->releaseDatabaseMutex();
482 printDebug(DM_Database
,"Table Created:%s",name
);
483 logFinest(logger
, "Table Created %s" , name
);
487 //TODO::If any operation fails in between, then we may have some
488 //dangling tuples, say we have have rows in INDEX table
489 //which will not have any corresponding entries in TABLE
490 //CHANGE the sequence so that it deletes from the bottom as
491 //opposed to start from top as is written now
492 DbRetVal
DatabaseManagerImpl::dropTable(const char *name
)
496 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
498 printError(ErrSysInternal
, "Unable to get database mutex");
499 return ErrSysInternal
;
502 //remove the entry in TABLE
503 CatalogTableTABLE
cTable(systemDatabase_
);
504 rv
= cTable
.getChunkAndTblPtr(name
, chunk
, tptr
);
506 systemDatabase_
->releaseDatabaseMutex();
507 printError(ErrSysInternal
, "Table %s does not exist", name
);
508 return ErrSysInternal
;
510 rv
= lMgr_
->getExclusiveLock(chunk
, NULL
);
513 systemDatabase_
->releaseDatabaseMutex();
514 printError(ErrLockTimeOut
, "Unable to acquire exclusive lock on the table\n");
518 rv
= cTable
.remove(name
, chunk
, tptr
);
520 systemDatabase_
->releaseDatabaseMutex();
521 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
522 return ErrSysInternal
;
524 printDebug(DM_Database
,"Deleted from TABLE:%s",name
);
526 //remove the entries in the FIELD table
527 CatalogTableFIELD
cField(systemDatabase_
);
528 rv
= cField
.remove(tptr
);
530 systemDatabase_
->releaseDatabaseMutex();
531 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
532 return ErrSysInternal
;
534 printDebug(DM_Database
,"Deleted from FIELD:%s",name
);
536 rv
= deleteUserChunk((Chunk
*)chunk
);
538 systemDatabase_
->releaseDatabaseMutex();
539 printError(rv
, "Unable to delete the chunk");
542 printDebug(DM_Database
,"Deleted UserChunk:%x", chunk
);
544 //TODO::check whether indexes are available and drop that also.
545 CatalogTableINDEX
cIndex(systemDatabase_
);
546 int noIndexes
= cIndex
.getNumIndexes(tptr
);
547 for (int i
=1 ; i
<= noIndexes
; i
++) {
548 char *idxName
= cIndex
.getIndexName(tptr
, 1);
549 dropIndexInt(idxName
, false);
551 Chunk
*chunkNode
= systemDatabase_
->getSystemDatabaseChunk(UserChunkTableId
);
552 chunkNode
->free(systemDatabase_
, (Chunk
*) chunk
);
553 systemDatabase_
->releaseDatabaseMutex();
554 printDebug(DM_Database
, "Deleted Table %s" , name
);
555 logFinest(logger
, "Deleted Table %s" , name
);
556 rv
= lMgr_
->releaseLock(chunk
);
559 printError(ErrLockTimeOut
, "Unable to release exclusive lock on the table\n");
565 //Return values: NULL for table not found
566 Table
* DatabaseManagerImpl::openTable(const char *name
)
569 //TODO::store table handles in list so that if it is
570 //not closed by the application. destructor shall close it.
571 TableImpl
*table
= new TableImpl();
573 table
->setSystemDB(systemDatabase_
);
574 table
->setLockManager(lMgr_
);
575 table
->setTrans(ProcessManager::getThreadTransAddr(systemDatabase_
->procSlot
));
577 //to store the chunk pointer of table
580 //to store the tuple pointer of the table
583 //TODO::need to take shared lock on the table so that
584 //all ddl operation will be denied on that table
585 //which includes index creation, alter table
587 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
589 printError(ErrSysInternal
, "Unable to get database mutex");
593 CatalogTableTABLE
cTable(systemDatabase_
);
594 ret
= cTable
.getChunkAndTblPtr(name
, chunk
, tptr
);
597 systemDatabase_
->releaseDatabaseMutex();
599 printError(ErrNotExists
, "Table not exists %s", name
);
602 TABLE
*tTuple
= (TABLE
*)tptr
;
603 table
->setTableInfo(tTuple
->tblName_
, tTuple
->tblID_
, tTuple
->length_
,
604 tTuple
->numFlds_
, tTuple
->numIndexes_
, tTuple
->chunkPtr_
);
605 /*rv = table->lock(true); //take shared lock
608 printError(ErrLockTimeOut, "Unable to acquire shared lock on the table\n");
609 systemDatabase_->releaseDatabaseMutex();
615 if (tTuple
->numFlds_
< 31)
617 table
->isIntUsedForNULL
= true;
618 table
->iNullInfo
= 0;
619 table
->iNotNullInfo
=0;
623 table
->isIntUsedForNULL
= false;
624 int noFields
= os::align(tTuple
->numFlds_
);
625 table
->cNullInfo
= (char*) malloc(noFields
);
626 table
->cNotNullInfo
= (char*) malloc(noFields
);
627 for (int i
=0 ; i
< noFields
; i
++) table
->cNullInfo
[i
] =0;
628 for (int i
=0 ; i
< noFields
; i
++) table
->cNotNullInfo
[i
] =0;
632 //get field information from FIELD table
633 CatalogTableFIELD
cField(systemDatabase_
);
634 cField
.getFieldInfo(tptr
, table
->fldList_
);
636 //populate the notnull info
637 FieldIterator fIter
= table
->fldList_
.getIterator();
639 while (fIter
.hasElement())
641 FieldDef def
= fIter
.nextElement();
642 if (table
->isIntUsedForNULL
) {
643 if (def
.isNull_
) SETBIT(table
->iNotNullInfo
, fldpos
);
646 if (def
.isNull_
) table
->cNotNullInfo
[fldpos
-1] = 1;
651 //get the number of indexes on this table
652 //and populate the indexPtr array
653 CatalogTableINDEX
cIndex(systemDatabase_
);
654 table
->numIndexes_
= cIndex
.getNumIndexes(tptr
);
655 if (table
->numIndexes_
) {
656 table
->indexPtr_
= new char*[table
->numIndexes_
];
657 table
->idxInfo
= new IndexInfo
*[table
->numIndexes_
];
661 table
->indexPtr_
= NULL
;
663 cIndex
.getIndexPtrs(tptr
, table
->indexPtr_
);
664 for (int i
=0 ; i
< table
->numIndexes_
; i
++ )
666 HashIndexInfo
*hIdxInfo
= new HashIndexInfo();
667 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
668 cIndexField
.getFieldInfo(table
->indexPtr_
[i
], hIdxInfo
->idxFldList
);
669 ChunkIterator citer
= CatalogTableINDEX::getIterator(table
->indexPtr_
[i
]);
670 hIdxInfo
->noOfBuckets
= CatalogTableINDEX::getNoOfBuckets(table
->indexPtr_
[i
]);
671 FieldIterator fIter
= hIdxInfo
->idxFldList
.getIterator();
672 bool firstFld
= true;
673 while (fIter
.hasElement())
675 FieldDef def
= fIter
.nextElement();
678 hIdxInfo
->fldOffset
= table
->fldList_
.getFieldOffset(def
.fldName_
);
679 hIdxInfo
->type
= table
->fldList_
.getFieldType(def
.fldName_
);
680 hIdxInfo
->compLength
= table
->fldList_
.getFieldLength(def
.fldName_
);
683 hIdxInfo
->type
= typeComposite
;
684 hIdxInfo
->compLength
= hIdxInfo
->compLength
+
685 table
->fldList_
.getFieldLength(def
.fldName_
);
689 hIdxInfo
->isUnique
= CatalogTableINDEX::getUnique(table
->indexPtr_
[i
]);
690 hIdxInfo
->buckets
= (Bucket
*)citer
.nextElement();
691 table
->idxInfo
[i
] = (IndexInfo
*) hIdxInfo
;
693 systemDatabase_
->releaseDatabaseMutex();
694 // lMgr-> tTuple->chunkPtr_
695 printDebug(DM_Database
,"Opening table handle name:%s chunk:%x numIndex:%d",
696 name
, chunk
, table
->numIndexes_
);
697 logFinest(logger
, "Opening Table %s" , name
);
705 List
DatabaseManagerImpl::getAllTableNames()
708 //to store the tuple pointer of the table
711 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
713 printError(ErrSysInternal
, "Unable to get database mutex");
717 CatalogTableTABLE
cTable(systemDatabase_
);
718 List tableList
= cTable
.getTableList();
719 systemDatabase_
->releaseDatabaseMutex();
726 //Return values: -1 for table not found
727 void DatabaseManagerImpl::closeTable(Table
*table
)
729 printDebug(DM_Database
,"Closing table handle: %x", table
);
730 if (NULL
== table
) return;
733 logFinest(logger
, "Closing Table");
736 DbRetVal
DatabaseManagerImpl::createIndex(const char *indName
, IndexInitInfo
*info
)
739 if (!info
->isUnique
&& info
->isPrimary
)
741 printError(ErrBadCall
, "Primary key cannot be non unique\n");
744 if (info
->indType
== hashIndex
)
746 //Assumes info is of type HashIndexInitInfo
747 HashIndexInitInfo
*hInfo
= (HashIndexInitInfo
*) info
;
748 rv
= createHashIndex(indName
, info
->tableName
, info
->list
, hInfo
->bucketSize
,
749 info
->isUnique
, info
->isPrimary
);
751 else if (info
->indType
== treeIndex
)
754 printError(ErrNotYet
, "Tree Index not supported\n");
757 printError(ErrBadCall
, "Index type not supported\n");
764 //-1 -> Table does not exists
765 //-2 -> Field does not exists
766 //-3 -> bucketSize is not valid
767 DbRetVal
DatabaseManagerImpl::createHashIndex(const char *indName
, const char *tblName
,
768 FieldNameList
&fldList
, int bucketSize
, bool isUnique
, bool isPrimary
)
770 //validate the bucket size
771 if (bucketSize
< 100 || bucketSize
> 200000)
773 printError(ErrBadRange
, "Index Bucket size %d not in range 100-200000",
777 int totFlds
= fldList
.size();
780 printError(ErrBadCall
, "No Field name specified");
785 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
788 printError(ErrSysInternal
, "Unable to get database mutex");
789 return ErrSysInternal
;
792 //check whether table exists
793 CatalogTableTABLE
cTable(systemDatabase_
);
794 cTable
.getChunkAndTblPtr(tblName
, chunk
, tptr
);
797 systemDatabase_
->releaseDatabaseMutex();
798 printError(ErrNotExists
, "Table does not exist %s", tblName
);
802 //check whether field exists
803 char **fptr
= new char* [totFlds
];
804 CatalogTableFIELD
cField(systemDatabase_
);
805 rv
= cField
.getFieldPtrs(fldList
, tptr
, fptr
);
809 systemDatabase_
->releaseDatabaseMutex();
810 //TODO::check test cases of dbapi/Index, they give wrong results
811 //if (rv == ErrBadCall) {
812 //// if (isPrimary) printError(ErrBadCall, "Field can have NULL values");
814 //printError(ErrNotExists, "Field does not exist");
817 if (rv
!= ErrBadCall
) {
818 printError(ErrNotExists
, "Field does not exist");
822 for (int i
=0; i
<totFlds
; i
++)
824 FIELD
* fInfo
= (FIELD
*)fptr
[i
];
825 if (fInfo
->type_
== typeFloat
|| fInfo
->type_
== typeDouble
|| fInfo
->type_
== typeTimeStamp
)
827 printError(ErrBadArg
, "HashIndex cannot be created for float or double or timestamp type");
829 systemDatabase_
->releaseDatabaseMutex();
832 if (!fInfo
->isNull_
&& isPrimary
)
834 printError(ErrBadArg
, "Primary Index cannot be created on field without NOTNULL constraint");
836 systemDatabase_
->releaseDatabaseMutex();
840 //create chunk to store the meta data of the index created
841 //for latches and bucket pointers
842 printDebug(DM_HashIndex
, "Creating chunk for storing hash buckets of size %d\n",
843 bucketSize
* sizeof(Bucket
));
844 Chunk
* chunkInfo
= createUserChunk(bucketSize
* sizeof(Bucket
));
845 if (NULL
== chunkInfo
)
848 systemDatabase_
->releaseDatabaseMutex();
849 printError(ErrSysInternal
, "Unable to create chunk");
850 return ErrSysInternal
;
852 //create memory for holding the bucket pointers
853 void *buckets
= chunkInfo
->allocate(db_
, &rv
);
857 deleteUserChunk(chunkInfo
);
858 systemDatabase_
->releaseDatabaseMutex();
859 printError(rv
, "Unable to allocate memory for bucket");
862 Bucket
*buck
= (Bucket
*) buckets
;
863 initHashBuckets(buck
, bucketSize
);
865 //create chunk to store the hash index nodes
866 Chunk
* hChunk
= createUserChunk(sizeof(HashIndexNode
));
870 deleteUserChunk(chunkInfo
);
871 systemDatabase_
->releaseDatabaseMutex();
872 printError(ErrSysInternal
, "Unable to create chunk for storing hash index nodes");
873 return ErrSysInternal
;
877 void *tupleptr
= NULL
;
878 CatalogTableINDEX
cIndex(systemDatabase_
);
879 rv
= cIndex
.insert(indName
, tptr
, fldList
.size(), isUnique
,
880 chunkInfo
, bucketSize
, hChunk
, tupleptr
);
884 deleteUserChunk(hChunk
);
885 deleteUserChunk(chunkInfo
);
886 systemDatabase_
->releaseDatabaseMutex();
887 printError(ErrSysInternal
, "Catalog table updation failed in INDEX table");
888 return ErrSysInternal
;
890 //add rows to INDEXFIELD
891 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
892 rv
= cIndexField
.insert(fldList
, tupleptr
, tptr
, fptr
);
897 cIndex
.remove(indName
, (void *&)chunkInfo
, (void *&)hChunk
, (void *&)tupleptr
);
898 deleteUserChunk(hChunk
);
899 deleteUserChunk(chunkInfo
);
900 systemDatabase_
->releaseDatabaseMutex();
901 printError(ErrSysInternal
, "Catalog table updation failed in INDEXFIELD table");
902 return ErrSysInternal
;
905 //TODO::If tuples present in this table, then
906 //create hash index nodes and store it
908 systemDatabase_
->releaseDatabaseMutex();
909 printDebug(DM_Database
, "Creating Hash Index Name:%s tblname:%s buckets:%x",
910 indName
, tblName
, buckets
);
911 logFinest(logger
, "Creating HashIndex %s on %s with bucket size %d",
912 indName
, tblName
, buckets
);
916 void DatabaseManagerImpl::initHashBuckets(Bucket
*buck
, int bucketSize
)
918 os::memset((void*)buck
, 0, bucketSize
* sizeof(Bucket
));
920 for (int i
=0; i
< bucketSize
; i
++)
922 buck
[i
].mutex_
.init("Bucket");
927 DbRetVal
DatabaseManagerImpl::dropIndex(const char *name
)
929 return dropIndexInt(name
, true);
932 DbRetVal
DatabaseManagerImpl::dropIndexInt(const char *name
, bool takeLock
)
935 void *chunk
= NULL
, *hchunk
= NULL
;
939 rv
= systemDatabase_
->getDatabaseMutex();
942 printError(ErrSysInternal
, "Unable to get database mutex");
943 return ErrSysInternal
;
947 //remove the entry in INDEX
948 CatalogTableINDEX
cIndex(systemDatabase_
);
949 rv
= cIndex
.remove(name
, chunk
, hchunk
, tptr
);
952 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
953 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
954 return ErrSysInternal
;
956 printDebug(DM_Database
, "Removing from INDEX %s",name
);
957 //remove the entries in the INDEXFIELD table
958 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
959 rv
= cIndexField
.remove(tptr
);
962 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
963 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
964 return ErrSysInternal
;
966 printDebug(DM_Database
, "Removing from INDEXFIELD %s",name
);
968 //delete the index chunk
969 rv
= deleteUserChunk((Chunk
*)chunk
);
972 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
973 printError(ErrSysInternal
, "Unable to delete the index chunk");
974 return ErrSysInternal
;
976 //delete the index hash node chunk
977 rv
= deleteUserChunk((Chunk
*)hchunk
);
980 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
981 printError(ErrSysInternal
, "Unable to delete the index hash node chunk");
982 return ErrSysInternal
;
984 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
985 Chunk
*chunkNode
= systemDatabase_
->getSystemDatabaseChunk(UserChunkTableId
);
986 chunkNode
->free(systemDatabase_
, (Chunk
*) chunk
);
987 chunkNode
->free(systemDatabase_
, (Chunk
*) hchunk
);
989 //TODO::If tuples present in this table, then
990 //free all hash index nodes for this table.
991 //free all nodes in list of all buckets
994 printDebug(DM_Database
, "Dropped hash index %s",name
);
995 logFinest(logger
, "Deleted Index %s", name
);
998 DbRetVal
DatabaseManagerImpl::printIndexInfo(char *name
)
1000 CatalogTableINDEX
cIndex(systemDatabase_
);
1002 void *chunk
= NULL
, *hchunk
= NULL
;
1004 rv
= cIndex
.get(name
, chunk
, hchunk
, tptr
);
1005 if (OK
!= rv
) return rv
;
1006 printf("<IndexName> %s </IndexName>\n", name
);
1007 printf("<Unique> %d </Unique>\n", CatalogTableINDEX::getUnique(tptr
));
1008 Chunk
*ch
= (Chunk
*) chunk
;
1009 printf("<HashBucket>\n");
1010 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1011 printf(" <TotalBuckets> %d </TotalBuckets> \n", CatalogTableINDEX::getNoOfBuckets(tptr
));
1012 printf("</HashBucket>\n");
1014 ch
= (Chunk
*) hchunk
;
1015 printf("<IndexNodes>\n");
1016 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1017 printf(" <TotalNodes> %d </TotalNodes>\n", ch
->getTotalDataNodes());
1018 printf("<IndexNodes>\n");
1022 DbRetVal
DatabaseManagerImpl::registerThread()
1027 printError(ErrAlready
, "Process already registered\n");
1030 pMgr_
= new ProcessManager();
1031 rv
= pMgr_
->registerThread();
1032 if (rv
==OK
) { procSlot
= pMgr_
->getProcSlot();
1033 printDebug(DM_Process
, "Process registed with slot %d\n", procSlot
);
1038 DbRetVal
DatabaseManagerImpl::deregisterThread()
1043 rv
= pMgr_
->deregisterThread(procSlot
);
1050 bool DatabaseManagerImpl::isAnyOneRegistered()
1052 if (pMgr_
!= NULL
) return pMgr_
->isAnyOneRegistered();
1057 void DatabaseManagerImpl::printUsageStatistics()
1059 pMgr_
->printUsageStatistics();
1060 tMgr_
->printUsageStatistics();
1061 lMgr_
->printUsageStatistics();
1064 void DatabaseManagerImpl::printDebugLockInfo()
1066 lMgr_
->printDebugInfo();
1069 void DatabaseManagerImpl::printDebugTransInfo()
1071 tMgr_
->printDebugInfo(systemDatabase_
);
1073 void DatabaseManagerImpl::printDebugProcInfo()
1075 pMgr_
->printDebugInfo();
1077 void DatabaseManagerImpl::printDebugChunkInfo()
1079 printf("<NotYetImplemented> </NotYetImplemented>\n");
1081 ChunkIterator
DatabaseManagerImpl::getSystemTableIterator(CatalogTableID id
)
1083 Chunk
*fChunk
= systemDatabase_
->getSystemDatabaseChunk(id
);
1084 return fChunk
->getIterator();
1087 Chunk
* DatabaseManagerImpl::getSystemTableChunk(CatalogTableID id
)
1089 return systemDatabase_
->getSystemDatabaseChunk(id
);