Skip to content

Commit

Permalink
Refactor: Moved logic preventing unload of required game resources
Browse files Browse the repository at this point in the history
This logic is now handled from within the file system by querying
the current Game for the candidate file path prior to unload.
  • Loading branch information
danij-deng committed Jan 11, 2012
1 parent 53b0a26 commit c6f08af
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 73 deletions.
10 changes: 6 additions & 4 deletions doomsday/engine/portable/include/fs_main.h
Expand Up @@ -157,22 +157,24 @@ abstractfile_t* F_FindLumpFile(const char* path, int* lumpIdx);
* other files are single lumps whose base filename will become the lump name.
*
* @param path Path to the file to be opened. Either a "real" file in the local
* file system, or a "virtual" file in the virtual file system.
* file system, or a "virtual" file in the virtual file system.
* @param baseOffset Offset from the start of the file in bytes to begin.
* @param allowDuplicate @c true = allow opening multiple copies of the same file.
* @return @c true, if the operation is successful.
*/
boolean F_AddFile(const char* path, size_t baseOffset, boolean allowDuplicate);

/**
* Remove a file from the virtual file system.
* Attempt to remove a file from the virtual file system.
*
* @param permitRequired @c true= allow removal of resources marked as "required"
* by the currently loaded Game.
* @return @c true if the operation is successful.
*/
boolean F_RemoveFile(const char* path);
boolean F_RemoveFile(const char* path, boolean permitRequired);

boolean F_AddFiles(const char* const* paths, size_t num, boolean allowDuplicate);
boolean F_RemoveFiles(const char* const* paths, size_t num);
boolean F_RemoveFiles(const char* const* paths, size_t num, boolean permitRequired);

/**
* @return @c true if the file can be opened for reading.
Expand Down
5 changes: 5 additions & 0 deletions doomsday/engine/portable/include/game.h
Expand Up @@ -67,6 +67,11 @@ void Game_Delete(Game* game);
struct AbstractResource_s* Game_AddResource(Game* game, resourceclass_t rclass,
struct AbstractResource_s* record);

/**
* @return @c true iff @a absolutePath points to a required resource.
*/
boolean Game_IsRequiredResource(Game* game, const char* absolutePath);

/**
* Change the identfier of the plugin associated with this.
* @param pluginId New identifier.
Expand Down
61 changes: 9 additions & 52 deletions doomsday/engine/portable/src/dd_main.c
Expand Up @@ -539,37 +539,6 @@ static int validateResource(AbstractResource* rec, void* paramaters)
return validated;
}

static boolean isRequiredResource(Game* game, const char* absolutePath)
{
AbstractResource* const* records = Game_Resources(game, RC_PACKAGE, 0);
if(records)
{
AbstractResource* const* recordIt;
// Is this resource from a container?
abstractfile_t* file = F_FindLumpFile(absolutePath, NULL);
if(file)
{
// Yes; use the container's path instead.
absolutePath = Str_Text(AbstractFile_Path(file));
}

for(recordIt = records; *recordIt; recordIt++)
{
AbstractResource* rec = *recordIt;
if(AbstractResource_ResourceFlags(rec) & RF_STARTUP)
{
const ddstring_t* resolvedPath = AbstractResource_ResolvedPath(rec, true);
if(resolvedPath && !Str_CompareIgnoreCase(resolvedPath, absolutePath))
{
return true;
}
}
}
}
// Not found, so no.
return false;
}

static void locateGameResources(Game* game)
{
Game* oldGame = theGame;
Expand Down Expand Up @@ -2395,9 +2364,10 @@ D_CMD(Load)

D_CMD(Unload)
{
ddstring_t foundPath, searchPath;
int i, result = 0;
boolean didUnloadFiles = false;
ddstring_t searchPath;
Game* game;
int i;

// No arguments; unload the current game if loaded.
if(argc == 1)
Expand Down Expand Up @@ -2441,34 +2411,21 @@ D_CMD(Unload)
return true;
}

/// Try the resource locator.
Str_Init(&foundPath);
// Try the resource locator.
for(i = 1; i < argc; ++i)
{
Str_Set(&searchPath, argv[i]);
Str_Strip(&searchPath);

if(!F_FindResource2(RC_PACKAGE, Str_Text(&searchPath), &foundPath))
continue;

// Do not attempt to unload a resource required by the current game.
if(isRequiredResource(theGame, Str_Text(&foundPath)))
if(!F_FindResource2(RC_PACKAGE, argv[i], &searchPath) ||
!F_RemoveFile(Str_Text(&searchPath), false/*not required game resources*/))
{
Con_Message("\"%s\" is required by the current game and cannot be unloaded in isolation.\n",
F_PrettyPath(Str_Text(&foundPath)));
continue;
}

// We can safely remove this file.
if(F_RemoveFile(Str_Text(&foundPath)))
{
result = 1;
}
// Success!
didUnloadFiles = true;
}

Str_Free(&foundPath);
Str_Free(&searchPath);
return result != 0;
return didUnloadFiles;
}

D_CMD(Reset)
Expand Down
52 changes: 35 additions & 17 deletions doomsday/engine/portable/src/fs_main.c
Expand Up @@ -304,20 +304,37 @@ static lumpnum_t chooseWadLumpDirectory(lumpnum_t lumpNum)
return lumpNum;
}

