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
) 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
) 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 if (trans
->status_
!= TransNotUsed
) return ErrAlready
;
88 //the previous transaction shall be used again
89 trans
->status_
= TransRunning
;
90 trans
->isoLevel_
= level
;
91 printDebug(DM_Transaction
, "Using the same transaction slot\n");
97 DbRetVal rv
= sysdb
->getTransTableMutex();
100 printError(rv
, "Unable to acquire transtable mutex");
103 Transaction
*iter
= firstTrans
;
105 for (i
=0 ; i
< Conf::config
.getMaxProcs(); i
++)
107 if (iter
->status_
== TransNotUsed
) break;
110 // if Transaction table is full return error
111 if (i
== Conf::config
.getMaxProcs()) {
112 printError(ErrNoResource
, "Transaction slots are full");
113 sysdb
->releaseTransTableMutex();
114 return ErrNoResource
;
116 printDebug(DM_Transaction
, "Using transaction slot %d \n", i
);
118 //Make this free slot, as the current transaction and
121 trans
->status_
= TransRunning
;
122 trans
->isoLevel_
= level
;
123 sysdb
->releaseTransTableMutex();
124 ProcessManager::setThreadTransaction(trans
, sysdb
->procSlot
);
128 void TransactionManager::setFirstTrans(Transaction
*trans
)
134 DbRetVal
TransactionManager::commit(LockManager
*lockManager
)
136 Database
*sysdb
= lockManager
->systemDatabase_
;
137 Transaction
*trans
= ProcessManager::getThreadTransaction(sysdb
->procSlot
);
140 printError(ErrNotOpen
, "No transaction started for this procSlot %d", sysdb
->procSlot
);
143 DbRetVal rv
= sysdb
->getTransTableMutex();
146 printError(rv
, "Unable to acquire transtable mutex");
150 if (trans
->status_
!= TransRunning
)
152 sysdb
->releaseTransTableMutex();
153 printError(ErrBadCall
, "Transaction is not in running state %d\n", trans
->status_
);
156 trans
->status_
= TransCommitting
;
157 sysdb
->releaseTransTableMutex();
159 trans
->releaseAllLocks(lockManager
);
160 if(NULL
!= trans
->waitLock_
)
162 printError(ErrSysInternal
, "Trans WaitLock is not null\n");
163 return ErrSysInternal
;
165 //TODO::flush all redo logs to disk
166 //TODO::remove all the logs in memory
167 trans
->removeUndoLogs(sysdb
);
168 rv
= sysdb
->getTransTableMutex();
171 printError(rv
, "Unable to acquire transtable mutex");
174 trans
->status_
= TransNotUsed
;
175 sysdb
->releaseTransTableMutex();
176 printDebug(DM_Transaction
, "Committed transaction:%x",trans
);
180 DbRetVal
TransactionManager::rollback(LockManager
*lockManager
, Transaction
*t
)
182 Database
*sysdb
= lockManager
->systemDatabase_
;
185 trans
= ProcessManager::getThreadTransaction(sysdb
->procSlot
);
192 DbRetVal rv
= sysdb
->getTransTableMutex();
195 printError(rv
, "Unable to acquire transtable mutex");
199 if (trans
->status_
!= TransRunning
)
201 sysdb
->releaseTransTableMutex();
202 //will be called during connection disconnect without starting transaction.
205 trans
->status_
= TransAborting
;
206 sysdb
->releaseTransTableMutex();
208 trans
->applyUndoLogs(sysdb
);
209 //TODO::remove all the logs in memory
210 trans
->releaseAllLocks(lockManager
);
211 if(NULL
!= trans
->waitLock_
)
213 printError(ErrSysInternal
, "Trans waitlock is not null");
214 return ErrSysInternal
;
217 rv
= sysdb
->getTransTableMutex();
220 //nothing can be done.. go ahead and set it.
221 //no harm. parallel starttransaction will miss this slot. thats ok
224 trans
->status_
= TransNotUsed
;
225 sysdb
->releaseTransTableMutex();
226 printDebug(DM_Transaction
, "Aborted transaction:%x",trans
);