Fisheye: Tag 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c refers to a dead (removed) revision in file `src/ch/Device IO.h'. Fisheye: No comparison available. Pass `N' to diff? Index: src/ch/TBasePathData.cpp =================================================================== diff -u -r5fd6beaad9f1eccb664b997d151acb59961e4827 -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/TBasePathData.cpp (.../TBasePathData.cpp) (revision 5fd6beaad9f1eccb664b997d151acb59961e4827) +++ src/ch/TBasePathData.cpp (.../TBasePathData.cpp) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -30,15 +30,13 @@ TBasePathData::TBasePathData() : m_bMove(true), - m_iDriveNumber(-2), - m_iBufferIndex(-1) + m_iDriveNumber(-2) { } TBasePathData::TBasePathData(const TBasePathData& rEntry) : m_bMove(rEntry.m_bMove), m_iDriveNumber(rEntry.m_iDriveNumber), - m_iBufferIndex(rEntry.m_iBufferIndex), m_pathDst(rEntry.m_pathDst) { } Index: src/ch/TBasePathData.h =================================================================== diff -u -r5fd6beaad9f1eccb664b997d151acb59961e4827 -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/TBasePathData.h (.../TBasePathData.h) (revision 5fd6beaad9f1eccb664b997d151acb59961e4827) +++ src/ch/TBasePathData.h (.../TBasePathData.h) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -40,10 +40,6 @@ void SetDriveNumber(int iDriveNumber) { m_iDriveNumber = iDriveNumber; } bool IsDriveNumberSet() const { return m_iDriveNumber != -2; } - int GetBufferIndex() { return m_iBufferIndex; } - void SetBufferIndex(int iBufferIndex) { m_iBufferIndex = iBufferIndex; } - bool IsBufferIndexSet() const { return m_iBufferIndex != -1; } - void SetDestinationPath(const chcore::TSmartPath& strPath); chcore::TSmartPath GetDestinationPath() const; bool IsDestinationPathSet() const { return !m_pathDst.IsEmpty(); } @@ -55,7 +51,6 @@ bool m_bMove; // specifies if we can use MoveFile (if will be moved) int m_iDriveNumber; // disk number (default -1 - none) - int m_iBufferIndex; // buffer number, with which we'll copy this data (default 0) chcore::TSmartPath m_pathDst; // dest path }; Index: src/ch/TLocalFilesystem.cpp =================================================================== diff -u -rcd9791a359fbb6fc6bdc5757f4b1647a71c397c2 -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision cd9791a359fbb6fc6bdc5757f4b1647a71c397c2) +++ src/ch/TLocalFilesystem.cpp (.../TLocalFilesystem.cpp) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -27,6 +27,7 @@ #include "DataBuffer.h" #include #include "FileSupport.h" +#include void TLocalFilesystem::GetDriveData(const chcore::TSmartPath& spPath, int* piDrvNum, UINT* puiDrvType) { @@ -212,6 +213,97 @@ return pathInput; } +TLocalFilesystem::EPathsRelation TLocalFilesystem::GetPathsRelation(const chcore::TSmartPath& pathFirst, const chcore::TSmartPath& pathSecond) +{ + if(pathFirst.IsEmpty() || pathSecond.IsEmpty()) + THROW(_T("Invalid pointer"), 0, 0, 0); + + // get information about both paths + int iFirstDriveNumber = 0; + UINT uiFirstDriveType = 0; + GetDriveData(pathFirst, &iFirstDriveNumber, &uiFirstDriveType); + + int iSecondDriveNumber = 0; + UINT uiSecondDriveType = 0; + GetDriveData(pathSecond, &iSecondDriveNumber, &uiSecondDriveType); + + // what kind of relation... + EPathsRelation eRelation = eRelation_Other; + if(uiFirstDriveType == DRIVE_REMOTE || uiSecondDriveType == DRIVE_REMOTE) + eRelation = eRelation_Network; + else if(uiFirstDriveType == DRIVE_CDROM || uiSecondDriveType == DRIVE_CDROM) + eRelation = eRelation_CDRom; + else if(uiFirstDriveType == DRIVE_FIXED && uiSecondDriveType == DRIVE_FIXED) + { + // two hdd's - is this the same physical disk ? + wchar_t wchFirstDrive = pathFirst.GetDriveLetter(); + wchar_t wchSecondDrive = pathSecond.GetDriveLetter(); + + if(wchFirstDrive == L'\0' || wchSecondDrive == L'\0') + THROW(_T("Fixed drive without drive letter"), 0, 0, 0); + + if(wchFirstDrive == wchSecondDrive) + eRelation = eRelation_SinglePhysicalDisk; + else + { + DWORD dwFirstPhysicalDisk = GetPhysicalDiskNumber(wchFirstDrive); + DWORD dwSecondPhysicalDisk = GetPhysicalDiskNumber(wchSecondDrive); + if(dwFirstPhysicalDisk == std::numeric_limits::max() || dwSecondPhysicalDisk == std::numeric_limits::max()) + THROW(_T("Problem with physical disk detection"), 0, 0, 0); + + if(dwFirstPhysicalDisk == dwSecondPhysicalDisk) + eRelation = eRelation_SinglePhysicalDisk; + else + eRelation = eRelation_TwoPhysicalDisks; + } + } + + return eRelation; +} + +DWORD TLocalFilesystem::GetPhysicalDiskNumber(wchar_t wchDrive) +{ + { + boost::shared_lock lock(m_lockDriveLetterToPhysicalDisk); + + std::map::iterator iterMap = m_mapDriveLetterToPhysicalDisk.find(wchDrive); + if(iterMap != m_mapDriveLetterToPhysicalDisk.end()) + return (*iterMap).second; + } + + wchar_t szDrive[] = { L'\\', L'\\', L'.', L'\\', wchDrive, L':', L'\0' }; + + HANDLE hDevice = CreateFile(szDrive, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if(hDevice == INVALID_HANDLE_VALUE) + return std::numeric_limits::max(); + + // buffer for data (cannot make member nor static because this function might be called by many threads at once) + // buffer is larger than one extent to allow getting information in multi-extent volumes (raid?) + const int stSize = sizeof(VOLUME_DISK_EXTENTS) + 20 * sizeof(DISK_EXTENT); + boost::shared_array spData(new BYTE[stSize]); + + VOLUME_DISK_EXTENTS* pVolumeDiskExtents = (VOLUME_DISK_EXTENTS*)spData.get(); + DWORD dwBytesReturned = 0; + BOOL bResult = DeviceIoControl(hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, pVolumeDiskExtents, stSize, &dwBytesReturned, NULL); + if(!bResult) + return std::numeric_limits::max(); + + CloseHandle(hDevice); + + if(pVolumeDiskExtents->NumberOfDiskExtents == 0) + return std::numeric_limits::max(); + + DISK_EXTENT* pDiskExtent = &pVolumeDiskExtents->Extents[0]; + + boost::unique_lock lock(m_lockDriveLetterToPhysicalDisk); + m_mapDriveLetterToPhysicalDisk.insert(std::make_pair(wchDrive, pDiskExtent->DiskNumber)); + + return pDiskExtent->DiskNumber; +} + +///////////////////////////////////////////////////////////////////////////////////// +// class TLocalFilesystemFind + TLocalFilesystemFind::TLocalFilesystemFind(const chcore::TSmartPath& pathDir, const chcore::TSmartPath& pathMask) : m_pathDir(pathDir), m_pathMask(pathMask), @@ -257,7 +349,7 @@ return true; } } - while(::FindNextFile(m_hFind, &wfd)); + while(m_hFind != INVALID_HANDLE_VALUE && ::FindNextFile(m_hFind, &wfd)); // checking m_hFind in case other thread changed it (it shouldn't happen though) Close(); } Index: src/ch/TLocalFilesystem.h =================================================================== diff -u -r886c32a98f09ae8dc24ceb6b27e5c8a75104954e -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision 886c32a98f09ae8dc24ceb6b27e5c8a75104954e) +++ src/ch/TLocalFilesystem.h (.../TLocalFilesystem.h) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -24,6 +24,8 @@ #define __TLOCALFILESYSTEM_H__ #include "../libchcore/TPath.h" +#include +#include class CFileInfo; typedef boost::shared_ptr CFileInfoPtr; @@ -36,6 +38,16 @@ class TLocalFilesystem { public: + enum EPathsRelation + { + eRelation_Network, // at least one of the paths is network one + eRelation_CDRom, // at least one of the paths relates to cd/dvd drive + eRelation_TwoPhysicalDisks, // paths lies on two separate physical disks + eRelation_SinglePhysicalDisk, // paths lies on the same physical disk + eRelation_Other // other type of relation + }; + +public: static void GetDriveData(const chcore::TSmartPath& spPath, int *piDrvNum, UINT *puiDrvType); static bool PathExist(chcore::TSmartPath strPath); // check for file or folder existence @@ -52,9 +64,16 @@ static TLocalFilesystemFind CreateFinderObject(const chcore::TSmartPath& pathDir, const chcore::TSmartPath& pathMask); static TLocalFilesystemFile CreateFileObject(); + EPathsRelation GetPathsRelation(const chcore::TSmartPath& pathFirst, const chcore::TSmartPath& pathSecond); + private: static chcore::TSmartPath PrependPathExtensionIfNeeded(const chcore::TSmartPath& pathInput); + DWORD GetPhysicalDiskNumber(wchar_t wchDrive); +private: + std::map m_mapDriveLetterToPhysicalDisk; // caches drive letter -> physical disk number + boost::shared_mutex m_lockDriveLetterToPhysicalDisk; + friend class TLocalFilesystemFind; friend class TLocalFilesystemFile; }; Index: src/ch/TSubTaskContext.cpp =================================================================== diff -u -r6dc950d4d76107421ff6eb62069b70f20bcc450e -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/TSubTaskContext.cpp (.../TSubTaskContext.cpp) (revision 6dc950d4d76107421ff6eb62069b70f20bcc450e) +++ src/ch/TSubTaskContext.cpp (.../TSubTaskContext.cpp) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -24,16 +24,18 @@ #include "TSubTaskContext.h" TSubTaskContext::TSubTaskContext(chcore::TTaskDefinition& rTaskDefinition, TBasePathDataContainer& rBasePathDataContainer, CFileInfoArray& rFilesCache, TTaskLocalStats& rTaskLocalStats, - TTaskBasicProgressInfo& rTaskBasicProgressInfo, TTaskConfigTracker& rCfgTracker, icpf::log_file& rLog, chcore::IFeedbackHandler* piFeedbackHandler, TWorkerThreadController& rThreadController) : -m_rTaskDefinition(rTaskDefinition), -m_rBasePathDataContainer(rBasePathDataContainer), -m_rFilesCache(rFilesCache), -m_rTaskLocalStats(rTaskLocalStats), -m_rTaskBasicProgressInfo(rTaskBasicProgressInfo), -m_rCfgTracker(rCfgTracker), -m_rLog(rLog), -m_piFeedbackHandler(piFeedbackHandler), -m_rThreadController(rThreadController) + TTaskBasicProgressInfo& rTaskBasicProgressInfo, TTaskConfigTracker& rCfgTracker, icpf::log_file& rLog, chcore::IFeedbackHandler* piFeedbackHandler, + TWorkerThreadController& rThreadController, TLocalFilesystem& rfsLocal) : + m_rTaskDefinition(rTaskDefinition), + m_rBasePathDataContainer(rBasePathDataContainer), + m_rFilesCache(rFilesCache), + m_rTaskLocalStats(rTaskLocalStats), + m_rTaskBasicProgressInfo(rTaskBasicProgressInfo), + m_rCfgTracker(rCfgTracker), + m_rLog(rLog), + m_piFeedbackHandler(piFeedbackHandler), + m_rThreadController(rThreadController), + m_rfsLocal(rfsLocal) { } Index: src/ch/TSubTaskContext.h =================================================================== diff -u -r6dc950d4d76107421ff6eb62069b70f20bcc450e -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/TSubTaskContext.h (.../TSubTaskContext.h) (revision 6dc950d4d76107421ff6eb62069b70f20bcc450e) +++ src/ch/TSubTaskContext.h (.../TSubTaskContext.h) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -36,6 +36,7 @@ class TTaskLocalStats; class TTaskConfigTracker; class TTaskBasicProgressInfo; +class TLocalFilesystem; /////////////////////////////////////////////////////////////////////////// // TSubTaskContext @@ -45,7 +46,7 @@ public: TSubTaskContext(chcore::TTaskDefinition& rTaskDefinition, TBasePathDataContainer& rBasePathDataContainer, CFileInfoArray& rFilesCache, TTaskLocalStats& rTaskLocalStats, TTaskBasicProgressInfo& rTaskBasicProgressInfo, TTaskConfigTracker& rCfgTracker, icpf::log_file& rLog, - chcore::IFeedbackHandler* piFeedbackHandler, TWorkerThreadController& rThreadController); + chcore::IFeedbackHandler* piFeedbackHandler, TWorkerThreadController& rThreadController, TLocalFilesystem& rfsLocal); ~TSubTaskContext(); chcore::TTaskDefinition& GetTaskDefinition() { return m_rTaskDefinition; } @@ -75,6 +76,9 @@ TWorkerThreadController& GetThreadController() { return m_rThreadController; } const TWorkerThreadController& GetThreadController() const { return m_rThreadController; } + TLocalFilesystem& GetLocalFilesystem() { return m_rfsLocal; } + const TLocalFilesystem& GetLocalFilesystem() const { return m_rfsLocal; } + private: chcore::TTaskDefinition& m_rTaskDefinition; @@ -91,6 +95,9 @@ // configuration changes tracking TTaskConfigTracker& m_rCfgTracker; + // local filesystem access functions + TLocalFilesystem& m_rfsLocal; + // additional data icpf::log_file& m_rLog; Index: src/ch/TSubTaskCopyMove.cpp =================================================================== diff -u -r633a533cb6e741d44fe28aa56339e1d2709b1b27 -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) +++ src/ch/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -28,7 +28,6 @@ #include "task.h" #include "TLocalFilesystem.h" #include "FeedbackHandler.h" -#include "Device IO.h" // assume max sectors of 4kB (for rounding) #define MAXSECTORSIZE 4096 @@ -275,51 +274,31 @@ int TSubTaskCopyMove::GetBufferIndex(const CFileInfoPtr& spFileInfo) { - TBasePathDataContainer& rSrcPathsInfo = GetContext().GetBasePathDataContainer(); - chcore::TTaskDefinition& rTaskDefinition = GetContext().GetTaskDefinition(); - if(!spFileInfo) THROW(_T("Invalid pointer"), 0, 0, 0); - if(spFileInfo->GetSrcIndex() == std::numeric_limits::max()) - THROW(_T("Received non-relative (standalone) path info"), 0, 0, 0); - // check if this information has already been stored - size_t stBaseIndex = spFileInfo->GetSrcIndex(); - if(stBaseIndex >= rSrcPathsInfo.GetCount()) - THROW(_T("Index out of bounds"), 0, 0, 0); + chcore::TSmartPath pathSource = spFileInfo->GetFullFilePath(); + chcore::TSmartPath pathDestination = GetContext().GetTaskDefinition().GetDestinationPath(); - TBasePathDataPtr spPathData = rSrcPathsInfo.GetAt(stBaseIndex); - if(spPathData->IsBufferIndexSet()) - return spPathData->GetBufferIndex(); + TLocalFilesystem::EPathsRelation eRelation = GetContext().GetLocalFilesystem().GetPathsRelation(pathSource, pathDestination); + switch(eRelation) + { + case TLocalFilesystem::eRelation_Network: + return BI_LAN; - // buffer index wasn't cached previously - read it now - int iDriveNumber = 0; - UINT uiDriveType = 0; - int iDstDriveNumber = 0; - UINT uiDstDriveType = 0; - TLocalFilesystem::GetDriveData(rTaskDefinition.GetSourcePathAt(stBaseIndex), &iDriveNumber, &uiDriveType); - TLocalFilesystem::GetDriveData(rTaskDefinition.GetDestinationPath(), &iDstDriveNumber, &uiDstDriveType); + case TLocalFilesystem::eRelation_CDRom: + return BI_CD; - // what kind of buffer - int iBufferIndex = BI_DEFAULT; - if(uiDriveType == DRIVE_REMOTE || uiDstDriveType == DRIVE_REMOTE) - iBufferIndex = BI_LAN; - else if(uiDriveType == DRIVE_CDROM || uiDstDriveType == DRIVE_CDROM) - iBufferIndex = BI_CD; - else if(uiDriveType == DRIVE_FIXED && uiDstDriveType == DRIVE_FIXED) - { - // two hdd's - is this the same physical disk ? - if(iDriveNumber == iDstDriveNumber || IsSamePhysicalDisk(iDriveNumber, iDstDriveNumber)) - iBufferIndex = BI_ONEDISK; - else - iBufferIndex = BI_TWODISKS; - } - else - iBufferIndex = BI_DEFAULT; + case TLocalFilesystem::eRelation_TwoPhysicalDisks: + return BI_TWODISKS; - spPathData->SetBufferIndex(iBufferIndex); + case TLocalFilesystem::eRelation_SinglePhysicalDisk: + return BI_ONEDISK; - return iBufferIndex; + //case eRelation_Other: + default: + return BI_DEFAULT; + } } TSubTaskBase::ESubOperationResult TSubTaskCopyMove::CustomCopyFileFB(CUSTOM_COPY_PARAMS* pData) Index: src/ch/ch.vc90.vcproj =================================================================== diff -u -r888524d8a33af49ee8e8ce83f98017323046f109 -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 888524d8a33af49ee8e8ce83f98017323046f109) +++ src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -423,10 +423,6 @@ > - - Index: src/ch/task.cpp =================================================================== diff -u -r642028606eae63b6bf4549ab02a2c5438db04aa6 -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/task.cpp (.../task.cpp) (revision 642028606eae63b6bf4549ab02a2c5438db04aa6) +++ src/ch/task.cpp (.../task.cpp) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -698,7 +698,7 @@ m_localStats.EnableTimeTracking(); // prepare context for subtasks - TSubTaskContext tSubTaskContext(m_tTaskDefinition, m_arrSourcePathsInfo, m_files, m_localStats, m_tTaskBasicProgressInfo, m_cfgTracker, m_log, m_piFeedbackHandler, m_workerThread); + TSubTaskContext tSubTaskContext(m_tTaskDefinition, m_arrSourcePathsInfo, m_files, m_localStats, m_tTaskBasicProgressInfo, m_cfgTracker, m_log, m_piFeedbackHandler, m_workerThread, m_fsLocal); for(; stSubOperationIndex < m_tTaskDefinition.GetOperationPlan().GetSubOperationsCount() && eResult == TSubTaskBase::eSubResult_Continue; ++stSubOperationIndex) { Index: src/ch/task.h =================================================================== diff -u -r0cd863a6e51b221c4f7bf6e7b83ddfc43a5d433f -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/ch/task.h (.../task.h) (revision 0cd863a6e51b221c4f7bf6e7b83ddfc43a5d433f) +++ src/ch/task.h (.../task.h) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -32,6 +32,7 @@ #include "TTaskLocalStats.h" #include "TTaskGlobalStats.h" #include "TBasicProgressInfo.h" +#include "TLocalFilesystem.h" // enum representing current processing state of the task enum ETaskCurrentState @@ -245,6 +246,9 @@ // other helpers icpf::log_file m_log; ///< Log file where task information will be stored + // Local filesystem access + TLocalFilesystem m_fsLocal; + /// Thread controlling object TWorkerThreadController m_workerThread; Index: src/libchcore/TPath.cpp =================================================================== diff -u -r5fd6beaad9f1eccb664b997d151acb59961e4827 -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/libchcore/TPath.cpp (.../TPath.cpp) (revision 5fd6beaad9f1eccb664b997d151acb59961e4827) +++ src/libchcore/TPath.cpp (.../TPath.cpp) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -616,6 +616,29 @@ } // ============================================================================ +/// chcore::TSmartPath::GetDriveLetter +/// @date 2011/07/17 +/// +/// @brief Retrieves drive letter from path. +/// @return Drive letter or zero in case path does not have drive. +// ============================================================================ +wchar_t TSmartPath::GetDriveLetter() const +{ + if(!m_pPath) + return L'\0'; + + if(m_pPath->m_strPath.GetLength() >= 2 && m_pPath->m_strPath.GetAt(1) == _T(':')) + { + wchar_t wchDrive = m_pPath->m_strPath.GetAt(0); + if(wchDrive >= L'a' && wchDrive <= L'z') + wchDrive = L'A' + wchDrive - L'a'; + return wchDrive; + } + + return L'\0'; +} + +// ============================================================================ /// chcore::TSmartPath::IsServerName /// @date 2011/04/05 /// Index: src/libchcore/TPath.h =================================================================== diff -u -r5fd6beaad9f1eccb664b997d151acb59961e4827 -r4c09a2d7ab35a30114ff2b7c4db12bc413bf538c --- src/libchcore/TPath.h (.../TPath.h) (revision 5fd6beaad9f1eccb664b997d151acb59961e4827) +++ src/libchcore/TPath.h (.../TPath.h) (revision 4c09a2d7ab35a30114ff2b7c4db12bc413bf538c) @@ -100,6 +100,7 @@ bool IsDrive() const; bool HasDrive() const; TSmartPath GetDrive() const; // c: for c:\windows\test.txt + wchar_t GetDriveLetter() const; // 'c' for c:\windows\test.txt, null for non-drive based paths bool IsServerName() const; bool HasServerName() const;