|
|
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
contain.hxx
Abstract:
contains class definitions for CONTAINER class objects.
Author:
Madan Appiah (madana) 28-Dec-1994
Environment:
User Mode - Win32
Revision History:
--*/
#ifndef SAFERELEASE
#define SAFERELEASE(p,x) if ((p) != NULL) { (p)->Release(x); (p) = NULL; };
#endif
// so as to easily recognize Extensible prefixes, require them to start with
// a character that is illegal in URLs
#define EXTENSIBLE_FIRST (':')
struct SCORE_ITEM { DWORD dwScore; // score of this item
DWORD dwItemOffset; // offset to hash table item
DWORD dwHashValue; // masked value from hash table item
DWORD dwHashOffset; // offset to url entry from hash table item
};
/*++
Class Description:
Class definition that manages the URL objects.
Private Member functions:
Public Member functions:
URL_CONTAINER : constructs an URL container.
~URL_CONTAINER : destructs an URL container.
GetStatus : Retrieves object status.
CleanupUrls : Deletes unused URLs and frees up file system cache space.
DeleteIndex: Deletes all files not in use and attempts to delete index file.
AddUrl : Adds an URL to the container and copies the cache file.
RetrieveUrl : Retrieves an url from the cache.
DeleteUrl : Deletes the specified url from cache.
UnlockUrl : Decrements the reference count.
GetUrlInfo : Gets info of the specified url file.
SetUrlInfo : Sets info of the specified url file.
SetExemptDelta: Sets an exemption on the entry
CreateUniqueFile : Creates a file in the cache path for the incoming url to store.
GetCacheInfo : Retrieves certain container info.
SetCacheLimit : Sets cache limit value.
DeleteAPendingUrl : Removes and deletes an url from the pending list. Returns FALSE if the list is empty.
FindNextEntry : Retrieves the next element from the container.
GetCacheSize : return current size of the cache.
--*/
class GroupMgr;
class URL_CONTAINER {
protected:
// This class has one vtable, so there is also one dword of alignment padding.
LONGLONG _CacheStartUpLimit;
DWORD _Status;
MEMMAP_FILE* _UrlObjStorage; CFileMgr* _FileManager;
LPTSTR _CachePath; LPTSTR _CachePrefix; DWORD _CachePrefixLen; DWORD _CacheEntryType; LPTSTR _CacheName; DWORD _CachePathLen; DWORD _ClusterSizeMinusOne; DWORD _ClusterSizeMask; DWORD _FileMapEntrySize; HANDLE _MutexHandle; BOOL _fIsInitialized; DWORD _dwRefCount; BOOL _fDeletePending; BOOL _fDeleted; BOOL _fMarked; BOOL _fMustLaunchScavenger; BOOL _fPerUserItem; DWORD _dwLastReference; DWORD _dwOptions; DWORD _dwTaken;
DWORD _dwBytesDownloaded; DWORD _dwItemsDownloaded;
#ifdef CHECKLOCK_NORMAL
DWORD _dwThreadLocked; #endif
BOOL SetHeaderFlags(DWORD dwStamp); DWORD CopyUrlInfo( LPURL_FILEMAP_ENTRY, LPCACHE_ENTRY_INFO*, LPDWORD, DWORD); DWORD CopyUrlInfoGuard( LPURL_FILEMAP_ENTRY, LPCACHE_ENTRY_INFO*, LPDWORD, DWORD); void UnlockAllItems (void); void UnlockItem (URL_FILEMAP_ENTRY* pEntry, HASH_ITEM* pItem); BOOL UpdateOfflineRedirect (DWORD, LPCSTR, DWORD, LPCSTR); BOOL DeleteIndex (void); void CloseContainerFile(); DWORD SetExemptDelta (URL_FILEMAP_ENTRY*, DWORD dwExemptDelta, DWORD dwItemOffset=0); DWORD DeleteUrlEntry (URL_FILEMAP_ENTRY*, HASH_ITEM* pHash, DWORD dwSig);
DWORD UpdateStickness(URL_FILEMAP_ENTRY*, DWORD dwOp, DWORD dwItemOffset=0);
public: URL_CONTAINER( LPTSTR CacheName, LPTSTR CachePath, LPTSTR CachePrefix, LONGLONG CacheLimit, DWORD dwOptions ); ~URL_CONTAINER( VOID );
DWORD Init();
DWORD GetStatus( VOID ) { return( _Status ); };
#ifdef CHECKLOCK_PARANOID
void CheckNoLocks(DWORD dwThreadId); #endif
BOOL LockContainer( BOOL *fMustUnlock ); VOID UnlockContainer( VOID ); BOOL WalkLeakList (void);
DWORD GetLastReference(); BOOL IsVisible(); void Mark(BOOL fMarked); BOOL GetMarked(); BOOL GetDeleted(); void SetDeleted(BOOL fDeleted); BOOL GetDeletePending(); void SetDeletePending(BOOL fDeletePending); void AddRef(); DWORD Release(BOOL fTryToUnmap); void TryToUnmap(DWORD dwAcceptableRefCount); DWORD GetOptions();
//
// Internal routines called by the cache management.
//
DWORD CleanupUrls ( DWORD Factor, DWORD dwFilter);
DWORD FixupHandler (DWORD dwFactor, DWORD dwFilter);
BOOL PrefixMatch( LPCSTR UrlName ) { return (_CachePrefix && (strnicmp(_CachePrefix, UrlName, _CachePrefixLen)==0) ); }
#ifdef CHECKLOCK_PARANOID
void CheckUnlocked() { INET_ASSERT(_dwTaken==0 || GetCurrentThreadId() != _dwThreadLocked); } #endif
LPSTR GetCacheName() { return _CacheName; }
LPSTR GetCachePath() { return _CachePath; }
LPSTR GetCachePrefix() { return _CachePrefix; }
BOOL IsContentContainer() { return (_CachePrefix[0] == 0); }
DWORD GetCachePathLen() { return _CachePathLen; }
DWORD IsInitialized() { return _fIsInitialized; }
BOOL IsPerUserItem() { return _fPerUserItem; }
VOID SetPerUserItem(BOOL fFlag) { _fPerUserItem = fFlag; }
VOID SetCacheSize(LONGLONG dlSize) { _UrlObjStorage->SetCacheSize(dlSize); }
//
// External routines called by the cache APIs.
//
virtual LPSTR GetPrefixMap(); virtual LPSTR GetVolumeLabel(); virtual LPSTR GetVolumeTitle();
virtual DWORD AddUrl(AddUrlArg* args); virtual DWORD AddIdentityUrl(AddUrlArg* args);
virtual DWORD RetrieveUrl( LPCSTR UrlName, LPCACHE_ENTRY_INFO* EntryInfo, LPDWORD EntryInfoSize, DWORD dwLookupFlags, DWORD dwRetrievalFlags);
DWORD DeleteUrl( LPCSTR UrlName );
DWORD UnlockUrl( LPCSTR UrlName ); virtual DWORD GetUrlInfo( LPCSTR UrlName, LPCACHE_ENTRY_INFO* ppUrlInfo, LPDWORD UrlInfoLength, DWORD dwLookupFlags, DWORD dwEntryFlags, DWORD dwRetrievalFlags);
DWORD SetUrlInfo( LPCSTR UrlName, LPCACHE_ENTRY_INFO UrlInfo, DWORD FieldControl);
DWORD SetUrlGroup (LPCSTR lpszUrl, DWORD dwFlags, GROUPID GroupId);
DWORD GetUrlInGroup (LPCSTR lpszUrl, GROUPID* pGroupId, LPDWORD pdwExemptDelta);
DWORD CreateUniqueFile( LPCSTR UrlName, DWORD ExpectedSize, LPCSTR lpszFileExtension, LPTSTR FileName, HANDLE *phfHandle, BOOL fCreateUniqueFile = FALSE);
DWORD RegisterCacheNotify( HWND hWnd, UINT uMsg, GROUPID gid, DWORD dwFilter);
VOID SendCacheNotification(DWORD dwOpcode) { BOOL fUnlock;
LockContainer(&fUnlock); NotifyCacheChange(dwOpcode, 0); if (fUnlock) UnlockContainer(); }
VOID SetCacheLimit(LONGLONG CacheLimit ) { BOOL fUnlock;
LockContainer(&fUnlock); _UrlObjStorage->SetCacheLimit(CacheLimit); if (fUnlock) UnlockContainer(); }
LONGLONG GetCacheStartUpLimit() { BOOL fUnlock; LONGLONG llResult;
LockContainer(&fUnlock); llResult = _CacheStartUpLimit; if (fUnlock) UnlockContainer(); return llResult; }
LONGLONG GetCacheLimit() { BOOL fUnlock;
LockContainer(&fUnlock); LONGLONG cbLimit = _UrlObjStorage->GetCacheLimit(); if (fUnlock) UnlockContainer(); return cbLimit; }
LONGLONG GetCacheSize() { BOOL fUnlock;
LockContainer(&fUnlock); LONGLONG CacheSize = _UrlObjStorage->GetCacheSize(); if (fUnlock) UnlockContainer(); return CacheSize; }
LONGLONG GetExemptUsage() { BOOL fUnlock;
LockContainer(&fUnlock); LONGLONG ExemptCacheUsage = _UrlObjStorage->GetExemptUsage(); if (fUnlock) UnlockContainer(); return ExemptCacheUsage; }
VOID GetCacheInfo( LPTSTR CachePath, LONGLONG *CacheLimit ) { BOOL fUnlock;
LockContainer(&fUnlock); *CacheLimit = _UrlObjStorage->GetCacheLimit(); memcpy(CachePath, _CachePath, _CachePathLen); if (fUnlock) UnlockContainer(); }
DWORD GetInitialFindHandle (void) { DWORD dwHandle; BOOL fUnlock;
LockContainer(&fUnlock); dwHandle = *_UrlObjStorage->GetPtrToHashTableOffset(); if (fUnlock) UnlockContainer(); return dwHandle; }
DWORD FindNextEntry( LPDWORD Handle, LPCACHE_ENTRY_INFO* lppCacheEntryInfo, LPDWORD lpCacheEntryInfoSize, DWORD dwFilter, GROUPID GroupId, DWORD dwFlags, DWORD dwRetrievalFlags);
BOOL SetHeaderData(DWORD nIdx, DWORD dwData) { BOOL fRet, fUnlock; LockContainer(&fUnlock); fRet = _UrlObjStorage->SetHeaderData(nIdx, dwData); if (fUnlock) UnlockContainer(); return fRet; }
BOOL GetHeaderData(DWORD nIdx, LPDWORD pdwData) { BOOL fRet, fUnlock; LockContainer(&fUnlock); fRet = _UrlObjStorage->GetHeaderData(nIdx, pdwData); if (fUnlock) UnlockContainer(); return fRet; }
BOOL IncrementHeaderData(DWORD nIdx, LPDWORD pdwData) { BOOL fRet, fUnlock; LockContainer(&fUnlock); fRet = _UrlObjStorage->IncrementHeaderData(nIdx, pdwData); if (fUnlock) UnlockContainer(); return fRet; }
DWORD AddLeakFile (LPCSTR pszFile);
// Creates a cache directory with a given name to allow existing directories
// to be copied into another cache file.
BOOL CreateDirWithSecureName( LPSTR szDirName) { return _FileManager->CreateDirWithSecureName( szDirName); }
// Creates a redirect from TargetUrl to OriginUrl
BOOL CreateRedirect( LPSTR szTargetUrl, LPSTR szOriginUrl) { BOOL retVal = FALSE;
HASH_ITEM* pTargetItem;
if( HashFindItem( szTargetUrl, 0, &pTargetItem) != TRUE) goto doneCreateRedirect;
if( UpdateOfflineRedirect( OffsetFromPointer(pTargetItem), szTargetUrl, lstrlen( szTargetUrl), szOriginUrl) != TRUE) goto doneCreateRedirect;
retVal = TRUE;
doneCreateRedirect: return retVal; }
private:
// hash table wrapper methods
DWORD OffsetFromPointer (LPVOID p) { SSIZE_T llDiff = PtrDifference(p, *_UrlObjStorage->GetHeapStart()); #if defined(_AMD64_) || defined(_IA64_)
return GuardedCast(llDiff); #else
return llDiff; #endif
}
LPBYTE PointerFromOffset (DWORD dw) { return ((LPBYTE) *_UrlObjStorage->GetHeapStart()) + dw; }
LPURL_FILEMAP_ENTRY HashGetEntry (HASH_ITEM *pItem) { INET_ASSERT (pItem->dwHash > HASH_END); return (URL_FILEMAP_ENTRY*) PointerFromOffset (pItem->dwOffset); }
void HashSetEntry (HASH_ITEM* pItem, LPBYTE pEntry) { pItem->dwOffset = OffsetFromPointer (pEntry); }
BOOL HashFindItem (LPCSTR pszUrl, DWORD dwLookupFlags, HASH_ITEM** ppItem); /////////////////////////////////////////////////////////////////////////////
// WARNING: if HASH_*_CREATE set, the file might be grown and remapped //
// so all pointers into the file must be recalculated from their offsets //
/////////////////////////////////////////////////////////////////////////////
PRIVATE HASH_ITEM* IsMatch (HASH_ITEM *pItem, LPCSTR pszKey, DWORD dwFlags);
LPURL_FILEMAP_ENTRY HashFindEntry (LPCSTR pszUrl, DWORD dwLookupFlags = 0) { HASH_ITEM *pItem; if (HashFindItem (pszUrl, dwLookupFlags, &pItem)) return HashGetEntry (pItem); else return NULL; }
void AdjustGroupUsage(GROUP_ENTRY* pGroupEntry, LONGLONG llDelta) { if( pGroupEntry && !IsInvalidGroup(pGroupEntry->gid) ) { if( pGroupEntry->llDiskUsage >= -llDelta ) { pGroupEntry->llDiskUsage += llDelta; } else { INET_ASSERT(FALSE); // underflow
pGroupEntry->llDiskUsage = 0; } } }
VOID NotifyCacheChange(DWORD dwOpcode, DWORD dwHOffset) { //
// the caller of this method has container locked, so there
// no need to call (Un)LockContain here.
//
DWORD dwFilter = 0; _UrlObjStorage->GetHeaderData( CACHE_HEADER_DATA_NOTIFICATION_FILTER, &dwFilter);
if( dwFilter & dwOpcode ) { DWORD dwHWnd = 0; DWORD dwUMsg = 0;
_UrlObjStorage->GetHeaderData( CACHE_HEADER_DATA_NOTIFICATION_HWND, &dwHWnd); _UrlObjStorage->GetHeaderData( CACHE_HEADER_DATA_NOTIFICATION_MESG, &dwUMsg);
if( dwHWnd && dwUMsg && IsWindow((HWND)DWORD_PTR(dwHWnd)) ) { // NOTE: we will not check for msg q overflow
PostMessage( (HWND)DWORD_PTR(dwHWnd), (UINT)dwUMsg, (WPARAM)dwOpcode, (LPARAM)dwHOffset ); } } }
BOOL IsUrlEntryExemptFromScavenging ( HASH_ITEM* pItem, URL_FILEMAP_ENTRY* pEntry, DWORD dwFilter, LONGLONG qwGmtTime, GroupMgr* pgm );
BOOL ScavengeItem (HASH_ITEM* pItem, BOOL* pfMustUnlock);
void ScavengerDebugSpew (SCORE_ITEM*, LONGLONG*);
friend class GroupMgr; };
|