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 ***************************************************************************/
19 #include<CatalogTables.h>
20 #include<Transaction.h>
24 LockTable::LockTable()
27 LockTable::~LockTable()
31 void LockTable::setDb(Database
*sysDb_
)
33 systemDatabase_
= sysDb_
;
34 lockBuckets
= systemDatabase_
->getLockHashBuckets();
37 Bucket
* LockTable::getLockBucket(void *tuple
)
39 unsigned long key
=(unsigned long)tuple
;
40 int bucketNo
= key
% LOCK_BUCKET_SIZE
;
41 printDebug(DM_Lock
, "getLockBucket bucketno:%d",bucketNo
);
42 return &(lockBuckets
[bucketNo
]);
45 void LockTable::printUsageStatistics()
47 Bucket
* buckets
= systemDatabase_
->getLockHashBuckets();
49 LockHashNode
*lockNode
;
50 int nodeCount
=0, bucketCount
=0;
51 for (int i
=0; i
< LOCK_BUCKET_SIZE
; i
++)
53 bucket
= &(buckets
[i
]);
54 lockNode
= (LockHashNode
*) bucket
->bucketList_
;
55 if (lockNode
) bucketCount
++; else continue;
56 while (NULL
!= lockNode
) { nodeCount
++; lockNode
= lockNode
->next_
; }
58 printf("<LockTable>\n");
59 printf(" <TotalBuckets> %d </TotalBuckets>\n", LOCK_BUCKET_SIZE
);
60 printf(" <UsedBuckets> %d </UsedBuckets>\n", bucketCount
);
61 printf(" <TotalLockNodes> %d </TotalLockNodes>\n", nodeCount
);
62 printf("</LockTable>\n");
65 void LockTable::printMutexInfo()
67 Bucket
* buckets
= systemDatabase_
->getLockHashBuckets();
69 LockHashNode
*lockNode
;
70 int nodeCount
=0, bucketCount
=0;
71 printf("<LockTable>\n");
72 for (int i
=0; i
< LOCK_BUCKET_SIZE
; i
++)
74 bucket
= &(buckets
[i
]);
75 bucket
->mutex_
.print();
77 printf("</LockTable>\n");
80 void LockTable::printDebugInfo()
82 Bucket
* buckets
= systemDatabase_
->getLockHashBuckets();
84 LockHashNode
*lockNode
;
85 int nodeCount
=0, bucketCount
=0;
86 printf("<LockTable>\n");
87 for (int i
=0; i
< LOCK_BUCKET_SIZE
; i
++)
90 bucket
= &(buckets
[i
]);
91 //if (bucket) bucketCount++; else continue;
92 lockNode
= (LockHashNode
*) bucket
->bucketList_
;
94 while (NULL
!= lockNode
)
98 lockNode
= lockNode
->next_
;
102 printf(" <LockBucket> \n");
103 printf(" <BucketNo> %d </BucketNo> \n", i
);
104 printf(" <TotalNodes> %d </TotalNodes>\n", nodeCount
);
105 printf(" <LockBucket>\n");
109 printf(" <TotalUsedBuckets> %d </TotalUsedBuckets>\n", bucketCount
);
110 Chunk
*chunk
= systemDatabase_
->getSystemDatabaseChunk(LockTableId
);
111 printf(" <TotalPages> %d </TotalPages>\n", chunk
->totalPages());
112 printf("</LockTable>\n");
116 LockHashNode
* LockTable::getLockNode(void *tuple
, DbRetVal
&rv
, bool takeMutex
)
118 curBucket
= getLockBucket(tuple
);
121 int lockRet
= getBucketMutex();
124 printDebug(DM_Lock
, "Mutex is waiting for long time:May be deadlock");
125 printError(ErrLockTimeOut
, "Unable to get bucket mutex");
130 LockHashNode
*iter
= (LockHashNode
*) curBucket
->bucketList_
;
136 //Iterate though the list and find the element's lock info
139 if(iter
->ptrToTuple_
== tuple
) break;
140 printDebug(DM_Lock
, "Finding the lock node. iter:%x",iter
);
150 DbRetVal
LockTable::addNewLockNode(void *tuple
, Transaction
**trans
,
154 LockHashNode
*newNode
= allocLockNode(linfo
, tuple
, &rv
);
155 if (NULL
== newNode
) return rv
;
157 LockHashNode
*it
= (LockHashNode
*) curBucket
->bucketList_
;
160 curBucket
->bucketList_
= (void*)newNode
; //make it as head
161 (*trans
)->insertIntoHasList(systemDatabase_
, newNode
);
164 while (NULL
!= it
->next_
) it
= it
->next_
;
166 (*trans
)->insertIntoHasList(systemDatabase_
, newNode
);
170 DbRetVal
LockTable::releaseLock(LockHashNode
*node
)
173 node
->lInfo_
.noOfReaders_
= 0;
174 if (node
->lInfo_
.waitWriters_
== 0 || node
->lInfo_
.waitReaders_
==0)
176 int tries
= Conf::config
.getMutexRetries();
178 rv
= deallocLockNode(node
, curBucket
);
180 printError(ErrWarning
, "Fatal:Leak: Unable to dealloc lock node %d tries", Conf::config
.getMutexRetries());
184 }while (rv
== ErrLockTimeOut
);
185 printDebug(DM_Lock
, "Releasing exclusive lock and dealloc node:%x", node
);
189 printDebug(DM_Lock
, "Releasing exclusive lock");
194 LockHashNode
* LockTable::allocLockNode(LockInfo
&info
, void *tuple
, DbRetVal
*rv
)
197 Chunk
*chunk
= systemDatabase_
->getSystemDatabaseChunk(LockTableId
);
198 LockHashNode
*node
= NULL
;
200 int totalTries
= Conf::config
.getMutexRetries();
201 while (tries
< totalTries
)
204 node
= (LockHashNode
*)chunk
->allocate(systemDatabase_
, rv
);
205 if (node
!=NULL
) break;
206 if (*rv
!= ErrLockTimeOut
)
208 printError(*rv
, "Unable to allocate hash index node");
215 printError(*rv
, "Unable to allocate lock node after %d retry", tries
);
218 node
->ptrToTuple_
= tuple
;
224 void LockTable::deallocLockNode(LockHashNode
*node
)
226 Chunk
*chunk
= systemDatabase_
->getSystemDatabaseChunk(LockTableId
);
227 chunk
->free(systemDatabase_
, node
);
231 DbRetVal
LockTable::deallocLockNode(LockHashNode
*node
, Bucket
*bucket
)
233 Chunk
*chunk
= systemDatabase_
->getSystemDatabaseChunk(LockTableId
);
234 LockHashNode
*nodeList
= (LockHashNode
*) bucket
->bucketList_
;
235 LockHashNode
*iter
= nodeList
, *prev
= nodeList
;
236 if (NULL
== nodeList
)
238 printError(ErrSysFatal
, "Fatal:Lock Bucket is NULL");
241 //If it is the first node, then make the bucket point to the next node
243 if (nodeList
== node
)
245 bucket
->bucketList_
= node
->next_
;
246 chunk
->free(systemDatabase_
, node
);
252 prev
->next_
= iter
->next_
;
253 chunk
->free(systemDatabase_
, node
);
259 printError(ErrSysFatal
, "Fatal: Lock node not found in bucket");
263 DbRetVal
LockTable::getBucketMutex()
265 int procSlot
= systemDatabase_
->procSlot
;
266 struct timeval timeout
, timeval
;
267 timeout
.tv_sec
= Conf::config
.getMutexSecs();
268 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
270 int totalTries
= Conf::config
.getMutexRetries() *2;
272 while (tries
< totalTries
)
274 ret
= curBucket
->mutex_
.getLock(procSlot
, true);
276 timeval
.tv_sec
= timeout
.tv_sec
;
277 timeval
.tv_usec
= timeout
.tv_usec
;
278 os::select(0, 0, 0, 0, &timeval
);
281 if (tries
>= totalTries
) return ErrLockTimeOut
;
285 void LockTable::releaseBucketMutex()
287 curBucket
->mutex_
.releaseLock(systemDatabase_
->procSlot
);