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>
23 DbRetVal
Transaction::insertIntoHasList(Database
*sysdb
, LockHashNode
*node
)
26 Chunk
*chunk
= sysdb
->getSystemDatabaseChunk(TransHasTableId
);
28 TransHasNode
*hasNode
= (TransHasNode
*)chunk
->allocate(sysdb
, &rv
);
31 printError(rv
, "Could not allocate Lock node");
34 printDebug(DM_Transaction
, "insertIntoHasList new TransHasNode created:%x",
36 hasNode
->node_
= node
;
37 hasNode
->next_
= NULL
;
38 if (NULL
== hasLockList_
)
40 printDebug(DM_Transaction
, "hasLockList is null:It is now %x",hasNode
);
41 hasLockList_
= hasNode
;
45 TransHasNode
*it
= hasLockList_
;
46 while (NULL
!= it
->next_
) { it
= it
->next_
; }
48 printDebug(DM_Transaction
, "Added to hasLockList at end:%x",it
);
52 DbRetVal
Transaction::removeFromHasList(Database
*sysdb
, void *tuple
)
54 Chunk
*chunk
= sysdb
->getSystemDatabaseChunk(TransHasTableId
);
55 TransHasNode
*iter
= hasLockList_
, *prev
= hasLockList_
;
58 printError(ErrNotFound
, "There are no tuple lock in has list.");
63 if (tuple
== iter
->node_
->ptrToTuple_
)
65 prev
->next_
= iter
->next_
;
66 chunk
->free(sysdb
, iter
);
67 if (iter
== hasLockList_
) hasLockList_
= NULL
;
73 printError(ErrNotFound
, "There are no tuple lock in has list.");
78 DbRetVal
Transaction::releaseAllLocks(LockManager
*lockManager_
)
80 Database
*sysdb
=lockManager_
->systemDatabase_
;
81 Chunk
*chunk
= sysdb
->getSystemDatabaseChunk(TransHasTableId
);
82 TransHasNode
*iter
= hasLockList_
, *prev
;
87 printDebug(DM_Transaction
, "Releasing lock %x",prev
->node_
->ptrToTuple_
);
88 lockManager_
->releaseLock(prev
->node_
->ptrToTuple_
);
89 chunk
->free(sysdb
, prev
);
94 bool Transaction::findInHasList(Database
*sysdb
, LockHashNode
*node
)
96 TransHasNode
*iter
= hasLockList_
;
99 if (iter
->node_
== node
) return true;
105 DbRetVal
Transaction::appendUndoLog(Database
*sysdb
, OperationType type
,
106 void *data
, size_t size
)
109 UndoLogInfo
*logInfo
= createUndoLog(sysdb
, type
, data
, size
, &rv
);
110 if (logInfo
== NULL
) return rv
;
111 os::memcpy((char*)logInfo
+ sizeof(UndoLogInfo
), data
, size
);
113 printDebug(DM_Transaction
, "creating undo log and append %x optype:%d",
120 DbRetVal
Transaction::appendLogicalUndoLog(Database
*sysdb
, OperationType type
, void *data
, size_t size
, void* indexPtr
)
123 UndoLogInfo
*logInfo
= createUndoLog(sysdb
, type
, data
, size
, &rv
);
124 if (logInfo
== NULL
) return rv
;
125 char **indPtr
= (char**)((char*)logInfo
+ sizeof(UndoLogInfo
));
126 *indPtr
= (char*) indexPtr
;
128 printDebug(DM_Transaction
, "creating logical undo log and append %x optype:%d", logInfo
, type
);
132 DbRetVal
Transaction::appendLogicalHashUndoLog(Database
*sysdb
, OperationType type
, void *data
, size_t size
)
135 HashUndoLogInfo
*hInfo
= (HashUndoLogInfo
*) data
;
136 UndoLogInfo
*logInfo
= createUndoLog(sysdb
, type
, hInfo
->tuple_
, size
, &rv
);
137 if (logInfo
== NULL
) return rv
;
138 memcpy((char*)logInfo
+ sizeof(UndoLogInfo
), data
, sizeof(HashUndoLogInfo
));
140 printDebug(DM_Transaction
, "creating logical undo log and append %x optype:%d", logInfo
, type
);
144 UndoLogInfo
* Transaction::createUndoLog(Database
*sysdb
, OperationType type
, void *data
,
145 size_t size
, DbRetVal
*rv
)
147 Chunk
*chunk
= sysdb
->getSystemDatabaseChunk(UndoLogTableID
);
148 UndoLogInfo
*logInfo
= (UndoLogInfo
*)chunk
->allocate(sysdb
,
149 size
+ sizeof(UndoLogInfo
), rv
);
150 if (logInfo
== NULL
) {
151 printError(*rv
, "Unable to allocate undo log record\n");
154 logInfo
->opType_
= type
;
155 logInfo
->ptrToTuple_
= data
;
156 logInfo
->size_
= size
;
157 logInfo
->next_
= NULL
;
161 void Transaction::addAtBegin(UndoLogInfo
* logInfo
)
163 //add it to the begin of the log list
164 logInfo
->next_
= firstUndoLog_
;
165 firstUndoLog_
= logInfo
;
169 UndoLogInfo
* Transaction::popUndoLog()
171 UndoLogInfo
*iter
= firstUndoLog_
, *prev
= firstUndoLog_
;
177 firstUndoLog_
= iter
;
182 int Transaction::noOfUndoLogs()
184 UndoLogInfo
*iter
= firstUndoLog_
;
193 void Transaction::printDebugInfo(Database
*sysdb
)
195 printf("<TransactionInfo>\n");
196 if (waitLock_
!= NULL
)
198 printf("<WaitLock>");
200 printf("</WaitLock>");
203 printf("<UndoLogs>\n");
204 Chunk
*chunk
= sysdb
->getSystemDatabaseChunk(UndoLogTableID
);
205 printf(" <TotalPages> %d </TotalPages>\n", chunk
->totalPages());
206 UndoLogInfo
*iter
= firstUndoLog_
;
214 printf("</TotalNodes> %d </TotalNodes>\n", count
);
215 printf("</UndoLogs>\n");
217 printf("<TransHasList>\n");
218 chunk
= sysdb
->getSystemDatabaseChunk(TransHasTableId
);
219 printf(" <TotalPages> %d </TotalPages>\n", chunk
->totalPages());
220 TransHasNode
*hasIter
= hasLockList_
;
222 while (NULL
!= hasIter
)
225 hasIter
= hasIter
->next_
;
228 printf("</TotalNodes> %d </TotalNodes>\n", count
);
229 printf("</TransHasList>\n");
231 printf("</TransactionInfo>\n");
234 DbRetVal
Transaction::removeUndoLogs(Database
*sysdb
)
236 Chunk
*chunk
= sysdb
->getSystemDatabaseChunk(UndoLogTableID
);
237 UndoLogInfo
*logInfo
= NULL
;
238 while(NULL
!= (logInfo
= popUndoLog()))
240 chunk
->free(sysdb
, logInfo
);
246 DbRetVal
Transaction::applyUndoLogs(Database
*sysdb
)
248 Chunk
*chunk
= sysdb
->getSystemDatabaseChunk(UndoLogTableID
);
249 UndoLogInfo
*logInfo
= NULL
;
250 while(NULL
!= (logInfo
= popUndoLog()))
252 switch(logInfo
->opType_
)
254 case InsertOperation
:
256 int *isUsed
= ((int*)(logInfo
->ptrToTuple_
) - 1);
258 printError(ErrSysFatal
, "Fatal: Row is already not in use");
261 //May memcpy is not needed as no one will update this
262 //as lock is taken on this tuple
263 os::memcpy(logInfo
->ptrToTuple_
, (char*) logInfo
+
264 sizeof(UndoLogInfo
), logInfo
->size_
);
268 case DeleteOperation
:
270 int *isUsed
= ((int*)(logInfo
->ptrToTuple_
) - 1);
272 printError(ErrSysFatal
, "Fatal: Row is already in use");
275 os::memcpy(logInfo
->ptrToTuple_
, (char*) logInfo
+
276 sizeof(UndoLogInfo
), logInfo
->size_
);
279 case UpdateOperation
:
281 int *isUsed
= ((int*)(logInfo
->ptrToTuple_
) - 1);
283 printError(ErrSysFatal
, "Fatal: Row is not in use");
285 os::memcpy(logInfo
->ptrToTuple_
, (char*) logInfo
+
286 sizeof(UndoLogInfo
), logInfo
->size_
);
289 case InsertHashIndexOperation
:
290 HashIndex::deleteLogicalUndoLog(sysdb
, (char *)logInfo
291 + sizeof(UndoLogInfo
));
293 //case UpdateHashIndexOperation:
294 //HashIndex::updateLogicalUndoLog((char *)logInfo
295 // + sizeof(UndoLogInfo));
297 case DeleteHashIndexOperation
:
298 HashIndex::insertLogicalUndoLog(sysdb
, (char *)logInfo
299 + sizeof(UndoLogInfo
));
302 chunk
->free(sysdb
, logInfo
);