Improved performance.
This commit is contained in:
parent
0d5fe58361
commit
454ed9f0ba
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
109
ole/storage32.c
109
ole/storage32.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user