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

📄 sbcacheentry.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 "SBcacheEntry.hpp"   // For this class #include "SBcacheMisc.hpp"    // For SBcacheReaderWriterMutex,                               // SBcacheRefCount base class  #include "VXItrd.h"          // For VXItrcSleep()  #include <cstdio>            // For FILE, fopen( ), etc #include <cerrno>            // For errno to report fopen( ) errors #include <string.h>          // For strerror( )  #ifndef _win32_ #include <unistd.h> #endif  // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8  // SBcacheEntryMutex, a RW mutex implemented over a single exclusive lock // mutex.  We do this to save handles for the rw mutex. // We cannot use a pool here, because we rely on // cache entry locks being held in conflict with each other... a pool has // a good chance of deadlocking. // class SBcacheEntryMutex { public:   SBcacheEntryMutex(SBcacheMutex* m) :     _mutex(m), _nreaders(0), _writer(0), _writers_waiting(0) { }   ~SBcacheEntryMutex() { }   VXItrdResult Create(const wchar_t* n) { return VXItrd_RESULT_SUCCESS; }    VXItrdResult Lock() const {     VXItrdResult rc = _mutex->Lock();     if (rc != VXItrd_RESULT_SUCCESS) return rc;     ++_writers_waiting;     while (_nreaders || _writer) {       rc = _mutex->Unlock();       if (rc != VXItrd_RESULT_SUCCESS) return rc;       VXItrdThreadYield();       rc = _mutex->Lock();       if (rc != VXItrd_RESULT_SUCCESS) return rc;     }     --_writers_waiting;     ++_writer;     rc = _mutex->Unlock();     if (rc != VXItrd_RESULT_SUCCESS) return rc;     return VXItrd_RESULT_SUCCESS;   }   VXItrdResult Unlock() const {     VXItrdResult rc = _mutex->Lock();     if (rc != VXItrd_RESULT_SUCCESS) return rc;     --_writer;     rc = _mutex->Unlock();     if (rc != VXItrd_RESULT_SUCCESS) return rc;     return VXItrd_RESULT_SUCCESS;   }    VXItrdResult StartRead() const {     VXItrdResult rc = _mutex->Lock();     if (rc != VXItrd_RESULT_SUCCESS) return rc;     // i.e. while a writer holds the lock _or_ is waiting for it     while (_writer || _writers_waiting) {       rc = _mutex->Unlock();       if (rc != VXItrd_RESULT_SUCCESS) return rc;       VXItrdThreadYield();       rc = _mutex->Lock();       if (rc != VXItrd_RESULT_SUCCESS) return rc;     }     ++_nreaders;     rc = _mutex->Unlock();     if (rc != VXItrd_RESULT_SUCCESS) return rc;     return VXItrd_RESULT_SUCCESS;   }   VXItrdResult EndRead() const {     VXItrdResult rc = _mutex->Lock();     if (rc != VXItrd_RESULT_SUCCESS) return rc;     --_nreaders;     rc = _mutex->Unlock();     if (rc != VXItrd_RESULT_SUCCESS) return rc;     return VXItrd_RESULT_SUCCESS;   } private:   SBcacheMutex*  _mutex;   mutable short  _nreaders;   mutable short  _writer;   mutable short  _writers_waiting; };  // SBcacheStream, implementation of VXIcacheStream class SBcacheStream : public VXIcacheStream { public:   // Constructor and destructor   SBcacheStream(VXIlogInterface *log, VXIunsigned diagTagBase, 		const SBcacheString &moduleName, const SBcacheKey &key, 		SBcacheEntry &entry, VXIcacheOpenMode mode, bool blockingIO, 		VXIulong maxSizeBytes, FILE *filePtr) :     VXIcacheStream(log, diagTagBase, moduleName, key), _entry(entry),     _mode(mode), _blockingIO(blockingIO), _maxSizeBytes(maxSizeBytes),     _filePtr(filePtr), _sizeBytes(0) { }   virtual ~SBcacheStream( ) { if ( _filePtr ) Close(false); }    // Read and write   virtual VXIcacheResult Read(VXIbyte          *buffer, 			      VXIulong          buflen, 			      VXIulong         *nread);    virtual VXIcacheResult Write(const VXIbyte   *buffer, 			       VXIulong         buflen, 			       VXIulong        *nwritten);    // Close   virtual VXIcacheResult Close(bool invalidate);  private:   SBcacheStream(const SBcacheStream &s);   const SBcacheStream &operator=(const SBcacheStream &s);  private:   SBcacheEntry      _entry;   VXIcacheOpenMode  _mode;   bool              _blockingIO;   VXIulong          _maxSizeBytes;   FILE             *_filePtr;   VXIunsigned       _sizeBytes; };   // Read from the stream VXIcacheResult SBcacheStream::Read(VXIbyte          *buffer, 				   VXIulong          buflen, 				   VXIulong         *nread) {   VXIcacheResult rc = VXIcache_RESULT_SUCCESS;   *nread = 0;    if ( _mode != CACHE_MODE_READ ) {     Error (206, NULL);     rc = VXIcache_RESULT_IO_ERROR;   } else if ( ! _filePtr ) {     Error (207, NULL);     rc = VXIcache_RESULT_FATAL_ERROR;   }    // Read, for blocking I/O read in a loop. Note this is a lame   // implementation of non-blocking I/O, without doing a fctl( ) or   // open( ) this will almost always block, but it is very OS   // dependant and tricky to do real non-blocking I/O.   if ( rc == VXIcache_RESULT_SUCCESS ) {     size_t read;     do {       read = fread (&buffer[*nread], 1, (size_t) (buflen - *nread), _filePtr);       if ( read > 0 ) 	*nread += read;     } while (( _blockingIO ) && ( *nread < buflen ) && 	     (( read > 0 ) || ( ! feof (_filePtr) )));      if ( *nread == 0 ) {       if ( ferror (_filePtr) ) { 	_entry.LogIOError (208); 	rc = VXIcache_RESULT_IO_ERROR;       } else if ( feof (_filePtr) ) { 	rc = VXIcache_RESULT_END_OF_STREAM;       } else { 	rc = VXIcache_RESULT_WOULD_BLOCK;       }     }   }    Diag (SBCACHE_STREAM_TAGID, L"Read", 	L"%s, %S: %lu bytes, %lu requested, rc = %d", 	_entry.GetKey( ).c_str( ), _entry.GetPath( ).c_str( ), buflen, 	*nread, rc);   return rc; }   // Write to the stream VXIcacheResult SBcacheStream::Write(const VXIbyte   *buffer, 				    VXIulong         buflen, 				    VXIulong        *nwritten) {   VXIcacheResult rc = VXIcache_RESULT_SUCCESS;   *nwritten = 0;    if ( _mode != CACHE_MODE_WRITE ) {     Error (209, NULL);     rc = VXIcache_RESULT_IO_ERROR;   } else if ( ! _filePtr ) {     Error (210, NULL);     rc = VXIcache_RESULT_FATAL_ERROR;   } else if ( _sizeBytes + buflen > _maxSizeBytes ) {     rc = VXIcache_RESULT_EXCEED_MAXSIZE;   }    // Write, for blocking I/O write in a loop. Note this is a lame   // implementation of non-blocking I/O, without doing a fctl( ) or   // open( ) this will almost always block, but it is very OS   // dependant and tricky to do real non-blocking I/O.   if ( rc == VXIcache_RESULT_SUCCESS ) {     size_t written;     do {       written = fwrite (&buffer[*nwritten], 1, (size_t) (buflen - *nwritten), 			_filePtr);       if ( written > 0 ) { 	*nwritten += written; 	_sizeBytes += written;       }     } while (( _blockingIO ) && ( *nwritten < buflen ) && 	     (( written > 0 ) || ( ! ferror (_filePtr) )));      if ( *nwritten == 0 ) {       if ( ferror (_filePtr) ) { 	_entry.LogIOError (212); 	rc = VXIcache_RESULT_IO_ERROR;       } else { 	rc = VXIcache_RESULT_WOULD_BLOCK;       }     }   }    Diag (SBCACHE_STREAM_TAGID, L"Write", 	L"%s, %S: %lu bytes, %lu requested, rc = %d", 	_entry.GetKey( ).c_str( ), _entry.GetPath( ).c_str( ), buflen, 	*nwritten, rc);   return rc; }   // Close the stream VXIcacheResult SBcacheStream::Close(bool invalidate) {   VXIcacheResult rc = VXIcache_RESULT_SUCCESS;    // Close the file   if ( fclose (_filePtr) != 0 ) {     _entry.LogIOError (300);     rc = VXIcache_RESULT_IO_ERROR;   }   _filePtr = NULL;    // Close the cache entry, do this after logging to ensure the entry   // isn't deleted on us after the close   VXIcacheResult rc2 = _entry.Close (GetLog( ), _mode, _sizeBytes, invalidate);   if ( rc2 != VXIcache_RESULT_SUCCESS )     rc = rc2;    return rc; }   // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8   // SBcacheEntryDetails, real reference counted cache entry class SBcacheEntryDetails : public SBcacheRefCount, public SBinetLogger { public:   // Constructor and destructor   SBcacheEntryDetails(VXIlogInterface *log, VXIunsigned diagTagBase, 		      SBcacheMutex *refCountMutex) :     SBcacheRefCount(refCountMutex),     SBinetLogger(MODULE_SBCACHE, log, diagTagBase),     _rwMutex(refCountMutex),     _creationCost(CACHE_CREATION_COST_DEFAULT), _lastModified(0),     _lastAccessed(0), _flags(CACHE_FLAG_NULL), _key(), _path(), _sizeBytes(0),     _fileExists(false), _invalidated(false) { }   virtual ~SBcacheEntryDetails( );    // Release the cache entry   static VXItrdResult Release (SBcacheEntryDetails **rc) {     return SBcacheRefCount::Release (reinterpret_cast<SBcacheRefCount **>(rc)); }    // Create the entry   VXIcacheResult Create( );    // Open the entry   VXIcacheResult Open(VXIlogInterface       *log, 		      const SBcacheString   &moduleName, 		      const SBcacheKey      &key, 		      const SBcachePath     &path, 		      VXIcacheOpenMode       mode, 		      VXIint32               flags, 		      VXIulong               maxSizeBytes, 		      const VXIMap          *properties, 		      VXIMap                *streamInfo, 		      VXIcacheStream       **stream);    // Unlock the entry   VXIcacheResult Unlock(VXIlogInterface  *log);    // Accessors   bool IsLocked( ) const {     return ((_flags & (CACHE_FLAG_LOCK | CACHE_FLAG_LOCK_MEMORY)) != 0); }    bool IsExpired (time_t cutoffTime, time_t *lastAccessed) const {     bool expired = (( ! IsLocked( ) ) && ( _lastAccessed < cutoffTime ));     Diag (SBCACHE_ENTRY_TAGID, L"IsExpired", L"%s, %S, %s (%d %lu %lu)",           _key.c_str( ), _path.c_str( ), (expired ? L"true" : L"false"), 	  (int) IsLocked( ), (unsigned long) _lastAccessed,     	  (unsigned long) cutoffTime);     *lastAccessed = _lastAccessed;     return expired;   }    const SBcacheKey &GetKey( ) const { return _key; }   const SBcachePath &GetPath( ) const { return _path; }    VXIulong GetSizeBytes (bool haveEntryOpen) const {     VXIulong size = 0;     if (( haveEntryOpen ) || 	( _rwMutex.StartRead( ) == VXItrd_RESULT_SUCCESS )) {       size = _sizeBytes;       if ( ! haveEntryOpen ) 	_rwMutex.EndRead( );     }     return size;   }    // Error logging   VXIlogResult LogIOError (VXIunsigned errorID) const {     return Error (errorID, L"%s%S%s%S%s%d", L"path", _path.c_str( ), 		  L"errnoStr", strerror(errno), L"errno", errno);   }   VXIlogResult LogIOError (VXIlogInterface *log, 			   VXIunsigned errorID, 			   const SBcachePath &path) const {     return Error (log, errorID, L"%s%S%s%S%s%d", L"path", path.c_str( ), 		  L"errnoStr", strerror(errno), L"errno", errno);   }    // Comparison operators, smaller is defined as a preference for   // deleting this entry first, equality is having equal preference   bool operator< (const SBcacheEntryDetails &entry) const {     return ((( (! IsLocked( )) && (entry.IsLocked( )) ) || 	     ( _creationCost < entry._creationCost ) || 	     ( _lastAccessed < entry._lastAccessed ) || 	     ( _sizeBytes < entry._sizeBytes )) ? true : false);   }   bool operator> (const SBcacheEntryDetails &entry) const {     return ((( (IsLocked( )) && (! entry.IsLocked( )) ) || 	     ( _creationCost > entry._creationCost ) || 	     ( _lastAccessed > entry._lastAccessed ) || 	     ( _sizeBytes > entry._sizeBytes )) ? true : false);   }   bool operator== (const SBcacheEntryDetails &entry) const {     return ((( IsLocked( ) == entry.IsLocked( ) ) && 	     ( _creationCost == entry._creationCost ) && 	     ( _lastAccessed == entry._lastAccessed ) && 	     ( _sizeBytes == entry._sizeBytes )) ? true : false);   }   bool operator!= (const SBcacheEntryDetails &entry) const {     return ((( IsLocked( ) != entry.IsLocked( ) ) || 	     ( _creationCost != entry._creationCost ) || 	     ( _lastAccessed != entry._lastAccessed ) || 	     ( _sizeBytes != entry._sizeBytes )) ? true : false);   }  public:   // Only for SBcacheStream use    // Close   VXIcacheResult Close (VXIlogInterface  *log, 			VXIcacheOpenMode  mode, 			VXIunsigned       sizeBytes, 			bool              invalidate);  private:   // Delete the on-disk entry, internal routine, no mutex held   VXIcacheResult DeleteFile( );    // Disable the copy constructor and assignment operator   SBcacheEntryDetails(const SBcacheEntryDetails &entry);   const SBcacheEntryDetails &operator=(const SBcacheEntryDetails &entry);  private:   // Est base bytes: 76 + (wcslen(modname) + wcslen(key) + wcslen(path)) * 2   //                 76 + (10 + 32 + 40) * 2 = 76 + 164 = 240   //                 Linux: 76 + (*4)328 = 404   //                 404 + 8(refcnt) + (4 + 4 + (12 * 10) (logger)) = 540   SBcacheEntryMutex        _rwMutex;         // (12)   VXIcacheCreationCost     _creationCost;    // (4)   time_t                   _lastModified;    // (4)   time_t                   _lastAccessed;    // (4)   VXIint32                 _flags;           // (4)   SBcacheKey               _key;             // (12 + wcslen(key) * 2)   SBcachePath              _path;            // (12 + strlen(path))   VXIunsigned              _sizeBytes;       // (4)   bool                     _fileExists;      // (2?)   bool                     _invalidated;     // (2?) };   // Destructor SBcacheEntryDetails::~SBcacheEntryDetails( ) {   // Delete the on-disk file if appropriate   // TBD make this conditional by removing the #if 0 once   // persistant caching across process restarts (saving/loading   // the index file) is implemented #if 0   if ( _invalidated ) #endif     DeleteFile( ); }   // Create the entry VXIcacheResult SBcacheEntryDetails::Create( )

⌨️ 快捷键说明

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