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

📄 sbcacheentry.cpp

📁 sloedgy open sip stack source code
💻 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 <vxibuildopts.h>
#if P_VXI
 
 #include "SBcacheEntry.hpp"   // For this class
 #include "SBcacheMisc.hpp"    // For SBcacheReaderWriterMutex,
                               // SBcacheRefCount base class
 
 #include "vxi/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

#if defined(_MSC_VER)
#pragma warning(disable:4061)
#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( );
 }
 

⌨️ 快捷键说明

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