📄 sbcacheentry.cpp
字号:
// Create the entry
VXIcacheResult SBcacheEntryDetails::Create( )
{
// Create the mutex
VXIcacheResult rc = VXIcache_RESULT_SUCCESS;
if ( _rwMutex.Create(L"SBcacheEntry rw mutex") != VXItrd_RESULT_SUCCESS ) {
Error (109, L"%s%s", L"mutex", L"cache entry rw mutex");
rc = VXIcache_RESULT_SYSTEM_ERROR;
}
return rc;
}
// Open the entry
VXIcacheResult SBcacheEntryDetails::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)
{
VXIcacheResult rc = VXIcache_RESULT_SUCCESS;
FILE *filePtr = NULL;
// Lock and copy input data
switch ( mode ) {
case CACHE_MODE_WRITE:
if ( _rwMutex.Lock( ) != VXItrd_RESULT_SUCCESS ) {
Error (log, 110, L"%s%s", L"mutex", L"cache entry rw mutex, writer");
rc = VXIcache_RESULT_SYSTEM_ERROR;
} else {
// If the open fails due to directory not existing, call
// path.CreateDirectories( ) to create the dir tree then open
// again
if ( ! _invalidated ) {
filePtr = fopen (path.c_str( ), "wb");
int retries = 10; // work around possible race condition w/ rmdir
while ((retries-- > 0) &&
( ! filePtr ) &&
( path.CreateDirectories( ) == VXIcache_RESULT_SUCCESS ))
filePtr = fopen (path.c_str( ), "wb");
}
if ( ! filePtr ) {
if ( _invalidated ) {
// Invalidated or another thread attempted an open for write
// and failed, we only got here due to a race condition
// where we were waiting on the mutex to start our write
// before the failure/invalidation happened by the previous
// writer
rc = VXIcache_RESULT_FAILURE;
} else {
// File open error
LogIOError (log, 213, path);
rc = VXIcache_RESULT_IO_ERROR;
}
_fileExists = false;
_rwMutex.Unlock( );
} else {
_fileExists = true;
_creationCost = CACHE_CREATION_COST_DEFAULT;
_flags = flags;
_sizeBytes = 0;
// Only set the path and key if they differ
if (path != _path || key != _key) {
_path = path;
_key = key;
}
// Load properties
if ( properties ) {
const VXIValue *value =
VXIMapGetProperty (properties, CACHE_CREATION_COST);
if ( value ) {
if ( VXIValueGetType(value) == VALUE_INTEGER )
_creationCost = (VXIcacheCreationCost)
VXIIntegerValue ((const VXIInteger *) value);
else
Error (log, 301, L"%s%d", L"VXIValueType",
VXIValueGetType(value));
}
}
}
}
break;
case CACHE_MODE_READ:
if ( _rwMutex.StartRead( ) != VXItrd_RESULT_SUCCESS ) {
Error (log, 110, L"%s%s", L"mutex", L"cache entry rw mutex, reader");
rc = VXIcache_RESULT_SYSTEM_ERROR;
} else {
if (( _fileExists ) && ( ! _invalidated )) {
filePtr = fopen (_path.c_str( ), "rb");
if ( ! filePtr ) {
_fileExists = false;
LogIOError (log, 214, _path);
_rwMutex.EndRead( );
rc = VXIcache_RESULT_IO_ERROR;
}
} else {
// Invalidated or another thread attempted an open for write
// and failed, we only got here due to a race condition where
// we were waiting on the mutex to start our read before the
// failure/invalidation happened by the writer
_rwMutex.EndRead( );
rc = VXIcache_RESULT_FAILURE;
}
}
break;
default:
Error (log, 215, L"%s%d", L"mode", mode);
rc = VXIcache_RESULT_UNSUPPORTED;
}
if ( rc == VXIcache_RESULT_SUCCESS ) {
// Update the accessed time
_lastAccessed = time(0);
if (mode == CACHE_MODE_WRITE)
_lastModified = _lastAccessed;
// Return stream information
if ( streamInfo ) {
if (( VXIMapSetProperty (streamInfo, CACHE_INFO_LAST_MODIFIED,
(VXIValue *) VXIIntegerCreate(_lastModified)) !=
VXIvalue_RESULT_SUCCESS ) ||
( VXIMapSetProperty (streamInfo, CACHE_INFO_SIZE_BYTES,
(VXIValue *) VXIIntegerCreate (_sizeBytes)) !=
VXIvalue_RESULT_SUCCESS )) {
Error (log, 100, NULL);
rc = VXIcache_RESULT_OUT_OF_MEMORY;
}
}
}
// Return the stream
if ( rc == VXIcache_RESULT_SUCCESS ) {
SBcacheEntry entry(this);
*stream = new SBcacheStream (log, GetDiagBase( ), moduleName, key,
entry, mode,
((flags & CACHE_FLAG_NONBLOCKING_IO) == 0),
maxSizeBytes, filePtr);
if ( ! *stream ) {
Error (log, 100, NULL);
fclose (filePtr);
Close (log, mode, 0, true);
rc = VXIcache_RESULT_OUT_OF_MEMORY;
}
}
Diag (log, SBCACHE_ENTRY_TAGID, L"Open", L"%s, %S, 0x%x, 0x%x: rc = %d",
key.c_str( ), path.c_str( ), mode, flags, rc);
return rc;
}
// Close the entry
VXIcacheResult SBcacheEntryDetails::Close(VXIlogInterface *log,
VXIcacheOpenMode mode,
VXIunsigned sizeBytes,
bool invalidate)
{
VXIcacheResult rc = VXIcache_RESULT_SUCCESS;
Diag (log, SBCACHE_ENTRY_TAGID, L"Close", L"entering: %s, %S, 0x%x, %u, %d",
_key.c_str( ), _path.c_str( ), mode, sizeBytes, invalidate);
// Invalidate the entry if requested to do so, we just set a flag so
// when the entry is deleted we remove the on-disk copy. Can't just
// do "_invalidated = invalidate" as there may be multiple readers
// at once, if one reader thinks we're good (don't invalidate) and
// another thinks we're bad (invalidate) don't want us to have race
// conditions where we ignore the invalidate request.
if ( invalidate )
_invalidated = true;
// Unlock the entry, note that we should avoid doing anything after
// the unlock (including logging ) because this object may get
// deleted as soon as we do so
switch ( mode ) {
case CACHE_MODE_WRITE:
_sizeBytes = sizeBytes;
if ( _rwMutex.Unlock( ) != VXItrd_RESULT_SUCCESS ) {
Error (log, 111, L"%s%s", L"mutex", L"cache entry rw mutex, writer");
rc = VXIcache_RESULT_SYSTEM_ERROR;
}
break;
case CACHE_MODE_READ:
if ( _rwMutex.EndRead( ) != VXItrd_RESULT_SUCCESS ) {
Error (log, 111, L"%s%s", L"mutex", L"cache entry rw mutex, reader");
rc = VXIcache_RESULT_SYSTEM_ERROR;
}
break;
default:
Error (log, 211, L"%s%d", L"mode", mode);
rc = VXIcache_RESULT_FATAL_ERROR;
}
Diag (log, SBCACHE_ENTRY_TAGID, L"Close", L"exiting: rc = %d", rc);
return rc;
}
// Unlock the entry
VXIcacheResult SBcacheEntryDetails::Unlock(VXIlogInterface *log)
{
VXIcacheResult rc = VXIcache_RESULT_SUCCESS;
if ( _rwMutex.Lock( ) != VXItrd_RESULT_SUCCESS ) {
Error (log, 110, L"%s%s", L"mutex", L"cache entry rw mutex, writer");
rc = VXIcache_RESULT_SYSTEM_ERROR;
} else {
if ( _flags & CACHE_FLAG_LOCK )
_flags = (_flags ^ CACHE_FLAG_LOCK);
if ( _flags & CACHE_FLAG_LOCK_MEMORY )
_flags = (_flags ^ CACHE_FLAG_LOCK_MEMORY);
if ( _rwMutex.Unlock( ) != VXItrd_RESULT_SUCCESS ) {
Error (log, 111, L"%s%s", L"mutex", L"cache entry rw mutex, writer");
rc = VXIcache_RESULT_SYSTEM_ERROR;
}
}
Diag (log, SBCACHE_ENTRY_TAGID, L"Unlock", L"%s, %S: rc = %d",
_key.c_str( ), _path.c_str( ), rc);
return rc;
}
// Delete the on-disk entry, internal routine, no mutex held
VXIcacheResult SBcacheEntryDetails::DeleteFile( )
{
VXIcacheResult rc = VXIcache_RESULT_SUCCESS;
// Delete the file
if ( _fileExists ) {
if ( remove (_path.c_str( )) != 0 )
LogIOError (216);
// Remove directory
SBcacheNString head(_path.c_str());
SBcacheNString::size_type pos = head.find_last_of("/\\");
if (pos != SBcacheNString::npos) {
head = head.substr(0, pos);
if (!head.empty()) {
#ifdef WIN32
RemoveDirectory(head.c_str());
#else
rmdir(head.c_str());
#endif
}
}
_fileExists = false;
}
Diag (SBCACHE_ENTRY_TAGID, L"DeleteFile", L"%s, %S: rc = %d",
_key.c_str( ), _path.c_str( ), rc);
return rc;
}
// -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
// Construct a SBcacheEntry from details
SBcacheEntry::SBcacheEntry (SBcacheEntryDetails *details) : _details(details)
{
if ( SBcacheEntryDetails::AddRef (_details) != VXItrd_RESULT_SUCCESS )
_details = NULL;
}
// Destructor
SBcacheEntry::~SBcacheEntry( )
{
if ( _details )
SBcacheEntryDetails::Release (&_details);
}
// Create the entry
VXIcacheResult SBcacheEntry::Create(VXIlogInterface *log,
VXIunsigned diagTagBase,
SBcacheMutex *refCountMutex)
{
if ( _details )
return VXIcache_RESULT_FATAL_ERROR;
VXIcacheResult rc;
_details = new SBcacheEntryDetails (log, diagTagBase, refCountMutex);
if ( ! _details ) {
SBinetLogger::Error (log, MODULE_SBCACHE, 100, NULL);
rc = VXIcache_RESULT_OUT_OF_MEMORY;
} else {
rc = _details->Create( );
}
return rc;
}
// Open the entry
VXIcacheResult SBcacheEntry::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)
{
return (_details == NULL ? VXIcache_RESULT_FATAL_ERROR :
_details->Open (log, moduleName, key, path, mode, flags,
maxSizeBytes, properties, streamInfo, stream));
}
// Close the entry
VXIcacheResult SBcacheEntry::Close(VXIlogInterface *log,
VXIcacheOpenMode mode,
VXIunsigned sizeBytes,
bool invalidate)
{
return (_details == NULL ? VXIcache_RESULT_FATAL_ERROR :
_details->Close (log, mode, sizeBytes, invalidate));
}
// Unlock the entry
VXIcacheResult SBcacheEntry::Unlock(VXIlogInterface *log)
{
return (_details == NULL ? VXIcache_RESULT_FATAL_ERROR :
_details->Unlock (log));
}
// Accessors
bool SBcacheEntry::IsLocked( ) const
{
return _details->IsLocked( );
}
bool SBcacheEntry::IsExpired (time_t cutoffTime,
time_t *lastAccessed) const
{
return _details->IsExpired (cutoffTime, lastAccessed);
}
const SBcacheKey & SBcacheEntry::GetKey( ) const
{
return _details->GetKey( );
}
const SBcachePath & SBcacheEntry::GetPath( ) const
{
return _details->GetPath( );
}
VXIulong SBcacheEntry::GetSizeBytes (bool haveEntryOpen) const
{
return _details->GetSizeBytes (haveEntryOpen);
}
// Error logging
VXIlogResult SBcacheEntry::LogIOError (VXIunsigned errorID) const
{
return _details->LogIOError (errorID);
}
// Copy constructor and assignment operator that implement reference
// counting of the held SBcacheEntryData
SBcacheEntry::SBcacheEntry (const SBcacheEntry & e) : _details(e._details)
{
if ( SBcacheEntryDetails::AddRef (_details) != VXItrd_RESULT_SUCCESS )
_details = NULL;
}
SBcacheEntry & SBcacheEntry::operator= (const SBcacheEntry & e)
{
if ( &e != this ) {
SBcacheEntryDetails::Release (&_details);
if ( SBcacheEntryDetails::AddRef (e._details) == VXItrd_RESULT_SUCCESS )
_details = e._details;
}
return *this;
}
// Comparison operators, smaller is defined as a preference for
// deleting this entry first, equality is having equal preference
bool SBcacheEntry::operator< (const SBcacheEntry &entry) const
{
return _details->operator< (*(entry._details));
}
bool SBcacheEntry::operator> (const SBcacheEntry &entry) const
{
return _details->operator> (*(entry._details));
}
bool SBcacheEntry::operator== (const SBcacheEntry &entry) const
{
return _details->operator== (*(entry._details));
}
bool SBcacheEntry::operator!= (const SBcacheEntry &entry) const
{
return _details->operator!= (*(entry._details));
}
#endif // P_VXI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -