mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 14:25:52 +00:00
- Add shared->Exclusive promotion support to value cache routines as well.
- Implement CmpCompareNewValueDataAgainstKCBCache as an optimization during Set Value Key operations, so that if the value is already identical, it will not be written again. svn path=/trunk/; revision=31280
This commit is contained in:
parent
140729513a
commit
db48b40873
2 changed files with 173 additions and 11 deletions
|
@ -296,7 +296,11 @@ DoAgain:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Search for the value */
|
/* Search for the value */
|
||||||
SearchResult = SearchFail;
|
SearchResult = CmpCompareNewValueDataAgainstKCBCache(Kcb,
|
||||||
|
ValueName,
|
||||||
|
Type,
|
||||||
|
Data,
|
||||||
|
DataLength);
|
||||||
if (SearchResult == SearchNeedExclusiveLock)
|
if (SearchResult == SearchNeedExclusiveLock)
|
||||||
{
|
{
|
||||||
/* Try again with the exclusive lock */
|
/* Try again with the exclusive lock */
|
||||||
|
|
|
@ -55,12 +55,10 @@ CmpGetValueListFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||||
*ValueListToRelease = HCELL_NIL;
|
*ValueListToRelease = HCELL_NIL;
|
||||||
*IndexIsCached = FALSE;
|
*IndexIsCached = FALSE;
|
||||||
|
|
||||||
/* Get the hive */
|
/* Get the hive and value ceche */
|
||||||
Hive = Kcb->KeyHive;
|
Hive = Kcb->KeyHive;
|
||||||
|
ChildList = &Kcb->ValueCache;
|
||||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
|
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
|
||||||
|
|
||||||
/* Get the child value cache */
|
|
||||||
//ChildList = &Kcb->ValueCache;
|
|
||||||
ChildList = (PCACHED_CHILD_LIST)&KeyNode->ValueList;
|
ChildList = (PCACHED_CHILD_LIST)&KeyNode->ValueList;
|
||||||
|
|
||||||
/* Check if the value is cached */
|
/* Check if the value is cached */
|
||||||
|
@ -73,10 +71,20 @@ CmpGetValueListFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Make sure the KCB is locked exclusive */
|
||||||
|
if (!(CmpIsKcbLockedExclusive(Kcb)) &&
|
||||||
|
!(CmpTryToConvertKcbSharedToExclusive(Kcb)))
|
||||||
|
{
|
||||||
|
/* We need the exclusive lock */
|
||||||
|
return SearchNeedExclusiveLock;
|
||||||
|
}
|
||||||
|
|
||||||
/* Select the value list as our cell, and get the actual list array */
|
/* Select the value list as our cell, and get the actual list array */
|
||||||
CellToRelease = ChildList->ValueList;
|
CellToRelease = ChildList->ValueList;
|
||||||
*CellData = (PCELL_DATA)HvGetCell(Hive, CellToRelease);
|
*CellData = (PCELL_DATA)HvGetCell(Hive, CellToRelease);
|
||||||
if (!(*CellData)) return SearchFail;
|
if (!(*CellData)) return SearchFail;
|
||||||
|
|
||||||
|
/* FIXME: Here we would cache the value */
|
||||||
|
|
||||||
/* Return the cell to be released */
|
/* Return the cell to be released */
|
||||||
*ValueListToRelease = CellToRelease;
|
*ValueListToRelease = CellToRelease;
|
||||||
|
@ -210,12 +218,10 @@ CmpFindValueByNameFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||||
*CellToRelease = HCELL_NIL;
|
*CellToRelease = HCELL_NIL;
|
||||||
*Value = NULL;
|
*Value = NULL;
|
||||||
|
|
||||||
/* Get the hive */
|
/* Get the hive and child list */
|
||||||
Hive = Kcb->KeyHive;
|
Hive = Kcb->KeyHive;
|
||||||
|
ChildList = &Kcb->ValueCache;
|
||||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
|
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
|
||||||
|
|
||||||
/* Get the child value cache */
|
|
||||||
//ChildList = &Kcb->ValueCache;
|
|
||||||
ChildList = (PCACHED_CHILD_LIST)&KeyNode->ValueList;
|
ChildList = (PCACHED_CHILD_LIST)&KeyNode->ValueList;
|
||||||
|
|
||||||
/* Check if the child list has any entries */
|
/* Check if the child list has any entries */
|
||||||
|
@ -226,7 +232,13 @@ CmpFindValueByNameFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||||
&CellData,
|
&CellData,
|
||||||
&IndexIsCached,
|
&IndexIsCached,
|
||||||
&Cell);
|
&Cell);
|
||||||
if (SearchResult != SearchSuccess) return SearchResult;
|
if (SearchResult != SearchSuccess)
|
||||||
|
{
|
||||||
|
/* We either failed or need the exclusive lock */
|
||||||
|
ASSERT((SearchResult == SearchFail) || !(CmpIsKcbLockedExclusive(Kcb)));
|
||||||
|
ASSERT(Cell == HCELL_NIL);
|
||||||
|
return SearchResult;
|
||||||
|
}
|
||||||
|
|
||||||
/* The index shouldn't be cached right now */
|
/* The index shouldn't be cached right now */
|
||||||
if (IndexIsCached) ASSERT_VALUE_CACHE();
|
if (IndexIsCached) ASSERT_VALUE_CACHE();
|
||||||
|
@ -251,7 +263,13 @@ CmpFindValueByNameFromCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||||
IndexIsCached,
|
IndexIsCached,
|
||||||
ValueIsCached,
|
ValueIsCached,
|
||||||
CellToRelease);
|
CellToRelease);
|
||||||
if (SearchResult != SearchSuccess) return SearchResult;
|
if (SearchResult != SearchSuccess)
|
||||||
|
{
|
||||||
|
/* We either failed or need the exclusive lock */
|
||||||
|
ASSERT((SearchResult == SearchFail) || !(CmpIsKcbLockedExclusive(Kcb)));
|
||||||
|
ASSERT(Cell == HCELL_NIL);
|
||||||
|
return SearchResult;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if the both the index and the value are cached */
|
/* Check if the both the index and the value are cached */
|
||||||
if ((IndexIsCached) && (*ValueIsCached))
|
if ((IndexIsCached) && (*ValueIsCached))
|
||||||
|
@ -647,3 +665,143 @@ CmpQueryKeyValueData(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||||
/* Return the search result as well */
|
/* Return the search result as well */
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE_SEARCH_RETURN_TYPE
|
||||||
|
NTAPI
|
||||||
|
CmpCompareNewValueDataAgainstKCBCache(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
||||||
|
IN PUNICODE_STRING ValueName,
|
||||||
|
IN ULONG Type,
|
||||||
|
IN PVOID Data,
|
||||||
|
IN ULONG DataSize)
|
||||||
|
{
|
||||||
|
VALUE_SEARCH_RETURN_TYPE SearchResult;
|
||||||
|
PCM_KEY_NODE KeyNode;
|
||||||
|
PCM_CACHED_VALUE *CachedValue;
|
||||||
|
ULONG Index;
|
||||||
|
PCM_KEY_VALUE Value;
|
||||||
|
BOOLEAN ValueCached, BufferAllocated = FALSE;
|
||||||
|
PVOID Buffer;
|
||||||
|
HCELL_INDEX ValueCellToRelease = HCELL_NIL, CellToRelease = HCELL_NIL;
|
||||||
|
BOOLEAN IsSmall;
|
||||||
|
ULONG CompareResult;
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/* Check if this is a symlink */
|
||||||
|
if (Kcb->Flags & KEY_SYM_LINK)
|
||||||
|
{
|
||||||
|
/* We need the exclusive lock */
|
||||||
|
if (!(CmpIsKcbLockedExclusive(Kcb)) &&
|
||||||
|
!(CmpTryToConvertKcbSharedToExclusive(Kcb)))
|
||||||
|
{
|
||||||
|
/* We need the exclusive lock */
|
||||||
|
return SearchNeedExclusiveLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, get the key node */
|
||||||
|
KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
|
||||||
|
if (!KeyNode) return SearchFail;
|
||||||
|
|
||||||
|
/* Cleanup the KCB cache */
|
||||||
|
CmpCleanUpKcbValueCache(Kcb);
|
||||||
|
|
||||||
|
/* Sanity checks */
|
||||||
|
ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)));
|
||||||
|
ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND));
|
||||||
|
|
||||||
|
/* Set the value cache */
|
||||||
|
Kcb->ValueCache.Count = KeyNode->ValueList.Count;
|
||||||
|
Kcb->ValueCache.ValueList = KeyNode->ValueList.List;
|
||||||
|
|
||||||
|
/* Release the cell */
|
||||||
|
HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the search */
|
||||||
|
SearchResult = CmpFindValueByNameFromCache(Kcb,
|
||||||
|
ValueName,
|
||||||
|
&CachedValue,
|
||||||
|
&Index,
|
||||||
|
&Value,
|
||||||
|
&ValueCached,
|
||||||
|
&ValueCellToRelease);
|
||||||
|
if (SearchResult == SearchNeedExclusiveLock)
|
||||||
|
{
|
||||||
|
/* We need the exclusive lock */
|
||||||
|
ASSERT(!CmpIsKcbLockedExclusive(Kcb));
|
||||||
|
ASSERT(ValueCellToRelease == HCELL_NIL);
|
||||||
|
ASSERT(Value == NULL);
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
else if (SearchResult == SearchSuccess)
|
||||||
|
{
|
||||||
|
/* Sanity check */
|
||||||
|
ASSERT(Value);
|
||||||
|
|
||||||
|
/* First of all, check if the key size and type matches */
|
||||||
|
if ((Type == Value->Type) &&
|
||||||
|
(DataSize == (Value->DataLength & ~CM_KEY_VALUE_SPECIAL_SIZE)))
|
||||||
|
{
|
||||||
|
/* Check if this is a small key */
|
||||||
|
IsSmall = (DataSize <= CM_KEY_VALUE_SMALL) ? TRUE: FALSE;
|
||||||
|
if (IsSmall)
|
||||||
|
{
|
||||||
|
/* Compare against the data directly */
|
||||||
|
Buffer = &Value->Data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Do a search */
|
||||||
|
SearchResult = CmpGetValueDataFromCache(Kcb,
|
||||||
|
CachedValue,
|
||||||
|
(PCELL_DATA)Value,
|
||||||
|
ValueCached,
|
||||||
|
&Buffer,
|
||||||
|
&BufferAllocated,
|
||||||
|
&CellToRelease);
|
||||||
|
if (SearchResult != SearchSuccess)
|
||||||
|
{
|
||||||
|
/* Sanity checks */
|
||||||
|
ASSERT(Buffer == NULL);
|
||||||
|
ASSERT(BufferAllocated == FALSE);
|
||||||
|
goto Quickie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now check the data size */
|
||||||
|
if (DataSize)
|
||||||
|
{
|
||||||
|
/* Do the compare */
|
||||||
|
CompareResult = RtlCompareMemory(Buffer,
|
||||||
|
Data,
|
||||||
|
DataSize &
|
||||||
|
~CM_KEY_VALUE_SPECIAL_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It's equal */
|
||||||
|
CompareResult = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now check if the compare wasn't equal */
|
||||||
|
if (CompareResult != DataSize) SearchResult = SearchFail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The length or type isn't equal */
|
||||||
|
SearchResult = SearchFail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Quickie:
|
||||||
|
/* Release the value cell */
|
||||||
|
if (ValueCellToRelease) HvReleaseCell(Kcb->KeyHive, ValueCellToRelease);
|
||||||
|
|
||||||
|
/* Free the buffer */
|
||||||
|
if (BufferAllocated) ExFreePool(Buffer);
|
||||||
|
|
||||||
|
/* Free the cell */
|
||||||
|
if (CellToRelease) HvReleaseCell(Kcb->KeyHive, CellToRelease);
|
||||||
|
|
||||||
|
/* Return the search result */
|
||||||
|
return SearchResult;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue