📄 sbcache.cpp
字号:
/****************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. * ***********************************************************************/ #include "SBcacheInternal.h" #define OSBCACHE_EXPORTS #ifdef OPENVXI #define SBCACHE_API static #else #define SBCACHE_EXPORTS #include "SBcache.h" // Init/Shutdown/Create/Destroy #endif #include "OSBcache.h" // OSB version of init/shutdown/create/destroy #include "SBcacheManager.hpp" // For SBcacheManager #include "SBcacheLog.h" // For logging #include "base64.h" // base64 encoding functions #include "md5.h" // MD5 digest functions #define MAX_CACHE_KEY 256 /*****************************************************************************/ // Static definitions and functions /*****************************************************************************/ static VXIunsigned gblDiagTagBase = 0; static SBcacheManager *gblCacheMgr = NULL; // Static class to ensure the cache index file is updated even if // SBcacheShutDown( ) is not called class SBcacheTerminate { public: SBcacheTerminate( ) { } ~SBcacheTerminate( ); }; static SBcacheTerminate gblCacheTerminate; SBcacheTerminate::~SBcacheTerminate( ) { if (gblCacheMgr) { // Disable logging, the log resource is probably gone by now so // trying to use it as will be done at shutdown causes a crash gblCacheMgr->ClearLogResource( ); // Write out the index gblCacheMgr->WriteIndex( ); // NOTE: Do not delete the cache manager here, doing so may result // in crashes/asserts due to deleting mutexes that are active } } /*****************************************************************************/ // Cache Interface Class, one per channel /*****************************************************************************/ class SBcacheInterface : public VXIcacheInterface, public SBinetLogger { public: SBcacheInterface(VXIlogInterface *log, VXIunsigned diagTagBase); virtual ~SBcacheInterface( ) { } /****************************************/ // Static functions for mapping from C to C++ /****************************************/ static VXIint32 GetVersion(void); static const VXIchar* GetImplementationName(void); static VXIcacheResult CallOpen(struct VXIcacheInterface *pThis, const VXIchar *moduleName, const VXIchar *key, VXIcacheOpenMode mode, VXIint32 flags, const VXIMap *properties, VXIMap *streamInfo, VXIcacheStream **stream); static VXIcacheResult CallClose(struct VXIcacheInterface *pThis, VXIcacheStream **stream); static VXIcacheResult CallUnlock(struct VXIcacheInterface *pThis, const VXIchar *key); static VXIcacheResult CallRead(struct VXIcacheInterface *pThis, VXIbyte *buffer, VXIulong buflen, VXIulong *nread, VXIcacheStream *stream); static VXIcacheResult CallWrite(struct VXIcacheInterface *pThis, const VXIbyte *buffer, VXIulong buflen, VXIulong *nwritten, VXIcacheStream *stream); static VXIcacheResult CallOpenEx(struct VXIcacheInterface *pThis, const VXIchar *moduleName, const VXIbyte *key, VXIulong keySizeBytes, VXIcacheOpenMode mode, VXIint32 flags, const VXIMap *properties, VXIMap *streamInfo, VXIcacheStream **stream); static VXIcacheResult CallCloseEx(struct VXIcacheInterface *pThis, VXIbool keepEntry, VXIcacheStream **stream); static VXIcacheResult CallUnlockEx(struct VXIcacheInterface *pThis, const VXIbyte *key, VXIulong keySizeBytes); private: /****************************************/ // The real implementations /****************************************/ VXIcacheResult Open(const VXIchar *moduleName, const VXIchar *key, VXIcacheOpenMode mode, VXIint32 flags, const VXIMap *properties, VXIMap *streamInfo, VXIcacheStream **stream); VXIcacheResult Open(const VXIchar *moduleName, const VXIbyte *key, VXIulong keySizeBytes, VXIcacheOpenMode mode, VXIint32 flags, const VXIMap *properties, VXIMap *streamInfo, VXIcacheStream **stream); VXIcacheResult Close(VXIbool keepEntry, VXIcacheStream **stream); VXIcacheResult Unlock(const VXIchar *key); VXIcacheResult Unlock(const VXIbyte *key, VXIulong keySizeBytes); VXIcacheResult Read(VXIbyte *buffer, VXIulong buflen, VXIulong *nread, VXIcacheStream *stream); VXIcacheResult Write(const VXIbyte *buffer, VXIulong buflen, VXIulong *nwritten, VXIcacheStream *stream); /************************************/ // Utility methods /************************************/ SBcacheKey MakeCacheKey(const VXIbyte *buf, VXIunsigned bufSizeBytes) const; SBcacheKey MakeCacheKey(const VXIchar *buf) const; }; SBcacheInterface::SBcacheInterface(VXIlogInterface *log, VXIunsigned diagTagBase) : SBinetLogger(MODULE_SBCACHE, log, diagTagBase) { VXIcacheInterface::GetVersion = SBcacheInterface::GetVersion; VXIcacheInterface::GetImplementationName = SBcacheInterface::GetImplementationName; VXIcacheInterface::Open = SBcacheInterface::CallOpen; VXIcacheInterface::Close = SBcacheInterface::CallClose; VXIcacheInterface::Unlock = SBcacheInterface::CallUnlock; VXIcacheInterface::Read = SBcacheInterface::CallRead; VXIcacheInterface::Write = SBcacheInterface::CallWrite; VXIcacheInterface::OpenEx = SBcacheInterface::CallOpenEx; VXIcacheInterface::CloseEx = SBcacheInterface::CallCloseEx; VXIcacheInterface::UnlockEx = SBcacheInterface::CallUnlockEx; } VXIcacheResult SBcacheInterface::Open(const VXIchar *moduleName, const VXIchar *key, VXIcacheOpenMode mode, VXIint32 flags, const VXIMap *properties, VXIMap *streamInfo, VXIcacheStream **stream ) { VXIcacheResult rc = VXIcache_RESULT_SUCCESS; if (( ! key ) || ( ! key[0] ) || ( ! stream ) || ( mode > CACHE_MODE_READ_CREATE )) { Error (200, NULL); rc = VXIcache_RESULT_INVALID_ARGUMENT; } else { // Create the final cache key SBcacheKey finalKey = MakeCacheKey (key); if ( finalKey.length( ) == 0 ) { Error(100, NULL); rc = VXIcache_RESULT_OUT_OF_MEMORY; } else { // Open the cache entry SBcacheString finalModuleName; if ( moduleName ) finalModuleName = moduleName; rc = gblCacheMgr->Open (GetLog( ), finalModuleName, finalKey, mode, flags, properties, streamInfo, stream); } } return rc; } VXIcacheResult SBcacheInterface::Open(const VXIchar *moduleName, const VXIbyte *key, VXIulong keySizeBytes, VXIcacheOpenMode mode, VXIint32 flags, const VXIMap *properties, VXIMap *streamInfo, VXIcacheStream **stream ) { VXIcacheResult rc = VXIcache_RESULT_SUCCESS; if (( ! key ) || ( keySizeBytes < 1 ) || ( ! stream ) || ( mode > CACHE_MODE_READ_CREATE )) { Error (200, NULL); rc = VXIcache_RESULT_INVALID_ARGUMENT; } else { // Create the final cache key SBcacheKey finalKey = MakeCacheKey (key, keySizeBytes); if ( finalKey.length( ) == 0 ) { Error(100, NULL); rc = VXIcache_RESULT_OUT_OF_MEMORY; } else { // Open the cache entry SBcacheString finalModuleName; if ( moduleName ) finalModuleName = moduleName; rc = gblCacheMgr->Open (GetLog( ), finalModuleName, finalKey, mode, flags, properties, streamInfo, stream); } } return rc; } VXIcacheResult SBcacheInterface::Close (VXIbool keepEntry, VXIcacheStream **stream) { VXIcacheResult rc = VXIcache_RESULT_SUCCESS; if (( ! stream ) || ( ! *stream )) { Error (201, NULL); rc = VXIcache_RESULT_INVALID_ARGUMENT; } else { VXIcacheResult rc2; if ( ! keepEntry ) { // May have deleted the entry from the table already, so ignore // all non-fatal errors rc2 = gblCacheMgr->Delete (GetLog( ), (*stream)->GetKey( ), true); if ( rc2 < VXIcache_RESULT_SUCCESS ) rc = rc2; } rc2 = (*stream)->Close (keepEntry ? false : true); if ( rc2 != VXIcache_RESULT_SUCCESS ) rc = rc2; delete *stream; *stream = NULL; } return rc; } VXIcacheResult SBcacheInterface::Unlock(const VXIchar *key) { VXIcacheResult rc = VXIcache_RESULT_SUCCESS; if (( ! key ) || ( ! key[0] )) { Error (202, NULL); rc = VXIcache_RESULT_INVALID_ARGUMENT; } else { // Create the final cache key SBcacheKey finalKey = MakeCacheKey (key); if ( finalKey.length( ) == 0 ) { Error(100, NULL); rc = VXIcache_RESULT_OUT_OF_MEMORY; } else { // Unlock the entry rc = gblCacheMgr->Unlock (GetLog( ), finalKey); } } return rc; } VXIcacheResult SBcacheInterface::Unlock(const VXIbyte *key, VXIulong keySizeBytes) { VXIcacheResult rc = VXIcache_RESULT_SUCCESS; if (( ! key ) || ( keySizeBytes < 1 )) { Error (202, NULL); rc = VXIcache_RESULT_INVALID_ARGUMENT; } else { // Create the final cache key SBcacheKey finalKey = MakeCacheKey (key, keySizeBytes); if ( finalKey.length( ) == 0 ) { Error(100, NULL); rc = VXIcache_RESULT_OUT_OF_MEMORY; } else { // Unlock the entry rc = gblCacheMgr->Unlock (GetLog( ), finalKey); } } return rc; } VXIcacheResult SBcacheInterface::Read(VXIbyte *buffer, VXIulong buflen, VXIulong *nread, VXIcacheStream *stream ) { VXIcacheResult rc = VXIcache_RESULT_SUCCESS; if (( ! buffer ) || ( buflen < 1 ) || ( ! nread ) || ( ! stream )) { Error (203, NULL); rc = VXIcache_RESULT_INVALID_ARGUMENT; } else { rc = stream->Read (buffer, buflen, nread); } return rc; } VXIcacheResult SBcacheInterface::Write(const VXIbyte *buffer, VXIulong buflen, VXIulong *nwritten, VXIcacheStream *stream ) { VXIcacheResult rc = VXIcache_RESULT_SUCCESS; if (( ! buffer ) || ( buflen < 1 ) || ( ! nwritten ) || ( ! stream )) { Error (204, NULL); rc = VXIcache_RESULT_INVALID_ARGUMENT; } else { rc = stream->Write (buffer, buflen, nwritten); if (( rc == VXIcache_RESULT_SUCCESS ) || ( rc == VXIcache_RESULT_WOULD_BLOCK )) gblCacheMgr->WriteNotification (GetLog( ), stream->GetModuleName( ), *nwritten, stream->GetKey()); } return rc; } /** * Use MD5 to generate a key off binary data */ SBcacheKey SBcacheInterface::MakeCacheKey(const VXIbyte *buf, VXIunsigned bufSizeBytes) const { // Create a MD5 digest for the key unsigned char digest[16]; memset(digest, 0, 16 * sizeof(unsigned char)); MD5_CTX md5; MD5Init (&md5); MD5Update (&md5, buf, bufSizeBytes); MD5Final (digest, &md5); // The final key is an ASCII string using a base64 encoding of the // binary MD5 digest VXIchar keyBuf[B64ELEN(16) + 1]; keyBuf[B64ELEN(16)] = L'\0'; wcsb64e (digest, 16, keyBuf); return keyBuf; } /** * Generate a key off wide character data */ SBcacheKey SBcacheInterface::MakeCacheKey(const VXIchar *key) const { // If the text is too long, create a MD5 based key size_t keyLen = ::wcslen (key); if ( keyLen > MAX_CACHE_KEY ) return MakeCacheKey ((const VXIbyte *) key, keyLen * sizeof(*key));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -