// remove the entry from the database and then destroy the cacheentry void InternalCCache::remove(const char* key) { log->debug("removing cache entry with key (%s)", key); // lock the cache for writing, which means we know nobody is sitting in find() lock->wrlock(); // grab the entry from the database. ISessionCacheEntry* entry = findi(key); if (!entry) { lock->unlock(); return; } // ok, remove the entry and lock it m_hashtable.erase(key); dynamic_cast<InternalCCacheEntry*>(entry)->lock(); lock->unlock(); // we can release the entry lock because we know we're not in the cache anymore entry->unlock(); // Now delete the entry delete entry; }
void InternalCCache::insert( const char* key, const IApplication* application, const char* client_addr, ShibProfile profile, const char* providerId, SAMLAuthenticationStatement* s, SAMLResponse* r, const IRoleDescriptor* source, time_t created, time_t accessed ) { log->debug("caching new entry for application %s: \"%s\"", application->getId(), key); InternalCCacheEntry* entry = new InternalCCacheEntry( this, key, application, client_addr, profile, providerId, s, r, source, created, accessed ); lock->wrlock(); m_hashtable[key]=entry; lock->unlock(); }
OSTHREAD_FUNC lock_thread(void *parm){ //int i = (int)(long long) parm; int j; int r; for (j=0; j < LOCK_OPS; ++j){ lock_l.lock(); r = lock_n.next() % 2; lock_counter1 = lock_counter1 ^ r; lock_counter2 = lock_counter2 ^ r; lock_counter3 = lock_counter3 + 1; lock_l.unlock(); } return 0; }
static void* RWRunner(void* arg) { struct timeval tv; int op, op2, interval; RWLock* rwlock; gettimeofday(&tv, NULL); rwlock = new RWLock(reinterpret_cast<int64_t>(arg)); while (!threadStop) { op = rand_r(reinterpret_cast<uint32_t*>(&tv.tv_usec)) % 10; if (op < 8) // read { interval = rand_r(reinterpret_cast<uint32_t*>(&tv.tv_usec)) % 100000; rwlock->read_lock(); rwlock->lock(); CPPUNIT_ASSERT(rwlock->getReading() > 0); CPPUNIT_ASSERT(rwlock->getWriting() == 0); rwlock->unlock(); usleep(interval); op2 = rand_r(reinterpret_cast<uint32_t*>(&tv.tv_usec)) % 2; if (op2) { rwlock->upgrade_to_write(); rwlock->lock(); CPPUNIT_ASSERT(rwlock->getReading() == 0); CPPUNIT_ASSERT(rwlock->getWriting() == 1); rwlock->unlock(); usleep(interval); rwlock->write_unlock(); } else { /* For testing the lock recovery code in the BRM workernodes */ /* int crash = rand_r((uint32_t *) &tv.tv_usec) % 100; if (crash > 0) // 1% chance of crashing rwlock->read_unlock(); */ } } else if (op < 9) // write { interval = rand_r(reinterpret_cast<uint32_t*>(&tv.tv_usec)) % 100000; rwlock->write_lock(); rwlock->lock(); CPPUNIT_ASSERT(rwlock->getReading() == 0); CPPUNIT_ASSERT(rwlock->getWriting() == 1); rwlock->unlock(); usleep(interval); op2 = rand_r(reinterpret_cast<uint32_t*>(&tv.tv_usec)) % 2; if (op2) { rwlock->downgrade_to_read(); rwlock->lock(); CPPUNIT_ASSERT(rwlock->getReading() > 0); CPPUNIT_ASSERT(rwlock->getWriting() == 0); rwlock->unlock(); usleep(interval); rwlock->read_unlock(); } else rwlock->write_unlock(); } else if (op == 9) // delete { delete rwlock; rwlock = new RWLock(reinterpret_cast<int64_t>(arg)); } } delete rwlock; pthread_exit(0); }
void InternalCCache::cleanup() { #ifdef _DEBUG saml::NDC ndc("cleanup()"); #endif int rerun_timer = 0; int timeout_life = 0; Mutex* mutex = Mutex::create(); // Load our configuration details... const XMLCh* tag=m_root->getAttributeNS(NULL,cleanupInterval); if (tag && *tag) rerun_timer = XMLString::parseInt(tag); tag=m_root->getAttributeNS(NULL,cacheTimeout); if (tag && *tag) timeout_life = XMLString::parseInt(tag); if (rerun_timer <= 0) rerun_timer = 300; // rerun every 5 minutes if (timeout_life <= 0) timeout_life = 28800; // timeout after 8 hours mutex->lock(); log->info("Cleanup thread started... Run every %d secs; timeout after %d secs", rerun_timer, timeout_life); while (shutdown == false) { shutdown_wait->timedwait(mutex,rerun_timer); if (shutdown == true) break; log->debug("Cleanup thread running..."); // Ok, let's run through the cleanup process and clean out // really old sessions. This is a two-pass process. The // first pass is done holding a read-lock while we iterate over // the database. The second pass doesn't need a lock because // the 'deletes' will lock the database. // Pass 1: iterate over the map and find all entries that have not been // used in X hours vector<string> stale_keys; time_t stale = time(NULL) - timeout_life; lock->rdlock(); for (map<string,InternalCCacheEntry*>::iterator i=m_hashtable.begin(); i != m_hashtable.end(); i++) { // If the last access was BEFORE the stale timeout... i->second->lock(); time_t last=i->second->lastAccess(); i->second->unlock(); if (last < stale) stale_keys.push_back(i->first); } lock->unlock(); log->info("deleting %d old items.", stale_keys.size()); // Pass 2: walk through the list of stale entries and remove them from // the database for (vector<string>::iterator j = stale_keys.begin(); j != stale_keys.end(); j++) { remove (j->c_str()); // Transaction Logging STConfig& stc=static_cast<STConfig&>(ShibTargetConfig::getConfig()); stc.getTransactionLog().infoStream() << "Purged expired session from memory (ID: " << j->c_str() << ")"; stc.releaseTransactionLog(); } } log->info("Cleanup thread finished."); mutex->unlock(); delete mutex; Thread::exit(NULL); }