Commit 454ed9f0 authored by Thuy Nguyen's avatar Thuy Nguyen Committed by Alexandre Julliard

Improved performance.

parent 0d5fe583
......@@ -59,8 +59,10 @@ struct MappedPage
LPVOID lpBytes;
};
#define BLOCKS_PER_PAGE 128
#define PAGE_SIZE 65536
#define PAGE_SIZE 131072
#define BLOCKS_PER_PAGE 256
#define NUMBER_OF_MAPPED_PAGES 100
/***********************************************************
* Prototypes for private methods
......@@ -82,7 +84,6 @@ static void BIGBLOCKFILE_RemoveBlock(LPBIGBLOCKFILE This,
static BigBlock* BIGBLOCKFILE_AddBigBlock(LPBIGBLOCKFILE This,
ULONG index);
static BigBlock* BIGBLOCKFILE_CreateBlock(ULONG index);
static DWORD BIGBLOCKFILE_GetProtectMode(DWORD openFlags);
/******************************************************************************
......@@ -134,34 +135,19 @@ BigBlockFile * BIGBLOCKFILE_Construct(
This->filesize.LowPart = GetFileSize(This->hfile, NULL);
This->blocksize = blocksize;
/* create the read only mapped pages list
*/
This->headmap_ro = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage));
if (This->headmap_ro == NULL)
{
CloseHandle(This->hfilemap);
CloseHandle(This->hfile);
HeapFree(GetProcessHeap(), 0, This);
return NULL;
}
This->headmap_ro->next = NULL;
/* create the writeable mapped pages list
/* create the mapped pages list
*/
This->headmap_w = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage));
This->maplisthead = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage));
if (This->headmap_w == NULL)
if (This->maplisthead == NULL)
{
CloseHandle(This->hfilemap);
CloseHandle(This->hfile);
HeapFree(GetProcessHeap(), 0, This->headmap_ro);
HeapFree(GetProcessHeap(), 0, This);
return NULL;
}
This->headmap_w->next = NULL;
This->maplisthead->next = NULL;
/* initialize the block list
*/
......@@ -178,11 +164,10 @@ BigBlockFile * BIGBLOCKFILE_Construct(
void BIGBLOCKFILE_Destructor(
LPBIGBLOCKFILE This)
{
/* unmap all views and destroy the mapped page lists
/* unmap all views and destroy the mapped page list
*/
BIGBLOCKFILE_FreeAllMappedPages(This);
HeapFree(GetProcessHeap(), 0, This->headmap_ro);
HeapFree(GetProcessHeap(), 0, This->headmap_w);
HeapFree(GetProcessHeap(), 0, This->maplisthead);
/* close all open handles
*/
......@@ -262,7 +247,6 @@ void* BIGBLOCKFILE_GetBigBlock(LPBIGBLOCKFILE This, ULONG index)
* BIGBLOCKFILE_ReleaseBigBlock
*
* Releases the specified block.
*
*/
void BIGBLOCKFILE_ReleaseBigBlock(LPBIGBLOCKFILE This, void *pBlock)
{
......@@ -615,126 +599,120 @@ static void * BIGBLOCKFILE_GetMappedView(
DWORD pagenum,
DWORD desired_access)
{
MappedPage * current;
MappedPage * newMappedPage;
DWORD hioffset, lowoffset;
DWORD numBytesToMap;
/* use correct list
*/
if (desired_access == FILE_MAP_READ)
current = This->headmap_ro;
else if (desired_access == FILE_MAP_WRITE)
current = This->headmap_w;
else
return NULL;
MappedPage* current = This->maplisthead;
ULONG count = 1;
BOOL found = FALSE;
hioffset = 0;
lowoffset = PAGE_SIZE * pagenum;
assert(This->maplisthead != NULL);
while (current->next != NULL)
{
if (current->next->number == pagenum) /* page already mapped */
/*
* Search for the page in the list.
*/
while ((found == FALSE) && (current->next != NULL))
{
current->next->ref++;
return current->next->lpBytes;
}
else if (current->next->number > pagenum) /* this page is not mapped yet */
if (current->next->number == pagenum)
{
/* allocate new MappedPage
*/
newMappedPage = HeapAlloc(GetProcessHeap(), 0, sizeof(MappedPage));
if (newMappedPage == NULL)
return NULL;
found = TRUE;
/* initialize the new MappedPage
/*
* If it's not already at the head of the list
* move it there.
*/
newMappedPage->number = pagenum;
newMappedPage->ref = 1;
if (current != This->maplisthead)
{
MappedPage* temp = current->next;
newMappedPage->next = current->next;
current->next = newMappedPage;
current->next = current->next->next;
/* actually map the page
*/
if (((pagenum + 1) * PAGE_SIZE) > This->filesize.LowPart)
numBytesToMap = This->filesize.LowPart - (pagenum * PAGE_SIZE);
else
numBytesToMap = PAGE_SIZE;
temp->next = This->maplisthead->next;
This->maplisthead->next = temp;
}
}
newMappedPage->lpBytes = MapViewOfFile(This->hfilemap,
desired_access,
hioffset,
lowoffset,
numBytesToMap);
/*
* 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))
{
UnmapViewOfFile(current->next->lpBytes);
return newMappedPage->lpBytes;
HeapFree(GetProcessHeap(), 0, current->next);
current->next = NULL;
}
else
if (current->next != NULL)
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));
if (newMappedPage == NULL)
return NULL;
/* initialize the new MappedPage
*/
newMappedPage->number = pagenum;
newMappedPage->ref = 1;
newMappedPage->ref = 0;
newMappedPage->next = NULL;
current->next = newMappedPage;
newMappedPage->next = This->maplisthead->next;
This->maplisthead->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;
if (This->flProtect == PAGE_READONLY)
desired_access = FILE_MAP_READ;
else
desired_access = FILE_MAP_WRITE;
newMappedPage->lpBytes = MapViewOfFile(This->hfilemap,
desired_access,
hioffset,
lowoffset,
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]
*
* Decrements the reference count of the mapped page.
* If the page is not used anymore it will be unmapped.
*/
static void BIGBLOCKFILE_ReleaseMappedPage(
LPBIGBLOCKFILE This,
DWORD pagenum,
DWORD access)
{
MappedPage * previous;
MappedPage * current;
MappedPage* previous = This->maplisthead;
MappedPage* current;
/* use the list corresponding to the desired access mode
*/
if (access == FILE_MAP_READ)
previous = This->headmap_ro;
else if (access == FILE_MAP_WRITE)
previous = This->headmap_w;
else
return;
assert(This->maplisthead->next != NULL);
current = previous->next;
......@@ -747,17 +725,6 @@ static void BIGBLOCKFILE_ReleaseMappedPage(
/* decrement the reference count
*/
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;
}
else
......@@ -772,47 +739,25 @@ static void BIGBLOCKFILE_ReleaseMappedPage(
* BIGBLOCKFILE_FreeAllMappedPages [PRIVATE]
*
* Unmap all currently mapped pages.
* Empty both mapped pages lists.
* Empty mapped pages list.
*/
static void BIGBLOCKFILE_FreeAllMappedPages(
LPBIGBLOCKFILE This)
{
/*
* start with the read only list
*/
MappedPage * current = This->headmap_ro->next;
while (current != NULL)
{
/* unmap views
*/
UnmapViewOfFile(current->lpBytes);
/* free the nodes
*/
This->headmap_ro->next = current->next;
HeapFree(GetProcessHeap(), 0, current);
current = This->headmap_ro->next;
}
/*
* then do the write list
*/
current = This->headmap_w->next;
MappedPage * current = This->maplisthead->next;
while (current != NULL)
{
/* unmap views
/* Unmap views.
*/
UnmapViewOfFile(current->lpBytes);
/* free the nodes
/* Free the nodes.
*/
This->headmap_w->next = current->next;
This->maplisthead->next = current->next;
HeapFree(GetProcessHeap(), 0, current);
current = This->headmap_w->next;
current = This->maplisthead->next;
}
}
......
......@@ -2461,6 +2461,7 @@ void StorageImpl_SetNextBlockInChain(
void* depotBuffer;
assert(depotBlockCount < This->bigBlockDepotCount);
assert(blockIndex != nextBlock);
if (depotBlockCount < COUNT_BBDEPOTINHEADER)
{
......@@ -3740,12 +3741,28 @@ BlockChainStream* BlockChainStream_Construct(
ULONG propertyIndex)
{
BlockChainStream* newStream;
ULONG blockIndex;
newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(BlockChainStream));
newStream->parentStorage = parentStorage;
newStream->headOfStreamPlaceHolder = headOfStreamPlaceHolder;
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;
}
......@@ -3833,10 +3850,24 @@ BOOL BlockChainStream_ReadAt(BlockChainStream* This,
BYTE* bufferWalker;
BYTE* bigBlockBuffer;
if (This->lastBlockNoInSequence == 0xFFFFFFFF)
This->lastBlockNoInSequence = blockNoInSequence;
/*
* Find the first block in the stream that contains part of the buffer.
*/
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))
{
......@@ -3846,6 +3877,8 @@ BOOL BlockChainStream_ReadAt(BlockChainStream* This,
blockNoInSequence--;
}
This->lastBlockNoInSequenceIndex = blockIndex;
/*
* Start reading the buffer.
*/
......@@ -3906,10 +3939,25 @@ BOOL BlockChainStream_WriteAt(BlockChainStream* This,
BYTE* bufferWalker;
BYTE* bigBlockBuffer;
if (This->lastBlockNoInSequence == 0xFFFFFFFF)
This->lastBlockNoInSequence = blockNoInSequence;
/*
* Find the first block in the stream that contains part of the buffer.
*/
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))
{
......@@ -3919,6 +3967,8 @@ BOOL BlockChainStream_WriteAt(BlockChainStream* This,
blockNoInSequence--;
}
This->lastBlockNoInSequenceIndex = blockIndex;
/*
* Here, I'm casting away the constness on the buffer variable
* This is OK since we don't intend to modify that buffer.
......@@ -4001,6 +4051,9 @@ BOOL BlockChainStream_Shrink(BlockChainStream* This,
blockIndex,
BLOCK_END_OF_CHAIN);
This->tailIndex = blockIndex;
This->numBlocks = numBlocks;
/*
* Mark the extra blocks as free
*/
......@@ -4061,9 +4114,10 @@ BOOL BlockChainStream_Enlarge(BlockChainStream* This,
This->ownerPropertyIndex,
&chainProp);
}
}
currentBlock = blockIndex;
This->tailIndex = blockIndex;
This->numBlocks = 1;
}
/*
* 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
*/
if (This->tailIndex == BLOCK_END_OF_CHAIN)
{
currentBlock = blockIndex;
while (blockIndex != BLOCK_END_OF_CHAIN)
{
oldNumBlocks++;
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
*/
......@@ -4106,6 +4170,9 @@ BOOL BlockChainStream_Enlarge(BlockChainStream* This,
oldNumBlocks++;
}
This->tailIndex = blockIndex;
This->numBlocks = newNumBlocks;
return TRUE;
}
......
......@@ -140,8 +140,7 @@ struct BigBlockFile
HANDLE hfile;
HANDLE hfilemap;
DWORD flProtect;
MappedPage *headmap_ro;
MappedPage *headmap_w;
MappedPage *maplisthead;
BigBlock *headblock;
};
......@@ -726,6 +725,10 @@ struct BlockChainStream
StorageImpl* parentStorage;
ULONG* headOfStreamPlaceHolder;
ULONG ownerPropertyIndex;
ULONG lastBlockNoInSequence;
ULONG lastBlockNoInSequenceIndex;
ULONG tailIndex;
ULONG numBlocks;
};
/*
......
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