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));
52 DbRetVal
DatabaseManagerImpl::openSystemDatabase()
54 DbRetVal rv
= openDatabase(SYSTEMDB
);
55 if (rv
!= OK
) return rv
;
56 systemDatabase_
= db_
;
58 if (NULL
== systemDatabase_
)
60 printError(ErrAlready
, "Database is already opened");
63 printDebug(DM_Database
, "Opened system database");
64 logFinest(logger
, "Opened system database");
68 DbRetVal
DatabaseManagerImpl::closeSystemDatabase()
71 //make them to point to system database file descriptor
72 //and database pointer
73 db_
= systemDatabase_
;
76 printDebug(DM_Database
, "Closed system database");
77 logFinest(logger
, "Closed System database");
81 DbRetVal
DatabaseManagerImpl::createDatabase(const char *name
, size_t size
)
85 printError(ErrAlready
, "Database is already created");
88 caddr_t rtnAddr
= (caddr_t
) NULL
;
89 shared_memory_id shm_id
= 0;
91 char *startaddr
= (char*)Conf::config
.getMapAddress();
92 shared_memory_key key
= 0;
93 if (0 == strcmp(name
, SYSTEMDB
))
96 key
= Conf::config
.getSysDbKey();
100 startaddr
= startaddr
+ Conf::config
.getMaxSysDbSize();
101 key
= Conf::config
.getUserDbKey();
103 shm_id
= os::shm_create(key
, size
, 0666);
106 printError(ErrOS
, "Shared memory create failed");
110 void *shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
111 rtnAddr
= (caddr_t
) shm_ptr
;
112 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
114 printError(ErrOS
, "Shared memory attach returned -ve value %d", rtnAddr
);
117 memset(shm_ptr
, 0, size
);
118 db_
= new Database();
119 printDebug(DM_Database
, "Creating database:%s",name
);
121 //TODO:for user database do not have transtable and processtable mutex
122 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
123 db_
->setDatabaseID(1);
125 db_
->setMaxSize(size
);
126 db_
->setMaxChunks(MAX_CHUNKS
);
127 db_
->initAllocDatabaseMutex();
128 db_
->initTransTableMutex();
129 db_
->initDatabaseMutex();
130 db_
->initProcessTableMutex();
132 //compute the first page after book keeping information
133 size_t offset
= os::alignLong(sizeof (DatabaseMetaData
));
134 //Only for system db chunk array, trans array and proc array will be there
135 if (0 == strcmp(name
, SYSTEMDB
))
137 offset
= offset
+ os::alignLong( MAX_CHUNKS
* sizeof (Chunk
));
138 offset
= offset
+ os::alignLong( Conf::config
.getMaxTrans() * sizeof(Transaction
));
139 offset
= offset
+ os::alignLong( Conf::config
.getMaxProcs() * sizeof(ThreadInfo
));
141 int multiple
= os::floor(offset
/ PAGE_SIZE
);
142 char *curPage
= (((char*)rtnAddr
) + ((multiple
+ 1) * PAGE_SIZE
));
144 db_
->setCurrentPage(curPage
);
145 db_
->setFirstPage(curPage
);
147 if (0 == strcmp(name
, SYSTEMDB
)) return OK
;
149 //Allocate new chunk to store hash index nodes
150 Chunk
*chunkInfo
= createUserChunk(sizeof(HashIndexNode
));
151 if (NULL
== chunkInfo
)
153 printError(ErrSysInternal
, "Failed to allocate hash index nodes chunk");
154 return ErrSysInternal
;
156 printDebug(DM_Database
, "Creating Chunk for storing Hash index nodes %x",
159 db_
->setHashIndexChunk(chunkInfo
);
160 logFinest(logger
, "Created database %s" , name
);
165 DbRetVal
DatabaseManagerImpl::deleteDatabase(const char *name
)
167 shared_memory_id shm_id
= 0;
168 if (0 == strcmp(name
, SYSTEMDB
))
170 shm_id
= os::shm_open(Conf::config
.getSysDbKey(), 100, 0666);
171 os::shmctl(shm_id
, IPC_RMID
);
173 shm_id
= os::shm_open(Conf::config
.getUserDbKey(), 100, 0666);
174 os::shmctl(shm_id
, IPC_RMID
);
176 logFinest(logger
, "Deleted database %s" , name
);
180 DbRetVal
DatabaseManagerImpl::openDatabase(const char *name
)
182 long size
= Conf::config
.getMaxSysDbSize();
183 char *startaddr
= (char*)Conf::config
.getMapAddress();
184 if (0 == strcmp(name
, SYSTEMDB
))
186 if (NULL
!=systemDatabase_
)
188 printError(ErrAlready
, "System Database already open");
194 if (NULL
==systemDatabase_
)
196 printError(ErrNotOpen
, "System Database not open");
199 size
= Conf::config
.getMaxDbSize();
200 startaddr
= startaddr
+ Conf::config
.getMaxSysDbSize();
204 printError(ErrAlready
, "User Database already open");
207 //system db should be opened before user database files
208 caddr_t rtnAddr
= (caddr_t
) NULL
;
210 shared_memory_id shm_id
= 0;
211 shared_memory_key key
= 0;
213 if (0 == strcmp(name
, SYSTEMDB
))
214 key
= Conf::config
.getSysDbKey();
216 key
= Conf::config
.getUserDbKey();
219 int ret
= ProcessManager::mutex
.getLock(false);
220 //If you are not getting lock ret !=0, it means somebody else is there.
221 //he will close the database.
224 printError(ErrSysInternal
, "Another thread calling open:Wait and then Retry\n");
225 return ErrSysInternal
;
227 void *shm_ptr
= NULL
;
228 bool firstThread
= false;
229 //printf("PRABA::DEBUG:: opendb %d %s\n", ProcessManager::noThreads, name);
230 if (ProcessManager::noThreads
== 0 && 0 == strcmp(name
, SYSTEMDB
)
231 || ProcessManager::noThreads
== 1 && 0 != strcmp(name
, SYSTEMDB
) ) {
232 shm_id
= os::shm_open(key
, size
, 0666);
235 printError(ErrOS
, "Shared memory open failed");
236 ProcessManager::mutex
.releaseLock(false);
239 shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
240 if (0 == strcmp(name
, SYSTEMDB
))
243 ProcessManager::sysAddr
= (char*) shm_ptr
;
247 ProcessManager::usrAddr
= (char*) shm_ptr
;
250 if (0 == strcmp(name
, SYSTEMDB
))
251 shm_ptr
= ProcessManager::sysAddr
;
253 shm_ptr
= ProcessManager::usrAddr
;
255 ProcessManager::mutex
.releaseLock(false);
258 rtnAddr
= (caddr_t
) shm_ptr
;
260 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
262 printError(ErrOS
, "Shared memory attach returned -ve value %x %d", shm_ptr
, errno
);
265 db_
= new Database();
266 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
268 if (firstThread
) ProcessManager::systemDatabase
= db_
;
270 printDebug(DM_Database
, "Opening database: %s", name
);
271 logFinest(logger
, "Opened database %s" , name
);
275 DbRetVal
DatabaseManagerImpl::closeDatabase()
280 //Database is already closed
283 printDebug(DM_Database
, "Closing database: %s",(char*)db_
->getName());
284 //check if this is the last thread to be deregistered
285 int ret
= ProcessManager::mutex
.getLock(false);
286 //If you are not getting lock ret !=0, it means somebody else is there.
287 //he will close the database.
289 //printf("PRABA::FOR DEBUG closedb %d %s\n", ProcessManager::noThreads, (char*)db_->getName());
290 if (ProcessManager::noThreads
== 0 && 0 == strcmp((char*)db_
->getName(), SYSTEMDB
)
291 || ProcessManager::noThreads
== 1 && 0 != strcmp((char*)db_
->getName(), SYSTEMDB
) ) {
292 os::shm_detach((char*)db_
->getMetaDataPtr());
295 ProcessManager::mutex
.releaseLock(false);
296 logFinest(logger
, "Closed database");
301 //Assumes that system database mutex is taken before calling this.
302 Chunk
* DatabaseManagerImpl::createUserChunk(size_t size
)
304 //Allocate new node in system database to store
305 Chunk
*chunk
= getSystemTableChunk(UserChunkTableId
);
306 void *ptr
= chunk
->allocate(systemDatabase_
);
309 printError(ErrNoMemory
, "Allocation failed for User chunk catalog table");
312 Chunk
*chunkInfo
= (Chunk
*)ptr
;
313 chunkInfo
->initMutex();
314 if (0 != size
) chunkInfo
->setSize(size
);
315 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
316 chunkInfo
->curPage_
= db_
->getFreePage(chunkInfo
->allocSize_
);
318 chunkInfo
->curPage_
= db_
->getFreePage();
319 if ( NULL
== chunkInfo
->curPage_
)
321 chunkInfo
->destroyMutex();
322 chunk
->free(db_
, ptr
);
323 printError(ErrNoMemory
, "Database full: No space to allocate from database");
326 PageInfo
* firstPageInfo
= ((PageInfo
*)chunkInfo
->curPage_
);
327 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
329 int multiple
= os::floor(chunkInfo
->allocSize_
/ PAGE_SIZE
);
330 int offset
= ((multiple
+ 1) * PAGE_SIZE
);
331 firstPageInfo
->setPageAsUsed(offset
);
334 firstPageInfo
->setPageAsUsed(chunkInfo
->allocSize_
);
337 VarSizeInfo
*varInfo
= (VarSizeInfo
*)(((char*)firstPageInfo
) + sizeof(PageInfo
));
338 varInfo
->isUsed_
= 0;
339 varInfo
->size_
= PAGE_SIZE
- sizeof(PageInfo
) - sizeof(VarSizeInfo
);
342 chunkInfo
->firstPage_
= chunkInfo
->curPage_
;
345 chunkInfo
->setAllocType(VariableSizeAllocator
);
347 chunkInfo
->setAllocType(FixedSizeAllocator
);
349 //TODO::Generate chunkid::use tableid
350 chunkInfo
->setChunkID(-1);
351 printDebug(DM_Database
, "Creating new User chunk chunkID:%d size: %d firstPage:%x",
352 -1, chunkInfo
->allocSize_
, firstPageInfo
);
358 //Assumes that system database mutex is taken before calling this.
359 DbRetVal
DatabaseManagerImpl::deleteUserChunk(Chunk
*chunk
)
361 //Go to the pages and set them to notUsed
362 Page
*page
= chunk
->firstPage_
;
363 PageInfo
* pageInfo
= ((PageInfo
*)page
);
364 //Here...sure that atleast one page will be there even no tuples
365 //are inserted.so not checking if pageInfo == NULL
366 while( pageInfo
->nextPage_
!= NULL
)
368 PageInfo
*prev
= pageInfo
;
369 pageInfo
= (PageInfo
*)(pageInfo
->nextPage_
);
370 //sets pageInfo->isUsed_ = 0 and pageInfo->hasFreeSpace_ = 0
371 //and initializes the page content to zero
372 if(NULL
== pageInfo
->nextPageAfterMerge_
)
373 os::memset(prev
, 0, PAGE_SIZE
);
376 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
377 os::memset(prev
, 0, size
);
379 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, prev
);
381 //The above loop wont execute for the last page
382 //and for the case where table has only one page
383 if(NULL
== pageInfo
->nextPageAfterMerge_
)
384 os::memset(pageInfo
, 0, PAGE_SIZE
);
387 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
388 os::memset(pageInfo
, 0, size
);
390 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, pageInfo
);
391 chunk
->chunkID_
= -1;
392 chunk
->allocSize_
= 0;
393 chunk
->curPage_
= NULL
;
394 chunk
->firstPage_
= NULL
;
395 chunk
->destroyMutex();
396 printDebug(DM_Database
,"deleting user chunk:%x",chunk
);
400 //-1 -> Unable to create chunk. No memory
401 //-2 -> Unable to update the catalog tables
402 DbRetVal
DatabaseManagerImpl::createTable(const char *name
, TableDef
&def
)
405 int fldCount
= def
.getFieldCount();
406 //If total field count is less than 32, then 1 integer is used to store all null
407 //information, if it is more then 1 char is used to store null information
409 //This is to done to reduce cpu cycles for small tables
411 if (fldCount
> 31) addSize
= 4; else addSize
= os::align(fldCount
);
412 size_t sizeofTuple
= os::align(def
.getTupleSize())+addSize
;
413 rv
= systemDatabase_
->getDatabaseMutex();
415 printError(rv
, "Unable to get Database mutex");
422 //check whether table already exists
423 CatalogTableTABLE
cTable(systemDatabase_
);
424 cTable
.getChunkAndTblPtr(name
, chunk
, tptr
);
427 systemDatabase_
->releaseDatabaseMutex();
428 printError(ErrAlready
, "Table %s already exists", name
);
432 //create a chunk to store the tuples
433 Chunk
*ptr
= createUserChunk(sizeofTuple
);
436 systemDatabase_
->releaseDatabaseMutex();
437 printError(ErrNoResource
, "Unable to create user chunk");
438 return ErrNoResource
;
440 printDebug(DM_Database
,"Created UserChunk:%x", ptr
);
443 int tblID
= ((Chunk
*)ptr
)->getChunkID();
444 rv
= cTable
.insert(name
, tblID
, sizeofTuple
,
445 def
.getFieldCount(), ptr
, tptr
);
448 deleteUserChunk(ptr
);
449 systemDatabase_
->releaseDatabaseMutex();
450 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
451 return ErrSysInternal
;
453 printDebug(DM_Database
,"Inserted into TABLE:%s",name
);
455 FieldIterator iter
= def
.getFieldIterator();
456 CatalogTableFIELD
cField(systemDatabase_
);
457 rv
= cField
.insert(iter
, tblID
,tptr
);
460 deleteUserChunk(ptr
);
461 void *cptr
, *ttptr
;//Dummy as remove below needs both these OUT params
462 cTable
.remove(name
, cptr
, ttptr
);
463 systemDatabase_
->releaseDatabaseMutex();
464 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
465 return ErrSysInternal
;
467 printDebug(DM_Database
,"Inserted into FIELD:%s",name
);
468 systemDatabase_
->releaseDatabaseMutex();
469 printDebug(DM_Database
,"Table Created:%s",name
);
470 logFinest(logger
, "Table Created %s" , name
);
474 //TODO::If any operation fails in between, then we may have some
475 //dangling tuples, say we have have rows in INDEX table
476 //which will not have any corresponding entries in TABLE
477 //CHANGE the sequence so that it deletes from the bottom as
478 //opposed to start from top as is written now
479 DbRetVal
DatabaseManagerImpl::dropTable(const char *name
)
483 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
485 printError(ErrSysInternal
, "Unable to get database mutex");
486 return ErrSysInternal
;
489 //remove the entry in TABLE
490 CatalogTableTABLE
cTable(systemDatabase_
);
491 rv
= cTable
.remove(name
, chunk
, tptr
);
493 systemDatabase_
->releaseDatabaseMutex();
494 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
495 return ErrSysInternal
;
497 printDebug(DM_Database
,"Deleted from TABLE:%s",name
);
499 //remove the entries in the FIELD table
500 CatalogTableFIELD
cField(systemDatabase_
);
501 rv
= cField
.remove(tptr
);
503 systemDatabase_
->releaseDatabaseMutex();
504 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
505 return ErrSysInternal
;
507 printDebug(DM_Database
,"Deleted from FIELD:%s",name
);
509 rv
= deleteUserChunk((Chunk
*)chunk
);
511 systemDatabase_
->releaseDatabaseMutex();
512 printError(rv
, "Unable to delete the chunk");
515 printDebug(DM_Database
,"Deleted UserChunk:%x", chunk
);
517 //TODO::check whether indexes are available and drop that also.
518 CatalogTableINDEX
cIndex(systemDatabase_
);
519 int noIndexes
= cIndex
.getNumIndexes(tptr
);
521 for (int i
=1 ; i
<= noIndexes
; i
++) {
522 idxName
= cIndex
.getIndexName(tptr
, i
);
523 dropIndexInt(idxName
, false);
525 Chunk
*chunkNode
= systemDatabase_
->getSystemDatabaseChunk(UserChunkTableId
);
526 chunkNode
->free(systemDatabase_
, (Chunk
*) chunk
);
527 systemDatabase_
->releaseDatabaseMutex();
528 printDebug(DM_Database
, "Deleted Table %s" , name
);
529 logFinest(logger
, "Deleted Table %s" , name
);
533 //Return values: NULL for table not found
534 Table
* DatabaseManagerImpl::openTable(const char *name
)
537 //TODO::store table handles in list so that if it is
538 //not closed by the application. destructor shall close it.
539 TableImpl
*table
= new TableImpl();
541 table
->setSystemDB(systemDatabase_
);
542 table
->setLockManager(lMgr_
);
543 table
->setTrans(&(tMgr_
->trans
));
545 //to store the chunk pointer of table
548 //to store the tuple pointer of the table
551 //TODO::need to take shared lock on the table so that
552 //all ddl operation will be denied on that table
553 //which includes index creation, alter table
555 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
557 printError(ErrSysInternal
, "Unable to get database mutex");
560 CatalogTableTABLE
cTable(systemDatabase_
);
561 ret
= cTable
.getChunkAndTblPtr(name
, chunk
, tptr
);
564 printError(ErrNotExists
, "Table not exists %s", name
);
567 TABLE
*tTuple
= (TABLE
*)tptr
;
568 table
->setTableInfo(tTuple
->tblName_
, tTuple
->tblID_
, tTuple
->length_
,
569 tTuple
->numFlds_
, tTuple
->numIndexes_
, tTuple
->chunkPtr_
);
571 //get field information from FIELD table
572 CatalogTableFIELD
cField(systemDatabase_
);
573 cField
.getFieldInfo(tptr
, table
->fldList_
);
575 //get the number of indexes on this table
576 //and populate the indexPtr array
577 CatalogTableINDEX
cIndex(systemDatabase_
);
578 table
->numIndexes_
= cIndex
.getNumIndexes(tptr
);
579 if (table
->numIndexes_
)
580 table
->indexPtr_
= new char*[table
->numIndexes_
];
582 table
->indexPtr_
= NULL
;
583 cIndex
.getIndexPtrs(tptr
, table
->indexPtr_
);
585 //HACK:Below works only for one hash index on table
586 if (table
->numIndexes_
== 1)
588 SingleFieldHashIndexInfo
*hIdxInfo
= new SingleFieldHashIndexInfo();
589 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
590 cIndexField
.getFieldNameAndType(table
->indexPtr_
[0], hIdxInfo
->fldName
,
592 ChunkIterator citer
= CatalogTableINDEX::getIterator(table
->indexPtr_
[0]);
593 hIdxInfo
->noOfBuckets
= CatalogTableINDEX::getNoOfBuckets(table
->indexPtr_
[0]);
594 hIdxInfo
->isUnique
= CatalogTableINDEX::getUnique(table
->indexPtr_
[0]);
595 hIdxInfo
->buckets
= (Bucket
*)citer
.nextElement();
597 table
->idxInfo
= (IndexInfo
*) hIdxInfo
;
599 systemDatabase_
->releaseDatabaseMutex();
600 if (tTuple
->numFlds_
> 31)
602 table
->isIntUsedForNULL
= true;
603 table
->iNullInfo
= 0;
607 table
->isIntUsedForNULL
= false;
608 int noFields
= os::align(tTuple
->numFlds_
);
609 table
->cNullInfo
= (char*) malloc(noFields
);
610 for (int i
=0 ; i
< noFields
; i
++) table
->cNullInfo
[i
] =0;
612 printDebug(DM_Database
,"Opening table handle name:%s chunk:%x numIndex:%d",
613 name
, chunk
, table
->numIndexes_
);
614 logFinest(logger
, "Opening Table %s" , name
);
621 List
DatabaseManagerImpl::getAllTableNames()
624 //to store the tuple pointer of the table
627 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
629 printError(ErrSysInternal
, "Unable to get database mutex");
633 CatalogTableTABLE
cTable(systemDatabase_
);
634 List tableList
= cTable
.getTableList();
635 systemDatabase_
->releaseDatabaseMutex();
642 //Return values: -1 for table not found
643 void DatabaseManagerImpl::closeTable(Table
*table
)
645 printDebug(DM_Database
,"Closing table handle: %x", table
);
646 if (NULL
== table
) return;
648 logFinest(logger
, "Closing Table");
651 DbRetVal
DatabaseManagerImpl::createIndex(const char *indName
, IndexInitInfo
*info
)
654 if (info
->indType
== hashIndex
)
656 //Assumes info is of type HashIndexInitInfo
657 HashIndexInitInfo
*hInfo
= (HashIndexInitInfo
*) info
;
658 rv
= createHashIndex(indName
, info
->tableName
, info
->list
, hInfo
->bucketSize
,
669 //-1 -> Table does not exists
670 //-2 -> Field does not exists
671 //-3 -> bucketSize is not valid
672 DbRetVal
DatabaseManagerImpl::createHashIndex(const char *indName
, const char *tblName
,
673 FieldNameList
&fldList
, int bucketSize
, bool isUnique
)
675 //validate the bucket size
676 if (bucketSize
< 100 || bucketSize
> 200000)
678 printError(ErrBadRange
, "Index Bucket size %d not in range 100-200000",
684 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
687 printError(ErrSysInternal
, "Unable to get database mutex");
688 return ErrSysInternal
;
691 //check whether table exists
692 CatalogTableTABLE
cTable(systemDatabase_
);
693 cTable
.getChunkAndTblPtr(tblName
, chunk
, tptr
);
696 systemDatabase_
->releaseDatabaseMutex();
697 printError(ErrNotExists
, "Table does not exist %s", tblName
);
700 int totFlds
= fldList
.size();
702 //check whether field exists
703 char **fptr
= new char* [totFlds
];
704 CatalogTableFIELD
cField(systemDatabase_
);
705 rv
= cField
.getFieldPtrs(fldList
, tptr
, fptr
);
709 systemDatabase_
->releaseDatabaseMutex();
710 printError(ErrNotExists
, "Field does not exist");
714 //create chunk to store the meta data of the index created
715 //for latches and bucket pointers
716 Chunk
* chunkInfo
= createUserChunk(bucketSize
* sizeof(Bucket
));
717 if (NULL
== chunkInfo
)
720 systemDatabase_
->releaseDatabaseMutex();
721 printError(ErrSysInternal
, "Unable to create chunk");
722 return ErrSysInternal
;
724 //create memory for holding the bucket pointers
725 void *buckets
= chunkInfo
->allocate(db_
);
729 deleteUserChunk(chunkInfo
);
730 systemDatabase_
->releaseDatabaseMutex();
731 printError(ErrNoMemory
, "Unable to allocate memory for bucket");
734 Bucket
*buck
= (Bucket
*) buckets
;
735 initHashBuckets(buck
, bucketSize
);
737 //create chunk to store the hash index nodes
738 Chunk
* hChunk
= createUserChunk(sizeof(HashIndexNode
));
742 deleteUserChunk(chunkInfo
);
743 systemDatabase_
->releaseDatabaseMutex();
744 printError(ErrSysInternal
, "Unable to create chunk for storing hash index nodes");
745 return ErrSysInternal
;
750 void *tupleptr
= NULL
;
751 CatalogTableINDEX
cIndex(systemDatabase_
);
752 DbRetVal ret
= cIndex
.insert(indName
, tptr
, fldList
.size(), isUnique
,
753 chunkInfo
, bucketSize
, hChunk
, tupleptr
);
757 deleteUserChunk(hChunk
);
758 deleteUserChunk(chunkInfo
);
759 systemDatabase_
->releaseDatabaseMutex();
760 printError(ErrSysInternal
, "Catalog table updation failed in INDEX table");
761 return ErrSysInternal
;
763 //add rows to INDEXFIELD
764 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
765 ret
= cIndexField
.insert(fldList
, tupleptr
, tptr
, fptr
);
770 deleteUserChunk(hChunk
);
771 deleteUserChunk(chunkInfo
);
772 systemDatabase_
->releaseDatabaseMutex();
773 printError(ErrSysInternal
, "Catalog table updation failed in INDEXFIELD table");
774 return ErrSysInternal
;
777 //TODO::If tuples present in this table, then
778 //create hash index nodes and store it
780 systemDatabase_
->releaseDatabaseMutex();
781 printDebug(DM_Database
, "Creating Hash Index Name:%s tblname:%s buckets:%x",
782 indName
, tblName
, buckets
);
783 logFinest(logger
, "Creating HashIndex %s on %s with bucket size %d",
784 indName
, tblName
, buckets
);
788 void DatabaseManagerImpl::initHashBuckets(Bucket
*buck
, int bucketSize
)
790 os::memset((void*)buck
, 0, bucketSize
* sizeof(Bucket
));
792 for (int i
=0; i
< bucketSize
; i
++)
794 buck
[i
].mutex_
.init("Bucket");
799 DbRetVal
DatabaseManagerImpl::dropIndex(const char *name
)
801 return dropIndexInt(name
, true);
804 DbRetVal
DatabaseManagerImpl::dropIndexInt(const char *name
, bool takeLock
)
807 void *chunk
= NULL
, *hchunk
= NULL
;
811 rv
= systemDatabase_
->getDatabaseMutex();
814 printError(ErrSysInternal
, "Unable to get database mutex");
815 return ErrSysInternal
;
819 //remove the entry in INDEX
820 CatalogTableINDEX
cIndex(systemDatabase_
);
821 rv
= cIndex
.remove(name
, chunk
, hchunk
, tptr
);
824 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
825 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
826 return ErrSysInternal
;
828 printDebug(DM_Database
, "Removing from INDEX %s",name
);
829 //remove the entries in the INDEXFIELD table
830 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
831 rv
= cIndexField
.remove(tptr
);
834 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
835 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
836 return ErrSysInternal
;
838 printDebug(DM_Database
, "Removing from INDEXFIELD %s",name
);
840 //delete the index chunk
841 rv
= deleteUserChunk((Chunk
*)chunk
);
844 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
845 printError(ErrSysInternal
, "Unable to delete the index chunk");
846 return ErrSysInternal
;
848 //delete the index hash node chunk
849 rv
= deleteUserChunk((Chunk
*)hchunk
);
852 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
853 printError(ErrSysInternal
, "Unable to delete the index hash node chunk");
854 return ErrSysInternal
;
856 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
857 Chunk
*chunkNode
= systemDatabase_
->getSystemDatabaseChunk(UserChunkTableId
);
858 chunkNode
->free(systemDatabase_
, (Chunk
*) chunk
);
859 chunkNode
->free(systemDatabase_
, (Chunk
*) hchunk
);
861 //TODO::If tuples present in this table, then
862 //free all hash index nodes for this table.
863 //free all nodes in list of all buckets
866 printDebug(DM_Database
, "Dropped hash index %s",name
);
867 logFinest(logger
, "Deleted Index %s", name
);
871 DbRetVal
DatabaseManagerImpl::registerThread()
876 printError(ErrAlready
, "Process already registered\n");
879 pMgr_
= new ProcessManager();
880 return pMgr_
->registerThread();
883 DbRetVal
DatabaseManagerImpl::deregisterThread()
888 rv
= pMgr_
->deregisterThread();
895 ChunkIterator
DatabaseManagerImpl::getSystemTableIterator(CatalogTableID id
)
897 Chunk
*fChunk
= systemDatabase_
->getSystemDatabaseChunk(id
);
898 return fChunk
->getIterator();
901 Chunk
* DatabaseManagerImpl::getSystemTableChunk(CatalogTableID id
)
903 return systemDatabase_
->getSystemDatabaseChunk(id
);