lock manager and chunk allocation mutex modificationsw
[csql.git] / src / storage / TransactionManager.cxx
blobcd1c4f129546633e2f817a426f3a05a317cc3e74
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) freeCount++;
32 else
34 usedCount++;
35 undoLogCount += iter->noOfUndoLogs();
37 iter++;
39 printf("<TransactionTable>\n");
40 printf(" <UsedSlots> %d </UsedSlots>\n", usedCount);
41 printf(" <FreeSlots> %d </FreeSlots>\n", freeCount);
43 printf(" <UndoLogs>\n");
44 printf(" <TotalNodes> %d </TotalNodes>\n", undoLogCount);
45 printf(" </UndoLogs>\n");
46 printf("</TransactionTable>\n");
50 void TransactionManager::printDebugInfo(Database *sysdb)
52 Transaction *iter = firstTrans;
53 int i=0, usedCount =0, freeCount =0, undoLogCount=0;
54 printf("<TransactionTable>\n");
55 for (; i < Conf::config.getMaxProcs(); i++)
57 if (iter->status_ == TransNotUsed || iter->status_ == TransReserved) freeCount++;
58 else
60 usedCount++;
61 undoLogCount += iter->noOfUndoLogs();
62 iter->printDebugInfo(sysdb);
64 iter++;
67 printf(" <UsedSlots> %d </UsedSlots>\n", usedCount);
68 printf(" <FreeSlots> %d </FreeSlots>\n", freeCount);
70 Chunk *chunk = sysdb->getSystemDatabaseChunk(UndoLogTableID);
72 printf(" <UndoLogs>\n");
73 printf(" <TotalNodes> %d </TotalNodes>\n", undoLogCount);
74 printf(" <TotalPages> %d </TotalPages>\n", chunk->totalPages());
75 printf(" </UndoLogs>\n");
76 printf("</TransactionTable>\n");
80 DbRetVal TransactionManager::startTransaction(LockManager *lMgr, IsolationLevel level)
82 Database *sysdb = lMgr->systemDatabase_;
83 Transaction *trans = ProcessManager::getThreadTransaction(sysdb->procSlot);
84 if (NULL != trans)
86 trans->printTotalNodes();
87 //
88 if (trans->status_ != TransReserved) return ErrAlready;
89 else if (trans->status_ == TransReserved)
91 //the previous transaction shall be used again
92 //trans->status_ = TransRunning;
93 if ( 0 != Mutex::CASGen(&trans->status_, TransReserved, TransRunning)) {
94 printError(ErrLockTimeOut, "unable to get lock to reuse the transaction");
95 return ErrLockTimeOut;
97 trans->isoLevel_ = level;
98 printDebug(DM_Transaction, "Using the same transaction slot\n");
99 logFinest(Conf::logger, "Transaction Start:Reusing :%x", trans);
100 return OK;
105 DbRetVal rv = sysdb->getTransTableMutex();
106 if (OK != rv)
108 printError(rv, "Unable to acquire transtable mutex");
109 return rv;
111 Transaction *iter = firstTrans;
112 int i;
113 for (i =0 ; i < Conf::config.getMaxProcs(); i++)
115 if (iter->status_ == TransNotUsed) break;
116 iter++;
118 // if Transaction table is full return error
119 if (i == Conf::config.getMaxProcs()) {
120 printError(ErrNoResource, "Transaction slots are full");
121 sysdb->releaseTransTableMutex();
122 return ErrNoResource;
124 printDebug(DM_Transaction, "Using transaction slot %d \n", i);
126 //Make this free slot, as the current transaction and
127 //set the state
128 trans = iter;
129 //trans->status_ = TransRunning;
130 if ( 0 != Mutex::CASGen(&trans->status_ , TransNotUsed, TransRunning)) {
131 printError(ErrLockTimeOut, "Unable to start transaction. Timeout. Retry..");
132 sysdb->releaseTransTableMutex();
133 return ErrLockTimeOut;
135 trans->isoLevel_ = level;
136 ProcessManager::setThreadTransaction(trans, sysdb->procSlot);
137 sysdb->releaseTransTableMutex();
138 //trans->printTotalNodes();
139 logFinest(Conf::logger, "Transaction Start:Using :%x", trans);
140 return OK;
143 void TransactionManager::setFirstTrans(Transaction *trans)
145 firstTrans = trans;
148 DbRetVal TransactionManager::commit(LockManager *lockManager)
150 Database *sysdb = lockManager->systemDatabase_;
151 Transaction *trans = ProcessManager::getThreadTransaction(sysdb->procSlot);
152 DbRetVal rv = OK;
153 if (NULL == trans)
155 printError(ErrNotOpen, "No transaction started for this procSlot %d", sysdb->procSlot);
156 return ErrNotOpen;
158 rv = trans->releaseAllLocks(lockManager);
159 if (rv != OK) {
160 printError(ErrSysInternal, "Fatal:Unable to release all the locks\n");
162 if(NULL != trans->waitLock_)
164 printError(ErrSysInternal, "Fatal:Trans WaitLock is not null\n");
166 trans->removeUndoLogs(sysdb);
167 if ( 0 != Mutex::CASGen(&trans->status_, TransRunning, TransReserved))
169 printError(ErrSysFatal, "Transaction state corrupted %d\n", trans->status_);
170 return ErrSysFatal;
172 printDebug(DM_Transaction, "Committed transaction:%x",trans);
173 logFinest(Conf::logger, "Transaction Committed:%x", trans);
174 return OK;
177 DbRetVal TransactionManager::rollback(LockManager *lockManager, Transaction *t)
179 Database *sysdb = lockManager->systemDatabase_;
180 Transaction *trans = NULL;
181 DbRetVal rv = OK;
182 if (t == NULL)
183 trans = ProcessManager::getThreadTransaction(sysdb->procSlot);
184 else
185 trans = t;
186 if (NULL == trans)
188 return OK;
191 if (trans->status_ != TransRunning)
193 //sysdb->releaseTransTableMutex();
194 //will be called during connection disconnect without starting transaction.
195 return OK;
198 trans->applyUndoLogs(sysdb);
199 rv = trans->releaseAllLocks(lockManager);
200 if (rv != OK) {
201 printError(ErrSysInternal, "Fatal:Unable to release all the locks");
203 if(NULL != trans->waitLock_)
205 printError(ErrSysInternal, "Fatal:Trans waitlock is not null");
206 //return ErrSysInternal;
209 //trans->status_ = TransNotUsed;
210 if ( 0 != Mutex::CASGen(&trans->status_, TransRunning, TransReserved))
212 printError(ErrSysFatal, "Fatal:Unable to abort transaction %d\n", trans->status_);
213 return ErrSysFatal;
215 printDebug(DM_Transaction, "Aborted transaction:%x",trans);
216 logFinest(Conf::logger, "Transaction Aborted:%x", trans);
217 return OK;
219 bool TransactionManager::isTransactionConsistent(Database *sysdb)
221 DbRetVal rv = sysdb->getTransTableMutex();
222 if (OK != rv)
224 printError(rv, "Unable to acquire transtable mutex");
225 return false;
227 Transaction *iter = firstTrans;
228 int i;
229 for (i =0 ; i < Conf::config.getMaxProcs(); i++)
231 if (iter->status_ == TransRunning && iter->noOfUndoLogs()) {
232 printError( ErrSysInternal, "Transaction slot %d not consistent status:%d undoLogs:%d\n",i, iter->status_, iter->noOfUndoLogs());
233 sysdb->releaseTransTableMutex();
234 return false;
236 iter++;
238 sysdb->releaseTransTableMutex();
239 return true;