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>
28 #include<TableConfig.h>
32 DatabaseManagerImpl::~DatabaseManagerImpl()
34 //Note:Databases are closed by the session interface
36 ListIterator iter
= tableHandleList
.getIterator();
37 //PRABA::commented below...gives core dump
38 //while ((tbl = (Table *)iter.nextElement()) != NULL) delete tbl;
39 tableHandleList
.reset();
44 void DatabaseManagerImpl::createLockManager()
46 lMgr_
= new LockManager(systemDatabase_
);
50 void DatabaseManagerImpl::createTransactionManager()
53 tMgr_
= new TransactionManager();
54 tMgr_
->setFirstTrans(systemDatabase_
->getSystemDatabaseTrans(0));
57 void DatabaseManagerImpl::setProcSlot()
59 systemDatabase_
->setProcSlot(procSlot
);
60 db_
->setProcSlot(procSlot
);
62 DbRetVal
DatabaseManagerImpl::openSystemDatabase()
64 DbRetVal rv
= openDatabase(SYSTEMDB
);
65 if (rv
!= OK
) return rv
;
66 systemDatabase_
= db_
;
68 printDebug(DM_Database
, "Opened system database");
72 DbRetVal
DatabaseManagerImpl::closeSystemDatabase()
75 //make them to point to system database file descriptor
76 //and database pointer
77 db_
= systemDatabase_
;
80 printDebug(DM_Database
, "Closed system database");
84 DbRetVal
DatabaseManagerImpl::createDatabase(const char *name
, size_t size
)
86 bool isMmapNeeded
= Conf::config
.useMmap();
88 if (isMmapNeeded && !Conf::config.useDurability()) {
89 printError(ErrBadArg, "If MMAP is set to true. Durability must be true.");
97 long fixAddr
= 399998976L;
98 bool firstTimeServer
= false;
101 printError(ErrAlready
, "Database is already created");
104 caddr_t rtnAddr
= (caddr_t
) NULL
;
105 void *mapAddr
= NULL
;
106 shared_memory_id shm_id
= 0;
108 char *startaddr
= (char*)Conf::config
.getMapAddress();
109 shared_memory_key key
= 0;
110 if (0 == strcmp(name
, SYSTEMDB
))
113 key
= Conf::config
.getSysDbKey();
117 startaddr
= startaddr
+ Conf::config
.getMaxSysDbSize();
118 key
= Conf::config
.getUserDbKey();
120 if (!isMmapNeeded
|| isMmapNeeded
&& 0 == strcmp(name
, SYSTEMDB
)) {
121 shm_id
= os::shm_create(key
, size
, 0660);
124 printError(ErrOS
, "Shared Memory already exists");
125 printError(ErrOS
, "Shared memory create failed");
126 shm_id
= os::shm_open(Conf::config
.getSysDbKey(), 100, 0660);
127 os::shmctl(shm_id
, IPC_RMID
);
128 delete systemDatabase_
;
129 systemDatabase_
= NULL
;
133 sprintf(dbMapFile
, "%s/db.chkpt.data1", Conf::config
.getDbFile());
134 if (FILE *file
= fopen(dbMapFile
, "r")) {
136 sprintf(cmd
, "cp %s %s/db.chkpt.data", dbMapFile
, Conf::config
.getDbFile());
137 int ret
= system(cmd
);
139 printError(ErrOS
, "could not copy data file to map file");
143 sprintf(dbMapFile
, "%s/db.chkpt.data", Conf::config
.getDbFile());
144 fd
= open(dbMapFile
, O_CREAT
| O_RDWR
, 0660);
146 printError(ErrOS
, "Mmap file could not be opened");
149 if(fstat(fd
, &st
) == -1) {
150 printf("Unable to retrieve the db File data\n");
155 if (st
.st_size
== 0) {
156 firstTimeServer
= true;
157 off_t flSize
= lseek(fd
, size
- 1, SEEK_SET
);
160 int wSize
= write(fd
, a
, 1);
161 mapAddr
= os::mmap((void *)(fixAddr
+ Conf::config
.getMaxSysDbSize()), size
, PROT_READ
| PROT_WRITE
, MAP_FIXED
| MAP_SHARED
, fd
, 0);
162 rtnAddr
= (caddr_t
) mapAddr
;
163 printDebug(DM_Database
, "Mapped db file address = %x", mapAddr
);
165 void *shm_ptr
= NULL
;
166 if (!isMmapNeeded
|| isMmapNeeded
&& 0 == strcmp(name
, SYSTEMDB
)) {
167 shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
168 rtnAddr
= (caddr_t
) shm_ptr
;
169 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
171 printError(ErrOS
, "Shared memory attach returned -ve value %d", rtnAddr
);
175 db_
= new Database();
176 printDebug(DM_Database
, "Creating database:%s",name
);
178 /*if (!isMmapNeeded || isMmapNeeded && 0 == strcmp(name, SYSTEMDB)) {
179 memset(shm_ptr, 0, size );
182 //TODO:for user database do not have transtable and processtable mutex
183 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
184 db_
->setDatabaseID(1);
186 db_
->setMaxSize(size
);
187 db_
->setNoOfChunks(0);
188 db_
->initAllocDatabaseMutex();
189 db_
->initTransTableMutex();
190 db_
->initDatabaseMutex();
191 db_
->initProcessTableMutex();
192 db_
->initPrepareStmtMutex();
193 db_
->setUniqueChunkID(100);
194 //compute the first page after book keeping information
195 size_t offset
= os::alignLong(sizeof (DatabaseMetaData
));
196 //Only for system db chunk array, trans array and proc array will be there
197 if (0 == strcmp(name
, SYSTEMDB
))
199 offset
= offset
+ os::alignLong( MAX_CHUNKS
* sizeof (Chunk
));
200 offset
= offset
+ os::alignLong( Conf::config
.getMaxProcs() * sizeof(Transaction
));
201 offset
= offset
+ os::alignLong( Conf::config
.getMaxProcs() * sizeof(ThreadInfo
));
203 int multiple
= os::floor(offset
/ PAGE_SIZE
);
204 char *curPage
= (((char*)rtnAddr
) + ((multiple
+ 1) * PAGE_SIZE
));
206 db_
->setCurrentPage(curPage
);
207 db_
->setFirstPage(curPage
);
209 if (0 == strcmp(name
, SYSTEMDB
)) return OK
;
211 /*Allocate new chunk to store hash index nodes
212 Chunk *chunkInfo = createUserChunk(sizeof(HashIndexNode));
213 if (NULL == chunkInfo)
215 printError(ErrSysInternal, "Failed to allocate hash index nodes chunk");
216 return ErrSysInternal;
218 printDebug(DM_Database, "Creating Chunk for storing Hash index nodes %x",
221 db_->setHashIndexChunk(chunkInfo);*/
225 DbRetVal
DatabaseManagerImpl::deleteDatabase(const char *name
)
227 shared_memory_id shm_id
= 0;
228 if (0 == strcmp(name
, SYSTEMDB
))
230 shm_id
= os::shm_open(Conf::config
.getSysDbKey(), 100, 0660);
231 os::shmctl(shm_id
, IPC_RMID
);
232 delete systemDatabase_
;
233 systemDatabase_
= NULL
;
235 shm_id
= os::shm_open(Conf::config
.getUserDbKey(), 100, 0660);
236 os::shmctl(shm_id
, IPC_RMID
);
243 DbRetVal
DatabaseManagerImpl::openDatabase(const char *name
)
245 bool isMmapNeeded
= Conf::config
.useMmap();
246 char dbMapFile
[1024];
248 long size
= Conf::config
.getMaxSysDbSize();
249 char *startaddr
= (char*)Conf::config
.getMapAddress();
250 long fixAddr
= 399998976L;
251 if (0 == strcmp(name
, SYSTEMDB
))
253 if (NULL
!=systemDatabase_
)
255 printError(ErrAlready
, "System Database already open");
261 if (NULL
==systemDatabase_
)
263 printError(ErrNotOpen
, "System Database not open");
266 size
= Conf::config
.getMaxDbSize();
267 startaddr
= startaddr
+ Conf::config
.getMaxSysDbSize();
268 fixAddr
+= Conf::config
.getMaxSysDbSize();
272 printError(ErrAlready
, "User Database already open");
275 //system db should be opened before user database files
276 caddr_t rtnAddr
= (caddr_t
) NULL
;
278 shared_memory_id shm_id
= 0;
279 shared_memory_key key
= 0;
281 if (0 == strcmp(name
, SYSTEMDB
))
282 key
= Conf::config
.getSysDbKey();
284 key
= Conf::config
.getUserDbKey();
287 void *shm_ptr
= NULL
;
288 void *mapAddr
= NULL
;
289 bool firstThread
= false;
290 //printf("PRABA::DEBUG:: opendb %d %s\n", ProcessManager::noThreads, name);
291 if ( ( ProcessManager::noThreads
== 0 && 0 == strcmp(name
, SYSTEMDB
) ||
292 ProcessManager::noThreads
== 1 && 0 != strcmp(name
, SYSTEMDB
) ) )
294 if(isMmapNeeded
&& 0 != strcmp(name
, SYSTEMDB
)){
295 //BIJAYA: Attached to Map File
296 sprintf(dbMapFile
, "%s/db.chkpt.data", Conf::config
.getDbFile());
297 fd
= open(dbMapFile
, O_RDWR
, 0660);
299 printError(ErrOS
, "Mmap file could not be opened");
302 mapAddr
= os::mmap((void *)fixAddr
, size
, PROT_READ
| PROT_WRITE
, MAP_FIXED
| MAP_SHARED
, fd
, 0);
304 shm_ptr
= (caddr_t
) mapAddr
;
305 printDebug(DM_Database
, "Mapped db file address = %x", mapAddr
);
308 shm_id
= os::shm_open(key
, size
, 0660);
311 printError(ErrOS
, "Shared memory open failed");
314 shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
316 if (0 == strcmp(name
, SYSTEMDB
))
319 ProcessManager::sysAddr
= (char*) shm_ptr
;
323 ProcessManager::usrAddr
= (char*) shm_ptr
;
326 if (0 == strcmp(name
, SYSTEMDB
))
327 shm_ptr
= ProcessManager::sysAddr
;
328 else shm_ptr
= ProcessManager::usrAddr
;
332 rtnAddr
= (caddr_t
) shm_ptr
;
334 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffffffffffff)
336 printError(ErrOS
, "Shared memory attach returned -ve value %x %d", shm_ptr
, errno
);
340 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
342 printError(ErrOS
, "Shared memory attach returned -ve value %x %d", shm_ptr
, errno
);
347 db_
= new Database();
348 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
351 if (firstThread
) ProcessManager::systemDatabase
= db_
;
353 printDebug(DM_Database
, "Opening database: %s", name
);
357 DbRetVal
DatabaseManagerImpl::closeDatabase()
362 //Database is already closed
365 printDebug(DM_Database
, "Closing database: %s",(char*)db_
->getName());
366 //check if this is the last thread to be deregistered
367 int ret
=0;// ProcessManager::mutex.getLock(-1, false);
368 //If you are not getting lock ret !=0, it means somebody else is there.
369 //he will close the database.
371 //printf("PRABA::FOR DEBUG closedb %d %s\n", ProcessManager::noThreads, (char*)db_->getName());
372 if (ProcessManager::noThreads
== 0 && 0 == strcmp((char*)db_
->getName(), SYSTEMDB
)
373 || ProcessManager::noThreads
== 1 && 0 != strcmp((char*)db_
->getName(), SYSTEMDB
) ) {
374 os::shm_detach((char*)db_
->getMetaDataPtr());
377 // ProcessManager::mutex.releaseLock(-1, false);
382 //Assumes that system database mutex is taken before calling this.
383 Chunk
* DatabaseManagerImpl::createUserChunk(size_t size
)
385 //Allocate new node in system database to store
386 Chunk
*chunk
= getSystemTableChunk(UserChunkTableId
);
388 void *ptr
= chunk
->allocate(systemDatabase_
, &rv
);
391 printError(rv
, "Allocation failed for User chunk catalog table");
394 Chunk
*chunkInfo
= (Chunk
*)ptr
;
395 chunkInfo
->initMutex();
396 if (0 != size
) chunkInfo
->setSize(size
);
397 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
398 chunkInfo
->curPage_
= db_
->getFreePage(chunkInfo
->allocSize_
);
400 chunkInfo
->curPage_
= db_
->getFreePage();
401 if ( NULL
== chunkInfo
->curPage_
)
403 chunkInfo
->destroyMutex();
404 chunk
->free(db_
, ptr
);
405 printError(ErrNoMemory
, "Database full: No space to allocate from database");
408 PageInfo
* firstPageInfo
= ((PageInfo
*)chunkInfo
->curPage_
);
409 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
411 int multiple
= os::floor(chunkInfo
->allocSize_
/ PAGE_SIZE
);
412 int offset
= ((multiple
+ 1) * PAGE_SIZE
);
413 firstPageInfo
->setPageAsUsed(offset
);
417 firstPageInfo
->setPageAsUsed(chunkInfo
->allocSize_
);
418 char *data
= ((char*)firstPageInfo
) + sizeof(PageInfo
);
423 VarSizeInfo
*varInfo
= (VarSizeInfo
*)(((char*)firstPageInfo
) + sizeof(PageInfo
));
424 varInfo
->isUsed_
= 0;
425 varInfo
->size_
= PAGE_SIZE
- sizeof(PageInfo
) - sizeof(VarSizeInfo
);
428 chunkInfo
->firstPage_
= chunkInfo
->curPage_
;
431 chunkInfo
->setAllocType(VariableSizeAllocator
);
433 chunkInfo
->setAllocType(FixedSizeAllocator
);
435 //TODO::Generate chunkid::use tableid
436 chunkInfo
->setChunkID(db_
->getUniqueIDForChunk());
437 db_
->incrementChunk();
438 printDebug(DM_Database
, "Creating new User chunk chunkID:%d size: %d firstPage:%x",
439 -1, chunkInfo
->allocSize_
, firstPageInfo
);
444 //Assumes that system database mutex is taken before calling this.
445 DbRetVal
DatabaseManagerImpl::deleteUserChunk(Chunk
*chunk
)
447 //Go to the pages and set them to notUsed
448 Page
*page
= chunk
->firstPage_
;
449 PageInfo
* pageInfo
= ((PageInfo
*)page
);
450 //Here...sure that atleast one page will be there even no tuples
451 //are inserted.so not checking if pageInfo == NULL
452 while( pageInfo
->nextPage_
!= NULL
)
454 PageInfo
*prev
= pageInfo
;
455 pageInfo
= (PageInfo
*)(pageInfo
->nextPage_
);
456 //sets pageInfo->isUsed_ = 0 and pageInfo->hasFreeSpace_ = 0
457 //and initializes the page content to zero
458 if(NULL
== pageInfo
->nextPageAfterMerge_
)
459 os::memset(prev
, 0, PAGE_SIZE
);
462 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
463 os::memset(prev
, 0, size
);
465 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, prev
);
467 //The above loop wont execute for the last page
468 //and for the case where table has only one page
469 if(NULL
== pageInfo
->nextPageAfterMerge_
)
470 os::memset(pageInfo
, 0, PAGE_SIZE
);
473 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
474 os::memset(pageInfo
, 0, size
);
476 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, pageInfo
);
477 chunk
->chunkID_
= -1;
478 chunk
->allocSize_
= 0;
479 chunk
->curPage_
= NULL
;
480 chunk
->firstPage_
= NULL
;
481 chunk
->destroyMutex();
482 db_
->decrementChunk();
483 Chunk
*userChunk
= getSystemTableChunk(UserChunkTableId
);
484 userChunk
->free(systemDatabase_
,chunk
);
485 printDebug(DM_Database
,"deleting user chunk:%x",chunk
);
489 //-1 -> Unable to create chunk. No memory
490 //-2 -> Unable to update the catalog tables
491 DbRetVal
DatabaseManagerImpl::createTable(const char *name
, TableDef
&def
)
494 if (!Util::isIdentifier((char*)name
)) {
495 printError(ErrBadArg
, "Invalid character for index name");
498 int fldCount
= def
.getFieldCount();
501 printError(ErrNotExists
,"Table can't be created without Field");
505 //If total field count is less than 32, then 1 integer is used to store all null
506 //information, if it is more then 1 char is used to store null information
508 //This is to done to reduce cpu cycles for small tables
510 if (fldCount
< 31) addSize
= 4; else addSize
= os::align(fldCount
);
511 size_t sizeofTuple
= os::alignLong(def
.getTupleSize()+addSize
);
512 rv
= systemDatabase_
->getDatabaseMutex();
514 printError(rv
, "Unable to get Database mutex");
520 void *vcchunk
= NULL
;
522 //check whether table already exists
523 CatalogTableTABLE
cTable(systemDatabase_
);
524 cTable
.getChunkAndTblPtr(name
, chunk
, tptr
, vcchunk
);
527 systemDatabase_
->releaseDatabaseMutex();
528 printError(ErrAlready
, "Table %s already exists", name
);
532 //create a chunk to store the tuples
533 Chunk
*ptr
= createUserChunk(sizeofTuple
);
536 systemDatabase_
->releaseDatabaseMutex();
537 printError(ErrNoResource
, "Unable to create user chunk");
538 return ErrNoResource
;
540 printDebug(DM_Database
,"Created UserChunk:%x", ptr
);
541 ptr
->setChunkName(name
);
543 int tblID
= ((Chunk
*)ptr
)->getChunkID();
545 //check whether varchar is present in table
546 FieldIterator fiter
= def
.getFieldIterator();
547 bool isVarcharPresent
= def
.isVarcharPresentInSchema(fiter
);
549 if (isVarcharPresent
) {
550 //creat chunk to store varchar values
551 vcptr
= createUserChunk();
554 deleteUserChunk(ptr
);
555 systemDatabase_
->releaseDatabaseMutex();
556 printError(ErrNoResource
, "Unable to create user chunk for varchar");
557 return ErrNoResource
;
559 printDebug(DM_Database
,"Created UserChunk for Varchar:%x", vcptr
);
560 vcptr
->setChunkName(name
);
562 rv
= cTable
.insert(name
, tblID
, sizeofTuple
,
563 def
.getFieldCount(), ptr
, tptr
, vcptr
);
566 deleteUserChunk(ptr
);
567 if (vcptr
) deleteUserChunk(vcptr
);
568 systemDatabase_
->releaseDatabaseMutex();
569 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
570 return ErrSysInternal
;
572 printDebug(DM_Database
,"Inserted into TABLE:%s",name
);
574 FieldIterator iter
= def
.getFieldIterator();
575 CatalogTableFIELD
cField(systemDatabase_
);
576 rv
= cField
.insert(iter
, tblID
,tptr
);
579 deleteUserChunk(ptr
);
580 if (vcptr
) deleteUserChunk(vcptr
);
581 void *cptr
, *ttptr
;//Dummy as remove below needs both these OUT params
582 cTable
.remove(name
, cptr
, ttptr
);
583 systemDatabase_
->releaseDatabaseMutex();
584 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
585 return ErrSysInternal
;
587 printDebug(DM_Database
,"Inserted into FIELD:%s",name
);
588 systemDatabase_
->releaseDatabaseMutex();
589 printDebug(DM_Database
,"Table Created:%s",name
);
590 logFinest(Conf::logger
, "Table Created %s" , name
);
594 //TODO::If any operation fails in between, then we may have some
595 //dangling tuples, say we have have rows in INDEX table
596 //which will not have any corresponding entries in TABLE
597 //CHANGE the sequence so that it deletes from the bottom as
598 //opposed to start from top as is written now
599 DbRetVal
DatabaseManagerImpl::dropTable(const char *name
)
603 void *vcchunk
= NULL
;
604 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
606 printError(ErrSysInternal
, "Unable to get database mutex");
607 return ErrSysInternal
;
609 //remove the entry in TABLE
610 CatalogTableTABLE
cTable(systemDatabase_
);
611 rv
= cTable
.getChunkAndTblPtr(name
, chunk
, tptr
, vcchunk
);
613 systemDatabase_
->releaseDatabaseMutex();
614 printError(ErrSysInternal
, "Table %s does not exist", name
);
615 return ErrSysInternal
;
617 CatalogTableFK
cFK(systemDatabase_
);
618 int noOfRelation
=cFK
.getNumFkTable(tptr
);
621 printError(ErrSysInternal
, "Unable to drop table due to relation exist.Drop child table...");
622 systemDatabase_
->releaseDatabaseMutex();
623 return ErrSysInternal
;
625 rv
= lMgr_
->getExclusiveLock(chunk
, NULL
);
628 systemDatabase_
->releaseDatabaseMutex();
629 printError(ErrLockTimeOut
, "Unable to acquire exclusive lock on the table\n");
633 rv
= cTable
.remove(name
, chunk
, tptr
);
635 systemDatabase_
->releaseDatabaseMutex();
636 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
637 return ErrSysInternal
;
639 printDebug(DM_Database
,"Deleted from TABLE:%s",name
);
641 //remove the entries in the FIELD table
642 CatalogTableFIELD
cField(systemDatabase_
);
643 rv
= cField
.remove(tptr
);
645 systemDatabase_
->releaseDatabaseMutex();
646 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
647 return ErrSysInternal
;
649 printDebug(DM_Database
,"Deleted from FIELD:%s",name
);
651 rv
= deleteUserChunk((Chunk
*)chunk
);
653 systemDatabase_
->releaseDatabaseMutex();
654 printError(rv
, "Unable to delete the chunk");
657 printDebug(DM_Database
,"Deleted UserChunk:%x", chunk
);
659 if (vcchunk
!= NULL
) {
660 rv
= deleteUserChunk((Chunk
*)vcchunk
);
662 systemDatabase_
->releaseDatabaseMutex();
663 printError(rv
, "Unable to delete the chunk");
666 printDebug(DM_Database
,"Deleted UserChunk for Varchar:%x", chunk
);
669 //TODO::check whether indexes are available and drop that also.
670 CatalogTableINDEX
cIndex(systemDatabase_
);
671 int noIndexes
= cIndex
.getNumIndexes(tptr
);
672 for (int i
=1 ; i
<= noIndexes
; i
++) {
673 char *idxName
= cIndex
.getIndexName(tptr
, 1);
674 dropIndexInt(idxName
, false);
676 bool isFkExist
=cFK
.isFkTable(tptr
);
679 dropForeignKey(tptr
,false);
681 systemDatabase_
->releaseDatabaseMutex();
682 printDebug(DM_Database
, "Deleted Table %s" , name
);
683 logFinest(Conf::logger
, "Deleted Table %s" , name
);
684 rv
= lMgr_
->releaseLock(chunk
);
687 printError(ErrLockTimeOut
, "Unable to release exclusive lock on the table\n");
693 //Return values: NULL for table not found
694 Table
* DatabaseManagerImpl::openTable(const char *name
,bool checkpkfk
)
697 //TODO::store table handles in list so that if it is
698 //not closed by the application. destructor shall close it.
699 TableImpl
*table
= new TableImpl();
701 table
->setSystemDB(systemDatabase_
);
702 table
->setLockManager(lMgr_
);
703 table
->setTrans(ProcessManager::getThreadTransAddr(systemDatabase_
->procSlot
));
705 //to store the chunk pointer of table
707 void *vcchunk
= NULL
;
709 //to store the tuple pointer of the table
712 //TODO::need to take shared lock on the table so that
713 //all ddl operation will be denied on that table
714 //which includes index creation, alter table
716 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
718 printError(ErrSysInternal
, "Unable to get database mutex");
722 CatalogTableTABLE
cTable(systemDatabase_
);
723 ret
= cTable
.getChunkAndTblPtr(name
, chunk
, tptr
, vcchunk
);
726 systemDatabase_
->releaseDatabaseMutex();
728 printError(ErrNotExists
, "Table not exists %s", name
);
731 CTABLE
*tTuple
= (CTABLE
*)tptr
;
732 table
->setTableInfo(tTuple
->tblName_
, tTuple
->tblID_
, tTuple
->length_
,
733 tTuple
->numFlds_
, tTuple
->numIndexes_
,
734 tTuple
->chunkPtr_
, tTuple
->varcharChunkPtr_
);
735 /*rv = table->lock(true); //take shared lock
738 printError(ErrLockTimeOut, "Unable to acquire shared lock on the table\n");
739 systemDatabase_->releaseDatabaseMutex();
745 if (tTuple
->numFlds_
< 31)
747 table
->isIntUsedForNULL
= true;
748 table
->iNullInfo
= 0;
749 table
->iNotNullInfo
=0;
753 table
->isIntUsedForNULL
= false;
754 int noFields
= os::align(tTuple
->numFlds_
);
755 table
->cNullInfo
= (char*) malloc(noFields
);
756 table
->cNotNullInfo
= (char*) malloc(noFields
);
757 for (int i
=0 ; i
< noFields
; i
++) table
->cNullInfo
[i
] =0;
758 for (int i
=0 ; i
< noFields
; i
++) table
->cNotNullInfo
[i
] =0;
762 //get field information from FIELD table
763 CatalogTableFIELD
cField(systemDatabase_
);
764 table
->ptrToAuto
= cField
.getFieldInfo(tptr
, table
->fldList_
);
766 //populate the notnull info
767 FieldIterator fIter
= table
->fldList_
.getIterator();
769 while (fIter
.hasElement())
771 FieldDef
*def
= fIter
.nextElement();
772 if (table
->isIntUsedForNULL
) {
773 if (def
->isNull_
) SETBIT(table
->iNotNullInfo
, fldpos
);
776 if (def
->isNull_
) table
->cNotNullInfo
[fldpos
-1] = 1;
781 //get the number of indexes on this table
782 //and populate the indexPtr array
783 CatalogTableINDEX
cIndex(systemDatabase_
);
784 table
->numIndexes_
= cIndex
.getNumIndexes(tptr
);
785 if (table
->numIndexes_
) {
786 table
->indexPtr_
= new char*[table
->numIndexes_
];
787 table
->idxInfo
= new IndexInfo
*[table
->numIndexes_
];
791 table
->indexPtr_
= NULL
;
793 cIndex
.getIndexPtrs(tptr
, table
->indexPtr_
);
794 for (int i
=0 ; i
< table
->numIndexes_
; i
++ )
796 HashIndexInfo
*hIdxInfo
= new HashIndexInfo();
797 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
798 cIndexField
.getFieldInfo(table
->indexPtr_
[i
], hIdxInfo
->idxFldList
);
799 ChunkIterator citer
= CatalogTableINDEX::getIterator(table
->indexPtr_
[i
]);
800 hIdxInfo
->indexPtr
= table
->indexPtr_
[i
];
801 hIdxInfo
->indType
= ((CINDEX
*)hIdxInfo
->indexPtr
)->indexType_
;
802 hIdxInfo
->noOfBuckets
= CatalogTableINDEX::getNoOfBuckets(table
->indexPtr_
[i
]);
803 FieldIterator fIter
= hIdxInfo
->idxFldList
.getIterator();
804 bool firstFld
= true;
805 while (fIter
.hasElement())
807 FieldDef
*def
= fIter
.nextElement();
810 hIdxInfo
->fldOffset
= table
->fldList_
.getFieldOffset(def
->fldName_
);
811 hIdxInfo
->type
= table
->fldList_
.getFieldType(def
->fldName_
);
812 hIdxInfo
->compLength
= table
->fldList_
.getFieldLength(def
->fldName_
);
815 hIdxInfo
->type
= typeComposite
;
816 hIdxInfo
->compLength
= hIdxInfo
->compLength
+
817 table
->fldList_
.getFieldLength(def
->fldName_
);
821 hIdxInfo
->isUnique
= CatalogTableINDEX::getUnique(table
->indexPtr_
[i
]);
822 hIdxInfo
->buckets
= (Bucket
*)citer
.nextElement();
823 table
->idxInfo
[i
] = (IndexInfo
*) hIdxInfo
;
825 systemDatabase_
->releaseDatabaseMutex();
826 //Foreign key Operation
828 CatalogTableFK
cFk(systemDatabase_
);
830 table
->numFkRelation_
= cFk
.getNumFkTable(tptr
);
831 if (table
->numFkRelation_
) {
832 table
->isPkTbl
=true;//TODO:for Delete In casecade
833 totalFld
=cFk
.getNoOfFkTable(tptr
);
834 //printDebug(DM_TEST,"Total table is %d\n",totalFld);
835 char **fptr
= new char* [totalFld
];
836 cFk
.getFkTableName(tptr
,fptr
);
837 for(int count
=0; count
< totalFld
; count
++){
838 //printDebug(DM_TEST,"FK Name is %s\n",fptr[count]);
839 table
->tblFkList
.append(openTable(fptr
[count
],false));
844 char *tblName
= NULL
;
845 table
->isFkTbl
= cFk
.isFkTable(tptr
);
848 totalFld
=cFk
.getNoOfPkTable(tptr
);
849 char **fptr
= new char* [totalFld
];
850 cFk
.getPkTableName(tptr
,fptr
);
851 for(int count
=0; count
<totalFld
; count
++){
852 //printDebug(DM_TEST,"Parent Name is %s\n",fptr[count]);
853 table
->tblList
.append(openTable(fptr
[count
],false));
858 // lMgr-> tTuple->chunkPtr_
859 printDebug(DM_Database
,"Opening table handle name:%s chunk:%x numIndex:%d",
860 name
, chunk
, table
->numIndexes_
);
861 logFinest(Conf::logger
, "Opening Table %s" , name
);
863 tableHandleList
.append(table
);
870 List
DatabaseManagerImpl::getAllTableNames(int *retval
)
873 //to store the tuple pointer of the table
876 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
878 printError(ErrSysInternal
, "Unable to get database mutex");
883 CatalogTableTABLE
cTable(systemDatabase_
);
884 List tableList
= cTable
.getTableList();
885 systemDatabase_
->releaseDatabaseMutex();
892 //Return values: -1 for table not found
893 void DatabaseManagerImpl::closeTable(Table
*table
)
895 printDebug(DM_Database
,"Closing table handle: %x", table
);
896 if (NULL
== table
) return;
898 /* TableImpl *fkTbl =NULL;
899 ListIterator tblIter = ((TableImpl*)table)->tblList.getIterator();
901 while (tblIter.hasElement()){
902 fkTbl = (TableImpl *) tblIter.nextElement();
905 ((TableImpl*)table)->tblList.reset();
906 tblIter = ((TableImpl*)table)->tblFkList.getIterator();
908 while (tblIter.hasElement()){
909 fkTbl = (TableImpl *) tblIter.nextElement();
912 ((TableImpl*)table)->tblFkList.reset();*/
913 tableHandleList
.remove(table
, false);
914 if (table
) delete table
; table
= NULL
;
915 logFinest(Conf::logger
, "Closing Table");
918 DbRetVal
DatabaseManagerImpl::createIndex(const char *indName
, IndexInitInfo
*info
)
921 if (!info
->isUnique
&& info
->isPrimary
)
923 printError(ErrBadCall
, "Primary key cannot be non unique\n");
926 if (!Util::isIdentifier((char*)indName
)) {
927 printError(ErrBadArg
, "Invalid character for index name");
931 if (info
->indType
== hashIndex
)
933 //Assumes info is of type HashIndexInitInfo
934 HashIndexInitInfo
*hInfo
= (HashIndexInitInfo
*) info
;
935 rv
= createHashIndex(indName
, info
->tableName
, info
->list
, hInfo
->bucketSize
,
936 info
->isUnique
, info
->isPrimary
);
938 else if (info
->indType
== treeIndex
)
940 HashIndexInitInfo
*hInfo
= (HashIndexInitInfo
*) info
;
941 rv
= createTreeIndex(indName
, info
->tableName
, info
->list
,
942 hInfo
->bucketSize
, info
->isUnique
, info
->isPrimary
);
945 printError(ErrBadCall
, "Index type not supported\n");
952 //-1 -> Table does not exists
953 //-2 -> Field does not exists
954 //-3 -> bucketSize is not valid
955 DbRetVal
DatabaseManagerImpl::createHashIndex(const char *indName
, const char *tblName
,
956 FieldNameList
&fldList
, int bucketSize
, bool isUnique
, bool isPrimary
)
958 //validate the bucket size
959 if (bucketSize
< 100 || bucketSize
> 200000)
961 printError(ErrBadRange
, "Index Bucket size %d not in range 100-200000",
965 int totFlds
= fldList
.size();
968 printError(ErrBadCall
, "No Field name specified");
973 void *vcchunk
= NULL
;
974 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
977 printError(ErrSysInternal
, "Unable to get database mutex");
978 return ErrSysInternal
;
981 //check whether table exists
982 CatalogTableTABLE
cTable(systemDatabase_
);
983 cTable
.getChunkAndTblPtr(tblName
, chunk
, tptr
,chunk
);
986 systemDatabase_
->releaseDatabaseMutex();
987 printError(ErrNotExists
, "Table does not exist %s", tblName
);
991 //check whether field exists
992 char **fptr
= new char* [totFlds
];
993 CatalogTableFIELD
cField(systemDatabase_
);
994 rv
= cField
.getFieldPtrs(fldList
, tptr
, fptr
);
998 systemDatabase_
->releaseDatabaseMutex();
999 //TODO::check test cases of dbapi/Index, they give wrong results
1000 //if (rv == ErrBadCall) {
1001 //// if (isPrimary) printError(ErrBadCall, "Field can have NULL values");
1003 //printError(ErrNotExists, "Field does not exist");
1005 //return ErrBadCall;
1006 if (rv
!= ErrBadCall
) {
1007 printError(ErrNotExists
, "Field does not exist");
1008 return ErrNotExists
;
1011 for (int i
=0; i
<totFlds
; i
++)
1013 CFIELD
* fInfo
= (CFIELD
*)fptr
[i
];
1014 if (fInfo
->type_
== typeFloat
|| fInfo
->type_
== typeDouble
|| fInfo
->type_
== typeTimeStamp
)
1016 printError(ErrBadArg
, "HashIndex cannot be created for float or double or timestamp type");
1018 systemDatabase_
->releaseDatabaseMutex();
1021 if (!fInfo
->isNull_
&& isPrimary
)
1023 printError(ErrBadArg
, "Primary Index cannot be created on field without NOTNULL constraint");
1025 systemDatabase_
->releaseDatabaseMutex();
1028 if(isPrimary
){fInfo
->isPrimary_
=true;fInfo
->isUnique_
=true;}
1029 if(isUnique
){fInfo
->isUnique_
=true;}
1031 //create chunk to store the meta data of the index created
1032 //for latches and bucket pointers
1033 printDebug(DM_HashIndex
, "Creating chunk for storing hash buckets of size %d\n",
1034 bucketSize
* sizeof(Bucket
));
1035 Chunk
* chunkInfo
= createUserChunk(bucketSize
* sizeof(Bucket
));
1036 if (NULL
== chunkInfo
)
1039 systemDatabase_
->releaseDatabaseMutex();
1040 printError(ErrSysInternal
, "Unable to create chunk");
1041 return ErrSysInternal
;
1043 chunkInfo
->setChunkName(indName
);
1044 //create memory for holding the bucket pointers
1045 void *buckets
= chunkInfo
->allocate(db_
, &rv
);
1046 if (NULL
== buckets
)
1049 deleteUserChunk(chunkInfo
);
1050 systemDatabase_
->releaseDatabaseMutex();
1051 printError(rv
, "Unable to allocate memory for bucket");
1054 Bucket
*buck
= (Bucket
*) buckets
;
1055 initHashBuckets(buck
, bucketSize
);
1057 //create chunk to store the hash index nodes
1058 Chunk
* hChunk
= createUserChunk(sizeof(HashIndexNode
));
1062 deleteUserChunk(chunkInfo
);
1063 systemDatabase_
->releaseDatabaseMutex();
1064 printError(ErrSysInternal
, "Unable to create chunk for storing hash index nodes");
1065 return ErrSysInternal
;
1068 hChunk
->setChunkName(indName
);
1070 void *tupleptr
= NULL
;
1071 CatalogTableINDEX
cIndex(systemDatabase_
);
1072 rv
= cIndex
.insert(indName
, tptr
, fldList
.size(), isUnique
,
1073 chunkInfo
, bucketSize
, hChunk
, tupleptr
);
1077 deleteUserChunk(hChunk
);
1078 deleteUserChunk(chunkInfo
);
1079 systemDatabase_
->releaseDatabaseMutex();
1080 printError(ErrSysInternal
, "Catalog table updation failed in INDEX table");
1081 return ErrSysInternal
;
1083 //add rows to INDEXFIELD
1084 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1085 rv
= cIndexField
.insert(fldList
, tupleptr
, tptr
, fptr
);
1090 cIndex
.remove(indName
, (void *&)chunkInfo
, (void *&)hChunk
, (void *&)tupleptr
);
1091 deleteUserChunk(hChunk
);
1092 deleteUserChunk(chunkInfo
);
1093 systemDatabase_
->releaseDatabaseMutex();
1094 printError(ErrSysInternal
, "Catalog table updation failed in INDEXFIELD table");
1095 return ErrSysInternal
;
1098 systemDatabase_
->releaseDatabaseMutex();
1100 //TODO:: Take table lock
1102 // Following code is written by Kishor Amballi
1103 TableImpl
*tbl
= (TableImpl
*) openTable(tblName
);
1104 if (! tbl
->numTuples()) {
1105 printDebug(DM_Database
, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName
, tblName
, buckets
);
1106 logFinest(Conf::logger
, "Creating HashIndex %s on %s with bucket size %d", indName
, tblName
, buckets
);
1110 HashIndexInfo
*indxInfo
= NULL
;
1112 for (i
= 0; i
< tbl
->numIndexes_
; i
++) {
1113 if(((HashIndexInfo
*)tbl
->idxInfo
[i
])->indexPtr
== tupleptr
) {
1114 indxInfo
= (HashIndexInfo
*) tbl
->idxInfo
[i
];
1118 void *recPtr
= NULL
;
1119 ChunkIterator chIter
= ((Chunk
*)chunk
)->getIterator();
1120 tbl
->setLoading(true);
1121 while ((recPtr
= chIter
.nextElement()) != NULL
) {
1122 rv
= tbl
->insertIndexNode(*tbl
->trans
, tupleptr
, indxInfo
, recPtr
);
1123 if (rv
== ErrUnique
) {
1130 printDebug(DM_Database
, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName
, tblName
, buckets
);
1131 logFinest(Conf::logger
, "Creating HashIndex %s on %s with bucket size %d", indName
, tblName
, buckets
);
1136 DbRetVal
DatabaseManagerImpl::createTreeIndex(const char *indName
, const char *tblName
,
1137 FieldNameList
&fldList
, int nodeSize
, bool isUnique
, bool isPrimary
)
1139 if (nodeSize
< 20 || nodeSize
> 20000)
1141 printError(ErrBadRange
,"Tree Index Node size %d not in range 20-20000",
1145 int totFlds
= fldList
.size();
1147 printError(ErrBadCall
, "No Field name specified");
1149 }else if (totFlds
!= 1) {
1150 printError(ErrBadCall
, "Composite index not supported for Tree");
1155 void *vcchunk
= NULL
;
1156 DbRetVal rv
= systemDatabase_
->getDatabaseMutex();
1159 printError(ErrSysInternal
, "Unable to get database mutex");
1160 return ErrSysInternal
;
1162 //check whether table exists
1164 CatalogTableTABLE
cTable(systemDatabase_
);
1165 cTable
.getChunkAndTblPtr(tblName
, chunk
, tptr
, vcchunk
);
1168 systemDatabase_
->releaseDatabaseMutex();
1169 printError(ErrNotExists
, "Table does not exist %s", tblName
);
1170 return ErrNotExists
;
1172 char **fptr
= new char* [totFlds
];
1173 CatalogTableFIELD
cField(systemDatabase_
);
1174 rv
= cField
.getFieldPtrs(fldList
, tptr
, fptr
);
1178 systemDatabase_
->releaseDatabaseMutex();
1179 if (rv
!= ErrBadCall
) {
1180 printError(ErrNotExists
, "Field does not exist");
1181 return ErrNotExists
;
1184 for (int i
=0; i
<totFlds
; i
++)
1186 CFIELD
* fInfo
= (CFIELD
*)fptr
[i
];
1187 if (!fInfo
->isNull_
&& isPrimary
)
1189 printError(ErrBadArg
, "Primary Index cannot be created on field without NOTNULL constraint");
1191 systemDatabase_
->releaseDatabaseMutex();
1195 int chunkSize
= sizeof(TreeNode
)+(nodeSize
* sizeof(void*));
1196 printDebug(DM_HashIndex
, "Creating chunk for storing tree nodes of size %d\n", chunkSize
);
1198 Chunk
* chunkInfo
= createUserChunk(chunkSize
);
1199 if (NULL
== chunkInfo
)
1202 systemDatabase_
->releaseDatabaseMutex();
1203 printError(ErrSysInternal
, "Unable to create chunk");
1204 return ErrSysInternal
;
1208 void *tupleptr
= NULL
;
1210 CatalogTableINDEX
cIndex(systemDatabase_
);
1211 rv
= cIndex
.insert(indName
, tptr
, fldList
.size(), isUnique
,
1212 chunkInfo
, nodeSize
, NULL
, tupleptr
);
1216 deleteUserChunk(chunkInfo
);
1217 systemDatabase_
->releaseDatabaseMutex();
1218 printError(ErrSysInternal
, "Catalog table updation failed in INDEX table");
1219 return ErrSysInternal
;
1221 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1222 rv
= cIndexField
.insert(fldList
, tupleptr
, tptr
, fptr
);
1227 void *hChunk
= NULL
;
1228 cIndex
.remove(indName
, (void *&)chunkInfo
, (void *&)hChunk
, (void *&)tupleptr
);
1229 deleteUserChunk(chunkInfo
);
1230 systemDatabase_
->releaseDatabaseMutex();
1231 printError(ErrSysInternal
, "Catalog table updation failed in INDEXFIELD table");
1232 return ErrSysInternal
;
1235 systemDatabase_
->releaseDatabaseMutex();
1236 //TODO::if tuples already present in this table, then create tree index '
1238 TableImpl
*tbl
= (TableImpl
*) openTable(tblName
);
1239 if (! tbl
->numTuples()) {
1240 printDebug(DM_Database
, "Creating Tree Index Name:%s tblname:%s node size:%x",indName
, tblName
, nodeSize
);
1241 logFinest(Conf::logger
, "Creating TreeIndex %s on %s with node size %d",indName
, tblName
, nodeSize
);
1245 HashIndexInfo
*indxInfo
= NULL
;
1247 for (i
= 0; i
< tbl
->numIndexes_
; i
++) {
1248 if(((HashIndexInfo
*)tbl
->idxInfo
[i
])->indexPtr
== tupleptr
) {
1249 indxInfo
= (HashIndexInfo
*) tbl
->idxInfo
[i
];
1253 void *recPtr
= NULL
;
1254 ChunkIterator chIter
= ((Chunk
*)chunk
)->getIterator();
1255 tbl
->setLoading(true);
1256 while ((recPtr
= chIter
.nextElement()) != NULL
) {
1257 rv
= tbl
->insertIndexNode(*tbl
->trans
, tupleptr
, indxInfo
, recPtr
);
1258 if (rv
== ErrUnique
) {
1265 printDebug(DM_Database
, "Creating Tree Index Name:%s tblname:%s node size:%x",
1266 indName
, tblName
, nodeSize
);
1267 logFinest(Conf::logger
, "Creating TreeIndex %s on %s with node size %d",
1268 indName
, tblName
, nodeSize
);
1274 void DatabaseManagerImpl::initHashBuckets(Bucket
*buck
, int bucketSize
)
1276 os::memset((void*)buck
, 0, bucketSize
* sizeof(Bucket
));
1278 for (int i
=0; i
< bucketSize
; i
++)
1280 buck
[i
].mutex_
.init("Bucket");
1285 DbRetVal
DatabaseManagerImpl::dropIndex(const char *name
)
1287 return dropIndexInt(name
, true);
1290 DbRetVal
DatabaseManagerImpl::dropIndexInt(const char *name
, bool takeLock
)
1293 void *chunk
= NULL
, *hchunk
= NULL
;
1297 rv
= systemDatabase_
->getDatabaseMutex();
1300 printError(ErrSysInternal
, "Unable to get database mutex");
1301 return ErrSysInternal
;
1305 //remove the entry in INDEX
1306 CatalogTableINDEX
cIndex(systemDatabase_
);
1307 rv
= cIndex
.remove(name
, chunk
, hchunk
, tptr
);
1310 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
1311 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
1312 return ErrSysInternal
;
1314 printDebug(DM_Database
, "Removing from INDEX %s",name
);
1315 //remove the entries in the INDEXFIELD table
1316 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1317 rv
= cIndexField
.remove(tptr
);
1320 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
1321 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
1322 return ErrSysInternal
;
1324 printDebug(DM_Database
, "Removing from INDEXFIELD %s",name
);
1326 //delete the index chunk
1327 CINDEX
*iptr
= (CINDEX
*)tptr
;
1328 rv
= deleteUserChunk((Chunk
*)chunk
);
1331 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
1332 printError(ErrSysInternal
, "Unable to delete the index chunk");
1333 return ErrSysInternal
;
1335 //delete the index hash node chunk
1336 if (iptr
->indexType_
== hashIndex
) {
1337 rv
= deleteUserChunk((Chunk
*)hchunk
);
1340 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
1341 printError(ErrSysInternal
, "Unable to delete the index hash node chunk");
1342 return ErrSysInternal
;
1345 if (takeLock
) systemDatabase_
->releaseDatabaseMutex();
1347 //TODO::If tuples present in this table, then
1348 //free all hash index nodes for this table.
1349 //free all nodes in list of all buckets
1352 printDebug(DM_Database
, "Dropped hash index %s",name
);
1353 logFinest(Conf::logger
, "Deleted Index %s", name
);
1356 DbRetVal
DatabaseManagerImpl::createForeignKey(char *fKName
,ForeignKeyInfo
*info
)
1359 int totFkFlds
= info
->fkFldList
.size();
1360 int totPkFlds
= info
->pkFldList
.size();
1361 if (totFkFlds
==0 && totPkFlds
==0) {
1362 printError(ErrBadCall
, "No Field name specified");
1367 void *vcchunk
= NULL
;
1368 rv
= systemDatabase_
->getDatabaseMutex();
1371 printError(ErrSysInternal
, "Unable to get database mutex");
1372 return ErrSysInternal
;
1374 CatalogTableTABLE
cTable(systemDatabase_
);
1375 cTable
.getChunkAndTblPtr(info
->fkTableName
, chunk
, tptr
, vcchunk
);
1378 systemDatabase_
->releaseDatabaseMutex();
1379 printError(ErrNotExists
, "Table does not exist %s", info
->fkTableName
);
1380 return ErrNotExists
;
1382 char **fptr
= new char* [totFkFlds
];
1383 CatalogTableFIELD
cField(systemDatabase_
);
1384 rv
= cField
.getFieldPtrs(info
->fkFldList
, tptr
, fptr
);
1388 systemDatabase_
->releaseDatabaseMutex();
1389 if (rv
!= ErrBadCall
) {
1390 printError(ErrNotExists
, "Field does not exist");
1391 return ErrNotExists
;
1395 void *chunkPk
= NULL
;
1396 void *vcchunkPk
= NULL
;
1397 CatalogTableTABLE
c2Table(systemDatabase_
);
1398 c2Table
.getChunkAndTblPtr(info
->pkTableName
, chunkPk
, tPkptr
, vcchunkPk
);
1401 systemDatabase_
->releaseDatabaseMutex();
1402 printError(ErrNotExists
, "Table does not exist %s", info
->pkTableName
);
1403 return ErrNotExists
;
1405 char **fPkptr
= new char* [totPkFlds
];
1406 CatalogTableFIELD
c2Field(systemDatabase_
);
1407 rv
= c2Field
.getFieldPtrs(info
->pkFldList
, tPkptr
, fPkptr
);
1412 systemDatabase_
->releaseDatabaseMutex();
1413 if (rv
!= ErrBadCall
) {
1414 printError(ErrNotExists
, "Field does not exist");
1415 return ErrNotExists
;
1418 //Create New chunkdatanode
1419 CatalogTableFK
cFK(systemDatabase_
);
1420 rv
= cFK
.insert(fKName
, tptr
, tPkptr
);//TODO
1425 systemDatabase_
->releaseDatabaseMutex();
1426 printError(ErrSysInternal
, "Catalog table updation failed in CFK table");
1427 return ErrSysInternal
;
1430 CatalogTableFKFIELD
cFKField(systemDatabase_
);
1431 rv
= cFKField
.insert(fKName
,fptr
,fPkptr
,totFkFlds
);
1437 systemDatabase_
->releaseDatabaseMutex();
1438 printError(ErrSysInternal
, "Catalog table updation failed in CFKFIELD table");
1439 return ErrSysInternal
;
1441 systemDatabase_
->releaseDatabaseMutex();
1446 DbRetVal
DatabaseManagerImpl::dropForeignKey(void *tptr
,bool trylock
)
1450 rv
= systemDatabase_
->getDatabaseMutex();
1453 printError(ErrSysInternal
, "Unable to get database mutex");
1454 return ErrSysInternal
;
1458 CatalogTableFK
cFK(systemDatabase_
);
1459 int total
= cFK
.getNoOfPkTable(tptr
);
1460 //printDebug(DM_TEST,"total fk chunk %d",total);
1461 for (int i
=0;i
< total
; i
++)
1463 fkChunk
= cFK
.getFkCTable(tptr
);
1467 systemDatabase_
->releaseDatabaseMutex();
1469 printError(ErrSysInternal
, "Catalog table not finds CFKFIELD table");
1470 return ErrSysInternal
;
1472 CatalogTableFKFIELD
cFKField(systemDatabase_
);
1473 rv
= cFKField
.remove(fkChunk
);
1477 systemDatabase_
->releaseDatabaseMutex();
1479 printError(ErrSysInternal
, "Catalog table updation failed in CFKFIELD table");
1480 return ErrSysInternal
;
1482 rv
=cFK
.remove(fkChunk
);
1486 systemDatabase_
->releaseDatabaseMutex();
1488 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
1489 return ErrSysInternal
;
1493 systemDatabase_
->releaseDatabaseMutex();
1498 void DatabaseManagerImpl::printTreeIndexNodeInfo(char *name
, bool flag
)
1500 CatalogTableINDEX
cIndex(systemDatabase_
);
1502 void *chunk
= NULL
, *hchunk
= NULL
;
1504 rv
= cIndex
.get(name
, chunk
, hchunk
, tptr
);
1505 if (OK
!= rv
) return;
1506 IndexType iType
= CatalogTableINDEX::getType(tptr
);
1507 if (treeIndex
!= iType
)
1509 printf("%s is not a tree index\n ");
1512 Chunk
*ch
= (Chunk
*) chunk
;
1513 if(flag
){ if(hchunk
)((TreeNode
*) hchunk
)->displayAll(); }
1515 int offset
= CatalogTableINDEX::getOffsetOfFirstField(tptr
);
1516 //if(typeInt != offset) { printf("%s is not on Integer Type Field. To see info Index should be on integer type field. \n "); return;}
1517 if(hchunk
) ((TreeNode
*) hchunk
)->displayAll(offset
);
1521 DbRetVal
DatabaseManagerImpl::printIndexInfo(char *name
)
1523 CatalogTableINDEX
cIndex(systemDatabase_
);
1525 void *chunk
= NULL
, *hchunk
= NULL
;
1527 rv
= cIndex
.get(name
, chunk
, hchunk
, tptr
);
1528 if (OK
!= rv
) return rv
;
1529 printf("<IndexName> %s </IndexName>\n", name
);
1530 printf("<Unique> %d </Unique>\n", CatalogTableINDEX::getUnique(tptr
));
1531 IndexType iType
= CatalogTableINDEX::getType(tptr
);
1532 if(hashIndex
== iType
)
1533 printf("<Type> Hash Index </Type>\n");
1534 else if (treeIndex
== iType
)
1535 printf("<Type> Tree Index </Type>\n");
1537 printf("<Type> Unknown Index </Type>\n");
1539 Chunk
*ch
= (Chunk
*) chunk
;
1540 printf("<HashBucket>\n");
1541 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1542 printf(" <TotalBuckets> %d </TotalBuckets> \n", CatalogTableINDEX::getNoOfBuckets(tptr
));
1543 printf("</HashBucket>\n");
1544 if(treeIndex
!= iType
){
1545 ch
= (Chunk
*) hchunk
;
1546 printf("<IndexNodes>\n");
1547 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1548 printf(" <TotalNodes> %d </TotalNodes>\n", ch
->getTotalDataNodes());
1549 printf("<IndexNodes>\n");
1551 printf("<IndexNodes>\n");
1552 printf(" <TotalNodes> %d </TotalNodes>\n", ch
->getTotalDataNodes());
1554 printf(" <TotalElements> %lld </TotalElements>\n",((TreeNode
*) hchunk
)->getTotalElements());
1556 printf(" <TotalElements> 0 </TotalElements>\n");
1557 printf("<IndexNodes>\n");
1562 DbRetVal
DatabaseManagerImpl::registerThread()
1567 printError(ErrAlready
, "Process already registered\n");
1570 pMgr_
= new ProcessManager();
1571 rv
= pMgr_
->registerThread();
1572 if (rv
==OK
) { procSlot
= pMgr_
->getProcSlot();
1573 printDebug(DM_Process
, "Process registed with slot %d\n", procSlot
);
1578 DbRetVal
DatabaseManagerImpl::deregisterThread()
1583 rv
= pMgr_
->deregisterThread(procSlot
);
1590 bool DatabaseManagerImpl::isAnyOneRegistered()
1592 if (pMgr_
!= NULL
) return pMgr_
->isAnyOneRegistered();
1597 void DatabaseManagerImpl::printUsageStatistics()
1599 pMgr_
->printUsageStatistics();
1600 tMgr_
->printUsageStatistics();
1601 lMgr_
->printUsageStatistics();
1604 void DatabaseManagerImpl::printDebugLockInfo()
1606 lMgr_
->printDebugInfo();
1609 void DatabaseManagerImpl::printDebugTransInfo()
1611 tMgr_
->printDebugInfo(systemDatabase_
);
1613 void DatabaseManagerImpl::printDebugProcInfo()
1615 pMgr_
->printDebugInfo();
1617 void DatabaseManagerImpl::printDebugChunkInfo()
1619 printf("<NotYetImplemented> </NotYetImplemented>\n");
1621 ChunkIterator
DatabaseManagerImpl::getSystemTableIterator(CatalogTableID id
)
1623 Chunk
*fChunk
= systemDatabase_
->getSystemDatabaseChunk(id
);
1624 return fChunk
->getIterator();
1627 Chunk
* DatabaseManagerImpl::getSystemTableChunk(CatalogTableID id
)
1629 return systemDatabase_
->getSystemDatabaseChunk(id
);
1632 int DatabaseManagerImpl::getNoOfPagesForTable(char *tblName
)
1634 Table
*tbl
= openTable(tblName
);
1635 TableImpl
*tb
= (TableImpl
*) tbl
;
1637 if (tb
->numTuples()) pages
= tb
->pagesUsed();
1642 DbRetVal
DatabaseManagerImpl::loadRecords(char *tblName
, char *buffer
)
1644 // buffer should be as big as the no of pages occupied by the records
1645 Table
*tbl
= openTable(tblName
);
1646 TableImpl
*tb
= (TableImpl
*) tbl
;
1647 char *bufIter
= buffer
;
1648 int pages
= *(int *) bufIter
; bufIter
+= sizeof(int);
1649 Page
*firstPage
= ((Chunk
*)(tb
->chunkPtr_
))->getFirstPage();
1650 PageInfo
*pi
= (PageInfo
*) firstPage
;
1651 memcpy(bufIter
, pi
, PAGE_SIZE
);
1652 bufIter
+= PAGE_SIZE
;
1653 for (int i
= 0; i
< pages
- 1; i
++) {
1654 Page
*nPage
= pi
->nextPage_
;
1655 memcpy(bufIter
, nPage
, PAGE_SIZE
);
1656 bufIter
+= PAGE_SIZE
;
1657 pi
= (PageInfo
*) nPage
;
1663 DbRetVal
DatabaseManagerImpl::pasteRecords(char *tblName
, void *buffer
)
1665 // buffer should be as big as the no of pages occupied by the records
1666 Table
*tbl
= openTable(tblName
);
1667 TableImpl
*tb
= (TableImpl
*) tbl
;
1668 Database
*db
= tb
->getDB();
1669 char *bufIter
= (char *) buffer
;
1670 int pages
= *(int *) bufIter
;
1671 bufIter
+= sizeof(int);
1673 Page
*firstPage
= ((Chunk
*)(tb
->chunkPtr_
))->getFirstPage();
1674 PageInfo
*pi
= (PageInfo
*) firstPage
;
1675 memcpy(pi
, bufIter
, PAGE_SIZE
);
1676 bufIter
+= PAGE_SIZE
;
1677 while (--pages
!= 0) {
1678 //get a new page allocated
1679 Page
*newPage
= db
->getFreePage();
1680 memcpy(newPage
, bufIter
, PAGE_SIZE
);
1681 pi
->nextPage_
= newPage
;
1682 pi
= (PageInfo
*) newPage
;
1684 // initialize chunk details and pageInfo
1685 ((Chunk
*)tb
->chunkPtr_
)->curPage_
= pi
;
1690 DbRetVal
DatabaseManagerImpl::checkPoint()
1692 DbRetVal rv
= writeSchemaFile();
1693 if (rv
!= OK
) { printf ("checkpoint error\n"); }
1694 rv
= db()->checkPoint();
1698 DbRetVal
DatabaseManagerImpl::writeSchemaFile()
1706 sprintf(schFile
, "%s/db.chkpt.schema1", Conf::config
.getDbFile());
1707 sprintf(mapFile
, "%s/db.chkpt.map1", Conf::config
.getDbFile());
1708 fp
= fopen(schFile
, "r");
1711 int ret
= unlink(schFile
);
1713 printError(ErrOS
, "checkpoint: delete schema file failed");
1717 fp
= fopen(schFile
, "w+");
1719 printError(ErrOS
, "Unable to create schema file for chkpt.");
1722 fp1
= fopen(mapFile
, "r");
1725 int ret
= unlink(mapFile
);
1727 printError(ErrOS
, "checkpoint: delete schema file failed");
1731 fd
= open(mapFile
, O_WRONLY
|O_CREAT
, 0644);
1733 printError(ErrOS
, "checkpoint: Unable to create map file.");
1736 List tableList
= getAllTableNames();
1737 ListIterator iter
= tableList
.getIterator();
1738 Identifier
*elem
= NULL
;
1740 while (iter
.hasElement()) {
1741 elem
= (Identifier
*) iter
.nextElement();
1742 // if (TableConf::config.isTableCached(elem->name) == OK) continue;
1743 fprintf(fp
, "CREATE TABLE %s (", elem
->name
);
1744 Table
*table
= openTable(elem
->name
);
1746 void *chunk
= NULL
; void *tptr
=NULL
; void *vcchunk
= NULL
;
1747 CatalogTableTABLE
cTable(systemDatabase_
);
1748 rv
= cTable
.getChunkAndTblPtr(elem
->name
, chunk
, tptr
, vcchunk
);
1750 strcpy(obj
.name
, elem
->name
);
1752 obj
.bucketChunk
= NULL
;
1753 obj
.firstPage
= ((Chunk
*)chunk
)->getFirstPage();
1754 obj
.curPage
= ((Chunk
*)chunk
)->getCurrentPage();
1756 write(fd
, buf
, sizeof(obj
));
1757 FieldInfo
*info
= new FieldInfo();
1758 List fNameList
= table
->getFieldNameList();
1759 ListIterator fNameIter
= fNameList
.getIterator();
1761 bool firstField
=true;
1762 char fieldName
[IDENTIFIER_LENGTH
];
1763 while (fNameIter
.hasElement()) {
1764 elem
= (Identifier
*) fNameIter
.nextElement();
1765 Table::getFieldNameAlone(elem
->name
, fieldName
);
1766 rv
= table
->getFieldInfo(elem
->name
, info
);
1768 printf("unable to retrive info for table %s\n", elem
->name
);
1771 fprintf(fp
, "%s %s ", fieldName
, AllDataType::getSQLString(info
->type
));
1774 fprintf(fp
, ", %s %s ", fieldName
, AllDataType::getSQLString(info
->type
));
1775 if (info
->type
== typeString
) fprintf(fp
, "(%d)",info
->length
);
1776 if (info
->type
== typeBinary
) fprintf(fp
, "(%d)",info
->length
);
1777 if (info
->isNull
) fprintf(fp
, " NOT NULL ");
1778 if (info
->isDefault
) fprintf(fp
, " DEFAULT '%s' ", info
->defaultValueBuf
);
1779 if (info
->isAutoIncrement
) fprintf(fp
, " AUTO_INCREMENT ");
1781 fprintf(fp
, ");\n");
1782 table
->printSQLIndexString(fp
, fd
);
1791 DbRetVal
DatabaseManagerImpl::recover()
1794 if (!Conf::config
.useMmap())rv
= db()->recoverUserDB();
1795 rv
= sysDb()->recoverSystemDB();
1799 void DatabaseManagerImpl::sendSignal(int signal
)
1801 ThreadInfo
* tInfo
= sysDb()->getThreadInfo(0);
1802 for (int i
=0; i
< Conf::config
.getMaxProcs(); i
++)
1804 if (tInfo
->pid_
!=0) os::kill(tInfo
->pid_
, signal
);