commiting changes from enterprise version for V2.4
[csql.git] / src / storage / Transaction.cxx
blobbaf56bf9aa15914f187dfd20ae6462b1beddb470
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>
23 DbRetVal Transaction::insertIntoHasList(Database *sysdb, LockHashNode *node)
25 //allocate lock node
26 Chunk *chunk = sysdb->getSystemDatabaseChunk(TransHasTableId);
27 DbRetVal rv = OK;
28 TransHasNode *hasNode = (TransHasNode*)chunk->allocate(sysdb, &rv);
29 if (NULL == hasNode)
31 printError(rv, "Could not allocate Lock node");
32 return rv;
34 printDebug(DM_Transaction, "insertIntoHasList new TransHasNode created:%x",
35 hasNode);
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;
42 return OK;
45 TransHasNode *it = hasLockList_;
46 while (NULL != it->next_) { it = it->next_; }
47 it->next_ = hasNode;
48 printDebug(DM_Transaction, "Added to hasLockList at end:%x",it);
49 return OK;
52 DbRetVal Transaction::removeFromHasList(Database *sysdb, void *tuple)
54 Chunk *chunk = sysdb->getSystemDatabaseChunk(TransHasTableId);
55 TransHasNode *iter = hasLockList_, *prev = hasLockList_;
56 if (NULL == iter)
58 printError(ErrNotFound, "There are no tuple lock in has list.");
59 return ErrNotFound;
61 while (iter != NULL)
63 if (tuple == iter->node_->ptrToTuple_)
65 prev->next_ = iter->next_;
66 chunk->free(sysdb, iter);
67 if (iter == hasLockList_) hasLockList_ = NULL;
68 return OK;
70 prev = iter;
71 iter = iter->next_;
73 printError(ErrNotFound, "There are no tuple lock in has list.");
74 return ErrNotFound;
78 DbRetVal Transaction::releaseAllLocks(LockManager *lockManager_)
80 Database *sysdb =lockManager_->systemDatabase_;
81 Chunk *chunk = sysdb->getSystemDatabaseChunk(TransHasTableId);
82 TransHasNode *iter = hasLockList_, *prev;
83 while (NULL != iter)
85 prev = iter;
86 iter = iter->next_;
87 printDebug(DM_Transaction, "Releasing lock %x",prev->node_->ptrToTuple_);
88 lockManager_->releaseLock(prev->node_->ptrToTuple_);
89 chunk->free(sysdb, prev);
91 hasLockList_ = NULL;
92 return OK;
94 bool Transaction::findInHasList(Database *sysdb, LockHashNode *node)
96 TransHasNode *iter = hasLockList_;
97 while (NULL != iter)
99 if (iter->node_ == node) return true;
100 iter = iter->next_;
102 return false;
105 DbRetVal Transaction::appendUndoLog(Database *sysdb, OperationType type,
106 void *data, size_t size)
108 DbRetVal rv =OK;
109 UndoLogInfo *logInfo = createUndoLog(sysdb, type, data, size, &rv);
110 if (logInfo == NULL) return rv;
111 os::memcpy((char*)logInfo + sizeof(UndoLogInfo), data, size);
112 addAtBegin(logInfo);
113 printDebug(DM_Transaction, "creating undo log and append %x optype:%d",
114 logInfo, type);
115 return OK;
120 DbRetVal Transaction::appendLogicalUndoLog(Database *sysdb, OperationType type, void *data, size_t size, void* indexPtr)
122 DbRetVal rv = OK;
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;
127 addAtBegin(logInfo);
128 printDebug(DM_Transaction, "creating logical undo log and append %x optype:%d", logInfo, type);
129 return rv;
132 DbRetVal Transaction::appendLogicalHashUndoLog(Database *sysdb, OperationType type, void *data, size_t size)
134 DbRetVal rv = OK;
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));
139 addAtBegin(logInfo);
140 printDebug(DM_Transaction, "creating logical undo log and append %x optype:%d", logInfo, type);
141 return rv;
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");
152 return NULL;
154 logInfo->opType_ = type;
155 logInfo->ptrToTuple_ = data;
156 logInfo->size_ = size;
157 logInfo->next_ = NULL;
158 return logInfo;
161 void Transaction::addAtBegin(UndoLogInfo* logInfo)
163 //add it to the begin of the log list
164 logInfo->next_ = firstUndoLog_;
165 firstUndoLog_ = logInfo;
166 return;
169 UndoLogInfo* Transaction::popUndoLog()
171 UndoLogInfo *iter = firstUndoLog_, *prev = firstUndoLog_;
172 if(NULL != iter)
174 prev = iter;
175 iter = iter->next_;
177 firstUndoLog_ = iter;
178 return prev;
182 int Transaction::noOfUndoLogs()
184 UndoLogInfo *iter = firstUndoLog_;
185 int count =0;
186 while(NULL != iter)
188 count++;
189 iter = iter->next_;
191 return count;
193 void Transaction::printDebugInfo(Database *sysdb)
195 printf("<TransactionInfo>\n");
196 if (waitLock_ != NULL)
198 printf("<WaitLock>");
199 waitLock_->print();
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_;
207 int count =0;
208 while(NULL != iter)
210 iter->print();
211 iter = iter->next_;
212 count++;
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_;
221 count =0;
222 while (NULL != hasIter)
224 hasIter->print();
225 hasIter = hasIter->next_;
226 count++;
228 printf("</TotalNodes> %d </TotalNodes>\n", count);
229 printf("</TransHasList>\n");
231 printf("</TransactionInfo>\n");
232 return ;
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);
242 return OK;
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:
255 *((int*)(logInfo->ptrToTuple_) - 1) = 0;
256 //May memcpy is not needed as no one will update this
257 //as lock is taken on this tuple
258 os::memcpy(logInfo->ptrToTuple_, (char*) logInfo +
259 sizeof(UndoLogInfo), logInfo->size_);
260 break;
261 case DeleteOperation:
262 *((int*)(logInfo->ptrToTuple_) - 1) = 1;
263 os::memcpy(logInfo->ptrToTuple_, (char*) logInfo +
264 sizeof(UndoLogInfo), logInfo->size_);
265 break;
266 case UpdateOperation:
267 os::memcpy(logInfo->ptrToTuple_, (char*) logInfo +
268 sizeof(UndoLogInfo), logInfo->size_);
269 break;
271 case InsertHashIndexOperation:
272 HashIndex::deleteLogicalUndoLog(sysdb, (char *)logInfo
273 + sizeof(UndoLogInfo));
274 break;
275 //case UpdateHashIndexOperation:
276 //HashIndex::updateLogicalUndoLog((char *)logInfo
277 // + sizeof(UndoLogInfo));
278 //break;
279 case DeleteHashIndexOperation:
280 HashIndex::insertLogicalUndoLog(sysdb, (char *)logInfo
281 + sizeof(UndoLogInfo));
282 break;
284 chunk->free(sysdb, logInfo);
286 return OK;