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
39 void DatabaseManagerImpl::createLockManager()
41 lMgr_
= new LockManager(systemDatabase_
);
45 void DatabaseManagerImpl::createTransactionManager()
48 tMgr_
= new TransactionManager();
49 tMgr_
->setFirstTrans(systemDatabase_
->getSystemDatabaseTrans(0));
52 void DatabaseManagerImpl::setProcSlot()
54 systemDatabase_
->setProcSlot(procSlot
);
55 db_
->setProcSlot(procSlot
);
57 DbRetVal
DatabaseManagerImpl::openSystemDatabase()
59 DbRetVal rv
= openDatabase(SYSTEMDB
);
60 if (rv
!= OK
) return rv
;
61 systemDatabase_
= db_
;
63 printDebug(DM_Database
, "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");
79 DbRetVal
DatabaseManagerImpl::createDatabase(const char *name
, size_t size
)
81 bool isMmapNeeded
= Conf::config
.useMmap();
83 if (isMmapNeeded && !Conf::config.useDurability()) {
84 printError(ErrBadArg, "If MMAP is set to true. Durability must be true.");
90 char dbMapFile
[MAX_FILE_LEN
];
92 long fixAddr
= 399998976L;
93 bool firstTimeServer
= false;
96 printError(ErrAlready
, "Database is already created");
99 caddr_t rtnAddr
= (caddr_t
) NULL
;
100 void *mapAddr
= NULL
;
101 shared_memory_id shm_id
= 0;
103 char *startaddr
= (char*)Conf::config
.getMapAddress();
104 shared_memory_key key
= 0;
105 if (0 == strcmp(name
, SYSTEMDB
))
108 key
= Conf::config
.getSysDbKey();
112 startaddr
= startaddr
+ Conf::config
.getMaxSysDbSize();
113 key
= Conf::config
.getUserDbKey();
115 if (!isMmapNeeded
|| (isMmapNeeded
&& 0 == strcmp(name
, SYSTEMDB
))) {
116 shm_id
= os::shm_create(key
, size
, 0660);
119 #if (defined MMDB && defined EMBED)
120 printError(ErrOS
, "One application is already running.");
123 printError(ErrOS
, "Shared Memory already exists");
125 printError(ErrOS
, "Shared memory create failed");
129 //switch the checkpoint
130 if (Database::getCheckpointID() == 0)
131 Database::setCheckpointID(1);
133 Database::setCheckpointID(0);
134 int chkptID
=Database::getCheckpointID();
137 sprintf(dbMapFile
, "%s/db.chkpt.data%d", Conf::config
.getDbFile(), chkptID
);
138 /*if (FILE *file = fopen(dbMapFile, "r")) {
140 sprintf(cmd, "cp %s %s/db.chkpt.data", dbMapFile, Conf::config.getDbFile());
141 int ret = system(cmd);
143 printError(ErrOS, "could not copy data file to map file");
147 sprintf(dbMapFile, "%s/db.chkpt.data", Conf::config.getDbFile());
151 fd
= open(dbMapFile
, O_CREAT
| O_RDWR
, 0660);
153 printError(ErrOS
, "Mmap file could not be opened");
156 if(fstat(fd
, &st
) == -1) {
157 printf("Unable to retrieve the db File data\n");
162 if (st
.st_size
== 0 || st
.st_size
< size
) {
163 firstTimeServer
= true;
164 off_t flSize
= lseek(fd
, size
- 1, SEEK_SET
);
167 int wSize
= write(fd
, a
, 1);
168 mapAddr
= os::mmap((void *)(fixAddr
+ Conf::config
.getMaxSysDbSize()), size
, PROT_READ
| PROT_WRITE
, MAP_FIXED
| MAP_SHARED
, fd
, 0);
169 rtnAddr
= (caddr_t
) mapAddr
;
170 printDebug(DM_Database
, "Mapped db file address = %x", mapAddr
);
172 void *shm_ptr
= NULL
;
173 if (!isMmapNeeded
|| isMmapNeeded
&& 0 == strcmp(name
, SYSTEMDB
)) {
174 shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
175 rtnAddr
= (caddr_t
) shm_ptr
;
176 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
178 printError(ErrOS
, "Shared memory attach returned -ve value %d", rtnAddr
);
181 # if (defined MMDB && defined EMBED)
182 if (0 == strcmp(name
, SYSTEMDB
)) ProcessManager::sysAddr
= rtnAddr
;
183 else ProcessManager::usrAddr
= rtnAddr
;
186 db_
= new Database();
187 printDebug(DM_Database
, "Creating database:%s",name
);
189 /*if (!isMmapNeeded || isMmapNeeded && 0 == strcmp(name, SYSTEMDB)) {
190 memset(shm_ptr, 0, size );
193 //TODO:for user database do not have transtable and processtable mutex
194 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
195 db_
->setDatabaseID(1);
197 db_
->setMaxSize(size
);
198 db_
->setNoOfChunks(0);
199 db_
->initAllocDatabaseMutex();
200 db_
->initTransTableMutex();
201 db_
->initCheckpointMutex();
202 db_
->initProcessTableMutex();
203 db_
->initPrepareStmtMutex();
204 db_
->setUniqueChunkID(100);
205 //compute the first page after book keeping information
206 size_t offset
= os::alignLong(sizeof (DatabaseMetaData
));
207 //Only for system db chunk array, trans array and proc array will be there
208 if (0 == strcmp(name
, SYSTEMDB
))
210 db_
->setCanTakeCheckPoint(true);
211 offset
= offset
+ os::alignLong( MAX_CHUNKS
* sizeof (Chunk
));
212 offset
= offset
+ os::alignLong( Conf::config
.getMaxProcs() * sizeof(Transaction
));
213 offset
= offset
+ os::alignLong( Conf::config
.getMaxProcs() * sizeof(ThreadInfo
));
215 int multiple
= os::floor(offset
/ PAGE_SIZE
);
216 char *curPage
= (((char*)rtnAddr
) + ((multiple
+ 1) * PAGE_SIZE
));
218 db_
->setCurrentPage(curPage
);
219 db_
->setFirstPage(curPage
);
221 if (0 == strcmp(name
, SYSTEMDB
)) return OK
;
223 /*Allocate new chunk to store hash index nodes
224 Chunk *chunkInfo = createUserChunk(sizeof(HashIndexNode));
225 if (NULL == chunkInfo)
227 printError(ErrSysInternal, "Failed to allocate hash index nodes chunk");
228 return ErrSysInternal;
230 printDebug(DM_Database, "Creating Chunk for storing Hash index nodes %x",
233 db_->setHashIndexChunk(chunkInfo);*/
237 DbRetVal
DatabaseManagerImpl::deleteDatabase(const char *name
)
239 shared_memory_id shm_id
= 0;
240 if (0 == strcmp(name
, SYSTEMDB
))
242 shm_id
= os::shm_open(Conf::config
.getSysDbKey(), 100, 0660);
243 os::shmctl(shm_id
, IPC_RMID
);
244 delete systemDatabase_
;
245 systemDatabase_
= NULL
;
247 shm_id
= os::shm_open(Conf::config
.getUserDbKey(), 100, 0660);
248 os::shmctl(shm_id
, IPC_RMID
);
255 DbRetVal
DatabaseManagerImpl::openDatabase(const char *name
)
257 bool isMmapNeeded
= Conf::config
.useMmap();
258 char dbMapFile
[1024];
260 long size
= Conf::config
.getMaxSysDbSize();
261 char *startaddr
= (char*)Conf::config
.getMapAddress();
262 long fixAddr
= 399998976L;
263 if (0 == strcmp(name
, SYSTEMDB
))
265 if (NULL
!=systemDatabase_
)
267 printError(ErrAlready
, "System Database already open");
273 if (NULL
==systemDatabase_
)
275 printError(ErrNotOpen
, "System Database not open");
278 size
= Conf::config
.getMaxDbSize();
279 startaddr
= startaddr
+ Conf::config
.getMaxSysDbSize();
280 fixAddr
+= Conf::config
.getMaxSysDbSize();
284 printError(ErrAlready
, "User Database already open");
287 //system db should be opened before user database files
288 caddr_t rtnAddr
= (caddr_t
) NULL
;
290 shared_memory_id shm_id
= 0;
291 shared_memory_key key
= 0;
293 if (0 == strcmp(name
, SYSTEMDB
))
294 key
= Conf::config
.getSysDbKey();
296 key
= Conf::config
.getUserDbKey();
299 void *shm_ptr
= NULL
;
300 void *mapAddr
= NULL
;
301 bool firstThread
= false;
302 if ( ( ProcessManager::noThreads
== 0 && 0 == strcmp(name
, SYSTEMDB
) ||
303 ProcessManager::noThreads
== 1 && 0 != strcmp(name
, SYSTEMDB
) ) )
305 if(isMmapNeeded
&& 0 != strcmp(name
, SYSTEMDB
)){
306 //: Attach to Map File
307 int curChkptID
= Database::getCheckpointID();
308 sprintf(dbMapFile
, "%s/db.chkpt.data%d", Conf::config
.getDbFile(),
310 fd
= open(dbMapFile
, O_RDWR
, 0660);
312 printError(ErrOS
, "Mmap file could not be opened");
315 mapAddr
= os::mmap((void *)fixAddr
, size
, PROT_READ
| PROT_WRITE
, MAP_FIXED
| MAP_SHARED
, fd
, 0);
317 shm_ptr
= (caddr_t
) mapAddr
;
318 printDebug(DM_Database
, "Mapped db file address = %x", mapAddr
);
321 shm_id
= os::shm_open(key
, size
, 0660);
324 printError(ErrOS
, "Shared memory open failed");
327 shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
329 if (0 == strcmp(name
, SYSTEMDB
))
332 ProcessManager::sysAddr
= (char*) shm_ptr
;
336 ProcessManager::usrAddr
= (char*) shm_ptr
;
339 if (0 == strcmp(name
, SYSTEMDB
)) shm_ptr
= ProcessManager::sysAddr
;
340 else shm_ptr
= ProcessManager::usrAddr
;
344 rtnAddr
= (caddr_t
) shm_ptr
;
346 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffffffffffff)
348 printError(ErrOS
, "Shared memory attach returned -ve value %x %d", shm_ptr
, errno
);
352 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
354 printError(ErrOS
, "Shared memory attach returned -ve value %x %d", shm_ptr
, errno
);
359 db_
= new Database();
360 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
363 if (firstThread
) ProcessManager::systemDatabase
= db_
;
365 printDebug(DM_Database
, "Opening database: %s", name
);
369 DbRetVal
DatabaseManagerImpl::closeDatabase()
374 //Database is already closed
377 printDebug(DM_Database
, "Closing database: %s",(char*)db_
->getName());
378 //check if this is the last thread to be deregistered
379 int ret
=0;// ProcessManager::mutex.getLock(-1, false);
380 //If you are not getting lock ret !=0, it means somebody else is there.
381 //he will close the database.
382 if (0 != strcmp((char*)db_
->getName(), SYSTEMDB
)) {
383 int fd
= db_
->getChkptfd();
387 if (ProcessManager::noThreads
== 0 && 0 == strcmp((char*)db_
->getName(), SYSTEMDB
)
388 || ProcessManager::noThreads
== 1 && 0 != strcmp((char*)db_
->getName(), SYSTEMDB
) ) {
389 os::shm_detach((char*)db_
->getMetaDataPtr());
392 // ProcessManager::mutex.releaseLock(-1, false);
397 //Assumes that system database mutex is taken before calling this.
398 Chunk
* DatabaseManagerImpl::createUserChunk(size_t size
)
400 //Allocate new node in system database to store
401 Chunk
*chunk
= getSystemTableChunk(UserChunkTableId
);
403 void *ptr
= chunk
->allocate(systemDatabase_
, &rv
);
406 printError(rv
, "Allocation failed for User chunk catalog table");
409 Chunk
*chunkInfo
= (Chunk
*)ptr
;
410 chunkInfo
->initMutex();
411 if (0 != size
) chunkInfo
->setSize(size
);
412 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
413 chunkInfo
->curPage_
= db_
->getFreePage(chunkInfo
->allocSize_
);
415 chunkInfo
->curPage_
= db_
->getFreePage();
416 if ( NULL
== chunkInfo
->curPage_
)
418 chunkInfo
->destroyMutex();
419 chunk
->free(db_
, ptr
);
420 printError(ErrNoMemory
, "Database full: No space to allocate from database");
423 PageInfo
* firstPageInfo
= ((PageInfo
*)chunkInfo
->curPage_
);
424 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
426 int multiple
= os::floor(chunkInfo
->allocSize_
/ PAGE_SIZE
);
427 int offset
= ((multiple
+ 1) * PAGE_SIZE
);
428 firstPageInfo
->setPageAsUsed(offset
);
432 firstPageInfo
->setPageAsUsed(chunkInfo
->allocSize_
);
433 char *data
= ((char*)firstPageInfo
) + sizeof(PageInfo
);
438 VarSizeInfo
*varInfo
= (VarSizeInfo
*)(((char*)firstPageInfo
) + sizeof(PageInfo
));
439 varInfo
->isUsed_
= 0;
440 varInfo
->size_
= PAGE_SIZE
- sizeof(PageInfo
) - sizeof(VarSizeInfo
);
443 chunkInfo
->firstPage_
= chunkInfo
->curPage_
;
446 chunkInfo
->setAllocType(VariableSizeAllocator
);
448 chunkInfo
->setAllocType(FixedSizeAllocator
);
450 //TODO::Generate chunkid::use tableid
451 chunkInfo
->setChunkID(db_
->getUniqueIDForChunk());
452 db_
->incrementChunk();
453 chunkInfo
->setPageDirty(firstPageInfo
);
454 printDebug(DM_Database
, "Creating new User chunk chunkID:%d size: %d firstPage:%x",
455 -1, chunkInfo
->allocSize_
, firstPageInfo
);
460 //Assumes that system database mutex is taken before calling this.
461 DbRetVal
DatabaseManagerImpl::deleteUserChunk(Chunk
*chunk
)
463 //Go to the pages and set them to notUsed
464 Page
*page
= chunk
->firstPage_
;
465 PageInfo
* pageInfo
= ((PageInfo
*)page
);
466 //Here...sure that atleast one page will be there even no tuples
467 //are inserted.so not checking if pageInfo == NULL
468 while( pageInfo
->nextPage_
!= NULL
)
470 PageInfo
*prev
= pageInfo
;
471 pageInfo
= (PageInfo
*)(pageInfo
->nextPage_
);
472 //sets pageInfo->isUsed_ = 0 and pageInfo->hasFreeSpace_ = 0
473 //and initializes the page content to zero
474 if(NULL
== pageInfo
->nextPageAfterMerge_
){
475 os::memset(prev
, 0, PAGE_SIZE
);
476 SETBIT(prev
->flags
, IS_DIRTY
);
481 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
482 char *iter
= (char*)prev
, *end
=(char*)pageInfo
->nextPageAfterMerge_
;
483 os::memset(prev
, 0, size
);
484 //set dirty bit for all pages in merged pages
487 PageInfo
*info
= (PageInfo
*) iter
;
488 SETBIT(info
->flags
, IS_DIRTY
);
489 iter
= iter
+ PAGE_SIZE
;
492 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, prev
);
494 //The above loop wont execute for the last page
495 //and for the case where table has only one page
496 if(NULL
== pageInfo
->nextPageAfterMerge_
) {
497 os::memset(pageInfo
, 0, PAGE_SIZE
);
498 SETBIT(pageInfo
->flags
, IS_DIRTY
);
502 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
503 char *iter
= (char*)pageInfo
, *end
=(char*)pageInfo
->nextPageAfterMerge_
;
504 os::memset(pageInfo
, 0, size
);
505 //set dirty bit for all pages in merged pages
508 PageInfo
*info
= (PageInfo
*) iter
;
509 SETBIT(info
->flags
, IS_DIRTY
);
510 iter
= iter
+ PAGE_SIZE
;
513 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, pageInfo
);
514 chunk
->chunkID_
= -1;
515 chunk
->allocSize_
= 0;
516 chunk
->curPage_
= NULL
;
517 chunk
->firstPage_
= NULL
;
518 chunk
->destroyMutex();
519 db_
->decrementChunk();
520 Chunk
*userChunk
= getSystemTableChunk(UserChunkTableId
);
521 userChunk
->free(systemDatabase_
,chunk
);
522 printDebug(DM_Database
,"deleting user chunk:%x",chunk
);
526 //-1 -> Unable to create chunk. No memory
527 //-2 -> Unable to update the catalog tables
528 DbRetVal
DatabaseManagerImpl::createTable(const char *name
, TableDef
&def
)
531 if (!Util::isIdentifier((char*)name
)) {
532 printError(ErrBadArg
, "Invalid character for index name");
535 int fldCount
= def
.getFieldCount();
538 printError(ErrNotExists
,"Table can't be created without Field");
542 //If total field count is within 32, then 1 integer is used to store all
543 // null information, if it is more then 1 char is used to store null
544 // information of each field
545 //This is to done to reduce cpu cycles for small tables
547 if (fldCount
<= 32) addSize
= 4; else addSize
= os::align(fldCount
);
548 size_t sizeofTuple
= os::alignLong(def
.getTupleSize()+addSize
);
549 rv
= systemDatabase_
->getXCheckpointMutex();
551 printError(rv
, "Unable to get Database mutex");
557 void *vcchunk
= NULL
;
559 //check whether table already exists
560 CatalogTableTABLE
cTable(systemDatabase_
);
561 cTable
.getChunkAndTblPtr(name
, chunk
, tptr
, vcchunk
);
564 systemDatabase_
->releaseCheckpointMutex();
565 printError(ErrAlready
, "Table %s already exists", name
);
569 //create a chunk to store the tuples
570 Chunk
*ptr
= createUserChunk(sizeofTuple
);
573 systemDatabase_
->releaseCheckpointMutex();
574 printError(ErrNoResource
, "Unable to create user chunk");
575 return ErrNoResource
;
577 printDebug(DM_Database
,"Created UserChunk:%x", ptr
);
578 ptr
->setChunkName(name
);
580 int tblID
= ((Chunk
*)ptr
)->getChunkID();
582 //check whether varchar is present in table
583 FieldIterator fiter
= def
.getFieldIterator();
584 bool isVarcharPresent
= def
.isVarcharPresentInSchema(fiter
);
586 if (isVarcharPresent
) {
587 //creat chunk to store varchar values
588 vcptr
= createUserChunk();
591 deleteUserChunk(ptr
);
592 systemDatabase_
->releaseCheckpointMutex();
593 printError(ErrNoResource
, "Unable to create user chunk for varchar");
594 return ErrNoResource
;
596 printDebug(DM_Database
,"Created UserChunk for Varchar:%x", vcptr
);
597 vcptr
->setChunkName(name
);
599 rv
= cTable
.insert(name
, tblID
, sizeofTuple
,
600 def
.getFieldCount(), ptr
, tptr
, vcptr
);
603 deleteUserChunk(ptr
);
604 if (vcptr
) deleteUserChunk(vcptr
);
605 systemDatabase_
->releaseCheckpointMutex();
606 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
607 return ErrSysInternal
;
609 printDebug(DM_Database
,"Inserted into TABLE:%s",name
);
611 FieldIterator iter
= def
.getFieldIterator();
612 CatalogTableFIELD
cField(systemDatabase_
);
613 rv
= cField
.insert(iter
, tblID
,tptr
);
616 deleteUserChunk(ptr
);
617 if (vcptr
) deleteUserChunk(vcptr
);
618 void *cptr
, *ttptr
;//Dummy as remove below needs both these OUT params
619 cTable
.remove(name
, cptr
, ttptr
);
620 systemDatabase_
->releaseCheckpointMutex();
621 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
622 return ErrSysInternal
;
624 printDebug(DM_Database
,"Inserted into FIELD:%s",name
);
625 systemDatabase_
->releaseCheckpointMutex();
626 printDebug(DM_Database
,"Table Created:%s",name
);
627 logFinest(Conf::logger
, "Table Created %s" , name
);
630 DbRetVal
DatabaseManagerImpl::renameTable(const char *oldName
,const char *newName
)
633 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
635 printError(ErrSysInternal
, "Unable to get database mutex for rename table");
636 return ErrSysInternal
;
638 CatalogTableTABLE
cTable(systemDatabase_
);
639 rv
= cTable
.renameTable(oldName
,newName
);
641 printError(ErrSysInternal
, "Unable to rename table");
642 systemDatabase_
->releaseCheckpointMutex();
643 return ErrSysInternal
;
645 systemDatabase_
->releaseCheckpointMutex();
649 DbRetVal
DatabaseManagerImpl::renameField(const char *tableName
,const char *oldName
,const char *newName
)
651 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
653 printError(ErrSysInternal
, "Unable to get database mutex for rename table");
654 return ErrSysInternal
;
656 CatalogTableFIELD
fTable(systemDatabase_
);
657 rv
= fTable
.renameField(tableName
, oldName
, newName
);
659 printError(ErrSysInternal
, "Unable to rename field.");
660 systemDatabase_
->releaseCheckpointMutex();
661 return ErrSysInternal
;
663 systemDatabase_
->releaseCheckpointMutex();
667 //TODO::If any operation fails in between, then we may have some
668 //dangling tuples, say we have have rows in INDEX table
669 //which will not have any corresponding entries in TABLE
670 //CHANGE the sequence so that it deletes from the bottom as
671 //opposed to start from top as is written now
672 DbRetVal
DatabaseManagerImpl::dropTable(const char *name
)
676 void *vcchunk
= NULL
;
677 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
679 printError(ErrSysInternal
, "Unable to get database mutex");
680 return ErrSysInternal
;
682 //remove the entry in TABLE
683 CatalogTableTABLE
cTable(systemDatabase_
);
684 rv
= cTable
.getChunkAndTblPtr(name
, chunk
, tptr
, vcchunk
);
686 systemDatabase_
->releaseCheckpointMutex();
687 printError(ErrSysInternal
, "Table %s does not exist", name
);
688 return ErrSysInternal
;
690 CatalogTableFK
cFK(systemDatabase_
);
691 int noOfRelation
=cFK
.getNumFkTable(tptr
);
694 printError(ErrSysInternal
, "Unable to drop table due to relation exist.Drop child table...");
695 systemDatabase_
->releaseCheckpointMutex();
696 return ErrSysInternal
;
698 rv
= lMgr_
->getExclusiveLock(chunk
, NULL
);
701 systemDatabase_
->releaseCheckpointMutex();
702 printError(ErrLockTimeOut
, "Unable to acquire exclusive lock on the table\n");
706 rv
= cTable
.remove(name
, chunk
, tptr
);
708 systemDatabase_
->releaseCheckpointMutex();
709 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
710 return ErrSysInternal
;
712 printDebug(DM_Database
,"Deleted from TABLE:%s",name
);
714 //remove the entries in the FIELD table
715 CatalogTableFIELD
cField(systemDatabase_
);
716 rv
= cField
.remove(tptr
);
718 systemDatabase_
->releaseCheckpointMutex();
719 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
720 return ErrSysInternal
;
722 printDebug(DM_Database
,"Deleted from FIELD:%s",name
);
724 rv
= deleteUserChunk((Chunk
*)chunk
);
726 systemDatabase_
->releaseCheckpointMutex();
727 printError(rv
, "Unable to delete the chunk");
730 printDebug(DM_Database
,"Deleted UserChunk:%x", chunk
);
732 if (vcchunk
!= NULL
) {
733 rv
= deleteUserChunk((Chunk
*)vcchunk
);
735 systemDatabase_
->releaseCheckpointMutex();
736 printError(rv
, "Unable to delete the chunk");
739 printDebug(DM_Database
,"Deleted UserChunk for Varchar:%x", chunk
);
742 //TODO::check whether indexes are available and drop that also.
743 CatalogTableINDEX
cIndex(systemDatabase_
);
744 int noIndexes
= cIndex
.getNumIndexes(tptr
);
745 for (int i
=1 ; i
<= noIndexes
; i
++) {
746 char *idxName
= cIndex
.getIndexName(tptr
, 1);
747 dropIndexInt(idxName
, false);
749 bool isFkExist
=cFK
.isFkTable(tptr
);
752 dropForeignKey(tptr
,false);
754 systemDatabase_
->releaseCheckpointMutex();
755 printDebug(DM_Database
, "Deleted Table %s" , name
);
756 logFinest(Conf::logger
, "Deleted Table %s" , name
);
757 rv
= lMgr_
->releaseLock(chunk
);
760 printError(ErrLockTimeOut
, "Unable to release exclusive lock on the table\n");
766 //Return values: NULL for table not found
767 Table
* DatabaseManagerImpl::openTable(const char *name
,bool checkpkfk
)
770 //TODO::store table handles in list so that if it is
771 //not closed by the application. destructor shall close it.
772 TableImpl
*table
= new TableImpl();
774 table
->setSystemDB(systemDatabase_
);
775 table
->setLockManager(lMgr_
);
776 table
->setTrans(ProcessManager::getThreadTransAddr(systemDatabase_
->procSlot
));
778 //to store the chunk pointer of table
780 void *vcchunk
= NULL
;
782 //to store the tuple pointer of the table
785 //TODO::need to take shared lock on the table so that
786 //all ddl operation will be denied on that table
787 //which includes index creation, alter table
789 DbRetVal rv
= systemDatabase_
->getAllocDatabaseMutex();
791 printError(ErrSysInternal
, "Unable to get database mutex");
795 CatalogTableTABLE
cTable(systemDatabase_
);
796 ret
= cTable
.getChunkAndTblPtr(name
, chunk
, tptr
, vcchunk
);
799 systemDatabase_
->releaseAllocDatabaseMutex();
801 printError(ErrNotExists
, "Table not exists %s", name
);
804 CTABLE
*tTuple
= (CTABLE
*)tptr
;
805 table
->setTableInfo(tTuple
->tblName_
, tTuple
->tblID_
, tTuple
->length_
,
806 tTuple
->numFlds_
, tTuple
->numIndexes_
,
807 tTuple
->chunkPtr_
, tTuple
->varcharChunkPtr_
);
808 /*rv = table->lock(true); //take shared lock
811 printError(ErrLockTimeOut, "Unable to acquire shared lock on the table\n");
812 systemDatabase_->releaseAllocDatabaseMutex();
818 if (tTuple
->numFlds_
<= 32)
820 table
->isIntUsedForNULL
= true;
821 table
->iNullInfo
= 0;
822 table
->iNotNullInfo
=0;
826 table
->isIntUsedForNULL
= false;
827 int noFields
= os::align(tTuple
->numFlds_
);
828 table
->cNullInfo
= (char*) malloc(noFields
);
829 table
->cNotNullInfo
= (char*) malloc(noFields
);
830 for (int i
=0 ; i
< noFields
; i
++) table
->cNullInfo
[i
] =0;
831 for (int i
=0 ; i
< noFields
; i
++) table
->cNotNullInfo
[i
] =0;
835 //get field information from FIELD table
836 CatalogTableFIELD
cField(systemDatabase_
);
837 table
->ptrToAuto
= cField
.getFieldInfo(tptr
, table
->fldList_
);
839 //populate the notnull info
840 FieldIterator fIter
= table
->fldList_
.getIterator();
842 while (fIter
.hasElement())
844 FieldDef
*def
= fIter
.nextElement();
845 if (table
->isIntUsedForNULL
) {
846 if (def
->isNull_
) SETBIT(table
->iNotNullInfo
, fldpos
-1);
849 if (def
->isNull_
) table
->cNotNullInfo
[fldpos
-1] = 1;
854 //get the number of indexes on this table
855 //and populate the indexPtr array
856 CatalogTableINDEX
cIndex(systemDatabase_
);
857 table
->numIndexes_
= cIndex
.getNumIndexes(tptr
);
858 if (table
->numIndexes_
) {
859 table
->indexPtr_
= new char*[table
->numIndexes_
];
860 table
->idxInfo
= new IndexInfo
*[table
->numIndexes_
];
864 table
->indexPtr_
= NULL
;
866 cIndex
.getIndexPtrs(tptr
, table
->indexPtr_
);
867 for (int i
=0 ; i
< table
->numIndexes_
; i
++ )
869 HashIndexInfo
*hIdxInfo
= new HashIndexInfo();
870 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
871 cIndexField
.getFieldInfo(table
->indexPtr_
[i
], hIdxInfo
->idxFldList
);
872 ChunkIterator citer
= CatalogTableINDEX::getIterator(table
->indexPtr_
[i
]);
873 hIdxInfo
->indexPtr
= table
->indexPtr_
[i
];
874 hIdxInfo
->indType
= ((CINDEX
*)hIdxInfo
->indexPtr
)->indexType_
;
875 hIdxInfo
->noOfBuckets
= CatalogTableINDEX::getNoOfBuckets(table
->indexPtr_
[i
]);
876 FieldIterator fIter
= hIdxInfo
->idxFldList
.getIterator();
877 bool firstFld
= true;
878 while (fIter
.hasElement())
880 FieldDef
*def
= fIter
.nextElement();
883 hIdxInfo
->fldOffset
= table
->fldList_
.getFieldOffset(def
->fldName_
);
884 hIdxInfo
->type
= table
->fldList_
.getFieldType(def
->fldName_
);
885 hIdxInfo
->compLength
= table
->fldList_
.getFieldLength(def
->fldName_
);
888 hIdxInfo
->type
= typeComposite
;
889 hIdxInfo
->compLength
= hIdxInfo
->compLength
+
890 table
->fldList_
.getFieldLength(def
->fldName_
);
894 hIdxInfo
->isUnique
= CatalogTableINDEX::getUnique(table
->indexPtr_
[i
]);
895 hIdxInfo
->buckets
= (Bucket
*)citer
.nextElement();
896 table
->idxInfo
[i
] = (IndexInfo
*) hIdxInfo
;
898 systemDatabase_
->releaseAllocDatabaseMutex();
899 //Foreign key Operation
901 CatalogTableFK
cFk(systemDatabase_
);
903 table
->numFkRelation_
= cFk
.getNumFkTable(tptr
);
904 if (table
->numFkRelation_
) {
905 table
->isPkTbl
=true;//TODO:for Delete In casecade
906 totalFld
=cFk
.getNoOfFkTable(tptr
);
907 //printDebug(DM_TEST,"Total table is %d\n",totalFld);
908 char **fptr
= new char* [totalFld
];
909 cFk
.getFkTableName(tptr
,fptr
);
910 for(int count
=0; count
< totalFld
; count
++){
911 //printDebug(DM_TEST,"FK Name is %s\n",fptr[count]);
912 Table
*pkTable
=openTable(fptr
[count
],false);
913 if (pkTable
) table
->tblFkList
.append(pkTable
);
915 printError(ErrSysInternal
, "Unable to open foreign key tables");
924 char *tblName
= NULL
;
925 table
->isFkTbl
= cFk
.isFkTable(tptr
);
928 totalFld
=cFk
.getNoOfPkTable(tptr
);
929 char **fptr
= new char* [totalFld
];
930 cFk
.getPkTableName(tptr
,fptr
);
931 for(int count
=0; count
<totalFld
; count
++){
932 //printDebug(DM_TEST,"Parent Name is %s\n",fptr[count]);
933 Table
*fkTable
= openTable(fptr
[count
],false);
934 if (fkTable
) table
->tblList
.append(fkTable
);
936 printError(ErrSysInternal
, "Unable to open foreign key tables");
945 printDebug(DM_Database
,"Opening table handle name:%s chunk:%x numIndex:%d",
946 name
, chunk
, table
->numIndexes_
);
947 logFinest(Conf::logger
, "Opening Table %s" , name
);
951 List
DatabaseManagerImpl::getAllTableNames(int *retval
)
954 //to store the tuple pointer of the table
957 /*DbRetVal rv = systemDatabase_->getSCheckpointMutex();
959 printError(ErrSysInternal, "Unable to get checkpoint mutex");
960 if(retval) *retval = rv;
964 CatalogTableTABLE
cTable(systemDatabase_
);
965 List tableList
= cTable
.getTableList();
966 //systemDatabase_->releaseCheckpointMutex();
973 //Return values: -1 for table not found
974 void DatabaseManagerImpl::closeTable(Table
*table
)
976 printDebug(DM_Database
,"Closing table handle: %x", table
);
977 if (NULL
== table
) return;
979 /* TableImpl *fkTbl =NULL;
980 ListIterator tblIter = ((TableImpl*)table)->tblList.getIterator();
982 while (tblIter.hasElement()){
983 fkTbl = (TableImpl *) tblIter.nextElement();
986 ((TableImpl*)table)->tblList.reset();
987 tblIter = ((TableImpl*)table)->tblFkList.getIterator();
989 while (tblIter.hasElement()){
990 fkTbl = (TableImpl *) tblIter.nextElement();
993 ((TableImpl*)table)->tblFkList.reset();*/
994 if (table
) delete table
; table
= NULL
;
995 logFinest(Conf::logger
, "Closing Table");
998 DbRetVal
DatabaseManagerImpl::createIndex(const char *indName
, IndexInitInfo
*info
)
1001 if (!info
->isUnique
&& info
->isPrimary
)
1003 printError(ErrBadCall
, "Primary key cannot be non unique\n");
1006 if (!Util::isIdentifier((char*)indName
)) {
1007 printError(ErrBadArg
, "Invalid character for index name");
1011 if (info
->indType
== hashIndex
)
1013 //Assumes info is of type HashIndexInitInfo
1014 HashIndexInitInfo
*hInfo
= (HashIndexInitInfo
*) info
;
1015 rv
= createHashIndex(indName
, info
->tableName
, info
->list
, hInfo
->bucketSize
,
1016 info
->isUnique
, info
->isPrimary
);
1018 else if (info
->indType
== treeIndex
)
1020 HashIndexInitInfo
*hInfo
= (HashIndexInitInfo
*) info
;
1021 rv
= createTreeIndex(indName
, info
->tableName
, info
->list
,
1022 hInfo
->bucketSize
, info
->isUnique
, info
->isPrimary
);
1025 printError(ErrBadCall
, "Index type not supported\n");
1032 //-1 -> Table does not exists
1033 //-2 -> Field does not exists
1034 //-3 -> bucketSize is not valid
1035 DbRetVal
DatabaseManagerImpl::createHashIndex(const char *indName
, const char *tblName
,
1036 FieldNameList
&fldList
, int bucketSize
, bool isUnique
, bool isPrimary
)
1038 //validate the bucket size
1039 if (bucketSize
< 100 || bucketSize
> 200000)
1041 printError(ErrBadRange
, "Index Bucket size %d not in range 100-200000",
1045 int totFlds
= fldList
.size();
1048 printError(ErrBadCall
, "No Field name specified");
1053 void *vcchunk
= NULL
;
1054 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
1057 printError(ErrSysInternal
, "Unable to get database mutex");
1058 return ErrSysInternal
;
1061 //check whether table exists
1062 CatalogTableTABLE
cTable(systemDatabase_
);
1063 cTable
.getChunkAndTblPtr(tblName
, chunk
, tptr
, vcchunk
);
1066 systemDatabase_
->releaseCheckpointMutex();
1067 printError(ErrNotExists
, "Table does not exist %s", tblName
);
1068 return ErrNotExists
;
1071 //check whether field exists
1072 char **fptr
= new char* [totFlds
];
1073 CatalogTableFIELD
cField(systemDatabase_
);
1074 rv
= cField
.getFieldPtrs(fldList
, tptr
, fptr
);
1078 systemDatabase_
->releaseCheckpointMutex();
1079 //TODO::check test cases of dbapi/Index, they give wrong results
1080 //if (rv == ErrBadCall) {
1081 //// if (isPrimary) printError(ErrBadCall, "Field can have NULL values");
1083 //printError(ErrNotExists, "Field does not exist");
1085 //return ErrBadCall;
1086 if (rv
!= ErrBadCall
) {
1087 printError(ErrNotExists
, "Field does not exist");
1088 return ErrNotExists
;
1091 for (int i
=0; i
<totFlds
; i
++)
1093 CFIELD
* fInfo
= (CFIELD
*)fptr
[i
];
1094 if (fInfo
->type_
== typeFloat
|| fInfo
->type_
== typeDouble
|| fInfo
->type_
== typeTimeStamp
)
1096 printError(ErrBadArg
, "HashIndex cannot be created for float or double or timestamp type");
1098 systemDatabase_
->releaseCheckpointMutex();
1101 if (!fInfo
->isNull_
&& isPrimary
)
1103 printError(ErrBadArg
, "Primary Index cannot be created on field without NOTNULL constraint");
1105 systemDatabase_
->releaseCheckpointMutex();
1108 if(isPrimary
){fInfo
->isPrimary_
=true;fInfo
->isUnique_
=true;}
1109 if(isUnique
){fInfo
->isUnique_
=true;}
1111 //create chunk to store the meta data of the index created
1112 //for latches and bucket pointers
1113 printDebug(DM_HashIndex
, "Creating chunk for storing hash buckets of size %d\n",
1114 bucketSize
* sizeof(Bucket
));
1115 Chunk
* chunkInfo
= createUserChunk(bucketSize
* sizeof(Bucket
));
1116 if (NULL
== chunkInfo
)
1119 systemDatabase_
->releaseCheckpointMutex();
1120 printError(ErrSysInternal
, "Unable to create chunk");
1121 return ErrSysInternal
;
1123 chunkInfo
->setChunkName(indName
);
1124 //create memory for holding the bucket pointers
1125 void *buckets
= chunkInfo
->allocate(db_
, &rv
);
1126 if (NULL
== buckets
)
1129 deleteUserChunk(chunkInfo
);
1130 systemDatabase_
->releaseCheckpointMutex();
1131 printError(rv
, "Unable to allocate memory for bucket");
1134 Bucket
*buck
= (Bucket
*) buckets
;
1135 initHashBuckets(buck
, bucketSize
);
1137 //create chunk to store the hash index nodes
1138 Chunk
* hChunk
= createUserChunk(sizeof(HashIndexNode
));
1142 deleteUserChunk(chunkInfo
);
1143 systemDatabase_
->releaseCheckpointMutex();
1144 printError(ErrSysInternal
, "Unable to create chunk for storing hash index nodes");
1145 return ErrSysInternal
;
1148 hChunk
->setChunkName(indName
);
1150 void *tupleptr
= NULL
;
1151 CatalogTableINDEX
cIndex(systemDatabase_
);
1152 rv
= cIndex
.insert(indName
, tptr
, fldList
.size(), isUnique
,
1153 chunkInfo
, bucketSize
, hChunk
, tupleptr
);
1157 deleteUserChunk(hChunk
);
1158 deleteUserChunk(chunkInfo
);
1159 systemDatabase_
->releaseCheckpointMutex();
1160 printError(ErrSysInternal
, "Catalog table updation failed in INDEX table");
1161 return ErrSysInternal
;
1163 //add rows to INDEXFIELD
1164 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1165 rv
= cIndexField
.insert(fldList
, tupleptr
, tptr
, fptr
);
1170 cIndex
.remove(indName
, (void *&)chunkInfo
, (void *&)hChunk
, (void *&)tupleptr
);
1171 deleteUserChunk(hChunk
);
1172 deleteUserChunk(chunkInfo
);
1173 systemDatabase_
->releaseCheckpointMutex();
1174 printError(ErrSysInternal
, "Catalog table updation failed in INDEXFIELD table");
1175 return ErrSysInternal
;
1178 systemDatabase_
->releaseCheckpointMutex();
1180 //TODO:: Take table lock
1182 // Following code is written by Kishor Amballi
1183 TableImpl
*tbl
= (TableImpl
*) openTable(tblName
);
1185 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
1186 return ErrSysInternal
;
1188 if (! tbl
->numTuples()) {
1189 printDebug(DM_Database
, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName
, tblName
, buckets
);
1190 logFinest(Conf::logger
, "Creating HashIndex %s on %s with bucket size %d", indName
, tblName
, buckets
);
1194 HashIndexInfo
*indxInfo
= NULL
;
1196 for (i
= 0; i
< tbl
->numIndexes_
; i
++) {
1197 if(((HashIndexInfo
*)tbl
->idxInfo
[i
])->indexPtr
== tupleptr
) {
1198 indxInfo
= (HashIndexInfo
*) tbl
->idxInfo
[i
];
1202 void *recPtr
= NULL
;
1203 ChunkIterator chIter
= ((Chunk
*)chunk
)->getIterator();
1204 tbl
->setLoading(true);
1205 while ((recPtr
= chIter
.nextElement()) != NULL
) {
1206 rv
= tbl
->insertIndexNode(*tbl
->trans
, tupleptr
, indxInfo
, recPtr
);
1207 if (rv
== ErrUnique
) {
1214 printDebug(DM_Database
, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName
, tblName
, buckets
);
1215 logFinest(Conf::logger
, "Creating HashIndex %s on %s with bucket size %d", indName
, tblName
, buckets
);
1220 DbRetVal
DatabaseManagerImpl::createTreeIndex(const char *indName
, const char *tblName
,
1221 FieldNameList
&fldList
, int nodeSize
, bool isUnique
, bool isPrimary
)
1223 if (nodeSize
< 20 || nodeSize
> 20000)
1225 printError(ErrBadRange
,"Tree Index Node size %d not in range 20-20000",
1229 int totFlds
= fldList
.size();
1231 printError(ErrBadCall
, "No Field name specified");
1233 }else if (totFlds
!= 1) {
1234 printError(ErrBadCall
, "Composite index not supported for Tree");
1239 void *vcchunk
= NULL
;
1240 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
1243 printError(ErrSysInternal
, "Unable to get database mutex");
1244 return ErrSysInternal
;
1246 //check whether table exists
1248 CatalogTableTABLE
cTable(systemDatabase_
);
1249 cTable
.getChunkAndTblPtr(tblName
, chunk
, tptr
, vcchunk
);
1252 systemDatabase_
->releaseCheckpointMutex();
1253 printError(ErrNotExists
, "Table does not exist %s", tblName
);
1254 return ErrNotExists
;
1256 char **fptr
= new char* [totFlds
];
1257 CatalogTableFIELD
cField(systemDatabase_
);
1258 rv
= cField
.getFieldPtrs(fldList
, tptr
, fptr
);
1262 systemDatabase_
->releaseCheckpointMutex();
1263 if (rv
!= ErrBadCall
) {
1264 printError(ErrNotExists
, "Field does not exist");
1265 return ErrNotExists
;
1268 for (int i
=0; i
<totFlds
; i
++)
1270 CFIELD
* fInfo
= (CFIELD
*)fptr
[i
];
1271 if (!fInfo
->isNull_
&& isPrimary
)
1273 printError(ErrBadArg
, "Primary Index cannot be created on field without NOTNULL constraint");
1275 systemDatabase_
->releaseCheckpointMutex();
1278 if (fInfo
->type_
== typeVarchar
)
1280 printError(ErrBadArg
, "Tree Index not supported for varchar type. Use char data type instead.");
1282 systemDatabase_
->releaseCheckpointMutex();
1287 int chunkSize
= sizeof(TreeNode
)+(nodeSize
* sizeof(void*));
1288 printDebug(DM_HashIndex
, "Creating chunk for storing tree nodes of size %d\n", chunkSize
);
1290 Chunk
* chunkInfo
= createUserChunk(chunkSize
);
1291 if (NULL
== chunkInfo
)
1294 systemDatabase_
->releaseCheckpointMutex();
1295 printError(ErrSysInternal
, "Unable to create chunk");
1296 return ErrSysInternal
;
1300 void *tupleptr
= NULL
;
1302 CatalogTableINDEX
cIndex(systemDatabase_
);
1303 rv
= cIndex
.insert(indName
, tptr
, fldList
.size(), isUnique
,
1304 chunkInfo
, nodeSize
, NULL
, tupleptr
);
1308 deleteUserChunk(chunkInfo
);
1309 systemDatabase_
->releaseCheckpointMutex();
1310 printError(ErrSysInternal
, "Catalog table updation failed in INDEX table");
1311 return ErrSysInternal
;
1313 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1314 rv
= cIndexField
.insert(fldList
, tupleptr
, tptr
, fptr
);
1319 void *hChunk
= NULL
;
1320 cIndex
.remove(indName
, (void *&)chunkInfo
, (void *&)hChunk
, (void *&)tupleptr
);
1321 deleteUserChunk(chunkInfo
);
1322 systemDatabase_
->releaseCheckpointMutex();
1323 printError(ErrSysInternal
, "Catalog table updation failed in INDEXFIELD table");
1324 return ErrSysInternal
;
1327 systemDatabase_
->releaseCheckpointMutex();
1328 //TODO::if tuples already present in this table, then create tree index '
1330 TableImpl
*tbl
= (TableImpl
*) openTable(tblName
);
1332 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
1333 return ErrSysInternal
;
1335 if (! tbl
->numTuples()) {
1336 printDebug(DM_Database
, "Creating Tree Index Name:%s tblname:%s node size:%x",indName
, tblName
, nodeSize
);
1337 logFinest(Conf::logger
, "Creating TreeIndex %s on %s with node size %d",indName
, tblName
, nodeSize
);
1341 HashIndexInfo
*indxInfo
= NULL
;
1343 for (i
= 0; i
< tbl
->numIndexes_
; i
++) {
1344 if(((HashIndexInfo
*)tbl
->idxInfo
[i
])->indexPtr
== tupleptr
) {
1345 indxInfo
= (HashIndexInfo
*) tbl
->idxInfo
[i
];
1349 void *recPtr
= NULL
;
1350 ChunkIterator chIter
= ((Chunk
*)chunk
)->getIterator();
1351 tbl
->setLoading(true);
1352 while ((recPtr
= chIter
.nextElement()) != NULL
) {
1353 rv
= tbl
->insertIndexNode(*tbl
->trans
, tupleptr
, indxInfo
, recPtr
);
1354 if (rv
== ErrUnique
) {
1361 printDebug(DM_Database
, "Creating Tree Index Name:%s tblname:%s node size:%x",
1362 indName
, tblName
, nodeSize
);
1363 logFinest(Conf::logger
, "Creating TreeIndex %s on %s with node size %d",
1364 indName
, tblName
, nodeSize
);
1370 void DatabaseManagerImpl::initHashBuckets(Bucket
*buck
, int bucketSize
)
1372 os::memset((void*)buck
, 0, bucketSize
* sizeof(Bucket
));
1374 for (int i
=0; i
< bucketSize
; i
++)
1376 buck
[i
].mutex_
.init("Bucket");
1381 DbRetVal
DatabaseManagerImpl::dropIndex(const char *name
)
1383 return dropIndexInt(name
, true);
1386 DbRetVal
DatabaseManagerImpl::dropIndexInt(const char *name
, bool takeLock
)
1389 void *chunk
= NULL
, *hchunk
= NULL
;
1393 rv
= systemDatabase_
->getXCheckpointMutex();
1396 printError(ErrSysInternal
, "Unable to get database mutex");
1397 return ErrSysInternal
;
1401 //remove the entry in INDEX
1402 CatalogTableINDEX
cIndex(systemDatabase_
);
1403 rv
= cIndex
.remove(name
, chunk
, hchunk
, tptr
);
1406 if (takeLock
) systemDatabase_
->releaseCheckpointMutex();
1407 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
1408 return ErrSysInternal
;
1410 printDebug(DM_Database
, "Removing from INDEX %s",name
);
1411 //remove the entries in the INDEXFIELD table
1412 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1413 rv
= cIndexField
.remove(tptr
);
1416 if (takeLock
) systemDatabase_
->releaseCheckpointMutex();
1417 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
1418 return ErrSysInternal
;
1420 printDebug(DM_Database
, "Removing from INDEXFIELD %s",name
);
1422 //delete the index chunk
1423 CINDEX
*iptr
= (CINDEX
*)tptr
;
1424 rv
= deleteUserChunk((Chunk
*)chunk
);
1427 if (takeLock
) systemDatabase_
->releaseCheckpointMutex();
1428 printError(ErrSysInternal
, "Unable to delete the index chunk");
1429 return ErrSysInternal
;
1431 //delete the index hash node chunk
1432 if (iptr
->indexType_
== hashIndex
) {
1433 rv
= deleteUserChunk((Chunk
*)hchunk
);
1436 if (takeLock
) systemDatabase_
->releaseCheckpointMutex();
1437 printError(ErrSysInternal
, "Unable to delete the index hash node chunk");
1438 return ErrSysInternal
;
1441 if (takeLock
) systemDatabase_
->releaseCheckpointMutex();
1443 //TODO::If tuples present in this table, then
1444 //free all hash index nodes for this table.
1445 //free all nodes in list of all buckets
1448 printDebug(DM_Database
, "Dropped hash index %s",name
);
1449 logFinest(Conf::logger
, "Deleted Index %s", name
);
1452 DbRetVal
DatabaseManagerImpl::createForeignKey(char *fKName
,ForeignKeyInfo
*info
)
1455 int totFkFlds
= info
->fkFldList
.size();
1456 int totPkFlds
= info
->pkFldList
.size();
1457 if (totFkFlds
==0 && totPkFlds
==0) {
1458 printError(ErrBadCall
, "No Field name specified");
1463 void *vcchunk
= NULL
;
1464 rv
= systemDatabase_
->getXCheckpointMutex();
1467 printError(ErrSysInternal
, "Unable to get database mutex");
1468 return ErrSysInternal
;
1470 CatalogTableTABLE
cTable(systemDatabase_
);
1471 cTable
.getChunkAndTblPtr(info
->fkTableName
, chunk
, tptr
, vcchunk
);
1474 systemDatabase_
->releaseCheckpointMutex();
1475 printError(ErrNotExists
, "Table does not exist %s", info
->fkTableName
);
1476 return ErrNotExists
;
1478 char **fptr
= new char* [totFkFlds
];
1479 CatalogTableFIELD
cField(systemDatabase_
);
1480 rv
= cField
.getFieldPtrs(info
->fkFldList
, tptr
, fptr
);
1484 systemDatabase_
->releaseCheckpointMutex();
1485 if (rv
!= ErrBadCall
) {
1486 printError(ErrNotExists
, "Field does not exist");
1487 return ErrNotExists
;
1491 void *chunkPk
= NULL
;
1492 void *vcchunkPk
= NULL
;
1493 CatalogTableTABLE
c2Table(systemDatabase_
);
1494 c2Table
.getChunkAndTblPtr(info
->pkTableName
, chunkPk
, tPkptr
, vcchunkPk
);
1497 systemDatabase_
->releaseCheckpointMutex();
1498 printError(ErrNotExists
, "Table does not exist %s", info
->pkTableName
);
1499 return ErrNotExists
;
1501 char **fPkptr
= new char* [totPkFlds
];
1502 CatalogTableFIELD
c2Field(systemDatabase_
);
1503 rv
= c2Field
.getFieldPtrs(info
->pkFldList
, tPkptr
, fPkptr
);
1508 systemDatabase_
->releaseCheckpointMutex();
1509 if (rv
!= ErrBadCall
) {
1510 printError(ErrNotExists
, "Field does not exist");
1511 return ErrNotExists
;
1514 //Create New chunkdatanode
1515 CatalogTableFK
cFK(systemDatabase_
);
1516 rv
= cFK
.insert(fKName
, tptr
, tPkptr
);//TODO
1521 systemDatabase_
->releaseCheckpointMutex();
1522 printError(ErrSysInternal
, "Catalog table updation failed in CFK table");
1523 return ErrSysInternal
;
1526 CatalogTableFKFIELD
cFKField(systemDatabase_
);
1527 rv
= cFKField
.insert(fKName
,fptr
,fPkptr
,totFkFlds
);
1533 systemDatabase_
->releaseCheckpointMutex();
1534 printError(ErrSysInternal
, "Catalog table updation failed in CFKFIELD table");
1535 return ErrSysInternal
;
1537 systemDatabase_
->releaseCheckpointMutex();
1542 DbRetVal
DatabaseManagerImpl::dropForeignKey(void *tptr
,bool trylock
)
1546 rv
= systemDatabase_
->getXCheckpointMutex();
1549 printError(ErrSysInternal
, "Unable to get database mutex");
1550 return ErrSysInternal
;
1554 CatalogTableFK
cFK(systemDatabase_
);
1555 int total
= cFK
.getNoOfPkTable(tptr
);
1556 //printDebug(DM_TEST,"total fk chunk %d",total);
1557 for (int i
=0;i
< total
; i
++)
1559 fkChunk
= cFK
.getFkCTable(tptr
);
1563 systemDatabase_
->releaseCheckpointMutex();
1565 printError(ErrSysInternal
, "Catalog table not finds CFKFIELD table");
1566 return ErrSysInternal
;
1568 CatalogTableFKFIELD
cFKField(systemDatabase_
);
1569 rv
= cFKField
.remove(fkChunk
);
1573 systemDatabase_
->releaseCheckpointMutex();
1575 printError(ErrSysInternal
, "Catalog table updation failed in CFKFIELD table");
1576 return ErrSysInternal
;
1578 rv
=cFK
.remove(fkChunk
);
1582 systemDatabase_
->releaseCheckpointMutex();
1584 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
1585 return ErrSysInternal
;
1589 systemDatabase_
->releaseCheckpointMutex();
1594 void DatabaseManagerImpl::printTreeIndexNodeInfo(char *name
, bool flag
)
1596 CatalogTableINDEX
cIndex(systemDatabase_
);
1598 void *chunk
= NULL
, *hchunk
= NULL
;
1600 rv
= cIndex
.get(name
, chunk
, hchunk
, tptr
);
1601 if (OK
!= rv
) return;
1602 IndexType iType
= CatalogTableINDEX::getType(tptr
);
1603 if (treeIndex
!= iType
)
1605 printf("%s is not a tree index\n ");
1608 Chunk
*ch
= (Chunk
*) chunk
;
1609 if(flag
){ if(hchunk
)((TreeNode
*) hchunk
)->displayAll(); }
1611 int offset
= CatalogTableINDEX::getOffsetOfFirstField(tptr
);
1612 //if(typeInt != offset) { printf("%s is not on Integer Type Field. To see info Index should be on integer type field. \n "); return;}
1613 if(hchunk
) ((TreeNode
*) hchunk
)->displayAll(offset
);
1617 DbRetVal
DatabaseManagerImpl::printIndexInfo(char *name
)
1619 CatalogTableINDEX
cIndex(systemDatabase_
);
1621 void *chunk
= NULL
, *hchunk
= NULL
;
1623 rv
= cIndex
.get(name
, chunk
, hchunk
, tptr
);
1624 if (OK
!= rv
) return rv
;
1625 printf("<IndexName> %s </IndexName>\n", name
);
1626 printf("<Unique> %d </Unique>\n", CatalogTableINDEX::getUnique(tptr
));
1627 IndexType iType
= CatalogTableINDEX::getType(tptr
);
1628 if(hashIndex
== iType
)
1629 printf("<Type> Hash Index </Type>\n");
1630 else if (treeIndex
== iType
)
1631 printf("<Type> Tree Index </Type>\n");
1633 printf("<Type> Unknown Index </Type>\n");
1635 Chunk
*ch
= (Chunk
*) chunk
;
1636 printf("<HashBucket>\n");
1637 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1638 printf(" <TotalBuckets> %d </TotalBuckets> \n", CatalogTableINDEX::getNoOfBuckets(tptr
));
1639 printf("</HashBucket>\n");
1640 if(treeIndex
!= iType
){
1641 ch
= (Chunk
*) hchunk
;
1642 printf("<IndexNodes>\n");
1643 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1644 printf(" <TotalNodes> %d </TotalNodes>\n", ch
->getTotalDataNodes());
1645 printf("<IndexNodes>\n");
1647 printf("<IndexNodes>\n");
1648 printf(" <TotalNodes> %d </TotalNodes>\n", ch
->getTotalDataNodes());
1650 printf(" <TotalElements> %lld </TotalElements>\n",((TreeNode
*) hchunk
)->getTotalElements());
1652 printf(" <TotalElements> 0 </TotalElements>\n");
1653 printf("<IndexNodes>\n");
1658 DbRetVal
DatabaseManagerImpl::registerThread()
1663 printError(ErrAlready
, "Process already registered\n");
1666 pMgr_
= new ProcessManager();
1667 rv
= pMgr_
->registerThread();
1669 procSlot
= pMgr_
->getProcSlot();
1670 systemDatabase_
->setProcSlot(procSlot
);
1671 printDebug(DM_Process
, "Process registed with slot %d\n", procSlot
);
1676 DbRetVal
DatabaseManagerImpl::deregisterThread()
1681 rv
= pMgr_
->deregisterThread(procSlot
);
1688 bool DatabaseManagerImpl::isAnyOneRegistered()
1690 if (pMgr_
!= NULL
) return pMgr_
->isAnyOneRegistered();
1695 void DatabaseManagerImpl::printUsageStatistics()
1697 pMgr_
->printUsageStatistics();
1698 tMgr_
->printUsageStatistics();
1699 lMgr_
->printUsageStatistics();
1702 void DatabaseManagerImpl::printDebugLockInfo()
1704 lMgr_
->printDebugInfo();
1707 void DatabaseManagerImpl::printDebugTransInfo()
1709 tMgr_
->printDebugInfo(systemDatabase_
);
1711 void DatabaseManagerImpl::printDebugProcInfo()
1713 pMgr_
->printDebugInfo();
1715 void DatabaseManagerImpl::printDebugChunkInfo()
1717 printf("<NotYetImplemented> </NotYetImplemented>\n");
1719 ChunkIterator
DatabaseManagerImpl::getSystemTableIterator(CatalogTableID id
)
1721 Chunk
*fChunk
= systemDatabase_
->getSystemDatabaseChunk(id
);
1722 return fChunk
->getIterator();
1725 Chunk
* DatabaseManagerImpl::getSystemTableChunk(CatalogTableID id
)
1727 return systemDatabase_
->getSystemDatabaseChunk(id
);
1730 int DatabaseManagerImpl::getNoOfPagesForTable(char *tblName
)
1732 Table
*tbl
= openTable(tblName
);
1734 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
1737 TableImpl
*tb
= (TableImpl
*) tbl
;
1739 if (tb
->numTuples()) pages
= tb
->pagesUsed();
1744 DbRetVal
DatabaseManagerImpl::loadRecords(char *tblName
, char *buffer
)
1746 // buffer should be as big as the no of pages occupied by the records
1747 Table
*tbl
= openTable(tblName
);
1749 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
1750 return ErrSysInternal
;
1752 TableImpl
*tb
= (TableImpl
*) tbl
;
1753 char *bufIter
= buffer
;
1754 int pages
= *(int *) bufIter
; bufIter
+= sizeof(int);
1755 Page
*firstPage
= ((Chunk
*)(tb
->chunkPtr_
))->getFirstPage();
1756 PageInfo
*pi
= (PageInfo
*) firstPage
;
1757 memcpy(bufIter
, pi
, PAGE_SIZE
);
1758 bufIter
+= PAGE_SIZE
;
1759 for (int i
= 0; i
< pages
- 1; i
++) {
1760 Page
*nPage
= pi
->nextPage_
;
1761 memcpy(bufIter
, nPage
, PAGE_SIZE
);
1762 bufIter
+= PAGE_SIZE
;
1763 pi
= (PageInfo
*) nPage
;
1769 DbRetVal
DatabaseManagerImpl::pasteRecords(char *tblName
, void *buffer
)
1771 // buffer should be as big as the no of pages occupied by the records
1772 Table
*tbl
= openTable(tblName
);
1774 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
1775 return ErrSysInternal
;
1777 TableImpl
*tb
= (TableImpl
*) tbl
;
1778 Database
*db
= tb
->getDB();
1779 char *bufIter
= (char *) buffer
;
1780 int pages
= *(int *) bufIter
;
1781 bufIter
+= sizeof(int);
1783 Page
*firstPage
= ((Chunk
*)(tb
->chunkPtr_
))->getFirstPage();
1784 PageInfo
*pi
= (PageInfo
*) firstPage
;
1785 memcpy(pi
, bufIter
, PAGE_SIZE
);
1786 bufIter
+= PAGE_SIZE
;
1787 while (--pages
!= 0) {
1788 //get a new page allocated
1789 Page
*newPage
= db
->getFreePage();
1790 memcpy(newPage
, bufIter
, PAGE_SIZE
);
1791 pi
->nextPage_
= newPage
;
1792 pi
= (PageInfo
*) newPage
;
1794 // initialize chunk details and pageInfo
1795 ((Chunk
*)tb
->chunkPtr_
)->curPage_
= pi
;
1800 void DatabaseManagerImpl::setCanTakeCheckPoint(bool ctcp
)
1801 { systemDatabase_
->setCanTakeCheckPoint(ctcp
); }
1803 bool DatabaseManagerImpl::getCanTakeCheckPoint()
1804 { return systemDatabase_
->getCanTakeCheckPoint(); }
1806 DbRetVal
DatabaseManagerImpl::checkPoint()
1808 if (!systemDatabase_
->getCanTakeCheckPoint()) {
1809 printf("Load / Cache / Replication process might be running. CheckPoint not taken\n");
1810 return ErrLoadingOn
;
1812 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
1814 printError(rv
, "Unable to get checkpoint mutex");
1815 return ErrLockTimeOut
;
1817 if (tMgr_
&& !tMgr_
->isTransactionConsistent(systemDatabase_
)) {
1818 printf("not in transaction consistent point\n");
1819 systemDatabase_
->releaseCheckpointMutex();
1820 return ErrLockTimeOut
;
1822 rv
= writeSchemaFile();
1824 printError(ErrSysInternal
, "checkpoint error");
1826 rv
= db()->checkPoint();
1827 systemDatabase_
->releaseCheckpointMutex();
1831 DbRetVal
DatabaseManagerImpl::writeSchemaFile()
1837 char schFile
[MAX_FILE_LEN
];
1838 char mapFile
[MAX_FILE_LEN
];
1839 sprintf(schFile
, "%s/db.chkpt.schema1", Conf::config
.getDbFile());
1840 sprintf(mapFile
, "%s/db.chkpt.map1", Conf::config
.getDbFile());
1841 fp
= fopen(schFile
, "r");
1844 int ret
= unlink(schFile
);
1846 printError(ErrOS
, "checkpoint: delete schema file failed");
1850 fp
= fopen(schFile
, "w+");
1852 printError(ErrOS
, "Unable to create schema file for chkpt.");
1855 fp1
= fopen(mapFile
, "r");
1858 int ret
= unlink(mapFile
);
1860 printError(ErrOS
, "checkpoint: delete schema file failed");
1864 fd
= open(mapFile
, O_WRONLY
|O_CREAT
, 0644);
1866 printError(ErrOS
, "checkpoint: Unable to create map file.");
1869 List tableList
= getAllTableNames();
1870 ListIterator iter
= tableList
.getIterator();
1871 Identifier
*elem
= NULL
;
1873 while (iter
.hasElement()) {
1874 elem
= (Identifier
*) iter
.nextElement();
1875 // if (TableConf::config.isTableCached(elem->name) == OK) continue;
1876 fprintf(fp
, "CREATE TABLE %s (", elem
->name
);
1877 Table
*table
= openTable(elem
->name
);
1878 if (NULL
== table
) {
1879 printError(ErrSysInternal
, "Unable to open table %s", elem
->name
);
1880 return ErrSysInternal
;
1882 void *chunk
= NULL
; void *tptr
= NULL
; void *vcchunk
= NULL
;
1883 CatalogTableTABLE
cTable(systemDatabase_
);
1884 rv
= cTable
.getChunkAndTblPtr(elem
->name
, chunk
, tptr
, vcchunk
);
1886 strcpy(obj
.name
, elem
->name
);
1888 obj
.bucketChunk
= NULL
;
1889 obj
.firstPage
= ((Chunk
*)chunk
)->getFirstPage();
1890 obj
.curPage
= ((Chunk
*)chunk
)->getCurrentPage();
1892 write(fd
, buf
, sizeof(obj
));
1893 FieldInfo
*info
= new FieldInfo();
1894 List fNameList
= table
->getFieldNameList();
1895 ListIterator fNameIter
= fNameList
.getIterator();
1897 bool firstField
=true;
1898 char fieldName
[IDENTIFIER_LENGTH
];
1899 while (fNameIter
.hasElement()) {
1900 elem
= (Identifier
*) fNameIter
.nextElement();
1901 Table::getFieldNameAlone(elem
->name
, fieldName
);
1902 rv
= table
->getFieldInfo(elem
->name
, info
);
1904 printf("unable to retrive info for table %s\n", elem
->name
);
1907 fprintf(fp
, "%s %s ", fieldName
, AllDataType::getSQLString(info
->type
));
1910 fprintf(fp
, ", %s %s ", fieldName
, AllDataType::getSQLString(info
->type
));
1911 if (info
->type
== typeString
|| info
->type
== typeVarchar
||
1912 info
->type
== typeBinary
)
1913 fprintf(fp
, "(%d)",info
->length
);
1914 if (info
->isNull
) fprintf(fp
, " NOT NULL ");
1915 if (info
->isDefault
) fprintf(fp
, " DEFAULT '%s' ", info
->defaultValueBuf
);
1916 if (info
->isAutoIncrement
) fprintf(fp
, " AUTO_INCREMENT ");
1919 while (fNameIter
.hasElement())
1920 delete ((FieldName
*) fNameIter
.nextElement());
1923 fprintf(fp
, ");\n");
1924 table
->printSQLIndexString(fp
, fd
);
1928 ListIterator tIter
= tableList
.getIterator();
1930 while (tIter
.hasElement())
1931 delete ((FieldName
*) tIter
.nextElement());
1939 DbRetVal
DatabaseManagerImpl::recover()
1942 rv
= sysDb()->recoverSystemDB();
1943 if (rv
!= OK
) return rv
;
1944 if (!Conf::config
.useMmap())rv
= db()->recoverUserDB();
1948 void DatabaseManagerImpl::sendSignal(int signal
)
1950 ThreadInfo
* tInfo
= sysDb()->getThreadInfo(0);
1951 for (int i
=0; i
< Conf::config
.getMaxProcs(); i
++)
1953 if (tInfo
->pid_
!=0) os::kill(tInfo
->pid_
, signal
);