Common/LinearDiskCache: Replace std::fstream with File::IOFile

File::IOFile is better suited to this type of task.
Split out from a future PR.
This commit is contained in:
JosJuice
2020-11-04 20:59:34 +01:00
parent 069840fb7e
commit 28aa04312c
3 changed files with 22 additions and 45 deletions

View File

@ -6,12 +6,11 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <fstream>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/FileUtil.h" #include "Common/File.h"
#include "Common/Version.h" #include "Common/Version.h"
// On disk format: // On disk format:
@ -54,8 +53,6 @@ public:
// return number of read entries // return number of read entries
u32 OpenAndRead(const std::string& filename, LinearDiskCacheReader<K, V>& reader) u32 OpenAndRead(const std::string& filename, LinearDiskCacheReader<K, V>& reader)
{ {
using std::ios_base;
// Since we're reading/writing directly to the storage of K instances, // Since we're reading/writing directly to the storage of K instances,
// K must be trivially copyable. // K must be trivially copyable.
static_assert(std::is_trivially_copyable<K>::value, "K must be a trivially copyable type"); static_assert(std::is_trivially_copyable<K>::value, "K must be a trivially copyable type");
@ -65,16 +62,12 @@ public:
m_num_entries = 0; m_num_entries = 0;
// try opening for reading/writing // try opening for reading/writing
File::OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary); m_file.Open(filename, "r+b");
m_file.seekg(0, std::ios::end); const u64 file_size = m_file.GetSize();
std::fstream::pos_type end_pos = m_file.tellg();
m_file.seekg(0, std::ios::beg);
std::fstream::pos_type start_pos = m_file.tellg();
std::streamoff file_size = end_pos - start_pos;
m_header.Init(); m_header.Init();
if (m_file.is_open() && ValidateHeader()) if (m_file.IsOpen() && ValidateHeader())
{ {
// good header, read some key/value pairs // good header, read some key/value pairs
K key; K key;
@ -83,11 +76,9 @@ public:
u32 value_size = 0; u32 value_size = 0;
u32 entry_number = 0; u32 entry_number = 0;
std::fstream::pos_type last_pos = m_file.tellg(); while (m_file.ReadArray(&value_size, 1))
while (Read(&value_size))
{ {
std::streamoff next_extent = (last_pos - start_pos) + sizeof(value_size) + value_size; const u64 next_extent = m_file.Tell() + sizeof(value_size) + value_size;
if (next_extent > file_size) if (next_extent > file_size)
break; break;
@ -95,8 +86,8 @@ public:
value = new V[value_size]; value = new V[value_size];
// read key/value and pass to reader // read key/value and pass to reader
if (Read(&key) && Read(value, value_size) && Read(&entry_number) && if (m_file.ReadArray(&key, 1) && m_file.ReadArray(value, value_size) &&
entry_number == m_num_entries + 1) m_file.ReadArray(&entry_number, 1) && entry_number == m_num_entries + 1)
{ {
reader.Read(key, value, value_size); reader.Read(key, value, value_size);
} }
@ -106,10 +97,8 @@ public:
} }
m_num_entries++; m_num_entries++;
last_pos = m_file.tellg();
} }
m_file.seekp(last_pos); m_file.Clear();
m_file.clear();
delete[] value; delete[] value;
return m_num_entries; return m_num_entries;
@ -118,18 +107,16 @@ public:
// failed to open file for reading or bad header // failed to open file for reading or bad header
// close and recreate file // close and recreate file
Close(); Close();
File::OpenFStream(m_file, filename, ios_base::out | ios_base::trunc | ios_base::binary); m_file.Open(filename, "wb");
WriteHeader(); WriteHeader();
return 0; return 0;
} }
void Sync() { m_file.flush(); } void Sync() { m_file.Flush(); }
void Close() void Close()
{ {
if (m_file.is_open()) if (m_file.IsOpen())
m_file.close(); m_file.Close();
// clear any error flags
m_file.clear();
} }
// Appends a key-value pair to the store. // Appends a key-value pair to the store.
@ -137,35 +124,23 @@ public:
{ {
// TODO: Should do a check that we don't already have "key"? (I think each caller does that // TODO: Should do a check that we don't already have "key"? (I think each caller does that
// already.) // already.)
Write(&value_size); m_file.WriteArray(&value_size, 1);
Write(&key); m_file.WriteArray(&key, 1);
Write(value, value_size); m_file.WriteArray(value, value_size);
m_num_entries++; m_num_entries++;
Write(&m_num_entries); m_file.WriteArray(&m_num_entries, 1);
} }
private: private:
void WriteHeader() { Write(&m_header); } void WriteHeader() { m_file.WriteArray(&m_header, 1); }
bool ValidateHeader() bool ValidateHeader()
{ {
char file_header[sizeof(Header)]; char file_header[sizeof(Header)];
return (Read(file_header, sizeof(Header)) && return (m_file.ReadArray(file_header, sizeof(Header)) &&
!memcmp((const char*)&m_header, file_header, sizeof(Header))); !memcmp((const char*)&m_header, file_header, sizeof(Header)));
} }
template <typename D>
bool Write(const D* data, u32 count = 1)
{
return m_file.write(reinterpret_cast<const char*>(data), count * sizeof(D)).good();
}
template <typename D>
bool Read(D* data, u32 count = 1)
{
return m_file.read(reinterpret_cast<char*>(data), count * sizeof(D)).good();
}
struct Header struct Header
{ {
void Init() void Init()
@ -183,6 +158,6 @@ private:
} m_header; } m_header;
std::fstream m_file; File::IOFile m_file;
u32 m_num_entries; u32 m_num_entries;
}; };

View File

@ -10,6 +10,7 @@
#include "Common/Assert.h" #include "Common/Assert.h"
#include "Common/CommonFuncs.h" #include "Common/CommonFuncs.h"
#include "Common/FileUtil.h"
#include "Common/LinearDiskCache.h" #include "Common/LinearDiskCache.h"
#include "Common/MsgHandler.h" #include "Common/MsgHandler.h"

View File

@ -16,6 +16,7 @@
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Config/Config.h" #include "Common/Config/Config.h"
#include "Common/Event.h" #include "Common/Event.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
#include "Core/Config/MainSettings.h" #include "Core/Config/MainSettings.h"