Trie Index changes for retreiving metadata through catalog tool and
[csql.git] / src / storage / DatabaseManagerImpl.cxx
blob2e46201be82342bcdb4127d57386efcbb8db91c2
1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
4 * *
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. *
9 * *
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. *
14 * *
15 ***************************************************************************/
16 #include<Database.h>
17 #include<DatabaseManager.h>
18 #include<DatabaseManagerImpl.h>
19 #include<os.h>
20 #include<Table.h>
21 #include<TableImpl.h>
22 #include<Transaction.h>
23 #include<CatalogTables.h>
24 #include<Index.h>
25 #include<Lock.h>
26 #include<Debug.h>
27 #include<Config.h>
28 #include<TableConfig.h>
29 #include<Process.h>
32 DatabaseManagerImpl::~DatabaseManagerImpl()
34 //Note:Databases are closed by the session interface
35 delete tMgr_;
36 delete lMgr_;
39 void DatabaseManagerImpl::createLockManager()
41 lMgr_ = new LockManager(systemDatabase_);
42 return;
45 void DatabaseManagerImpl::createTransactionManager()
48 tMgr_ = new TransactionManager();
49 tMgr_->setFirstTrans(systemDatabase_->getSystemDatabaseTrans(0));
50 return;
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_;
62 db_ = NULL;
63 printDebug(DM_Database, "Opened system database");
64 return OK;
67 DbRetVal DatabaseManagerImpl::closeSystemDatabase()
69 Database *db = db_;
70 //make them to point to system database file descriptor
71 //and database pointer
72 db_ = systemDatabase_;
73 closeDatabase();
74 db_ = db;
75 printDebug(DM_Database, "Closed system database");
76 return OK;
79 DbRetVal DatabaseManagerImpl::createDatabase(const char *name, size_t size)
81 bool isMmapNeeded = Conf::config.useMmap();
82 /*
83 if (isMmapNeeded && !Conf::config.useDurability()) {
84 printError(ErrBadArg, "If MMAP is set to true. Durability must be true.");
85 return ErrBadArg;
88 file_desc fd = (file_desc)-1;
89 char cmd[1024];
90 char dbMapFile[MAX_FILE_LEN];
91 struct stat st;
92 long fixAddr = 399998976L;
93 bool firstTimeServer = false;
94 if (NULL != db_ )
96 printError(ErrAlready, "Database is already created");
97 return ErrAlready;
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();
110 else
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);
117 if (-1 == shm_id) {
118 if (errno == EEXIST)
119 #if (defined MMDB && defined EMBED)
120 printError(ErrOS, "One application is already running.");
121 return ErrOS;
122 #else
123 printError(ErrOS, "Shared Memory already exists");
124 #endif
125 printError(ErrOS, "Shared memory create failed");
126 exit(0);
128 } else {
129 //switch the checkpoint
130 if (Database::getCheckpointID() == 0)
131 Database::setCheckpointID(1);
132 else
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")) {
139 fclose(file);
140 sprintf(cmd, "cp %s %s/db.chkpt.data", dbMapFile, Conf::config.getDbFile());
141 int ret = system(cmd);
142 if (ret != 0) {
143 printError(ErrOS, "could not copy data file to map file");
144 return ErrOS;
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");
154 return ErrOS;
156 if(::stat(dbMapFile, &st) == -1) {
157 printf("Unable to retrieve the db File data\n");
158 os::closeFile(fd);
159 db_->setChkptfd((file_desc)-1);
160 return ErrOS;
162 #ifdef WINNT
163 int localfd = os::open(dbMapFile, fileOpenCreat,0);
164 #else
165 int localfd = fd;
166 #endif
167 if (st.st_size == 0 || st.st_size < size) {
168 firstTimeServer = true;
169 off_t flSize = os::lseek(localfd, size - 1, SEEK_SET);
171 char *a = "0";
172 int wSize = os::write(localfd, a, 1);
173 #ifdef WINNT
174 os::close(localfd);
175 #endif
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);
188 return ErrOS;
190 # if (defined MMDB && defined EMBED)
191 if (0 == strcmp(name, SYSTEMDB)) ProcessManager::sysAddr = rtnAddr;
192 else ProcessManager::usrAddr = rtnAddr;
193 # endif
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);
205 db_->setName(name);
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",
240 chunkInfo);
242 db_->setHashIndexChunk(chunkInfo);*/
243 return OK;
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;
255 } else {
256 shm_id = os::shm_open(Conf::config.getUserDbKey(), 100, 0660);
257 os::shm_remove(shm_id);
258 delete db_;
259 db_ = NULL;
261 return OK;
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");
277 return ErrAlready;
280 else
282 if (NULL ==systemDatabase_)
284 printError(ErrNotOpen, "System Database not open");
285 return ErrNotOpen;
287 size = Conf::config.getMaxDbSize();
288 startaddr = startaddr + Conf::config.getMaxSysDbSize();
289 fixAddr += Conf::config.getMaxSysDbSize();
291 if (NULL != db_)
293 printError(ErrAlready, "User Database already open");
294 return ErrAlready;
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();
304 else
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(),
318 curChkptID);
319 fd = os::openFile(dbMapFile, fileOpenReadWrite, 0660);
320 if ((file_desc)-1 == fd) {
321 printError(ErrOS, "Mmap file could not be opened");
322 return ErrOS;
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);
329 }else
331 shm_id = os::shm_open(key, size, 0660);
332 if (shm_id == -1 )
334 printError(ErrOS, "Shared memory open failed");
335 return ErrOS;
337 shm_ptr = os::shm_attach(shm_id, startaddr, SHM_RND);
339 if (0 == strcmp(name, SYSTEMDB))
341 firstThread = true;
342 ProcessManager::sysAddr = (char*) shm_ptr;
344 else
346 ProcessManager::usrAddr = (char*) shm_ptr;
348 } else {
349 if (0 == strcmp(name, SYSTEMDB)) shm_ptr = ProcessManager::sysAddr;
350 else shm_ptr = ProcessManager::usrAddr;
354 rtnAddr = (caddr_t) shm_ptr;
355 #if defined (x86_64)
356 if (rtnAddr < 0 || shm_ptr == (char*)0xffffffffffffffff)
358 printError(ErrOS, "Shared memory attach returned -ve value %x %d", shm_ptr, errno);
359 return ErrOS;
361 #else
362 if (rtnAddr < 0 || shm_ptr == (char*)0xffffffff)
364 printError(ErrOS, "Shared memory attach returned -ve value %x %d", shm_ptr, errno);
365 return ErrOS;
367 #endif
369 db_ = new Database();
370 db_->setMetaDataPtr((DatabaseMetaData*)rtnAddr);
371 db_->setChkptfd(fd);
373 if (firstThread) ProcessManager::systemDatabase = db_;
375 printDebug(DM_Database, "Opening database: %s", name);
376 return OK;
379 DbRetVal DatabaseManagerImpl::closeDatabase()
382 if (NULL == db_)
384 //Database is already closed
385 return OK;
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();
394 os::closeFile(fd);
396 if (ret == 0) {
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);
403 delete db_;
404 db_ = NULL;
405 return OK;
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);
412 DbRetVal rv = OK;
413 void *ptr = chunk->allocate(systemDatabase_, &rv);
414 if (NULL == ptr)
416 printError(rv, "Allocation failed for User chunk catalog table");
417 return NULL;
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_);
426 else
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");
433 return NULL;
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);
442 else
444 firstPageInfo->setPageAsUsed(chunkInfo->allocSize_);
445 char *data = ((char*)firstPageInfo) + sizeof(PageInfo);
446 *(InUse*)data =0;
448 if (0 == size)
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_;
457 if (0 == size)
458 chunkInfo->setAllocType(VariableSizeAllocator);
459 else
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);
467 return chunkInfo;
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);
489 else
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
495 while(iter <= end)
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);
510 else
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
516 while(iter <= end)
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);
533 return OK;
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)
540 DbRetVal rv = OK;
541 if (!Util::isIdentifier((char*)name)) {
542 printError(ErrBadArg, "Invalid character for index name");
543 return ErrBadArg;
545 int fldCount = def.getFieldCount();
546 if(0==fldCount)
548 printError(ErrNotExists,"Table can't be created without Field");
549 return ErrNotExists;
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
556 int addSize = 0;
557 if (fldCount <= 32) addSize = 4; else addSize = os::align(fldCount);
558 size_t sizeofTuple = os::alignLong(def.getTupleSize()+addSize);
559 rv = systemDatabase_->getXCheckpointMutex();
560 if (OK != rv ) {
561 printError(rv, "Unable to get Database mutex");
562 return rv;
565 void *tptr =NULL;
566 void *chunk = NULL;
567 void *vcchunk = NULL;
569 //check whether table already exists
570 CatalogTableTABLE cTable(systemDatabase_);
571 cTable.getChunkAndTblPtr(name, chunk, tptr, vcchunk);
572 if (NULL != tptr)
574 systemDatabase_->releaseCheckpointMutex();
575 printError(ErrAlready, "Table %s already exists", name);
576 return ErrAlready;
579 //create a chunk to store the tuples
580 Chunk *ptr = createUserChunk(sizeofTuple);
581 if (NULL == ptr)
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);
589 //add row to TABLE
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);
595 Chunk *vcptr = NULL;
596 if (isVarcharPresent) {
597 //creat chunk to store varchar values
598 vcptr = createUserChunk();
599 if (NULL == vcptr)
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);
611 if (OK != rv)
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);
620 //add rows to FIELD
621 FieldIterator iter = def.getFieldIterator();
622 CatalogTableFIELD cField(systemDatabase_);
623 rv = cField.insert(iter, tblID ,tptr);
624 if (OK != rv)
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);
638 return OK;
640 DbRetVal DatabaseManagerImpl::renameTable(const char *oldName,const char *newName)
642 void *chunk = NULL;
643 DbRetVal rv = systemDatabase_->getXCheckpointMutex();
644 if (OK != rv) {
645 printError(ErrSysInternal, "Unable to get database mutex for rename table");
646 return ErrSysInternal;
648 CatalogTableTABLE cTable(systemDatabase_);
649 rv = cTable.renameTable(oldName,newName);
650 if (OK != rv) {
651 printError(ErrSysInternal, "Unable to rename table");
652 systemDatabase_->releaseCheckpointMutex();
653 return ErrSysInternal;
655 systemDatabase_->releaseCheckpointMutex();
656 return OK;
658 DbRetVal DatabaseManagerImpl::renameIndex(const char *oldName,const char *newName)
660 void *chunk = NULL;
661 DbRetVal rv = systemDatabase_->getXCheckpointMutex();
662 if (OK != rv) {
663 printError(ErrSysInternal, "Unable to get database mutex for rename table");
664 return ErrSysInternal;
666 CatalogTableTABLE cTable(systemDatabase_);
667 rv = cTable.renameIndex(oldName,newName);
668 if (OK != rv) {
669 printError(ErrSysInternal, "Unable to rename table");
670 systemDatabase_->releaseCheckpointMutex();
671 return ErrSysInternal;
673 systemDatabase_->releaseCheckpointMutex();
674 return OK;
677 DbRetVal DatabaseManagerImpl::renameField(const char *tableName,const char *oldName,const char *newName)
679 DbRetVal rv = systemDatabase_->getXCheckpointMutex();
680 if (OK != rv) {
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);
686 if (OK != rv) {
687 printError(ErrSysInternal, "Unable to rename field.");
688 systemDatabase_->releaseCheckpointMutex();
689 return ErrSysInternal;
691 systemDatabase_->releaseCheckpointMutex();
692 return rv;
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)
702 void *chunk = NULL;
703 void *tptr =NULL;
704 void *vcchunk = NULL;
705 DbRetVal rv = systemDatabase_->getXCheckpointMutex();
706 if (OK != rv) {
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);
713 if (OK != rv) {
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);
720 if(noOfRelation)
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);
730 if (rv !=OK)
732 systemDatabase_->releaseCheckpointMutex();
733 txnMgr()->rollback(lockMgr());
734 printError(ErrLockTimeOut, "Unable to acquire exclusive lock on the table\n");
735 return rv;
737 rv = cTable.remove(name, chunk, tptr);
738 if (OK != rv) {
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);
749 if (OK != rv) {
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);
758 if (OK != rv) {
759 systemDatabase_->releaseCheckpointMutex();
760 txnMgr()->rollback(lockMgr());
761 printError(rv, "Unable to delete the chunk");
762 return rv;
764 printDebug(DM_Database,"Deleted UserChunk:%x", chunk);
766 if (vcchunk != NULL) {
767 rv = deleteUserChunk((Chunk*)vcchunk);
768 if (OK != rv) {
769 systemDatabase_->releaseCheckpointMutex();
770 txnMgr()->rollback(lockMgr());
771 printError(rv, "Unable to delete the chunk");
772 return rv;
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);
785 if(isFkExist)
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());
793 if (rv !=OK)
795 printError(ErrLockTimeOut, "Unable to release exclusive lock on the table\n");
796 return rv;
798 return OK;
801 //Return values: NULL for table not found
802 Table* DatabaseManagerImpl::openTable(const char *name,bool checkpkfk)
804 DbRetVal ret = OK;
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();
808 table->setDB(db_);
809 table->setSystemDB(systemDatabase_);
810 table->setLockManager(lMgr_);
811 table->setTrans(ProcessManager::getThreadTransAddr(systemDatabase_->procSlot));
813 //to store the chunk pointer of table
814 void *chunk = NULL;
815 void *vcchunk = NULL;
817 //to store the tuple pointer of the table
818 void *tptr =NULL;
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();
825 if (OK != rv) {
826 printError(ErrSysInternal, "Unable to get database mutex");
827 delete table;
828 return NULL;
830 CatalogTableTABLE cTable(systemDatabase_);
831 ret = cTable.getChunkAndTblPtr(name, chunk, tptr, vcchunk);
832 if ( OK != ret)
834 systemDatabase_->releaseAllocDatabaseMutex();
835 delete table;
836 printError(ErrNotExists, "Table not exists %s", name);
837 return NULL;
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
844 if (rv !=OK)
846 printError(ErrLockTimeOut, "Unable to acquire shared lock on the table\n");
847 systemDatabase_->releaseAllocDatabaseMutex();
848 delete table;
849 return NULL;
852 if (tTuple->numFlds_ <= 32)
854 table->isIntUsedForNULL = true;
855 table->iNullInfo = 0;
856 table->iNotNullInfo =0;
858 else
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();
875 int fldpos=1;
876 while (fIter.hasElement())
878 FieldDef *def = fIter.nextElement();
879 if (table->isIntUsedForNULL) {
880 if (def->isNull_) SETBIT(table->iNotNullInfo, fldpos-1);
882 else {
883 if (def->isNull_) table->cNotNullInfo[fldpos-1] = 1;
885 fldpos++;
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_];
896 else
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();
915 if (firstFld)
917 hIdxInfo->fldOffset = table->fldList_.getFieldOffset(def->fldName_);
918 hIdxInfo->type = table->fldList_.getFieldType(def->fldName_);
919 hIdxInfo->compLength = table->fldList_.getFieldLength(def->fldName_);
920 firstFld = false;
921 }else {
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
934 if(checkpkfk){
935 CatalogTableFK cFk(systemDatabase_);
936 int totalFld=0;
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);
948 else {
949 printError(ErrSysInternal, "Unable to open foreign key tables");
950 delete[] fptr;
951 pkTable->close();
952 return NULL;
955 delete[] fptr;
958 char *tblName = NULL;
959 table->isFkTbl = cFk.isFkTable(tptr);
960 if(table->isFkTbl)
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);
969 else {
970 printError(ErrSysInternal, "Unable to open foreign key tables");
971 delete[] fptr;
972 fkTable->close();
973 return NULL;
976 delete[] fptr;
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);
982 return table;
985 List DatabaseManagerImpl::getAllTableNames(int *retval)
987 DbRetVal ret = OK;
988 //to store the tuple pointer of the table
989 void *tptr =NULL;
991 /*DbRetVal rv = systemDatabase_->getSCheckpointMutex();
992 if (OK != rv) {
993 printError(ErrSysInternal, "Unable to get checkpoint mutex");
994 if(retval) *retval = rv;
995 List tableList;
996 return tableList;
998 CatalogTableTABLE cTable(systemDatabase_);
999 List tableList = cTable.getTableList();
1000 //systemDatabase_->releaseCheckpointMutex();
1001 return tableList;
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;
1012 table->unlock();
1013 /* TableImpl *fkTbl =NULL;
1014 ListIterator tblIter = ((TableImpl*)table)->tblList.getIterator();
1015 tblIter.reset();
1016 while (tblIter.hasElement()){
1017 fkTbl = (TableImpl *) tblIter.nextElement();
1018 closeTable(fkTbl);
1020 ((TableImpl*)table)->tblList.reset();
1021 tblIter = ((TableImpl*)table)->tblFkList.getIterator();
1022 tblIter.reset();
1023 while (tblIter.hasElement()){
1024 fkTbl = (TableImpl *) tblIter.nextElement();
1025 closeTable(fkTbl);
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)
1034 DbRetVal rv = OK;
1035 if (!info->isUnique && info->isPrimary)
1037 printError(ErrBadCall, "Primary key cannot be non unique\n");
1038 return ErrBadCall;
1040 if (!Util::isIdentifier((char*)indName)) {
1041 printError(ErrBadArg, "Invalid character for index name");
1042 return ErrBadArg;
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);
1064 }else {
1065 printError(ErrBadCall, "Index type not supported\n");
1066 return ErrBadCall;
1068 return rv;
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",
1082 bucketSize);
1083 return ErrBadRange;
1085 int totFlds = fldList.size();
1086 if (totFlds == 0)
1088 printError(ErrBadCall, "No Field name specified");
1089 return ErrBadCall;
1091 void *tptr =NULL;
1092 void *chunk = NULL;
1093 void *vcchunk = NULL;
1094 DbRetVal rv = systemDatabase_->getXCheckpointMutex();
1095 if (OK != rv)
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);
1104 if (NULL == tptr)
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);
1115 if (OK != rv)
1117 delete[] 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");
1122 //} else {
1123 //printError(ErrNotExists, "Field does not exist");
1124 //}
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");
1137 delete[] fptr;
1138 systemDatabase_->releaseCheckpointMutex();
1139 return ErrBadArg;
1141 if (!fInfo->isNull_ && isPrimary )
1143 printError(ErrBadArg, "Primary Index cannot be created on field without NOTNULL constraint");
1144 delete[] fptr;
1145 systemDatabase_->releaseCheckpointMutex();
1146 return ErrBadArg;
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)
1158 delete[] fptr;
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)
1168 delete[] fptr;
1169 deleteUserChunk(chunkInfo);
1170 systemDatabase_->releaseCheckpointMutex();
1171 printError(rv, "Unable to allocate memory for bucket");
1172 return rv;
1174 Bucket *buck = (Bucket*) buckets;
1175 initHashBuckets(buck, bucketSize);
1177 //create chunk to store the hash index nodes
1178 Chunk* hChunk = createUserChunk(sizeof(IndexNode));
1179 if (NULL == hChunk)
1181 delete[] fptr;
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);
1189 //add row to INDEX
1190 void *tupleptr = NULL;
1191 CatalogTableINDEX cIndex(systemDatabase_);
1192 rv = cIndex.insert(indName, tptr, fldList.size(), isUnique,
1193 chunkInfo, bucketSize, hChunk, tupleptr);
1194 if (OK != rv)
1196 delete[] fptr;
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);
1207 if (OK != rv)
1209 delete[] 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;
1217 delete[] fptr;
1218 systemDatabase_->releaseCheckpointMutex();
1220 //TODO:: Take table lock
1222 // Following code is written by Kishor Amballi
1223 TableImpl *tbl = (TableImpl *) openTable(tblName);
1224 if (NULL == tbl) {
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);
1231 closeTable(tbl);
1232 return OK;
1234 HashIndexInfo *indxInfo = NULL;
1235 int i = 0;
1236 for (i = 0; i < tbl->numIndexes_; i++) {
1237 if(((HashIndexInfo *)tbl->idxInfo[i])->indexPtr == tupleptr) {
1238 indxInfo = (HashIndexInfo *) tbl->idxInfo[i];
1239 break;
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) {
1248 closeTable(tbl);
1249 dropIndex(indName);
1250 return rv;
1253 closeTable(tbl);
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);
1256 return OK;
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",
1266 nodeSize);
1267 return ErrBadRange;
1269 int totFlds = fldList.size();
1270 if (totFlds == 0) {
1271 printError(ErrBadCall, "No Field name specified");
1272 return ErrBadCall;
1273 }else if (totFlds != 1) {
1274 printError(ErrBadCall, "Composite index not supported for Tree");
1275 return ErrBadCall;
1277 void *tptr =NULL;
1278 void *chunk = NULL;
1279 void *vcchunk = NULL;
1280 DbRetVal rv = systemDatabase_->getXCheckpointMutex();
1281 if (OK != rv)
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);
1290 if (NULL == tptr)
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);
1299 if (OK != rv)
1301 delete[] 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");
1314 delete[] fptr;
1315 systemDatabase_->releaseCheckpointMutex();
1316 return ErrBadArg;
1318 if (fInfo->type_ == typeVarchar)
1320 printError(ErrBadArg, "Tree Index not supported for varchar type. Use char data type instead.");
1321 delete[] fptr;
1322 systemDatabase_->releaseCheckpointMutex();
1323 return ErrBadArg;
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)
1333 delete[] fptr;
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);
1345 if (OK != rv)
1347 delete[] fptr;
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);
1356 if (OK != rv)
1358 delete[] 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;
1366 delete[] fptr;
1367 rv = createIndexNodeForRecords(tblName, tupleptr, chunk);
1368 if (rv != OK)
1370 dropIndex(indName);
1371 systemDatabase_->releaseCheckpointMutex();
1372 return rv;
1374 systemDatabase_->releaseCheckpointMutex();
1375 logFinest(Conf::logger, "Creating TreeIndex %s on %s rv:%d",
1376 indName, tblName, rv);
1377 return OK;
1379 DbRetVal DatabaseManagerImpl::createIndexNodeForRecords(const char* tblName,
1380 void *tupleptr, void *chunk)
1382 //TODO::if tuples already present in this table, then create tree index '
1383 //nodes
1384 TableImpl *tbl = (TableImpl *) openTable(tblName);
1385 if (NULL == tbl) {
1386 printError(ErrSysInternal, "Unable to open table %s", tblName);
1387 return ErrSysInternal;
1389 if (! tbl->numTuples()) {
1390 closeTable(tbl);
1391 return OK;
1393 HashIndexInfo *indxInfo = NULL;
1394 int i = 0;
1395 for (i = 0; i < tbl->numIndexes_; i++) {
1396 if(((HashIndexInfo *)tbl->idxInfo[i])->indexPtr == tupleptr) {
1397 indxInfo = (HashIndexInfo *) tbl->idxInfo[i];
1398 break;
1401 void *recPtr = NULL;
1402 ChunkIterator chIter = ((Chunk *)chunk)->getIterator();
1403 tbl->setLoading(true);
1404 DbRetVal rv = OK;
1405 while ((recPtr = chIter.nextElement()) != NULL) {
1406 rv = tbl->insertIndexNode(*tbl->trans, tupleptr, indxInfo, recPtr);
1407 if (rv == ErrUnique) {
1408 closeTable(tbl);
1409 return rv;
1412 closeTable(tbl);
1413 return OK;
1416 DbRetVal DatabaseManagerImpl::createTrieIndex(const char *indName, const char *tblName,
1417 FieldNameList &fldList, bool isUnique, bool isPrimary)
1419 int totFlds = fldList.size();
1420 void *tptr =NULL;
1421 char **fptr = new char* [totFlds];
1422 DbRetVal rv = validateIndex(tblName, fldList, &tptr, &fptr, isPrimary);
1423 if (OK != rv)
1425 delete[] fptr;
1426 return rv;
1428 rv = systemDatabase_->getXCheckpointMutex();
1429 if (OK != rv)
1431 printError(ErrSysInternal, "Unable to get database mutex");
1432 return ErrSysInternal;
1435 //below statements are actually setting values in the catalog table
1436 //thats why mutex is taken before this stmt. Do not change the order
1437 CFIELD* fInfo = (CFIELD*)fptr[0];
1438 if(isPrimary){fInfo->isPrimary_=true;fInfo->isUnique_=true;}
1439 if(isUnique){fInfo->isUnique_=true;}
1441 printDebug(DM_TrieIndex, "Creating chunk for storing trie nodes\n" );
1442 Chunk* chunkInfo = createUserChunk(sizeof(TrieNode));
1444 //chunk to store the linked list of trie values
1445 Chunk* hChunk = createUserChunk(sizeof(IndexNode));
1446 if (NULL == chunkInfo || NULL == hChunk)
1448 delete[] fptr;
1449 if (chunkInfo) deleteUserChunk(chunkInfo);
1450 systemDatabase_->releaseCheckpointMutex();
1451 printError(ErrSysInternal, "Unable to create trie node chunk");
1452 return ErrSysInternal;
1454 chunkInfo->setChunkName(indName);
1455 hChunk->setChunkName(indName);
1456 void *tupleptr = NULL;
1457 rv = updateIndexCatalogTables(indName,tptr, fptr, fldList, isUnique,
1458 chunkInfo, hChunk , tupleptr);
1459 delete[] fptr;
1460 if (OK != rv) {
1461 printError(ErrSysInternal, "Catalog table updation failed");
1462 deleteUserChunk(chunkInfo);
1463 deleteUserChunk(hChunk);
1464 systemDatabase_->releaseCheckpointMutex();
1465 return rv;
1468 void *chunk = NULL;
1469 void *vcchunk = NULL;
1470 CatalogTableTABLE cTable(systemDatabase_);
1471 cTable.getChunkAndTblPtr(tblName, chunk, tptr, vcchunk);
1472 //create index nodes if records already exist in the table
1473 rv = createIndexNodeForRecords(tblName, tupleptr, chunk);
1474 if (rv != OK)
1476 dropIndex(indName);
1477 systemDatabase_->releaseCheckpointMutex();
1478 return rv;
1480 systemDatabase_->releaseCheckpointMutex();
1481 logFinest(Conf::logger, "Creating TrieIndex %s on %s rv:%d",
1482 indName, tblName, rv);
1483 return OK;
1485 DbRetVal DatabaseManagerImpl::validateIndex(const char *tblName,
1486 FieldNameList &fldList, void **tptr, char ***fptr,
1487 bool isPrimary)
1489 int totFlds = fldList.size();
1490 if (totFlds != 1)
1492 printError(ErrBadCall, "No Field name specified or composite fields specified");
1493 return ErrBadCall;
1495 void *chunk = NULL;
1496 void *vcchunk = NULL;
1497 //check whether table exists
1498 CatalogTableTABLE cTable(systemDatabase_);
1499 cTable.getChunkAndTblPtr(tblName, chunk, *tptr, vcchunk);
1500 if (NULL == tptr)
1502 printError(ErrNotExists, "Table does not exist %s", tblName);
1503 return ErrNotExists;
1506 //check whether field exists
1507 CatalogTableFIELD cField(systemDatabase_);
1508 DbRetVal rv = cField.getFieldPtrs(fldList, *tptr, *fptr);
1509 if (OK != rv)
1511 if (rv != ErrBadCall) {
1512 printError(ErrNotExists, "Field does not exist");
1513 return ErrNotExists;
1516 CFIELD* fInfo = (CFIELD*)*fptr[0];
1517 if (!(fInfo->type_ == typeInt || fInfo->type_ == typeLongLong || fInfo->type_ == typeString || fInfo->type_ == typeVarchar))
1519 printError(ErrBadArg, "Trie Index cannot be created for float or double or timestamp type");
1520 return ErrBadArg;
1522 if (!fInfo->isNull_ && isPrimary )
1524 printError(ErrBadArg, "Primary Index cannot be created on field without NOTNULL constraint");
1525 return ErrBadArg;
1528 return OK;
1531 DbRetVal DatabaseManagerImpl::updateIndexCatalogTables(const char *indName,
1532 void *tptr, char **fptr, FieldNameList &fldList,
1533 bool isUnique, Chunk* chunkInfo, Chunk* hChunk,
1534 void *&tupleptr )
1536 //void *tupleptr = NULL;
1537 CatalogTableINDEX cIndex(systemDatabase_);
1538 DbRetVal rv = cIndex.insert(indName, tptr, fldList.size(), isUnique,
1539 chunkInfo, 0, hChunk, tupleptr);
1540 if (OK != rv)
1542 printError(ErrSysInternal, "Catalog table updation failed in INDEX table");
1543 return ErrSysInternal;
1545 CatalogTableINDEXFIELD cIndexField(systemDatabase_);
1546 rv = cIndexField.insert(fldList, tupleptr, tptr, fptr);
1547 if (OK != rv)
1549 //rollback the previous operation
1550 cIndex.remove(indName, (void *&)chunkInfo, (void *&)hChunk, (void *&)tupleptr);
1551 printError(ErrSysInternal, "Catalog table updation failed in INDEXFIELD table");
1552 return ErrSysInternal;
1554 return rv;
1557 DbRetVal DatabaseManagerImpl::removeIndexCatalogTables(const char *name, void *&chunk, void *&hchunk, void *&tptr)
1559 //remove the entry in INDEX
1560 CatalogTableINDEX cIndex(systemDatabase_);
1561 DbRetVal rv = cIndex.remove(name, chunk, hchunk, tptr);
1562 if (OK != rv)
1564 printError(ErrSysInternal, "Catalog table updation failed for INDEX table");
1565 return ErrSysInternal;
1567 printDebug(DM_Database, "Removing from INDEX %s",name);
1568 //remove the entries in the INDEXFIELD table
1569 CatalogTableINDEXFIELD cIndexField(systemDatabase_);
1570 rv = cIndexField.remove(tptr);
1571 if (OK != rv)
1573 printError(ErrSysInternal, "Catalog table updation failed for INDEX table");
1574 return ErrSysInternal;
1576 printDebug(DM_Database, "Removing from INDEXFIELD %s",name);
1577 return OK;
1579 DbRetVal DatabaseManagerImpl::removeIndexChunks(void* chunk, void* hchunk, IndexType iType)
1581 DbRetVal rv = deleteUserChunk((Chunk*)chunk);
1582 if (OK != rv)
1584 printError(ErrSysInternal, "Unable to delete the index chunk");
1585 return ErrSysInternal;
1587 //delete the index hash node chunk
1588 if (iType == hashIndex || iType == trieIndex) {
1589 rv = deleteUserChunk((Chunk*)hchunk);
1590 if (OK != rv)
1592 printError(ErrSysInternal, "Unable to delete the index hash node chunk");
1593 return ErrSysInternal;
1596 return OK;
1599 void DatabaseManagerImpl::initHashBuckets(Bucket *buck, int bucketSize)
1601 os::memset((void*)buck, 0, bucketSize * sizeof(Bucket));
1602 char mutName[IDENTIFIER_LENGTH];
1603 for (int i=0; i < bucketSize ; i++)
1605 sprintf(mutName, "BKT:%d",i);
1606 buck[i].mutex_.init(mutName);
1608 return;
1611 DbRetVal DatabaseManagerImpl::dropIndex(const char *name)
1613 return dropIndexInt(name, true);
1616 DbRetVal DatabaseManagerImpl::dropIndexInt(const char *name, bool takeLock)
1618 DbRetVal rv = OK;
1619 void *chunk = NULL, *hchunk = NULL;
1620 void *tptr =NULL;
1621 int ret = 0;
1622 if (takeLock) {
1623 rv = systemDatabase_->getXCheckpointMutex();
1624 if (OK != rv)
1626 printError(ErrSysInternal, "Unable to get database mutex");
1627 return ErrSysInternal;
1630 rv = removeIndexCatalogTables(name, chunk, hchunk, tptr);
1631 if (OK != rv)
1633 if (takeLock) systemDatabase_->releaseCheckpointMutex();
1634 return rv;
1637 CINDEX *iptr = (CINDEX*)tptr;
1638 rv = removeIndexChunks(chunk, hchunk, iptr->indexType_);
1639 if (OK != rv)
1641 if (takeLock) systemDatabase_->releaseCheckpointMutex();
1642 return rv;
1644 if (takeLock) systemDatabase_->releaseCheckpointMutex();
1646 printDebug(DM_Database, "Dropped index %s",name);
1647 logFinest(Conf::logger, "Deleted Index %s", name);
1648 return OK;
1650 DbRetVal DatabaseManagerImpl::createForeignKey(char *fKName,ForeignKeyInfo *info)
1652 DbRetVal rv = OK;
1653 int totFkFlds = info->fkFldList.size();
1654 int totPkFlds = info->pkFldList.size();
1655 if (totFkFlds==0 && totPkFlds==0) {
1656 printError(ErrBadCall, "No Field name specified");
1657 return ErrBadCall;
1659 void *tptr =NULL;
1660 void *chunk = NULL;
1661 void *vcchunk = NULL;
1662 rv = systemDatabase_->getXCheckpointMutex();
1663 if (OK != rv)
1665 printError(ErrSysInternal, "Unable to get database mutex");
1666 return ErrSysInternal;
1668 CatalogTableTABLE cTable(systemDatabase_);
1669 cTable.getChunkAndTblPtr(info->fkTableName, chunk, tptr, vcchunk);
1670 if (NULL == tptr)
1672 systemDatabase_->releaseCheckpointMutex();
1673 printError(ErrNotExists, "Table does not exist %s", info->fkTableName);
1674 return ErrNotExists;
1676 char **fptr = new char* [totFkFlds];
1677 CatalogTableFIELD cField(systemDatabase_);
1678 rv = cField.getFieldPtrs(info->fkFldList, tptr, fptr);
1679 if (OK != rv)
1681 delete[] fptr;
1682 systemDatabase_->releaseCheckpointMutex();
1683 if (rv != ErrBadCall) {
1684 printError(ErrNotExists, "Field does not exist");
1685 return ErrNotExists;
1688 void *tPkptr =NULL;
1689 void *chunkPk = NULL;
1690 void *vcchunkPk = NULL;
1691 CatalogTableTABLE c2Table(systemDatabase_);
1692 c2Table.getChunkAndTblPtr(info->pkTableName, chunkPk, tPkptr, vcchunkPk);
1693 if (NULL == tPkptr)
1695 systemDatabase_->releaseCheckpointMutex();
1696 printError(ErrNotExists, "Table does not exist %s", info->pkTableName);
1697 return ErrNotExists;
1699 char **fPkptr = new char* [totPkFlds];
1700 CatalogTableFIELD c2Field(systemDatabase_);
1701 rv = c2Field.getFieldPtrs(info->pkFldList, tPkptr, fPkptr);
1702 if (OK != rv)
1704 delete[] fptr;
1705 delete[] fPkptr;
1706 systemDatabase_->releaseCheckpointMutex();
1707 if (rv != ErrBadCall) {
1708 printError(ErrNotExists, "Field does not exist");
1709 return ErrNotExists;
1712 //Create New chunkdatanode
1713 CatalogTableFK cFK(systemDatabase_);
1714 rv = cFK.insert(fKName, tptr, tPkptr);//TODO
1715 if (OK != rv)
1717 delete[] fptr;
1718 delete[] fPkptr;
1719 systemDatabase_->releaseCheckpointMutex();
1720 printError(ErrSysInternal, "Catalog table updation failed in CFK table");
1721 return ErrSysInternal;
1724 CatalogTableFKFIELD cFKField(systemDatabase_);
1725 rv = cFKField.insert(fKName,fptr,fPkptr,totFkFlds);
1726 if (OK != rv)
1728 delete[] fptr;
1729 delete[] fPkptr;
1730 cFK.remove(tptr);
1731 systemDatabase_->releaseCheckpointMutex();
1732 printError(ErrSysInternal, "Catalog table updation failed in CFKFIELD table");
1733 return ErrSysInternal;
1735 systemDatabase_->releaseCheckpointMutex();
1736 delete[] fptr;
1737 delete[] fPkptr;
1738 return rv;
1740 DbRetVal DatabaseManagerImpl::dropForeignKey(void *tptr,bool trylock)
1742 DbRetVal rv = OK;
1743 if(trylock){
1744 rv = systemDatabase_->getXCheckpointMutex();
1745 if (OK != rv)
1747 printError(ErrSysInternal, "Unable to get database mutex");
1748 return ErrSysInternal;
1751 void *fkChunk=NULL;
1752 CatalogTableFK cFK(systemDatabase_);
1753 int total = cFK.getNoOfPkTable(tptr);
1754 //printDebug(DM_TEST,"total fk chunk %d",total);
1755 for (int i=0;i< total; i++)
1757 fkChunk = cFK.getFkCTable(tptr);
1758 if(NULL==fkChunk)
1760 if(trylock){
1761 systemDatabase_->releaseCheckpointMutex();
1763 printError(ErrSysInternal, "Catalog table not finds CFKFIELD table");
1764 return ErrSysInternal;
1766 CatalogTableFKFIELD cFKField(systemDatabase_);
1767 rv = cFKField.remove(fkChunk);
1768 if (OK != rv)
1770 if(trylock){
1771 systemDatabase_->releaseCheckpointMutex();
1773 printError(ErrSysInternal, "Catalog table updation failed in CFKFIELD table");
1774 return ErrSysInternal;
1776 rv =cFK.remove(fkChunk);
1777 if (OK != rv)
1779 if(trylock){
1780 systemDatabase_->releaseCheckpointMutex();
1782 printError(ErrSysInternal, "Catalog table updation failed for INDEX table");
1783 return ErrSysInternal;
1786 if(trylock){
1787 systemDatabase_->releaseCheckpointMutex();
1789 return rv;
1792 void DatabaseManagerImpl::printTreeIndexNodeInfo(char *name, bool flag)
1794 CatalogTableINDEX cIndex(systemDatabase_);
1795 DbRetVal rv = OK;
1796 void *chunk = NULL, *hchunk = NULL;
1797 void *tptr =NULL;
1798 rv = cIndex.get(name, chunk, hchunk, tptr);
1799 if (OK != rv) return;
1800 IndexType iType = CatalogTableINDEX::getType(tptr);
1801 if (treeIndex != iType)
1803 printf("%s is not a tree index\n ");
1804 return;
1806 Chunk *ch = (Chunk*) chunk;
1807 if(flag){ if(hchunk)((TreeNode*) hchunk)->displayAll(); }
1808 else {
1809 int offset = CatalogTableINDEX::getOffsetOfFirstField(tptr);
1810 //if(typeInt != offset) { printf("%s is not on Integer Type Field. To see info Index should be on integer type field. \n "); return;}
1811 if(hchunk) ((TreeNode*) hchunk)->displayAll(offset);
1814 DbRetVal DatabaseManagerImpl::printIndexDebugInfo(char *name)
1816 CatalogTableINDEX cIndex(systemDatabase_);
1817 DbRetVal rv = OK;
1818 void *chunk = NULL, *hchunk = NULL;
1819 void *tptr =NULL;
1820 rv = cIndex.get(name, chunk, hchunk, tptr);
1821 if (OK != rv) return rv;
1822 IndexType iType = CatalogTableINDEX::getType(tptr);
1823 if(hashIndex == iType) {
1825 else if (treeIndex == iType) {
1826 CINDEX *iptr = (CINDEX*)tptr;
1827 TreeNode *start = (TreeNode*) iptr->hashNodeChunk_;
1828 start->displayAll(0);
1830 else if (trieIndex == iType) {
1831 ChunkIterator citer = CatalogTableINDEX::getIterator(tptr);
1832 TrieNode* start = (TrieNode*)citer.nextElement();
1833 if(start) TrieIndex::displayAll(start);
1835 else
1836 printf("Unknown Index\n");
1840 DbRetVal DatabaseManagerImpl::printIndexInfo(char *name)
1842 CatalogTableINDEX cIndex(systemDatabase_);
1843 DbRetVal rv = OK;
1844 void *chunk = NULL, *hchunk = NULL;
1845 void *tptr =NULL;
1846 rv = cIndex.get(name, chunk, hchunk, tptr);
1847 if (OK != rv) return rv;
1848 printf("<IndexName> %s </IndexName>\n", name);
1849 printf("<Unique> %d </Unique>\n", CatalogTableINDEX::getUnique(tptr));
1850 IndexType iType = CatalogTableINDEX::getType(tptr);
1851 if(hashIndex == iType)
1852 printf("<Type> Hash Index </Type>\n");
1853 else if (treeIndex == iType)
1854 printf("<Type> Tree Index </Type>\n");
1855 else if (trieIndex == iType)
1856 printf("<Type> Trie Index </Type>\n");
1857 else
1858 printf("<Type> Unknown Index </Type>\n");
1860 Chunk *ch = (Chunk*) chunk;
1861 printf("<HashBucket>\n");
1862 printf(" <TotalPages> %d </TotalPages>\n", ch->totalPages());
1863 printf(" <TotalBuckets> %d </TotalBuckets> \n", CatalogTableINDEX::getNoOfBuckets(tptr));
1864 printf("</HashBucket>\n");
1865 printf("<IndexNodes>\n");
1866 if(hashIndex == iType){
1867 ch = (Chunk*) hchunk;
1868 printf(" <TotalPages> %d </TotalPages>\n", ch->totalPages());
1869 printf(" <TotalNodes> %d </TotalNodes>\n", ch->getTotalDataNodes());
1870 } else if (treeIndex == iType) {
1871 printf(" <TotalNodes> %d </TotalNodes>\n", ch->getTotalDataNodes());
1872 if(hchunk)
1873 printf(" <TotalElements> %lld </TotalElements>\n",((TreeNode*) hchunk)->getTotalElements());
1874 else
1875 printf(" <TotalElements> 0 </TotalElements>\n");
1876 } else if (trieIndex == iType)
1878 printf(" <TrieNodes> \n");
1879 printf(" <TotalPages> %d </TotalPages>\n", ch->totalPages());
1880 printf(" <TotalNodes> %d </TotalNodes>\n", ch->getTotalDataNodes());
1881 printf(" </TrieNodes> \n <TrieValues>\n");
1882 ch = (Chunk*) hchunk;
1883 printf(" <TotalPages> %d </TotalPages>\n", ch->totalPages());
1884 printf(" <TotalNodes> %d </TotalNodes>\n", ch->getTotalDataNodes());
1885 printf(" </TrieValues>\n");
1886 } else
1888 printf("Unknown Index type\n");
1890 printf("<IndexNodes>\n");
1891 return OK;
1894 DbRetVal DatabaseManagerImpl::registerThread()
1896 DbRetVal rv = OK;
1897 if (pMgr_ != NULL)
1899 printError(ErrAlready, "Process already registered\n");
1900 return ErrAlready;
1902 pMgr_ = new ProcessManager();
1903 rv = pMgr_->registerThread();
1904 if (rv ==OK) {
1905 procSlot = pMgr_->getProcSlot();
1906 systemDatabase_->setProcSlot(procSlot);
1907 printDebug(DM_Process, "Process registed with slot %d\n", procSlot);
1909 return rv;
1912 DbRetVal DatabaseManagerImpl::deregisterThread()
1914 DbRetVal rv = OK;
1915 if (pMgr_ != NULL)
1917 rv = pMgr_->deregisterThread(procSlot);
1918 delete pMgr_;
1919 pMgr_ = NULL;
1921 return rv;
1924 bool DatabaseManagerImpl::isAnyOneRegistered()
1926 if (pMgr_ != NULL) return pMgr_->isAnyOneRegistered();
1927 return true;
1931 void DatabaseManagerImpl::printUsageStatistics()
1933 pMgr_->printUsageStatistics();
1934 tMgr_->printUsageStatistics();
1935 lMgr_->printUsageStatistics();
1938 void DatabaseManagerImpl::printDebugLockInfo()
1940 lMgr_->printDebugInfo();
1943 void DatabaseManagerImpl::printDebugTransInfo()
1945 tMgr_->printDebugInfo(systemDatabase_);
1947 void DatabaseManagerImpl::printDebugProcInfo()
1949 pMgr_->printDebugInfo();
1951 void DatabaseManagerImpl::printDebugMutexInfo()
1953 Database *db = sysDb();
1954 db->printDebugMutexInfo();
1955 Chunk *chunk;
1956 int id=1;
1957 printf("<Chunk Mutexes>\n");
1958 chunk=db->getSystemDatabaseChunk(UserChunkTableId);
1959 while(id<MAX_CHUNKS)
1961 chunk=db->getSystemDatabaseChunk(id);
1962 if((chunk->getChunkID())!=0){
1963 chunk->printMutexInfo();
1965 id++;
1967 chunk=db->getSystemDatabaseChunk(UserChunkTableId);
1968 size_t size=chunk->getSize();
1969 int noOfDataNodes=os::floor((PAGE_SIZE - sizeof(PageInfo))/size);
1970 Page* page=chunk->getFirstPage();
1971 int i=0;
1972 Chunk *chk;
1973 while(page)
1975 char *data = ((char*)page) + sizeof(PageInfo);
1976 for (i = 0; i< noOfDataNodes; i++)
1978 if (*((InUse*)data) == 1)
1980 chk=(Chunk*)((InUse*)data+1);
1981 chk->printMutexInfo();
1983 data = data + size;
1985 page = (PageInfo*)(((PageInfo*)page)->nextPage_) ;
1987 printf("</Chunk Mutexes>\n");
1988 lMgr_->printMutexInfo();
1990 void DatabaseManagerImpl::printDebugChunkInfo()
1992 Database *db = sysDb();
1993 Chunk *chunk;
1994 int id=1;
1995 printf("<Chunk information>\n");
1996 printf(" <System Chunk >\n");
1997 chunk=db->getSystemDatabaseChunk(UserChunkTableId);
1998 chunk->print();
1999 while(id<MAX_CHUNKS)
2001 chunk=db->getSystemDatabaseChunk(id);
2002 if((chunk->getChunkID())!=0){
2003 chunk->print();
2005 id++;
2007 printf(" </System Chunk >\n");
2008 printf(" <User Chunk >\n");
2009 chunk=db->getSystemDatabaseChunk(UserChunkTableId);
2010 size_t size=chunk->getSize();
2011 int noOfDataNodes=os::floor((PAGE_SIZE - sizeof(PageInfo))/size);
2012 Page* page=chunk->getFirstPage();
2013 int i=0;
2014 Chunk *chk;
2015 while(page)
2017 char *data = ((char*)page) + sizeof(PageInfo);
2018 for (i = 0; i< noOfDataNodes; i++)
2020 if (*((InUse*)data) == 1)
2022 chk=(Chunk*)((InUse*)data+1);
2023 chk->print();
2025 data = data + size;
2027 page = (PageInfo*)(((PageInfo*)page)->nextPage_) ;
2029 printf(" </User Chunk >\n");
2030 printf("</Chunk information>\n");
2031 return;
2033 ChunkIterator DatabaseManagerImpl::getSystemTableIterator(CatalogTableID id)
2035 Chunk *fChunk = systemDatabase_->getSystemDatabaseChunk(id);
2036 return fChunk->getIterator();
2039 Chunk* DatabaseManagerImpl::getSystemTableChunk(CatalogTableID id)
2041 return systemDatabase_->getSystemDatabaseChunk(id);
2044 int DatabaseManagerImpl::getNoOfPagesForTable(char *tblName)
2046 Table *tbl = openTable(tblName);
2047 if (NULL == tbl) {
2048 printError(ErrSysInternal, "Unable to open table %s", tblName);
2049 return 0;
2051 TableImpl *tb = (TableImpl *) tbl;
2052 int pages = 0;
2053 if (tb->numTuples()) pages = tb->pagesUsed();
2054 closeTable(tbl);
2055 return pages;
2058 DbRetVal DatabaseManagerImpl::loadRecords(char *tblName, char *buffer)
2060 // buffer should be as big as the no of pages occupied by the records
2061 Table *tbl = openTable(tblName);
2062 if (NULL == tbl) {
2063 printError(ErrSysInternal, "Unable to open table %s", tblName);
2064 return ErrSysInternal;
2066 TableImpl *tb = (TableImpl *) tbl;
2067 char *bufIter = buffer;
2068 int pages = *(int *) bufIter; bufIter += sizeof(int);
2069 Page *firstPage = ((Chunk *)(tb->chunkPtr_))->getFirstPage();
2070 PageInfo *pi = (PageInfo *) firstPage;
2071 memcpy(bufIter, pi, PAGE_SIZE);
2072 bufIter += PAGE_SIZE;
2073 for (int i = 0; i < pages - 1; i++) {
2074 Page *nPage = pi->nextPage_;
2075 memcpy(bufIter, nPage, PAGE_SIZE);
2076 bufIter += PAGE_SIZE;
2077 pi = (PageInfo *) nPage;
2079 closeTable(tbl);
2080 return OK;
2083 DbRetVal DatabaseManagerImpl::pasteRecords(char *tblName, void *buffer)
2085 // buffer should be as big as the no of pages occupied by the records
2086 Table *tbl = openTable(tblName);
2087 if (NULL == tbl) {
2088 printError(ErrSysInternal, "Unable to open table %s", tblName);
2089 return ErrSysInternal;
2091 TableImpl *tb = (TableImpl *) tbl;
2092 Database *db = tb->getDB();
2093 char *bufIter = (char *) buffer;
2094 int pages = *(int *) bufIter;
2095 bufIter += sizeof(int);
2097 Page *firstPage = ((Chunk *)(tb->chunkPtr_))->getFirstPage();
2098 PageInfo *pi = (PageInfo *) firstPage;
2099 memcpy(pi, bufIter, PAGE_SIZE);
2100 bufIter += PAGE_SIZE;
2101 while (--pages != 0) {
2102 //get a new page allocated
2103 Page *newPage = db->getFreePage();
2104 memcpy(newPage, bufIter, PAGE_SIZE);
2105 pi->nextPage_ = newPage;
2106 pi = (PageInfo *) newPage;
2108 // initialize chunk details and pageInfo
2109 ((Chunk *)tb->chunkPtr_)->curPage_ = pi;
2110 closeTable(tbl);
2111 return OK;
2114 void DatabaseManagerImpl::setCanTakeCheckPoint(bool ctcp)
2115 { systemDatabase_->setCanTakeCheckPoint(ctcp); }
2117 bool DatabaseManagerImpl::getCanTakeCheckPoint()
2118 { return systemDatabase_->getCanTakeCheckPoint(); }
2120 DbRetVal DatabaseManagerImpl::checkPoint()
2122 if (!systemDatabase_->getCanTakeCheckPoint()) {
2123 printf("Load / Cache / Replication process might be running. CheckPoint not taken\n");
2124 return ErrLoadingOn;
2126 DbRetVal rv = systemDatabase_->getXCheckpointMutex();
2127 if (OK != rv ) {
2128 printError(rv, "Unable to get checkpoint mutex");
2129 return ErrLockTimeOut;
2131 if (tMgr_ && !tMgr_->isTransactionConsistent(systemDatabase_)) {
2132 printf("not in transaction consistent point\n");
2133 systemDatabase_->releaseCheckpointMutex();
2134 return ErrLockTimeOut;
2136 rv = writeSchemaFile();
2137 if (rv != OK) {
2138 printError(ErrSysInternal, "checkpoint error");
2140 rv = db()->checkPoint();
2141 systemDatabase_->releaseCheckpointMutex();
2142 return rv;
2145 DbRetVal DatabaseManagerImpl::writeSchemaFile()
2147 DbRetVal rv = OK;
2148 FILE *fp = NULL;
2149 FILE *fp1 = NULL;
2150 int fd = -1;
2151 char schFile[MAX_FILE_LEN];
2152 char mapFile[MAX_FILE_LEN];
2153 sprintf(schFile, "%s/db.chkpt.schema1", Conf::config.getDbFile());
2154 sprintf(mapFile, "%s/db.chkpt.map1", Conf::config.getDbFile());
2155 fp = fopen(schFile, "r");
2156 if (fp != NULL) {
2157 fclose(fp);
2158 int ret = unlink(schFile);
2159 if( ret != 0) {
2160 printError(ErrOS, "checkpoint: delete schema file failed");
2161 return ErrOS;
2164 fp = fopen(schFile, "w+");
2165 if (fp == NULL) {
2166 printError(ErrOS, "Unable to create schema file for chkpt.");
2167 return ErrOS;
2169 fp1 = fopen(mapFile, "r");
2170 if (fp1 != NULL) {
2171 fclose(fp1);
2172 int ret = unlink(mapFile);
2173 if( ret != 0) {
2174 printError(ErrOS, "checkpoint: delete schema file failed");
2175 return ErrOS;
2178 fd = open(mapFile, O_WRONLY|O_CREAT, 0644);
2179 if (fd == -1) {
2180 printError(ErrOS, "checkpoint: Unable to create map file.");
2181 return ErrOS;
2183 List tableList = getAllTableNames();
2184 ListIterator iter = tableList.getIterator();
2185 Identifier *elem = NULL;
2186 int count =0;
2187 while (iter.hasElement()) {
2188 elem = (Identifier*) iter.nextElement();
2189 // if (TableConf::config.isTableCached(elem->name) == OK) continue;
2190 fprintf(fp, "CREATE TABLE %s (", elem->name);
2191 Table *table = openTable(elem->name);
2192 if (NULL == table) {
2193 printError(ErrSysInternal, "Unable to open table %s", elem->name);
2194 return ErrSysInternal;
2196 void *chunk = NULL; void *tptr = NULL; void *vcchunk = NULL;
2197 CatalogTableTABLE cTable(systemDatabase_);
2198 rv = cTable.getChunkAndTblPtr(elem->name, chunk, tptr, vcchunk);
2199 struct Object obj;
2200 strcpy(obj.name, elem->name);
2201 obj.type = Tbl;
2202 obj.bucketChunk = NULL;
2203 obj.firstPage = ((Chunk *)chunk)->getFirstPage();
2204 obj.curPage = ((Chunk *)chunk)->getCurrentPage();
2205 void *buf = &obj;
2206 write(fd, buf, sizeof(obj));
2207 FieldInfo *info = new FieldInfo();
2208 List fNameList = table->getFieldNameList();
2209 ListIterator fNameIter = fNameList.getIterator();
2210 count++;
2211 bool firstField=true;
2212 char fieldName[IDENTIFIER_LENGTH];
2213 while (fNameIter.hasElement()) {
2214 elem = (Identifier*) fNameIter.nextElement();
2215 Table::getFieldNameAlone(elem->name, fieldName);
2216 rv = table->getFieldInfo(elem->name, info);
2217 if (rv !=OK) {
2218 printf("unable to retrive info for table %s\n", elem->name);
2220 if (firstField) {
2221 fprintf(fp, "%s %s ", fieldName, AllDataType::getSQLString(info->type));
2222 firstField = false;
2223 } else
2224 fprintf(fp, ", %s %s ", fieldName, AllDataType::getSQLString(info->type));
2225 if (info->type == typeString || info->type == typeVarchar ||
2226 info->type == typeBinary)
2227 fprintf(fp, "(%d)",info->length);
2228 if (info->isNull) fprintf(fp, " NOT NULL ");
2229 if (info->isDefault) fprintf(fp, " DEFAULT '%s' ", info->defaultValueBuf);
2230 if (info->isAutoIncrement) fprintf(fp, " AUTO_INCREMENT ");
2232 fNameIter.reset();
2233 while (fNameIter.hasElement())
2234 delete ((FieldName *) fNameIter.nextElement());
2235 fNameList.reset();
2237 fprintf(fp, ");\n");
2238 table->printSQLIndexString(fp, fd);
2239 delete info;
2240 closeTable(table);
2242 ListIterator tIter = tableList.getIterator();
2243 tIter.reset();
2244 while (tIter.hasElement())
2245 delete ((FieldName *) tIter.nextElement());
2246 tableList.reset();
2248 fclose(fp);
2249 close(fd);
2250 return OK;
2253 DbRetVal DatabaseManagerImpl::recover()
2255 DbRetVal rv = OK;
2256 rv = sysDb()->recoverSystemDB();
2257 if (rv != OK) return rv;
2258 if (!Conf::config.useMmap())rv = db()->recoverUserDB();
2259 return rv;
2262 void DatabaseManagerImpl::sendSignal(int signal)
2264 ThreadInfo* tInfo = sysDb()->getThreadInfo(0);
2265 for (int i=0; i < Conf::config.getMaxProcs(); i++)
2267 if (tInfo->pid_ !=0) os::kill(tInfo->pid_, signal);
2268 tInfo++;