Merge branch 'master' into 2.3beta-2.5beta
[csql/przemoc.git] / src / storage / Transaction.cxx
blob296d420e2def9bda3c7a526fbb54f53c27e2300d
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:
256 int *isUsed = ((int*)(logInfo->ptrToTuple_) - 1);
257 if (*isUsed == 0) {
258 printError(ErrSysFatal, "Fatal: Row is already not in use");
260 *isUsed = 0;
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_);
265 break;
267 break;
268 case DeleteOperation:
270 int *isUsed = ((int*)(logInfo->ptrToTuple_) - 1);
271 if (*isUsed == 1) {
272 printError(ErrSysFatal, "Fatal: Row is already in use");
274 *isUsed = 1;
275 os::memcpy(logInfo->ptrToTuple_, (char*) logInfo +
276 sizeof(UndoLogInfo), logInfo->size_);
277 break;
279 case UpdateOperation:
281 int *isUsed = ((int*)(logInfo->ptrToTuple_) - 1);
282 if (*isUsed == 0) {
283 printError(ErrSysFatal, "Fatal: Row is not in use");
285 os::memcpy(logInfo->ptrToTuple_, (char*) logInfo +
286 sizeof(UndoLogInfo), logInfo->size_);
287 break;
289 case InsertHashIndexOperation:
290 HashIndex::deleteLogicalUndoLog(sysdb, (char *)logInfo
291 + sizeof(UndoLogInfo));
292 break;
293 //case UpdateHashIndexOperation:
294 //HashIndex::updateLogicalUndoLog((char *)logInfo
295 // + sizeof(UndoLogInfo));
296 //break;
297 case DeleteHashIndexOperation:
298 HashIndex::insertLogicalUndoLog(sysdb, (char *)logInfo
299 + sizeof(UndoLogInfo));
300 break;
302 chunk->free(sysdb, logInfo);
304 return OK;