Skip to content

Commit

Permalink
resource: do not write to target file directly
Browse files Browse the repository at this point in the history
  • Loading branch information
dbartolini committed Aug 30, 2024
1 parent 069d2e8 commit c03f8de
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 18 deletions.
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Changelog
**Data Compiler**

* Fixed existence/redefinition checks for samplers.
* Improved data writing robustness.

**Runtime**

Expand Down
101 changes: 83 additions & 18 deletions src/resource/data_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,12 @@ static void read_data_dependencies(DataCompiler &dc, FilesystemDisk &data_fs, co
}
}

static void write_data_index(FilesystemDisk &data_fs, const char *filename, const HashMap<StringId64, DynamicString> &index)
static s32 write_data_index(FilesystemDisk &data_fs, const char *filename, const HashMap<StringId64, DynamicString> &index)
{
StringStream ss(default_allocator());
DynamicString temp_filename(default_allocator());

File *file = data_fs.open(filename, FileOpenMode::WRITE);
File *file = data_fs.open_temporary(temp_filename);
if (file->is_open()) {
auto cur = hash_map::begin(index);
auto end = hash_map::end(index);
Expand All @@ -478,16 +479,24 @@ static void write_data_index(FilesystemDisk &data_fs, const char *filename, cons
ss << "\"" << str.c_str() << "\" = \"" << cur->second.c_str() << "\"\n";
}

file->write(string_stream::c_str(ss), strlen32(string_stream::c_str(ss)));
u32 ss_len = strlen32(string_stream::c_str(ss));
if (ss_len != file->write(string_stream::c_str(ss), ss_len)) {
data_fs.close(*file);
return -1;
}
}
data_fs.close(*file);

RenameResult rr = data_fs.rename(temp_filename.c_str(), filename);
return rr.error == RenameResult::SUCCESS ? 0 : -1;
}

static void write_data_versions(FilesystemDisk &data_fs, const char *filename, const HashMap<DynamicString, u32> &versions)
static s32 write_data_versions(FilesystemDisk &data_fs, const char *filename, const HashMap<DynamicString, u32> &versions)
{
StringStream ss(default_allocator());
DynamicString temp_filename(default_allocator());

File *file = data_fs.open(filename, FileOpenMode::WRITE);
File *file = data_fs.open_temporary(temp_filename);
if (file->is_open()) {
auto cur = hash_map::begin(versions);
auto end = hash_map::end(versions);
Expand All @@ -497,16 +506,24 @@ static void write_data_versions(FilesystemDisk &data_fs, const char *filename, c
ss << cur->first.c_str() << " = " << cur->second << "\n";
}

file->write(string_stream::c_str(ss), strlen32(string_stream::c_str(ss)));
u32 ss_len = strlen32(string_stream::c_str(ss));
if (ss_len != file->write(string_stream::c_str(ss), ss_len)) {
data_fs.close(*file);
return -1;
}
}
data_fs.close(*file);

RenameResult rr = data_fs.rename(temp_filename.c_str(), filename);
return rr.error == RenameResult::SUCCESS ? 0 : -1;
}

static void write_data_mtimes(FilesystemDisk &data_fs, const char *filename, const HashMap<StringId64, u64> &mtimes)
static s32 write_data_mtimes(FilesystemDisk &data_fs, const char *filename, const HashMap<StringId64, u64> &mtimes)
{
StringStream ss(default_allocator());
DynamicString temp_filename(default_allocator());

File *file = data_fs.open(filename, FileOpenMode::WRITE);
File *file = data_fs.open_temporary(temp_filename);
if (file->is_open()) {
auto cur = hash_map::begin(mtimes);
auto end = hash_map::end(mtimes);
Expand All @@ -519,16 +536,24 @@ static void write_data_mtimes(FilesystemDisk &data_fs, const char *filename, con
ss << "\"" << key.c_str() << "\" = \"" << cur->second << "\"\n";
}

file->write(string_stream::c_str(ss), strlen32(string_stream::c_str(ss)));
u32 ss_len = strlen32(string_stream::c_str(ss));
if (ss_len != file->write(string_stream::c_str(ss), ss_len)) {
data_fs.close(*file);
return -1;
}
}
data_fs.close(*file);

RenameResult rr = data_fs.rename(temp_filename.c_str(), filename);
return rr.error == RenameResult::SUCCESS ? 0 : -1;
}

static void write_data_dependencies(FilesystemDisk &data_fs, const char *filename, const HashMap<StringId64, DynamicString> &index, const HashMap<StringId64, HashMap<DynamicString, u32>> &dependencies, const HashMap<StringId64, HashMap<DynamicString, u32>> &requirements)
static s32 write_data_dependencies(FilesystemDisk &data_fs, const char *filename, const HashMap<StringId64, DynamicString> &index, const HashMap<StringId64, HashMap<DynamicString, u32>> &dependencies, const HashMap<StringId64, HashMap<DynamicString, u32>> &requirements)
{
StringStream ss(default_allocator());
DynamicString temp_filename(default_allocator());

File *file = data_fs.open(filename, FileOpenMode::WRITE);
File *file = data_fs.open_temporary(temp_filename);
if (file->is_open()) {
auto cur = hash_map::begin(index);
auto end = hash_map::end(index);
Expand Down Expand Up @@ -570,9 +595,16 @@ static void write_data_dependencies(FilesystemDisk &data_fs, const char *filenam
ss << "]\n";
}

file->write(string_stream::c_str(ss), strlen32(string_stream::c_str(ss)));
u32 ss_len = strlen32(string_stream::c_str(ss));
if (ss_len != file->write(string_stream::c_str(ss), ss_len)) {
data_fs.close(*file);
return -1;
}
}
data_fs.close(*file);

RenameResult rr = data_fs.rename(temp_filename.c_str(), filename);
return rr.error == RenameResult::SUCCESS ? 0 : -1;
}

DataCompiler::DataCompiler(const DeviceOptions &opts, ConsoleServer &cs)
Expand Down Expand Up @@ -820,14 +852,35 @@ void DataCompiler::scan_and_restore(const char *data_dir)
void DataCompiler::save(const char *data_dir)
{
s64 time_start = time::now();
s32 res = 0;

FilesystemDisk data_fs(default_allocator());
data_fs.set_prefix(data_dir);

write_data_index(data_fs, CROWN_DATA_INDEX, _data_index);
write_data_mtimes(data_fs, CROWN_DATA_MTIMES, _data_mtimes);
write_data_dependencies(data_fs, CROWN_DATA_DEPENDENCIES, _data_index, _data_dependencies, _data_requirements);
write_data_versions(data_fs, CROWN_DATA_VERSIONS, _data_versions);
res = write_data_index(data_fs, CROWN_DATA_INDEX, _data_index);
if (res != 0) {
loge(DATA_COMPILER, "Failed to save: %s", CROWN_DATA_INDEX);
return;
}

res = write_data_mtimes(data_fs, CROWN_DATA_MTIMES, _data_mtimes);
if (res != 0) {
loge(DATA_COMPILER, "Failed to save: %s", CROWN_DATA_MTIMES);
return;
}

res = write_data_dependencies(data_fs, CROWN_DATA_DEPENDENCIES, _data_index, _data_dependencies, _data_requirements);
if (res != 0) {
loge(DATA_COMPILER, "Failed to save: %s", CROWN_DATA_DEPENDENCIES);
return;
}

res = write_data_versions(data_fs, CROWN_DATA_VERSIONS, _data_versions);
if (res != 0) {
loge(DATA_COMPILER, "Failed to save: %s", CROWN_DATA_VERSIONS);
return;
}

logi(DATA_COMPILER, "Saved state in " TIME_FMT, time::seconds(time::now() - time_start));
}

Expand Down Expand Up @@ -1089,7 +1142,8 @@ bool DataCompiler::compile(const char *data_dir, const char *platform_name)
hash_map::set(_data_requirements, id, new_requirements);

// Write data to disk.
File *outf = data_fs.open(dest.c_str(), FileOpenMode::WRITE);
DynamicString temp_dest(default_allocator());
File *outf = data_fs.open_temporary(temp_dest);
if (outf->is_open()) {
u32 size = array::size(output);
u32 written = outf->write(array::begin(output), size);
Expand All @@ -1099,6 +1153,11 @@ bool DataCompiler::compile(const char *data_dir, const char *platform_name)
success = false;
}
data_fs.close(*outf);

if (success) {
RenameResult rr = data_fs.rename(temp_dest.c_str(), dest.c_str());
success = rr.error == RenameResult::SUCCESS;
}
}

if (success) {
Expand Down Expand Up @@ -1205,7 +1264,8 @@ bool DataCompiler::compile(const char *data_dir, const char *platform_name)

if (success) {
// Write data to disk.
File *outf = bundle_fs.open(dest.c_str(), FileOpenMode::WRITE);
DynamicString temp_dest(default_allocator());
File *outf = bundle_fs.open_temporary(temp_dest);
if (outf->is_open()) {
u32 size = array::size(output);
u32 written = outf->write(array::begin(output), size);
Expand All @@ -1215,6 +1275,11 @@ bool DataCompiler::compile(const char *data_dir, const char *platform_name)
success = false;
}
bundle_fs.close(*outf);

if (success) {
RenameResult rr = data_fs.rename(temp_dest.c_str(), dest.c_str());
success = rr.error == RenameResult::SUCCESS;
}
}

if (!success) {
Expand Down

0 comments on commit c03f8de

Please sign in to comment.