Refactor autosave rotation.

In order to remove boost:filesystem from CResourceManager Move()
function has to be removed or rewrited. Since Move is only used in
autosave rotation it's simpler to change autosave rotation and remove
Move().

Now oldest autosaves (with lowest timestamp) will be removed in rotation.
master
Krzysztof Dermont 2016-05-15 19:42:27 +02:00
parent 2168b57cac
commit 32629a2f2a
5 changed files with 22 additions and 98 deletions

View File

@ -31,11 +31,8 @@
#include <physfs.h> #include <physfs.h>
#include <boost/filesystem.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
namespace fs = boost::filesystem;
CResourceManager::CResourceManager(const char *argv0) CResourceManager::CResourceManager(const char *argv0)
{ {
@ -231,32 +228,6 @@ long long CResourceManager::GetLastModificationTime(const std::string& filename)
return -1; return -1;
} }
//TODO: Don't use boost::filesystem. Why doesn't PHYSFS have this?
bool CResourceManager::Move(const std::string& from, const std::string& to)
{
if (PHYSFS_isInit())
{
bool success = true;
std::string writeDir = PHYSFS_getWriteDir();
try
{
std::string path_from = writeDir + "/" + CleanPath(from);
std::string path_to = writeDir + "/" + CleanPath(to);
#if PLATFORM_WINDOWS
fs::rename(CSystemUtilsWindows::UTF8_Decode(path_from), CSystemUtilsWindows::UTF8_Decode(path_to));
#else
fs::rename(path_from, path_to);
#endif
}
catch (std::exception&)
{
success = false;
}
return success;
}
return false;
}
bool CResourceManager::Remove(const std::string& filename) bool CResourceManager::Remove(const std::string& filename)
{ {
if (PHYSFS_isInit()) if (PHYSFS_isInit())

View File

@ -66,8 +66,6 @@ public:
//! Returns last modification date as timestamp //! Returns last modification date as timestamp
static long long GetLastModificationTime(const std::string &filename); static long long GetLastModificationTime(const std::string &filename);
//! Move file/directory
static bool Move(const std::string &from, const std::string &to);
//! Remove file //! Remove file
static bool Remove(const std::string& filename); static bool Remove(const std::string& filename);
}; };

View File

