src/server/TransactionManager.cxx

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007 by www.databasecache.com                           *
00003  *   Contact: praba_tuty@databasecache.com                                 *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015   ***************************************************************************/
00016 #include<Transaction.h>
00017 #include<Lock.h>
00018 #include<Database.h>
00019 #include<Allocator.h>
00020 #include<CatalogTables.h>
00021 #include<Debug.h>
00022 #include<Config.h>
00023 #include<Process.h>
00024 
00025 void TransactionManager::printUsageStatistics()
00026 {
00027     Transaction *iter = firstTrans;
00028     int i=0, usedCount =0, freeCount =0, undoLogCount=0;
00029     for (; i < Conf::config.getMaxProcs(); i++)
00030     {
00031             if (iter->status_ == TransNotUsed) freeCount++; 
00032             else 
00033             { 
00034                 usedCount++;
00035                 undoLogCount += iter->noOfUndoLogs();
00036             }
00037             iter++;
00038     }
00039     printf("<TransactionTable>\n");
00040     printf("  <UsedSlots> %d </UsedSlots>\n", usedCount);
00041     printf("  <FreeSlots> %d </FreeSlots>\n", freeCount);
00042 
00043     printf("  <UndoLogs>\n");
00044     printf("    <TotalNodes> %d </TotalNodes>\n", undoLogCount);
00045     printf("  </UndoLogs>\n");
00046     printf("</TransactionTable>\n");
00047 
00048 }
00049 
00050 void TransactionManager::printDebugInfo(Database *sysdb)
00051 {
00052     Transaction *iter = firstTrans;
00053     int i=0, usedCount =0, freeCount =0, undoLogCount=0;
00054     printf("<TransactionTable>\n");
00055     for (; i < Conf::config.getMaxProcs(); i++)
00056     {
00057             if (iter->status_ == TransNotUsed) freeCount++; 
00058             else 
00059             { 
00060                 usedCount++;
00061                 undoLogCount += iter->noOfUndoLogs();
00062                 iter->printDebugInfo(sysdb);
00063             }
00064             iter++;
00065     }
00066 
00067     printf("  <UsedSlots> %d </UsedSlots>\n", usedCount);
00068     printf("  <FreeSlots> %d </FreeSlots>\n", freeCount);
00069 
00070     Chunk *chunk = sysdb->getSystemDatabaseChunk(UndoLogTableID);
00071 
00072     printf("  <UndoLogs>\n");
00073     printf("    <TotalNodes> %d </TotalNodes>\n", undoLogCount);
00074     printf("    <TotalPages> %d </TotalPages>\n", chunk->totalPages());
00075     printf("  </UndoLogs>\n");
00076     printf("</TransactionTable>\n");
00077 }
00078 
00079 
00080 DbRetVal TransactionManager::startTransaction(LockManager *lMgr, IsolationLevel level)
00081 {
00082     Database *sysdb = lMgr->systemDatabase_;
00083     Transaction *trans = ProcessManager::getThreadTransaction(sysdb->procSlot);
00084     if (NULL != trans)
00085     {
00086         if (trans->status_ != TransNotUsed) return ErrAlready; 
00087         else {
00088             //the previous transaction shall be used again
00089             trans->status_ = TransRunning;
00090             trans->isoLevel_ = level;
00091             printDebug(DM_Transaction, "Using the same transaction slot\n");
00092             return OK;
00093         }
00094 
00095     }
00096 
00097     DbRetVal rv = sysdb->getTransTableMutex();
00098     if (OK != rv)
00099     {
00100         printError(rv, "Unable to acquire transtable mutex");
00101         return rv;
00102     }
00103     Transaction *iter = firstTrans;
00104     int i;
00105     for (i =0 ; i < Conf::config.getMaxProcs(); i++)
00106     {
00107             if (iter->status_ == TransNotUsed) break;
00108             iter++;
00109     }
00110     // if Transaction table is full return error
00111     if (i == Conf::config.getMaxProcs()) {
00112         printError(ErrNoResource, "Transaction slots are full");
00113         sysdb->releaseTransTableMutex();
00114         return ErrNoResource;
00115     }
00116     printDebug(DM_Transaction, "Using transaction slot %d \n", i);
00117 
00118     //Make this free slot, as the current transaction and
00119     //set the state
00120     trans = iter;
00121     trans->status_ = TransRunning;
00122     trans->isoLevel_ = level;
00123     sysdb->releaseTransTableMutex();
00124     ProcessManager::setThreadTransaction(trans, sysdb->procSlot);
00125     return OK;
00126 }
00127 
00128 void TransactionManager::setFirstTrans(Transaction *trans)
00129 {
00130     firstTrans = trans;
00131 }
00132 
00133 
00134 DbRetVal TransactionManager::commit(LockManager *lockManager)
00135 {
00136     Database *sysdb = lockManager->systemDatabase_;
00137     Transaction *trans = ProcessManager::getThreadTransaction(sysdb->procSlot);
00138     if (NULL == trans)
00139     { 
00140        printError(ErrNotOpen, "No transaction started for this procSlot %d", sysdb->procSlot);
00141        return ErrNotOpen;
00142     }
00143     DbRetVal rv = sysdb->getTransTableMutex();
00144     if (OK != rv)
00145     {
00146         printError(rv, "Unable to acquire transtable mutex");
00147         return rv;
00148     }
00149 
00150     if (trans->status_ != TransRunning)
00151     {
00152         sysdb->releaseTransTableMutex(); 
00153         printError(ErrBadCall, "Transaction is not in running state %d\n", trans->status_);
00154         return ErrBadCall;
00155     }
00156     trans->status_ = TransCommitting;
00157     sysdb->releaseTransTableMutex();
00158 
00159     trans->releaseAllLocks(lockManager);
00160     if(NULL != trans->waitLock_)
00161     {
00162             printError(ErrSysInternal, "Trans WaitLock is not null\n");
00163             return ErrSysInternal;
00164     }
00165     //TODO::flush all redo logs to disk
00166     //TODO::remove all the logs in memory
00167     trans->removeUndoLogs(sysdb);
00168     rv = sysdb->getTransTableMutex();
00169     if (OK != rv)
00170     {
00171         printError(rv, "Unable to acquire transtable mutex");
00172         return rv;
00173     }
00174     trans->status_ = TransNotUsed;
00175     sysdb->releaseTransTableMutex();
00176     printDebug(DM_Transaction, "Committed transaction:%x",trans);
00177     return OK;
00178 }
00179 
00180 DbRetVal TransactionManager::rollback(LockManager *lockManager, Transaction *t)
00181 {
00182     Database *sysdb = lockManager->systemDatabase_;
00183     Transaction *trans;
00184     if (t == NULL)
00185         trans = ProcessManager::getThreadTransaction(sysdb->procSlot);
00186     else
00187         trans = t;
00188     if (NULL == trans)
00189     { 
00190        return OK;
00191     }
00192     DbRetVal rv= sysdb->getTransTableMutex();
00193     if (OK != rv)
00194     {
00195         printError(rv, "Unable to acquire transtable mutex");
00196         return rv;
00197     }
00198 
00199     if (trans->status_ != TransRunning)
00200     {
00201         sysdb->releaseTransTableMutex(); 
00202         //will be called during connection disconnect without starting transaction.
00203         return OK;
00204     }
00205     trans->status_ = TransAborting;
00206     sysdb->releaseTransTableMutex();
00207 
00208     trans->applyUndoLogs(sysdb);
00209     //TODO::remove all the logs in memory
00210     trans->releaseAllLocks(lockManager);
00211     if(NULL != trans->waitLock_)
00212     {
00213        printError(ErrSysInternal, "Trans waitlock is not null");
00214        return ErrSysInternal;
00215     }
00216 
00217     rv = sysdb->getTransTableMutex();
00218     if (OK != rv)
00219     {
00220         //nothing can be done.. go ahead and set it. 
00221         //no harm. parallel starttransaction will miss this slot. thats ok
00222         //as it is not leak
00223     }
00224     trans->status_ = TransNotUsed;
00225     sysdb->releaseTransTableMutex();
00226     printDebug(DM_Transaction, "Aborted transaction:%x",trans);
00227 
00228     return OK;
00229 }

Generated on Mon Jun 9 22:37:15 2008 for csql by  doxygen 1.4.7