Index: src/ch/StatusDlg.cpp =================================================================== diff -u -N -ref313208b7c4a113907f2f72ee0b73406081501d -r1fa2eb7e39e2f8d84868d421fe1c4f0afc58d353 --- src/ch/StatusDlg.cpp (.../StatusDlg.cpp) (revision ef313208b7c4a113907f2f72ee0b73406081501d) +++ src/ch/StatusDlg.cpp (.../StatusDlg.cpp) (revision 1fa2eb7e39e2f8d84868d421fe1c4f0afc58d353) @@ -286,7 +286,7 @@ // transfer if (m_i64LastProcessed == 0) // if first time - show average - m_strTemp=GetSizeString( td.m_lTimeElapsed ? td.m_ullProcessedSize/td.m_lTimeElapsed : 0, m_szData, _MAX_PATH); // last avg + m_strTemp=GetSizeString( td.m_timeElapsed ? td.m_ullProcessedSize/td.m_timeElapsed : 0, m_szData, _MAX_PATH); // last avg else if ( (dwCurrentTime-m_dwLastUpdate) != 0) m_strTemp=GetSizeString( (static_cast(td.m_ullProcessedSize) - static_cast(m_i64LastProcessed))/(static_cast(dwCurrentTime-m_dwLastUpdate)/1000.0), m_szData, _MAX_PATH); @@ -295,14 +295,14 @@ // avg transfer GetDlgItem(IDC_TRANSFER_STATIC)->SetWindowText(m_strTemp+_T("/s (")+CString(GetResManager().LoadString(IDS_AVERAGEWORD_STRING)) - +CString(GetSizeString(td.m_lTimeElapsed ? td.m_ullProcessedSize/td.m_lTimeElapsed : 0, m_szData, _MAX_PATH))+_T("/s )") + +CString(GetSizeString(td.m_timeElapsed ? td.m_ullProcessedSize/td.m_timeElapsed : 0, m_szData, _MAX_PATH))+_T("/s )") ); // elapsed time / estimated total time (estimated time left) - FormatTime(td.m_lTimeElapsed, m_szTimeBuffer1, 40); - long lTotalTime = (td.m_ullProcessedSize == 0) ? 0 : (long)(td.m_ullSizeAll * td.m_lTimeElapsed / td.m_ullProcessedSize); - FormatTime(lTotalTime, m_szTimeBuffer2, 40); - FormatTime(std::max(0l, lTotalTime - td.m_lTimeElapsed), m_szTimeBuffer3, 40); + FormatTime(td.m_timeElapsed, m_szTimeBuffer1, 40); + time_t timeTotal = (td.m_ullProcessedSize == 0) ? 0 : (long)(td.m_ullSizeAll * td.m_timeElapsed / td.m_ullProcessedSize); + FormatTime(timeTotal, m_szTimeBuffer2, 40); + FormatTime(std::max((time_t)0l, timeTotal - td.m_timeElapsed), m_szTimeBuffer3, 40); _sntprintf(m_szData, _MAX_PATH, _T("%s / %s (%s)"), m_szTimeBuffer1, m_szTimeBuffer2, m_szTimeBuffer3); GetDlgItem(IDC_TIME_STATIC)->SetWindowText(m_szData); @@ -664,22 +664,24 @@ return 0; } -LPTSTR CStatusDlg::FormatTime(long lSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize) +LPTSTR CStatusDlg::FormatTime(time_t timeSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize) { - long lDays=lSeconds/86400; - lSeconds%=86400; - long lHours=lSeconds/3600; - lSeconds%=3600; - long lMinutes=lSeconds/60; - lSeconds%=60; + long lDays = boost::numeric_cast(timeSeconds/86400); + timeSeconds %= 86400; + long lHours = boost::numeric_cast(timeSeconds/3600); + timeSeconds %= 3600; + long lMinutes = boost::numeric_cast(timeSeconds/60); + timeSeconds %= 60; - if (lDays != 0) - _sntprintf(lpszBuffer, stMaxBufferSize, _T("%02d:%02d:%02d:%02d"), lDays, lHours, lMinutes, lSeconds); + if(lDays != 0) + _sntprintf(lpszBuffer, stMaxBufferSize, _T("%02d:%02d:%02d:%02d"), lDays, lHours, lMinutes, timeSeconds); else + { if (lHours != 0) - _sntprintf(lpszBuffer, stMaxBufferSize, _T("%02d:%02d:%02d"), lHours, lMinutes, lSeconds); + _sntprintf(lpszBuffer, stMaxBufferSize, _T("%02d:%02d:%02d"), lHours, lMinutes, timeSeconds); else - _sntprintf(lpszBuffer, stMaxBufferSize, _T("%02d:%02d"), lMinutes, lSeconds); + _sntprintf(lpszBuffer, stMaxBufferSize, _T("%02d:%02d"), lMinutes, timeSeconds); + } return lpszBuffer; } Index: src/ch/StatusDlg.h =================================================================== diff -u -N -ref313208b7c4a113907f2f72ee0b73406081501d -r1fa2eb7e39e2f8d84868d421fe1c4f0afc58d353 --- src/ch/StatusDlg.h (.../StatusDlg.h) (revision ef313208b7c4a113907f2f72ee0b73406081501d) +++ src/ch/StatusDlg.h (.../StatusDlg.h) (revision 1fa2eb7e39e2f8d84868d421fe1c4f0afc58d353) @@ -36,7 +36,7 @@ void PostCloseMessage(); void SetBufferSizesString(UINT uiValue, int iIndex); void RefreshStatus(); - LPTSTR FormatTime(long lSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize); + LPTSTR FormatTime(time_t timeSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize); int GetImageFromStatus(UINT nStatus); void ApplyButtonsState(); Index: src/ch/task.cpp =================================================================== diff -u -N -ref313208b7c4a113907f2f72ee0b73406081501d -r1fa2eb7e39e2f8d84868d421fe1c4f0afc58d353 --- src/ch/task.cpp (.../task.cpp) (revision ef313208b7c4a113907f2f72ee0b73406081501d) +++ src/ch/task.cpp (.../task.cpp) (revision 1fa2eb7e39e2f8d84868d421fe1c4f0afc58d353) @@ -170,7 +170,9 @@ m_prtGlobalStats(NULL), m_ullProcessedSize(0), m_ullTotalSize(0), - m_bTaskIsRunning(false) + m_bTaskIsRunning(false), + m_timeElapsed(0), + m_timeLast(-1) { } @@ -329,6 +331,55 @@ return m_bTaskIsRunning; } +void TTaskLocalStats::SetTimeElapsed(time_t timeElapsed) +{ + boost::unique_lock lock(m_lock); + m_timeElapsed = timeElapsed; +} + +time_t TTaskLocalStats::GetTimeElapsed() +{ + UpdateTime(); + + boost::shared_lock lock(m_lock); + return m_timeElapsed; +} + +void TTaskLocalStats::EnableTimeTracking() +{ + boost::upgrade_lock lock(m_lock); + if(m_timeLast == -1) + { + boost::upgrade_to_unique_lock lock_upgraded(lock); + m_timeLast = time(NULL); + } +} + +void TTaskLocalStats::DisableTimeTracking() +{ + UpdateTime(); + + boost::upgrade_lock lock(m_lock); + if(m_timeLast != -1) + { + boost::upgrade_to_unique_lock lock_upgraded(lock); + m_timeLast = -1; + } +} + +void TTaskLocalStats::UpdateTime() +{ + boost::upgrade_lock lock(m_lock); + if(m_timeLast != -1) + { + time_t timeCurrent = time(NULL); + + boost::upgrade_to_unique_lock lock_upgraded(lock); + m_timeElapsed += timeCurrent - m_timeLast; + m_timeLast = timeCurrent; + } +} + //////////////////////////////////////////////////////////////////////////// // CTask members CTask::CTask(chcore::IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID) : @@ -338,8 +389,6 @@ m_stCurrentIndex(0), m_nStatus(ST_NULL_STATUS), m_nPriority(THREAD_PRIORITY_NORMAL), - m_lTimeElapsed(0), - m_lLastTime(-1), m_ucCopies(1), m_ucCurrentCopy(0), m_uiResumeInterval(0), @@ -657,17 +706,19 @@ ar >> m_bsSizes; ar >> m_nPriority; - // this info could be calculated on load (low cost) - unsigned long long ullTotalSize = 0; + // this info could be calculated on load (low cost) + unsigned long long ullTotalSize = 0; ar >> ullTotalSize; - m_localStats.SetTotalSize(ullTotalSize); - - ar >> m_lTimeElapsed; + m_localStats.SetTotalSize(ullTotalSize); - // this info could be calculated on load (low cost) - unsigned long long ullProcessedSize = 0; + time_t timeElapsed = 0; + ar >> timeElapsed; + m_localStats.SetTimeElapsed(timeElapsed); + + // this info could be calculated on load (low cost) + unsigned long long ullProcessedSize = 0; ar >> ullProcessedSize; - m_localStats.SetProcessedSize(ullProcessedSize); + m_localStats.SetProcessedSize(ullProcessedSize); ar >> m_ucCurrentCopy; @@ -726,12 +777,13 @@ ar << m_bsSizes; ar << m_nPriority; - unsigned long long ullTotalSize = m_localStats.GetTotalSize(); + unsigned long long ullTotalSize = m_localStats.GetTotalSize(); ar << ullTotalSize; - ar << m_lTimeElapsed; + time_t timeElapsed = m_localStats.GetTimeElapsed(); + ar << timeElapsed; - unsigned long long ullProcessedSize = m_localStats.GetProcessedSize(); + unsigned long long ullProcessedSize = m_localStats.GetProcessedSize(); ar << ullProcessedSize; ar << m_ucCurrentCopy; @@ -801,7 +853,7 @@ KillThread(); SetStatus(0, ST_ERROR); SetStatus(ST_NULL_STATUS, ST_STEP_MASK); - m_lTimeElapsed=0; + m_localStats.SetTimeElapsed(0); SetCurrentIndex(0); SetCurrentCopy(0); BeginProcessing(); @@ -855,32 +907,32 @@ void CTask::GetSnapshot(TASK_DISPLAY_DATA *pData) { - boost::unique_lock lock(m_lock); + boost::unique_lock lock(m_lock); if(m_stCurrentIndex >= 0 && m_stCurrentIndex < m_files.GetSize()) - { - pData->m_strFullFilePath = m_files.GetAt(m_stCurrentIndex)->GetFullFilePath(); - pData->m_strFileName = m_files.GetAt(m_stCurrentIndex)->GetFileName(); - } + { + pData->m_strFullFilePath = m_files.GetAt(m_stCurrentIndex)->GetFullFilePath(); + pData->m_strFileName = m_files.GetAt(m_stCurrentIndex)->GetFileName(); + } else { if(m_files.GetSize() > 0) - { - pData->m_strFullFilePath = m_files.GetAt(0)->GetFullFilePath(); - pData->m_strFileName = m_files.GetAt(0)->GetFileName(); - } + { + pData->m_strFullFilePath = m_files.GetAt(0)->GetFullFilePath(); + pData->m_strFileName = m_files.GetAt(0)->GetFileName(); + } else { if(m_clipboard.GetSize() > 0) - { - pData->m_strFullFilePath = m_clipboard.GetAt(0)->GetPath(); - pData->m_strFileName = m_clipboard.GetAt(0)->GetFileName(); - } + { + pData->m_strFullFilePath = m_clipboard.GetAt(0)->GetPath(); + pData->m_strFileName = m_clipboard.GetAt(0)->GetFileName(); + } else - { - pData->m_strFullFilePath = GetResManager().LoadString(IDS_NONEINPUTFILE_STRING); - pData->m_strFileName = pData->m_strFullFilePath; - } + { + pData->m_strFullFilePath = GetResManager().LoadString(IDS_NONEINPUTFILE_STRING); + pData->m_strFileName = pData->m_strFullFilePath; + } } } @@ -903,7 +955,7 @@ pData->m_iCurrentBufferIndex=0; // percents - pData->m_nPercent = m_localStats.GetProgressInPercent(); + pData->m_nPercent = m_localStats.GetProgressInPercent(); // status string // first @@ -980,39 +1032,24 @@ } // time - UpdateTimeNL(); - pData->m_lTimeElapsed=m_lTimeElapsed; + pData->m_timeElapsed = m_localStats.GetTimeElapsed(); } -void CTask::CleanupAfterKill() -{ - boost::unique_lock lock(m_lock); - - CleanupAfterKillNL(); -} - void CTask::DeleteProgress(LPCTSTR lpszDirectory) { - m_lock.lock_shared(); + m_lock.lock_shared(); - CString strDel1 = lpszDirectory+m_strUniqueName+_T(".atd"); - CString strDel2 = lpszDirectory+m_strUniqueName+_T(".atp"); - CString strDel3 = lpszDirectory+m_strUniqueName+_T(".log"); + CString strDel1 = lpszDirectory+m_strUniqueName+_T(".atd"); + CString strDel2 = lpszDirectory+m_strUniqueName+_T(".atp"); + CString strDel3 = lpszDirectory+m_strUniqueName+_T(".log"); - m_lock.unlock_shared(); + m_lock.unlock_shared(); - DeleteFile(strDel1); - DeleteFile(strDel2); - DeleteFile(strDel3); + DeleteFile(strDel1); + DeleteFile(strDel2); + DeleteFile(strDel3); } -void CTask::UpdateTime() -{ - boost::unique_lock lock(m_lock); - - UpdateTimeNL(); -} - void CTask::SetFilters(const CFiltersArray* pFilters) { BOOST_ASSERT(pFilters); @@ -1225,22 +1262,6 @@ m_localStats.SetTotalSize(ullTotalSize); } -void CTask::CleanupAfterKillNL() -{ - UpdateTimeNL(); - m_lLastTime = -1; -} - -void CTask::UpdateTimeNL() -{ - if(m_lLastTime != -1) - { - long lVal = (long)time(NULL); - m_lTimeElapsed += lVal - m_lLastTime; - m_lLastTime = lVal; - } -} - CString CTask::GetUniqueNameNL() { return m_strUniqueName; @@ -2614,8 +2635,8 @@ if(!bReadTasksSize) pTask->CheckForWaitState(); // operation limiting - // set what's needed - pTask->m_lLastTime=(long)time(NULL); // last time (start counting) + // start tracking time + pTask->m_localStats.EnableTimeTracking(); // search for files if needed if((pTask->GetStatus(ST_STEP_MASK) == ST_NULL_STATUS @@ -2676,12 +2697,11 @@ if(bReadTasksSize) { - pTask->UpdateTime(); - pTask->m_lLastTime=-1; + pTask->m_localStats.DisableTimeTracking(); pTask->CheckForWaitState(); - pTask->m_lLastTime=(long)time(NULL); + pTask->m_localStats.EnableTimeTracking(); } // Phase II - copying/moving @@ -2697,7 +2717,7 @@ pTask->DeleteFiles(); // refresh time - pTask->UpdateTime(); + pTask->m_localStats.DisableTimeTracking(); // save progress before killed pTask->Store(false); @@ -2709,14 +2729,11 @@ piFeedbackHandler->RequestFeedback(CFeedbackHandler::eFT_OperationFinished, NULL); pTask->OnEndOperation(); - - // we have been killed - the last operation - pTask->CleanupAfterKill(); } catch(CProcessingException* e) { // refresh time - pTask->UpdateTime(); + pTask->m_localStats.DisableTimeTracking(); // log fmt.SetFormat(_T("Caught exception in ThrdProc [last error: %errno, type: %type]")); @@ -2769,8 +2786,6 @@ pTask->OnEndOperation(); - pTask->CleanupAfterKill(); - delete e; return 0xffffffff; // almost like -1 @@ -3070,6 +3085,16 @@ strFmt.Format(_T("Cannot load task data: %s (reason: %S)"), strPath, e.what()); LOG_ERROR(strFmt); } + catch(icpf::exception& e) + { + tchar_t szBuffer[65536]; + e.get_info(szBuffer, 65536); + szBuffer[65535] = _T('\0'); + + CString strFmt; + strFmt.Format(_T("Cannot load task data: %s (reason: %s)"), strPath, szBuffer); + LOG_ERROR(strFmt); + } } finder.Close(); } Index: src/ch/task.h =================================================================== diff -u -N -ref313208b7c4a113907f2f72ee0b73406081501d -r1fa2eb7e39e2f8d84868d421fe1c4f0afc58d353 --- src/ch/task.h (.../task.h) (revision ef313208b7c4a113907f2f72ee0b73406081501d) +++ src/ch/task.h (.../task.h) (revision 1fa2eb7e39e2f8d84868d421fe1c4f0afc58d353) @@ -95,7 +95,7 @@ ull_t m_ullSizeAll; int m_nPercent; - long m_lTimeElapsed; + time_t m_timeElapsed; unsigned char m_ucCurrentCopy; unsigned char m_ucCopies; @@ -277,12 +277,23 @@ void MarkTaskAsNotRunning(); bool IsRunning() const; + void SetTimeElapsed(time_t timeElapsed); + time_t GetTimeElapsed(); + + void EnableTimeTracking(); + void DisableTimeTracking(); + void UpdateTime(); + private: volatile unsigned long long m_ullProcessedSize; volatile unsigned long long m_ullTotalSize; volatile bool m_bTaskIsRunning; + // time + volatile time_t m_timeElapsed; + volatile time_t m_timeLast; + mutable boost::shared_mutex m_lock; TTasksGlobalStats* m_prtGlobalStats; }; @@ -433,12 +444,6 @@ void KillThread(); - void CleanupAfterKill(); - void CleanupAfterKillNL(); - - void UpdateTime(); - void UpdateTimeNL(); - CString GetUniqueNameNL(); void SetForceFlagNL(bool bFlag = true); @@ -461,10 +466,6 @@ UINT m_uiResumeInterval; // works only if the thread is off - // time - long m_lTimeElapsed; // store - long m_lLastTime; // not store - // feedback chcore::IFeedbackHandler* m_piFeedbackHandler;