// Cleanup NARoutine cache after the statement completes. Remove entries // using LRU policy, if the cache has grown too large. The approach here is // somewhat different from NATableDB caching, which deletes entries from the // NATable cache if the statement was DDL that may have affected the table // definition. NATable caching also deletes tables from the cache at this // time for performance reasons. void NARoutineDB::resetAfterStatement() { // Delete 'dirty' NARoutine objects that were not deleted earlier // to save compile-time performance. if (routinesToDeleteAfterStatement_.entries()) { // Clear the list of tables to delete after statement routinesToDeleteAfterStatement_.clear(); } if (entries()) { // Reduce size of cache if it has grown too large. if (!enforceMemorySpaceConstraints()) cacheMetaData_ = FALSE; // Disable cache if there is a problem. // Reset statement level flags refreshCacheInThisStatement_=FALSE; // Clear 'accessed in current statement' flag for all cached NARoutines. NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); NARoutineDBKey *key; NARoutine *routine; iter.getNext(key,routine); while(key) { routine->getAccessedInCurStmt() = FALSE; iter.getNext(key,routine); } } }
void NARoutineDB::flushCache() { //if something is cached if(cacheMetaData_) { //set the flag to indicate cache is clear cacheMetaData_ = FALSE; NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); NARoutineDBKey *key; NARoutine *routine; iter.getNext(key,routine); while(key && routine) { remove(key); delete routine ; iter.getNext(key,routine); } routinesToDeleteAfterStatement_.clear(); //set cache size to 0 to indicate nothing in cache currentCacheSize_ = 0; entries_ = 0; highWatermarkCache_ = 0; // High watermark of currentCacheSize_ totalLookupsCount_ = 0; // reset NARoutine entries lookup counter totalCacheHits_ = 0; // reset cache hit counter replacementCursor_ = 0; } }
//============================================================================ // This method writes the information related to the NAClusterInfo class to a // logfile called "NAClusterInfo.txt". //============================================================================ void NAClusterInfo::captureNAClusterInfo(ofstream & naclfile) { CollIndex i, ci; char filepath[OSIM_PATHMAX]; char filename[OSIM_FNAMEMAX]; // We don't capture data members that are computed during the compilation of // a query. These include: // // * smpCount_; // * tableToClusterMap_; // * activeClusters_; // naclfile << "localCluster_: " << localCluster_ << endl << "localSMP_: " << localSMP_ << endl; CollIndex *key_collindex; maps *val_maps; // Iterator for logging all the entries in clusterToCPUMap_ HashDictionary. NAHashDictionaryIterator<CollIndex, maps> C2CPUIter (*clusterToCPUMap_, NULL, NULL); naclfile << "clusterToCPUMap_: " << C2CPUIter.entries() << " :" << endl; if (C2CPUIter.entries() > 0) { // Write the header line for the table. naclfile << " "; naclfile.width(10); naclfile << "clusterNum" << " "; naclfile << "cpuList" << endl; for (i=0; i<C2CPUIter.entries(); i++) { C2CPUIter.getNext(key_collindex, val_maps); naclfile << " "; naclfile.width(10); naclfile << *key_collindex << " "; naclfile << val_maps->list->entries() << " : "; for (ci=0; ci<val_maps->list->entries(); ci++) { naclfile.width(3); naclfile << (*(val_maps->list))[ci] << " "; } naclfile << endl; } } Int32 * nodeID = NULL; NAString* nodeName = NULL; NAHashDictionaryIterator<Int32, NAString> nodeNameAndIDIter (*nodeIdToNodeNameMap_); naclfile << "nodeIdAndNodeNameMap: " << nodeNameAndIDIter.entries() << endl; for(nodeNameAndIDIter.getNext(nodeID, nodeName); nodeID && nodeName; nodeNameAndIDIter.getNext(nodeID, nodeName)) { naclfile << *nodeID << " " << nodeName->data() << endl; } // Now save the OS-specific information to the NAClusterInfo.txt file captureOSInfo(naclfile); }
// ---------------------------------------------------------------------------- // method: removeNARoutine // // The method is called when DDL is performed against a routine making its // definition incorrect. // It has a side affect of generating query invalidation keys that are // propagate to all the other processes that could have the routine stored // in cache. // ---------------------------------------------------------------------------- void NARoutineDB::removeNARoutine2(QualifiedName &routineName, ComQiScope qiScope, Int64 objUID) { NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); NARoutineDBKey *key = NULL; NARoutine *cachedNARoutine = NULL; NASet<Int64> objectUIDs(CmpCommon::statementHeap(), 1); // If there are no items in cache, skip if (entries() > 0) { NASet<Int64> objectUIDs(CmpCommon::statementHeap(), 1); // iterate over all entries and remove the ones that match the name iter.reset(); iter.getNext(key,cachedNARoutine); while(key && cachedNARoutine) { if (cachedNARoutine->getSqlName() == routineName) { objectUIDs.insert(cachedNARoutine->getRoutineID()); moveRoutineToDeleteList(cachedNARoutine,key); } iter.getNext(key,cachedNARoutine); } } // clear out the other users' caches too. if (qiScope == REMOVE_FROM_ALL_USERS) { // There are some scenarios where the affected object does not have an // NARoutine cache entry. However, other processes may have this routine // in their caches. Go ahead and create an invalidation key if (0 == objectUIDs.entries()) objectUIDs.insert(objUID); Int32 numKeys = objectUIDs.entries(); SQL_QIKEY qiKeys[numKeys]; for (CollIndex i = 0; i < numKeys; i++) { qiKeys[i].ddlObjectUID = objectUIDs[i]; qiKeys[i].operation[0] = 'O'; qiKeys[i].operation[1] = 'R'; } long retcode = SQL_EXEC_SetSecInvalidKeys(numKeys, qiKeys); } }
// ---------------------------------------------------------------------------- // method: free_entries_with_QI_key // // This method is sent a list of query invalidation keys. // It looks through the list of routines to see if any of them need to be // removed from cache because their definitions are no longer valid. // // numKeys - number of existing invalidation keys // qiKeyArray - actual keys // ---------------------------------------------------------------------------- void NARoutineDB::free_entries_with_QI_key(Int32 numKeys, SQL_QIKEY* qiKeyArray) { NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); NARoutineDBKey *key; NARoutine *routine; iter.getNext(key,routine); while(key && routine) { // See if item should be removed if (qiCheckForInvalidObject(numKeys, qiKeyArray, routine->getRoutineID(), routine->getSecKeySet())) moveRoutineToDeleteList(routine, key); iter.getNext(key,routine); } }
// // -- TriggerDB::print // // Debugging aid. // // For debugging only // LCOV_EXCL_START void TriggerDB::print(ostream& os) const { NAHashDictionaryIterator<TableOp, BeforeAndAfterTriggers> iter (*this) ; TableOp * top; BeforeAndAfterTriggers * triggers; iter.getNext(top,triggers); while (top) { os << "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " << endl; top->print(os); os << "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " << endl; triggers->print(os, "", ""); os << endl << "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " << endl; iter.getNext(top, triggers); } }
// NARoutineDB private member functions. // ====================================== // Check if cache size is within maximum allowed cache size. If not, // then remove entries in the cache based on the replacement policy, // until the cache size drops below the allowed size. // DO NOT CALL THIS ROUTINE IN THE MIDDLE OF A STATEMENT. NABoolean NARoutineDB::enforceMemorySpaceConstraints() { NABoolean retval = TRUE; // Set cache size to CQD setting. maxCacheSize_ = CmpCommon::getDefaultLong(ROUTINE_CACHE_SIZE) * 1024 * 1024; // Check if cache size is within memory constraints if (currentCacheSize_ <= maxCacheSize_) return retval; // Need to reduce cache size // Loop through the list and attempt to remove the entries // that are least recently used (that is, that have the oldest // timestamps of when they were last used). Do not allow the // number of times looped to exceed the number of entries in // cache. Lng32 loopCnt = 0, entries = this->entries(); while (currentCacheSize_ > maxCacheSize_ && loopCnt++ < entries){ // Find least recently used NARoutine in cache. NAHashDictionaryIterator<NARoutineDBKey,NARoutine> iter (*this); NARoutineDBKey *key=0, *oldestKey=0; NARoutine *routine=0, *oldestRoutine=0; Int64 oldestTime; iter.reset(); iter.getNext(key,routine); if (key && routine) // This should always be true. { oldestTime = routine->getLastUsedTime(); while(key) { // Check routine for last used time. Save oldest. Must use // '<=' so that oldestKey will get set first time through loop. if (routine && routine->getLastUsedTime() <= oldestTime) { oldestTime = routine->getLastUsedTime(); oldestKey = key; oldestRoutine = routine; } iter.getNext(key, routine); } remove(oldestKey); currentCacheSize_ -= oldestRoutine->getSize(); if (entries_>0) entries_--; delete oldestRoutine; } if ((ULng32) oldestRoutine->getSize() <= currentCacheSize_) { currentCacheSize_ -= oldestRoutine->getSize(); if (entries_>0) entries_--; } else { currentCacheSize_ = 0; entries_ = 0; } } //return true indicating cache size is below maximum memory allowance. if (currentCacheSize_ > maxCacheSize_) retval = FALSE; return retval; }