v1.18: address bad pp.dep caches?

This commit is contained in:
David Rose 2004-10-25 20:47:38 +00:00
parent f68ab23323
commit cfe15fb80b
5 changed files with 176 additions and 56 deletions

View File

@ -86,5 +86,5 @@
** Also be sure to change the version number **
** at the beginning of configure.in. **
**************** ****************/
#define VERSION "1.17"
#define VERSION "1.18"
/**************** UPDATE VERSION NUMBER HERE ****************/

View File

@ -5,7 +5,7 @@ dnl **************** UPDATE VERSION NUMBER HERE ****************
dnl ** Also be sure to change the version number **
dnl ** at the end of config_msvc.h. **
dnl **************** ****************
AM_INIT_AUTOMAKE(ppremake, 1.17)
AM_INIT_AUTOMAKE(ppremake, 1.18)
dnl **************** UPDATE VERSION NUMBER HERE ****************
AM_CONFIG_HEADER(config.h)

View File

@ -60,8 +60,11 @@ PPDependableFile(PPDirectory *directory, const string &filename) :
// cached modification time against the file's actual
// modification time, and storing the cached
// dependencies if they match.
//
// The return value is true if the cache is valid, false
// if something appears to be wrong.
////////////////////////////////////////////////////////////////////
void PPDependableFile::
bool PPDependableFile::
update_from_cache(const vector<string> &words) {
// Shouldn't call this once the file has actually been read.
assert((_flags & F_updated) == 0);
@ -69,6 +72,11 @@ update_from_cache(const vector<string> &words) {
assert((_flags & F_from_cache) == 0);
assert(words.size() >= 2);
if (!exists()) {
// The file doesn't even exist; clearly the cache is bad.
_flags |= F_bad_cache;
} else {
// The second parameter is the cached modification time.
time_t mtime = strtol(words[1].c_str(), (char **)NULL, 10);
if (mtime == get_mtime()) {
@ -109,6 +117,20 @@ update_from_cache(const vector<string> &words) {
}
}
return ((_flags & F_bad_cache) == 0);
}
////////////////////////////////////////////////////////////////////
// Function: PPDependableFile::clear_cache
// Access: Public
// Description: Forgets the cache we just read.
////////////////////////////////////////////////////////////////////
void PPDependableFile::
clear_cache() {
_dependencies.clear();
_flags &= ~(F_bad_cache | F_from_cache);
}
////////////////////////////////////////////////////////////////////
// Function: PPDependableFile::write_cache
// Access: Public
@ -317,6 +339,17 @@ was_examined() const {
return ((_flags & F_updated) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: PPDependableFile::was_cached
// Access: Public
// Description: Returns true if this file was found in the cache,
// false otherwise.
////////////////////////////////////////////////////////////////////
bool PPDependableFile::
was_cached() const {
return ((_flags & F_from_cache) != 0);
}
////////////////////////////////////////////////////////////////////
// Function: PPDependableFile::update_dependencies
// Access: Private
@ -375,6 +408,7 @@ compute_dependencies(string &circularity) {
} else {
cerr << "Warning: dependent file " << filename
<< " does not exist.\n";
_flags |= F_bad_cache;
}
} else {
@ -427,6 +461,12 @@ compute_dependencies(string &circularity) {
// with an "okcircular" comment.
if (!(*di)._okcircular) {
circ = (*di)._file->compute_dependencies(circularity);
if (((*di)._file->_flags & F_bad_cache) != 0) {
// If our dependent file had a broken cache, our own cache is
// suspect.
_flags |= F_bad_cache;
}
if (circ != (PPDependableFile *)NULL) {
// Oops, a circularity. Silly user.
circularity = get_dirpath() + " => " + circularity;
@ -441,6 +481,19 @@ compute_dependencies(string &circularity) {
_flags = (_flags & ~F_updating) | F_updated;
sort(_dependencies.begin(), _dependencies.end());
if ((_flags & (F_bad_cache | F_from_cache)) == (F_bad_cache | F_from_cache)) {
// Our cache is suspect. Re-read the file to flush the cache.
if (verbose || true) {
cerr << "Dependency cache for \"" << get_fullpath() << "\" is suspect.\n";
}
clear_cache();
_flags &= ~F_updated;
return compute_dependencies(circularity);
}
return circ;
}

View File

@ -29,7 +29,8 @@ class PPDirectory;
class PPDependableFile {
public:
PPDependableFile(PPDirectory *directory, const string &filename);
void update_from_cache(const vector<string> &words);
bool update_from_cache(const vector<string> &words);
void clear_cache();
void write_cache(ostream &out);
PPDirectory *get_directory() const;
@ -51,6 +52,7 @@ public:
string get_circularity();
bool was_examined() const;
bool was_cached() const;
private:
void update_dependencies();
@ -67,6 +69,7 @@ private:
F_statted = 0x008,
F_exists = 0x010,
F_from_cache = 0x020,
F_bad_cache = 0x040,
};
int _flags;
string _circularity;

View File

@ -23,6 +23,8 @@
#include <sys/types.h>
#endif
#include <sys/stat.h>
#include <algorithm>
#include <assert.h>
@ -31,6 +33,9 @@
#include <windows.h>
#endif
// How new must a pp.dep cache file be before we will believe it?
static const int max_cache_minutes = 60;
PPDirectory *current_output_directory = (PPDirectory *)NULL;
// An STL object to sort directories in order by dependency and then
@ -715,16 +720,52 @@ read_file_dependencies(const string &cache_filename) {
cache_pathname.set_text();
ifstream in;
if (!cache_pathname.open_read(in)) {
// Can't read it. Maybe it's not there. No problem.
if (verbose) {
cerr << "Couldn't read \"" << cache_pathname << "\"\n";
// Does the cache file exist, and is it recent enough? We don't
// trust old cache files on principle.
string os_specific = cache_pathname.to_os_specific();
time_t now = time(NULL);
#ifdef WIN32_VC
struct _stat this_buf;
bool this_exists = false;
if (_stat(os_specific.c_str(), &this_buf) == 0) {
this_exists = true;
}
#else // WIN32_VC
struct stat this_buf;
bool this_exists = false;
if (stat(os_specific.c_str(), &this_buf) == 0) {
this_exists = true;
}
#endif
if (!this_exists) {
// The cache file doesn't exist. That's OK.
if (verbose) {
cerr << "No cache file: \"" << cache_pathname << "\"\n";
}
} else if (this_buf.st_mtime < now - 60 * max_cache_minutes) {
// It exists, but it's too old.
if (verbose) {
cerr << "Cache file too old: \"" << cache_pathname << "\"\n";
}
} else {
// It exists and is new enough; use it.
if (!cache_pathname.open_read(in)) {
cerr << "Couldn't read \"" << cache_pathname << "\"\n";
} else {
if (verbose) {
cerr << "Loading cache \"" << cache_pathname << "\"\n";
}
bool okcache = true;
string line;
getline(in, line);
while (!in.fail() && !in.eof()) {
@ -732,10 +773,34 @@ read_file_dependencies(const string &cache_filename) {
tokenize_whitespace(line, words);
if (words.size() >= 2) {
PPDependableFile *file = get_dependable_file(words[0], false);
file->update_from_cache(words);
if (!file->update_from_cache(words)) {
// Hey, we asked for an invalid or absent file. Phooey.
// Invalidate the cache, and also make sure that this
// particular file (which maybe doesn't even exist) isn't
// mentioned in the cache file any more.
Dependables::iterator di;
di = _dependables.find(words[0]);
if (di != _dependables.end()) {
_dependables.erase(di);
}
okcache = false;
break;
}
}
getline(in, line);
}
if (!okcache) {
if (verbose || true) {
cerr << "Cache \"" << cache_pathname << "\" is stale.\n";
}
Dependables::iterator di;
for (di = _dependables.begin(); di != _dependables.end(); ++di) {
(*di).second->clear_cache();
}
}
}
}
Children::iterator ci;
@ -773,9 +838,8 @@ update_file_dependencies(const string &cache_filename) {
cache_pathname.unlink();
// If we have no files, don't bother writing the cache.
if (!_dependables.empty()) {
bool wrote_anything = false;
if (!_dependables.empty()) {
ofstream out;
if (!cache_pathname.open_write(out)) {
cerr << "Cannot update cache dependency file " << cache_pathname << "\n";
@ -792,7 +856,7 @@ update_file_dependencies(const string &cache_filename) {
Dependables::const_iterator di;
for (di = _dependables.begin(); di != _dependables.end(); ++di) {
PPDependableFile *file = (*di).second;
if (file->was_examined() || external_tree) {
if (file->was_examined() || (external_tree && file->was_cached())) {
if (file->is_circularity()) {
cerr << "Warning: circular #include directives:\n"
<< " " << file->get_circularity() << "\n";
@ -803,6 +867,7 @@ update_file_dependencies(const string &cache_filename) {
}
out.close();
}
if (!wrote_anything) {
// Well, if we didn't write anything, remove the cache file
@ -810,7 +875,6 @@ update_file_dependencies(const string &cache_filename) {
cache_pathname.unlink();
}
}
}
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {