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()
30 void LockTable::setDb(Database
*sysDb_
)
32 systemDatabase_
= sysDb_
;
33 lockBuckets
= systemDatabase_
->getLockHashBuckets();
35 Bucket
* LockTable::getLockBucket(void *tuple
)
37 unsigned long key
=(unsigned long)tuple
;
38 int bucketNo
= key
% LOCK_BUCKET_SIZE
;
39 printDebug(DM_Lock
, "getLockBucket bucketno:%d",bucketNo
);
40 return &(lockBuckets
[bucketNo
]);
43 void LockTable::printUsageStatistics()
45 Bucket
* buckets
= systemDatabase_
->getLockHashBuckets();
47 LockHashNode
*lockNode
;
48 int nodeCount
=0, bucketCount
=0;
49 for (int i
=0; i
< LOCK_BUCKET_SIZE
; i
++)
51 bucket
= &(buckets
[i
]);
52 lockNode
= (LockHashNode
*) bucket
->bucketList_
;
53 if (lockNode
) bucketCount
++; else continue;
54 while (NULL
!= lockNode
) { nodeCount
++; lockNode
= lockNode
->next_
; }
56 printf("<LockTable>\n");
57 printf(" <TotalBuckets> %d </TotalBuckets>\n", LOCK_BUCKET_SIZE
);
58 printf(" <UsedBuckets> %d </UsedBuckets>\n", bucketCount
);
59 printf(" <TotalLockNodes> %d </TotalLockNodes>\n", nodeCount
);
60 printf("</LockTable>\n");
63 void LockTable::printMutexInfo()
65 Bucket
* buckets
= systemDatabase_
->getLockHashBuckets();
67 LockHashNode
*lockNode
;
68 int nodeCount
=0, bucketCount
=0;
69 printf("<LockTable>\n");
70 for (int i
=0; i
< LOCK_BUCKET_SIZE
; i
++)
72 bucket
= &(buckets
[i
]);
73 bucket
->mutex_
.print();
75 printf("</LockTable>\n");
78 void LockTable::printDebugInfo()
80 Bucket
* buckets
= systemDatabase_
->getLockHashBuckets();
82 LockHashNode
*lockNode
;
83 int nodeCount
=0, bucketCount
=0;
84 printf("<LockTable>\n");
85 for (int i
=0; i
< LOCK_BUCKET_SIZE
; i
++)
88 bucket
= &(buckets
[i
]);
89 //if (bucket) bucketCount++; else continue;
90 lockNode
= (LockHashNode
*) bucket
->bucketList_
;
92 while (NULL
!= lockNode
)
96 lockNode
= lockNode
->next_
;
100 printf(" <LockBucket> \n");
101 printf(" <BucketNo> %d </BucketNo> \n", i
);
102 printf(" <TotalNodes> %d </TotalNodes>\n", nodeCount
);
103 printf(" <LockBucket>\n");
107 printf(" <TotalUsedBuckets> %d </TotalUsedBuckets>\n", bucketCount
);
108 Chunk
*chunk
= systemDatabase_
->getSystemDatabaseChunk(LockTableId
);
109 printf(" <TotalPages> %d </TotalPages>\n", chunk
->totalPages());
110 printf("</LockTable>\n");
113 LockHashNode
* LockTable::getLockNode(void *tuple
, DbRetVal
&rv
, bool takeMutex
)
115 curBucket
= getLockBucket(tuple
);
118 int lockRet
= getBucketMutex();
121 printDebug(DM_Lock
, "Mutex is waiting for long time:May be deadlock");
122 printError(ErrLockTimeOut
, "Unable to get bucket mutex");
127 LockHashNode
*iter
= (LockHashNode
*) curBucket
->bucketList_
;
133 //Iterate though the list and find the element's lock info
136 if(iter
->ptrToTuple_
== tuple
) break;
137 printDebug(DM_Lock
, "Finding the lock node. iter:%x",iter
);
147 DbRetVal
LockTable::addNewLockNode(void *tuple
, Transaction
**trans
,
151 LockHashNode
*newNode
= allocLockNode(linfo
, tuple
, &rv
);
152 if (NULL
== newNode
) return rv
;
154 LockHashNode
*it
= (LockHashNode
*) curBucket
->bucketList_
;
157 curBucket
->bucketList_
= (void*)newNode
; //make it as head
158 (*trans
)->insertIntoHasList(systemDatabase_
, newNode
);
161 while (NULL
!= it
->next_
) it
= it
->next_
;
163 (*trans
)->insertIntoHasList(systemDatabase_
, newNode
);
166 DbRetVal
LockTable::releaseLock(LockHashNode
*node
)
169 node
->lInfo_
.noOfReaders_
= 0;
170 if (node
->lInfo_
.waitWriters_
== 0 || node
->lInfo_
.waitReaders_
==0)
172 int tries
= Conf::config
.getMutexRetries();
174 rv
= deallocLockNode(node
, curBucket
);
176 printError(ErrWarning
, "Fatal:Leak: Unable to dealloc lock node %d tries", Conf::config
.getMutexRetries());
180 }while (rv
== ErrLockTimeOut
);
181 printDebug(DM_Lock
, "Releasing exclusive lock and dealloc node:%x", node
);
185 printDebug(DM_Lock
, "Releasing exclusive lock");
190 LockHashNode
* LockTable::allocLockNode(LockInfo
&info
, void *tuple
, DbRetVal
*rv
)
193 Chunk
*chunk
= systemDatabase_
->getSystemDatabaseChunk(LockTableId
);
194 LockHashNode
*node
= NULL
; //(LockHashNode*)chunk->allocate(systemDatabase_, rv);
196 int totalTries
= Conf::config
.getMutexRetries();
197 while (tries
< totalTries
)
200 node
= (LockHashNode
*)chunk
->allocate(systemDatabase_
, rv
);
201 if (node
!=NULL
) break;
202 if (*rv
!= ErrLockTimeOut
)
204 printError(*rv
, "Unable to allocate hash index node");
211 printError(*rv
, "Unable to allocate lock node after %d retry", tries
);
214 node
->ptrToTuple_
= tuple
;
219 void LockTable::deallocLockNode(LockHashNode
*node
)
221 Chunk
*chunk
= systemDatabase_
->getSystemDatabaseChunk(LockTableId
);
222 chunk
->free(systemDatabase_
, node
);
225 DbRetVal
LockTable::deallocLockNode(LockHashNode
*node
, Bucket
*bucket
)
227 Chunk
*chunk
= systemDatabase_
->getSystemDatabaseChunk(LockTableId
);
228 LockHashNode
*nodeList
= (LockHashNode
*) bucket
->bucketList_
;
229 LockHashNode
*iter
= nodeList
, *prev
= nodeList
;
230 if (NULL
== nodeList
)
232 printError(ErrSysFatal
, "Fatal:Lock Bucket is NULL");
235 //If it is the first node, then make the bucket point to the next node
237 if (nodeList
== node
)
239 bucket
->bucketList_
= node
->next_
;
240 chunk
->free(systemDatabase_
, node
);
246 prev
->next_
= iter
->next_
;
247 chunk
->free(systemDatabase_
, node
);
253 printError(ErrSysFatal
, "Fatal: Lock node not found in bucket");
256 DbRetVal
LockTable::getBucketMutex()
258 int procSlot
= systemDatabase_
->procSlot
;
259 struct timeval timeout
, timeval
;
260 timeout
.tv_sec
= Conf::config
.getMutexSecs();
261 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
263 int totalTries
= Conf::config
.getMutexRetries() *2;
265 while (tries
< totalTries
)
267 ret
= curBucket
->mutex_
.getLock(procSlot
, true);
269 timeval
.tv_sec
= timeout
.tv_sec
;
270 timeval
.tv_usec
= timeout
.tv_usec
;
271 os::select(0, 0, 0, 0, &timeval
);
274 if (tries
>= totalTries
) return ErrLockTimeOut
;
277 void LockTable::releaseBucketMutex()
279 curBucket
->mutex_
.releaseLock(systemDatabase_
->procSlot
);