FileMonitor redesign

Advantages:

* Simpler code in general
* No extra volume objects created
* Now actually notices if the disc or partition gets
  changed while the core is running
* No longer picks up on disc access done by the GUI
  (it used to do so as long as the core was running)
* Gets rid of a Core dependency in DiscIO

There are two performance disadvantages:

* FileMonitor is now a bit slower when used with VolumeDirectory
  because FileMonitor now always uses the FileSystemGCWii code
  for finding filenames instead of VolumeDirectory finding the
  filename on its own and directly hooking into FileMonitor.
  But this isn't such a big deal, because it's happening on the
  DVD thread, and my currently unmerged file system PR will make
  FileSystemGCWii's file finding code about as fast as
  VolumeDirectory's.
* FileMonitor's creation of the file system object is now
  done on the CPU thread instead of the DVD thread, and
  it will be done even if FileMonitor logging is disabled.
  This will be fixed in the next commit.
This commit is contained in:
JosJuice 2017-02-12 13:02:57 +01:00
parent 8035270aa8
commit b470fa5454
17 changed files with 153 additions and 191 deletions

View File

@ -8,6 +8,7 @@ set(SRCS
CoreTiming.cpp
DSPEmulator.cpp
ec_wii.cpp
FileMonitor.cpp
GeckoCodeConfig.cpp
GeckoCode.cpp
HotkeyManager.cpp

View File

@ -64,9 +64,9 @@
#include "Core/PowerPC/GDBStub.h"
#endif
#include "DiscIO/FileMonitor.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "InputCommon/GCAdapter.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/RenderBase.h"
@ -619,8 +619,6 @@ void EmuThread()
if (core_parameter.bCPUThread)
g_video_backend->Video_Cleanup();
FileMon::Close();
// We must set up this flag before executing HW::Shutdown()
s_hardware_initialized = false;
INFO_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down HW").c_str());

View File

@ -89,6 +89,7 @@
<ClCompile Include="FifoPlayer\FifoPlayer.cpp" />
<ClCompile Include="FifoPlayer\FifoRecordAnalyzer.cpp" />
<ClCompile Include="FifoPlayer\FifoRecorder.cpp" />
<ClCompile Include="FileMonitor.cpp" />
<ClCompile Include="GeckoCode.cpp" />
<ClCompile Include="GeckoCodeConfig.cpp" />
<ClCompile Include="HLE\HLE.cpp" />
@ -332,6 +333,7 @@
<ClInclude Include="FifoPlayer\FifoPlayer.h" />
<ClInclude Include="FifoPlayer\FifoRecordAnalyzer.h" />
<ClInclude Include="FifoPlayer\FifoRecorder.h" />
<ClInclude Include="FileMonitor.h" />
<ClInclude Include="GeckoCode.h" />
<ClInclude Include="GeckoCodeConfig.h" />
<ClInclude Include="HLE\HLE.h" />

View File

@ -281,6 +281,9 @@
<ClCompile Include="FifoPlayer\FifoRecorder.cpp">
<Filter>FifoPlayer</Filter>
</ClCompile>
<ClCompile Include="FileMonitor.cpp">
<Filter>FileMonitor</Filter>
</ClCompile>
<ClCompile Include="GeckoCode.cpp">
<Filter>GeckoCode</Filter>
</ClCompile>
@ -939,6 +942,9 @@
<ClInclude Include="FifoPlayer\FifoRecorder.h">
<Filter>FifoPlayer</Filter>
</ClInclude>
<ClInclude Include="FileMonitor.h">
<Filter>FileMonitor</Filter>
</ClInclud
<ClInclude Include="GeckoCode.h">
<Filter>GeckoCode</Filter>
</ClInclude>

View File

@ -0,0 +1,100 @@
// Copyright 2009 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/FileMonitor.h"
#include <algorithm>
#include <cctype>
#include <memory>
#include <string>
#include <unordered_set>
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/Logging/LogManager.h"
#include "Common/StringUtil.h"
#include "DiscIO/Enums.h"
#include "DiscIO/Filesystem.h"
#include "DiscIO/Volume.h"
namespace FileMonitor
{
static bool s_wii_disc;
static std::unique_ptr<DiscIO::IFileSystem> s_filesystem;
static std::string s_previous_file;
// Filtered files
static bool IsSoundFile(const std::string& filename)
{
std::string extension;
SplitPath(filename, nullptr, nullptr, &extension);
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
static const std::unordered_set<std::string> extensions = {
".adp", // 1080 Avalanche, Crash Bandicoot, etc.
".adx", // Sonic Adventure 2 Battle, etc.
".afc", // Zelda WW
".ast", // Zelda TP, Mario Kart
".brstm", // Wii Sports, Wario Land, etc.
".dsp", // Metroid Prime
".hps", // SSB Melee
".ogg", // Tony Hawk's Underground 2
".sad", // Disaster
".snd", // Tales of Symphonia
".song", // Tales of Symphonia
".ssm", // Custom Robo, Kirby Air Ride, etc.
".str", // Harry Potter & the Sorcerer's Stone
};
return extensions.find(extension) != extensions.end();
}
void SetFileSystem(const DiscIO::IVolume* volume)
{
s_wii_disc = volume->GetVolumeType() == DiscIO::Platform::WII_DISC;
s_filesystem = DiscIO::CreateFileSystem(volume);
s_previous_file.clear();
}
// Logs access to files in the file system set by SetFileSystem
void Log(u64 offset, bool decrypt)
{
// Do nothing if the log isn't selected
if (!LogManager::GetInstance()->IsEnabled(LogTypes::FILEMON, LogTypes::LWARNING))
return;
// For Wii discs, FileSystemGCWii will only load file systems from encrypted partitions
if (decrypt != s_wii_disc)
return;
// Do nothing if there is no valid file system
if (!s_filesystem)
return;
const std::string filename = s_filesystem->GetFileName(offset);
// Do nothing if no file was found at that offset
if (filename.empty())
return;
// Do nothing if we found the same file again
if (s_previous_file == filename)
return;
const u64 size = s_filesystem->GetFileSize(filename);
const std::string size_string = ThousandSeparate(size / 1000, 7);
const std::string log_string =
StringFromFormat("%s kB %s", size_string.c_str(), filename.c_str());
if (IsSoundFile(filename))
INFO_LOG(FILEMON, "%s", log_string.c_str());
else
WARN_LOG(FILEMON, "%s", log_string.c_str());
// Update the last accessed file
s_previous_file = filename;
}
} // namespace FileMonitor

View File

@ -0,0 +1,24 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "Common/CommonTypes.h"
namespace DiscIO
{
class IFileSystem;
class IVolume;
}
namespace FileMonitor
{
// Can be called with nullptr to set the file system to nothing. When not called
// with nullptr, the volume must remain valid until the next SetFileSystem call.
void SetFileSystem(const DiscIO::IVolume* volume);
// Logs access to files in the file system set by SetFileSystem
void Log(u64 offset, bool decrypt);
}

View File

@ -17,6 +17,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/FileMonitor.h"
#include "Core/HW/AudioInterface.h"
#include "Core/HW/DVDInterface.h"
#include "Core/HW/DVDThread.h"
@ -321,9 +322,14 @@ void DoState(PointerWrap& p)
if (disc_inside != IsDiscInside())
{
if (disc_inside)
{
PanicAlertT("An inserted disc was expected but not found.");
}
else
{
s_inserted_volume.reset();
FileMonitor::SetFileSystem(nullptr);
}
}
}
@ -474,6 +480,7 @@ void Shutdown()
{
DVDThread::Stop();
s_inserted_volume.reset();
FileMonitor::SetFileSystem(nullptr);
}
const DiscIO::IVolume& GetVolume()
@ -486,6 +493,7 @@ bool SetVolumeName(const std::string& disc_path)
{
DVDThread::WaitUntilIdle();
s_inserted_volume = DiscIO::CreateVolumeFromFilename(disc_path);
FileMonitor::SetFileSystem(s_inserted_volume.get());
SetLidOpen();
return IsDiscInside();
}
@ -496,6 +504,7 @@ bool SetVolumeDirectory(const std::string& full_path, bool is_wii,
DVDThread::WaitUntilIdle();
s_inserted_volume =
DiscIO::CreateVolumeFromDirectory(full_path, is_wii, apploader_path, DOL_path);
FileMonitor::SetFileSystem(s_inserted_volume.get());
SetLidOpen();
return IsDiscInside();
}
@ -513,6 +522,7 @@ static void EjectDiscCallback(u64 userdata, s64 cyclesLate)
{
DVDThread::WaitUntilIdle();
s_inserted_volume.reset();
FileMonitor::SetFileSystem(s_inserted_volume.get());
SetLidOpen();
}
@ -568,7 +578,9 @@ void SetLidOpen()
bool ChangePartition(u64 offset)
{
DVDThread::WaitUntilIdle();
return s_inserted_volume->ChangePartition(offset);
const bool success = s_inserted_volume->ChangePartition(offset);
FileMonitor::SetFileSystem(s_inserted_volume.get());
return success;
}
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)

