cache.cxx

来自「vovida的软交换」· CXX 代码 · 共 591 行 · 第 1/2 页

CXX
591
字号
/* ==================================================================== * The Vovida Software License, Version 1.0  *  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. *  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. *  * 3. The names "VOCAL", "Vovida Open Communication Application Library", *    and "Vovida Open Communication Application Library (VOCAL)" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor *    may "VOCAL" appear in their name, without prior written *    permission of Vovida Networks, Inc. *  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *  * ==================================================================== *  * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc.  For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */  /** * Cache.cxx -- 11/03/03 *  * This provides a cache system to the clients, the cache deals with  * the issues of finding the database etc, etc. */#include "Cache.hxx"#include "RecordTypes.h"#include "Record.hxx"#include "UpdateRegInfoRec.hxx"#include "DBResultset.hxx"#include "ConnectionManager.hxx"#include "CacheManager.hxx"#include "support.hxx"#include "cpLog.h"#include <sys/types.h>#include <unistd.h>#include <string>Cache* Cache::myInstance = NULL;int Cache::usageCount = 0;/** * Returns the existing instance of the Cache object  * Or creates one if none exist * A basic implementation of the singleton design  * pattern. * @return Cache* A pointer to the single instance of the Cache */Cache* Cache::getInstance() {  // Standard singleton pattern, check if an instance exists  if (myInstance == NULL) {     // No existing instance    myInstance = new Cache();    usageCount = 0;  }  cpLog(LOG_DEBUG, "Retrieving instance, user count is %d.", (usageCount+1));  usageCount++;  return myInstance;}void Cache::freeInstance() {   cpLog(LOG_DEBUG, "Freeing cache instance");  usageCount--;}void Cache::destroy() {   if (myInstance) {     cpLog(LOG_DEBUG, "Stopping manager threads");    // Stop the cache manager (the destructor automatically stops the thread)    if (myInstance->myCacheManager) {      (myInstance->myCacheManager)->shutdown();      (myInstance->myCacheManager)->join();      delete myInstance->myCacheManager;    }    // Stop the listeners from running    myInstance->stopAllListeners();      // Nothing should be accessing the cache so delete the objects themselves.    (myInstance->myCache)->empty();    // delete myDBManager; -- can't destory this !    if (myInstance->myDBThread){       delete myInstance->myDBThread;    }        cpLog(LOG_DEBUG, "Destroying Cache Object\n");    if (myInstance->myCache){       delete myInstance->myCache;    }    cpLog(LOG_DEBUG, "Deleting main cache instance");    usageCount = 0;    delete myInstance;    myInstance = NULL;  }}Record* Cache::getRecord(RecordType rtype, KeyType key, bool useCache) {  cpLog(LOG_DEBUG, "Fetching record of %s with key %s", Record::stringRecordType(rtype).c_str(), key.c_str());  Record *rec = NULL;  if (useCache) {     rec = myCache->get(rtype, key);  }    // 'rec' will be NULL if the object is not present  if (rec == NULL) {     cpLog(LOG_DEBUG, "Record not found in cache");        // Otherwise create a blank record    rec = Record::createNewRecord(rtype);      // Get a database connection    DBConnection* dbconn = myDBManager->searchDBConPool(dbinfo);    if (!dbconn) {       cpLog(LOG_ERR, "Can't get database connection");      return NULL;    }    // And look up the database    if (!rec->populateRecord(key, dbconn)) {       delete rec;      rec = NULL;      cpLog(LOG_DEBUG, "Record is NULL!\n");      myDBManager->returnDBCon(dbconn);      return rec;    };          // Insert this into the cache if it exists (and we're using the cache)    if (rec && useCache) {         myCache->insert(rtype, key, rec);     }    myDBManager->returnDBCon(dbconn);  } else {     cpLog(LOG_DEBUG, "Object found in cache (will reinsert with correct access time)");  }  // Sanity check that we created the right type of message  if ((rec != NULL) && (rec->getRecordType() != rtype)) {     // Only happens if Record subclass is incorrectly coded    // Delete the rogue object and return NULL, we should probably really    // ASSERT here as this is an error in the system    cpLog(LOG_ERR, "getRecord() returned incorrect record type");    // Erase this from the cache as well, this will force a database lookup next time    myCache->remove(rtype, key);    delete rec;    rec = NULL;   }  /*    * The cache system is taking care of coping objects so we can just   * return this pointer.   */     return rec;}bool Cache::insertRecord(Record* rec) {   cpLog(LOG_DEBUG, "Inserting record of type %s with key %s", 	(Record::stringRecordType(rec->getRecordType())).c_str(), 	rec->getKey().c_str());  // Get a database connection, that let the record insert itself  DBConnection* dbconn = myDBManager->searchDBConPool(dbinfo);      if (!dbconn) {    cpLog(LOG_ERR, "Can't get database connection");    return false;  }  bool result = rec->insertRecord(dbconn);  if (!result) cpLog(LOG_ERR, "Database insert failed");  myDBManager->returnDBCon(dbconn);  // The update callback will automatically amend the cache if required,   // if we did it here the update would be done twice  return result;}bool Cache::changeRecord(Record* rec) {   cpLog(LOG_DEBUG, "Changing record of type %s with key %s", 	(Record::stringRecordType(rec->getRecordType())).c_str(), 	rec->getKey().c_str());  // Get a database connection, that let the record insert itself  DBConnection* dbconn = myDBManager->searchDBConPool(dbinfo);    if (!dbconn) {     cpLog(LOG_ERR, "Can't get database connection");    return false;  }  bool result = rec->amendRecord(dbconn);  if (!result) cpLog(LOG_ERR, "Database change failed");  myDBManager->returnDBCon(dbconn);  // The update callback will automatically amend the cache if required,   // if we did it here the update would be done twice  return result;   }bool Cache::deleteRecord(Record* rec) {   cpLog(LOG_DEBUG, "Deleting record of type %s with key %s", 	(Record::stringRecordType(rec->getRecordType())).c_str(), 	rec->getKey().c_str());  // Get a database connection, that let the record insert itself  DBConnection* dbconn = myDBManager->searchDBConPool(dbinfo);    if (!dbconn) {     cpLog(LOG_ERR, "Can't get database connection");    return false;  }  bool result = rec->deleteRecord(dbconn);  if (!result) cpLog(LOG_ERR, "Database delete failed");  myDBManager->returnDBCon(dbconn);  // The update callback will automatically amend the cache if required,   // if we did it here the update would be done twice  return result;}bool Cache::registerForUpdates(string hostname, RecordType recType, callBackFuncPtr callBackFunc) {   // Can't register to listen for update reg records as that would risk   // creating loops, and only the clients should change them anyway  if (recType == UPDATE_REG_INFO_RECORD) return false;    cpLog(LOG_DEBUG, 	"Registering for update messages for records of type %s on %s",

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?