src/server/LockManager.cxx

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007 by www.databasecache.com                           *
00003  *   Contact: praba_tuty@databasecache.com                                 *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015   ***************************************************************************/
00016 #include<Lock.h>
00017 #include<Allocator.h>
00018 #include<Database.h>
00019 #include<CatalogTables.h>
00020 #include<Transaction.h>
00021 #include<Debug.h>
00022 #include<Config.h>
00023 #include<Process.h>
00024 Bucket* LockManager::getLockBucket(void *tuple)
00025 {
00026    int noOfBuckets = LOCK_BUCKET_SIZE;
00027    Bucket* buckets = systemDatabase_->getLockHashBuckets();
00028    unsigned long key =(unsigned long)tuple ;
00029    int bucketNo = HashIndex::computeHashBucket(typeULong, &key, noOfBuckets);
00030 
00031    Bucket *bucket = &(buckets[bucketNo]);
00032    printDebug(DM_Lock, "getLockBucket bucketno:%d bucket:%x",bucketNo, bucket);
00033    return bucket;
00034 }
00035 
00036 void LockManager::printUsageStatistics()
00037 {
00038    Bucket* buckets = systemDatabase_->getLockHashBuckets();
00039    Bucket* bucket;
00040    LockHashNode *lockNode;
00041    int nodeCount =0, bucketCount =0;
00042    for (int i =0; i< LOCK_BUCKET_SIZE; i++)
00043    {
00044        bucket = &(buckets[i]);
00045        lockNode = (LockHashNode*) bucket->bucketList_;
00046        if (lockNode) bucketCount++; else continue;
00047        while (NULL != lockNode) { nodeCount++; lockNode = lockNode->next_; }
00048    }
00049    printf("<LockTable>\n");
00050    printf("  <TotalBuckets> %d  </TotalBuckets>\n", LOCK_BUCKET_SIZE);
00051    printf("  <UsedBuckets> %d  </UsedBuckets>\n", bucketCount);
00052    printf("  <TotalLockNodes> %d  </TotalLockNodes>\n", nodeCount);
00053    printf("</LockTable>\n");
00054 
00055 }
00056 
00057 void LockManager::printDebugInfo()
00058 {
00059    Bucket* buckets = systemDatabase_->getLockHashBuckets();
00060    Bucket* bucket;
00061    LockHashNode *lockNode;
00062    int nodeCount =0, bucketCount =0;
00063    printf("<LockTable>\n");
00064    for (int i =0; i< LOCK_BUCKET_SIZE; i++)
00065    {
00066        nodeCount =0;
00067        bucket = &(buckets[i]);
00068        //if (bucket) bucketCount++; else continue;
00069        lockNode = (LockHashNode*) bucket->bucketList_;
00070 
00071        while (NULL != lockNode) 
00072        { 
00073            nodeCount++; 
00074            lockNode->print();
00075            lockNode = lockNode->next_; 
00076        }
00077        if (nodeCount) {
00078            bucketCount++;
00079            printf("  <LockBucket> \n");
00080            printf("    <BucketNo> %d </BucketNo> \n", i); 
00081            printf("    <TotalNodes> %d </TotalNodes>\n", nodeCount); 
00082            printf("  <LockBucket>\n");
00083        }
00084    }
00085 
00086    printf("  <TotalUsedBuckets> %d </TotalUsedBuckets>\n", bucketCount); 
00087    Chunk *chunk = systemDatabase_->getSystemDatabaseChunk(LockTableId);
00088    printf("  <TotalPages> %d </TotalPages>\n", chunk->totalPages()); 
00089    printf("</LockTable>\n");
00090 
00091 }
00092 
00093 DbRetVal LockManager::getSharedLock(void *tuple, Transaction **trans)
00094 {
00095    //get the bucket list
00096    //take the bucket mutex for read
00097    //go the the next level bucket list
00098    //get the bucket iterator
00099    //go the node where the lock info resides
00100    //check which mode the lock is taken
00101    // if shared then
00102    //      upgrade the bucket mutex to write
00103    //      take it and increment the readers count
00104    //      release bucket mutex and exit
00105    // if exclusive then
00106    //       go into the loop
00107    //       upgrade the bucket mutex to write
00108    //       increment waitReaders count
00109    //       release the bucket mutex
00110    //       wait for timeout period or (takes shared lock and release it ) till it becomes free.
00111    //       if times out
00112    //            take bucket mutex for write
00113    //            decrement waitReaders count
00114    //            releaese bucket mutex
00115 
00116    //            return
00117    //       if it becomes free
00118    //            take bucket mutex for write
00119    //            increment readers
00120    //            releaese bucket mutex
00121 
00122    //            return
00123    LockInfo linfo;
00124    linfo.noOfReaders_ = 1;
00125    //keeping it ready for the allocation, because when
00126    //lock node is not present in the list, then it means we are the first
00127    //to acquire lock so for sure we will get it.
00128    printDebug(DM_Lock, "LockManager::getSharedLock Begin");
00129    Bucket *bucket = getLockBucket(tuple);
00130    int lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot);
00131    if (lockRet != 0)
00132    {
00133        printDebug(DM_Lock, "LockManager::getSharedLock:End-Unable to get mutex");
00134        printError(ErrLockTimeOut,"Unable to acquire bucket mutex");
00135        return ErrLockTimeOut;
00136    }
00137    LockHashNode *lockNode = (LockHashNode*) bucket->bucketList_;
00138    if (NULL == lockNode)
00139    {
00140         DbRetVal rv = OK;
00141         LockHashNode *node = allocLockNode(linfo, tuple, &rv);
00142         if (NULL == node)
00143         {
00144             printError(rv, "Could not allocate Lock node");
00145             return rv;
00146             }
00147         printDebug(DM_Lock, "Bucket list is null: Allocating new LockHashNode %x", node);
00148         bucket->bucketList_ = (void*)node; //make it as head
00149         bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00150         rv = OK;
00151         if (trans != NULL) 
00152             rv = (*trans)->insertIntoHasList(systemDatabase_, node);
00153         if (rv !=OK) linfo.noOfReaders_--;
00154         printDebug(DM_Lock, "LockManager::getSharedLock End");
00155         return rv;
00156    }
00157    LockHashNode *cachedLockNode = NULL;
00158 
00159    LockHashNode *iter = lockNode;
00160    //Iterate though the list and find the element's lock info
00161    while(iter != NULL)
00162    {
00163        if(iter->ptrToTuple_ == tuple)
00164        {
00165            if (iter->lInfo_.noOfReaders_ == -1)
00166            {
00167 
00168                iter->lInfo_.waitReaders_++;
00169                        cachedLockNode = iter;
00170                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00171                if (trans != NULL) (*trans)->updateWaitLock(iter);
00172                printDebug(DM_Lock, "lock node:%x exclusive locked",iter);
00173                break;
00174            }
00175            else if (iter->lInfo_.noOfReaders_ == 0)
00176            {
00177                if(iter->lInfo_.waitWriters_ >0)
00178                {
00179                    iter->lInfo_.waitReaders_++;
00180                    cachedLockNode = iter;
00181                    bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00182                    if (trans != NULL) (*trans)->updateWaitLock(iter);
00183                    printDebug(DM_Lock, "lock node:%x Writers waiting.",iter);
00184                    break;
00185                }
00186                else
00187                {
00188                    iter->lInfo_.noOfReaders_++;
00189                    bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00190                    DbRetVal rv = OK;
00191                    if (trans != NULL) 
00192                      rv = (*trans)->insertIntoHasList(systemDatabase_, iter);
00193                    if (rv != OK) iter->lInfo_.noOfReaders_--;
00194                    printDebug(DM_Lock, "lock node:%x First to take shared lock",
00195                                                                           iter);
00196                    printDebug(DM_Lock, "LockManager::getSharedLock End");
00197                    return rv;
00198                 }
00199            }else
00200            {
00201                iter->lInfo_.noOfReaders_++;
00202                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00203                DbRetVal rv = OK;
00204                if (trans != NULL) 
00205                  rv = (*trans)->insertIntoHasList(systemDatabase_, iter);
00206                if (rv != OK) iter->lInfo_.noOfReaders_--;
00207                printDebug(DM_Lock, "lock node:%x incr readers",iter);
00208                printDebug(DM_Lock, "LockManager::getSharedLock End");
00209                return rv;
00210            }
00211        }
00212        printDebug(DM_Lock, "Finding the lock node. iter:%x",iter);
00213        iter = iter->next_;
00214    }
00215    if (NULL == cachedLockNode)
00216    {
00217         DbRetVal rv =OK;
00218         LockHashNode *node = allocLockNode(linfo, tuple, &rv);
00219         if (NULL == node)
00220         {
00221             bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00222             printError(rv, "Could not allocate Lock node");
00223             if (trans != NULL) (*trans)->removeWaitLock();
00224             return rv;
00225         }
00226         printDebug(DM_Lock,"Not Found.Created new lock node:%x",node);
00227         LockHashNode *it = lockNode;
00228         while (NULL != it->next_) it = it->next_;
00229         it->next_ = node;
00230         bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00231         rv = OK;
00232         if (trans != NULL) 
00233           rv = (*trans)->insertIntoHasList(systemDatabase_, node);
00234         if (rv != OK) linfo.noOfReaders_--;
00235         if (trans != NULL) (*trans)->removeWaitLock();
00236         printDebug(DM_Lock, "LockManager::getSharedLock End");
00237         return rv;
00238    }
00239    //bucket->mutex_.releaseLock();
00240    int tries = 0;
00241    int ret = 0;
00242    struct timeval timeout;
00243    timeout.tv_sec = Conf::config.getLockSecs();
00244    timeout.tv_usec = Conf::config.getLockUSecs();
00245 
00246    //printDebug(DM_Lock, "Trying to get mutex: for bucket %x\n", bucket);
00247    while (tries < Conf::config.getLockRetries())
00248    {
00249        lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot);
00250        if (lockRet != 0)
00251        {
00252            printDebug(DM_Lock, "Mutex is waiting for long time:May be deadlock");
00253            printDebug(DM_Lock, "LockManager::getSharedLock End");
00254            printError(ErrLockTimeOut, "Unable to get bucket mutex");
00255            if (trans != NULL) (*trans)->removeWaitLock();
00256            return ErrLockTimeOut;
00257        }
00258        if (cachedLockNode->lInfo_.noOfReaders_ == 0)
00259        {
00260            //if there are waiters allow then to take the lock
00261            if (cachedLockNode->lInfo_.waitWriters_ <0)
00262            {
00263                cachedLockNode->lInfo_.noOfReaders_++;
00264                cachedLockNode->lInfo_.waitReaders_--;
00265                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00266                DbRetVal rv = OK;
00267                if (trans != NULL) 
00268                  rv = (*trans)->insertIntoHasList(systemDatabase_, cachedLockNode);
00269                if (rv !=OK) {
00270                    cachedLockNode->lInfo_.noOfReaders_--;
00271                    cachedLockNode->lInfo_.waitReaders_++;
00272                    if (trans != NULL) (*trans)->removeWaitLock();
00273                    return rv;
00274                }
00275                if (trans != NULL) (*trans)->removeWaitLock();
00276                printDebug(DM_Lock, "LockManager::getSharedLock End");
00277                return OK;
00278            }
00279        } else if (cachedLockNode->lInfo_.noOfReaders_ == -1)
00280        {
00281            if (trans !=NULL && (*trans)->findInHasList(systemDatabase_, cachedLockNode))
00282            {
00283                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00284                if (trans != NULL) (*trans)->removeWaitLock();
00285                printDebug(DM_Lock, "LockManager::getSharedLock End");
00286                return OK;
00287            }
00288        } else
00289        {
00290            cachedLockNode->lInfo_.noOfReaders_++;
00291            cachedLockNode->lInfo_.waitReaders_--;
00292            bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00293            DbRetVal rv =OK;
00294            if (trans != NULL) 
00295               rv = (*trans)->insertIntoHasList(systemDatabase_, cachedLockNode);
00296            if (rv !=OK) {
00297                cachedLockNode->lInfo_.noOfReaders_--;
00298                cachedLockNode->lInfo_.waitReaders_++;
00299            }
00300            if (trans != NULL) (*trans)->removeWaitLock();
00301            printDebug(DM_Lock, "LockManager::getSharedLock End");
00302            return rv;
00303        }
00304 
00305        bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00306        os::select(0, 0, 0, 0, &timeout);
00307        tries++;
00308        printDebug(DM_Lock, "Trying to lock the lock node:%x iteration:%d",cachedLockNode, tries);
00309    }
00310    printDebug(DM_Lock, "Mutex is waiting for long time:May be deadlock");
00311    printDebug(DM_Lock, "LockManager::getSharedLock End");
00312    printError(ErrLockTimeOut, "Unable to acquire lock for long time.Timed out");
00313    if (trans != NULL) (*trans)->removeWaitLock();
00314    return ErrLockTimeOut;
00315 
00316 }
00317 
00318 DbRetVal LockManager::getExclusiveLock(void *tuple, Transaction **trans)
00319 {
00320    LockInfo linfo;
00321    linfo.noOfReaders_ = -1;
00322    printDebug(DM_Lock, "LockManager::getExclusiveLock Begin");
00323    //keeping it ready for the allocation, because when
00324    //lock node is not present in the list, then it means we are the first
00325    //to acquire lock so for sure we will get it.
00326 
00327    Bucket *bucket = getLockBucket(tuple);
00328    int lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot);
00329    if (lockRet != 0)
00330    {
00331        printDebug(DM_Lock, "Unable to acquire bucket mutex:May be deadlock");
00332        printError(ErrLockTimeOut, "Unable to acquire bucket mutex");
00333        return ErrLockTimeOut;
00334    }
00335    LockHashNode *lockNode = (LockHashNode*) bucket->bucketList_;
00336    if (NULL == lockNode)
00337    {
00338         DbRetVal rv = OK;
00339         LockHashNode *node = allocLockNode(linfo, tuple, &rv);
00340         if (NULL == node)
00341         {
00342             printError(rv, "Could not allocate Lock node");
00343             return rv;
00344         }
00345         printDebug(DM_Lock, "No head. So new lock node allocated:%x",node);
00346         bucket->bucketList_ = (void*)node; //make it as head
00347         bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00348         rv =OK;
00349         if (trans != NULL) 
00350            rv = (*trans)->insertIntoHasList(systemDatabase_, node);
00351         if (rv !=OK) linfo.noOfReaders_ = 0;
00352         printDebug(DM_Lock, "LockManager::getExclusiveLock End");
00353         return rv;
00354 
00355    }
00356    LockHashNode *cachedLockNode = NULL;
00357 
00358    LockHashNode *iter = lockNode;
00359    //Iterate though the list and find the element's lock info
00360    while(iter != NULL)
00361    {
00362        if(iter->ptrToTuple_ == tuple)
00363        {
00364            if (iter->lInfo_.noOfReaders_ != 0)
00365            {
00366                iter->lInfo_.waitWriters_++;
00367                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00368                if (trans != NULL) (*trans)->updateWaitLock(iter);
00369                cachedLockNode = iter;
00370                printDebug(DM_Lock, "Either some one has exclusive or shared lock:%x",iter);
00371                break;
00372            }
00373            else
00374            {
00375                iter->lInfo_.noOfReaders_ = -1;
00376                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00377                DbRetVal rv =OK;
00378                if (trans != NULL) 
00379                  rv = (*trans)->insertIntoHasList(systemDatabase_, iter);
00380                if (rv != OK) iter->lInfo_.noOfReaders_ = 0;
00381                printDebug(DM_Lock, "LockManager::getExclusiveLock End");
00382                return rv;
00383            }
00384        }
00385        printDebug(DM_Lock, "Finding the lock node. iter:%x",iter);
00386        iter = iter->next_;
00387    }
00388    if (NULL == cachedLockNode)
00389    {
00390         DbRetVal rv =OK;
00391         LockHashNode *node = allocLockNode(linfo, tuple, &rv);
00392         if (NULL == node)
00393         {
00394             bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00395             if (trans != NULL) (*trans)->updateWaitLock(NULL);
00396             printError(rv, "Could not allocate Lock node");
00397             return rv;
00398         }
00399         printDebug(DM_Lock, "Not Found:Creating new lock node:%x",node);
00400         LockHashNode *it = lockNode;
00401         while (NULL != it->next_) it = it->next_;
00402         it->next_ = node;
00403         bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00404         rv = OK;
00405         if (trans != NULL) 
00406           rv = (*trans)->insertIntoHasList(systemDatabase_, node);
00407         if (rv != OK) linfo.noOfReaders_ = 0;
00408          if (trans != NULL) (*trans)->removeWaitLock();
00409         printDebug(DM_Lock, "LockManager::getExclusiveLock End");
00410         return rv;
00411    }
00412    //bucket->mutex_.releaseLock();
00413    int tries = 0;
00414    int ret = 0;
00415    struct timeval timeout;
00416    timeout.tv_sec = Conf::config.getLockSecs();
00417    timeout.tv_usec = Conf::config.getLockUSecs();
00418 
00419    while (tries < Conf::config.getLockRetries())
00420    {
00421        lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot);
00422        if (lockRet != 0)
00423        {
00424            printError(ErrLockTimeOut, "Unable to get bucket mutex");
00425            return ErrLockTimeOut;
00426        }
00427        if (cachedLockNode->lInfo_.noOfReaders_ == 0)
00428        {
00429            cachedLockNode->lInfo_.noOfReaders_ = -1;
00430            cachedLockNode->lInfo_.waitWriters_--;
00431            bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00432            DbRetVal rv ;
00433            if (trans != NULL) 
00434                rv = (*trans)->insertIntoHasList(systemDatabase_, cachedLockNode);
00435            if (trans != NULL) (*trans)->removeWaitLock();
00436            printDebug(DM_Lock, "LockManager::getExclusiveLock End");
00437            return rv;
00438        }else if ( cachedLockNode->lInfo_.noOfReaders_ == 1)
00439        {
00440            if (trans !=NULL && (*trans)->findInHasList(systemDatabase_, cachedLockNode))
00441            {
00442                printDebug(DM_Lock, "upgrading shared to exclusive lock:%x",
00443                                                            cachedLockNode);
00444                //upgrade it to exclusive lock
00445                cachedLockNode->lInfo_.noOfReaders_ = -1;
00446                cachedLockNode->lInfo_.waitWriters_--;
00447                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00448                if (trans != NULL) (*trans)->removeWaitLock();
00449                printDebug(DM_Lock, "LockManager::getExclusiveLock End");
00450                return OK;
00451            }
00452            if (trans ==NULL && ProcessManager::hasLockList.exists(cachedLockNode->ptrToTuple_))
00453            {
00454                printDebug(DM_Lock, "upgrading shared to exclusive lock:%x",
00455                                                            cachedLockNode);
00456                //upgrade it to exclusive lock
00457                cachedLockNode->lInfo_.noOfReaders_ = -1;
00458                cachedLockNode->lInfo_.waitWriters_--;
00459                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00460                if (trans != NULL) (*trans)->removeWaitLock();
00461                printDebug(DM_Lock, "LockManager::getExclusiveLock End");
00462                return OK;
00463            }
00464        }else if ( cachedLockNode->lInfo_.noOfReaders_ == -1)
00465        {
00466            if (trans !=NULL && (*trans)->findInHasList(systemDatabase_, cachedLockNode))
00467            {
00468                printDebug(DM_Lock, "You already have exclusive lock:%x",
00469                                                         cachedLockNode);
00470                cachedLockNode->lInfo_.waitWriters_--;
00471                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00472                if (trans != NULL) (*trans)->removeWaitLock();
00473                printDebug(DM_Lock, "LockManager::getExclusiveLock End");
00474                return OK;
00475            }
00476            if (trans ==NULL && ProcessManager::hasLockList.exists(cachedLockNode->ptrToTuple_))
00477            {
00478                printDebug(DM_Lock, "You already have exclusive lock:%x",
00479                                                            cachedLockNode);
00480                cachedLockNode->lInfo_.waitWriters_--;
00481                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00482                if (trans != NULL) (*trans)->removeWaitLock();
00483                printDebug(DM_Lock, "LockManager::getExclusiveLock End");
00484                return OK;
00485            }
00486        }
00487        bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00488        os::select(0, 0, 0, 0, &timeout);
00489        tries++;
00490        printDebug(DM_Lock, "Trying to lock the lock node:%x iteration:%d",cachedLockNode, tries);
00491    }
00492    printDebug(DM_Lock, "LockManager::getExclusiveLock End");
00493    if (trans != NULL) (*trans)->removeWaitLock();
00494    printError(ErrLockTimeOut, "Unable to acquire lock for long time.Timed out");
00495    return ErrLockTimeOut;
00496 }
00497 
00498 DbRetVal LockManager::releaseLock(void *tuple)
00499 {
00500    LockInfo linfo;
00501    linfo.noOfReaders_ = 0;
00502    //keeping it ready for the allocation, because when
00503    //lock node is not present in the list, then it means we are the first
00504    //to acquire lock so for sure we will get it.
00505    printDebug(DM_Lock, "LockManager:releaseLock Start");
00506    Bucket *bucket = getLockBucket(tuple);
00507    printDebug(DM_Lock,"Bucket is %x", bucket);
00508    int lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot);
00509    if (lockRet != 0)
00510    {
00511        printDebug(DM_Lock, "Mutex is waiting for long time:May be deadlock");
00512        printDebug(DM_Lock, "LockManager:releaseLock End");
00513        printError(ErrLockTimeOut, "Unable to get bucket mutex");
00514        return ErrLockTimeOut;
00515    }
00516    LockHashNode *lockNode = (LockHashNode*) bucket->bucketList_;
00517    if (NULL == lockNode)
00518    {
00519        bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00520        printDebug(DM_Lock, "LockManager:releaseLock End");
00521        printError(ErrSysFatal, "Lock Element Not found: Probable Data Corruption.\n");
00522        return ErrSysFatal;
00523    }
00524 
00525    LockHashNode *iter = lockNode;
00526    //Iterate though the list and find the element's lock info
00527    while(iter != NULL)
00528    {
00529        if(iter->ptrToTuple_ == tuple)
00530        {
00531 
00532            if (iter->lInfo_.noOfReaders_ == -1)
00533            {
00534                iter->lInfo_.noOfReaders_ = 0;
00535                if (iter->lInfo_.waitWriters_ == 0 || iter->lInfo_.waitReaders_ ==0)
00536                {
00537                    deallocLockNode(iter, bucket);
00538                    bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00539                    printDebug(DM_Lock, "Releasing exclusive lock and dealloc node:%x",
00540                                                                                 iter);
00541                    printDebug(DM_Lock, "LockManager:releaseLock End");
00542                    return OK;
00543                }
00544                else
00545                {
00546                    bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00547                    printDebug(DM_Lock, "Releasing exclusive lock");
00548                    printDebug(DM_Lock, "LockManager:releaseLock End");
00549                    return OK;
00550                }
00551            }
00552            else if (iter->lInfo_.noOfReaders_ == 1)
00553            {
00554                iter->lInfo_.noOfReaders_ = 0;
00555                if (iter->lInfo_.waitWriters_ == 0 || iter->lInfo_.waitReaders_ ==0)
00556                {
00557                    deallocLockNode(iter, bucket);
00558                    bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00559                    printDebug(DM_Lock, "Releasing read lock and dealloc node:%x",iter);
00560                    printDebug(DM_Lock, "LockManager:releaseLock End");
00561                    return OK;
00562                }
00563            }
00564            else
00565            {
00566                iter->lInfo_.noOfReaders_--;
00567                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00568                printDebug(DM_Lock, "Decrementing read lock:%x",iter);
00569                printDebug(DM_Lock, "LockManager:releaseLock End");
00570                return OK;
00571            }
00572 
00573        }
00574        printDebug(DM_Lock, "Finding the lock node. iter:%x",iter);
00575        iter = iter->next_;
00576    }
00577    bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00578    printError(ErrSysFatal, "Lock Element Not found: Probable Data Corruption");
00579    return ErrSysFatal;
00580 }
00581 
00582 DbRetVal LockManager::isExclusiveLocked(void *tuple, Transaction **trans, bool &status)
00583 {
00584    Bucket *bucket = getLockBucket(tuple);
00585    printDebug(DM_Lock,"Bucket is %x", bucket);
00586    int lockRet = bucket->mutex_.getLock(systemDatabase_->procSlot);
00587    if (lockRet != 0)
00588    {
00589        printDebug(DM_Lock, "Mutex is waiting for long time:May be deadlock");
00590        printDebug(DM_Lock, "LockManager:releaseLock End");
00591        printError(ErrLockTimeOut, "Unable to get bucket mutex");
00592        return ErrLockTimeOut;
00593    }
00594    LockHashNode *lockNode = (LockHashNode*) bucket->bucketList_;
00595    if (NULL == lockNode)
00596    {
00597        bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00598        printDebug(DM_Lock, "bucketList is empty. so data element not locked");
00599        status = false;
00600        return OK;
00601    }
00602 
00603    LockHashNode *iter = lockNode;
00604    //Iterate though the list and find the element's lock info
00605    //Only exclusive locks are checked. shared locks are not considered for this
00606    while(iter != NULL)
00607    {
00608        if(iter->ptrToTuple_ == tuple)
00609        {
00610            if (iter->lInfo_.noOfReaders_ == -1)
00611            {
00612                if (trans != NULL && (*trans)->findInHasList(systemDatabase_, iter))
00613                {
00614                    printDebug(DM_Lock, "You already have exclusive Lock: %x", iter);
00615                    status = false;
00616                }
00617                else 
00618                    status = true;
00619                bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00620                return OK;
00621            }
00622        }
00623        printDebug(DM_Lock, "Finding the lock node. iter:%x",iter);
00624        iter = iter->next_;
00625    }
00626    bucket->mutex_.releaseLock(systemDatabase_->procSlot);
00627    status = false;
00628    return OK;
00629 }
00630 
00631 LockHashNode* LockManager::allocLockNode(LockInfo &info, void *tuple, DbRetVal *rv)
00632 {
00633     //allocate lock node
00634     Chunk *chunk = systemDatabase_->getSystemDatabaseChunk(LockTableId);
00635     LockHashNode *node = (LockHashNode*)chunk->allocate(systemDatabase_, rv);
00636     if (NULL == node)
00637     {
00638         printError(*rv, "Could not allocate Lock node");
00639         return NULL;
00640     }
00641     node->ptrToTuple_ = tuple;
00642     node->lInfo_ = info;
00643     node->next_ = NULL;
00644     return node;
00645 }
00646 
00647 void LockManager::deallocLockNode(LockHashNode *node, Bucket *bucket)
00648 {
00649     Chunk *chunk = systemDatabase_->getSystemDatabaseChunk(LockTableId);
00650     LockHashNode *nodeList = (LockHashNode*) bucket->bucketList_;
00651     LockHashNode *iter = nodeList, *prev = nodeList;
00652     if (NULL == nodeList)
00653     {
00654         printError(ErrSysFatal, "Lock Bucket corrupted");
00655         return;
00656     }
00657     //If it is the first node, then make the bucket point to the next node 
00658     //in the list
00659     if (nodeList == node)
00660     {
00661        bucket->bucketList_ = node->next_;
00662        chunk->free(systemDatabase_, node);
00663        return;
00664     }
00665     while(iter != node)
00666     {
00667         prev = iter;
00668         iter = iter->next_;
00669     }
00670     //delete the node by making previous element point to the next element 
00671     //of the deleted element in the list
00672     prev->next_ = iter->next_;
00673     chunk->free(systemDatabase_, node);
00674     return ;
00675 }

Generated on Mon Jun 9 22:37:15 2008 for csql by  doxygen 1.4.7