Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

TransferFile.cpp

Go to the documentation of this file.
00001 //
00002 // TransferFile.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 // CTransferFiles construction
00037 
00038 CTransferFiles::CTransferFiles()
00039 {
00040 }
00041 
00042 CTransferFiles::~CTransferFiles()
00043 {
00044         Close();
00045 }
00046 
00048 // CTransferFiles open a file
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 // CTransferFiles close all files
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 // CTransferFiles commit deferred writes
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 // CTransferFiles queue for deferred write
00115 
00116 void CTransferFiles::QueueDeferred(CTransferFile* pFile)
00117 {
00118         if ( NULL == m_pDeferred.Find( pFile ) ) m_pDeferred.AddTail( pFile );
00119 }
00120 
00122 // CTransferFiles remove a single file
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 // CTransferFile construction
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 // CTransferFile reference counts
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 // CTransferFile handle
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 // CTransferFile open
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         // Testing
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 // CTransferFile write access management
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 // CTransferFile read
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 // CTransferFile write (with deferred extension)
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 // CTransferFile deferred writes
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 }

Generated on Thu Dec 15 10:39:50 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2