ole32: Always move unmodified streams instead of copying on commit.

This commit is contained in:
Vincent Povirk 2010-05-04 17:40:55 -05:00 committed by Alexandre Julliard
parent d07a4868a1
commit e40afcb2b6
2 changed files with 106 additions and 12 deletions

View File

@ -2351,6 +2351,21 @@ static BlockChainStream **StorageImpl_GetCachedBlockChainStream(StorageImpl *Thi
return &This->blockChainCache[free_index];
}
static void StorageImpl_DeleteCachedBlockChainStream(StorageImpl *This, DirRef index)
{
int i;
for (i=0; i<BLOCKCHAIN_CACHE_SIZE; i++)
{
if (This->blockChainCache[i] && This->blockChainCache[i]->ownerDirEntry == index)
{
BlockChainStream_Destroy(This->blockChainCache[i]);
This->blockChainCache[i] = NULL;
return;
}
}
}
static HRESULT StorageImpl_StreamReadAt(StorageBaseImpl *base, DirRef index,
ULARGE_INTEGER offset, ULONG size, void *buffer, ULONG *bytesRead)
{
@ -2542,6 +2557,30 @@ static HRESULT StorageImpl_StreamWriteAt(StorageBaseImpl *base, DirRef index,
}
}
static HRESULT StorageImpl_StreamLink(StorageBaseImpl *base, DirRef dst,
DirRef src)
{
StorageImpl *This = (StorageImpl*)base;
DirEntry dst_data, src_data;
HRESULT hr;
hr = StorageImpl_ReadDirEntry(This, dst, &dst_data);
if (SUCCEEDED(hr))
hr = StorageImpl_ReadDirEntry(This, src, &src_data);
if (SUCCEEDED(hr))
{
StorageImpl_DeleteCachedBlockChainStream(This, src);
dst_data.startingBlock = src_data.startingBlock;
dst_data.size = src_data.size;
hr = StorageImpl_WriteDirEntry(This, dst, &dst_data);
}
return hr;
}
/*
* Virtual function table for the IStorage32Impl class.
*/
@ -2577,7 +2616,8 @@ static const StorageBaseImplVtbl StorageImpl_BaseVtbl =
StorageImpl_DestroyDirEntry,
StorageImpl_StreamReadAt,
StorageImpl_StreamWriteAt,
StorageImpl_StreamSetSize
StorageImpl_StreamSetSize,
StorageImpl_StreamLink
};
static HRESULT StorageImpl_Construct(
@ -4298,8 +4338,9 @@ static void TransactedSnapshotImpl_DestroyTemporaryCopy(
{
entry = &This->entries[cursor];
StorageBaseImpl_StreamSetSize(This->transactedParent,
entry->newTransactedParentEntry, zero);
if (entry->stream_dirty)
StorageBaseImpl_StreamSetSize(This->transactedParent,
entry->newTransactedParentEntry, zero);
StorageBaseImpl_DestroyDirEntry(This->transactedParent,
entry->newTransactedParentEntry);
@ -4366,9 +4407,19 @@ static HRESULT TransactedSnapshotImpl_CopyTree(TransactedSnapshotImpl* This)
return hr;
}
hr = StorageBaseImpl_CopyStream(
This->transactedParent, entry->newTransactedParentEntry,
(StorageBaseImpl*)This, cursor);
if (entry->stream_dirty)
{
hr = StorageBaseImpl_CopyStream(
This->transactedParent, entry->newTransactedParentEntry,
This->scratch, entry->stream_entry);
}
else if (entry->data.size.QuadPart)
{
hr = StorageBaseImpl_StreamLink(
This->transactedParent, entry->newTransactedParentEntry,
entry->transactedParentEntry);
}
if (FAILED(hr))
{
cursor = TransactedSnapshotImpl_FindNextChild(This, cursor);
@ -4457,12 +4508,8 @@ static HRESULT WINAPI TransactedSnapshotImpl_Commit(
else if (entry->read && entry->transactedParentEntry != entry->newTransactedParentEntry)
{
if (entry->transactedParentEntry != DIRENTRY_NULL)
{
StorageBaseImpl_StreamSetSize(This->transactedParent,
entry->transactedParentEntry, zero);
StorageBaseImpl_DestroyDirEntry(This->transactedParent,
entry->transactedParentEntry);
}
if (entry->stream_dirty)
{
StorageBaseImpl_StreamSetSize(This->scratch, entry->stream_entry, zero);
@ -4739,6 +4786,31 @@ static HRESULT TransactedSnapshotImpl_StreamSetSize(StorageBaseImpl *base,
return hr;
}
static HRESULT TransactedSnapshotImpl_StreamLink(StorageBaseImpl *base,
DirRef dst, DirRef src)
{
TransactedSnapshotImpl* This = (TransactedSnapshotImpl*) base;
HRESULT hr;
TransactedDirEntry *dst_entry, *src_entry;
hr = TransactedSnapshotImpl_EnsureReadEntry(This, src);
if (FAILED(hr)) return hr;
hr = TransactedSnapshotImpl_EnsureReadEntry(This, dst);
if (FAILED(hr)) return hr;
dst_entry = &This->entries[dst];
src_entry = &This->entries[src];
dst_entry->stream_dirty = src_entry->stream_dirty;
dst_entry->stream_entry = src_entry->stream_entry;
dst_entry->transactedParentEntry = src_entry->transactedParentEntry;
dst_entry->newTransactedParentEntry = src_entry->newTransactedParentEntry;
dst_entry->data.size = src_entry->data.size;
return S_OK;
}
static const IStorageVtbl TransactedSnapshotImpl_Vtbl =
{
StorageBaseImpl_QueryInterface,
@ -4771,7 +4843,8 @@ static const StorageBaseImplVtbl TransactedSnapshotImpl_BaseVtbl =
TransactedSnapshotImpl_DestroyDirEntry,
TransactedSnapshotImpl_StreamReadAt,
TransactedSnapshotImpl_StreamWriteAt,
TransactedSnapshotImpl_StreamSetSize
TransactedSnapshotImpl_StreamSetSize,
TransactedSnapshotImpl_StreamLink
};
static HRESULT TransactedSnapshotImpl_Construct(StorageBaseImpl *parentStorage,
@ -4974,6 +5047,15 @@ static HRESULT StorageInternalImpl_StreamSetSize(StorageBaseImpl *base,
index, newsize);
}
static HRESULT StorageInternalImpl_StreamLink(StorageBaseImpl *base,
DirRef dst, DirRef src)
{
StorageInternalImpl* This = (StorageInternalImpl*) base;
return StorageBaseImpl_StreamLink(This->parentStorage,
dst, src);
}
/******************************************************************************
**
** Storage32InternalImpl_Commit
@ -5333,7 +5415,8 @@ static const StorageBaseImplVtbl StorageInternalImpl_BaseVtbl =
StorageInternalImpl_DestroyDirEntry,
StorageInternalImpl_StreamReadAt,
StorageInternalImpl_StreamWriteAt,
StorageInternalImpl_StreamSetSize
StorageInternalImpl_StreamSetSize,
StorageInternalImpl_StreamLink
};
/******************************************************************************

View File

@ -263,6 +263,7 @@ struct StorageBaseImplVtbl {
HRESULT (*StreamReadAt)(StorageBaseImpl*,DirRef,ULARGE_INTEGER,ULONG,void*,ULONG*);
HRESULT (*StreamWriteAt)(StorageBaseImpl*,DirRef,ULARGE_INTEGER,ULONG,const void*,ULONG*);
HRESULT (*StreamSetSize)(StorageBaseImpl*,DirRef,ULARGE_INTEGER);
HRESULT (*StreamLink)(StorageBaseImpl*,DirRef,DirRef);
};
static inline void StorageBaseImpl_Destroy(StorageBaseImpl *This)
@ -320,6 +321,16 @@ static inline HRESULT StorageBaseImpl_StreamSetSize(StorageBaseImpl *This,
return This->baseVtbl->StreamSetSize(This, index, newsize);
}
/* Make dst point to the same stream that src points to. Other stream operations
* will not work properly for entries that point to the same stream, so this
* must be a very temporary state, and only one entry pointing to a given stream
* may be reachable at any given time. */
static inline HRESULT StorageBaseImpl_StreamLink(StorageBaseImpl *This,
DirRef dst, DirRef src)
{
return This->baseVtbl->StreamLink(This, dst, src);
}
/****************************************************************************
* StorageBaseImpl stream list handlers
*/