1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 ***************************************************************************/
16 #include<Transaction.h>
20 #include<CatalogTables.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
++;
35 undoLogCount
+= iter
->noOfUndoLogs();
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
++;
61 undoLogCount
+= iter
->noOfUndoLogs();
62 iter
->printDebugInfo(sysdb
);
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
);
86 trans
->printTotalNodes();
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
);
105 DbRetVal rv
= sysdb
->getTransTableMutex();
108 printError(rv
, "Unable to acquire transtable mutex");
111 Transaction
*iter
= firstTrans
;
113 for (i
=0 ; i
< Conf::config
.getMaxProcs(); i
++)
115 if (iter
->status_
== TransNotUsed
) break;
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
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
);
143 void TransactionManager::setFirstTrans(Transaction
*trans
)
148 DbRetVal
TransactionManager::commit(LockManager
*lockManager
)
150 Database
*sysdb
= lockManager
->systemDatabase_
;
151 Transaction
*trans
= ProcessManager::getThreadTransaction(sysdb
->procSlot
);
155 printError(ErrNotOpen
, "No transaction started for this procSlot %d", sysdb
->procSlot
);
158 rv
= trans
->releaseAllLocks(lockManager
);
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_
);
172 printDebug(DM_Transaction
, "Committed transaction:%x",trans
);
173 logFinest(Conf::logger
, "Transaction Committed:%x", trans
);
177 DbRetVal
TransactionManager::rollback(LockManager
*lockManager
, Transaction
*t
)
179 Database
*sysdb
= lockManager
->systemDatabase_
;
180 Transaction
*trans
= NULL
;
183 trans
= ProcessManager::getThreadTransaction(sysdb
->procSlot
);
191 if (trans
->status_
!= TransRunning
)
193 //sysdb->releaseTransTableMutex();
194 //will be called during connection disconnect without starting transaction.
198 trans
->applyUndoLogs(sysdb
);
199 rv
= trans
->releaseAllLocks(lockManager
);
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_
);
215 printDebug(DM_Transaction
, "Aborted transaction:%x",trans
);
216 logFinest(Conf::logger
, "Transaction Aborted:%x", trans
);
219 bool TransactionManager::isTransactionConsistent(Database
*sysdb
)
221 DbRetVal rv
= sysdb
->getTransTableMutex();
224 printError(rv
, "Unable to acquire transtable mutex");
227 Transaction
*iter
= firstTrans
;
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();
238 sysdb
->releaseTransTableMutex();