Home > Software engineering >  c testing if one file is older than a set of files
c testing if one file is older than a set of files

Time:03-02

I am creating a cache for some data, but of course I want the cache to become invalid if any of the source files from which the cache is made is modified. TO that effect I made this function:

bool CacheIsValid(
    const std::string& cache_shader_path,
    const std::vector<std::string>& shader_paths)
{
    // This is really messy because of the std stuff, the short of it is:
    // Find the youngest file in the shader paths, then check it against the
    // timestamp of the cached file.
    std::time_t youngest_file_ts = std::time(nullptr);
    for(auto file : shader_paths)
    {
        std::time_t current_timestamp =
            std::chrono::system_clock::to_time_t(
                std::chrono::file_clock::to_sys(fs::last_write_time(file)));
        double time_diff = difftime(youngest_file_ts, current_timestamp);
        if(time_diff > 0) youngest_file_ts = current_timestamp;
    }

    // All this is doing is comparing the youngest file time stamp with the cache.
    return fs::exists(cache_shader_path)
        && (difftime(youngest_file_ts, std::chrono::system_clock::to_time_t(
            std::chrono::file_clock::to_sys(fs::last_write_time(cache_shader_path)))) < 0);
}

I don't know what I did wrong but that is always returning true even when the input files are modified. I am checking the timestamps using stat and the files on disk are objectively younger than the cache file, I also tested that the inputs to this function are correct, and they are.

CodePudding user response:

It seems to me that you're jumping through a lot of hoops that make this tremendously more difficult than it needs to be. filesystem::last_write_time returns a time_point<someclock>1 , which supports comparison. As such, at least as far as I can see, there's no reason to do the long, drawn-out conversion to time_t, then using difftime to do the comparison.

If I understand the idea of what you're doing, you want to ascertain that the one file is at least as new as any of the files named in the vector. To do that a bit more directly, I'd write code something along this general line:

bool isNewer(std::string const &file, std::vector<std::string> const &otherFiles) {
    auto newest = std::max_element(otherFiles.begin(), otherFiles.end(), 
        [&](std::string const &a, std::string const &b) {           
            return fs::last_write_time(a) > fs::last_write_time(b);
        });

    return fs::last_write_time(file) >= fs::last_write_time(*newest);
}

I may have misunderstood the direction you want one or both comparisons done, in which case this may not be right--but if so, changing the comparison(s) to match your requirements should be trivial.


  1. where someclock is some arbitrary type that meets a few specified requirements for C 17, or std::chrono::file_clock for C 20.

CodePudding user response:

due to you want to find youngest_file_ts -> find most recently timestamp (greater number) of a changing file however

double time_diff = difftime(youngest_file_ts, current_timestamp);
if(time_diff > 0) youngest_file_ts = current_timestamp; // find greater number one

after the for loop youngest_file_ts is oldest timestamp of a changing file therefor

(difftime(youngest_file_ts, std::chrono::system_clock::to_time_t(
          std::chrono::file_clock::to_sys(fs::last_write_time(cache_shader_path)))) < 0) alway true.

it should be change like

    if (shader_paths.empty()) {
        return false
    } else {
//initialize youngest_file_ts as last_write_time of first element in shader_paths
        std::time_t youngest_file_ts = std::chrono::system_clock::to_time_t(
                 std::chrono::file_clock::to_sys(fs::last_write_time(shader_paths.at(0))); 
        for (auto file : shader_paths)
        {
            std::time_t current_timestamp = std::chrono::system_clock::to_time_t(
                std::chrono::file_clock::to_sys(fs::last_write_time(file)));
            double time_diff = difftime(youngest_file_ts, current_timestamp);
            if (time_diff < 0) youngest_file_ts = current_timestamp;
        }
        // All this is doing is comparing the youngest file time stamp with the cache.
        return fs::exists(cache_shader_path)
            && (difftime(youngest_file_ts, std::chrono::system_clock::to_time_t(
                std::chrono::file_clock::to_sys(fs::last_write_time(cache_shader_path)))) < 0);
    }
  • Related