Skip to content

Commit

Permalink
FS|RemoteFeed: Remember remote status of cached files
Browse files Browse the repository at this point in the history
The real last-modified time of remote files is stored in a special
auxiliary file. This ensures that non-versioned files use a version
number that matches the server-side file when Doomsday loads cached
data files.
  • Loading branch information
skyjake committed Oct 17, 2017
1 parent 2249902 commit a87a87e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 8 deletions.
2 changes: 2 additions & 0 deletions doomsday/sdk/libcore/include/de/filesys/directoryfeed.h
Expand Up @@ -105,6 +105,8 @@ class DENG2_PUBLIC DirectoryFeed : public Feed
*/
static File::Status fileStatus(NativePath const &nativePath);

static void setFileModifiedTime(NativePath const &nativePath, Time const &modifiedAt);

/**
* Creates and interprets a single native file and adds it to a folder. The created
* file is not governed by any feed and will not be pruned during folder pruning.
Expand Down
45 changes: 39 additions & 6 deletions doomsday/sdk/libcore/src/filesys/directoryfeed.cpp
Expand Up @@ -27,7 +27,9 @@
#include <QDir>
#include <QFileInfo>

using namespace de;
namespace de {

static String const fileStatusSuffix = ".doomsday_file_status";

DirectoryFeed::DirectoryFeed(NativePath const &nativePath, Flags const &mode)
: _nativePath(nativePath), _mode(mode) {}
Expand Down Expand Up @@ -79,7 +81,10 @@ Feed::PopulatedFiles DirectoryFeed::populate(Folder const &folder)
}
else
{
populateFile(folder, entry.fileName(), populated);
if (!entry.fileName().endsWith(fileStatusSuffix)) // ignore meta files
{
populateFile(folder, entry.fileName(), populated);
}
}
}
return populated;
Expand Down Expand Up @@ -253,17 +258,43 @@ void DirectoryFeed::changeWorkingDir(NativePath const &nativePath)
File::Status DirectoryFeed::fileStatus(NativePath const &nativePath)
{
QFileInfo info(nativePath);

if (!info.exists())
{
/// @throw StatusError Determining the file status was not possible.
throw StatusError("DirectoryFeed::fileStatus", nativePath + " inaccessible");
}

// Get file status information.
return File::Status(info.isDir()? File::Type::Folder : File::Type::File,
dsize(info.size()),
info.lastModified());
File::Status st { info.isDir()? File::Type::Folder : File::Type::File,
dsize(info.size()),
info.lastModified() };

// Check for overridden status.
String const overrideName = nativePath + fileStatusSuffix;
if (QFileInfo().exists(overrideName))
{
QFile f(overrideName);
if (f.open(QFile::ReadOnly))
{
st.modifiedAt = Time::fromText(String::fromUtf8(f.readAll()), Time::ISOFormat);
}
}
return st;
}

void DirectoryFeed::setFileModifiedTime(NativePath const &nativePath, Time const &modifiedAt)
{
String const overrideName = nativePath + fileStatusSuffix;
if (!modifiedAt.isValid())
{
QFile::remove(overrideName);
return;
}
QFile f(overrideName);
if (f.open(QFile::WriteOnly | QFile::Truncate))
{
f.write(modifiedAt.asText(Time::ISOFormat).toUtf8());
}
}

File &DirectoryFeed::manuallyPopulateSingleFile(NativePath const &nativePath,
Expand Down Expand Up @@ -314,3 +345,5 @@ File &DirectoryFeed::manuallyPopulateSingleFile(NativePath const &nativePath,
FS::DontInheritFeeds | FS::PopulateNewFolder);
}
}

} // namespace de
15 changes: 13 additions & 2 deletions doomsday/sdk/libcore/src/filesys/remotefile.cpp
Expand Up @@ -19,11 +19,13 @@
#include "de/RemoteFile"

#include "de/App"
#include "de/DirectoryFeed"
#include "de/FileSystem"
#include "de/RecordValue"
#include "de/RemoteFeedRelay"
#include "de/ScriptSystem"
#include "de/TextValue"
#include "de/TimeValue"

namespace de {

Expand All @@ -35,7 +37,6 @@ DENG2_PIMPL(RemoteFile)
Block remoteMetaId;
Block buffer;
RemoteFeedRelay::FileContentsRequest fetching;
//SafePtr<File const> cachedFile;

Impl(Public *i) : Base(i) {}

Expand Down Expand Up @@ -150,9 +151,19 @@ void RemoteFile::fetchContents()
File &data = cacheFolder.replaceFile(fn);
data << d->buffer;
d->buffer.clear();

data.flush();

// Override the last modified time.
{
auto st = data.status();
st.modifiedAt = status().modifiedAt;
data.setStatus(st);

// Remember this for later as well.
DirectoryFeed::setFileModifiedTime(data.correspondingNativePath(),
st.modifiedAt);
}

setTarget(data.reinterpret());

// d->cachedFile.reset(&data);
Expand Down

0 comments on commit a87a87e

Please sign in to comment.