code reorg
[csql.git] / src / storage / TransactionManager.cxx
blob9bb9d67854942b984b2caaf1830820d5d5309d23
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<Transaction.h>
17 #include<Lock.h>
18 #include<Database.h>
19 #include<Allocator.h>
20 #include<CatalogTables.h>
21 #include<Debug.h>
22 #include<Config.h>
23 #include<Process.h>
25 void TransactionManager::printUsageStatistics()
27 Transaction *iter = firstTrans;
28 int i=0, usedCount =0, freeCount =0, undoLogCount=0;
29 for (; i < Conf::config.getMaxProcs(); i++)
31 if (iter->status_ == TransNotUsed || iter->status_ == TransReserved)
33 freeCount++;
35 else
37 usedCount++;
38 undoLogCount += iter->noOfUndoLogs();
40 iter++;
42 printf("<TransactionTable>\n");
43 printf(" <UsedSlots> %d </UsedSlots>\n", usedCount);
44 printf(" <FreeSlots> %d </FreeSlots>\n", freeCount);
46 printf(" <UndoLogs>\n");
47 printf(" <TotalNodes> %d </TotalNodes>\n", undoLogCount);
48 printf(" </UndoLogs>\n");
49 printf("</TransactionTable>\n");
53 void TransactionManager::printDebugInfo(Database *sysdb)
55 Transaction *iter = firstTrans;
56 int i=0, usedCount =0, freeCount =0, undoLogCount=0;
57 printf("<TransactionTable>\n");
58 for (; i < Conf::config.getMaxProcs(); i++)
60 if (iter->status_ == TransNotUsed || iter->status_ == TransReserved)
62 freeCount++;
64 else
66 usedCount++;
67 undoLogCount += iter->noOfUndoLogs();
68 iter->printDebugInfo(sysdb);
70 iter++;
73 printf(" <UsedSlots> %d </UsedSlots>\n", usedCount);
74 printf(" <FreeSlots> %d </FreeSlots>\n", freeCount);
76 Chunk *chunk = sysdb->getSystemDatabaseChunk(UndoLogTableID);
78 printf(" <UndoLogs>\n");
79 printf(" <TotalNodes> %d </TotalNodes>\n", undoLogCount);
80 printf(" <TotalPages> %d </TotalPages>\n", chunk->totalPages());
81 printf(" </UndoLogs>\n");
82 printf("</TransactionTable>\n");
86 DbRetVal TransactionManager::startTransaction(LockManager *lMgr, IsolationLevel level)
88 Database *sysdb = lMgr->systemDatabase_;
89 Transaction *trans = ProcessManager::getThreadTransaction(sysdb->procSlot);
90 if (NULL != trans)
92 trans->printTotalNodes();
93 if (trans->status_ != TransReserved) return ErrAlready;
94 else if (trans->status_ == TransReserved)
96 //the previous transaction shall be used again
97 //trans->status_ = TransRunning;
98 if ( 0 != Mutex::CASGen(&trans->status_, TransReserved, TransRunning))
100 printError(ErrLockTimeOut, "unable to get lock to reuse the transaction");
101 return ErrLockTimeOut;
103 trans->isoLevel_ = level;
104 printDebug(DM_Transaction, "Using the same transaction slot\n");
105 logFinest(Conf::logger, "Transaction Start:Reusing :%x", trans);
106 return OK;
111 DbRetVal rv = sysdb->getTransTableMutex();
112 if (OK != rv)
114 printError(rv, "Unable to acquire transtable mutex");
115 return rv;
117 Transaction *iter = firstTrans;
118 int i;
119 for (i =0 ; i < Conf::config.getMaxProcs(); i++)
121 if (iter->status_ == TransNotUsed) break;
122 iter++;
124 // if Transaction table is full return error
125 if (i == Conf::config.getMaxProcs()) {
126 printError(ErrNoResource, "Transaction slots are full");
127 sysdb->releaseTransTableMutex();
128 return ErrNoResource;
130 printDebug(DM_Transaction, "Using transaction slot %d \n", i);
132 //Make this free slot, as the current transaction and
133 //set the state
134 trans = iter;
135 //trans->status_ = TransRunning;
136 if ( 0 != Mutex::CASGen(&trans->status_ , TransNotUsed, TransRunning)) {
137 printError(ErrLockTimeOut, "Unable to start transaction. Timeout. Retry..");
138 sysdb->releaseTransTableMutex();
139 return ErrLockTimeOut;
141 trans->isoLevel_ = level;
142 ProcessManager::setThreadTransaction(trans, sysdb->procSlot);
143 sysdb->releaseTransTableMutex();
144 //trans->printTotalNodes();
145 logFinest(Conf::logger, "Transaction Start:Using :%x", trans);
146 return OK;
149 void TransactionManager::setFirstTrans(Transaction *trans)
151 firstTrans = trans;
154 DbRetVal TransactionManager::commit(LockManager *lockManager)
156 Database *sysdb = lockManager->systemDatabase_;
157 Transaction *trans = ProcessManager::getThreadTransaction(sysdb->procSlot);
158 DbRetVal rv = OK;
159 if (NULL == trans)
161 printError(ErrNotOpen, "No transaction started for this procSlot %d", sysdb->procSlot);
162 return ErrNotOpen;
164 rv = trans->releaseAllLocks(lockManager);
165 if (rv != OK) {
166 printError(ErrSysInternal, "Fatal:Unable to release all the locks\n");
168 if(NULL != trans->waitLock_)
170 printError(ErrSysInternal, "Fatal:Trans WaitLock is not null\n");
172 trans->removeUndoLogs(sysdb);
173 if ( 0 != Mutex::CASGen(&trans->status_, TransRunning, TransReserved))
175 printError(ErrSysFatal, "Transaction state corrupted %d\n", trans->status_);
176 return ErrSysFatal;
178 printDebug(DM_Transaction, "Committed transaction:%x",trans);
179 logFinest(Conf::logger, "Transaction Committed:%x", trans);
180 return OK;
183 DbRetVal TransactionManager::rollback(LockManager *lockManager, Transaction *t)
185 Database *sysdb = lockManager->systemDatabase_;
186 Transaction *trans = NULL;
187 DbRetVal rv = OK;
188 if (t == NULL)
189 trans = ProcessManager::getThreadTransaction(sysdb->procSlot);
190 else
191 trans = t;
192 if (NULL == trans)
194 return OK;
197 if (trans->status_ != TransRunning)
199 //sysdb->releaseTransTableMutex();
200 //will be called during connection disconnect without starting transaction.
201 return OK;
204 trans->applyUndoLogs(sysdb);
205 rv = trans->releaseAllLocks(lockManager);
206 if (rv != OK) {
207 printError(ErrSysInternal, "Fatal:Unable to release all the locks");
209 if(NULL != trans->waitLock_)
211 printError(ErrSysInternal, "Fatal:Trans waitlock is not null");
212 //return ErrSysInternal;
215 //trans->status_ = TransNotUsed;
216 if ( 0 != Mutex::CASGen(&trans->status_, TransRunning, TransReserved))
218 printError(ErrSysFatal, "Fatal:Unable to abort transaction %d\n", trans->status_);
219 return ErrSysFatal;
221 printDebug(DM_Transaction, "Aborted transaction:%x",trans);
222 logFinest(Conf::logger, "Transaction Aborted:%x", trans);
223 return OK;
226 bool TransactionManager::isTransactionConsistent(Database *sysdb)
228 DbRetVal rv = sysdb->getTransTableMutex();
229 if (OK != rv)
231 printError(rv, "Unable to acquire transtable mutex");
232 return false;
234 Transaction *iter = firstTrans;
235 int i;
236 for (i =0 ; i < Conf::config.getMaxProcs(); i++)
238 if (iter->status_ == TransRunning && iter->noOfUndoLogs()) {
239 printError( ErrSysInternal, "Transaction slot %d not consistent status:%d undoLogs:%d\n",i, iter->status_, iter->noOfUndoLogs());
240 sysdb->releaseTransTableMutex();
241 return false;
243 iter++;
245 sysdb->releaseTransTableMutex();
246 return true;