On dedicated servers, save copy of last autosave on crash
This is to avoid all autosaves being overwritten when the server is auto-restarted with a new map
This commit is contained in:
@@ -690,6 +690,32 @@ bool CrashLog::WriteScreenshot(char *filename, const char *filename_last, const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEDICATED
|
||||||
|
static bool CopyAutosave(const std::string &old_name, const std::string &new_name)
|
||||||
|
{
|
||||||
|
FILE *old_fh = FioFOpenFile(old_name, "rb", AUTOSAVE_DIR);
|
||||||
|
if (old_fh == nullptr) return false;
|
||||||
|
auto guard1 = scope_guard([=]() {
|
||||||
|
FioFCloseFile(old_fh);
|
||||||
|
});
|
||||||
|
FILE *new_fh = FioFOpenFile(new_name, "wb", AUTOSAVE_DIR);
|
||||||
|
if (new_fh == nullptr) return false;
|
||||||
|
auto guard2 = scope_guard([=]() {
|
||||||
|
FioFCloseFile(new_fh);
|
||||||
|
});
|
||||||
|
|
||||||
|
char buffer[4096 * 4];
|
||||||
|
size_t length;
|
||||||
|
do {
|
||||||
|
length = fread(buffer, 1, lengthof(buffer), old_fh);
|
||||||
|
if (fwrite(buffer, 1, length, new_fh) != length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} while (length == lengthof(buffer));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the crash log, writes it to a file and then subsequently tries
|
* Makes the crash log, writes it to a file and then subsequently tries
|
||||||
* to make a crash dump and crash savegame. It uses DEBUG to write
|
* to make a crash dump and crash savegame. It uses DEBUG to write
|
||||||
@@ -703,6 +729,27 @@ bool CrashLog::MakeCrashLog(char *buffer, const char *last)
|
|||||||
if (crashlogged) return false;
|
if (crashlogged) return false;
|
||||||
crashlogged = true;
|
crashlogged = true;
|
||||||
|
|
||||||
|
char *name_buffer_date = this->name_buffer + seprintf(this->name_buffer, lastof(this->name_buffer), "crash-");
|
||||||
|
time_t cur_time = time(nullptr);
|
||||||
|
strftime(name_buffer_date, lastof(this->name_buffer) - name_buffer_date, "%Y%m%dT%H%M%SZ", gmtime(&cur_time));
|
||||||
|
|
||||||
|
#ifdef DEDICATED
|
||||||
|
if (!_settings_client.gui.keep_all_autosave) {
|
||||||
|
extern FiosNumberedSaveName &GetAutoSaveFiosNumberedSaveName();
|
||||||
|
FiosNumberedSaveName &autosave = GetAutoSaveFiosNumberedSaveName();
|
||||||
|
int num = autosave.GetLastNumber();
|
||||||
|
if (num >= 0) {
|
||||||
|
std::string old_file = autosave.FilenameUsingNumber(num, "");
|
||||||
|
char save_suffix[MAX_PATH];
|
||||||
|
seprintf(save_suffix, lastof(save_suffix), "-(%s)", this->name_buffer);
|
||||||
|
std::string new_file = autosave.FilenameUsingNumber(num, save_suffix);
|
||||||
|
if (CopyAutosave(old_file, new_file)) {
|
||||||
|
printf("Saving copy of last autosave: %s -> %s\n\n", old_file.c_str(), new_file.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!VideoDriver::EmergencyAcquireGameLock(20, 2)) {
|
if (!VideoDriver::EmergencyAcquireGameLock(20, 2)) {
|
||||||
printf("Failed to acquire gamelock before filling crash log\n\n");
|
printf("Failed to acquire gamelock before filling crash log\n\n");
|
||||||
}
|
}
|
||||||
@@ -710,10 +757,6 @@ bool CrashLog::MakeCrashLog(char *buffer, const char *last)
|
|||||||
char filename[MAX_PATH];
|
char filename[MAX_PATH];
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
char *name_buffer_date = this->name_buffer + seprintf(this->name_buffer, lastof(this->name_buffer), "crash-");
|
|
||||||
time_t cur_time = time(nullptr);
|
|
||||||
strftime(name_buffer_date, lastof(this->name_buffer) - name_buffer_date, "%Y%m%dT%H%M%SZ", gmtime(&cur_time));
|
|
||||||
|
|
||||||
printf("Crash encountered, generating crash log...\n");
|
printf("Crash encountered, generating crash log...\n");
|
||||||
this->FillCrashLog(buffer, last);
|
this->FillCrashLog(buffer, last);
|
||||||
printf("%s\n", buffer);
|
printf("%s\n", buffer);
|
||||||
|
@@ -791,7 +791,12 @@ FiosNumberedSaveName::FiosNumberedSaveName(const std::string &prefix) : prefix(p
|
|||||||
std::string FiosNumberedSaveName::Filename()
|
std::string FiosNumberedSaveName::Filename()
|
||||||
{
|
{
|
||||||
if (++this->number >= _settings_client.gui.max_num_autosaves) this->number = 0;
|
if (++this->number >= _settings_client.gui.max_num_autosaves) this->number = 0;
|
||||||
return stdstr_fmt("%s%u.sav", this->prefix.c_str(), this->number);
|
return this->FilenameUsingNumber(this->number, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FiosNumberedSaveName::FilenameUsingNumber(int num, const char *suffix) const
|
||||||
|
{
|
||||||
|
return stdstr_fmt("%s%u%s.sav", this->prefix.c_str(), num, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -136,7 +136,9 @@ FiosType FiosGetSavegameListCallback(SaveLoadOperation fop, const std::string &f
|
|||||||
struct FiosNumberedSaveName {
|
struct FiosNumberedSaveName {
|
||||||
FiosNumberedSaveName(const std::string &prefix);
|
FiosNumberedSaveName(const std::string &prefix);
|
||||||
std::string Filename();
|
std::string Filename();
|
||||||
|
std::string FilenameUsingNumber(int num, const char *suffix) const;
|
||||||
std::string Extension();
|
std::string Extension();
|
||||||
|
int GetLastNumber() const { return this->number; }
|
||||||
private:
|
private:
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
int number;
|
int number;
|
||||||
|
@@ -1929,14 +1929,19 @@ void StateGameLoop()
|
|||||||
assert(IsLocalCompany());
|
assert(IsLocalCompany());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FiosNumberedSaveName &GetAutoSaveFiosNumberedSaveName()
|
||||||
|
{
|
||||||
|
static FiosNumberedSaveName _autosave_ctr("autosave");
|
||||||
|
return _autosave_ctr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an autosave. The default name is "autosave#.sav". However with
|
* Create an autosave. The default name is "autosave#.sav". However with
|
||||||
* the setting 'keep_all_autosave' the name defaults to company-name + date
|
* the setting 'keep_all_autosave' the name defaults to company-name + date
|
||||||
*/
|
*/
|
||||||
static void DoAutosave()
|
static void DoAutosave()
|
||||||
{
|
{
|
||||||
static FiosNumberedSaveName _autosave_ctr("autosave");
|
DoAutoOrNetsave(GetAutoSaveFiosNumberedSaveName(), true);
|
||||||
DoAutoOrNetsave(_autosave_ctr, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user