virtualMountSystem.cpp
Engine/source/core/virtualMountSystem.cpp
Namespaces:
namespace
namespace
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "core/virtualMountSystem.h" 26 27#include "console/console.h" 28#include "core/tAlgorithm.h" 29 30namespace Torque 31{ 32namespace FS 33{ 34 35bool gVMSVerboseLog = false; 36 37bool VirtualMountSystem::mount(String root, FileSystemRef fs) 38{ 39 bool ok = Parent::mount(root,fs); 40 if (!ok) 41 return false; 42 43 root = String::ToLower(root); 44 45 mRootMap[root].push_back(fs); 46 47// PathFSMap* rootDict = NULL; 48// if (!mMountMap.tryGetValue(root, rootDict)) 49// { 50// rootDict = new PathFSMap(); 51// mMountMap[root] = rootDict; 52// } 53// 54// U32 start = Platform::getRealMilliseconds(); 55// 56// // get the paths from the fs and add them to the rootDict 57// Vector<String> paths; 58// 59// // we'll use the mount system's findByPattern function to build the path list. 60// // but, we want to override its default behavior so that it searches only the desired fs. 61// _setFindByPatternOverrideFS(fs); 62// 63// Torque::Path basePath; 64// // we use an empty root so that the resulting filenames don't have the root filename in them. 65// // we don't want to include the root in the dict has entries. we can omit the root because we have 66// // specified an override FS; the search would fail otherwise. 67// //basePath.setRoot(root); 68// basePath.setRoot(""); 69// basePath.setPath("/"); 70// mUseParentFind = true; 71// if (findByPattern(basePath, "*.*", true, paths, true) == -1) 72// { 73// // this is probably a problem 74// _log("Unable to get paths from filesystem for virtual mount"); 75// _setFindByPatternOverrideFS(NULL); 76// mUseParentFind = false; 77// return false; 78// } 79// 80// _setFindByPatternOverrideFS(NULL); 81// mUseParentFind = false; 82// 83// for (S32 i = 0; i < paths.size(); ++i) 84// { 85// String path = String::ToLower(paths[i]); 86// 87// // is it a directory? if so remove dir prefix 88// String dirPrefix = "DIR:"; 89// String::SizeType dIdx = path.find(dirPrefix, 0, String::NoCase); 90// if (dIdx == 0) 91// path = path.substr(dirPrefix.length()); 92// // omit leading / 93// if (path[(String::SizeType)0] == '/') 94// path = path.substr(1); 95// 96// // warn about duplicate files (not directories) 97// // JMQ: disabled this, it false alarms at startup because the mount doc always mounts the 98// // root before other processing mounts. still, would be useful, maybe change the mount doc to 99// // not mount root? 100// if (dIdx != 0 && (*rootDict)[path].size() > 0) 101// _log(String::ToString("Duplicate file path detected, first volume containing file will be used: %s", path.c_str())); 102// 103// (*rootDict)[path].push_back(fs); 104// } 105// 106// if (gVMSVerboseLog) 107// _log(String::ToString("Indexed virtual file system in %ums", Platform::getRealMilliseconds() - start)); 108 109 return true; 110} 111 112bool VirtualMountSystem::mount(String root, const Path &path) 113{ 114 //AssertFatal(false, "This function not supported in virtual mount system"); 115 return Parent::mount(root, path); 116} 117 118FileSystemRef VirtualMountSystem::unmount(String root) 119{ 120 FileSystemRef ret = Parent::unmount(root); 121 122 mRootMap.erase(root); 123 124 // clear all filesystem lists for root. 125// PathFSMap* rootDict = NULL; 126// root = String::ToLower(root); 127// if (!mMountMap.tryGetValue(root, rootDict)) 128// return ret; 129// 130// // buh bye 131// mMountMap.erase(root); 132// delete rootDict; 133 134 return ret; 135} 136 137bool VirtualMountSystem::unmount(FileSystemRef fs) 138{ 139 bool unmounted = Parent::unmount(fs); 140 if (!unmounted) 141 return false; 142 143 for(PathFSMap::Iterator ritr = mRootMap.begin();ritr != mRootMap.end();++ritr) 144 { 145 RootToFSVec &vec = (*ritr).value; 146 for (S32 i = vec.size() - 1;i >= 0;i--) 147 { 148 if (vec[i].getPointer() == fs.getPointer()) 149 vec.erase(i); 150 } 151 } 152 153 // this is a linear time operation, because we have to search every path in all roots 154 // to remove references to the fs. 155 // contant time operation can be achieved be using the unmount(string) version, which unmounts all 156 // filesystems for a given root and so doesn't need to do any searching. 157// U32 start = Platform::getRealMilliseconds(); 158// for (RootToPathFSMap::Iterator riter = mMountMap.begin(); 159// riter != mMountMap.end(); 160// ++riter) 161// { 162// PathFSMap* rootDict = (*riter).value; 163// for (PathFSMap::Iterator piter = rootDict->begin(); 164// piter != rootDict->end(); 165// ++piter) 166// { 167// Vector<FileSystemRef>& plist = (*piter).value; 168// for (S32 i = plist.size() - 1; 169// i >= 0; 170// i--) 171// { 172// if (plist[i].getPointer() == fs.getPointer()) 173// plist.erase(i); 174// } 175// } 176// } 177// 178// if (gVMSVerboseLog) 179// _log(String::ToString("Unmounted virtual file system in %ums", Platform::getRealMilliseconds() - start)); 180 181 return true; 182} 183 184S32 VirtualMountSystem::findByPattern( const Path &inBasePath, const String &inFilePattern, bool inRecursive, Vector<String> &outList, bool includeDirs/* =false */, bool multiMatch /* = true */ ) 185{ 186 if (mUseParentFind) 187 // use parent version 188 return Parent::findByPattern(inBasePath, inFilePattern, inRecursive, outList, includeDirs, multiMatch); 189 190 // don't want to re-enter this version 191 mUseParentFind = true; 192 193 // kind of cheesy, just call find by pattern on each File system mounted on the root 194 for (Vector<MountFS>::const_iterator itr = mMountList.begin(); itr != mMountList.end(); itr++) 195 { 196 if (itr->root.equal( inBasePath.getRoot(), String::NoCase ) ) 197 { 198 FileSystemRef fsref = itr->fileSystem; 199 _setFindByPatternOverrideFS(fsref); 200 Parent::findByPattern(inBasePath, inFilePattern, inRecursive, outList, includeDirs, multiMatch); 201 _setFindByPatternOverrideFS(NULL); 202 } 203 } 204 205 mUseParentFind = false; 206 207 return outList.size(); 208} 209 210bool VirtualMountSystem::createPath(const Path& path) 211{ 212 bool ret = Parent::createPath(path); 213 214// if (ret) 215// { 216// // make sure the filesystem that owns the path has the path elements 217// // in its search table (so that we can open the file, if it is new) 218// String root = String::ToLower(path.getRoot()); 219// FileSystemRef fsRef = getFileSystem(path); 220// 221// PathFSMap* rootDict = mMountMap[root]; 222// if (rootDict) 223// { 224// // add all directories in the path 225// // add the filename 226// 227// // Start from the top and work our way down 228// Path sub,dir; 229// dir.setPath(""); 230// for (U32 i = 0; i < path.getDirectoryCount(); i++) 231// { 232// sub.setPath(path.getDirectory(i)); 233// dir.appendPath(sub); 234// 235// Vector<FileSystemRef>& fsList = (*rootDict)[String::ToLower(dir.getPath())]; 236// Vector<FileSystemRef>::iterator iter = ::find(fsList.begin(), fsList.end(), fsRef); 237// 238// if (iter == fsList.end()) 239// fsList.push_back(fsRef); 240// } 241// 242// // add full file path 243// Vector<FileSystemRef>& fsList = (*rootDict)[String::ToLower(path.getFullPath(false))]; 244// Vector<FileSystemRef>::iterator iter = ::find(fsList.begin(), fsList.end(), fsRef); 245// 246// if (iter == fsList.end()) 247// fsList.push_back(fsRef); 248// } 249// } 250 251 return ret; 252} 253 254void VirtualMountSystem::_log(const String& msg) 255{ 256 String newMsg = "VirtualMountSystem: " + msg; 257 Con::warnf("%s", newMsg.c_str()); 258} 259 260FileSystemRef VirtualMountSystem::_removeMountFromList(String root) 261{ 262 return Parent::_removeMountFromList(root); 263} 264 265FileSystemRef VirtualMountSystem::_getFileSystemFromList(const Path& fullpath) const 266{ 267 String root = String::ToLower(fullpath.getRoot()); 268 String path = fullpath.getFullPathWithoutRoot(); 269 // eat leading slash 270 if (path[(String::SizeType)0] == '/') 271 path = path.substr(1); 272 // lowercase it 273 path = String::ToLower(path); 274 275 // find the dictionary for root 276// PathFSMap* rootDict = NULL; 277// if (!mMountMap.tryGetValue(root, rootDict)) 278// return NULL; 279// 280// // see if we have a FS list for this path 281// Vector<FileSystemRef>& fsList = (*rootDict)[path]; 282 283 RootToFSVec fsList; 284 if(! mRootMap.tryGetValue(root, fsList)) 285 return NULL; 286 287 if (fsList.size() == 0) 288 { 289 // no exact match for path, defer to parent 290 return Parent::_getFileSystemFromList(fullpath); 291 } 292 else 293 { 294 // find the right file system 295 if(fsList.size() == 1) 296 return fsList[0]; 297 298 // Go in reverse order to pick up the last matching virtual path 299 for(S32 i = fsList.size()-1; i >= 0 ; --i) 300 { 301 FileNodeRef fn = fsList[i]->resolve(path); 302 if(fn != NULL) 303 return fsList[i]; 304 } 305 306 return fsList[0]; 307 } 308} 309 310} //namespace FS 311} //namespace Torque 312