View File

@ -21,6 +21,7 @@
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/FileMonitor.h"
#include "Core/HW/DVDInterface.h"
#include "Core/HW/DVDThread.h"
#include "Core/HW/Memmap.h"
@ -277,6 +278,8 @@ static void DVDThread()
ReadRequest request;
while (s_request_queue.Pop(request))
{
FileMonitor::Log(request.dvd_offset, request.decrypt);
std::vector<u8> buffer(request.length);
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
if (!volume.Read(request.dvd_offset, request.length, buffer.data(), request.decrypt))

View File

@ -7,7 +7,6 @@ set(SRCS
DriveBlob.cpp
Enums.cpp
FileBlob.cpp
FileMonitor.cpp
FileSystemGCWii.cpp
Filesystem.cpp
NANDContentLoader.cpp

View File

@ -42,7 +42,6 @@
<ClCompile Include="DriveBlob.cpp" />
<ClCompile Include="Enums.cpp" />
<ClCompile Include="FileBlob.cpp" />
<ClCompile Include="FileMonitor.cpp" />
<ClCompile Include="Filesystem.cpp" />
<ClCompile Include="FileSystemGCWii.cpp" />
<ClCompile Include="NANDContentLoader.cpp" />
@ -64,7 +63,6 @@
<ClInclude Include="DriveBlob.h" />
<ClInclude Include="Enums.h" />
<ClInclude Include="FileBlob.h" />
<ClInclude Include="FileMonitor.h" />
<ClInclude Include="Filesystem.h" />
<ClInclude Include="FileSystemGCWii.h" />
<ClInclude Include="NANDContentLoader.h" />

View File

@ -51,9 +51,6 @@
<ClCompile Include="WbfsBlob.cpp">
<Filter>Volume\Blob</Filter>
</ClCompile>
<ClCompile Include="FileMonitor.cpp">
<Filter>Volume</Filter>
</ClCompile>
<ClCompile Include="VolumeCreator.cpp">
<Filter>Volume</Filter>
</ClCompile>
@ -113,9 +110,6 @@
<ClInclude Include="WbfsBlob.h">
<Filter>Volume\Blob</Filter>
</ClInclude>
<ClInclude Include="FileMonitor.h">
<Filter>Volume</Filter>
</ClInclude>
<ClInclude Include="Volume.h">
<Filter>Volume</Filter>
</ClInclude>

View File

@ -1,151 +0,0 @@
// Copyright 2009 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <algorithm>
#include <cctype>
#include <cstring>
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/Logging/LogManager.h"
#include "Common/StringUtil.h"
#include "Core/Boot/Boot.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "DiscIO/Enums.h"
#include "DiscIO/FileMonitor.h"
#include "DiscIO/Filesystem.h"
#include "DiscIO/Volume.h"
#include "DiscIO/VolumeCreator.h"
namespace FileMon
{
static std::unique_ptr<DiscIO::IVolume> s_open_iso;
static std::unique_ptr<DiscIO::IFileSystem> s_filesystem;
static std::string ISOFile = "", CurrentFile = "";
static bool FileAccess = true;
// Filtered files
bool IsSoundFile(const std::string& filename)
{
std::string extension;
SplitPath(filename, nullptr, nullptr, &extension);
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
static std::unordered_set<std::string> extensions = {
".adp", // 1080 Avalanche, Crash Bandicoot, etc.
".adx", // Sonic Adventure 2 Battle, etc.
".afc", // Zelda WW
".ast", // Zelda TP, Mario Kart
".brstm", // Wii Sports, Wario Land, etc.
".dsp", // Metroid Prime
".hps", // SSB Melee
".ogg", // Tony Hawk's Underground 2
".sad", // Disaster
".snd", // Tales of Symphonia
".song", // Tales of Symphonia
".ssm", // Custom Robo, Kirby Air Ride, etc.
".str", // Harry Potter & the Sorcerer's Stone
};
return extensions.find(extension) != extensions.end();
}
// Read the file system
void ReadFileSystem(const std::string& filename)
{
// Should have an actual Shutdown procedure or something
s_open_iso.reset();
s_filesystem.reset();
s_open_iso = DiscIO::CreateVolumeFromFilename(filename);
if (!s_open_iso)
return;
if (s_open_iso->GetVolumeType() != DiscIO::Platform::WII_WAD)
{
s_filesystem = DiscIO::CreateFileSystem(s_open_iso.get());
if (!s_filesystem)
return;
}
FileAccess = true;
}
// Logs a file if it passes a few checks
void CheckFile(const std::string& file, u64 size)
{
// Don't do anything if the log is unselected
if (!LogManager::GetInstance()->IsEnabled(LogTypes::FILEMON, LogTypes::LWARNING))
return;
// Do nothing if we found the same file again
if (CurrentFile == file)
return;
if (size > 0)
size = (size / 1000);
std::string str = StringFromFormat("%s kB %s", ThousandSeparate(size, 7).c_str(), file.c_str());
if (IsSoundFile(file))
{
INFO_LOG(FILEMON, "%s", str.c_str());
}
else
{
WARN_LOG(FILEMON, "%s", str.c_str());
}
// Update the current file
CurrentFile = file;
}
// Find the filename
void FindFilename(u64 offset)
{
// Don't do anything if a game is not running
if (Core::GetState() != Core::State::Running)
return;
// Or if the log is unselected
if (!LogManager::GetInstance()->IsEnabled(LogTypes::FILEMON, LogTypes::LWARNING))
return;
// Or if we don't have file access
if (!FileAccess)
return;
if (!s_filesystem || ISOFile != SConfig::GetInstance().m_LastFilename)
{
FileAccess = false;
ReadFileSystem(SConfig::GetInstance().m_LastFilename);
ISOFile = SConfig::GetInstance().m_LastFilename;
INFO_LOG(FILEMON, "Opening '%s'", ISOFile.c_str());
return;
}
const std::string filename = s_filesystem->GetFileName(offset);
if (filename.empty())
return;
CheckFile(filename, s_filesystem->GetFileSize(filename));
}
void Close()
{
s_open_iso.reset();
s_filesystem.reset();
ISOFile = "";
CurrentFile = "";
FileAccess = true;
}
} // FileMon

View File

@ -1,18 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <string>
#include "Common/CommonTypes.h"
namespace FileMon
{
bool IsSoundFile(const std::string& filename);
void ReadFileSystem(const std::string& file);
void CheckFile(const std::string& file, u64 size);
void FindFilename(u64 offset);
void Close();
}

View File

@ -18,6 +18,9 @@ IFileSystem::~IFileSystem()
std::unique_ptr<IFileSystem> CreateFileSystem(const IVolume* volume)
{
if (!volume)
return nullptr;
std::unique_ptr<IFileSystem> filesystem = std::make_unique<CFileSystemGCWii>(volume);
if (!filesystem)

View File

@ -19,7 +19,6 @@
#include "Common/Logging/Log.h"
#include "DiscIO/Blob.h"
#include "DiscIO/Enums.h"
#include "DiscIO/FileMonitor.h"
#include "DiscIO/Volume.h"
#include "DiscIO/VolumeDirectory.h"
@ -130,8 +129,6 @@ bool CVolumeDirectory::Read(u64 offset, u64 length, u8* buffer, bool decrypt) co
u64 fileSize = file.GetSize();
FileMon::CheckFile(fileName, fileSize);
if (fileOffset < fileSize)
{
u64 fileBytes = std::min(fileSize - fileOffset, length);

View File

@ -17,7 +17,6 @@
#include "Common/StringUtil.h"
#include "DiscIO/Blob.h"
#include "DiscIO/Enums.h"
#include "DiscIO/FileMonitor.h"
#include "DiscIO/Filesystem.h"
#include "DiscIO/Volume.h"
#include "DiscIO/VolumeGC.h"
@ -38,8 +37,6 @@ bool CVolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const
if (decrypt)
PanicAlertT("Tried to decrypt data from a non-Wii volume");
FileMon::FindFilename(_Offset);
return m_pReader->Read(_Offset, _Length, _pBuffer);
}

View File

@ -22,7 +22,6 @@
#include "DiscIO/Blob.h"
#include "DiscIO/Enums.h"
#include "DiscIO/FileMonitor.h"
#include "DiscIO/Filesystem.h"
#include "DiscIO/Volume.h"
#include "DiscIO/VolumeCreator.h"
@ -59,8 +58,6 @@ bool CVolumeWiiCrypted::Read(u64 _ReadOffset, u64 _Length, u8* _pBuffer, bool de
if (!decrypt)
return m_pReader->Read(_ReadOffset, _Length, _pBuffer);
FileMon::FindFilename(_ReadOffset);
std::vector<u8> read_buffer(BLOCK_TOTAL_SIZE);
while (_Length > 0)
{