📄 sbcacheentry.cpp
字号:
{ // 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)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -