1
0
forked from 0ad/0ad

vfs_mount: bugfix: choose newer version of a file if present in loose dir and archive

vfs_optimizer: add enable/disable logic for trace
vfs_tree: add code to determine most recent file

This was SVN commit r3562.
This commit is contained in:
janwas 2006-02-25 19:26:00 +00:00
parent 2aebdd1894
commit 78a5202e49
5 changed files with 68 additions and 22 deletions

View File

@ -94,16 +94,25 @@ char mount_get_type(const Mount* m)
}
bool mount_should_replace(const Mount* m_old, const Mount* m_new, bool files_are_identical)
bool mount_should_replace(const Mount* m_old, const Mount* m_new,
size_t size_old, size_t size_new, time_t mtime_old, time_t mtime_new)
{
// need to "replace" if not yet associated with a Mount
// 1) "replace" if not yet associated with a Mount.
if(!m_old)
return true;
// keep old if new priority is lower.
// 2) keep old if new priority is lower.
if(m_new->pri < m_old->pri)
return false;
// assume they're the same if size and last-modified time match.
// note: FAT timestamp only has 2 second resolution
const double mtime_diff = difftime(mtime_old, mtime_new);
const bool identical = (size_old == size_new) &&
fabs(mtime_diff) <= 2.0;
// 3) go with more efficient source (if files are identical)
//
// since priority is not less, we really ought to always go with m_new.
// however, there is one special case we handle for performance reasons:
// if the file contents are the same, prefer the more efficient source.
@ -111,7 +120,12 @@ bool mount_should_replace(const Mount* m_old, const Mount* m_new, bool files_are
// especially if set incorrectly.
//
// note: see MountType for explanation of type > type2.
if(files_are_identical && m_old->type > m_new->type)
if(identical && m_old->type > m_new->type)
return false;
// 4) don't replace "old" file if modified more recently than "new".
// (still provide for 2 sec. FAT tolerance - see above)
if(mtime_diff > 2.0)
return false;
return true;

View File

@ -97,8 +97,8 @@ extern LibError x_unmap(XFile* xf);
// accessor routines that obviate the need to access Mount fields directly:
//
extern bool mount_should_replace(const Mount* m_old, const Mount* m_new,
bool files_are_identical);
bool mount_should_replace(const Mount* m_old, const Mount* m_new,
size_t size_old, size_t size_new, time_t mtime_old, time_t mtime_new);
extern char mount_get_type(const Mount* m);

View File

@ -23,11 +23,23 @@ void trace_shutdown()
}
static bool trace_enabled;
// enabled by default. by the time we can decide whether a trace needs to
// be generated (see should_rebuild_main_archive), file accesses will
// already have occurred; hence default enabled and disable if not needed.
static bool trace_enabled = true;
static bool trace_force_enabled = false; // see below
// note: explicitly enabling trace means the user wants one to be
// generated even if an up-to-date version exists.
// (mechanism: ignore any attempts to disable)
void trace_enable(bool want_enabled)
{
trace_enabled = want_enabled;
if(want_enabled)
trace_force_enabled = true;
if(trace_force_enabled)
trace_enabled = true;
}
@ -76,6 +88,9 @@ void trace_clear()
LibError trace_write_to_file(const char* trace_filename)
{
if(!trace_enabled)
return INFO_SKIPPED;
char N_fn[PATH_MAX];
RETURN_ERR(file_make_full_native_path(trace_filename, N_fn));
FILE* f = fopen(N_fn, "wt");
@ -584,8 +599,6 @@ static void EntCb(const char* path, const DirEnt* ent, void* context)
params->files.push_back(file_make_unique_fn_copy(path));
}
LibError vfs_opt_rebuild_main_archive(const char* P_archive_path, const char* trace_filename)
{
// get list of all files
@ -613,7 +626,6 @@ LibError vfs_opt_rebuild_main_archive(const char* P_archive_path, const char* tr
#endif
return ret;
}
@ -621,11 +633,21 @@ LibError vfs_opt_rebuild_main_archive(const char* P_archive_path, const char* tr
// autobuild logic: decides when to (re)build an archive.
//
static const size_t REBUILD_MAIN_ARCHIVE_THRESHOLD = 100;
static const size_t BUILD_MINI_ARCHIVE_THRESHOLD = 30;
static const size_t REBUILD_MAIN_ARCHIVE_THRESHOLD = 50;
static const size_t BUILD_MINI_ARCHIVE_THRESHOLD = 20;
static bool should_rebuild_main_archive()
static bool should_rebuild_main_archive(const char* P_archive_path,
const char* trace_filename)
{
// if there's no trace file, no point in building a main archive.
struct stat s;
if(file_stat(trace_filename, &s) != ERR_OK)
return false;
// otherwise, if trace is up-to-date, stop recording a new one.
const time_t vfs_mtime = tree_most_recent_mtime();
if(s.st_mtime >= vfs_mtime)
trace_enable(false);
if(loose_files.size() >= REBUILD_MAIN_ARCHIVE_THRESHOLD)
return true;
@ -650,11 +672,9 @@ LibError vfs_opt_auto_build_archive(const char* P_dst_path,
const char* main_archive_name, const char* trace_filename)
{
char P_archive_path[PATH_MAX];
if(should_rebuild_main_archive())
{
RETURN_ERR(vfs_path_append(P_archive_path, P_dst_path, main_archive_name));
RETURN_ERR(vfs_path_append(P_archive_path, P_dst_path, main_archive_name));
if(should_rebuild_main_archive(P_archive_path, trace_filename))
return vfs_opt_rebuild_main_archive(P_archive_path, trace_filename);
}
else if(should_build_mini_archive())
{
loose_files.push_back(0);

View File

@ -32,6 +32,18 @@
static void* node_alloc();
// remembers which VFS file is the most recently modified.
static time_t most_recent_mtime;
static void set_most_recent_if_newer(time_t mtime)
{
most_recent_mtime = MAX(most_recent_mtime, mtime);
}
time_t tree_most_recent_mtime()
{
return most_recent_mtime;
}
//-----------------------------------------------------------------------------
// locking
// these are exported to protect the vfs_mount list; apart from that, it is
@ -459,12 +471,8 @@ LibError tree_add_file(TDir* td, const char* name,
RETURN_ERR(ret);
if(ret == INFO_ALREADY_PRESENT)
{
// assume they're the same if size and last-modified time match.
// note: FAT timestamp only has 2 second resolution
TFile* tf = (TFile*)node;
const bool is_same = (tf->size == size) &&
fabs(difftime(tf->mtime, mtime)) <= 2.0;
if(!mount_should_replace(tf->m, m, is_same))
if(!mount_should_replace(tf->m, m, tf->size, size, tf->mtime, mtime))
return INFO_ALREADY_PRESENT;
stats_vfs_file_remove(tf->size);
@ -476,6 +484,8 @@ LibError tree_add_file(TDir* td, const char* name,
tf->size = size;
tf->memento = memento;
stats_vfs_file_add(size);
set_most_recent_if_newer(mtime);
return ERR_OK;
}

View File

@ -36,6 +36,8 @@ extern void tree_display();
// rebuilding VFS and on exit.
extern void tree_clear();
extern time_t tree_most_recent_mtime();
// attempt to add <fn> to <dir>, storing its attributes.
// overrides previously existing files of the same name if the new one
// is more important, determined via priority and file location.