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.");
88 file_desc fd
= (file_desc
)-1;
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
= os::openFile(dbMapFile
, fileOpenCreat
, 0660);
152 if ((file_desc
) -1 == fd
) {
153 printError(ErrOS
, "Mmap file could not be opened");
156 if(::stat(dbMapFile
, &st
) == -1) {
157 printf("Unable to retrieve the db File data\n");
159 db_
->setChkptfd((file_desc
)-1);
163 int localfd
= os::open(dbMapFile
, fileOpenCreat
,0);
167 if (st
.st_size
== 0 || st
.st_size
< size
) {
168 firstTimeServer
= true;
169 off_t flSize
= os::lseek(localfd
, size
- 1, SEEK_SET
);
172 int wSize
= os::write(localfd
, a
, 1);
176 mapAddr
= os::mmap((void *)(fixAddr
+ Conf::config
.getMaxSysDbSize()), size
,
177 mapProtRead
| mapProtWrite
, mapFixed
| mapShared
, fd
, 0);
178 rtnAddr
= (caddr_t
) mapAddr
;
179 printDebug(DM_Database
, "Mapped db file address = %x", mapAddr
);
181 void *shm_ptr
= NULL
;
182 if (!isMmapNeeded
|| isMmapNeeded
&& 0 == strcmp(name
, SYSTEMDB
)) {
183 shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
184 rtnAddr
= (caddr_t
) shm_ptr
;
185 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
187 printError(ErrOS
, "Shared memory attach returned -ve value %d", rtnAddr
);
190 # if (defined MMDB && defined EMBED)
191 if (0 == strcmp(name
, SYSTEMDB
)) ProcessManager::sysAddr
= rtnAddr
;
192 else ProcessManager::usrAddr
= rtnAddr
;
195 db_
= new Database();
196 printDebug(DM_Database
, "Creating database:%s",name
);
198 /*if (!isMmapNeeded || isMmapNeeded && 0 == strcmp(name, SYSTEMDB)) {
199 memset(shm_ptr, 0, size );
202 //TODO:for user database do not have transtable and processtable mutex
203 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
204 db_
->setDatabaseID(1);
206 db_
->setMaxSize(size
);
207 db_
->setNoOfChunks(0);
208 db_
->initAllocDatabaseMutex();
209 db_
->initTransTableMutex();
210 db_
->initCheckpointMutex();
211 db_
->initProcessTableMutex();
212 db_
->initPrepareStmtMutex();
213 db_
->setUniqueChunkID(100);
214 //compute the first page after book keeping information
215 size_t offset
= os::alignLong(sizeof (DatabaseMetaData
));
216 //Only for system db chunk array, trans array and proc array will be there
217 if (0 == strcmp(name
, SYSTEMDB
))
219 db_
->setCanTakeCheckPoint(true);
220 offset
= offset
+ os::alignLong( MAX_CHUNKS
* sizeof (Chunk
));
221 offset
= offset
+ os::alignLong( Conf::config
.getMaxProcs() * sizeof(Transaction
));
222 offset
= offset
+ os::alignLong( Conf::config
.getMaxProcs() * sizeof(ThreadInfo
));
224 int multiple
= os::floor(offset
/ PAGE_SIZE
);
225 char *curPage
= (((char*)rtnAddr
) + ((multiple
+ 1) * PAGE_SIZE
));
227 db_
->setCurrentPage(curPage
);
228 db_
->setFirstPage(curPage
);
230 if (0 == strcmp(name
, SYSTEMDB
)) return OK
;
232 /*Allocate new chunk to store hash index nodes
233 Chunk *chunkInfo = createUserChunk(sizeof(IndexNode));
234 if (NULL == chunkInfo)
236 printError(ErrSysInternal, "Failed to allocate hash index nodes chunk");
237 return ErrSysInternal;
239 printDebug(DM_Database, "Creating Chunk for storing Hash index nodes %x",
242 db_->setHashIndexChunk(chunkInfo);*/
246 DbRetVal
DatabaseManagerImpl::deleteDatabase(const char *name
)
248 shared_memory_id shm_id
= 0;
249 if (0 == strcmp(name
, SYSTEMDB
))
251 shm_id
= os::shm_open(Conf::config
.getSysDbKey(), 100, 0660);
252 os::shm_remove(shm_id
);
253 delete systemDatabase_
;
254 systemDatabase_
= NULL
;
256 shm_id
= os::shm_open(Conf::config
.getUserDbKey(), 100, 0660);
257 os::shm_remove(shm_id
);
264 DbRetVal
DatabaseManagerImpl::openDatabase(const char *name
)
266 bool isMmapNeeded
= Conf::config
.useMmap();
267 char dbMapFile
[1024];
268 file_desc fd
= (file_desc
)-1;
269 long size
= Conf::config
.getMaxSysDbSize();
270 char *startaddr
= (char*)Conf::config
.getMapAddress();
271 long fixAddr
= 399998976L;
272 if (0 == strcmp(name
, SYSTEMDB
))
274 if (NULL
!=systemDatabase_
)
276 printError(ErrAlready
, "System Database already open");
282 if (NULL
==systemDatabase_
)
284 printError(ErrNotOpen
, "System Database not open");
287 size
= Conf::config
.getMaxDbSize();
288 startaddr
= startaddr
+ Conf::config
.getMaxSysDbSize();
289 fixAddr
+= Conf::config
.getMaxSysDbSize();
293 printError(ErrAlready
, "User Database already open");
296 //system db should be opened before user database files
297 caddr_t rtnAddr
= (caddr_t
) NULL
;
299 shared_memory_id shm_id
= 0;
300 shared_memory_key key
= 0;
302 if (0 == strcmp(name
, SYSTEMDB
))
303 key
= Conf::config
.getSysDbKey();
305 key
= Conf::config
.getUserDbKey();
308 void *shm_ptr
= NULL
;
309 void *mapAddr
= NULL
;
310 bool firstThread
= false;
311 if ( ( ProcessManager::noThreads
== 0 && 0 == strcmp(name
, SYSTEMDB
) ||
312 ProcessManager::noThreads
== 1 && 0 != strcmp(name
, SYSTEMDB
) ) )
314 if(isMmapNeeded
&& 0 != strcmp(name
, SYSTEMDB
)){
315 //: Attach to Map File
316 int curChkptID
= Database::getCheckpointID();
317 sprintf(dbMapFile
, "%s/db.chkpt.data%d", Conf::config
.getDbFile(),
319 fd
= os::openFile(dbMapFile
, fileOpenReadWrite
, 0660);
320 if ((file_desc
)-1 == fd
) {
321 printError(ErrOS
, "Mmap file could not be opened");
324 mapAddr
= os::mmap((void *)fixAddr
, size
, mapProtRead
| mapProtWrite
,
325 mapFixed
| mapShared
, fd
, 0);
327 shm_ptr
= (caddr_t
) mapAddr
;
328 printDebug(DM_Database
, "Mapped db file address = %x", mapAddr
);
331 shm_id
= os::shm_open(key
, size
, 0660);
334 printError(ErrOS
, "Shared memory open failed");
337 shm_ptr
= os::shm_attach(shm_id
, startaddr
, SHM_RND
);
339 if (0 == strcmp(name
, SYSTEMDB
))
342 ProcessManager::sysAddr
= (char*) shm_ptr
;
346 ProcessManager::usrAddr
= (char*) shm_ptr
;
349 if (0 == strcmp(name
, SYSTEMDB
)) shm_ptr
= ProcessManager::sysAddr
;
350 else shm_ptr
= ProcessManager::usrAddr
;
354 rtnAddr
= (caddr_t
) shm_ptr
;
356 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffffffffffff)
358 printError(ErrOS
, "Shared memory attach returned -ve value %x %d", shm_ptr
, errno
);
362 if (rtnAddr
< 0 || shm_ptr
== (char*)0xffffffff)
364 printError(ErrOS
, "Shared memory attach returned -ve value %x %d", shm_ptr
, errno
);
369 db_
= new Database();
370 db_
->setMetaDataPtr((DatabaseMetaData
*)rtnAddr
);
373 if (firstThread
) ProcessManager::systemDatabase
= db_
;
375 printDebug(DM_Database
, "Opening database: %s", name
);
379 DbRetVal
DatabaseManagerImpl::closeDatabase()
384 //Database is already closed
387 printDebug(DM_Database
, "Closing database: %s",(char*)db_
->getName());
388 //check if this is the last thread to be deregistered
389 int ret
=0;// ProcessManager::mutex.getLock(-1, false);
390 //If you are not getting lock ret !=0, it means somebody else is there.
391 //he will close the database.
392 if (0 != strcmp((char*)db_
->getName(), SYSTEMDB
)) {
393 file_desc fd
= db_
->getChkptfd();
397 if (ProcessManager::noThreads
== 0 && 0 == strcmp((char*)db_
->getName(), SYSTEMDB
)
398 || ProcessManager::noThreads
== 1 && 0 != strcmp((char*)db_
->getName(), SYSTEMDB
) ) {
399 os::shm_detach((char*)db_
->getMetaDataPtr());
402 // ProcessManager::mutex.releaseLock(-1, false);
407 //Assumes that system database mutex is taken before calling this.
408 Chunk
* DatabaseManagerImpl::createUserChunk(size_t size
)
410 //Allocate new node in system database to store
411 Chunk
*chunk
= getSystemTableChunk(UserChunkTableId
);
413 void *ptr
= chunk
->allocate(systemDatabase_
, &rv
);
416 printError(rv
, "Allocation failed for User chunk catalog table");
419 Chunk
*chunkInfo
= (Chunk
*)ptr
;
420 int id
= db_
->getUniqueIDForChunk();
421 db_
->incrementChunk();
422 chunkInfo
->initMutex(id
);
423 if (0 != size
) chunkInfo
->setSize(size
);
424 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
425 chunkInfo
->curPage_
= db_
->getFreePage(chunkInfo
->allocSize_
);
427 chunkInfo
->curPage_
= db_
->getFreePage();
428 if ( NULL
== chunkInfo
->curPage_
)
430 chunkInfo
->destroyMutex();
431 chunk
->free(db_
, ptr
);
432 printError(ErrNoMemory
, "Database full: No space to allocate from database");
435 PageInfo
* firstPageInfo
= ((PageInfo
*)chunkInfo
->curPage_
);
436 if (chunkInfo
->allocSize_
> PAGE_SIZE
)
438 int multiple
= os::floor(chunkInfo
->allocSize_
/ PAGE_SIZE
);
439 int offset
= ((multiple
+ 1) * PAGE_SIZE
);
440 firstPageInfo
->setPageAsUsed(offset
);
444 firstPageInfo
->setPageAsUsed(chunkInfo
->allocSize_
);
445 char *data
= ((char*)firstPageInfo
) + sizeof(PageInfo
);
450 VarSizeInfo
*varInfo
= (VarSizeInfo
*)(((char*)firstPageInfo
) + sizeof(PageInfo
));
451 varInfo
->isUsed_
= 0;
452 varInfo
->size_
= PAGE_SIZE
- sizeof(PageInfo
) - sizeof(VarSizeInfo
);
455 chunkInfo
->firstPage_
= chunkInfo
->curPage_
;
458 chunkInfo
->setAllocType(VariableSizeAllocator
);
460 chunkInfo
->setAllocType(FixedSizeAllocator
);
462 chunkInfo
->setChunkID(id
);
463 chunkInfo
->setPageDirty(firstPageInfo
);
464 printDebug(DM_Database
, "Creating new User chunk chunkID:%d size: %d firstPage:%x",
465 -1, chunkInfo
->allocSize_
, firstPageInfo
);
470 //Assumes that system database mutex is taken before calling this.
471 DbRetVal
DatabaseManagerImpl::deleteUserChunk(Chunk
*chunk
)
473 //Go to the pages and set them to notUsed
474 Page
*page
= chunk
->firstPage_
;
475 PageInfo
* pageInfo
= ((PageInfo
*)page
);
476 //Here...sure that atleast one page will be there even no tuples
477 //are inserted.so not checking if pageInfo == NULL
478 while( pageInfo
->nextPage_
!= NULL
)
480 PageInfo
*prev
= pageInfo
;
481 pageInfo
= (PageInfo
*)(pageInfo
->nextPage_
);
482 //sets pageInfo->isUsed_ = 0 and pageInfo->hasFreeSpace_ = 0
483 //and initializes the page content to zero
484 if(NULL
== pageInfo
->nextPageAfterMerge_
){
485 os::memset(prev
, 0, PAGE_SIZE
);
486 SETBIT(prev
->flags
, IS_DIRTY
);
491 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
492 char *iter
= (char*)prev
, *end
=(char*)pageInfo
->nextPageAfterMerge_
;
493 os::memset(prev
, 0, size
);
494 //set dirty bit for all pages in merged pages
497 PageInfo
*info
= (PageInfo
*) iter
;
498 SETBIT(info
->flags
, IS_DIRTY
);
499 iter
= iter
+ PAGE_SIZE
;
502 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, prev
);
504 //The above loop wont execute for the last page
505 //and for the case where table has only one page
506 if(NULL
== pageInfo
->nextPageAfterMerge_
) {
507 os::memset(pageInfo
, 0, PAGE_SIZE
);
508 SETBIT(pageInfo
->flags
, IS_DIRTY
);
512 int size
= (char*) pageInfo
->nextPageAfterMerge_
- (char*) pageInfo
;
513 char *iter
= (char*)pageInfo
, *end
=(char*)pageInfo
->nextPageAfterMerge_
;
514 os::memset(pageInfo
, 0, size
);
515 //set dirty bit for all pages in merged pages
518 PageInfo
*info
= (PageInfo
*) iter
;
519 SETBIT(info
->flags
, IS_DIRTY
);
520 iter
= iter
+ PAGE_SIZE
;
523 printDebug(DM_Database
,"deleting user chunk:%x clearing page %x",chunk
, pageInfo
);
524 chunk
->chunkID_
= -1;
525 chunk
->allocSize_
= 0;
526 chunk
->curPage_
= NULL
;
527 chunk
->firstPage_
= NULL
;
528 chunk
->destroyMutex();
529 db_
->decrementChunk();
530 Chunk
*userChunk
= getSystemTableChunk(UserChunkTableId
);
531 userChunk
->free(systemDatabase_
,chunk
);
532 printDebug(DM_Database
,"deleting user chunk:%x",chunk
);
536 //-1 -> Unable to create chunk. No memory
537 //-2 -> Unable to update the catalog tables
538 DbRetVal
DatabaseManagerImpl::createTable(const char *name
, TableDef
&def
)
541 if (!Util::isIdentifier((char*)name
)) {
542 printError(ErrBadArg
, "Invalid character for index name");
545 int fldCount
= def
.getFieldCount();
548 printError(ErrNotExists
,"Table can't be created without Field");
552 //If total field count is within 32, then 1 integer is used to store all
553 // null information, if it is more then 1 char is used to store null
554 // information of each field
555 //This is to done to reduce cpu cycles for small tables
557 if (fldCount
<= 32) addSize
= 4; else addSize
= os::align(fldCount
);
558 size_t sizeofTuple
= os::alignLong(def
.getTupleSize()+addSize
);
559 rv
= systemDatabase_
->getXCheckpointMutex();
561 printError(rv
, "Unable to get Database mutex");
567 void *vcchunk
= NULL
;
569 //check whether table already exists
570 CatalogTableTABLE
cTable(systemDatabase_
);
571 cTable
.getChunkAndTblPtr(name
, chunk
, tptr
, vcchunk
);
574 systemDatabase_
->releaseCheckpointMutex();
575 printError(ErrAlready
, "Table %s already exists", name
);
579 //create a chunk to store the tuples
580 Chunk
*ptr
= createUserChunk(sizeofTuple
);
583 systemDatabase_
->releaseCheckpointMutex();
584 printError(ErrNoResource
, "Unable to create user chunk");
585 return ErrNoResource
;
587 printDebug(DM_Database
,"Created UserChunk:%x", ptr
);
588 ptr
->setChunkName(name
);
590 int tblID
= ((Chunk
*)ptr
)->getChunkID();
592 //check whether varchar is present in table
593 FieldIterator fiter
= def
.getFieldIterator();
594 bool isVarcharPresent
= def
.isVarcharPresentInSchema(fiter
);
596 if (isVarcharPresent
) {
597 //creat chunk to store varchar values
598 vcptr
= createUserChunk();
601 deleteUserChunk(ptr
);
602 systemDatabase_
->releaseCheckpointMutex();
603 printError(ErrNoResource
, "Unable to create user chunk for varchar");
604 return ErrNoResource
;
606 printDebug(DM_Database
,"Created UserChunk for Varchar:%x", vcptr
);
607 vcptr
->setChunkName(name
);
609 rv
= cTable
.insert(name
, tblID
, sizeofTuple
,
610 def
.getFieldCount(), ptr
, tptr
, vcptr
);
613 deleteUserChunk(ptr
);
614 if (vcptr
) deleteUserChunk(vcptr
);
615 systemDatabase_
->releaseCheckpointMutex();
616 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
617 return ErrSysInternal
;
619 printDebug(DM_Database
,"Inserted into TABLE:%s",name
);
621 FieldIterator iter
= def
.getFieldIterator();
622 CatalogTableFIELD
cField(systemDatabase_
);
623 rv
= cField
.insert(iter
, tblID
,tptr
);
626 deleteUserChunk(ptr
);
627 if (vcptr
) deleteUserChunk(vcptr
);
628 void *cptr
, *ttptr
;//Dummy as remove below needs both these OUT params
629 cTable
.remove(name
, cptr
, ttptr
);
630 systemDatabase_
->releaseCheckpointMutex();
631 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
632 return ErrSysInternal
;
634 printDebug(DM_Database
,"Inserted into FIELD:%s",name
);
635 systemDatabase_
->releaseCheckpointMutex();
636 printDebug(DM_Database
,"Table Created:%s",name
);
637 logFinest(Conf::logger
, "Table Created %s" , name
);
640 DbRetVal
DatabaseManagerImpl::renameTable(const char *oldName
,const char *newName
)
643 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
645 printError(ErrSysInternal
, "Unable to get database mutex for rename table");
646 return ErrSysInternal
;
648 CatalogTableTABLE
cTable(systemDatabase_
);
649 rv
= cTable
.renameTable(oldName
,newName
);
651 printError(ErrSysInternal
, "Unable to rename table");
652 systemDatabase_
->releaseCheckpointMutex();
653 return ErrSysInternal
;
655 systemDatabase_
->releaseCheckpointMutex();
658 DbRetVal
DatabaseManagerImpl::renameIndex(const char *oldName
,const char *newName
)
661 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
663 printError(ErrSysInternal
, "Unable to get database mutex for rename table");
664 return ErrSysInternal
;
666 CatalogTableTABLE
cTable(systemDatabase_
);
667 rv
= cTable
.renameIndex(oldName
,newName
);
669 printError(ErrSysInternal
, "Unable to rename table");
670 systemDatabase_
->releaseCheckpointMutex();
671 return ErrSysInternal
;
673 systemDatabase_
->releaseCheckpointMutex();
677 DbRetVal
DatabaseManagerImpl::renameField(const char *tableName
,const char *oldName
,const char *newName
)
679 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
681 printError(ErrSysInternal
, "Unable to get database mutex for rename table");
682 return ErrSysInternal
;
684 CatalogTableFIELD
fTable(systemDatabase_
);
685 rv
= fTable
.renameField(tableName
, oldName
, newName
);
687 printError(ErrSysInternal
, "Unable to rename field.");
688 systemDatabase_
->releaseCheckpointMutex();
689 return ErrSysInternal
;
691 systemDatabase_
->releaseCheckpointMutex();
695 //TODO::If any operation fails in between, then we may have some
696 //dangling tuples, say we have have rows in INDEX table
697 //which will not have any corresponding entries in TABLE
698 //CHANGE the sequence so that it deletes from the bottom as
699 //opposed to start from top as is written now
700 DbRetVal
DatabaseManagerImpl::dropTable(const char *name
)
704 void *vcchunk
= NULL
;
705 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
707 printError(ErrSysInternal
, "Unable to get database mutex");
708 return ErrSysInternal
;
710 //remove the entry in TABLE
711 CatalogTableTABLE
cTable(systemDatabase_
);
712 rv
= cTable
.getChunkAndTblPtr(name
, chunk
, tptr
, vcchunk
);
714 systemDatabase_
->releaseCheckpointMutex();
715 printError(ErrSysInternal
, "Table %s does not exist", name
);
716 return ErrSysInternal
;
718 CatalogTableFK
cFK(systemDatabase_
);
719 int noOfRelation
=cFK
.getNumFkTable(tptr
);
722 printError(ErrSysInternal
, "Unable to drop table due to relation exist.Drop child table...");
723 systemDatabase_
->releaseCheckpointMutex();
724 return ErrSysInternal
;
726 txnMgr()->rollback(lockMgr());
727 txnMgr()->startTransaction(lockMgr(), READ_COMMITTED
);
728 Transaction
**trans
= ProcessManager::getThreadTransAddr(systemDatabase_
->procSlot
);
729 rv
= lMgr_
->getExclusiveLock(chunk
, trans
);
732 systemDatabase_
->releaseCheckpointMutex();
733 txnMgr()->rollback(lockMgr());
734 printError(ErrLockTimeOut
, "Unable to acquire exclusive lock on the table\n");
737 rv
= cTable
.remove(name
, chunk
, tptr
);
739 systemDatabase_
->releaseCheckpointMutex();
740 txnMgr()->rollback(lockMgr());
741 printError(ErrSysInternal
, "Unable to update catalog table TABLE");
742 return ErrSysInternal
;
744 printDebug(DM_Database
,"Deleted from TABLE:%s",name
);
746 //remove the entries in the FIELD table
747 CatalogTableFIELD
cField(systemDatabase_
);
748 rv
= cField
.remove(tptr
);
750 systemDatabase_
->releaseCheckpointMutex();
751 txnMgr()->rollback(lockMgr());
752 printError(ErrSysInternal
, "Unable to update catalog table FIELD");
753 return ErrSysInternal
;
755 printDebug(DM_Database
,"Deleted from FIELD:%s",name
);
757 rv
= deleteUserChunk((Chunk
*)chunk
);
759 systemDatabase_
->releaseCheckpointMutex();
760 txnMgr()->rollback(lockMgr());
761 printError(rv
, "Unable to delete the chunk");
764 printDebug(DM_Database
,"Deleted UserChunk:%x", chunk
);
766 if (vcchunk
!= NULL
) {
767 rv
= deleteUserChunk((Chunk
*)vcchunk
);
769 systemDatabase_
->releaseCheckpointMutex();
770 txnMgr()->rollback(lockMgr());
771 printError(rv
, "Unable to delete the chunk");
774 printDebug(DM_Database
,"Deleted UserChunk for Varchar:%x", chunk
);
777 //TODO::check whether indexes are available and drop that also.
778 CatalogTableINDEX
cIndex(systemDatabase_
);
779 int noIndexes
= cIndex
.getNumIndexes(tptr
);
780 for (int i
=1 ; i
<= noIndexes
; i
++) {
781 char *idxName
= cIndex
.getIndexName(tptr
, 1);
782 dropIndexInt(idxName
, false);
784 bool isFkExist
=cFK
.isFkTable(tptr
);
787 dropForeignKey(tptr
,false);
789 systemDatabase_
->releaseCheckpointMutex();
790 printDebug(DM_Database
, "Deleted Table %s" , name
);
791 logFinest(Conf::logger
, "Deleted Table %s" , name
);
792 rv
= txnMgr()->commit(lockMgr());
795 printError(ErrLockTimeOut
, "Unable to release exclusive lock on the table\n");
801 //Return values: NULL for table not found
802 Table
* DatabaseManagerImpl::openTable(const char *name
,bool checkpkfk
)
805 //TODO::store table handles in list so that if it is
806 //not closed by the application. destructor shall close it.
807 TableImpl
*table
= new TableImpl();
809 table
->setSystemDB(systemDatabase_
);
810 table
->setLockManager(lMgr_
);
811 table
->setTrans(ProcessManager::getThreadTransAddr(systemDatabase_
->procSlot
));
813 //to store the chunk pointer of table
815 void *vcchunk
= NULL
;
817 //to store the tuple pointer of the table
820 //TODO::need to take shared lock on the table so that
821 //all ddl operation will be denied on that table
822 //which includes index creation, alter table
824 DbRetVal rv
= systemDatabase_
->getAllocDatabaseMutex();
826 printError(ErrSysInternal
, "Unable to get database mutex");
830 CatalogTableTABLE
cTable(systemDatabase_
);
831 ret
= cTable
.getChunkAndTblPtr(name
, chunk
, tptr
, vcchunk
);
834 systemDatabase_
->releaseAllocDatabaseMutex();
836 printError(ErrNotExists
, "Table not exists %s", name
);
839 CTABLE
*tTuple
= (CTABLE
*)tptr
;
840 table
->setTableInfo(tTuple
->tblName_
, tTuple
->tblID_
, tTuple
->length_
,
841 tTuple
->numFlds_
, tTuple
->numIndexes_
,
842 tTuple
->chunkPtr_
, tTuple
->varcharChunkPtr_
);
843 rv
= table
->lock(true); //take shared lock
846 printError(ErrLockTimeOut
, "Unable to acquire shared lock on the table\n");
847 systemDatabase_
->releaseAllocDatabaseMutex();
852 if (tTuple
->numFlds_
<= 32)
854 table
->isIntUsedForNULL
= true;
855 table
->iNullInfo
= 0;
856 table
->iNotNullInfo
=0;
860 table
->isIntUsedForNULL
= false;
861 int noFields
= os::align(tTuple
->numFlds_
);
862 table
->cNullInfo
= (char*) malloc(noFields
);
863 table
->cNotNullInfo
= (char*) malloc(noFields
);
864 for (int i
=0 ; i
< noFields
; i
++) table
->cNullInfo
[i
] =0;
865 for (int i
=0 ; i
< noFields
; i
++) table
->cNotNullInfo
[i
] =0;
869 //get field information from FIELD table
870 CatalogTableFIELD
cField(systemDatabase_
);
871 table
->ptrToAuto
= cField
.getFieldInfo(tptr
, table
->fldList_
);
873 //populate the notnull info
874 FieldIterator fIter
= table
->fldList_
.getIterator();
876 while (fIter
.hasElement())
878 FieldDef
*def
= fIter
.nextElement();
879 if (table
->isIntUsedForNULL
) {
880 if (def
->isNull_
) SETBIT(table
->iNotNullInfo
, fldpos
-1);
883 if (def
->isNull_
) table
->cNotNullInfo
[fldpos
-1] = 1;
888 //get the number of indexes on this table
889 //and populate the indexPtr array
890 CatalogTableINDEX
cIndex(systemDatabase_
);
891 table
->numIndexes_
= cIndex
.getNumIndexes(tptr
);
892 if (table
->numIndexes_
) {
893 table
->indexPtr_
= new char*[table
->numIndexes_
];
894 table
->idxInfo
= new IndexInfo
*[table
->numIndexes_
];
898 table
->indexPtr_
= NULL
;
900 cIndex
.getIndexPtrs(tptr
, table
->indexPtr_
);
901 for (int i
=0 ; i
< table
->numIndexes_
; i
++ )
903 HashIndexInfo
*hIdxInfo
= new HashIndexInfo();
904 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
905 cIndexField
.getFieldInfo(table
->indexPtr_
[i
], hIdxInfo
->idxFldList
);
906 ChunkIterator citer
= CatalogTableINDEX::getIterator(table
->indexPtr_
[i
]);
907 hIdxInfo
->indexPtr
= table
->indexPtr_
[i
];
908 hIdxInfo
->indType
= ((CINDEX
*)hIdxInfo
->indexPtr
)->indexType_
;
909 hIdxInfo
->noOfBuckets
= CatalogTableINDEX::getNoOfBuckets(table
->indexPtr_
[i
]);
910 FieldIterator fIter
= hIdxInfo
->idxFldList
.getIterator();
911 bool firstFld
= true;
912 while (fIter
.hasElement())
914 FieldDef
*def
= fIter
.nextElement();
917 hIdxInfo
->fldOffset
= table
->fldList_
.getFieldOffset(def
->fldName_
);
918 hIdxInfo
->type
= table
->fldList_
.getFieldType(def
->fldName_
);
919 hIdxInfo
->compLength
= table
->fldList_
.getFieldLength(def
->fldName_
);
922 hIdxInfo
->type
= typeComposite
;
923 hIdxInfo
->compLength
= hIdxInfo
->compLength
+
924 table
->fldList_
.getFieldLength(def
->fldName_
);
928 hIdxInfo
->isUnique
= CatalogTableINDEX::getUnique(table
->indexPtr_
[i
]);
929 hIdxInfo
->buckets
= (Bucket
*)citer
.nextElement();
930 table
->idxInfo
[i
] = (IndexInfo
*) hIdxInfo
;
932 systemDatabase_
->releaseAllocDatabaseMutex();
933 //Foreign key Operation
935 CatalogTableFK
cFk(systemDatabase_
);
937 table
->numFkRelation_
= cFk
.getNumFkTable(tptr
);
938 if (table
->numFkRelation_
) {
939 table
->isPkTbl
=true;//TODO:for Delete In casecade
940 totalFld
=cFk
.getNoOfFkTable(tptr
);
941 //printDebug(DM_TEST,"Total table is %d\n",totalFld);
942 char **fptr
= new char* [totalFld
];
943 cFk
.getFkTableName(tptr
,fptr
);
944 for(int count
=0; count
< totalFld
; count
++){
945 //printDebug(DM_TEST,"FK Name is %s\n",fptr[count]);
946 Table
*pkTable
=openTable(fptr
[count
],false);
947 if (pkTable
) table
->tblFkList
.append(pkTable
);
949 printError(ErrSysInternal
, "Unable to open foreign key tables");
958 char *tblName
= NULL
;
959 table
->isFkTbl
= cFk
.isFkTable(tptr
);
962 totalFld
=cFk
.getNoOfPkTable(tptr
);
963 char **fptr
= new char* [totalFld
];
964 cFk
.getPkTableName(tptr
,fptr
);
965 for(int count
=0; count
<totalFld
; count
++){
966 //printDebug(DM_TEST,"Parent Name is %s\n",fptr[count]);
967 Table
*fkTable
= openTable(fptr
[count
],false);
968 if (fkTable
) table
->tblList
.append(fkTable
);
970 printError(ErrSysInternal
, "Unable to open foreign key tables");
979 printDebug(DM_Database
,"Opening table handle name:%s chunk:%x numIndex:%d",
980 name
, chunk
, table
->numIndexes_
);
981 logFinest(Conf::logger
, "Opening Table %s" , name
);
985 List
DatabaseManagerImpl::getAllTableNames(int *retval
)
988 //to store the tuple pointer of the table
991 /*DbRetVal rv = systemDatabase_->getSCheckpointMutex();
993 printError(ErrSysInternal, "Unable to get checkpoint mutex");
994 if(retval) *retval = rv;
998 CatalogTableTABLE
cTable(systemDatabase_
);
999 List tableList
= cTable
.getTableList();
1000 //systemDatabase_->releaseCheckpointMutex();
1007 //Return values: -1 for table not found
1008 void DatabaseManagerImpl::closeTable(Table
*table
)
1010 printDebug(DM_Database
,"Closing table handle: %x", table
);
1011 if (NULL
== table
) return;
1013 /* TableImpl *fkTbl =NULL;
1014 ListIterator tblIter = ((TableImpl*)table)->tblList.getIterator();
1016 while (tblIter.hasElement()){
1017 fkTbl = (TableImpl *) tblIter.nextElement();
1020 ((TableImpl*)table)->tblList.reset();
1021 tblIter = ((TableImpl*)table)->tblFkList.getIterator();
1023 while (tblIter.hasElement()){
1024 fkTbl = (TableImpl *) tblIter.nextElement();
1027 ((TableImpl*)table)->tblFkList.reset();*/
1028 if (table
) delete table
; table
= NULL
;
1029 logFinest(Conf::logger
, "Closing Table");
1032 DbRetVal
DatabaseManagerImpl::createIndex(const char *indName
, IndexInitInfo
*info
)
1035 if (!info
->isUnique
&& info
->isPrimary
)
1037 printError(ErrBadCall
, "Primary key cannot be non unique\n");
1040 if (!Util::isIdentifier((char*)indName
)) {
1041 printError(ErrBadArg
, "Invalid character for index name");
1045 if (info
->indType
== hashIndex
)
1047 //Assumes info is of type HashIndexInitInfo
1048 HashIndexInitInfo
*hInfo
= (HashIndexInitInfo
*) info
;
1049 rv
= createHashIndex(indName
, info
->tableName
, info
->list
, hInfo
->bucketSize
,
1050 info
->isUnique
, info
->isPrimary
);
1052 else if (info
->indType
== treeIndex
)
1054 HashIndexInitInfo
*hInfo
= (HashIndexInitInfo
*) info
;
1055 rv
= createTreeIndex(indName
, info
->tableName
, info
->list
,
1056 hInfo
->bucketSize
, info
->isUnique
, info
->isPrimary
);
1058 else if (info
->indType
== trieIndex
)
1060 HashIndexInitInfo
*hInfo
= (HashIndexInitInfo
*) info
;
1061 rv
= createTrieIndex(indName
, info
->tableName
, info
->list
,
1062 info
->isUnique
, info
->isPrimary
);
1065 printError(ErrBadCall
, "Index type not supported\n");
1072 //-1 -> Table does not exists
1073 //-2 -> Field does not exists
1074 //-3 -> bucketSize is not valid
1075 DbRetVal
DatabaseManagerImpl::createHashIndex(const char *indName
, const char *tblName
,
1076 FieldNameList
&fldList
, int bucketSize
, bool isUnique
, bool isPrimary
)
1078 //validate the bucket size
1079 if (bucketSize
< 100 || bucketSize
> 200000)
1081 printError(ErrBadRange
, "Index Bucket size %d not in range 100-200000",
1085 int totFlds
= fldList
.size();
1088 printError(ErrBadCall
, "No Field name specified");
1093 void *vcchunk
= NULL
;
1094 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
1097 printError(ErrSysInternal
, "Unable to get database mutex");
1098 return ErrSysInternal
;
1101 //check whether table exists
1102 CatalogTableTABLE
cTable(systemDatabase_
);
1103 cTable
.getChunkAndTblPtr(tblName
, chunk
, tptr
, vcchunk
);
1106 systemDatabase_
->releaseCheckpointMutex();
1107 printError(ErrNotExists
, "Table does not exist %s", tblName
);
1108 return ErrNotExists
;
1111 //check whether field exists
1112 char **fptr
= new char* [totFlds
];
1113 CatalogTableFIELD
cField(systemDatabase_
);
1114 rv
= cField
.getFieldPtrs(fldList
, tptr
, fptr
);
1118 systemDatabase_
->releaseCheckpointMutex();
1119 //TODO::check test cases of dbapi/Index, they give wrong results
1120 //if (rv == ErrBadCall) {
1121 //// if (isPrimary) printError(ErrBadCall, "Field can have NULL values");
1123 //printError(ErrNotExists, "Field does not exist");
1125 //return ErrBadCall;
1126 if (rv
!= ErrBadCall
) {
1127 printError(ErrNotExists
, "Field does not exist");
1128 return ErrNotExists
;
1131 for (int i
=0; i
<totFlds
; i
++)
1133 CFIELD
* fInfo
= (CFIELD
*)fptr
[i
];
1134 if (fInfo
->type_
== typeFloat
|| fInfo
->type_
== typeDouble
|| fInfo
->type_
== typeTimeStamp
)
1136 printError(ErrBadArg
, "HashIndex cannot be created for float or double or timestamp type");
1138 systemDatabase_
->releaseCheckpointMutex();
1141 if (!fInfo
->isNull_
&& isPrimary
)
1143 printError(ErrBadArg
, "Primary Index cannot be created on field without NOTNULL constraint");
1145 systemDatabase_
->releaseCheckpointMutex();
1148 if(isPrimary
){fInfo
->isPrimary_
=true;fInfo
->isUnique_
=true;}
1149 if(isUnique
){fInfo
->isUnique_
=true;}
1151 //create chunk to store the meta data of the index created
1152 //for latches and bucket pointers
1153 printDebug(DM_HashIndex
, "Creating chunk for storing hash buckets of size %d\n",
1154 bucketSize
* sizeof(Bucket
));
1155 Chunk
* chunkInfo
= createUserChunk(bucketSize
* sizeof(Bucket
));
1156 if (NULL
== chunkInfo
)
1159 systemDatabase_
->releaseCheckpointMutex();
1160 printError(ErrSysInternal
, "Unable to create chunk");
1161 return ErrSysInternal
;
1163 chunkInfo
->setChunkName(indName
);
1164 //create memory for holding the bucket pointers
1165 void *buckets
= chunkInfo
->allocate(db_
, &rv
);
1166 if (NULL
== buckets
)
1169 deleteUserChunk(chunkInfo
);
1170 systemDatabase_
->releaseCheckpointMutex();
1171 printError(rv
, "Unable to allocate memory for bucket");
1174 Bucket
*buck
= (Bucket
*) buckets
;
1175 initHashBuckets(buck
, bucketSize
);
1177 //create chunk to store the hash index nodes
1178 Chunk
* hChunk
= createUserChunk(sizeof(IndexNode
));
1182 deleteUserChunk(chunkInfo
);
1183 systemDatabase_
->releaseCheckpointMutex();
1184 printError(ErrSysInternal
, "Unable to create chunk for storing hash index nodes");
1185 return ErrSysInternal
;
1188 hChunk
->setChunkName(indName
);
1190 void *tupleptr
= NULL
;
1191 CatalogTableINDEX
cIndex(systemDatabase_
);
1192 rv
= cIndex
.insert(indName
, tptr
, fldList
.size(), isUnique
,
1193 chunkInfo
, bucketSize
, hChunk
, tupleptr
);
1197 deleteUserChunk(hChunk
);
1198 deleteUserChunk(chunkInfo
);
1199 systemDatabase_
->releaseCheckpointMutex();
1200 printError(ErrSysInternal
, "Catalog table updation failed in INDEX table");
1201 return ErrSysInternal
;
1203 //add rows to INDEXFIELD
1204 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1205 rv
= cIndexField
.insert(fldList
, tupleptr
, tptr
, fptr
);
1210 cIndex
.remove(indName
, (void *&)chunkInfo
, (void *&)hChunk
, (void *&)tupleptr
);
1211 deleteUserChunk(hChunk
);
1212 deleteUserChunk(chunkInfo
);
1213 systemDatabase_
->releaseCheckpointMutex();
1214 printError(ErrSysInternal
, "Catalog table updation failed in INDEXFIELD table");
1215 return ErrSysInternal
;
1218 systemDatabase_
->releaseCheckpointMutex();
1220 //TODO:: Take table lock
1222 // Following code is written by Kishor Amballi
1223 TableImpl
*tbl
= (TableImpl
*) openTable(tblName
);
1225 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
1226 return ErrSysInternal
;
1228 if (! tbl
->numTuples()) {
1229 printDebug(DM_Database
, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName
, tblName
, buckets
);
1230 logFinest(Conf::logger
, "Creating HashIndex %s on %s with bucket size %d", indName
, tblName
, buckets
);
1234 HashIndexInfo
*indxInfo
= NULL
;
1236 for (i
= 0; i
< tbl
->numIndexes_
; i
++) {
1237 if(((HashIndexInfo
*)tbl
->idxInfo
[i
])->indexPtr
== tupleptr
) {
1238 indxInfo
= (HashIndexInfo
*) tbl
->idxInfo
[i
];
1242 void *recPtr
= NULL
;
1243 ChunkIterator chIter
= ((Chunk
*)chunk
)->getIterator();
1244 tbl
->setLoading(true);
1245 while ((recPtr
= chIter
.nextElement()) != NULL
) {
1246 rv
= tbl
->insertIndexNode(*tbl
->trans
, tupleptr
, indxInfo
, recPtr
);
1247 if (rv
== ErrUnique
) {
1254 printDebug(DM_Database
, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName
, tblName
, buckets
);
1255 logFinest(Conf::logger
, "Creating HashIndex %s on %s with bucket size %d", indName
, tblName
, buckets
);
1260 DbRetVal
DatabaseManagerImpl::createTreeIndex(const char *indName
, const char *tblName
,
1261 FieldNameList
&fldList
, int nodeSize
, bool isUnique
, bool isPrimary
)
1263 if (nodeSize
< 20 || nodeSize
> 20000)
1265 printError(ErrBadRange
,"Tree Index Node size %d not in range 20-20000",
1269 int totFlds
= fldList
.size();
1271 printError(ErrBadCall
, "No Field name specified");
1273 }else if (totFlds
!= 1) {
1274 printError(ErrBadCall
, "Composite index not supported for Tree");
1279 void *vcchunk
= NULL
;
1280 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
1283 printError(ErrSysInternal
, "Unable to get database mutex");
1284 return ErrSysInternal
;
1286 //check whether table exists
1288 CatalogTableTABLE
cTable(systemDatabase_
);
1289 cTable
.getChunkAndTblPtr(tblName
, chunk
, tptr
, vcchunk
);
1292 systemDatabase_
->releaseCheckpointMutex();
1293 printError(ErrNotExists
, "Table does not exist %s", tblName
);
1294 return ErrNotExists
;
1296 char **fptr
= new char* [totFlds
];
1297 CatalogTableFIELD
cField(systemDatabase_
);
1298 rv
= cField
.getFieldPtrs(fldList
, tptr
, fptr
);
1302 systemDatabase_
->releaseCheckpointMutex();
1303 if (rv
!= ErrBadCall
) {
1304 printError(ErrNotExists
, "Field does not exist");
1305 return ErrNotExists
;
1308 for (int i
=0; i
<totFlds
; i
++)
1310 CFIELD
* fInfo
= (CFIELD
*)fptr
[i
];
1311 if (!fInfo
->isNull_
&& isPrimary
)
1313 printError(ErrBadArg
, "Primary Index cannot be created on field without NOTNULL constraint");
1315 systemDatabase_
->releaseCheckpointMutex();
1318 if (fInfo
->type_
== typeVarchar
)
1320 printError(ErrBadArg
, "Tree Index not supported for varchar type. Use char data type instead.");
1322 systemDatabase_
->releaseCheckpointMutex();
1327 int chunkSize
= sizeof(TreeNode
)+(nodeSize
* sizeof(void*));
1328 printDebug(DM_HashIndex
, "Creating chunk for storing tree nodes of size %d\n", chunkSize
);
1330 Chunk
* chunkInfo
= createUserChunk(chunkSize
);
1331 if (NULL
== chunkInfo
)
1334 systemDatabase_
->releaseCheckpointMutex();
1335 printError(ErrSysInternal
, "Unable to create chunk");
1336 return ErrSysInternal
;
1340 void *tupleptr
= NULL
;
1342 CatalogTableINDEX
cIndex(systemDatabase_
);
1343 rv
= cIndex
.insert(indName
, tptr
, fldList
.size(), isUnique
,
1344 chunkInfo
, nodeSize
, NULL
, tupleptr
);
1348 deleteUserChunk(chunkInfo
);
1349 systemDatabase_
->releaseCheckpointMutex();
1350 printError(ErrSysInternal
, "Catalog table updation failed in INDEX table");
1351 return ErrSysInternal
;
1353 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1354 rv
= cIndexField
.insert(fldList
, tupleptr
, tptr
, fptr
);
1359 void *hChunk
= NULL
;
1360 cIndex
.remove(indName
, (void *&)chunkInfo
, (void *&)hChunk
, (void *&)tupleptr
);
1361 deleteUserChunk(chunkInfo
);
1362 systemDatabase_
->releaseCheckpointMutex();
1363 printError(ErrSysInternal
, "Catalog table updation failed in INDEXFIELD table");
1364 return ErrSysInternal
;
1367 systemDatabase_
->releaseCheckpointMutex();
1368 //TODO::if tuples already present in this table, then create tree index '
1370 TableImpl
*tbl
= (TableImpl
*) openTable(tblName
);
1372 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
1373 return ErrSysInternal
;
1375 if (! tbl
->numTuples()) {
1376 printDebug(DM_Database
, "Creating Tree Index Name:%s tblname:%s node size:%x",indName
, tblName
, nodeSize
);
1377 logFinest(Conf::logger
, "Creating TreeIndex %s on %s with node size %d",indName
, tblName
, nodeSize
);
1381 HashIndexInfo
*indxInfo
= NULL
;
1383 for (i
= 0; i
< tbl
->numIndexes_
; i
++) {
1384 if(((HashIndexInfo
*)tbl
->idxInfo
[i
])->indexPtr
== tupleptr
) {
1385 indxInfo
= (HashIndexInfo
*) tbl
->idxInfo
[i
];
1389 void *recPtr
= NULL
;
1390 ChunkIterator chIter
= ((Chunk
*)chunk
)->getIterator();
1391 tbl
->setLoading(true);
1392 while ((recPtr
= chIter
.nextElement()) != NULL
) {
1393 rv
= tbl
->insertIndexNode(*tbl
->trans
, tupleptr
, indxInfo
, recPtr
);
1394 if (rv
== ErrUnique
) {
1401 printDebug(DM_Database
, "Creating Tree Index Name:%s tblname:%s node size:%x",
1402 indName
, tblName
, nodeSize
);
1403 logFinest(Conf::logger
, "Creating TreeIndex %s on %s with node size %d",
1404 indName
, tblName
, nodeSize
);
1408 DbRetVal
DatabaseManagerImpl::createTrieIndex(const char *indName
, const char *tblName
,
1409 FieldNameList
&fldList
, bool isUnique
, bool isPrimary
)
1411 int totFlds
= fldList
.size();
1413 char **fptr
= new char* [totFlds
];
1414 DbRetVal rv
= validateIndex(tblName
, fldList
, &tptr
, &fptr
, isPrimary
);
1420 rv
= systemDatabase_
->getXCheckpointMutex();
1423 printError(ErrSysInternal
, "Unable to get database mutex");
1424 return ErrSysInternal
;
1427 //below statements are actually setting values in the catalog table
1428 //thats why mutex is taken before this stmt. Do not change the order
1429 CFIELD
* fInfo
= (CFIELD
*)fptr
[0];
1430 if(isPrimary
){fInfo
->isPrimary_
=true;fInfo
->isUnique_
=true;}
1431 if(isUnique
){fInfo
->isUnique_
=true;}
1433 printDebug(DM_TrieIndex
, "Creating chunk for storing trie nodes\n" );
1434 Chunk
* chunkInfo
= createUserChunk(sizeof(TrieNode
));
1436 //chunk to store the linked list of trie values
1437 Chunk
* hChunk
= createUserChunk(sizeof(IndexNode
));
1438 if (NULL
== chunkInfo
|| NULL
== hChunk
)
1441 if (chunkInfo
) deleteUserChunk(chunkInfo
);
1442 systemDatabase_
->releaseCheckpointMutex();
1443 printError(ErrSysInternal
, "Unable to create trie node chunk");
1444 return ErrSysInternal
;
1446 chunkInfo
->setChunkName(indName
);
1447 hChunk
->setChunkName(indName
);
1448 rv
= updateIndexCatalogTables(indName
,tptr
, fptr
, fldList
, isUnique
,
1449 chunkInfo
, hChunk
);
1452 printError(ErrSysInternal
, "Catalog table updation failed");
1453 deleteUserChunk(chunkInfo
);
1454 deleteUserChunk(hChunk
);
1455 systemDatabase_
->releaseCheckpointMutex();
1458 systemDatabase_
->releaseCheckpointMutex();
1459 //TODO:: create index nodes if records already exist in the table
1462 DbRetVal
DatabaseManagerImpl::validateIndex(const char *tblName
,
1463 FieldNameList
&fldList
, void **tptr
, char ***fptr
,
1466 int totFlds
= fldList
.size();
1469 printError(ErrBadCall
, "No Field name specified or composite fields specified");
1473 void *vcchunk
= NULL
;
1474 //check whether table exists
1475 CatalogTableTABLE
cTable(systemDatabase_
);
1476 cTable
.getChunkAndTblPtr(tblName
, chunk
, *tptr
, vcchunk
);
1479 printError(ErrNotExists
, "Table does not exist %s", tblName
);
1480 return ErrNotExists
;
1483 //check whether field exists
1484 CatalogTableFIELD
cField(systemDatabase_
);
1485 DbRetVal rv
= cField
.getFieldPtrs(fldList
, *tptr
, *fptr
);
1488 if (rv
!= ErrBadCall
) {
1489 printError(ErrNotExists
, "Field does not exist");
1490 return ErrNotExists
;
1493 CFIELD
* fInfo
= (CFIELD
*)*fptr
[0];
1494 if (!(fInfo
->type_
== typeInt
|| fInfo
->type_
== typeLongLong
|| fInfo
->type_
== typeString
|| fInfo
->type_
== typeVarchar
))
1496 printError(ErrBadArg
, "Trie Index cannot be created for float or double or timestamp type");
1499 if (!fInfo
->isNull_
&& isPrimary
)
1501 printError(ErrBadArg
, "Primary Index cannot be created on field without NOTNULL constraint");
1508 DbRetVal
DatabaseManagerImpl::updateIndexCatalogTables(const char *indName
,
1509 void *tptr
, char **fptr
, FieldNameList
&fldList
,
1510 bool isUnique
, Chunk
* chunkInfo
, Chunk
* hChunk
)
1512 void *tupleptr
= NULL
;
1513 CatalogTableINDEX
cIndex(systemDatabase_
);
1514 DbRetVal rv
= cIndex
.insert(indName
, tptr
, fldList
.size(), isUnique
,
1515 chunkInfo
, 0, hChunk
, tupleptr
);
1518 printError(ErrSysInternal
, "Catalog table updation failed in INDEX table");
1519 return ErrSysInternal
;
1521 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1522 rv
= cIndexField
.insert(fldList
, tupleptr
, tptr
, fptr
);
1525 //rollback the previous operation
1526 cIndex
.remove(indName
, (void *&)chunkInfo
, (void *&)hChunk
, (void *&)tupleptr
);
1527 printError(ErrSysInternal
, "Catalog table updation failed in INDEXFIELD table");
1528 return ErrSysInternal
;
1533 DbRetVal
DatabaseManagerImpl::removeIndexCatalogTables(const char *name
, void *&chunk
, void *&hchunk
, void *&tptr
)
1535 //remove the entry in INDEX
1536 CatalogTableINDEX
cIndex(systemDatabase_
);
1537 DbRetVal rv
= cIndex
.remove(name
, chunk
, hchunk
, tptr
);
1540 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
1541 return ErrSysInternal
;
1543 printDebug(DM_Database
, "Removing from INDEX %s",name
);
1544 //remove the entries in the INDEXFIELD table
1545 CatalogTableINDEXFIELD
cIndexField(systemDatabase_
);
1546 rv
= cIndexField
.remove(tptr
);
1549 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
1550 return ErrSysInternal
;
1552 printDebug(DM_Database
, "Removing from INDEXFIELD %s",name
);
1555 DbRetVal
DatabaseManagerImpl::removeIndexChunks(void* chunk
, void* hchunk
, IndexType iType
)
1557 DbRetVal rv
= deleteUserChunk((Chunk
*)chunk
);
1560 printError(ErrSysInternal
, "Unable to delete the index chunk");
1561 return ErrSysInternal
;
1563 //delete the index hash node chunk
1564 if (iType
== hashIndex
|| iType
== trieIndex
) {
1565 rv
= deleteUserChunk((Chunk
*)hchunk
);
1568 printError(ErrSysInternal
, "Unable to delete the index hash node chunk");
1569 return ErrSysInternal
;
1575 void DatabaseManagerImpl::initHashBuckets(Bucket
*buck
, int bucketSize
)
1577 os::memset((void*)buck
, 0, bucketSize
* sizeof(Bucket
));
1578 char mutName
[IDENTIFIER_LENGTH
];
1579 for (int i
=0; i
< bucketSize
; i
++)
1581 sprintf(mutName
, "BKT:%d",i
);
1582 buck
[i
].mutex_
.init(mutName
);
1587 DbRetVal
DatabaseManagerImpl::dropIndex(const char *name
)
1589 return dropIndexInt(name
, true);
1592 DbRetVal
DatabaseManagerImpl::dropIndexInt(const char *name
, bool takeLock
)
1595 void *chunk
= NULL
, *hchunk
= NULL
;
1599 rv
= systemDatabase_
->getXCheckpointMutex();
1602 printError(ErrSysInternal
, "Unable to get database mutex");
1603 return ErrSysInternal
;
1606 rv
= removeIndexCatalogTables(name
, chunk
, hchunk
, tptr
);
1609 if (takeLock
) systemDatabase_
->releaseCheckpointMutex();
1613 CINDEX
*iptr
= (CINDEX
*)tptr
;
1614 rv
= removeIndexChunks(chunk
, hchunk
, iptr
->indexType_
);
1617 if (takeLock
) systemDatabase_
->releaseCheckpointMutex();
1620 if (takeLock
) systemDatabase_
->releaseCheckpointMutex();
1622 printDebug(DM_Database
, "Dropped index %s",name
);
1623 logFinest(Conf::logger
, "Deleted Index %s", name
);
1626 DbRetVal
DatabaseManagerImpl::createForeignKey(char *fKName
,ForeignKeyInfo
*info
)
1629 int totFkFlds
= info
->fkFldList
.size();
1630 int totPkFlds
= info
->pkFldList
.size();
1631 if (totFkFlds
==0 && totPkFlds
==0) {
1632 printError(ErrBadCall
, "No Field name specified");
1637 void *vcchunk
= NULL
;
1638 rv
= systemDatabase_
->getXCheckpointMutex();
1641 printError(ErrSysInternal
, "Unable to get database mutex");
1642 return ErrSysInternal
;
1644 CatalogTableTABLE
cTable(systemDatabase_
);
1645 cTable
.getChunkAndTblPtr(info
->fkTableName
, chunk
, tptr
, vcchunk
);
1648 systemDatabase_
->releaseCheckpointMutex();
1649 printError(ErrNotExists
, "Table does not exist %s", info
->fkTableName
);
1650 return ErrNotExists
;
1652 char **fptr
= new char* [totFkFlds
];
1653 CatalogTableFIELD
cField(systemDatabase_
);
1654 rv
= cField
.getFieldPtrs(info
->fkFldList
, tptr
, fptr
);
1658 systemDatabase_
->releaseCheckpointMutex();
1659 if (rv
!= ErrBadCall
) {
1660 printError(ErrNotExists
, "Field does not exist");
1661 return ErrNotExists
;
1665 void *chunkPk
= NULL
;
1666 void *vcchunkPk
= NULL
;
1667 CatalogTableTABLE
c2Table(systemDatabase_
);
1668 c2Table
.getChunkAndTblPtr(info
->pkTableName
, chunkPk
, tPkptr
, vcchunkPk
);
1671 systemDatabase_
->releaseCheckpointMutex();
1672 printError(ErrNotExists
, "Table does not exist %s", info
->pkTableName
);
1673 return ErrNotExists
;
1675 char **fPkptr
= new char* [totPkFlds
];
1676 CatalogTableFIELD
c2Field(systemDatabase_
);
1677 rv
= c2Field
.getFieldPtrs(info
->pkFldList
, tPkptr
, fPkptr
);
1682 systemDatabase_
->releaseCheckpointMutex();
1683 if (rv
!= ErrBadCall
) {
1684 printError(ErrNotExists
, "Field does not exist");
1685 return ErrNotExists
;
1688 //Create New chunkdatanode
1689 CatalogTableFK
cFK(systemDatabase_
);
1690 rv
= cFK
.insert(fKName
, tptr
, tPkptr
);//TODO
1695 systemDatabase_
->releaseCheckpointMutex();
1696 printError(ErrSysInternal
, "Catalog table updation failed in CFK table");
1697 return ErrSysInternal
;
1700 CatalogTableFKFIELD
cFKField(systemDatabase_
);
1701 rv
= cFKField
.insert(fKName
,fptr
,fPkptr
,totFkFlds
);
1707 systemDatabase_
->releaseCheckpointMutex();
1708 printError(ErrSysInternal
, "Catalog table updation failed in CFKFIELD table");
1709 return ErrSysInternal
;
1711 systemDatabase_
->releaseCheckpointMutex();
1716 DbRetVal
DatabaseManagerImpl::dropForeignKey(void *tptr
,bool trylock
)
1720 rv
= systemDatabase_
->getXCheckpointMutex();
1723 printError(ErrSysInternal
, "Unable to get database mutex");
1724 return ErrSysInternal
;
1728 CatalogTableFK
cFK(systemDatabase_
);
1729 int total
= cFK
.getNoOfPkTable(tptr
);
1730 //printDebug(DM_TEST,"total fk chunk %d",total);
1731 for (int i
=0;i
< total
; i
++)
1733 fkChunk
= cFK
.getFkCTable(tptr
);
1737 systemDatabase_
->releaseCheckpointMutex();
1739 printError(ErrSysInternal
, "Catalog table not finds CFKFIELD table");
1740 return ErrSysInternal
;
1742 CatalogTableFKFIELD
cFKField(systemDatabase_
);
1743 rv
= cFKField
.remove(fkChunk
);
1747 systemDatabase_
->releaseCheckpointMutex();
1749 printError(ErrSysInternal
, "Catalog table updation failed in CFKFIELD table");
1750 return ErrSysInternal
;
1752 rv
=cFK
.remove(fkChunk
);
1756 systemDatabase_
->releaseCheckpointMutex();
1758 printError(ErrSysInternal
, "Catalog table updation failed for INDEX table");
1759 return ErrSysInternal
;
1763 systemDatabase_
->releaseCheckpointMutex();
1768 void DatabaseManagerImpl::printTreeIndexNodeInfo(char *name
, bool flag
)
1770 CatalogTableINDEX
cIndex(systemDatabase_
);
1772 void *chunk
= NULL
, *hchunk
= NULL
;
1774 rv
= cIndex
.get(name
, chunk
, hchunk
, tptr
);
1775 if (OK
!= rv
) return;
1776 IndexType iType
= CatalogTableINDEX::getType(tptr
);
1777 if (treeIndex
!= iType
)
1779 printf("%s is not a tree index\n ");
1782 Chunk
*ch
= (Chunk
*) chunk
;
1783 if(flag
){ if(hchunk
)((TreeNode
*) hchunk
)->displayAll(); }
1785 int offset
= CatalogTableINDEX::getOffsetOfFirstField(tptr
);
1786 //if(typeInt != offset) { printf("%s is not on Integer Type Field. To see info Index should be on integer type field. \n "); return;}
1787 if(hchunk
) ((TreeNode
*) hchunk
)->displayAll(offset
);
1791 DbRetVal
DatabaseManagerImpl::printIndexInfo(char *name
)
1793 CatalogTableINDEX
cIndex(systemDatabase_
);
1795 void *chunk
= NULL
, *hchunk
= NULL
;
1797 rv
= cIndex
.get(name
, chunk
, hchunk
, tptr
);
1798 if (OK
!= rv
) return rv
;
1799 printf("<IndexName> %s </IndexName>\n", name
);
1800 printf("<Unique> %d </Unique>\n", CatalogTableINDEX::getUnique(tptr
));
1801 IndexType iType
= CatalogTableINDEX::getType(tptr
);
1802 if(hashIndex
== iType
)
1803 printf("<Type> Hash Index </Type>\n");
1804 else if (treeIndex
== iType
)
1805 printf("<Type> Tree Index </Type>\n");
1806 else if (trieIndex
== iType
)
1807 printf("<Type> Trie Index </Type>\n");
1809 printf("<Type> Unknown Index </Type>\n");
1811 Chunk
*ch
= (Chunk
*) chunk
;
1812 printf("<HashBucket>\n");
1813 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1814 printf(" <TotalBuckets> %d </TotalBuckets> \n", CatalogTableINDEX::getNoOfBuckets(tptr
));
1815 printf("</HashBucket>\n");
1816 printf("<IndexNodes>\n");
1817 if(hashIndex
== iType
){
1818 ch
= (Chunk
*) hchunk
;
1819 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1820 printf(" <TotalNodes> %d </TotalNodes>\n", ch
->getTotalDataNodes());
1821 } else if (treeIndex
== iType
) {
1822 printf(" <TotalNodes> %d </TotalNodes>\n", ch
->getTotalDataNodes());
1824 printf(" <TotalElements> %lld </TotalElements>\n",((TreeNode
*) hchunk
)->getTotalElements());
1826 printf(" <TotalElements> 0 </TotalElements>\n");
1827 } else if (trieIndex
== iType
)
1829 printf(" <TrieNodes> \n");
1830 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1831 printf(" <TotalNodes> %d </TotalNodes>\n", ch
->getTotalDataNodes());
1832 printf(" </TrieNodes> \n <TrieValues>\n");
1833 ch
= (Chunk
*) hchunk
;
1834 printf(" <TotalPages> %d </TotalPages>\n", ch
->totalPages());
1835 printf(" <TotalNodes> %d </TotalNodes>\n", ch
->getTotalDataNodes());
1836 printf(" </TrieValues>\n");
1839 printf("Unknown Index type\n");
1841 printf("<IndexNodes>\n");
1845 DbRetVal
DatabaseManagerImpl::registerThread()
1850 printError(ErrAlready
, "Process already registered\n");
1853 pMgr_
= new ProcessManager();
1854 rv
= pMgr_
->registerThread();
1856 procSlot
= pMgr_
->getProcSlot();
1857 systemDatabase_
->setProcSlot(procSlot
);
1858 printDebug(DM_Process
, "Process registed with slot %d\n", procSlot
);
1863 DbRetVal
DatabaseManagerImpl::deregisterThread()
1868 rv
= pMgr_
->deregisterThread(procSlot
);
1875 bool DatabaseManagerImpl::isAnyOneRegistered()
1877 if (pMgr_
!= NULL
) return pMgr_
->isAnyOneRegistered();
1882 void DatabaseManagerImpl::printUsageStatistics()
1884 pMgr_
->printUsageStatistics();
1885 tMgr_
->printUsageStatistics();
1886 lMgr_
->printUsageStatistics();
1889 void DatabaseManagerImpl::printDebugLockInfo()
1891 lMgr_
->printDebugInfo();
1894 void DatabaseManagerImpl::printDebugTransInfo()
1896 tMgr_
->printDebugInfo(systemDatabase_
);
1898 void DatabaseManagerImpl::printDebugProcInfo()
1900 pMgr_
->printDebugInfo();
1902 void DatabaseManagerImpl::printDebugMutexInfo()
1904 Database
*db
= sysDb();
1905 db
->printDebugMutexInfo();
1908 printf("<Chunk Mutexes>\n");
1909 chunk
=db
->getSystemDatabaseChunk(UserChunkTableId
);
1910 while(id
<MAX_CHUNKS
)
1912 chunk
=db
->getSystemDatabaseChunk(id
);
1913 if((chunk
->getChunkID())!=0){
1914 chunk
->printMutexInfo();
1918 chunk
=db
->getSystemDatabaseChunk(UserChunkTableId
);
1919 size_t size
=chunk
->getSize();
1920 int noOfDataNodes
=os::floor((PAGE_SIZE
- sizeof(PageInfo
))/size
);
1921 Page
* page
=chunk
->getFirstPage();
1926 char *data
= ((char*)page
) + sizeof(PageInfo
);
1927 for (i
= 0; i
< noOfDataNodes
; i
++)
1929 if (*((InUse
*)data
) == 1)
1931 chk
=(Chunk
*)((InUse
*)data
+1);
1932 chk
->printMutexInfo();
1936 page
= (PageInfo
*)(((PageInfo
*)page
)->nextPage_
) ;
1938 printf("</Chunk Mutexes>\n");
1939 lMgr_
->printMutexInfo();
1941 void DatabaseManagerImpl::printDebugChunkInfo()
1943 Database
*db
= sysDb();
1946 printf("<Chunk information>\n");
1947 printf(" <System Chunk >\n");
1948 chunk
=db
->getSystemDatabaseChunk(UserChunkTableId
);
1950 while(id
<MAX_CHUNKS
)
1952 chunk
=db
->getSystemDatabaseChunk(id
);
1953 if((chunk
->getChunkID())!=0){
1958 printf(" </System Chunk >\n");
1959 printf(" <User Chunk >\n");
1960 chunk
=db
->getSystemDatabaseChunk(UserChunkTableId
);
1961 size_t size
=chunk
->getSize();
1962 int noOfDataNodes
=os::floor((PAGE_SIZE
- sizeof(PageInfo
))/size
);
1963 Page
* page
=chunk
->getFirstPage();
1968 char *data
= ((char*)page
) + sizeof(PageInfo
);
1969 for (i
= 0; i
< noOfDataNodes
; i
++)
1971 if (*((InUse
*)data
) == 1)
1973 chk
=(Chunk
*)((InUse
*)data
+1);
1978 page
= (PageInfo
*)(((PageInfo
*)page
)->nextPage_
) ;
1980 printf(" </User Chunk >\n");
1981 printf("</Chunk information>\n");
1984 ChunkIterator
DatabaseManagerImpl::getSystemTableIterator(CatalogTableID id
)
1986 Chunk
*fChunk
= systemDatabase_
->getSystemDatabaseChunk(id
);
1987 return fChunk
->getIterator();
1990 Chunk
* DatabaseManagerImpl::getSystemTableChunk(CatalogTableID id
)
1992 return systemDatabase_
->getSystemDatabaseChunk(id
);
1995 int DatabaseManagerImpl::getNoOfPagesForTable(char *tblName
)
1997 Table
*tbl
= openTable(tblName
);
1999 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
2002 TableImpl
*tb
= (TableImpl
*) tbl
;
2004 if (tb
->numTuples()) pages
= tb
->pagesUsed();
2009 DbRetVal
DatabaseManagerImpl::loadRecords(char *tblName
, char *buffer
)
2011 // buffer should be as big as the no of pages occupied by the records
2012 Table
*tbl
= openTable(tblName
);
2014 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
2015 return ErrSysInternal
;
2017 TableImpl
*tb
= (TableImpl
*) tbl
;
2018 char *bufIter
= buffer
;
2019 int pages
= *(int *) bufIter
; bufIter
+= sizeof(int);
2020 Page
*firstPage
= ((Chunk
*)(tb
->chunkPtr_
))->getFirstPage();
2021 PageInfo
*pi
= (PageInfo
*) firstPage
;
2022 memcpy(bufIter
, pi
, PAGE_SIZE
);
2023 bufIter
+= PAGE_SIZE
;
2024 for (int i
= 0; i
< pages
- 1; i
++) {
2025 Page
*nPage
= pi
->nextPage_
;
2026 memcpy(bufIter
, nPage
, PAGE_SIZE
);
2027 bufIter
+= PAGE_SIZE
;
2028 pi
= (PageInfo
*) nPage
;
2034 DbRetVal
DatabaseManagerImpl::pasteRecords(char *tblName
, void *buffer
)
2036 // buffer should be as big as the no of pages occupied by the records
2037 Table
*tbl
= openTable(tblName
);
2039 printError(ErrSysInternal
, "Unable to open table %s", tblName
);
2040 return ErrSysInternal
;
2042 TableImpl
*tb
= (TableImpl
*) tbl
;
2043 Database
*db
= tb
->getDB();
2044 char *bufIter
= (char *) buffer
;
2045 int pages
= *(int *) bufIter
;
2046 bufIter
+= sizeof(int);
2048 Page
*firstPage
= ((Chunk
*)(tb
->chunkPtr_
))->getFirstPage();
2049 PageInfo
*pi
= (PageInfo
*) firstPage
;
2050 memcpy(pi
, bufIter
, PAGE_SIZE
);
2051 bufIter
+= PAGE_SIZE
;
2052 while (--pages
!= 0) {
2053 //get a new page allocated
2054 Page
*newPage
= db
->getFreePage();
2055 memcpy(newPage
, bufIter
, PAGE_SIZE
);
2056 pi
->nextPage_
= newPage
;
2057 pi
= (PageInfo
*) newPage
;
2059 // initialize chunk details and pageInfo
2060 ((Chunk
*)tb
->chunkPtr_
)->curPage_
= pi
;
2065 void DatabaseManagerImpl::setCanTakeCheckPoint(bool ctcp
)
2066 { systemDatabase_
->setCanTakeCheckPoint(ctcp
); }
2068 bool DatabaseManagerImpl::getCanTakeCheckPoint()
2069 { return systemDatabase_
->getCanTakeCheckPoint(); }
2071 DbRetVal
DatabaseManagerImpl::checkPoint()
2073 if (!systemDatabase_
->getCanTakeCheckPoint()) {
2074 printf("Load / Cache / Replication process might be running. CheckPoint not taken\n");
2075 return ErrLoadingOn
;
2077 DbRetVal rv
= systemDatabase_
->getXCheckpointMutex();
2079 printError(rv
, "Unable to get checkpoint mutex");
2080 return ErrLockTimeOut
;
2082 if (tMgr_
&& !tMgr_
->isTransactionConsistent(systemDatabase_
)) {
2083 printf("not in transaction consistent point\n");
2084 systemDatabase_
->releaseCheckpointMutex();
2085 return ErrLockTimeOut
;
2087 rv
= writeSchemaFile();
2089 printError(ErrSysInternal
, "checkpoint error");
2091 rv
= db()->checkPoint();
2092 systemDatabase_
->releaseCheckpointMutex();
2096 DbRetVal
DatabaseManagerImpl::writeSchemaFile()
2102 char schFile
[MAX_FILE_LEN
];
2103 char mapFile
[MAX_FILE_LEN
];
2104 sprintf(schFile
, "%s/db.chkpt.schema1", Conf::config
.getDbFile());
2105 sprintf(mapFile
, "%s/db.chkpt.map1", Conf::config
.getDbFile());
2106 fp
= fopen(schFile
, "r");
2109 int ret
= unlink(schFile
);
2111 printError(ErrOS
, "checkpoint: delete schema file failed");
2115 fp
= fopen(schFile
, "w+");
2117 printError(ErrOS
, "Unable to create schema file for chkpt.");
2120 fp1
= fopen(mapFile
, "r");
2123 int ret
= unlink(mapFile
);
2125 printError(ErrOS
, "checkpoint: delete schema file failed");
2129 fd
= open(mapFile
, O_WRONLY
|O_CREAT
, 0644);
2131 printError(ErrOS
, "checkpoint: Unable to create map file.");
2134 List tableList
= getAllTableNames();
2135 ListIterator iter
= tableList
.getIterator();
2136 Identifier
*elem
= NULL
;
2138 while (iter
.hasElement()) {
2139 elem
= (Identifier
*) iter
.nextElement();
2140 // if (TableConf::config.isTableCached(elem->name) == OK) continue;
2141 fprintf(fp
, "CREATE TABLE %s (", elem
->name
);
2142 Table
*table
= openTable(elem
->name
);
2143 if (NULL
== table
) {
2144 printError(ErrSysInternal
, "Unable to open table %s", elem
->name
);
2145 return ErrSysInternal
;
2147 void *chunk
= NULL
; void *tptr
= NULL
; void *vcchunk
= NULL
;
2148 CatalogTableTABLE
cTable(systemDatabase_
);
2149 rv
= cTable
.getChunkAndTblPtr(elem
->name
, chunk
, tptr
, vcchunk
);
2151 strcpy(obj
.name
, elem
->name
);
2153 obj
.bucketChunk
= NULL
;
2154 obj
.firstPage
= ((Chunk
*)chunk
)->getFirstPage();
2155 obj
.curPage
= ((Chunk
*)chunk
)->getCurrentPage();
2157 write(fd
, buf
, sizeof(obj
));
2158 FieldInfo
*info
= new FieldInfo();
2159 List fNameList
= table
->getFieldNameList();
2160 ListIterator fNameIter
= fNameList
.getIterator();
2162 bool firstField
=true;
2163 char fieldName
[IDENTIFIER_LENGTH
];
2164 while (fNameIter
.hasElement()) {
2165 elem
= (Identifier
*) fNameIter
.nextElement();
2166 Table::getFieldNameAlone(elem
->name
, fieldName
);
2167 rv
= table
->getFieldInfo(elem
->name
, info
);
2169 printf("unable to retrive info for table %s\n", elem
->name
);
2172 fprintf(fp
, "%s %s ", fieldName
, AllDataType::getSQLString(info
->type
));
2175 fprintf(fp
, ", %s %s ", fieldName
, AllDataType::getSQLString(info
->type
));
2176 if (info
->type
== typeString
|| info
->type
== typeVarchar
||
2177 info
->type
== typeBinary
)
2178 fprintf(fp
, "(%d)",info
->length
);
2179 if (info
->isNull
) fprintf(fp
, " NOT NULL ");
2180 if (info
->isDefault
) fprintf(fp
, " DEFAULT '%s' ", info
->defaultValueBuf
);
2181 if (info
->isAutoIncrement
) fprintf(fp
, " AUTO_INCREMENT ");
2184 while (fNameIter
.hasElement())
2185 delete ((FieldName
*) fNameIter
.nextElement());
2188 fprintf(fp
, ");\n");
2189 table
->printSQLIndexString(fp
, fd
);
2193 ListIterator tIter
= tableList
.getIterator();
2195 while (tIter
.hasElement())
2196 delete ((FieldName
*) tIter
.nextElement());
2204 DbRetVal
DatabaseManagerImpl::recover()
2207 rv
= sysDb()->recoverSystemDB();
2208 if (rv
!= OK
) return rv
;
2209 if (!Conf::config
.useMmap())rv
= db()->recoverUserDB();
2213 void DatabaseManagerImpl::sendSignal(int signal
)
2215 ThreadInfo
* tInfo
= sysDb()->getThreadInfo(0);
2216 for (int i
=0; i
< Conf::config
.getMaxProcs(); i
++)
2218 if (tInfo
->pid_
!=0) os::kill(tInfo
->pid_
, signal
);