⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sbcachemanager.cpp

📁 OSB-PIK-OpenVXI-3.0.0源代码 “中国XML论坛 - 专业的XML技术讨论区--XML在语音技术中的应用”
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 /****************License************************************************  *  * Copyright 2000-2003.  ScanSoft, Inc.      *  * Use of this software is subject to notices and obligations set forth   * in the SpeechWorks Public License - Software Version 1.2 which is   * included with this software.   *  * ScanSoft is a registered trademark of ScanSoft, Inc., and OpenSpeech,   * SpeechWorks and the SpeechWorks logo are registered trademarks or   * trademarks of SpeechWorks International, Inc. in the United States   * and other countries.  *  ***********************************************************************/  // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8  #include "SBcacheInternal.h"  #include "SBcacheManager.hpp"    // for this class  #include <list>                  // for STL list template class #include <vector>                  // for STL list template class #include <algorithm> #include <limits.h>              // for ULONG_MAX  #if defined(__GNUC__) && (__GNUC__ == 3) && (__GNUC_MINOR__ < 2) #include <strstream> #else #include <sstream>               // for basic_ostringstream( ) #endif  static const int CACHE_REF_COUNT_MUTEX_POOL_SIZE = 256; static const int CACHE_MAX_DIR_ENTRIES = 256; static const char CACHE_ENTRY_FILE_EXTENSION[] = ".sbc";  // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8   // Shut down the manager SBcacheManager::~SBcacheManager( ) {   if ( _cacheDir.length( ) > 0 ) {     // Lock to be paranoid, makes sure everyone else is done     if ( _entryTableMutex.Lock( ) != VXItrd_RESULT_SUCCESS ) {       Error (110, L"%s%s", L"mutex", L"entry table mutex");     } else {       // Write out the index file       WriteIndex( );        // Clear the cache entries       _entryTable.erase (_entryTable.begin( ), _entryTable.end( ));       _entryLRUList.erase(_entryLRUList.begin(), _entryLRUList.end());       _curSizeBytes.Reset (0);        // Clear the directory name       _cacheDir = "";        if ( _entryTableMutex.Unlock( ) != VXItrd_RESULT_SUCCESS ) 	Error (111, L"%s%s", L"mutex", L"entry table mutex");     }   } }   // Create the manager VXIcacheResult SBcacheManager::Create(const SBcacheNString &cacheDir, 				      VXIulong              cacheMaxSizeBytes, 				      VXIulong              entryMaxSizeBytes, 				      VXIulong              entryExpTimeSec, 				      VXIbool               unlockEntries,                                       VXIulong              cacheLowWaterBytes) {   VXIcacheResult rc = VXIcache_RESULT_SUCCESS;    // Avoid double initialization   if ( _cacheDir.length( ) > 0 ) {     Error (112, NULL);     rc = VXIcache_RESULT_FATAL_ERROR;   }    // Create the path sequence number   if (( rc == VXIcache_RESULT_SUCCESS ) &&       ( _pathSeqNum.Create( ) != VXItrd_RESULT_SUCCESS )) {     Error (109, L"%s%s", L"mutex", L"path seq num");     rc = VXIcache_RESULT_SYSTEM_ERROR;   }    // Create the entry table mutex   if (( rc == VXIcache_RESULT_SUCCESS ) &&       ( _entryTableMutex.Create(L"SBcacheManager entry table mutex") != 	VXItrd_RESULT_SUCCESS )) {     Error (109, L"%s%s", L"mutex", L"entry table mutex");     rc = VXIcache_RESULT_SYSTEM_ERROR;   }    // Create the mutex pool   if (( rc == VXIcache_RESULT_SUCCESS ) &&       ( _refCntMutexPool.Create(L"SBcacheManager refCnt mutex pool", 				CACHE_REF_COUNT_MUTEX_POOL_SIZE) )) {     Error (109, L"%s%s", L"mutex", L"entry table mutex");     rc = VXIcache_RESULT_SYSTEM_ERROR;   }    // Create the cache size   if (( rc == VXIcache_RESULT_SUCCESS ) &&       ( _curSizeBytes.Create( ) != VXItrd_RESULT_SUCCESS )) {     Error (109, L"%s%s", L"mutex", L"cache size mutex");     rc = VXIcache_RESULT_SYSTEM_ERROR;   }    // Create the cache directory if required   if ( rc == VXIcache_RESULT_SUCCESS ) {     SBcacheStatInfo statInfo;     if ( SBcacheStat (cacheDir.c_str( ), &statInfo) ) {       // Exists, make sure it is a file       if ( ! SBcacheIsDir(statInfo) ) { 	Error (113, L"%s%S", L"cacheDirectory", cacheDir.c_str( )); 	rc = VXIcache_RESULT_FATAL_ERROR;       } else { 	// Load the cache index file 	rc = ReadIndex (cacheDir);       }     } else if ( ! SBcacheMkdir (cacheDir.c_str( )) ) {       Error (114, L"%s%S", L"cacheDirectory", cacheDir.c_str( ));       rc = VXIcache_RESULT_FATAL_ERROR;     }   }    // Update data members   if ( rc == VXIcache_RESULT_SUCCESS ) {     _cacheDir = cacheDir;     _maxSizeBytes = cacheMaxSizeBytes;     _entryMaxSizeBytes = entryMaxSizeBytes;     _lowWaterBytes = cacheLowWaterBytes;   }    _entryReserve = 0;   ReserveEntries(0); // Disable, for now.    Diag (SBCACHE_MGR_TAGID, L"Create", L"rc = %d", rc);   return rc; }  // NOTE: This is disabled, see above, until SPR is fixed or NPFed. // // Interesting trick, we want to reserve a certain amount of memory for N // entries, but we only have an estimate as to the size of an entry, and we // can't make all the code use a special allocator.   // Solution: Make an estimate(E) of how much an entry will take up, and // grab N * E bytes from the general allocator.  Whenever we add an entry, // we give back E bytes (if we can), whenver we remove an entry we take E // bytes (unless we hit the maximum preallocation).   // void SBcacheManager::ReserveEntries(int nentries) {   for (int i = 0; i < nentries; ++i) {     SBcacheEntryEstimate* es = new SBcacheEntryEstimate();     es->next = _entryReserve;     _entryReserve = es;   }   _entriesReserved = nentries;   _maxEntriesReserved = nentries; }  void SBcacheManager::EntryAdded() {   if (_entriesReserved > 0) {     SBcacheEntryEstimate* es = _entryReserve;     _entryReserve = es->next;     delete es;     _entriesReserved--;   } else {     static int once = 1;     if (once) {       once = 0;     }   } }  void SBcacheManager::EntryRemoved() {   if (_maxEntriesReserved > _entriesReserved) {     SBcacheEntryEstimate* es = new SBcacheEntryEstimate();     es->next = _entryReserve;     _entryReserve = es;     _entriesReserved++;   } }  // Synchronized table and LRU list // bool SBcacheManager::InsertEntry(SBcacheEntry& entry) {   SBcacheEntryTable::value_type tableEntry (entry.GetKey(), entry);   if ( ! _entryTable.insert (tableEntry).second )     return false;   _entryLRUList.push_back(entry);   EntryAdded();   return true; }  void SBcacheManager::RemoveEntry(const SBcacheEntry& entry) {   SBcacheEntryTable::iterator te = _entryTable.find(entry.GetKey());   _entryTable.erase(te);   SBcacheEntryList::iterator vi = _entryLRUList.begin();   for (; vi != _entryLRUList.end(); ++vi)     if (entry.Equivalent(*vi)) {       _entryLRUList.erase(vi);       break;     }   EntryRemoved(); }  void SBcacheManager::TouchEntry(const SBcacheEntry& entry) {   SBcacheEntryList::iterator vi = _entryLRUList.begin();   for (; vi != _entryLRUList.end(); ++vi)     if (entry.Equivalent(*vi)) {       _entryLRUList.erase(vi);       _entryLRUList.push_back(entry);       break;     } }   //####################################################################### // Note about locking protocol.  THere are three locks in this code: //   A. The entrytable lock (_entryTableMutex) //   B. a lock per entry  (GetSizeBytes, Open, Close) //   C. a lock of _curSizeBytes (atomic operations) // Currently, both locks A & C are held inside of lock B because an open // obtains a lock and holds it until the entry is closed.  Therefore, // a B lock must never be obtained while an A or C lock is held! //#######################################################################  // Open an entry VXIcacheResult SBcacheManager::Open(VXIlogInterface       *log, 				    const SBcacheString   &moduleName, 				    const SBcacheKey      &key, 				    VXIcacheOpenMode       mode, 				    VXIint32               flags, 				    const VXIMap          *properties, 				    VXIMap                *streamInfo, 				    VXIcacheStream       **stream) {   VXIcacheResult rc = VXIcache_RESULT_SUCCESS;    // Big loop where we attempt to open and re-open the cache entry for   // as long as we get recoverable errors   VXIcacheOpenMode finalMode;   do {     finalMode = mode;     rc = VXIcache_RESULT_SUCCESS;      if ( _entryTableMutex.StartRead( ) != VXItrd_RESULT_SUCCESS ) {       Error (log, 110, L"%s%s", L"mutex", L"entry table mutex");       return VXIcache_RESULT_SYSTEM_ERROR;     }      // Find the entry and open it, only need read permission     bool entryOpened = false;     SBcacheEntry entry;     SBcacheEntryTable::iterator vi = _entryTable.find (key);     if ( vi == _entryTable.end( ) ) {       rc = VXIcache_RESULT_NOT_FOUND;     } else {       entry = (*vi).second;       finalMode = (mode == CACHE_MODE_READ_CREATE ? CACHE_MODE_READ : mode);     }      if ( _entryTableMutex.EndRead( ) != VXItrd_RESULT_SUCCESS ) {       Error (log, 111, L"%s%s", L"mutex", L"entry table mutex");       rc = VXIcache_RESULT_SYSTEM_ERROR;     }       // For write and read/create mode, create the entry if not found     if (( rc == VXIcache_RESULT_NOT_FOUND ) && ( mode != CACHE_MODE_READ )) {       rc = VXIcache_RESULT_SUCCESS;        // Get write permission       if ( _entryTableMutex.Lock( ) != VXItrd_RESULT_SUCCESS ) { 	Error (log, 110, L"%s%s", L"mutex", L"entry table mutex"); 	rc = VXIcache_RESULT_SYSTEM_ERROR;       } else { 	// Try to find the entry again, it may have been created by now 	vi = _entryTable.find (key); 	if ( vi != _entryTable.end( ) ) { 	  // Found it this time 	  entry = (*vi).second; 	  finalMode = (mode == CACHE_MODE_READ_CREATE ? CACHE_MODE_READ : mode); 	} else { 	  // Create and open the entry for write 	  rc = entry.Create (GetLog( ), GetDiagBase( ), 			     _refCntMutexPool.GetMutex( ));  	  if ( rc == VXIcache_RESULT_SUCCESS ) { 	    finalMode = (mode == CACHE_MODE_READ_CREATE ? CACHE_MODE_WRITE : 			 mode);              // Note entry lock obtained while entrytable lock is held! We             // can get away with this, because the lock isn't visible to             // anyone else yet. 	    rc = entry.Open (log, moduleName, key, 			     GetNewEntryPath (moduleName, key), 			     finalMode, flags, _entryMaxSizeBytes, properties, 			     streamInfo, stream); 	  }  	  // Insert the entry 	  if ( rc == VXIcache_RESULT_SUCCESS ) { 	    entryOpened = true;  	    SBcacheEntryTable::value_type tableEntry (key, entry); 	    if ( !InsertEntry(entry)) { 	      Error (log, 100, NULL); 	      (*stream)->Close (true); 	      *stream = NULL; 	      rc = VXIcache_RESULT_OUT_OF_MEMORY; 	    }  	  } 	}  	if ( _entryTableMutex.Unlock( ) != VXItrd_RESULT_SUCCESS ) { 	  Error (log, 111, L"%s%s", L"mutex", L"entry table mutex"); 	  rc = VXIcache_RESULT_SYSTEM_ERROR; 	}       }     }       // Open pre-existing entry. Note that this may return     // VXIcache_RESULT_FAILURE in some cases where we then need to     // retry the entire process of opening the entry -- that occurs

⌨️ 快捷键说明

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