Commit 393c5af2 authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

ole32: Add a cache for block chain streams in StorageImpl.

parent c6d4df8b
...@@ -2268,6 +2268,63 @@ static HRESULT StorageImpl_BaseReadDirEntry(StorageBaseImpl *base, ...@@ -2268,6 +2268,63 @@ static HRESULT StorageImpl_BaseReadDirEntry(StorageBaseImpl *base,
return StorageImpl_ReadDirEntry(This, index, data); return StorageImpl_ReadDirEntry(This, index, data);
} }
static BlockChainStream **StorageImpl_GetFreeBlockChainCacheEntry(StorageImpl* This)
{
int i;
for (i=0; i<BLOCKCHAIN_CACHE_SIZE; i++)
{
if (!This->blockChainCache[i])
{
return &This->blockChainCache[i];
}
}
i = This->blockChainToEvict;
BlockChainStream_Destroy(This->blockChainCache[i]);
This->blockChainCache[i] = NULL;
This->blockChainToEvict++;
if (This->blockChainToEvict == BLOCKCHAIN_CACHE_SIZE)
This->blockChainToEvict = 0;
return &This->blockChainCache[i];
}
static BlockChainStream **StorageImpl_GetCachedBlockChainStream(StorageImpl *This,
DirRef index)
{
int i, free_index=-1;
for (i=0; i<BLOCKCHAIN_CACHE_SIZE; i++)
{
if (!This->blockChainCache[i])
{
if (free_index == -1) free_index = i;
}
else if (This->blockChainCache[i]->ownerDirEntry == index)
{
return &This->blockChainCache[i];
}
}
if (free_index == -1)
{
free_index = This->blockChainToEvict;
BlockChainStream_Destroy(This->blockChainCache[free_index]);
This->blockChainCache[free_index] = NULL;
This->blockChainToEvict++;
if (This->blockChainToEvict == BLOCKCHAIN_CACHE_SIZE)
This->blockChainToEvict = 0;
}
This->blockChainCache[free_index] = BlockChainStream_Construct(This, NULL, index);
return &This->blockChainCache[free_index];
}
static HRESULT StorageImpl_StreamReadAt(StorageBaseImpl *base, DirRef index, static HRESULT StorageImpl_StreamReadAt(StorageBaseImpl *base, DirRef index,
ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead) ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead)
{ {
...@@ -2309,15 +2366,13 @@ static HRESULT StorageImpl_StreamReadAt(StorageBaseImpl *base, DirRef index, ...@@ -2309,15 +2366,13 @@ static HRESULT StorageImpl_StreamReadAt(StorageBaseImpl *base, DirRef index,
} }
else else
{ {
BlockChainStream *stream; BlockChainStream *stream = NULL;
stream = BlockChainStream_Construct(This, NULL, index); stream = *StorageImpl_GetCachedBlockChainStream(This, index);
if (!stream) return E_OUTOFMEMORY; if (!stream) return E_OUTOFMEMORY;
hr = BlockChainStream_ReadAt(stream, offset, bytesToRead, buffer, bytesRead); hr = BlockChainStream_ReadAt(stream, offset, bytesToRead, buffer, bytesRead);
BlockChainStream_Destroy(stream);
return hr; return hr;
} }
} }
...@@ -2329,7 +2384,7 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index, ...@@ -2329,7 +2384,7 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
DirEntry data; DirEntry data;
HRESULT hr; HRESULT hr;
SmallBlockChainStream *smallblock=NULL; SmallBlockChainStream *smallblock=NULL;
BlockChainStream *bigblock=NULL; BlockChainStream **pbigblock=NULL, *bigblock=NULL;
hr = StorageImpl_ReadDirEntry(This, index, &data); hr = StorageImpl_ReadDirEntry(This, index, &data);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
...@@ -2351,7 +2406,8 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index, ...@@ -2351,7 +2406,8 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
} }
else else
{ {
bigblock = BlockChainStream_Construct(This, NULL, index); pbigblock = StorageImpl_GetCachedBlockChainStream(This, index);
bigblock = *pbigblock;
if (!bigblock) return E_OUTOFMEMORY; if (!bigblock) return E_OUTOFMEMORY;
} }
} }
...@@ -2362,7 +2418,8 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index, ...@@ -2362,7 +2418,8 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
} }
else else
{ {
bigblock = BlockChainStream_Construct(This, NULL, index); pbigblock = StorageImpl_GetCachedBlockChainStream(This, index);
bigblock = *pbigblock;
if (!bigblock) return E_OUTOFMEMORY; if (!bigblock) return E_OUTOFMEMORY;
} }
...@@ -2375,15 +2432,15 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index, ...@@ -2375,15 +2432,15 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
SmallBlockChainStream_Destroy(smallblock); SmallBlockChainStream_Destroy(smallblock);
return E_FAIL; return E_FAIL;
} }
pbigblock = StorageImpl_GetFreeBlockChainCacheEntry(This);
*pbigblock = bigblock;
} }
else if (bigblock && newsize.QuadPart < LIMIT_TO_USE_SMALL_BLOCK) else if (bigblock && newsize.QuadPart < LIMIT_TO_USE_SMALL_BLOCK)
{ {
smallblock = Storage32Impl_BigBlocksToSmallBlocks(This, &bigblock); smallblock = Storage32Impl_BigBlocksToSmallBlocks(This, pbigblock);
if (!smallblock) if (!smallblock)
{
BlockChainStream_Destroy(bigblock);
return E_FAIL; return E_FAIL;
}
} }
/* Set the size of the block chain. */ /* Set the size of the block chain. */
...@@ -2395,7 +2452,6 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index, ...@@ -2395,7 +2452,6 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
else else
{ {
BlockChainStream_SetSize(bigblock, newsize); BlockChainStream_SetSize(bigblock, newsize);
BlockChainStream_Destroy(bigblock);
} }
/* Set the size in the directory entry. */ /* Set the size in the directory entry. */
...@@ -2450,13 +2506,11 @@ static HRESULT StorageImpl_StreamWriteAt(StorageBaseImpl *base, DirRef index, ...@@ -2450,13 +2506,11 @@ static HRESULT StorageImpl_StreamWriteAt(StorageBaseImpl *base, DirRef index,
{ {
BlockChainStream *stream; BlockChainStream *stream;
stream = BlockChainStream_Construct(This, NULL, index); stream = *StorageImpl_GetCachedBlockChainStream(This, index);
if (!stream) return E_OUTOFMEMORY; if (!stream) return E_OUTOFMEMORY;
hr = BlockChainStream_WriteAt(stream, offset, size, buffer, bytesWritten); hr = BlockChainStream_WriteAt(stream, offset, size, buffer, bytesWritten);
BlockChainStream_Destroy(stream);
return hr; return hr;
} }
} }
...@@ -2741,6 +2795,7 @@ static void StorageImpl_Invalidate(StorageBaseImpl* iface) ...@@ -2741,6 +2795,7 @@ static void StorageImpl_Invalidate(StorageBaseImpl* iface)
static void StorageImpl_Destroy(StorageBaseImpl* iface) static void StorageImpl_Destroy(StorageBaseImpl* iface)
{ {
StorageImpl *This = (StorageImpl*) iface; StorageImpl *This = (StorageImpl*) iface;
int i;
TRACE("(%p)\n", This); TRACE("(%p)\n", This);
StorageImpl_Invalidate(iface); StorageImpl_Invalidate(iface);
...@@ -2751,6 +2806,9 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface) ...@@ -2751,6 +2806,9 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface)
BlockChainStream_Destroy(This->rootBlockChain); BlockChainStream_Destroy(This->rootBlockChain);
BlockChainStream_Destroy(This->smallBlockDepotChain); BlockChainStream_Destroy(This->smallBlockDepotChain);
for (i=0; i<BLOCKCHAIN_CACHE_SIZE; i++)
BlockChainStream_Destroy(This->blockChainCache[i]);
if (This->bigBlockFile) if (This->bigBlockFile)
BIGBLOCKFILE_Destructor(This->bigBlockFile); BIGBLOCKFILE_Destructor(This->bigBlockFile);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
......
...@@ -325,6 +325,9 @@ static inline HRESULT StorageBaseImpl_StreamSetSize(StorageBaseImpl *This, ...@@ -325,6 +325,9 @@ static inline HRESULT StorageBaseImpl_StreamSetSize(StorageBaseImpl *This,
void StorageBaseImpl_AddStream(StorageBaseImpl * stg, StgStreamImpl * strm); void StorageBaseImpl_AddStream(StorageBaseImpl * stg, StgStreamImpl * strm);
void StorageBaseImpl_RemoveStream(StorageBaseImpl * stg, StgStreamImpl * strm); void StorageBaseImpl_RemoveStream(StorageBaseImpl * stg, StgStreamImpl * strm);
/* Number of BlockChainStream objects to cache in a StorageImpl */
#define BLOCKCHAIN_CACHE_SIZE 4
/**************************************************************************** /****************************************************************************
* Storage32Impl definitions. * Storage32Impl definitions.
* *
...@@ -367,6 +370,10 @@ struct StorageImpl ...@@ -367,6 +370,10 @@ struct StorageImpl
BlockChainStream* smallBlockDepotChain; BlockChainStream* smallBlockDepotChain;
BlockChainStream* smallBlockRootChain; BlockChainStream* smallBlockRootChain;
/* Cache of block chain streams objects for directory entries */
BlockChainStream* blockChainCache[BLOCKCHAIN_CACHE_SIZE];
UINT blockChainToEvict;
/* /*
* Pointer to the big block file abstraction * Pointer to the big block file abstraction
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment