Improved performance.

This commit is contained in:
Thuy Nguyen 1999-03-12 17:06:46 +00:00 committed by Alexandre Julliard
parent 0d5fe58361
commit 454ed9f0ba
3 changed files with 193 additions and 178 deletions

View File

@ -59,31 +59,32 @@ struct MappedPage
LPVOID lpBytes; LPVOID lpBytes;
}; };
#define BLOCKS_PER_PAGE 128 #define PAGE_SIZE 131072
#define PAGE_SIZE 65536 #define BLOCKS_PER_PAGE 256
#define NUMBER_OF_MAPPED_PAGES 100
/*********************************************************** /***********************************************************
* Prototypes for private methods * Prototypes for private methods
*/ */
static void* BIGBLOCKFILE_GetMappedView(LPBIGBLOCKFILE This, static void* BIGBLOCKFILE_GetMappedView(LPBIGBLOCKFILE This,
DWORD pagenum, DWORD pagenum,
DWORD desired_access); DWORD desired_access);
static void BIGBLOCKFILE_ReleaseMappedPage(LPBIGBLOCKFILE This, static void BIGBLOCKFILE_ReleaseMappedPage(LPBIGBLOCKFILE This,
DWORD pagenum, DWORD pagenum,
DWORD access); DWORD access);
static void BIGBLOCKFILE_FreeAllMappedPages(LPBIGBLOCKFILE This); static void BIGBLOCKFILE_FreeAllMappedPages(LPBIGBLOCKFILE This);
static void* BIGBLOCKFILE_GetBigBlockPointer(LPBIGBLOCKFILE This, static void* BIGBLOCKFILE_GetBigBlockPointer(LPBIGBLOCKFILE This,
ULONG index, ULONG index,
DWORD desired_access); DWORD desired_access);
static BigBlock* BIGBLOCKFILE_GetBigBlockFromPointer(LPBIGBLOCKFILE This, static BigBlock* BIGBLOCKFILE_GetBigBlockFromPointer(LPBIGBLOCKFILE This,
void* pBlock); void* pBlock);
static void BIGBLOCKFILE_RemoveBlock(LPBIGBLOCKFILE This, static void BIGBLOCKFILE_RemoveBlock(LPBIGBLOCKFILE This,
ULONG index); ULONG index);
static BigBlock* BIGBLOCKFILE_AddBigBlock(LPBIGBLOCKFILE This, static BigBlock* BIGBLOCKFILE_AddBigBlock(LPBIGBLOCKFILE This,
ULONG index); ULONG index);
static BigBlock* BIGBLOCKFILE_CreateBlock(ULONG index); static BigBlock* BIGBLOCKFILE_CreateBlock(ULONG index);
static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags);
static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags);
/****************************************************************************** /******************************************************************************
* BIGBLOCKFILE_Construct * BIGBLOCKFILE_Construct
@ -94,7 +95,7 @@ static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags);
*/ */
BigBlockFile * BIGBLOCKFILE_Construct( BigBlockFile * BIGBLOCKFILE_Construct(
HANDLE hFile, HANDLE hFile,
DWORD openFlags, DWORD openFlags,
ULONG blocksize) ULONG blocksize)
{ {
LPBIGBLOCKFILE This; LPBIGBLOCKFILE This;
@ -134,11 +135,11 @@ BigBlockFile * BIGBLOCKFILE_Construct(
This->filesize.LowPart = GetFileSize(This->hfile, NULL); This->filesize.LowPart = GetFileSize(This->hfile, NULL);
This->blocksize = blocksize; This->blocksize = blocksize;
/* create the read only mapped pages list /* create the mapped pages list
*/ */
This->headmap_ro = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage)); This->maplisthead = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage));
if (This->headmap_ro == NULL) if (This->maplisthead == NULL)
{ {
CloseHandle(This->hfilemap); CloseHandle(This->hfilemap);
CloseHandle(This->hfile); CloseHandle(This->hfile);
@ -146,22 +147,7 @@ BigBlockFile * BIGBLOCKFILE_Construct(
return NULL; return NULL;
} }
This->headmap_ro->next = NULL; This->maplisthead->next = NULL;
/* create the writeable mapped pages list
*/
This->headmap_w = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage));
if (This->headmap_w == NULL)
{
CloseHandle(This->hfilemap);
CloseHandle(This->hfile);
HeapFree(GetProcessHeap(), 0, This->headmap_ro);
HeapFree(GetProcessHeap(), 0, This);
return NULL;
}
This->headmap_w->next = NULL;
/* initialize the block list /* initialize the block list
*/ */
@ -178,11 +164,10 @@ BigBlockFile * BIGBLOCKFILE_Construct(
void BIGBLOCKFILE_Destructor( void BIGBLOCKFILE_Destructor(
LPBIGBLOCKFILE This) LPBIGBLOCKFILE This)
{ {
/* unmap all views and destroy the mapped page lists /* unmap all views and destroy the mapped page list
*/ */
BIGBLOCKFILE_FreeAllMappedPages(This); BIGBLOCKFILE_FreeAllMappedPages(This);
HeapFree(GetProcessHeap(), 0, This->headmap_ro); HeapFree(GetProcessHeap(), 0, This->maplisthead);
HeapFree(GetProcessHeap(), 0, This->headmap_w);
/* close all open handles /* close all open handles
*/ */
@ -262,7 +247,6 @@ void* BIGBLOCKFILE_GetBigBlock(LPBIGBLOCKFILE This, ULONG index)
* BIGBLOCKFILE_ReleaseBigBlock * BIGBLOCKFILE_ReleaseBigBlock
* *
* Releases the specified block. * Releases the specified block.
*
*/ */
void BIGBLOCKFILE_ReleaseBigBlock(LPBIGBLOCKFILE This, void *pBlock) void BIGBLOCKFILE_ReleaseBigBlock(LPBIGBLOCKFILE This, void *pBlock)
{ {
@ -612,129 +596,123 @@ static BigBlock* BIGBLOCKFILE_GetBigBlockFromPointer(
*/ */
static void * BIGBLOCKFILE_GetMappedView( static void * BIGBLOCKFILE_GetMappedView(
LPBIGBLOCKFILE This, LPBIGBLOCKFILE This,
DWORD pagenum, DWORD pagenum,
DWORD desired_access) DWORD desired_access)
{ {
MappedPage * current; MappedPage* current = This->maplisthead;
MappedPage * newMappedPage; ULONG count = 1;
DWORD hioffset, lowoffset; BOOL found = FALSE;
DWORD numBytesToMap;
/* use correct list assert(This->maplisthead != NULL);
/*
* Search for the page in the list.
*/ */
if (desired_access == FILE_MAP_READ) while ((found == FALSE) && (current->next != NULL))
current = This->headmap_ro;
else if (desired_access == FILE_MAP_WRITE)
current = This->headmap_w;
else
return NULL;
hioffset = 0;
lowoffset = PAGE_SIZE * pagenum;
while (current->next != NULL)
{ {
if (current->next->number == pagenum) /* page already mapped */ if (current->next->number == pagenum)
{ {
current->next->ref++; found = TRUE;
return current->next->lpBytes;
/*
* If it's not already at the head of the list
* move it there.
*/
if (current != This->maplisthead)
{
MappedPage* temp = current->next;
current->next = current->next->next;
temp->next = This->maplisthead->next;
This->maplisthead->next = temp;
}
} }
else if (current->next->number > pagenum) /* this page is not mapped yet */
/*
* The list is full and we haven't found it.
* Free the last element of the list because we'll add a new
* one at the head.
*/
if ((found == FALSE) &&
(count >= NUMBER_OF_MAPPED_PAGES) &&
(current->next != NULL))
{ {
/* allocate new MappedPage UnmapViewOfFile(current->next->lpBytes);
*/
newMappedPage = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage));
if (newMappedPage == NULL) HeapFree(GetProcessHeap(), 0, current->next);
return NULL; current->next = NULL;
/* initialize the new MappedPage
*/
newMappedPage->number = pagenum;
newMappedPage->ref = 1;
newMappedPage->next = current->next;
current->next = newMappedPage;
/* actually map the page
*/
if (((pagenum + 1) * PAGE_SIZE) > This->filesize.LowPart)
numBytesToMap = This->filesize.LowPart - (pagenum * PAGE_SIZE);
else
numBytesToMap = PAGE_SIZE;
newMappedPage->lpBytes = MapViewOfFile(This->hfilemap,
desired_access,
hioffset,
lowoffset,
numBytesToMap);
return newMappedPage->lpBytes;
} }
else
if (current->next != NULL)
current = current->next; current = current->next;
count++;
} }
/* reached end of the list, this view is not mapped yet /*
* Add the page at the head of the list.
*/ */
if (current->next == NULL) if (found == FALSE)
{ {
/* allocate new MappedPage MappedPage* newMappedPage;
*/ DWORD numBytesToMap;
DWORD hioffset = 0;
DWORD lowoffset = PAGE_SIZE * pagenum;
newMappedPage = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage)); newMappedPage = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage));
if (newMappedPage == NULL) if (newMappedPage == NULL)
return NULL; return NULL;
/* initialize the new MappedPage
*/
newMappedPage->number = pagenum; newMappedPage->number = pagenum;
newMappedPage->ref = 1; newMappedPage->ref = 0;
newMappedPage->next = NULL; newMappedPage->next = This->maplisthead->next;
current->next = newMappedPage; This->maplisthead->next = newMappedPage;
/* actually map the page
*/
if (((pagenum + 1) * PAGE_SIZE) > This->filesize.LowPart) if (((pagenum + 1) * PAGE_SIZE) > This->filesize.LowPart)
numBytesToMap = This->filesize.LowPart - (pagenum * PAGE_SIZE); numBytesToMap = This->filesize.LowPart - (pagenum * PAGE_SIZE);
else else
numBytesToMap = PAGE_SIZE; numBytesToMap = PAGE_SIZE;
if (This->flProtect == PAGE_READONLY)
desired_access = FILE_MAP_READ;
else
desired_access = FILE_MAP_WRITE;
newMappedPage->lpBytes = MapViewOfFile(This->hfilemap, newMappedPage->lpBytes = MapViewOfFile(This->hfilemap,
desired_access, desired_access,
hioffset, hioffset,
lowoffset, lowoffset,
numBytesToMap); numBytesToMap);
return newMappedPage->lpBytes;
} }
return NULL; /*
* The page we want should now be at the head of the list.
*/
assert(This->maplisthead->next != NULL);
current = This->maplisthead->next;
current->ref++;
return current->lpBytes;
} }
/****************************************************************************** /******************************************************************************
* BIGBLOCKFILE_ReleaseMappedPage [PRIVATE] * BIGBLOCKFILE_ReleaseMappedPage [PRIVATE]
* *
* Decrements the reference count of the mapped page. * Decrements the reference count of the mapped page.
* If the page is not used anymore it will be unmapped.
*/ */
static void BIGBLOCKFILE_ReleaseMappedPage( static void BIGBLOCKFILE_ReleaseMappedPage(
LPBIGBLOCKFILE This, LPBIGBLOCKFILE This,
DWORD pagenum, DWORD pagenum,
DWORD access) DWORD access)
{ {
MappedPage * previous; MappedPage* previous = This->maplisthead;
MappedPage * current; MappedPage* current;
/* use the list corresponding to the desired access mode assert(This->maplisthead->next != NULL);
*/
if (access == FILE_MAP_READ)
previous = This->headmap_ro;
else if (access == FILE_MAP_WRITE)
previous = This->headmap_w;
else
return;
current = previous->next; current = previous->next;
@ -747,17 +725,6 @@ static void BIGBLOCKFILE_ReleaseMappedPage(
/* decrement the reference count /* decrement the reference count
*/ */
current->ref--; current->ref--;
if (current->ref == 0)
{
/* this page is not used anymore, we can unmap it
*/
UnmapViewOfFile(current->lpBytes);
previous->next = current->next;
HeapFree(GetProcessHeap(), 0, current);
}
return; return;
} }
else else
@ -772,47 +739,25 @@ static void BIGBLOCKFILE_ReleaseMappedPage(
* BIGBLOCKFILE_FreeAllMappedPages [PRIVATE] * BIGBLOCKFILE_FreeAllMappedPages [PRIVATE]
* *
* Unmap all currently mapped pages. * Unmap all currently mapped pages.
* Empty both mapped pages lists. * Empty mapped pages list.
*/ */
static void BIGBLOCKFILE_FreeAllMappedPages( static void BIGBLOCKFILE_FreeAllMappedPages(
LPBIGBLOCKFILE This) LPBIGBLOCKFILE This)
{ {
/* MappedPage * current = This->maplisthead->next;
* start with the read only list
*/
MappedPage * current = This->headmap_ro->next;
while (current != NULL) while (current != NULL)
{ {
/* unmap views /* Unmap views.
*/ */
UnmapViewOfFile(current->lpBytes); UnmapViewOfFile(current->lpBytes);
/* free the nodes /* Free the nodes.
*/ */
This->headmap_ro->next = current->next; This->maplisthead->next = current->next;
HeapFree(GetProcessHeap(), 0, current); HeapFree(GetProcessHeap(), 0, current);
current = This->headmap_ro->next; current = This->maplisthead->next;
}
/*
* then do the write list
*/
current = This->headmap_w->next;
while (current != NULL)
{
/* unmap views
*/
UnmapViewOfFile(current->lpBytes);
/* free the nodes
*/
This->headmap_w->next = current->next;
HeapFree(GetProcessHeap(), 0, current);
current = This->headmap_w->next;
} }
} }

View File

@ -2461,6 +2461,7 @@ void StorageImpl_SetNextBlockInChain(
void* depotBuffer; void* depotBuffer;
assert(depotBlockCount < This->bigBlockDepotCount); assert(depotBlockCount < This->bigBlockDepotCount);
assert(blockIndex != nextBlock);
if (depotBlockCount < COUNT_BBDEPOTINHEADER) if (depotBlockCount < COUNT_BBDEPOTINHEADER)
{ {
@ -2713,7 +2714,7 @@ BOOL StorageImpl_ReadProperty(
ULARGE_INTEGER offsetInPropSet; ULARGE_INTEGER offsetInPropSet;
BOOL readSucessful; BOOL readSucessful;
ULONG bytesRead; ULONG bytesRead;
offsetInPropSet.HighPart = 0; offsetInPropSet.HighPart = 0;
offsetInPropSet.LowPart = index * PROPSET_BLOCK_SIZE; offsetInPropSet.LowPart = index * PROPSET_BLOCK_SIZE;
@ -3740,12 +3741,28 @@ BlockChainStream* BlockChainStream_Construct(
ULONG propertyIndex) ULONG propertyIndex)
{ {
BlockChainStream* newStream; BlockChainStream* newStream;
ULONG blockIndex;
newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(BlockChainStream)); newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(BlockChainStream));
newStream->parentStorage = parentStorage; newStream->parentStorage = parentStorage;
newStream->headOfStreamPlaceHolder = headOfStreamPlaceHolder; newStream->headOfStreamPlaceHolder = headOfStreamPlaceHolder;
newStream->ownerPropertyIndex = propertyIndex; newStream->ownerPropertyIndex = propertyIndex;
newStream->lastBlockNoInSequence = 0xFFFFFFFF;
newStream->tailIndex = BLOCK_END_OF_CHAIN;
newStream->numBlocks = 0;
blockIndex = BlockChainStream_GetHeadOfChain(newStream);
while (blockIndex != BLOCK_END_OF_CHAIN)
{
newStream->numBlocks++;
newStream->tailIndex = blockIndex;
blockIndex = StorageImpl_GetNextBlockInChain(
parentStorage,
blockIndex);
}
return newStream; return newStream;
} }
@ -3833,10 +3850,24 @@ BOOL BlockChainStream_ReadAt(BlockChainStream* This,
BYTE* bufferWalker; BYTE* bufferWalker;
BYTE* bigBlockBuffer; BYTE* bigBlockBuffer;
if (This->lastBlockNoInSequence == 0xFFFFFFFF)
This->lastBlockNoInSequence = blockNoInSequence;
/* /*
* Find the first block in the stream that contains part of the buffer. * Find the first block in the stream that contains part of the buffer.
*/ */
blockIndex = BlockChainStream_GetHeadOfChain(This); if (blockNoInSequence > This->lastBlockNoInSequence)
{
ULONG temp = blockNoInSequence;
blockIndex = This->lastBlockNoInSequenceIndex;
blockNoInSequence -= This->lastBlockNoInSequence;
This->lastBlockNoInSequence = temp;
}
else
{
blockIndex = BlockChainStream_GetHeadOfChain(This);
This->lastBlockNoInSequence = blockNoInSequence;
}
while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN))
{ {
@ -3846,6 +3877,8 @@ BOOL BlockChainStream_ReadAt(BlockChainStream* This,
blockNoInSequence--; blockNoInSequence--;
} }
This->lastBlockNoInSequenceIndex = blockIndex;
/* /*
* Start reading the buffer. * Start reading the buffer.
*/ */
@ -3906,11 +3939,26 @@ BOOL BlockChainStream_WriteAt(BlockChainStream* This,
BYTE* bufferWalker; BYTE* bufferWalker;
BYTE* bigBlockBuffer; BYTE* bigBlockBuffer;
if (This->lastBlockNoInSequence == 0xFFFFFFFF)
This->lastBlockNoInSequence = blockNoInSequence;
/* /*
* Find the first block in the stream that contains part of the buffer. * Find the first block in the stream that contains part of the buffer.
*/ */
blockIndex = BlockChainStream_GetHeadOfChain(This); if (blockNoInSequence > This->lastBlockNoInSequence)
{
ULONG temp = blockNoInSequence;
blockIndex = This->lastBlockNoInSequenceIndex;
blockNoInSequence -= This->lastBlockNoInSequence;
This->lastBlockNoInSequence = temp;
}
else
{
blockIndex = BlockChainStream_GetHeadOfChain(This);
This->lastBlockNoInSequence = blockNoInSequence;
}
while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN))
{ {
blockIndex = blockIndex =
@ -3919,6 +3967,8 @@ BOOL BlockChainStream_WriteAt(BlockChainStream* This,
blockNoInSequence--; blockNoInSequence--;
} }
This->lastBlockNoInSequenceIndex = blockIndex;
/* /*
* Here, I'm casting away the constness on the buffer variable * Here, I'm casting away the constness on the buffer variable
* This is OK since we don't intend to modify that buffer. * This is OK since we don't intend to modify that buffer.
@ -4001,6 +4051,9 @@ BOOL BlockChainStream_Shrink(BlockChainStream* This,
blockIndex, blockIndex,
BLOCK_END_OF_CHAIN); BLOCK_END_OF_CHAIN);
This->tailIndex = blockIndex;
This->numBlocks = numBlocks;
/* /*
* Mark the extra blocks as free * Mark the extra blocks as free
*/ */
@ -4046,24 +4099,25 @@ BOOL BlockChainStream_Enlarge(BlockChainStream* This,
} }
else else
{ {
StgProperty chainProp; StgProperty chainProp;
assert(This->ownerPropertyIndex != PROPERTY_NULL); assert(This->ownerPropertyIndex != PROPERTY_NULL);
StorageImpl_ReadProperty( StorageImpl_ReadProperty(
This->parentStorage, This->parentStorage,
This->ownerPropertyIndex, This->ownerPropertyIndex,
&chainProp); &chainProp);
chainProp.startingBlock = blockIndex; chainProp.startingBlock = blockIndex;
StorageImpl_WriteProperty( StorageImpl_WriteProperty(
This->parentStorage, This->parentStorage,
This->ownerPropertyIndex, This->ownerPropertyIndex,
&chainProp); &chainProp);
} }
}
currentBlock = blockIndex; This->tailIndex = blockIndex;
This->numBlocks = 1;
}
/* /*
* Figure out how many blocks are needed to contain this stream * Figure out how many blocks are needed to contain this stream
@ -4076,15 +4130,25 @@ BOOL BlockChainStream_Enlarge(BlockChainStream* This,
/* /*
* Go to the current end of chain * Go to the current end of chain
*/ */
while (blockIndex != BLOCK_END_OF_CHAIN) if (This->tailIndex == BLOCK_END_OF_CHAIN)
{ {
oldNumBlocks++;
currentBlock = blockIndex; currentBlock = blockIndex;
blockIndex = while (blockIndex != BLOCK_END_OF_CHAIN)
StorageImpl_GetNextBlockInChain(This->parentStorage, currentBlock); {
This->numBlocks++;
currentBlock = blockIndex;
blockIndex =
StorageImpl_GetNextBlockInChain(This->parentStorage, currentBlock);
}
This->tailIndex = currentBlock;
} }
currentBlock = This->tailIndex;
oldNumBlocks = This->numBlocks;
/* /*
* Add new blocks to the chain * Add new blocks to the chain
*/ */
@ -4106,6 +4170,9 @@ BOOL BlockChainStream_Enlarge(BlockChainStream* This,
oldNumBlocks++; oldNumBlocks++;
} }
This->tailIndex = blockIndex;
This->numBlocks = newNumBlocks;
return TRUE; return TRUE;
} }

View File

@ -140,8 +140,7 @@ struct BigBlockFile
HANDLE hfile; HANDLE hfile;
HANDLE hfilemap; HANDLE hfilemap;
DWORD flProtect; DWORD flProtect;
MappedPage *headmap_ro; MappedPage *maplisthead;
MappedPage *headmap_w;
BigBlock *headblock; BigBlock *headblock;
}; };
@ -724,8 +723,12 @@ void StorageUtl_CopyPropertyToSTATSTG(STATSTG* destination,
struct BlockChainStream struct BlockChainStream
{ {
StorageImpl* parentStorage; StorageImpl* parentStorage;
ULONG* headOfStreamPlaceHolder; ULONG* headOfStreamPlaceHolder;
ULONG ownerPropertyIndex; ULONG ownerPropertyIndex;
ULONG lastBlockNoInSequence;
ULONG lastBlockNoInSequenceIndex;
ULONG tailIndex;
ULONG numBlocks;
}; };
/* /*