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

FragmentedFile.cpp

Go to the documentation of this file.
00001 //
00002 // FragmentedFile.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 "Settings.h"
00025 #include "FragmentedFile.h"
00026 #include "TransferFile.h"
00027 
00028 #ifdef _DEBUG
00029 #undef THIS_FILE
00030 static char THIS_FILE[]=__FILE__;
00031 #define new DEBUG_NEW
00032 #endif
00033 
00034 #undef _WIN32_WINNT
00035 #define _WIN32_WINNT 0x0500
00036 #include <winioctl.h>
00037 
00038 
00040 // CFragmentedFile construction
00041 
00042 CFragmentedFile::CFragmentedFile()
00043 : m_pFile( NULL ), m_nUnflushed( 0 ), m_oFList( 0 )
00044 { }
00045 
00046 CFragmentedFile::~CFragmentedFile()
00047 {
00048         Clear();
00049 }
00050 
00052 // CFragmentedFile create
00053 
00054 BOOL CFragmentedFile::Create(LPCTSTR pszFile, QWORD nLength)
00055 {
00056         if ( m_pFile != NULL || m_oFList.limit() > 0 ) return FALSE;
00057         if ( nLength == 0 ) return FALSE;
00058         
00059         m_pFile = TransferFiles.Open( pszFile, TRUE, TRUE );
00060         if ( m_pFile == NULL ) return FALSE;
00061 
00062     m_oFList.swap( FF::SimpleFragmentList( nLength ) );
00063 
00064     m_oFList.insert( FF::SimpleFragment( 0, nLength ) );
00065         
00066         if ( Settings.Downloads.SparseThreshold > 0 && theApp.m_bNT &&
00067                  nLength >= Settings.Downloads.SparseThreshold * 1024 )
00068         {
00069                 DWORD dwOut = 0;
00070                 HANDLE hFile = m_pFile->GetHandle( TRUE );
00071                 
00072                 if ( ! DeviceIoControl( hFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwOut, NULL ) )
00073                 {
00074                         DWORD nError = GetLastError();
00075                         theApp.Message( MSG_ERROR, _T("Unable to set sparse file: \"%s\", Win32 error %x."), pszFile, nError );
00076                 }
00077         }
00078         
00079         return TRUE;
00080 }
00081 
00083 // CFragmentedFile open
00084 
00085 BOOL CFragmentedFile::Open(LPCTSTR pszFile)
00086 {
00087         if ( m_pFile != NULL || m_oFList.limit() == 0 ) return FALSE;
00088         
00089         m_pFile = TransferFiles.Open( pszFile, TRUE, FALSE );
00090         
00091         if ( m_pFile == NULL ) return FALSE;
00092         
00093         return TRUE;
00094 }
00095 
00097 // CFragmentedFile flush
00098 
00099 BOOL CFragmentedFile::Flush()
00100 {
00101         if ( m_nUnflushed == 0 ) return FALSE;
00102         if ( m_pFile == NULL || ! m_pFile->IsOpen() ) return FALSE;
00103         FlushFileBuffers( m_pFile->GetHandle() );
00104         m_nUnflushed = 0;
00105         return TRUE;
00106 }
00107 
00109 // CFragmentedFile close
00110 
00111 void CFragmentedFile::Close()
00112 {
00113         if ( m_pFile != NULL )
00114         {
00115                 m_pFile->Release( TRUE );
00116                 m_pFile = NULL;
00117                 m_nUnflushed = 0;
00118         }
00119 }
00120 
00122 // CFragmentedFile clear
00123 
00124 void CFragmentedFile::Clear()
00125 {
00126         Close();
00127 
00128     m_oFList.swap( FF::SimpleFragmentList( 0 ) );
00129 
00130 }
00131 
00133 // CFragmentedFile make complete
00134 
00135 BOOL CFragmentedFile::MakeComplete()
00136 {
00137         if ( m_oFList.empty() ) return FALSE;
00138 
00139     m_oFList.clear();
00140         
00141         if ( m_pFile != NULL )
00142         {
00143                 HANDLE hFile = m_pFile->GetHandle( TRUE );
00144                 
00145                 if ( hFile != INVALID_HANDLE_VALUE )
00146                 {
00147                         DWORD nSizeHigh = (DWORD)( m_oFList.limit() >> 32 );
00148                         DWORD nSizeLow  = (DWORD)( m_oFList.limit() & 0xFFFFFFFF );
00149                         SetFilePointer( hFile, nSizeLow, (PLONG)&nSizeHigh, FILE_BEGIN );
00150                         SetEndOfFile( hFile );
00151                 }
00152         }
00153         
00154         return TRUE;
00155 }
00156 
00158 // CFragmentedFile serialize
00159 
00160 void CFragmentedFile::Serialize(CArchive& ar, int nVersion)
00161 {
00162         if ( ar.IsStoring() )
00163         {
00164         SerializeOut1( ar, m_oFList );
00165         }
00166         else
00167         {
00168                 ASSERT( m_oFList.limit() == 0 );
00169                 
00170         SerializeIn1( ar, m_oFList, nVersion );
00171         }
00172 }
00173 
00175 // CFragmentedFile simple intersections
00176 
00177 BOOL CFragmentedFile::IsPositionRemaining(QWORD nOffset) const
00178 {
00179     return hasPosition( m_oFList, nOffset );
00180 }
00181 
00182 BOOL CFragmentedFile::DoesRangeOverlap(QWORD nOffset, QWORD nLength) const
00183 {
00184     return overlaps( m_oFList, FF::SimpleFragment( nOffset, nOffset + nLength ) );
00185 }
00186 
00187 QWORD CFragmentedFile::GetRangeOverlap(QWORD nOffset, QWORD nLength) const
00188 {
00189     return overlappingSum( m_oFList, FF::SimpleFragment( nOffset, nOffset + nLength ) );
00190 }
00191 
00193 // CFragmentedFile write some data to a range
00194 
00195 BOOL CFragmentedFile::WriteRange(QWORD nOffset, LPCVOID pData, QWORD nLength)
00196 {
00197         if ( m_pFile == NULL ) return FALSE;
00198         if ( nLength == 0 ) return TRUE;
00199 
00200     FF::SimpleFragment oMatch( nOffset, nOffset + nLength );
00201     FF::SimpleFragmentList::ConstIteratorPair
00202         pMatches = m_oFList.overlappingRange( oMatch );
00203     if ( pMatches.first == pMatches.second ) return FALSE;
00204 
00205         QWORD nResult, nProcessed = 0;
00206 
00207     for ( ; pMatches.first != pMatches.second; ++pMatches.first )
00208     {
00209         QWORD nStart = std::max( pMatches.first->begin(), oMatch.begin() );
00210         nResult = std::min( pMatches.first->end(), oMatch.end() ) - nStart;
00211 
00212         const char* pSource
00213             = static_cast< const char* >( pData ) + nStart - oMatch.begin();
00214 
00215         if ( !m_pFile->Write( nStart, pSource, nResult, &nResult ) ) return FALSE;
00216 
00217         nProcessed += nResult;
00218         }
00219         
00220         m_nUnflushed += nProcessed;
00221     m_oFList.erase( oMatch );
00222         return nProcessed > 0;
00223 }
00224 
00226 // CFragmentedFile read some data from a range
00227 
00228 BOOL CFragmentedFile::ReadRange(QWORD nOffset, LPVOID pData, QWORD nLength)
00229 {
00230         if ( m_pFile == NULL ) return FALSE;
00231         if ( nLength == 0 ) return TRUE;
00232         
00233         if ( DoesRangeOverlap( nOffset, nLength ) ) return FALSE;
00234         
00235         QWORD nRead = 0;
00236         m_pFile->Read( nOffset, pData, nLength, &nRead );
00237         
00238         return nRead == nLength;
00239 }
00240 
00242 // CFragmentedFile invalidate a range
00243 
00244 QWORD CFragmentedFile::InvalidateRange(QWORD nOffset, QWORD nLength)
00245 {
00246     return m_oFList.insert( FF::SimpleFragment( nOffset, nOffset + nLength ) );
00247 }

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