00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "TransferFile.h"
00025
00026 #ifdef _DEBUG
00027 #undef THIS_FILE
00028 static char THIS_FILE[]=__FILE__;
00029 #define new DEBUG_NEW
00030 #endif
00031
00032 CTransferFiles TransferFiles;
00033
00034
00036
00037
00038 CTransferFiles::CTransferFiles()
00039 {
00040 }
00041
00042 CTransferFiles::~CTransferFiles()
00043 {
00044 Close();
00045 }
00046
00048
00049
00050 CTransferFile* CTransferFiles::Open(LPCTSTR pszFile, BOOL bWrite, BOOL bCreate)
00051 {
00052 CSingleLock pLock( &m_pSection, TRUE );
00053 CTransferFile* pFile = NULL;
00054
00055 if ( m_pMap.Lookup( pszFile, (void*&)pFile ) )
00056 {
00057 if ( bWrite && ! pFile->EnsureWrite() ) return NULL;
00058 }
00059 else
00060 {
00061 pFile = new CTransferFile( pszFile );
00062
00063 if ( ! pFile->Open( bWrite, bCreate ) )
00064 {
00065 delete pFile;
00066 return NULL;
00067 }
00068
00069 m_pMap.SetAt( pFile->m_sPath, pFile );
00070 }
00071
00072 pFile->AddRef();
00073
00074 return pFile;
00075 }
00076
00078
00079
00080 void CTransferFiles::Close()
00081 {
00082 CSingleLock pLock( &m_pSection, TRUE );
00083
00084 for ( POSITION pos = m_pMap.GetStartPosition() ; pos ; )
00085 {
00086 CTransferFile* pFile;
00087 CString strPath;
00088
00089 m_pMap.GetNextAssoc( pos, strPath, (void*&)pFile );
00090 delete pFile;
00091 }
00092
00093 m_pMap.RemoveAll();
00094 m_pDeferred.RemoveAll();
00095 }
00096
00098
00099
00100 void CTransferFiles::CommitDeferred()
00101 {
00102 CSingleLock pLock( &m_pSection, TRUE );
00103
00104 for ( POSITION pos = m_pDeferred.GetHeadPosition() ; pos ; )
00105 {
00106 CTransferFile* pFile = (CTransferFile*)m_pDeferred.GetNext( pos );
00107 pFile->DeferredWrite( TRUE );
00108 }
00109
00110 m_pDeferred.RemoveAll();
00111 }
00112
00114
00115
00116 void CTransferFiles::QueueDeferred(CTransferFile* pFile)
00117 {
00118 if ( NULL == m_pDeferred.Find( pFile ) ) m_pDeferred.AddTail( pFile );
00119 }
00120
00122
00123
00124 void CTransferFiles::Remove(CTransferFile* pFile)
00125 {
00126 m_pMap.RemoveKey( pFile->m_sPath );
00127 if ( POSITION pos = m_pDeferred.Find( pFile ) ) m_pDeferred.RemoveAt( pos );
00128 }
00129
00130
00132
00133
00134 CTransferFile::CTransferFile(LPCTSTR pszPath)
00135 {
00136 m_sPath = pszPath;
00137 m_hFile = INVALID_HANDLE_VALUE;
00138 m_nReference = 0;
00139 m_bWrite = FALSE;
00140 m_nDeferred = 0;
00141 }
00142
00143 CTransferFile::~CTransferFile()
00144 {
00145 if ( m_hFile != INVALID_HANDLE_VALUE )
00146 {
00147 DeferredWrite();
00148 CloseHandle( m_hFile );
00149 }
00150 }
00151
00153
00154
00155 void CTransferFile::AddRef()
00156 {
00157 CSingleLock pLock( &TransferFiles.m_pSection, TRUE );
00158 m_nReference++;
00159 }
00160
00161 void CTransferFile::Release(BOOL bWrite)
00162 {
00163 CSingleLock pLock( &TransferFiles.m_pSection, TRUE );
00164
00165 if ( ! --m_nReference )
00166 {
00167 TransferFiles.Remove( this );
00168 delete this;
00169 return;
00170 }
00171
00172 if ( m_bWrite && bWrite ) CloseWrite();
00173 }
00174
00176
00177
00178 HANDLE CTransferFile::GetHandle(BOOL bWrite)
00179 {
00180 CSingleLock pLock( &TransferFiles.m_pSection, TRUE );
00181
00182 if ( bWrite && ! m_bWrite ) return INVALID_HANDLE_VALUE;
00183 if ( m_nDeferred > 0 ) DeferredWrite();
00184
00185 return m_hFile;
00186 }
00187
00188 BOOL CTransferFile::IsOpen()
00189 {
00190 return m_hFile != INVALID_HANDLE_VALUE;
00191 }
00192
00194
00195
00196 BOOL CTransferFile::Open(BOOL bWrite, BOOL bCreate)
00197 {
00198 if ( m_hFile != INVALID_HANDLE_VALUE ) return FALSE;
00199
00200 DWORD dwDesiredAccess = GENERIC_READ;
00201 if ( bWrite ) dwDesiredAccess |= GENERIC_WRITE;
00202
00203 DWORD dwShare = FILE_SHARE_READ|FILE_SHARE_WRITE;
00204 if ( theApp.m_bNT ) dwShare |= FILE_SHARE_DELETE;
00205 DWORD dwCreation = bCreate ? CREATE_ALWAYS : OPEN_EXISTING;
00206
00207 #if 1
00208 m_hFile = CreateFile( m_sPath, dwDesiredAccess, dwShare,
00209 NULL, dwCreation, FILE_ATTRIBUTE_NORMAL, NULL );
00210 #else
00211
00212 m_hFile = CreateFile( _T("C:\\Junk\\Incomplete.bin"), dwDesiredAccess,
00213 dwShare, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
00214 #endif
00215
00216 if ( m_hFile != INVALID_HANDLE_VALUE ) m_bWrite = bWrite;
00217
00218 return m_hFile != INVALID_HANDLE_VALUE;
00219 }
00220
00222
00223
00224 BOOL CTransferFile::EnsureWrite()
00225 {
00226 if ( m_hFile == INVALID_HANDLE_VALUE ) return FALSE;
00227 if ( m_bWrite ) return TRUE;
00228
00229 CloseHandle( m_hFile );
00230 m_hFile = INVALID_HANDLE_VALUE;
00231
00232 if ( Open( TRUE, FALSE ) ) return TRUE;
00233
00234 Open( FALSE, FALSE );
00235
00236 return FALSE;
00237 }
00238
00239 BOOL CTransferFile::CloseWrite()
00240 {
00241 if ( m_hFile == INVALID_HANDLE_VALUE ) return FALSE;
00242 if ( ! m_bWrite ) return TRUE;
00243
00244 DeferredWrite();
00245
00246 CloseHandle( m_hFile );
00247 m_hFile = INVALID_HANDLE_VALUE;
00248
00249 return Open( FALSE, FALSE );
00250 }
00251
00253
00254
00255 BOOL CTransferFile::Read(QWORD nOffset, LPVOID pBuffer, QWORD nBuffer, QWORD* pnRead)
00256 {
00257 CSingleLock pLock( &TransferFiles.m_pSection, TRUE );
00258
00259 *pnRead = 0;
00260 if ( m_hFile == INVALID_HANDLE_VALUE ) return FALSE;
00261 if ( m_nDeferred > 0 ) DeferredWrite();
00262
00263 DWORD nOffsetLow = (DWORD)( nOffset & 0x00000000FFFFFFFF );
00264 DWORD nOffsetHigh = (DWORD)( ( nOffset & 0xFFFFFFFF00000000 ) >> 32 );
00265 SetFilePointer( m_hFile, nOffsetLow, (PLONG)&nOffsetHigh, FILE_BEGIN );
00266
00267 return ReadFile( m_hFile, pBuffer, (DWORD)nBuffer, (DWORD*)pnRead, NULL );
00268 }
00269
00271
00272
00273 #define DEFERRED_THRESHOLD (20*1024*1024)
00274
00275 BOOL CTransferFile::Write(QWORD nOffset, LPCVOID pBuffer, QWORD nBuffer, QWORD* pnWritten)
00276 {
00277 CSingleLock pLock( &TransferFiles.m_pSection, TRUE );
00278
00279 *pnWritten = 0;
00280 if ( m_hFile == INVALID_HANDLE_VALUE ) return FALSE;
00281 if ( ! m_bWrite ) return FALSE;
00282
00283 if ( nOffset > DEFERRED_THRESHOLD )
00284 {
00285 DWORD nSizeHigh = 0;
00286 QWORD nSize = (QWORD)GetFileSize( m_hFile, &nSizeHigh );
00287 nSize |= ( (QWORD)nSizeHigh << 32 );
00288
00289 if ( nOffset > nSize && nOffset - nSize > DEFERRED_THRESHOLD )
00290 {
00291 TransferFiles.QueueDeferred( this );
00292
00293 if ( m_nDeferred >= DEFERRED_MAX ) DeferredWrite();
00294
00295 DefWrite* pWrite = &m_pDeferred[ m_nDeferred++ ];
00296
00297 pWrite->m_nOffset = nOffset;
00298 pWrite->m_nLength = (DWORD)nBuffer;
00299 pWrite->m_pBuffer = new BYTE[ (DWORD)nBuffer ];
00300 CopyMemory( pWrite->m_pBuffer, pBuffer, (DWORD)nBuffer );
00301 *pnWritten = nBuffer;
00302
00303 theApp.Message( MSG_TEMP, _T("Deferred write of %I64i bytes at %I64i"), nBuffer, nOffset );
00304
00305 return TRUE;
00306 }
00307 }
00308
00309 DWORD nOffsetLow = (DWORD)( nOffset & 0x00000000FFFFFFFF );
00310 DWORD nOffsetHigh = (DWORD)( ( nOffset & 0xFFFFFFFF00000000 ) >> 32 );
00311 SetFilePointer( m_hFile, nOffsetLow, (PLONG)&nOffsetHigh, FILE_BEGIN );
00312
00313 return WriteFile( m_hFile, pBuffer, (DWORD)nBuffer, (LPDWORD)pnWritten, NULL );
00314 }
00315
00317
00318
00319 void CTransferFile::DeferredWrite(BOOL bOffline)
00320 {
00321 if ( m_nDeferred == 0 ) return;
00322 if ( m_hFile == INVALID_HANDLE_VALUE ) return;
00323 if ( ! m_bWrite ) return;
00324
00325 DefWrite* pWrite = m_pDeferred;
00326
00327 for ( int nDeferred = 0 ; nDeferred < m_nDeferred ; nDeferred++, pWrite++ )
00328 {
00329 theApp.Message( MSG_TEMP, _T("Committing deferred write of %lu bytes at %I64i"),
00330 pWrite->m_nLength, pWrite->m_nOffset );
00331
00332 DWORD nOffsetLow = (DWORD)( pWrite->m_nOffset & 0x00000000FFFFFFFF );
00333 DWORD nOffsetHigh = (DWORD)( ( pWrite->m_nOffset & 0xFFFFFFFF00000000 ) >> 32 );
00334 SetFilePointer( m_hFile, nOffsetLow, (PLONG)&nOffsetHigh, FILE_BEGIN );
00335
00336 DWORD nWritten = 0;
00337 WriteFile( m_hFile, pWrite->m_pBuffer, pWrite->m_nLength, &nWritten, NULL );
00338
00339 delete [] pWrite->m_pBuffer;
00340 }
00341
00342 m_nDeferred = 0;
00343 theApp.Message( MSG_TEMP, _T("Commit finished") );
00344 }