static boolean unloadFile2(const char* path)
static boolean unloadFile2(const char* path, boolean permitRequired, boolean quiet)
{
int idx;
errorIfNotInited("unloadFile2");
idx = findFileNodeIndexForPath(loadedFiles, path);
if(idx >= 0)
{
// Do not attempt to unload a resource required by the current game.
if(!permitRequired && Game_IsRequiredResource(theGame, path))
{
if(!quiet)
{
Con_Message("\"%s\" is required by the current game.\n"
"Required game files cannot be unloaded in isolation.\n", F_PrettyPath(path));
}
return false;
}

if(!quiet && verbose >= 1)
{
Con_Message("Unloading \"%s\"...\n", F_PrettyPath(path));
}

return removeLoadedFile(idx);
}
return false; // No such file loaded.
}

static boolean unloadFile(const char* path)
static boolean unloadFile(const char* path, boolean permitRequired)
{
VERBOSE( Con_Message("Unloading \"%s\"...\n", F_PrettyPath(path)) )
return unloadFile2(path);
return unloadFile2(path, permitRequired, false/*do log issues*/);
}

static void clearFileIds(void)
Expand All @@ -334,9 +351,10 @@ static void clearFileIds(void)

void F_PrintFileId(byte identifier[16])
{
assert(identifier);
{ uint i;
uint i;
if(!identifier) return;
for(i = 0; i < 16; ++i)
{
Con_Printf("%02x", identifier[i]);
}
}
Expand Down Expand Up @@ -529,7 +547,8 @@ static int unloadListFiles(FileList* list, boolean nonStartup)
file = FileList_GetFile(list, i);
if(!nonStartup || !AbstractFile_HasStartup(file))
{
if(unloadFile2(Str_Text(AbstractFile_Path(file))))
if(unloadFile2(Str_Text(AbstractFile_Path(file)),
true/*allow unloading game resources*/, true/*quiet please*/))
{
++unloaded;
}
Expand Down Expand Up @@ -1717,7 +1736,8 @@ boolean F_AddFile(const char* path, size_t baseOffset, boolean allowDuplicate)
boolean F_AddFiles(const char* const* paths, size_t num, boolean allowDuplicate)
{
boolean succeeded = false;
{ size_t i;
size_t i;

for(i = 0; i < num; ++i)
{
if(F_AddFile(paths[i], 0, allowDuplicate))
Expand All @@ -1726,8 +1746,10 @@ boolean F_AddFiles(const char* const* paths, size_t num, boolean allowDuplicate)
succeeded = true; // At least one has been loaded.
}
else
{
Con_Message("Warning: Errors occured while loading %s\n", paths[i]);
}}
}
}

// A changed file list may alter the main lump directory.
if(succeeded)
Expand All @@ -1737,30 +1759,26 @@ boolean F_AddFiles(const char* const* paths, size_t num, boolean allowDuplicate)
return succeeded;
}

boolean F_RemoveFile(const char* path)
boolean F_RemoveFile(const char* path, boolean permitRequired)
{
boolean unloadedResources = unloadFile(path);
boolean unloadedResources = unloadFile(path, permitRequired);
if(unloadedResources)
DD_UpdateEngineState();
return unloadedResources;
}

boolean F_RemoveFiles(const char* const* filenames, size_t num)
boolean F_RemoveFiles(const char* const* filenames, size_t num, boolean permitRequired)
{
boolean succeeded = false;
size_t i;

for(i = 0; i < num; ++i)
{
if(unloadFile(filenames[i]))
if(unloadFile(filenames[i], permitRequired))
{
VERBOSE2( Con_Message("Done unloading %s\n", F_PrettyPath(filenames[i])) )
succeeded = true; // At least one has been unloaded.
}
else
{
Con_Message("Warning: Errors occured while unloading %s\n", filenames[i]);
}
}

// A changed file list may alter the main lump directory.
Expand Down
31 changes: 31 additions & 0 deletions doomsday/engine/portable/src/game.c
Expand Up @@ -179,6 +179,37 @@ AbstractResource* Game_AddResource(Game* g, resourceclass_t rclass,
return record;
}

boolean Game_IsRequiredResource(Game* game, const char* absolutePath)
{
AbstractResource* const* records = Game_Resources(game, RC_PACKAGE, 0);
if(records)
{
AbstractResource* const* recordIt;
// Is this resource from a container?
abstractfile_t* file = F_FindLumpFile(absolutePath, NULL);
if(file)
{
// Yes; use the container's path instead.
absolutePath = Str_Text(AbstractFile_Path(file));
}

for(recordIt = records; *recordIt; recordIt++)
{
AbstractResource* rec = *recordIt;
if(AbstractResource_ResourceFlags(rec) & RF_STARTUP)
{
const ddstring_t* resolvedPath = AbstractResource_ResolvedPath(rec, true);
if(resolvedPath && !Str_CompareIgnoreCase(resolvedPath, absolutePath))
{
return true;
}
}
}
}
// Not found, so no.
return false;
}

pluginid_t Game_SetPluginId(Game* g, pluginid_t pluginId)
{
assert(g);
Expand Down

0 comments on commit c6f08af

Please sign in to comment.