do memory card write test in a separate thread

This commit is contained in:
Chris Danford
2004-04-07 01:18:11 +00:00
parent 7135f8cc1d
commit d93f758024
9 changed files with 340 additions and 20 deletions
@@ -0,0 +1,91 @@
#include "global.h"
#include "MemoryCardDriverThreaded.h"
#include "RageLog.h"
#include "RageUtil.h"
#include "RageFileManager.h"
int MemoryCardDriverThreaded::MountThread_Start( void *p )
{
((MemoryCardDriverThreaded*)p)->MountThreadMain();
return 0;
}
template<class T>
bool VectorsAreEqual( const T &a, const T &b )
{
if( a.size() != b.size() )
return false;
for( unsigned i=0; i<a.size(); i++ )
{
if( a[i] != b[i] )
return false;
}
return true;
}
MemoryCardDriverThreaded::MemoryCardDriverThreaded() :
m_mutexStorageDevices("StorageDevices")
{
m_bShutdown = false;
}
void MemoryCardDriverThreaded::StartThread()
{
m_threadMemoryCardMount.SetName("MemoryCardMount");
m_threadMemoryCardMount.Create( MountThread_Start, this );
}
MemoryCardDriverThreaded::~MemoryCardDriverThreaded()
{
m_bShutdown = true;
LOG->Trace( "Shutting down Mount thread..." );
m_threadMemoryCardMount.Wait();
LOG->Trace( "Mount thread shut down." );
}
bool MemoryCardDriverThreaded::StorageDevicesChanged()
{
LockMut( m_mutexStorageDevices );
if( m_bStorageDevicesChanged )
{
m_bStorageDevicesChanged = false;
return true;
}
else
{
return false;
}
}
void MemoryCardDriverThreaded::GetStorageDevices( vector<UsbStorageDevice>& vDevicesOut )
{
LockMut( m_mutexStorageDevices );
vDevicesOut.clear();
for( unsigned i=0; i<m_vStorageDevices.size(); i++ )
vDevicesOut.push_back( m_vStorageDevices[i] );
}
bool MemoryCardDriverThreaded::MountAndTestWrite( UsbStorageDevice* pDevice, CString sMountPoint )
{
LockMut( m_mutexStorageDevices );
vector<UsbStorageDeviceEx>::const_iterator iter = find( m_vStorageDevices.begin(), m_vStorageDevices.end(), *pDevice );
if( iter == m_vStorageDevices.end() )
{
LOG->Warn( "Tried to mount a memory card that is no longer connected" );
return false;
}
if( !iter->bWriteTestSucceeded )
return false;
this->Mount( pDevice, sMountPoint );
return true;
}
/*
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
* Chris Danford
*/
@@ -0,0 +1,57 @@
#ifndef MemoryCardDriverThreaded_H
#define MemoryCardDriverThreaded_H 1
/*
-----------------------------------------------------------------------------
Class: MemoryCardDriverThreaded
Desc: Adapter .
Copyright (c) 2001-2004 by the person(s) listed below. All rights reserved.
Chris Danford
-----------------------------------------------------------------------------
*/
#include "MemoryCardDriver.h"
#include "RageThreads.h"
struct UsbStorageDeviceEx : public UsbStorageDevice
{
UsbStorageDeviceEx() { MakeBlank(); }
void MakeBlank()
{
bWriteTestSucceeded = false;
}
bool bWriteTestSucceeded;
};
class MemoryCardDriverThreaded : public MemoryCardDriver
{
public:
MemoryCardDriverThreaded();
~MemoryCardDriverThreaded();
void StartThread(); // call this in the derived constructor to start the mounting thread
virtual bool StorageDevicesChanged();
virtual void GetStorageDevices( vector<UsbStorageDevice>& vStorageDevicesOut );
virtual bool MountAndTestWrite( UsbStorageDevice* pDevice, CString sMountPoint );
static int MountThread_Start( void *p );
protected:
virtual void MountThreadMain() = 0;
virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint ) = 0;
RageThread m_threadMemoryCardMount;
bool m_bShutdown;
vector<UsbStorageDeviceEx> m_vStorageDevices;
bool m_bStorageDevicesChanged;
RageMutex m_mutexStorageDevices; // protects the above two
};
#endif
/*
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
* Chris Danford
*/
@@ -0,0 +1,128 @@
#include "global.h"
#include "MemoryCardDriverThreaded_Windows.h"
#include "RageUtil.h"
#include <io.h>
#include <fcntl.h>
#include "RageFileManager.h"
#include "RageLog.h"
#include <windows.h>
MemoryCardDriverThreaded_Windows::MemoryCardDriverThreaded_Windows()
{
StartThread();
}
typedef const CString& CCStringRef;
bool TestWrite( CCStringRef sDrive )
{
// TODO: Use RageFileDirect here to detect ready state?
TCHAR szVolumeNameBuffer[MAX_PATH];
DWORD dwVolumeSerialNumber;
DWORD dwMaximumComponentLength;
DWORD lpFileSystemFlags;
TCHAR szFileSystemNameBuffer[MAX_PATH];
BOOL bReady = GetVolumeInformation(
sDrive,
szVolumeNameBuffer,
sizeof(szVolumeNameBuffer),
&dwVolumeSerialNumber,
&dwMaximumComponentLength,
&lpFileSystemFlags,
szFileSystemNameBuffer,
sizeof(szFileSystemNameBuffer) );
if( !bReady )
return false;
// Try to write a file.
// TODO: Can we use RageFile for this?
CString sFile = sDrive + "temp";
FILE* fp = fopen( sFile, "w" );
if( fp == NULL )
return false;
fclose( fp );
remove( sFile );
return true;
}
void MemoryCardDriverThreaded_Windows::MountThreadMain()
{
DWORD dwLastLogicalDrives = 0;
while( !m_bShutdown )
{
DWORD dwNewLogicalDrives = ::GetLogicalDrives();
if( dwNewLogicalDrives != dwLastLogicalDrives )
{
vector<UsbStorageDeviceEx> vNewStorageDevices;
const int MAX_DRIVES = 26;
for( int i=2; i<MAX_DRIVES; i++ ) // skip 'a:" and "b:"
{
DWORD mask = (1 << i);
if( dwNewLogicalDrives & mask ) // drive letter is valid
{
CString sDrive = ssprintf( "%c:\\", 'a'+i%26 );
LOG->Warn( "Found drive %s", sDrive.c_str() );
if( GetDriveType(sDrive) == DRIVE_REMOVABLE ) // is a removable drive
{
UsbStorageDeviceEx usbd;
usbd.sOsMountDir = sDrive;
usbd.bWriteTestSucceeded = TestWrite( sDrive );
vNewStorageDevices.push_back( usbd );
}
}
}
{
LockMut( m_mutexStorageDevices );
m_bStorageDevicesChanged = true;
m_vStorageDevices = vNewStorageDevices;
}
}
dwLastLogicalDrives = dwNewLogicalDrives;
::Sleep( 100 );
}
}
void MemoryCardDriverThreaded_Windows::Mount( UsbStorageDevice* pDevice, CString sMountPoint )
{
ASSERT( !pDevice->sOsMountDir.empty() );
/* Unmount any previous mounts for this mountpoint. */
vector<RageFileManager::DriverLocation> Mounts;
FILEMAN->GetLoadedDrivers( Mounts );
for( unsigned i = 0; i < Mounts.size(); ++i )
{
if( Mounts[i].Type.CompareNoCase( "dir" ) )
continue; // wrong type
if( Mounts[i].Root.CompareNoCase( pDevice->sOsMountDir ) )
continue; // wrong root
FILEMAN->Unmount( Mounts[i].Type, Mounts[i].Root, Mounts[i].MountPoint );
}
FILEMAN->Mount( "dir", pDevice->sOsMountDir, sMountPoint.c_str() );
LOG->Trace( "FILEMAN->Mount %s %s", pDevice->sOsMountDir.c_str(), sMountPoint.c_str() );
}
void MemoryCardDriverThreaded_Windows::Unmount( UsbStorageDevice* pDevice, CString sMountPoint )
{
// nothing to do here...
}
void MemoryCardDriverThreaded_Windows::Flush( UsbStorageDevice* pDevice )
{
// Do we need anything here? I don't lose data if ejecting
// soon after a write. From the activity LED, it looks like
// Windows flushes automatically every ~2 seconds. -Chris
}
/*
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
* Chris Danford
*/
@@ -0,0 +1,23 @@
#ifndef MemoryCardDriverThreaded_Windows_H
#define MemoryCardDriverThreaded_Windows_H 1
#include "MemoryCardDriverThreaded.h"
class MemoryCardDriverThreaded_Windows : public MemoryCardDriverThreaded
{
public:
MemoryCardDriverThreaded_Windows();
virtual void Unmount( UsbStorageDevice* pDevice, CString sMountPoint );
virtual void Flush( UsbStorageDevice* pDevice );
protected:
virtual void MountThreadMain();
virtual void Mount( UsbStorageDevice* pDevice, CString sMountPoint );
};
#endif
/*
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
* Chris Danford
*/