Skip to content

Commit

Permalink
libdeng2|FS: ArchiveFeed observes source file for deletion
Browse files Browse the repository at this point in the history
If the source file is deleted, any changes to the archive are first
saved.
  • Loading branch information
skyjake committed Feb 27, 2014
1 parent 51526df commit ca26424
Showing 1 changed file with 54 additions and 24 deletions.
78 changes: 54 additions & 24 deletions doomsday/libdeng2/src/filesys/archivefeed.cpp
Expand Up @@ -29,9 +29,10 @@
namespace de {

DENG2_PIMPL(ArchiveFeed)
, DENG2_OBSERVES(File, Deletion)
{
/// File where the archive is stored (in a serialized format).
File &file;
File *file;

/// The archive can be physically stored here, as Archive doesn't make a
/// copy of the buffer.
Expand All @@ -45,9 +46,9 @@ DENG2_PIMPL(ArchiveFeed)
/// The feed whose archive this feed is using.
ArchiveFeed *parentFeed;

Instance(Public *feed, File &f) : Base(feed), file(f), arch(0), parentFeed(0)
Instance(Public *feed, File &f) : Base(feed), file(&f), arch(0), parentFeed(0)
{
/// @todo Observe the file for deletion.
file->audienceForDeletion += this;

// If the file happens to be a byte array file, we can use it
// directly to store the Archive.
Expand All @@ -73,29 +74,53 @@ DENG2_PIMPL(ArchiveFeed)

Instance(Public *feed, ArchiveFeed &parentFeed, String const &path)
: Base(feed), file(parentFeed.d->file), arch(0), basePath(path), parentFeed(&parentFeed)
{}
{
file->audienceForDeletion += this;
}

~Instance()
{
if(file)
{
file->audienceForDeletion -= this;
}

if(arch)
{
// If modified, the archive is written back to the file.
if(arch->modified())
{
LOG_RES_MSG("Updating archive in ") << file.description();
writeIfModified();
delete arch;
}
}

// Make sure we have either a compressed or uncompressed version of
// each entry in memory before destroying the source file.
arch->cache();
void writeIfModified()
{
if(!file || !arch) return;

file.clear();
Writer(file) << *arch;
}
else
{
LOG_RES_VERBOSE("Not updating archive in %s (not changed)") << file.description();
}
delete arch;
// If modified, the archive is written back to the file.
if(arch->modified())
{
LOG_RES_MSG("Updating archive in ") << file->description();

// Make sure we have either a compressed or uncompressed version of
// each entry in memory before destroying the source file.
arch->cache();

file->clear();
Writer(*file) << *arch;
}
else
{
LOG_RES_VERBOSE("Not updating archive in %s (not changed)") << file->description();
}
}

void fileBeingDeleted(File const &deleted)
{
if(file == &deleted)
{
// Ensure that changes are saved and detach from the file.
writeIfModified();
file = 0;
}
}

Expand Down Expand Up @@ -125,18 +150,19 @@ DENG2_PIMPL(ArchiveFeed)
String entry = basePath / *i;

std::auto_ptr<ArchiveEntryFile> archFile(new ArchiveEntryFile(*i, archive(), entry));

// Use the status of the entry within the archive.
archFile->setStatus(archive().entryStatus(entry));

// Create a new file that accesses this feed's archive and interpret the contents.
File *file = folder.fileSystem().interpret(archFile.release());
folder.add(file);
File *f = folder.fileSystem().interpret(archFile.release());
folder.add(f);

// We will decide on pruning this.
file->setOriginFeed(&self);
f->setOriginFeed(&self);

// Include the file in the main index.
folder.fileSystem().index(*file);
folder.fileSystem().index(*f);
}

// Also populate subfolders.
Expand Down Expand Up @@ -165,7 +191,11 @@ ArchiveFeed::~ArchiveFeed()

String ArchiveFeed::description() const
{
return "archive in " + d->file.description();
if(d->file)
{
return "archive in " + d->file->description();
}
return "archive in (no file)";
}

void ArchiveFeed::populate(Folder &folder)
Expand Down

0 comments on commit ca26424

Please sign in to comment.