@ -105,6 +105,7 @@
#include "ui/screen/screen_loading.h" #include "ui/screen/screen_loading.h"
#include <algorithm>
#include <iomanip> #include <iomanip>
#include <stdexcept> #include <stdexcept>
#include <ctime> #include <ctime>
@ -5456,7 +5457,7 @@ void CRobotMain::SetAutosave(bool enable)
m_autosave = enable; m_autosave = enable;
m_autosaveLast = m_gameTimeAbsolute; m_autosaveLast = m_gameTimeAbsolute;
AutosaveRotate(false); AutosaveRotate();
} }
bool CRobotMain::GetAutosave() bool CRobotMain::GetAutosave()
@ -5482,7 +5483,7 @@ void CRobotMain::SetAutosaveSlots(int slots)
if (m_autosaveSlots == slots) return; if (m_autosaveSlots == slots) return;
m_autosaveSlots = slots; m_autosaveSlots = slots;
AutosaveRotate(false); AutosaveRotate();
} }
int CRobotMain::GetAutosaveSlots() int CRobotMain::GetAutosaveSlots()
@ -5490,85 +5491,39 @@ int CRobotMain::GetAutosaveSlots()
return m_autosaveSlots; return m_autosaveSlots;
} }
int CRobotMain::AutosaveRotate(bool freeOne) // Remove oldest saves with autosave prefix
void CRobotMain::AutosaveRotate()
{ {
if (m_playerProfile == nullptr) if (m_playerProfile == nullptr)
return 0; return;
GetLogger()->Debug("Rotate autosaves...\n"); GetLogger()->Debug("Rotate autosaves...\n");
// Find autosave dirs
auto saveDirs = CResourceManager::ListDirectories(m_playerProfile->GetSaveDir()); auto saveDirs = CResourceManager::ListDirectories(m_playerProfile->GetSaveDir());
std::map<int, std::string> autosaveDirs;
for (auto& dir : saveDirs)
{
try
{
const std::string autosavePrefix = "autosave"; const std::string autosavePrefix = "autosave";
if (dir.substr(0, autosavePrefix.length()) == autosavePrefix) std::vector<std::string> autosaves;
{ std::copy_if(saveDirs.begin(), saveDirs.end(), std::back_inserter(autosaves), [&](const std::string &save) {
int id = boost::lexical_cast<int>(dir.substr(autosavePrefix.length())); return save.substr(0, autosavePrefix.length()) == autosavePrefix;
autosaveDirs[id] = m_playerProfile->GetSaveFile(dir); });
}
}
catch (...)
{
GetLogger()->Info("Bad autosave found: %s\n", dir.c_str());
// skip
}
}
if (autosaveDirs.size() == 0) return 1;
// Remove all but last m_autosaveSlots std::sort(autosaves.begin(), autosaves.end(), std::less<std::string>());
std::map<int, std::string> autosavesToKeep; for (int i = 0; i < static_cast<int>(autosaves.size()) - m_autosaveSlots + 1; i++)
int last_id = autosaveDirs.rbegin()->first;
int count = 0;
int to_keep = m_autosaveSlots-(freeOne ? 1 : 0);
int new_last_id = Math::Min(autosaveDirs.size(), to_keep);
bool rotate = false;
for (int i = last_id; i > 0; i--)
{ {
if (autosaveDirs.count(i) > 0) CResourceManager::RemoveDirectory(m_playerProfile->GetSaveDir() + "/" + autosaves[i]);
{
count++;
if (count > m_autosaveSlots-(freeOne ? 1 : 0) || !m_autosave)
{
GetLogger()->Trace("Remove %s\n", autosaveDirs[i].c_str());
CResourceManager::RemoveDirectory(autosaveDirs[i]);
rotate = true;
} }
else
{
GetLogger()->Trace("Keep %s\n", autosaveDirs[i].c_str());
autosavesToKeep[new_last_id-count+1] = autosaveDirs[i];
}
}
}
// Rename autosaves that we kept
if (rotate)
{
for (auto& save : autosavesToKeep)
{
std::string newDir = m_playerProfile->GetSaveFile("autosave" + boost::lexical_cast<std::string>(save.first));
GetLogger()->Trace("Rename %s -> %s\n", save.second.c_str(), newDir.c_str());
CResourceManager::Move(save.second, newDir);
}
}
return rotate ? count : count+1;
} }
void CRobotMain::Autosave() void CRobotMain::Autosave()
{ {
int id = AutosaveRotate(true); AutosaveRotate();
GetLogger()->Info("Autosave!\n"); GetLogger()->Info("Autosave!\n");
std::string dir = m_playerProfile->GetSaveFile("autosave" + boost::lexical_cast<std::string>(id));
char timestr[100]; char timestr[100];
char infostr[100];
time_t now = time(nullptr); time_t now = time(nullptr);
strftime(timestr, 99, "%x %X", localtime(&now)); strftime(timestr, 99, "%y%m%d%H%M%S", localtime(&now));
std::string info = std::string("[AUTOSAVE] ")+timestr; strftime(infostr, 99, "%y.%m.%d %H:%M", localtime(&now));
std::string info = std::string("[AUTOSAVE] ") + infostr;
std::string dir = m_playerProfile->GetSaveFile(std::string("autosave") + timestr);
m_playerProfile->SaveScene(dir, info); m_playerProfile->SaveScene(dir, info);
} }

View File

@ -402,7 +402,7 @@ protected:
void ExecuteCmd(const std::string& cmd); void ExecuteCmd(const std::string& cmd);
void UpdateSpeedLabel(); void UpdateSpeedLabel();
int AutosaveRotate(bool freeOne); void AutosaveRotate();
void Autosave(); void Autosave();
bool DestroySelectedObject(); bool DestroySelectedObject();
void PushToSelectionHistory(CObject* obj); void PushToSelectionHistory(CObject* obj);

View File

@ -80,7 +80,7 @@ void CScreenIO::IOReadName()
} }
time(&now); time(&now);
strftime(line, 99, "%y%m%d%H%M", localtime(&now)); strftime(line, 99, "%y.%m.%d %H:%M", localtime(&now));
sprintf(name, "%s - %s %d", line, resume.c_str(), m_main->GetLevelRank()); sprintf(name, "%s - %s %d", line, resume.c_str(), m_main->GetLevelRank());
pe->SetText(name); pe->SetText(name);