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

Alexandre Julliard julliard at winehq.org
Wed Dec 16 09:41:32 CST 2009


Module: wine
Branch: master
Commit: 393c5af205c5b25a50e0b2d06a5889162286abf2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=393c5af205c5b25a50e0b2d06a5889162286abf2

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Tue Dec 15 14:44:49 2009 -0600

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

---

 dlls/ole32/storage32.c |   88 +++++++++++++++++++++++++++++++++++++++--------
 dlls/ole32/storage32.h |    7 ++++
 2 files changed, 80 insertions(+), 15 deletions(-)

diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c
index 90d2434..2a7e9f0 100644
--- a/dlls/ole32/storage32.c
+++ b/dlls/ole32/storage32.c
@@ -2268,6 +2268,63 @@ static HRESULT StorageImpl_BaseReadDirEntry(StorageBaseImpl *base,
   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,
   ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead)
 {
@@ -2309,15 +2366,13 @@ static HRESULT StorageImpl_StreamReadAt(StorageBaseImpl *base, DirRef index,
   }
   else
   {
-    BlockChainStream *stream;
+    BlockChainStream *stream = NULL;
 
-    stream = BlockChainStream_Construct(This, NULL, index);
+    stream = *StorageImpl_GetCachedBlockChainStream(This, index);
     if (!stream) return E_OUTOFMEMORY;
 
     hr = BlockChainStream_ReadAt(stream, offset, bytesToRead, buffer, bytesRead);
 
-    BlockChainStream_Destroy(stream);
-
     return hr;
   }
 }
@@ -2329,7 +2384,7 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
   DirEntry data;
   HRESULT hr;
   SmallBlockChainStream *smallblock=NULL;
-  BlockChainStream *bigblock=NULL;
+  BlockChainStream **pbigblock=NULL, *bigblock=NULL;
 
   hr = StorageImpl_ReadDirEntry(This, index, &data);
   if (FAILED(hr)) return hr;
@@ -2351,7 +2406,8 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
     }
     else
     {
-      bigblock = BlockChainStream_Construct(This, NULL, index);
+      pbigblock = StorageImpl_GetCachedBlockChainStream(This, index);
+      bigblock = *pbigblock;
       if (!bigblock) return E_OUTOFMEMORY;
     }
   }
@@ -2362,7 +2418,8 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
   }
   else
   {
-    bigblock = BlockChainStream_Construct(This, NULL, index);
+    pbigblock = StorageImpl_GetCachedBlockChainStream(This, index);
+    bigblock = *pbigblock;
     if (!bigblock) return E_OUTOFMEMORY;
   }
 
@@ -2375,15 +2432,15 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
       SmallBlockChainStream_Destroy(smallblock);
       return E_FAIL;
     }
+
+    pbigblock = StorageImpl_GetFreeBlockChainCacheEntry(This);
+    *pbigblock = bigblock;
   }
   else if (bigblock && newsize.QuadPart < LIMIT_TO_USE_SMALL_BLOCK)
   {
-    smallblock = Storage32Impl_BigBlocksToSmallBlocks(This, &bigblock);
+    smallblock = Storage32Impl_BigBlocksToSmallBlocks(This, pbigblock);
     if (!smallblock)
-    {
-      BlockChainStream_Destroy(bigblock);
       return E_FAIL;
-    }
   }
 
   /* Set the size of the block chain. */
@@ -2395,7 +2452,6 @@ static HRESULT StorageImpl_StreamSetSize(StorageBaseImpl *base, DirRef index,
   else
   {
     BlockChainStream_SetSize(bigblock, newsize);
-    BlockChainStream_Destroy(bigblock);
   }
 
   /* Set the size in the directory entry. */
@@ -2450,13 +2506,11 @@ static HRESULT StorageImpl_StreamWriteAt(StorageBaseImpl *base, DirRef index,
   {
     BlockChainStream *stream;
 
-    stream = BlockChainStream_Construct(This, NULL, index);
+    stream = *StorageImpl_GetCachedBlockChainStream(This, index);
     if (!stream) return E_OUTOFMEMORY;
 
     hr = BlockChainStream_WriteAt(stream, offset, size, buffer, bytesWritten);
 
-    BlockChainStream_Destroy(stream);
-
     return hr;
   }
 }
@@ -2741,6 +2795,7 @@ static void StorageImpl_Invalidate(StorageBaseImpl* iface)
 static void StorageImpl_Destroy(StorageBaseImpl* iface)
 {
   StorageImpl *This = (StorageImpl*) iface;
+  int i;
   TRACE("(%p)\n", This);
 
   StorageImpl_Invalidate(iface);
@@ -2751,6 +2806,9 @@ static void StorageImpl_Destroy(StorageBaseImpl* iface)
   BlockChainStream_Destroy(This->rootBlockChain);
   BlockChainStream_Destroy(This->smallBlockDepotChain);
 
+  for (i=0; i<BLOCKCHAIN_CACHE_SIZE; i++)
+    BlockChainStream_Destroy(This->blockChainCache[i]);
+
   if (This->bigBlockFile)
     BIGBLOCKFILE_Destructor(This->bigBlockFile);
   HeapFree(GetProcessHeap(), 0, This);
diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h
index 07a4b33..03328b2 100644
--- a/dlls/ole32/storage32.h
+++ b/dlls/ole32/storage32.h
@@ -325,6 +325,9 @@ static inline HRESULT StorageBaseImpl_StreamSetSize(StorageBaseImpl *This,
 void StorageBaseImpl_AddStream(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.
  *
@@ -367,6 +370,10 @@ struct StorageImpl
   BlockChainStream* smallBlockDepotChain;
   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
    */




More information about the wine-cvs mailing list