[VFS/STFS] Cache any hash-blocks we read from in memory
This commit is contained in:
parent
6ba9b032a3
commit
99b7848a34
|
@ -624,55 +624,67 @@ size_t StfsContainerDevice::BlockToHashBlockOffsetSTFS(
|
||||||
|
|
||||||
const StfsHashEntry* StfsContainerDevice::GetBlockHash(const uint8_t* map_ptr,
|
const StfsHashEntry* StfsContainerDevice::GetBlockHash(const uint8_t* map_ptr,
|
||||||
uint32_t block_index) {
|
uint32_t block_index) {
|
||||||
|
auto& volume_descriptor = header_.metadata.stfs_volume_descriptor;
|
||||||
|
|
||||||
// Offset for selecting the secondary hash block, in packages that have them
|
// Offset for selecting the secondary hash block, in packages that have them
|
||||||
uint32_t secondary_table_offset =
|
uint32_t secondary_table_offset =
|
||||||
header_.metadata.stfs_volume_descriptor.flags.root_active_index
|
volume_descriptor.flags.root_active_index ? kSectorSize : 0;
|
||||||
? kSectorSize
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
|
auto hash_offset_lv0 = BlockToHashBlockOffsetSTFS(block_index, 0);
|
||||||
|
if (!cached_hash_tables_.count(hash_offset_lv0)) {
|
||||||
// If this is read_only_format then it doesn't contain secondary blocks, no
|
// If this is read_only_format then it doesn't contain secondary blocks, no
|
||||||
// need to check upper hash levels
|
// need to check upper hash levels
|
||||||
if (header_.metadata.stfs_volume_descriptor.flags.read_only_format) {
|
if (volume_descriptor.flags.read_only_format) {
|
||||||
secondary_table_offset = 0;
|
secondary_table_offset = 0;
|
||||||
} else {
|
} else {
|
||||||
// Not a read-only package, need to check each levels active index flag to
|
// Not a read-only package, need to check each levels active index flag to
|
||||||
// see if we need to use secondary block or not
|
// see if we need to use secondary block or not
|
||||||
|
|
||||||
// Check L2 active index flag...
|
// Check level1 table if package has it
|
||||||
if (header_.metadata.stfs_volume_descriptor.allocated_block_count >
|
if (volume_descriptor.allocated_block_count > kBlocksPerHashLevel[0]) {
|
||||||
|
auto hash_offset_lv1 = BlockToHashBlockOffsetSTFS(block_index, 1);
|
||||||
|
|
||||||
|
if (!cached_hash_tables_.count(hash_offset_lv1)) {
|
||||||
|
// Check level2 table if package has it
|
||||||
|
if (volume_descriptor.allocated_block_count >
|
||||||
kBlocksPerHashLevel[1]) {
|
kBlocksPerHashLevel[1]) {
|
||||||
auto hash_offset = BlockToHashBlockOffsetSTFS(block_index, 2);
|
auto hash_offset_lv2 = BlockToHashBlockOffsetSTFS(block_index, 2);
|
||||||
auto hash_table = map_ptr + hash_offset + secondary_table_offset;
|
|
||||||
|
if (!cached_hash_tables_.count(hash_offset_lv2)) {
|
||||||
|
cached_hash_tables_[hash_offset_lv2] =
|
||||||
|
*reinterpret_cast<const StfsHashTable*>(
|
||||||
|
map_ptr + hash_offset_lv2 + secondary_table_offset);
|
||||||
|
}
|
||||||
|
|
||||||
auto record =
|
auto record =
|
||||||
(block_index / kBlocksPerHashLevel[1]) % kBlocksPerHashLevel[0];
|
(block_index / kBlocksPerHashLevel[1]) % kBlocksPerHashLevel[0];
|
||||||
auto record_data =
|
auto record_data =
|
||||||
reinterpret_cast<const StfsHashEntry*>(hash_table + record * 0x18);
|
&cached_hash_tables_[hash_offset_lv2].entries[record];
|
||||||
secondary_table_offset =
|
secondary_table_offset =
|
||||||
record_data->levelN_activeindex() ? kSectorSize : 0;
|
record_data->levelN_activeindex() ? kSectorSize : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check L1 active index flag...
|
cached_hash_tables_[hash_offset_lv1] =
|
||||||
if (header_.metadata.stfs_volume_descriptor.allocated_block_count >
|
*reinterpret_cast<const StfsHashTable*>(
|
||||||
kBlocksPerHashLevel[0]) {
|
map_ptr + hash_offset_lv1 + secondary_table_offset);
|
||||||
auto hash_offset = BlockToHashBlockOffsetSTFS(block_index, 1);
|
}
|
||||||
auto hash_table = map_ptr + hash_offset + secondary_table_offset;
|
|
||||||
|
|
||||||
auto record =
|
auto record =
|
||||||
(block_index / kBlocksPerHashLevel[0]) % kBlocksPerHashLevel[0];
|
(block_index / kBlocksPerHashLevel[0]) % kBlocksPerHashLevel[0];
|
||||||
auto record_data =
|
auto record_data =
|
||||||
reinterpret_cast<const StfsHashEntry*>(hash_table + record * 0x18);
|
&cached_hash_tables_[hash_offset_lv1].entries[record];
|
||||||
secondary_table_offset =
|
secondary_table_offset =
|
||||||
record_data->levelN_activeindex() ? kSectorSize : 0;
|
record_data->levelN_activeindex() ? kSectorSize : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hash_offset = BlockToHashBlockOffsetSTFS(block_index, 0);
|
cached_hash_tables_[hash_offset_lv0] =
|
||||||
auto hash_table = map_ptr + hash_offset + secondary_table_offset;
|
*reinterpret_cast<const StfsHashTable*>(map_ptr + hash_offset_lv0 +
|
||||||
|
secondary_table_offset);
|
||||||
|
}
|
||||||
|
|
||||||
auto record = block_index % kBlocksPerHashLevel[0];
|
auto record = block_index % kBlocksPerHashLevel[0];
|
||||||
auto record_data =
|
auto record_data = &cached_hash_tables_[hash_offset_lv0].entries[record];
|
||||||
reinterpret_cast<const StfsHashEntry*>(hash_table + record * 0x18);
|
|
||||||
|
|
||||||
return record_data;
|
return record_data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,6 +135,13 @@ struct StfsHashEntry {
|
||||||
};
|
};
|
||||||
static_assert_size(StfsHashEntry, 0x18);
|
static_assert_size(StfsHashEntry, 0x18);
|
||||||
|
|
||||||
|
struct StfsHashTable {
|
||||||
|
StfsHashEntry entries[170];
|
||||||
|
xe::be<uint32_t> num_blocks; // num L0 blocks covered by this table?
|
||||||
|
uint8_t padding[12];
|
||||||
|
};
|
||||||
|
static_assert_size(StfsHashTable, 0x1000);
|
||||||
|
|
||||||
/* SVOD structures */
|
/* SVOD structures */
|
||||||
struct SvodDeviceDescriptor {
|
struct SvodDeviceDescriptor {
|
||||||
uint8_t descriptor_length;
|
uint8_t descriptor_length;
|
||||||
|
@ -483,6 +490,8 @@ class StfsContainerDevice : public Device {
|
||||||
SvodLayoutType svod_layout_;
|
SvodLayoutType svod_layout_;
|
||||||
uint32_t blocks_per_hash_table_;
|
uint32_t blocks_per_hash_table_;
|
||||||
uint32_t block_step[2];
|
uint32_t block_step[2];
|
||||||
|
|
||||||
|
std::unordered_map<size_t, StfsHashTable> cached_hash_tables_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace vfs
|
} // namespace vfs
|
||||||
|
|
Loading…
Reference in New Issue