📄 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 <vxibuildopts.h>
#if P_VXI
#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));
return key;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -