reduce file op overhead; fix some obscure long-standing race conditions

with Unmount due to broken refcounting
This commit is contained in:
Glenn Maynard
2005-09-04 04:57:26 +00:00
parent 35272e5f9e
commit 6149d63867
+137 -127
View File
@@ -41,27 +41,27 @@ struct LoadedDriver
CString GetPath( const CString &sPath ) const; CString GetPath( const CString &sPath ) const;
}; };
static vector<LoadedDriver> g_Drivers; static vector<LoadedDriver *> g_pDrivers;
static void ReferenceAllDrivers( vector<LoadedDriver> &aDriverList ) static void ReferenceAllDrivers( vector<LoadedDriver *> &apDriverList )
{ {
g_Mutex->Lock(); g_Mutex->Lock();
aDriverList = g_Drivers; apDriverList = g_pDrivers;
for( unsigned i = 0; i < aDriverList.size(); ++i ) for( unsigned i = 0; i < apDriverList.size(); ++i )
++aDriverList[i].m_iRefs; ++apDriverList[i]->m_iRefs;
g_Mutex->Unlock(); g_Mutex->Unlock();
} }
static void UnreferenceAllDrivers( vector<LoadedDriver> &aDriverList ) static void UnreferenceAllDrivers( vector<LoadedDriver *> &apDriverList )
{ {
g_Mutex->Lock(); g_Mutex->Lock();
for( unsigned i = 0; i < aDriverList.size(); ++i ) for( unsigned i = 0; i < apDriverList.size(); ++i )
--aDriverList[i].m_iRefs; --apDriverList[i]->m_iRefs;
g_Mutex->Broadcast(); g_Mutex->Broadcast();
g_Mutex->Unlock(); g_Mutex->Unlock();
/* Clear the temporary list, to make it clear that the drivers may no longer be accessed. */ /* Clear the temporary list, to make it clear that the drivers may no longer be accessed. */
aDriverList.clear(); apDriverList.clear();
} }
RageFileDriver *RageFileManager::GetFileDriver( CString sMountpoint ) RageFileDriver *RageFileManager::GetFileDriver( CString sMountpoint )
@@ -72,13 +72,13 @@ RageFileDriver *RageFileManager::GetFileDriver( CString sMountpoint )
g_Mutex->Lock(); g_Mutex->Lock();
RageFileDriver *pRet = NULL; RageFileDriver *pRet = NULL;
for( unsigned i = 0; i < g_Drivers.size(); ++i ) for( unsigned i = 0; i < g_pDrivers.size(); ++i )
{ {
if( g_Drivers[i].m_sMountPoint.CompareNoCase( sMountpoint ) ) if( g_pDrivers[i]->m_sMountPoint.CompareNoCase( sMountpoint ) )
continue; continue;
pRet = g_Drivers[i].m_pDriver; pRet = g_pDrivers[i]->m_pDriver;
++g_Drivers[i].m_iRefs; ++g_pDrivers[i]->m_iRefs;
break; break;
} }
g_Mutex->Unlock(); g_Mutex->Unlock();
@@ -92,14 +92,14 @@ void RageFileManager::ReleaseFileDriver( RageFileDriver *pDriver )
g_Mutex->Lock(); g_Mutex->Lock();
unsigned i; unsigned i;
for( i = 0; i < g_Drivers.size(); ++i ) for( i = 0; i < g_pDrivers.size(); ++i )
{ {
if( g_Drivers[i].m_pDriver == pDriver ) if( g_pDrivers[i]->m_pDriver == pDriver )
break; break;
} }
ASSERT( i != g_Drivers.size() ); ASSERT( i != g_pDrivers.size() );
--g_Drivers[i].m_iRefs; --g_pDrivers[i]->m_iRefs;
g_Mutex->Broadcast(); g_Mutex->Broadcast();
g_Mutex->Unlock(); g_Mutex->Unlock();
@@ -116,19 +116,19 @@ static bool GrabDriver( RageFileDriver *pDriver )
while(1) while(1)
{ {
unsigned i; unsigned i;
for( i = 0; i < g_Drivers.size(); ++i ) for( i = 0; i < g_pDrivers.size(); ++i )
if( g_Drivers[i].m_pDriver == pDriver ) if( g_pDrivers[i]->m_pDriver == pDriver )
break; break;
if( i == g_Drivers.size() ) if( i == g_pDrivers.size() )
{ {
g_Mutex->Unlock(); g_Mutex->Unlock();
return false; return false;
} }
if( g_Drivers[i].m_iRefs == 0 ) if( g_pDrivers[i]->m_iRefs == 0 )
{ {
g_Drivers.erase( g_Drivers.begin()+i ); g_pDrivers.erase( g_pDrivers.begin()+i );
return true; return true;
} }
@@ -155,15 +155,15 @@ public:
/* Never flush FDB, except in LoadFromDrivers. */ /* Never flush FDB, except in LoadFromDrivers. */
void FlushDirCache( const CString &sPath ) { } void FlushDirCache( const CString &sPath ) { }
void LoadFromDrivers( const vector<LoadedDriver> &asDrivers ) void LoadFromDrivers( const vector<LoadedDriver *> &apDrivers )
{ {
/* XXX: Even though these two operations lock on their own, lock around /* XXX: Even though these two operations lock on their own, lock around
* them, too. That way, nothing can sneak in and get incorrect * them, too. That way, nothing can sneak in and get incorrect
* results between the flush and the re-population. */ * results between the flush and the re-population. */
FDB->FlushDirCache(); FDB->FlushDirCache();
for( unsigned i = 0; i < asDrivers.size(); ++i ) for( unsigned i = 0; i < apDrivers.size(); ++i )
if( asDrivers[i].m_sMountPoint != "/" ) if( apDrivers[i]->m_sMountPoint != "/" )
FDB->AddFile( asDrivers[i].m_sMountPoint, 0, 0 ); FDB->AddFile( apDrivers[i]->m_sMountPoint, 0, 0 );
} }
}; };
static RageFileDriverMountpoints *g_Mountpoints = NULL; static RageFileDriverMountpoints *g_Mountpoints = NULL;
@@ -233,10 +233,10 @@ RageFileManager::RageFileManager( CString argv0 )
g_Mutex = new RageEvent("RageFileManager"); g_Mutex = new RageEvent("RageFileManager");
g_Mountpoints = new RageFileDriverMountpoints; g_Mountpoints = new RageFileDriverMountpoints;
LoadedDriver ld; LoadedDriver *pLoadedDriver = new LoadedDriver;
ld.m_pDriver = g_Mountpoints; pLoadedDriver->m_pDriver = g_Mountpoints;
ld.m_sMountPoint = "/"; pLoadedDriver->m_sMountPoint = "/";
g_Drivers.push_back( ld ); g_pDrivers.push_back( pLoadedDriver );
/* The mount path is unused, but must be nonempty. */ /* The mount path is unused, but must be nonempty. */
RageFileManager::Mount( "mem", "(cache)", "/@mem" ); RageFileManager::Mount( "mem", "(cache)", "/@mem" );
@@ -314,11 +314,14 @@ RageFileManager::~RageFileManager()
{ {
/* Note that drivers can use previously-loaded drivers, eg. to load a ZIP /* Note that drivers can use previously-loaded drivers, eg. to load a ZIP
* from the FS. Unload drivers in reverse order. */ * from the FS. Unload drivers in reverse order. */
for( int i = g_Drivers.size()-1; i >= 0; --i ) for( int i = g_pDrivers.size()-1; i >= 0; --i )
delete g_Drivers[i].m_pDriver; {
g_Drivers.clear(); delete g_pDrivers[i]->m_pDriver;
delete g_pDrivers[i];
}
g_pDrivers.clear();
// delete g_Mountpoints; // g_Mountpoints was in g_Drivers // delete g_Mountpoints; // g_Mountpoints was in g_pDrivers
g_Mountpoints = NULL; g_Mountpoints = NULL;
delete g_Mutex; delete g_Mutex;
@@ -357,33 +360,33 @@ void RageFileManager::GetDirListing( CString sPath, CStringArray &AddTo, bool bO
{ {
NormalizePath( sPath ); NormalizePath( sPath );
vector<LoadedDriver> aDriverList; vector<LoadedDriver *> apDriverList;
ReferenceAllDrivers( aDriverList ); ReferenceAllDrivers( apDriverList );
for( unsigned i = 0; i < aDriverList.size(); ++i ) for( unsigned i = 0; i < apDriverList.size(); ++i )
{ {
LoadedDriver &ld = aDriverList[i]; LoadedDriver *pLoadedDriver = apDriverList[i];
const CString p = ld.GetPath( sPath ); const CString p = pLoadedDriver->GetPath( sPath );
if( p.size() == 0 ) if( p.size() == 0 )
continue; continue;
const unsigned OldStart = AddTo.size(); const unsigned OldStart = AddTo.size();
ld.m_pDriver->GetDirListing( p, AddTo, bOnlyDirs, bReturnPathToo ); pLoadedDriver->m_pDriver->GetDirListing( p, AddTo, bOnlyDirs, bReturnPathToo );
/* If returning the path, prepend the mountpoint name to the files this driver returned. */ /* If returning the path, prepend the mountpoint name to the files this driver returned. */
if( bReturnPathToo && ld.m_sMountPoint.size() > 0 ) if( bReturnPathToo && pLoadedDriver->m_sMountPoint.size() > 0 )
{ {
for( unsigned j = OldStart; j < AddTo.size(); ++j ) for( unsigned j = OldStart; j < AddTo.size(); ++j )
{ {
/* Skip the trailing slash on the mountpoint; there's already a slash there. */ /* Skip the trailing slash on the mountpoint; there's already a slash there. */
CString &sPath = AddTo[j]; CString &sPath = AddTo[j];
sPath.insert( 0, ld.m_sMountPoint, ld.m_sMountPoint.size()-1 ); sPath.insert( 0, pLoadedDriver->m_sMountPoint, pLoadedDriver->m_sMountPoint.size()-1 );
} }
} }
} }
UnreferenceAllDrivers( aDriverList ); UnreferenceAllDrivers( apDriverList );
/* More than one driver might return the same file. Remove duplicates (case- /* More than one driver might return the same file. Remove duplicates (case-
* insensitively). */ * insensitively). */
@@ -394,25 +397,25 @@ void RageFileManager::GetDirListing( CString sPath, CStringArray &AddTo, bool bO
bool RageFileManager::Remove( CString sPath ) bool RageFileManager::Remove( CString sPath )
{ {
vector<LoadedDriver> aDriverList; vector<LoadedDriver *> apDriverList;
ReferenceAllDrivers( aDriverList ); ReferenceAllDrivers( apDriverList );
NormalizePath( sPath ); NormalizePath( sPath );
/* Multiple drivers may have the same file. */ /* Multiple drivers may have the same file. */
bool bDeleted = false; bool bDeleted = false;
for( unsigned i = 0; i < aDriverList.size(); ++i ) for( unsigned i = 0; i < apDriverList.size(); ++i )
{ {
const CString p = aDriverList[i].GetPath( sPath ); const CString p = apDriverList[i]->GetPath( sPath );
if( p.size() == 0 ) if( p.size() == 0 )
continue; continue;
bool ret = aDriverList[i].m_pDriver->Remove( p ); bool ret = apDriverList[i]->m_pDriver->Remove( p );
if( ret ) if( ret )
bDeleted = true; bDeleted = true;
} }
UnreferenceAllDrivers( aDriverList ); UnreferenceAllDrivers( apDriverList );
return bDeleted; return bDeleted;
} }
@@ -445,11 +448,11 @@ static void AdjustMountpoint( CString &sMountPoint )
} }
static void AddFilesystemDriver( const LoadedDriver *pLoadedDriver, bool bAddToEnd ) static void AddFilesystemDriver( LoadedDriver *pLoadedDriver, bool bAddToEnd )
{ {
g_Mutex->Lock(); g_Mutex->Lock();
g_Drivers.insert( bAddToEnd? g_Drivers.end():g_Drivers.begin(), *pLoadedDriver ); g_pDrivers.insert( bAddToEnd? g_pDrivers.end():g_pDrivers.begin(), pLoadedDriver );
g_Mountpoints->LoadFromDrivers( g_Drivers ); g_Mountpoints->LoadFromDrivers( g_pDrivers );
g_Mutex->Unlock(); g_Mutex->Unlock();
} }
@@ -480,13 +483,13 @@ void RageFileManager::Mount( CString sType, CString sRoot, CString sMountPoint,
CHECKPOINT; CHECKPOINT;
LoadedDriver ld; LoadedDriver *pLoadedDriver = new LoadedDriver;
ld.m_pDriver = pDriver; pLoadedDriver->m_pDriver = pDriver;
ld.m_sType = sType; pLoadedDriver->m_sType = sType;
ld.m_sRoot = sRoot; pLoadedDriver->m_sRoot = sRoot;
ld.m_sMountPoint = sMountPoint; pLoadedDriver->m_sMountPoint = sMountPoint;
AddFilesystemDriver( &ld, bAddToEnd ); AddFilesystemDriver( pLoadedDriver, bAddToEnd );
} }
/* Mount a custom filesystem. */ /* Mount a custom filesystem. */
@@ -494,13 +497,13 @@ void RageFileManager::Mount( RageFileDriver *pDriver, CString sMountPoint, bool
{ {
AdjustMountpoint( sMountPoint ); AdjustMountpoint( sMountPoint );
LoadedDriver ld; LoadedDriver *pLoadedDriver = new LoadedDriver;
ld.m_pDriver = pDriver; pLoadedDriver->m_pDriver = pDriver;
ld.m_sType = ""; pLoadedDriver->m_sType = "";
ld.m_sRoot = ""; pLoadedDriver->m_sRoot = "";
ld.m_sMountPoint = sMountPoint; pLoadedDriver->m_sMountPoint = sMountPoint;
AddFilesystemDriver( &ld, bAddToEnd ); AddFilesystemDriver( pLoadedDriver, bAddToEnd );
} }
void RageFileManager::Unmount( CString sType, CString sRoot, CString sMountPoint ) void RageFileManager::Unmount( CString sType, CString sRoot, CString sMountPoint )
@@ -511,42 +514,43 @@ void RageFileManager::Unmount( CString sType, CString sRoot, CString sMountPoint
if( sMountPoint.size() && sMountPoint.Right(1) != "/" ) if( sMountPoint.size() && sMountPoint.Right(1) != "/" )
sMountPoint += '/'; sMountPoint += '/';
/* Find all drivers we want to delete. Remove them from g_Drivers, and move them /* Find all drivers we want to delete. Remove them from g_pDrivers, and move them
* into aDriverListToUnmount. */ * into aDriverListToUnmount. */
vector<LoadedDriver> aDriverListToUnmount; vector<LoadedDriver *> apDriverListToUnmount;
g_Mutex->Lock(); g_Mutex->Lock();
for( unsigned i = 0; i < g_Drivers.size(); ++i ) for( unsigned i = 0; i < g_pDrivers.size(); ++i )
{ {
if( !sType.empty() && g_Drivers[i].m_sType.CompareNoCase( sType ) ) if( !sType.empty() && g_pDrivers[i]->m_sType.CompareNoCase( sType ) )
continue; continue;
if( !sRoot.empty() && g_Drivers[i].m_sRoot.CompareNoCase( sRoot ) ) if( !sRoot.empty() && g_pDrivers[i]->m_sRoot.CompareNoCase( sRoot ) )
continue; continue;
if( !sMountPoint.empty() && g_Drivers[i].m_sMountPoint.CompareNoCase( sMountPoint ) ) if( !sMountPoint.empty() && g_pDrivers[i]->m_sMountPoint.CompareNoCase( sMountPoint ) )
continue; continue;
++g_Drivers[i].m_iRefs; ++g_pDrivers[i]->m_iRefs;
aDriverListToUnmount.push_back( g_Drivers[i] ); apDriverListToUnmount.push_back( g_pDrivers[i] );
g_Drivers.erase( g_Drivers.begin()+i ); g_pDrivers.erase( g_pDrivers.begin()+i );
--i; --i;
} }
g_Mountpoints->LoadFromDrivers( g_Drivers ); g_Mountpoints->LoadFromDrivers( g_pDrivers );
g_Mutex->Unlock(); g_Mutex->Unlock();
/* Now we have a list of drivers to remove. */ /* Now we have a list of drivers to remove. */
while( aDriverListToUnmount.size() ) while( apDriverListToUnmount.size() )
{ {
/* If the driver has more than one reference, somebody other than us is /* If the driver has more than one reference, somebody other than us is
* using it; wait for that operation to complete. Note that two Unmount() * using it; wait for that operation to complete. Note that two Unmount()
* calls that want to remove the same mountpoint will deadlock here. */ * calls that want to remove the same mountpoint will deadlock here. */
g_Mutex->Lock(); g_Mutex->Lock();
while( aDriverListToUnmount[0].m_iRefs > 1 ) while( apDriverListToUnmount[0]->m_iRefs > 1 )
g_Mutex->Wait(); g_Mutex->Wait();
g_Mutex->Unlock(); g_Mutex->Unlock();
delete aDriverListToUnmount[0].m_pDriver; delete apDriverListToUnmount[0]->m_pDriver;
aDriverListToUnmount.erase( aDriverListToUnmount.begin() ); delete apDriverListToUnmount[0];
apDriverListToUnmount.erase( apDriverListToUnmount.begin() );
} }
} }
@@ -572,8 +576,8 @@ bool RageFileManager::IsMounted( CString MountPoint )
{ {
LockMut( *g_Mutex ); LockMut( *g_Mutex );
for( unsigned i = 0; i < g_Drivers.size(); ++i ) for( unsigned i = 0; i < g_pDrivers.size(); ++i )
if( !g_Drivers[i].m_sMountPoint.CompareNoCase( MountPoint ) ) if( !g_pDrivers[i]->m_sMountPoint.CompareNoCase( MountPoint ) )
return true; return true;
return false; return false;
@@ -583,12 +587,12 @@ void RageFileManager::GetLoadedDrivers( vector<DriverLocation> &asMounts )
{ {
LockMut( *g_Mutex ); LockMut( *g_Mutex );
for( unsigned i = 0; i < g_Drivers.size(); ++i ) for( unsigned i = 0; i < g_pDrivers.size(); ++i )
{ {
DriverLocation l; DriverLocation l;
l.MountPoint = g_Drivers[i].m_sMountPoint; l.MountPoint = g_pDrivers[i]->m_sMountPoint;
l.Type = g_Drivers[i].m_sType; l.Type = g_pDrivers[i]->m_sType;
l.Root = g_Drivers[i].m_sRoot; l.Root = g_pDrivers[i]->m_sRoot;
asMounts.push_back( l ); asMounts.push_back( l );
} }
} }
@@ -599,19 +603,19 @@ void RageFileManager::FlushDirCache( CString sPath )
if( sPath == "" ) if( sPath == "" )
{ {
for( unsigned i = 0; i < g_Drivers.size(); ++i ) for( unsigned i = 0; i < g_pDrivers.size(); ++i )
g_Drivers[i].m_pDriver->FlushDirCache( "" ); g_pDrivers[i]->m_pDriver->FlushDirCache( "" );
return; return;
} }
/* Flush a specific path. */ /* Flush a specific path. */
NormalizePath( sPath ); NormalizePath( sPath );
for( unsigned i = 0; i < g_Drivers.size(); ++i ) for( unsigned i = 0; i < g_pDrivers.size(); ++i )
{ {
const CString path = g_Drivers[i].GetPath( sPath ); const CString &path = g_pDrivers[i]->GetPath( sPath );
if( path.size() == 0 ) if( path.size() == 0 )
continue; continue;
g_Drivers[i].m_pDriver->FlushDirCache( path ); g_pDrivers[i]->m_pDriver->FlushDirCache( path );
} }
} }
@@ -619,22 +623,23 @@ RageFileManager::FileType RageFileManager::GetFileType( CString sPath )
{ {
NormalizePath( sPath ); NormalizePath( sPath );
vector<LoadedDriver> aDriverList; vector<LoadedDriver *> apDriverList;
ReferenceAllDrivers( aDriverList ); ReferenceAllDrivers( apDriverList );
for( unsigned i = 0; i < aDriverList.size(); ++i ) RageFileManager::FileType ret = TYPE_NONE;
for( unsigned i = 0; i < apDriverList.size(); ++i )
{ {
const CString p = aDriverList[i].GetPath( sPath ); const CString p = apDriverList[i]->GetPath( sPath );
if( p.size() == 0 ) if( p.size() == 0 )
continue; continue;
FileType ret = aDriverList[i].m_pDriver->GetFileType( p ); ret = apDriverList[i]->m_pDriver->GetFileType( p );
if( ret != TYPE_NONE ) if( ret != TYPE_NONE )
return ret; break;
} }
UnreferenceAllDrivers( aDriverList ); UnreferenceAllDrivers( apDriverList );
return TYPE_NONE; return ret;
} }
@@ -642,42 +647,44 @@ int RageFileManager::GetFileSizeInBytes( CString sPath )
{ {
NormalizePath( sPath ); NormalizePath( sPath );
vector<LoadedDriver> aDriverList; vector<LoadedDriver *> apDriverList;
ReferenceAllDrivers( aDriverList ); ReferenceAllDrivers( apDriverList );
for( unsigned i = 0; i < aDriverList.size(); ++i ) int iRet = -1;
for( unsigned i = 0; i < apDriverList.size(); ++i )
{ {
const CString p = aDriverList[i].GetPath( sPath ); const CString p = apDriverList[i]->GetPath( sPath );
if( p.size() == 0 ) if( p.size() == 0 )
continue; continue;
int ret = aDriverList[i].m_pDriver->GetFileSizeInBytes( p ); iRet = apDriverList[i]->m_pDriver->GetFileSizeInBytes( p );
if( ret != -1 ) if( iRet != -1 )
return ret; break;
} }
UnreferenceAllDrivers( aDriverList ); UnreferenceAllDrivers( apDriverList );
return -1; return iRet;
} }
int RageFileManager::GetFileHash( CString sPath ) int RageFileManager::GetFileHash( CString sPath )
{ {
NormalizePath( sPath ); NormalizePath( sPath );
vector<LoadedDriver> aDriverList; vector<LoadedDriver *> apDriverList;
ReferenceAllDrivers( aDriverList ); ReferenceAllDrivers( apDriverList );
for( unsigned i = 0; i < aDriverList.size(); ++i ) int iRet = -1;
for( unsigned i = 0; i < apDriverList.size(); ++i )
{ {
const CString p = aDriverList[i].GetPath( sPath ); const CString p = apDriverList[i]->GetPath( sPath );
if( p.size() == 0 ) if( p.size() == 0 )
continue; continue;
int ret = aDriverList[i].m_pDriver->GetFileHash( p ); iRet = apDriverList[i]->m_pDriver->GetFileHash( p );
if( ret != -1 ) if( iRet != -1 )
return ret; break;
} }
UnreferenceAllDrivers( aDriverList ); UnreferenceAllDrivers( apDriverList );
return -1; return iRet;
} }
static bool SortBySecond( const pair<int,int> &a, const pair<int,int> &b ) static bool SortBySecond( const pair<int,int> &a, const pair<int,int> &b )
@@ -726,12 +733,12 @@ RageFileBasic *RageFileManager::Open( CString sPath, int mode, int &err )
RageFileBasic *RageFileManager::OpenForReading( CString sPath, int mode, int &err ) RageFileBasic *RageFileManager::OpenForReading( CString sPath, int mode, int &err )
{ {
vector<LoadedDriver> aDriverList; vector<LoadedDriver *> apDriverList;
ReferenceAllDrivers( aDriverList ); ReferenceAllDrivers( apDriverList );
for( unsigned i = 0; i < aDriverList.size(); ++i ) for( unsigned i = 0; i < apDriverList.size(); ++i )
{ {
LoadedDriver &ld = aDriverList[i]; LoadedDriver &ld = *apDriverList[i];
const CString path = ld.GetPath( sPath ); const CString path = ld.GetPath( sPath );
if( path.size() == 0 ) if( path.size() == 0 )
continue; continue;
@@ -739,7 +746,7 @@ RageFileBasic *RageFileManager::OpenForReading( CString sPath, int mode, int &er
RageFileBasic *ret = ld.m_pDriver->Open( path, mode, error ); RageFileBasic *ret = ld.m_pDriver->Open( path, mode, error );
if( ret ) if( ret )
{ {
UnreferenceAllDrivers( aDriverList ); UnreferenceAllDrivers( apDriverList );
return ret; return ret;
} }
@@ -748,7 +755,7 @@ RageFileBasic *RageFileManager::OpenForReading( CString sPath, int mode, int &er
if( error != ENOENT ) if( error != ENOENT )
err = error; err = error;
} }
UnreferenceAllDrivers( aDriverList ); UnreferenceAllDrivers( apDriverList );
return NULL; return NULL;
} }
@@ -774,13 +781,13 @@ RageFileBasic *RageFileManager::OpenForWriting( CString sPath, int mode, int &iE
* If the given path can not be created, return -1. This happens if a path * If the given path can not be created, return -1. This happens if a path
* that needs to be a directory is a file, or vice versa. * that needs to be a directory is a file, or vice versa.
*/ */
vector<LoadedDriver> aDriverList; vector<LoadedDriver *> apDriverList;
ReferenceAllDrivers( aDriverList ); ReferenceAllDrivers( apDriverList );
vector< pair<int,int> > Values; vector< pair<int,int> > Values;
for( unsigned i = 0; i < aDriverList.size(); ++i ) for( unsigned i = 0; i < apDriverList.size(); ++i )
{ {
LoadedDriver &ld = aDriverList[i]; LoadedDriver &ld = *apDriverList[i];
const CString path = ld.GetPath( sPath ); const CString path = ld.GetPath( sPath );
if( path.size() == 0 ) if( path.size() == 0 )
continue; continue;
@@ -798,14 +805,17 @@ RageFileBasic *RageFileManager::OpenForWriting( CString sPath, int mode, int &iE
for( unsigned i = 0; i < Values.size(); ++i ) for( unsigned i = 0; i < Values.size(); ++i )
{ {
const int iDriver = Values[i].first; const int iDriver = Values[i].first;
LoadedDriver &ld = aDriverList[iDriver]; LoadedDriver &ld = *apDriverList[iDriver];
const CString sDriverPath = ld.GetPath( sPath ); const CString sDriverPath = ld.GetPath( sPath );
ASSERT( !sDriverPath.empty() ); ASSERT( !sDriverPath.empty() );
int iThisError; int iThisError;
RageFileBasic *pRet = ld.m_pDriver->Open( sDriverPath, mode, iThisError ); RageFileBasic *pRet = ld.m_pDriver->Open( sDriverPath, mode, iThisError );
if( pRet ) if( pRet )
{
UnreferenceAllDrivers( apDriverList );
return pRet; return pRet;
}
/* The drivers are in order of priority; if they all return error, return the /* The drivers are in order of priority; if they all return error, return the
* first. Never return ERROR_WRITING_NOT_SUPPORTED. */ * first. Never return ERROR_WRITING_NOT_SUPPORTED. */
@@ -816,7 +826,7 @@ RageFileBasic *RageFileManager::OpenForWriting( CString sPath, int mode, int &iE
if( !iError ) if( !iError )
iError = EEXIST; /* no driver could write */ iError = EEXIST; /* no driver could write */
UnreferenceAllDrivers( aDriverList ); UnreferenceAllDrivers( apDriverList );
return NULL; return NULL;
} }