Index: src/ch/StatusDlg.cpp =================================================================== diff -u -rf25056c67d674c9491c8b23354236a253037132d -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/ch/StatusDlg.cpp (.../StatusDlg.cpp) (revision f25056c67d674c9491c8b23354236a253037132d) +++ src/ch/StatusDlg.cpp (.../StatusDlg.cpp) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -61,11 +61,13 @@ void CStatusDlg::DoDataExchange(CDataExchange* pDX) { CLanguageDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CStatusDlg) - DDX_Control(pDX, IDC_TASK_PROGRESS, m_ctlCurrentProgress); + DDX_Control(pDX, IDC_TASKCOUNT_PROGRESS, m_ctlTaskCountProgress); + DDX_Control(pDX, IDC_TASKSIZE_PROGRESS, m_ctlTaskSizeProgress); + DDX_Control(pDX, IDC_CURRENTOBJECT_PROGRESS, m_ctlCurrentObjectProgress); + DDX_Control(pDX, IDC_SUBTASKCOUNT_PROGRESS, m_ctlSubTaskCountProgress); + DDX_Control(pDX, IDC_SUBTASKSIZE_PROGRESS, m_ctlSubTaskSizeProgress); + DDX_Control(pDX, IDC_GLOBAL_PROGRESS, m_ctlProgressAll); DDX_Control(pDX, IDC_STATUS_LIST, m_ctlStatusList); - DDX_Control(pDX, IDC_ALL_PROGRESS, m_ctlProgressAll); - //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CStatusDlg,ictranslate::CLanguageDialog) @@ -148,7 +150,7 @@ m_ctlStatusList.SetImageList(&m_images, LVSIL_SMALL); // set fixed progresses ranges - m_ctlCurrentProgress.SetRange32(0, 100); + m_ctlTaskCountProgress.SetRange32(0, 100); m_ctlProgressAll.SetRange32(0, 100); // change the size of a dialog @@ -186,19 +188,25 @@ if (!bEnable) { - // get rid of text id disabling + GetDlgItem(IDC_TASKID_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYTASKID_STRING)); + GetDlgItem(IDC_OPERATION_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYOPERATIONTEXT_STRING)); - GetDlgItem(IDC_SOURCE_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYSOURCETEXT_STRING)); - GetDlgItem(IDC_DESTINATION_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYDESTINATIONTEXT_STRING)); + GetDlgItem(IDC_SOURCEOBJECT_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYSOURCETEXT_STRING)); + GetDlgItem(IDC_DESTINATIONOBJECT_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYDESTINATIONTEXT_STRING)); GetDlgItem(IDC_BUFFERSIZE_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYBUFFERSIZETEXT_STRING)); - GetDlgItem(IDC_PRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYPRIORITYTEXT_STRING)); + GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYPRIORITYTEXT_STRING)); - GetDlgItem(IDC_PROGRESS_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYPROCESSEDTEXT_STRING)); - GetDlgItem(IDC_TRANSFER_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYTRANSFERTEXT_STRING)); - GetDlgItem(IDC_TIME_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYTIMETEXT_STRING)); - GetDlgItem(IDC_ASSOCIATEDFILES__STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYASSOCFILE_STRING)); + // subtask + GetDlgItem(IDC_SUBTASKNAME_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYSUBTASKNAME_STRING)); + GetDlgItem(IDC_SUBTASKPROCESSED_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYPROCESSEDTEXT_STRING)); + GetDlgItem(IDC_SUBTASKTIME_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYTIMETEXT_STRING)); + GetDlgItem(IDC_SUBTASKTRANSFER_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYTRANSFERTEXT_STRING)); - m_ctlCurrentProgress.SetPos(0); + GetDlgItem(IDC_TASKPROCESSED_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYPROCESSEDTEXT_STRING)); + GetDlgItem(IDC_TASKTRANSFER_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYTRANSFERTEXT_STRING)); + GetDlgItem(IDC_TASKTIME_STATIC)->SetWindowText(GetResManager().LoadString(IDS_EMPTYTIMETEXT_STRING)); + + m_ctlTaskCountProgress.SetPos(0); } } @@ -224,118 +232,16 @@ if(spTask == NULL) return; - // index to string - _itot(nPos, m_szData, 10); - // get data snapshot from task chcore::TASK_DISPLAY_DATA td; spTask->GetSnapshot(&td); - // index subitem - CString strStatusText = GetStatusString(td); - CString strTemp; - LVITEM lvi; - lvi.mask=LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; - lvi.iItem=nPos; - lvi.iSubItem=0; - lvi.pszText = (PTSTR)(PCTSTR)strStatusText; - lvi.cchTextMax = lstrlen(lvi.pszText); - lvi.lParam = spTask->GetSessionUniqueID(); - lvi.iImage=GetImageFromStatus(td.m_eTaskState); - if (nPos < m_ctlStatusList.GetItemCount()) - m_ctlStatusList.SetItem(&lvi); - else - m_ctlStatusList.InsertItem(&lvi); + // set (update/add new) entry in the task list (on the left) + SetTaskListEntry(td, nPos, spTask); - // status subitem - lvi.mask=LVIF_TEXT; - lvi.iSubItem=1; - if(td.m_strFileName.IsEmpty()) - strTemp = GetResManager().LoadString(IDS_NONEINPUTFILE_STRING); - else - strTemp = td.m_strFileName; - lvi.pszText=strTemp.GetBuffer(0); - strTemp.ReleaseBuffer(); - lvi.cchTextMax=lstrlen(lvi.pszText); - m_ctlStatusList.SetItem(&lvi); - - // insert 'file' subitem - lvi.iSubItem=2; - strTemp = td.m_pathDstPath.ToString(); - lvi.pszText=strTemp.GetBuffer(0); - strTemp.ReleaseBuffer(); - lvi.cchTextMax=lstrlen(lvi.pszText); - m_ctlStatusList.SetItem(&lvi); - - // insert dest subitem - lvi.iSubItem=3; - _itot(boost::numeric_cast(td.m_dPercent), m_szData, 10); - _tcscat(m_szData, _T(" %")); - lvi.pszText=m_szData; - lvi.cchTextMax=lstrlen(lvi.pszText); - m_ctlStatusList.SetItem(&lvi); - // right side update if(spTask == m_spSelectedItem) - { - // data that can be changed by a thread - GetDlgItem(IDC_OPERATION_STATIC)->SetWindowText(strStatusText); // operation - - if(td.m_strFullFilePath.IsEmpty()) - GetDlgItem(IDC_SOURCE_STATIC)->SetWindowText(GetResManager().LoadString(IDS_NONEINPUTFILE_STRING)); - else - GetDlgItem(IDC_SOURCE_STATIC)->SetWindowText(td.m_strFullFilePath); // src object - - // count of processed data/overall count of data - _sntprintf(m_szData, _MAX_PATH, _T("%d/%d ("), td.m_stIndex, td.m_stSize); - strTemp=CString(m_szData); - strTemp+=GetSizeString(td.m_ullProcessedSize, m_szData, _MAX_PATH)+CString(_T("/")); - strTemp+=GetSizeString(td.m_ullSizeAll, m_szData, _MAX_PATH)+CString(_T(")")); - GetDlgItem(IDC_PROGRESS_STATIC)->SetWindowText(strTemp); - - // transfer - if (m_i64LastProcessed == 0) // if first time - show average - strTemp=GetSizeString( td.m_timeElapsed ? td.m_ullProcessedSize/td.m_timeElapsed : 0, m_szData, _MAX_PATH); // last avg - else - if ( (dwCurrentTime-m_dwLastUpdate) != 0) - strTemp=GetSizeString( (static_cast(td.m_ullProcessedSize) - static_cast(m_i64LastProcessed))/(static_cast(dwCurrentTime-m_dwLastUpdate)/1000.0), m_szData, _MAX_PATH); - else - strTemp=GetSizeString( 0ULL, m_szData, _MAX_PATH); - - // avg transfer - GetDlgItem(IDC_TRANSFER_STATIC)->SetWindowText(strTemp+_T("/s (")+CString(GetResManager().LoadString(IDS_AVERAGEWORD_STRING)) - +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_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); - - // remember current processed data (used for calculating transfer) - m_i64LastProcessed=td.m_ullProcessedSize; - - // set progress - m_ctlCurrentProgress.SetPos(boost::numeric_cast(td.m_dPercent)); - - SetBufferSizesString(td.m_iCurrentBufferSize, td.m_iCurrentBufferIndex); - - // data that can be changed only by user from outside the thread - // refresh only when there are new selected item -// if (spTask != m_spLastSelected) - { - GetDlgItem(IDC_DESTINATION_STATIC)->SetWindowText(td.m_pathDstPath.ToString()); - GetDlgItem(IDC_PRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(td.m_nPriority))); - GetDlgItem(IDC_ASSOCIATEDFILES__STATIC)->SetWindowText(td.m_strUniqueName); - } - - // refresh m_spLastSelected - m_spLastSelected = spTask; - } + UpdateTaskStatsDetails(td, dwCurrentTime); } void CStatusDlg::OnSetBuffersizeButton() @@ -464,31 +370,31 @@ { case ID_POPUP_TIME_CRITICAL: m_spSelectedItem->SetPriority(THREAD_PRIORITY_TIME_CRITICAL); - GetDlgItem(IDC_PRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_TIME_CRITICAL))); + GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_TIME_CRITICAL))); break; case ID_POPUP_HIGHEST: m_spSelectedItem->SetPriority(THREAD_PRIORITY_HIGHEST); - GetDlgItem(IDC_PRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_HIGHEST))); + GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_HIGHEST))); break; case ID_POPUP_ABOVE_NORMAL: m_spSelectedItem->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); - GetDlgItem(IDC_PRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_ABOVE_NORMAL))); + GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_ABOVE_NORMAL))); break; case ID_POPUP_NORMAL: m_spSelectedItem->SetPriority(THREAD_PRIORITY_NORMAL); - GetDlgItem(IDC_PRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_NORMAL))); + GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_NORMAL))); break; case ID_POPUP_BELOW_NORMAL: m_spSelectedItem->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); - GetDlgItem(IDC_PRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_BELOW_NORMAL))); + GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_BELOW_NORMAL))); break; case ID_POPUP_LOWEST: m_spSelectedItem->SetPriority(THREAD_PRIORITY_LOWEST); - GetDlgItem(IDC_PRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_LOWEST))); + GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_LOWEST))); break; case ID_POPUP_IDLE: m_spSelectedItem->SetPriority(THREAD_PRIORITY_IDLE); - GetDlgItem(IDC_PRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_IDLE))); + GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(THREAD_PRIORITY_IDLE))); break; } } @@ -665,6 +571,12 @@ return lpszBuffer; } +LPTSTR CStatusDlg::FormatTimeMiliseconds(unsigned long long timeMiliSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize) +{ + time_t timeSeconds = timeMiliSeconds / 1000; + return FormatTime(timeSeconds, lpszBuffer, stMaxBufferSize); +} + void CStatusDlg::RefreshStatus() { // remember address of a current selection @@ -704,7 +616,7 @@ // progress - count of processed data/count of data strTemp=GetSizeString(tTMStats.GetProcessedSize(), m_szData, _MAX_PATH)+CString(_T("/")); strTemp+=GetSizeString(tTMStats.GetTotalSize(), m_szData, _MAX_PATH); - GetDlgItem(IDC_OVERALL_PROGRESS_STATIC)->SetWindowText(strTemp); + GetDlgItem(IDC_GLOBALPROCESSED_STATIC)->SetWindowText(strTemp); // transfer if (m_i64LastAllTasksProcessed == 0) @@ -715,15 +627,14 @@ else strTemp=GetSizeString( 0ULL, m_szData, _MAX_PATH); - GetDlgItem(IDC_OVERALL_TRANSFER_STATIC)->SetWindowText(strTemp+_T("/s")); + GetDlgItem(IDC_GLOBALTRANSFER_STATIC)->SetWindowText(strTemp+_T("/s")); m_i64LastAllTasksProcessed=tTMStats.GetProcessedSize(); m_dwLastUpdate=dwCurrentTime; // if selection's missing - hide controls if (m_ctlStatusList.GetSelectedCount() == 0) { EnableControls(false); - m_spLastSelected.reset(); m_i64LastProcessed=0; } else @@ -868,10 +779,11 @@ { ClearResizableControls(); - AddResizableControl(IDC_001_STATIC, 0, 0, 0.5, 0.0); + // left part of dialog (task list) + AddResizableControl(IDC_TASKLIST_LABEL_STATIC, 0, 0, 0.5, 0.0); AddResizableControl(IDC_STATUS_LIST, 0, 0, 0.5, 1.0); - AddResizableControl(IDC_ROLL_UNROLL_BUTTON, 0.5, 0, 0, 0); + // left part of dialog (buttons under the task list) AddResizableControl(IDC_PAUSE_BUTTON, 0, 1.0, 0, 0); AddResizableControl(IDC_RESTART_BUTTON, 0, 1.0, 0, 0); AddResizableControl(IDC_RESUME_BUTTON, 0, 1.0, 0, 0); @@ -883,54 +795,85 @@ AddResizableControl(IDC_REMOVE_FINISHED_BUTTON, 0, 1.0, 0, 0); AddResizableControl(IDC_RESTART_ALL_BUTTON, 0, 1.0, 0, 0); - AddResizableControl(IDC_STICK_BUTTON, 1.0, 1.0, 0, 0); + // left part of dialog (global stats) + AddResizableControl(IDC_GLOBAL_GROUP_STATIC, 0.0, 1.0, 0.5, 0); - // sections separators - AddResizableControl(IDC_014_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_015_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_GLOBALPROCESSED_LABEL_STATIC, 0.0, 1.0, 0.0, 0.0); + AddResizableControl(IDC_GLOBALPROCESSED_STATIC, 0.0, 1.0, 0.5, 0); + AddResizableControl(IDC_GLOBALTRANSFER_LABEL_STATIC, 0.0, 1.0, 0.0, 0.0); + AddResizableControl(IDC_GLOBALTRANSFER_STATIC, 0.0, 1.0, 0.5, 0); + AddResizableControl(IDC_GLOBALPROGRESS_LABEL_STATIC, 0.0, 1.0, 0.0, 0.0); + AddResizableControl(IDC_GLOBAL_PROGRESS, 0.0, 1.0, 0.5, 0.0); - AddResizableControl(IDC_018_STATIC, 0.5, 0.0, 0.25, 0); - AddResizableControl(IDC_019_STATIC, 0.5, 0.0, 0.25, 0); - AddResizableControl(IDC_016_STATIC, 0.75, 0.0, 0.25, 0); - AddResizableControl(IDC_017_STATIC, 0.75, 0.0, 0.25, 0); + // right part of dialog (task info) + AddResizableControl(IDC_TASKINFORMATION_GROUP_STATIC, 0.5, 0.0, 0.5, 0); - // left part of right column - AddResizableControl(IDC_002_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_003_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_004_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_005_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_006_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_007_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_009_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_010_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_011_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_012_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_013_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_020_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_021_STATIC, 0.5, 0.0, 0.0, 0); - AddResizableControl(IDC_SHOW_LOG_BUTTON, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_SHOW_LOG_BUTTON, 0.5, 0.0, 0.0, 0.0); + // right part of dialog (subsequent entries) + AddResizableControl(IDC_TASKID_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_TASKID_STATIC, 0.5, 0.0, 0.5, 0); - // full length right column - AddResizableControl(IDC_ALL_PROGRESS, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_TASK_PROGRESS, 0.5, 0.0, 0.5, 0); - - // right part of right column - AddResizableControl(IDC_ASSOCIATEDFILES__STATIC, 0.5, 0.0, 0.5, 0); + AddResizableControl(IDC_OPERATION_LABEL_STATIC, 0.5, 0.0, 0.0, 0); AddResizableControl(IDC_OPERATION_STATIC, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_SOURCE_STATIC, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_DESTINATION_STATIC, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_PROGRESS_STATIC, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_TIME_STATIC, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_TRANSFER_STATIC, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_OVERALL_PROGRESS_STATIC, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_OVERALL_TRANSFER_STATIC, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_BUFFERSIZE_STATIC, 0.5, 0.0, 0.5, 0); - AddResizableControl(IDC_PRIORITY_STATIC, 0.5, 0.0, 0.5, 0); + AddResizableControl(IDC_SOURCEOBJECT_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_SOURCEOBJECT_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_DESTINATIONOBJECT_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_DESTINATIONOBJECT_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_BUFFERSIZE_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_BUFFERSIZE_STATIC, 0.5, 0.0, 0.5, 0); AddResizableControl(IDC_SET_BUFFERSIZE_BUTTON, 1.0, 0.0, 0.0, 0.0); + + AddResizableControl(IDC_THREADPRIORITY_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_THREADPRIORITY_STATIC, 0.5, 0.0, 0.5, 0); AddResizableControl(IDC_SET_PRIORITY_BUTTON, 1.0, 0.0, 0.0, 0.0); + // right part of the dialog (subtask stats) + AddResizableControl(IDC_CURRENTPHASE_GROUP_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_SUBTASKNAME_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_SUBTASKNAME_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_SUBTASKPROCESSED_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_SUBTASKPROCESSED_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_SUBTASKTIME_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_SUBTASKTIME_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_SUBTASKTRANSFER_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_SUBTASKTRANSFER_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_CURRENTOBJECT_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_CURRENTOBJECT_PROGRESS, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_SUBTASKCOUNT_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_SUBTASKCOUNT_PROGRESS, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_SUBTASKSIZE_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_SUBTASKSIZE_PROGRESS, 0.5, 0.0, 0.5, 0); + + // right part of the dialog (task stats) + AddResizableControl(IDC_ENTIRETASK_GROUP_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_TASKPROCESSED_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_TASKPROCESSED_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_TASKTIME_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_TASKTIME_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_TASKTRANSFER_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_TASKTRANSFER_STATIC, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_TASKCOUNT_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_TASKCOUNT_PROGRESS, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_TASKSIZE_LABEL_STATIC, 0.5, 0.0, 0.0, 0); + AddResizableControl(IDC_TASKSIZE_PROGRESS, 0.5, 0.0, 0.5, 0); + + AddResizableControl(IDC_SHOW_LOG_BUTTON, 1.0, 0.0, 0.0, 0); + AddResizableControl(IDC_STICK_BUTTON, 1.0, 1.0, 0, 0); + InitializeResizableControls(); } @@ -1015,3 +958,151 @@ return strStatusText; } + +void CStatusDlg::SetTaskListEntry(const chcore::TASK_DISPLAY_DATA &td, int nPos, const chcore::TTaskPtr& spTask) +{ + // index subitem + CString strStatusText = GetStatusString(td); + CString strTemp; + LVITEM lvi; + lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; + lvi.iItem = nPos; + lvi.iSubItem = 0; + lvi.pszText = (PTSTR)(PCTSTR)strStatusText; + lvi.cchTextMax = lstrlen(lvi.pszText); + lvi.lParam = spTask->GetSessionUniqueID(); + lvi.iImage = GetImageFromStatus(td.m_eTaskState); + if (nPos < m_ctlStatusList.GetItemCount()) + m_ctlStatusList.SetItem(&lvi); + else + m_ctlStatusList.InsertItem(&lvi); + + // status subitem + lvi.mask=LVIF_TEXT; + lvi.iSubItem=1; + if(td.m_strFileName.IsEmpty()) + strTemp = GetResManager().LoadString(IDS_NONEINPUTFILE_STRING); + else + strTemp = td.m_strFileName; + lvi.pszText=strTemp.GetBuffer(0); + strTemp.ReleaseBuffer(); + lvi.cchTextMax=lstrlen(lvi.pszText); + m_ctlStatusList.SetItem(&lvi); + + // insert 'file' subitem + lvi.iSubItem=2; + strTemp = td.m_pathDstPath.ToString(); + lvi.pszText=strTemp.GetBuffer(0); + strTemp.ReleaseBuffer(); + lvi.cchTextMax=lstrlen(lvi.pszText); + m_ctlStatusList.SetItem(&lvi); + + // insert dest subitem + lvi.iSubItem=3; + _itot(boost::numeric_cast(td.m_dPercent), m_szData, 10); + _tcscat(m_szData, _T(" %")); + lvi.pszText=m_szData; + lvi.cchTextMax=lstrlen(lvi.pszText); + m_ctlStatusList.SetItem(&lvi); +} + +CString CStatusDlg::GetProcessedText(unsigned long long ullProcessedCount, unsigned long long ullTotalCount, unsigned long long ullProcessedSize, unsigned long long ullTotalSize) +{ + CString strTemp; + _sntprintf(m_szData, _MAX_PATH, _T("%ld/%ld ("), ullProcessedCount, ullTotalCount); + strTemp = CString(m_szData); + strTemp += GetSizeString(ullProcessedSize, m_szData, _MAX_PATH) + CString(_T("/")); + strTemp += GetSizeString(ullTotalSize, m_szData, _MAX_PATH) + CString(_T(")")); + return strTemp; +} + +void CStatusDlg::UpdateTaskStatsDetails(chcore::TASK_DISPLAY_DATA &td, DWORD dwCurrentTime) +{ + chcore::TSubTaskStatsSnapshot& tSubTaskStats = td.m_tTaskSnapshot.GetCurrentSubTaskStats(); + + // text progress + CString strProcessedText = GetProcessedText(tSubTaskStats.GetProcessedCount(), tSubTaskStats.GetTotalCount(), tSubTaskStats.GetProcessedSize(), tSubTaskStats.GetTotalSize()); + GetDlgItem(IDC_SUBTASKPROCESSED_STATIC)->SetWindowText(strProcessedText); + + // progress bars + m_ctlCurrentObjectProgress.SetProgress(tSubTaskStats.GetCurrentItemProcessedSize(), tSubTaskStats.GetCurrentItemTotalSize()); + m_ctlSubTaskCountProgress.SetProgress(tSubTaskStats.GetProcessedCount(), tSubTaskStats.GetTotalCount()); + m_ctlSubTaskSizeProgress.SetProgress(tSubTaskStats.GetProcessedSize(), tSubTaskStats.GetTotalSize()); + + // time information + unsigned long long timeTotalEstimated = tSubTaskStats.GetEstimatedTotalTime(); + unsigned long long timeElapsed = tSubTaskStats.GetTimeElapsed(); + unsigned long long timeRemaining = timeTotalEstimated - timeElapsed; + + FormatTimeMiliseconds(timeElapsed, m_szTimeBuffer1, 40); + FormatTimeMiliseconds(timeTotalEstimated, m_szTimeBuffer2, 40); + FormatTimeMiliseconds(timeRemaining, m_szTimeBuffer3, 40); + + _sntprintf(m_szData, _MAX_PATH, _T("%s / %s (%s)"), m_szTimeBuffer1, m_szTimeBuffer2, m_szTimeBuffer3); + + GetDlgItem(IDC_SUBTASKTIME_STATIC)->SetWindowText(m_szData); + + // speed information + CString strSizeSpeed; + CString strCountSpeed; + + GetSizeString(tSubTaskStats.GetSizeSpeed(), m_szData, _MAX_PATH); + strSizeSpeed = m_szData; + GetSizeString(tSubTaskStats.GetAvgSizeSpeed(), m_szData, _MAX_PATH); + strSizeSpeed.AppendFormat(_T("/s (a: %s/s)"), m_szData); + + strCountSpeed.Format(_T("%.2f/s (a: %.2f/s)"), tSubTaskStats.GetCountSpeed(), tSubTaskStats.GetAvgCountSpeed()); + GetDlgItem(IDC_SUBTASKTRANSFER_STATIC)->SetWindowText(strSizeSpeed + _T("; ") + strCountSpeed); + + ////////////////////////////////////////////////////// + // data that can be changed by a thread + CString strStatusText = GetStatusString(td); + GetDlgItem(IDC_OPERATION_STATIC)->SetWindowText(strStatusText); // operation + + if(td.m_strFullFilePath.IsEmpty()) + GetDlgItem(IDC_SOURCEOBJECT_STATIC)->SetWindowText(GetResManager().LoadString(IDS_NONEINPUTFILE_STRING)); + else + GetDlgItem(IDC_SOURCEOBJECT_STATIC)->SetWindowText(td.m_strFullFilePath); // src object + + // count of processed data/overall count of data + strProcessedText = GetProcessedText(td.m_stIndex, td.m_stSize, td.m_ullProcessedSize, td.m_ullSizeAll); + GetDlgItem(IDC_TASKPROCESSED_STATIC)->SetWindowText(strProcessedText); + + // transfer + CString strSpeedText; + if (m_i64LastProcessed == 0) // if first time - show average + strSpeedText=GetSizeString( td.m_timeElapsed ? td.m_ullProcessedSize/td.m_timeElapsed : 0, m_szData, _MAX_PATH); // last avg + else + { + if ( (dwCurrentTime-m_dwLastUpdate) != 0) + strSpeedText=GetSizeString( (static_cast(td.m_ullProcessedSize) - static_cast(m_i64LastProcessed))/(static_cast(dwCurrentTime-m_dwLastUpdate)/1000.0), m_szData, _MAX_PATH); + else + strSpeedText=GetSizeString( 0ULL, m_szData, _MAX_PATH); + } + + // avg transfer + GetDlgItem(IDC_TASKTRANSFER_STATIC)->SetWindowText(strSpeedText+_T("/s (")+CString(GetResManager().LoadString(IDS_AVERAGEWORD_STRING)) + +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_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_TASKTIME_STATIC)->SetWindowText(m_szData); + + // remember current processed data (used for calculating transfer) + m_i64LastProcessed=td.m_ullProcessedSize; + + // set progress + m_ctlTaskCountProgress.SetPos(boost::numeric_cast(td.m_dPercent)); + + SetBufferSizesString(td.m_iCurrentBufferSize, td.m_iCurrentBufferIndex); + + GetDlgItem(IDC_DESTINATIONOBJECT_STATIC)->SetWindowText(td.m_pathDstPath.ToString()); + GetDlgItem(IDC_THREADPRIORITY_STATIC)->SetWindowText(GetResManager().LoadString(IDS_PRIORITY0_STRING+PriorityToIndex(td.m_nPriority))); + GetDlgItem(IDC_TASKID_STATIC)->SetWindowText(td.m_strUniqueName); +} Index: src/ch/StatusDlg.h =================================================================== diff -u -rf25056c67d674c9491c8b23354236a253037132d -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/ch/StatusDlg.h (.../StatusDlg.h) (revision f25056c67d674c9491c8b23354236a253037132d) +++ src/ch/StatusDlg.h (.../StatusDlg.h) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -20,6 +20,7 @@ #define __STATUSDLG_H__ #include "FFListCtrl.h" +#include "TProgressCtrlEx.h" namespace chcore { @@ -45,7 +46,7 @@ void PostCloseMessage(); void SetBufferSizesString(UINT uiValue, int iIndex); void RefreshStatus(); - LPTSTR FormatTime(time_t timeSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize); + int GetImageFromStatus(chcore::ETaskCurrentState eState); void ApplyButtonsState(); @@ -66,6 +67,13 @@ void StickDialogToScreenEdge(); + LPTSTR FormatTime(time_t timeSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize); + LPTSTR FormatTimeMiliseconds(unsigned long long timeMiliSeconds, LPTSTR lpszBuffer, size_t stMaxBufferSize); + + CString GetProcessedText(unsigned long long ullProcessedCount, unsigned long long ullTotalCount, unsigned long long ullProcessedSize, unsigned long long ullTotalSize); + void UpdateTaskStatsDetails( chcore::TASK_DISPLAY_DATA &td, DWORD dwCurrentTime ); + void SetTaskListEntry(const chcore::TASK_DISPLAY_DATA &td, int nPos, const chcore::TTaskPtr& spTask); + virtual BOOL OnInitDialog(); afx_msg void OnTimer(UINT_PTR nIDEvent); afx_msg void OnPauseButton(); @@ -96,7 +104,6 @@ protected: chcore::TTaskManager* m_pTasks; chcore::TTaskPtr m_spSelectedItem; - chcore::TTaskPtr m_spLastSelected; TCHAR m_szData[_MAX_PATH]; TCHAR m_szTimeBuffer1[40]; @@ -109,12 +116,15 @@ CImageList m_images; - CProgressCtrl m_ctlCurrentProgress; CFFListCtrl m_ctlStatusList; - CProgressCtrl m_ctlProgressAll; + +private: + TProgressCtrlEx m_ctlTaskCountProgress; + TProgressCtrlEx m_ctlTaskSizeProgress; + TProgressCtrlEx m_ctlCurrentObjectProgress; + TProgressCtrlEx m_ctlSubTaskCountProgress; + TProgressCtrlEx m_ctlSubTaskSizeProgress; + TProgressCtrlEx m_ctlProgressAll; }; -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - #endif Index: src/ch/TProgressCtrlEx.cpp =================================================================== diff -u --- src/ch/TProgressCtrlEx.cpp (revision 0) +++ src/ch/TProgressCtrlEx.cpp (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,37 @@ +/*************************************************************************** +* Copyright (C) 2001-2013 by J�zef Starosczyk * +* ixen@copyhandler.com * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU Library General Public License * +* (version 2) as published by the Free Software Foundation; * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU Library General Public * +* License along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ +#include "stdafx.h" +#include "TProgressCtrlEx.h" + +TProgressCtrlEx::TProgressCtrlEx() +{ +} + +void TProgressCtrlEx::SetProgress(unsigned long long ullPos, unsigned long long ullMaxRange) +{ + unsigned int uiDivider = 0; + while((ullMaxRange >> uiDivider) > (unsigned int)std::numeric_limits::max()) + ++uiDivider; + + ullPos >>= uiDivider; + ullMaxRange >>= uiDivider; + + SetRange32(0, (int)ullMaxRange); + SetPos((int)ullPos); +} Index: src/ch/TProgressCtrlEx.h =================================================================== diff -u --- src/ch/TProgressCtrlEx.h (revision 0) +++ src/ch/TProgressCtrlEx.h (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,30 @@ +/*************************************************************************** +* Copyright (C) 2001-2013 by J�zef Starosczyk * +* ixen@copyhandler.com * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU Library General Public License * +* (version 2) as published by the Free Software Foundation; * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU Library General Public * +* License along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ +#ifndef __TPROGRESSCTRLEX_H__ +#define __TPROGRESSCTRLEX_H__ + +class TProgressCtrlEx : public CProgressCtrl +{ +public: + TProgressCtrlEx(); + + void SetProgress(unsigned long long ullPos, unsigned long long ullMaxRange); +}; + +#endif Index: src/ch/ch.rc =================================================================== diff -u -rf25056c67d674c9491c8b23354236a253037132d -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/ch/ch.rc (.../ch.rc) (revision f25056c67d674c9491c8b23354236a253037132d) +++ src/ch/ch.rc (.../ch.rc) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -126,7 +126,7 @@ COMBOBOX IDC_CDROMMULTIPLIER_COMBO,306,18,31,56,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,0,HIDC_CDROMMULTIPLIER_COMBO EDITTEXT IDC_LANSIZE_EDIT,206,51,97,14,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_CLIENTEDGE,HIDC_LANSIZE_EDIT COMBOBOX IDC_LANMULTIPLIER_COMBO,306,52,31,56,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,0,HIDC_LANMULTIPLIER_COMBO - DEFPUSHBUTTON "&OK",IDOK,176,106,50,14,0,0,HIDOK + DEFPUSHBUTTON "&OK",IDOK,176,106,50,14,0,0,HIDCANCEL PUSHBUTTON "&Cancel",IDCANCEL,229,106,50,14,0,0,HIDCANCEL LTEXT "Default",IDC_001_STATIC,35,7,127,8 LTEXT "For copying inside one disk boundary",IDC_002_STATIC,35,38,130,8 @@ -171,67 +171,81 @@ CAPTION "Options" FONT 8, "Tahoma", 0, 0, 0x1 BEGIN - DEFPUSHBUTTON "&OK",IDOK,173,193,50,14,0,0,HIDOK + DEFPUSHBUTTON "&OK",IDOK,173,193,50,14,0,0,HIDCANCEL PUSHBUTTON "&Cancel",IDCANCEL,227,193,50,14,0,0,HIDCANCEL LISTBOX IDC_PROPERTIES_LIST,7,7,383,179,LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP,0,HIDC_PROPERTIES_LIST PUSHBUTTON "&Apply",IDC_APPLY_BUTTON,283,193,50,14,0,0,HIDC_APPLY_BUTTON - PUSHBUTTON "&Help",IDHELP,340,193,50,14,0,0,HIDHELP + PUSHBUTTON "&Help",IDHELP,340,193,50,14,0,0,HIDCANCEL END -IDD_STATUS_DIALOG DIALOGEX 0, 0, 479, 250 +IDD_STATUS_DIALOG DIALOGEX 0, 0, 491, 302 STYLE DS_SETFONT | DS_CONTEXTHELP | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME EXSTYLE WS_EX_APPWINDOW CAPTION "Status" FONT 8, "Tahoma", 0, 0, 0x1 BEGIN - CONTROL "List1",IDC_STATUS_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,19,224,171,0,HIDC_STATUS_LIST - PUSHBUTTON "&Pause",IDC_PAUSE_BUTTON,7,196,44,14,0,0,HIDC_PAUSE_BUTTON - PUSHBUTTON "&Restart",IDC_RESTART_BUTTON,97,196,44,14,0,0,HIDC_RESTART_BUTTON - PUSHBUTTON "&Cancel",IDC_CANCEL_BUTTON,142,196,44,14,0,0,HIDC_CANCEL_BUTTON - PUSHBUTTON "&Remove",IDC_DELETE_BUTTON,187,196,44,14,0,0,HIDC_DELETE_BUTTON - PUSHBUTTON "Pause/all",IDC_PAUSE_ALL_BUTTON,7,213,71,14,0,0,HIDC_PAUSE_ALL_BUTTON - PUSHBUTTON "Resume/all",IDC_START_ALL_BUTTON,79,213,71,14,0,0,HIDC_START_ALL_BUTTON - PUSHBUTTON "Cancel/all",IDC_CANCEL_ALL_BUTTON,7,229,71,14,0,0,HIDC_CANCEL_ALL_BUTTON - PUSHBUTTON "Remove/all",IDC_REMOVE_FINISHED_BUTTON,79,229,71,14,0,0,HIDC_REMOVE_FINISHED_BUTTON - PUSHBUTTON "Restart/all",IDC_RESTART_ALL_BUTTON,151,229,71,14,0,0,HIDC_RESTART_ALL_BUTTON - PUSHBUTTON "",IDC_STICK_BUTTON,472,243,7,7,BS_CENTER | BS_VCENTER | BS_FLAT,0,HIDC_STICK_BUTTON - PUSHBUTTON "...",IDC_SET_BUFFERSIZE_BUTTON,459,72,13,14,0,0,HIDC_SET_BUFFERSIZE_BUTTON - PUSHBUTTON ">",IDC_SET_PRIORITY_BUTTON,459,88,13,14,0,0,HIDC_SET_PRIORITY_BUTTON - PUSHBUTTON "View log",IDC_SHOW_LOG_BUTTON,249,167,223,14,0,0,HIDC_SHOW_LOG_BUTTON - LTEXT "Operations list:",IDC_001_STATIC,7,7,197,8 - CONTROL "Progress1",IDC_ALL_PROGRESS,"msctls_progress32",PBS_SMOOTH,313,234,159,9 - LTEXT "Progress:",IDC_002_STATIC,249,235,62,8 - CONTROL "Progress2",IDC_TASK_PROGRESS,"msctls_progress32",0x0,313,150,159,6 - LTEXT "Progress:",IDC_003_STATIC,249,148,62,8 - LTEXT "Destination object:",IDC_004_STATIC,249,59,62,8 - LTEXT "Source object:",IDC_005_STATIC,249,47,62,8 - LTEXT "Buffer size:",IDC_006_STATIC,249,75,62,8 - LTEXT "Thread priority:",IDC_007_STATIC,249,90,62,8 - LTEXT "Operation:",IDC_009_STATIC,249,34,62,8 - LTEXT "Transfer:",IDC_010_STATIC,249,136,62,8 - LTEXT "Processed:",IDC_011_STATIC,249,106,62,8 - LTEXT "Transfer:",IDC_012_STATIC,249,220,62,8 - LTEXT "Processed:",IDC_013_STATIC,249,205,62,8 - CTEXT "Global statistics",IDC_014_STATIC,293,191,84,8 - CTEXT "Current selection statistics",IDC_015_STATIC,293,7,113,8 - CONTROL "",IDC_016_STATIC,"Static",SS_ETCHEDHORZ,385,194,87,1 - CONTROL "",IDC_017_STATIC,"Static",SS_ETCHEDHORZ,411,10,61,1 - CONTROL "",IDC_018_STATIC,"Static",SS_ETCHEDHORZ,249,194,37,1 - CONTROL "",IDC_019_STATIC,"Static",SS_ETCHEDHORZ,249,10,38,1 - LTEXT "Time:",IDC_020_STATIC,249,121,62,8 - PUSHBUTTON "&Resume",IDC_RESUME_BUTTON,52,196,44,14,0,0,HIDC_RESUME_BUTTON - LTEXT "Task ID:",IDC_021_STATIC,249,19,62,8 - CONTROL "",IDC_ASSOCIATEDFILES__STATIC,"STATICEX",0x4,313,17,159,12,WS_EX_STATICEDGE,HIDC_ASSOCIATEDFILES__STATIC - CONTROL "",IDC_OPERATION_STATIC,"STATICEX",0x4,313,32,159,12,WS_EX_STATICEDGE,HIDC_OPERATION_STATIC - CONTROL "",IDC_SOURCE_STATIC,"STATICEX",0x4,313,45,159,12,WS_EX_STATICEDGE,HIDC_SOURCE_STATIC - CONTROL "",IDC_DESTINATION_STATIC,"STATICEX",0x4,313,58,159,12,WS_EX_STATICEDGE,HIDC_DESTINATION_STATIC - CONTROL "",IDC_PROGRESS_STATIC,"STATICEX",0x4,313,104,159,12,WS_EX_STATICEDGE,HIDC_PROGRESS_STATIC - CONTROL "",IDC_TIME_STATIC,"STATICEX",0x4,313,119,159,12,WS_EX_STATICEDGE,HIDC_TIME_STATIC - CONTROL "",IDC_TRANSFER_STATIC,"STATICEX",0x4,313,134,159,12,WS_EX_STATICEDGE,HIDC_TRANSFER_STATIC - CONTROL "",IDC_OVERALL_PROGRESS_STATIC,"STATICEX",0x4,313,203,159,12,WS_EX_STATICEDGE,HIDC_OVERALL_PROGRESS_STATIC - CONTROL "",IDC_OVERALL_TRANSFER_STATIC,"STATICEX",0x4,313,218,159,12,WS_EX_STATICEDGE,HIDC_OVERALL_TRANSFER_STATIC - CONTROL "",IDC_BUFFERSIZE_STATIC,"STATICEX",0x4,313,74,143,12,WS_EX_STATICEDGE,HIDC_BUFFERSIZE_STATIC - CONTROL "",IDC_PRIORITY_STATIC,"STATICEX",0x4,313,88,143,12,WS_EX_STATICEDGE,HIDC_PRIORITY_STATIC + CONTROL "List1",IDC_STATUS_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,19,223,171,0,HIDC_STATUS_LIST + PUSHBUTTON "&Pause",IDC_PAUSE_BUTTON,7,193,44,14,0,0,HIDC_PAUSE_BUTTON + PUSHBUTTON "&Restart",IDC_RESTART_BUTTON,97,193,44,14,0,0,HIDC_RESTART_BUTTON + PUSHBUTTON "&Cancel",IDC_CANCEL_BUTTON,142,193,44,14,0,0,HIDC_CANCEL_BUTTON + PUSHBUTTON "&Remove",IDC_DELETE_BUTTON,187,193,44,14,0,0,HIDC_DELETE_BUTTON + PUSHBUTTON "Pause/all",IDC_PAUSE_ALL_BUTTON,7,208,71,14,0,0,HIDC_PAUSE_ALL_BUTTON + PUSHBUTTON "Resume/all",IDC_START_ALL_BUTTON,79,208,71,14,0,0,HIDC_START_ALL_BUTTON + PUSHBUTTON "Cancel/all",IDC_CANCEL_ALL_BUTTON,7,223,71,14,0,0,HIDC_CANCEL_ALL_BUTTON + PUSHBUTTON "Remove/all",IDC_REMOVE_FINISHED_BUTTON,79,223,71,14,0,0,HIDC_REMOVE_FINISHED_BUTTON + PUSHBUTTON "Restart/all",IDC_RESTART_ALL_BUTTON,151,223,71,14,0,0,HIDC_RESTART_ALL_BUTTON + PUSHBUTTON "",IDC_STICK_BUTTON,484,295,7,7,BS_CENTER | BS_VCENTER | BS_FLAT,0,HIDC_STICK_BUTTON + PUSHBUTTON "...",IDC_SET_BUFFERSIZE_BUTTON,463,71,13,14,0,0,HIDC_SET_BUFFERSIZE_BUTTON + PUSHBUTTON ">",IDC_SET_PRIORITY_BUTTON,463,85,13,14,0,0,HIDC_SET_PRIORITY_BUTTON + PUSHBUTTON "View log",IDC_SHOW_LOG_BUTTON,431,18,45,12,0,0,HIDC_SHOW_LOG_BUTTON + LTEXT "List of tasks:",IDC_TASKLIST_LABEL_STATIC,7,7,223,8 + CONTROL "Progress1",IDC_GLOBAL_PROGRESS,"msctls_progress32",0x0,71,282,153,7 + LTEXT "Progress:",IDC_GLOBALPROGRESS_LABEL_STATIC,13,281,54,8 + CONTROL "Progress2",IDC_TASKSIZE_PROGRESS,"msctls_progress32",0x0,311,282,165,6 + LTEXT "Task size:",IDC_TASKSIZE_LABEL_STATIC,247,280,62,8 + LTEXT "Destination:",IDC_DESTINATIONOBJECT_LABEL_STATIC,247,61,40,8 + LTEXT "Source:",IDC_SOURCEOBJECT_LABEL_STATIC,247,48,62,8 + LTEXT "Buffer size:",IDC_BUFFERSIZE_LABEL_STATIC,247,75,62,8 + LTEXT "Thread priority:",IDC_THREADPRIORITY_LABEL_STATIC,247,89,62,8 + LTEXT "Operation:",IDC_OPERATION_LABEL_STATIC,247,35,62,8 + LTEXT "Speed:",IDC_TASKTRANSFER_LABEL_STATIC,247,258,62,8 + LTEXT "Processed:",IDC_TASKPROCESSED_LABEL_STATIC,247,232,62,8 + LTEXT "Transfer:",IDC_GLOBALTRANSFER_LABEL_STATIC,13,268,54,8 + LTEXT "Processed:",IDC_GLOBALPROCESSED_LABEL_STATIC,13,255,54,8 + LTEXT "Time:",IDC_TASKTIME_LABEL_STATIC,247,245,62,8 + PUSHBUTTON "&Resume",IDC_RESUME_BUTTON,52,193,44,14,0,0,HIDC_RESUME_BUTTON + LTEXT "Task ID:",IDC_TASKID_LABEL_STATIC,247,21,62,8 + CONTROL "",IDC_TASKID_STATIC,"STATICEX",0x4,311,18,118,12,WS_EX_STATICEDGE,HIDC_TASKID_STATIC + CONTROL "",IDC_OPERATION_STATIC,"STATICEX",0x4,311,32,165,12,WS_EX_STATICEDGE,HIDC_OPERATION_STATIC + CONTROL "",IDC_SOURCEOBJECT_STATIC,"STATICEX",0x4,311,45,165,12,WS_EX_STATICEDGE,HIDC_SOURCEOBJECT_STATIC + CONTROL "",IDC_DESTINATIONOBJECT_STATIC,"STATICEX",0x4,311,58,165,12,WS_EX_STATICEDGE,HIDC_DESTINATIONOBJECT_STATIC + CONTROL "",IDC_TASKPROCESSED_STATIC,"STATICEX",0x4,311,230,165,12,WS_EX_STATICEDGE,HIDC_TASKPROCESSED_STATIC + CONTROL "",IDC_TASKTIME_STATIC,"STATICEX",0x4,311,243,165,12,WS_EX_STATICEDGE,HIDC_TASKTIME_STATIC + CONTROL "",IDC_TASKTRANSFER_STATIC,"STATICEX",0x4,311,256,165,12,WS_EX_STATICEDGE,HIDC_TASKTRANSFER_STATIC + CONTROL "",IDC_GLOBALPROCESSED_STATIC,"STATICEX",0x4,71,253,153,12,WS_EX_STATICEDGE,HIDC_GLOBALPROCESSED_STATIC + CONTROL "",IDC_GLOBALTRANSFER_STATIC,"STATICEX",0x4,71,266,153,12,WS_EX_STATICEDGE,HIDC_GLOBALTRANSFER_STATIC + CONTROL "",IDC_BUFFERSIZE_STATIC,"STATICEX",0x4,311,72,151,12,WS_EX_STATICEDGE,HIDC_BUFFERSIZE_STATIC + CONTROL "",IDC_THREADPRIORITY_STATIC,"STATICEX",0x4,311,86,151,12,WS_EX_STATICEDGE,HIDC_THREADPRIORITY_STATIC + CONTROL "",IDC_SUBTASKCOUNT_PROGRESS,"msctls_progress32",0x0,311,189,165,6 + LTEXT "Count of objects:",IDC_SUBTASKCOUNT_LABEL_STATIC,247,187,62,8 + CONTROL "",IDC_SUBTASKSIZE_PROGRESS,"msctls_progress32",0x0,311,199,165,6 + LTEXT "Size of objects:",IDC_SUBTASKSIZE_LABEL_STATIC,247,197,62,8 + LTEXT "Processed:",IDC_SUBTASKPROCESSED_LABEL_STATIC,247,139,62,8 + CONTROL "",IDC_SUBTASKPROCESSED_STATIC,"STATICEX",0x4,311,136,165,12,WS_EX_STATICEDGE,HIDC_SUBTASKPROCESSED_STATIC + LTEXT "Time:",IDC_SUBTASKTIME_LABEL_STATIC,247,152,62,8 + CONTROL "",IDC_SUBTASKTIME_STATIC,"STATICEX",0x4,311,149,165,12,WS_EX_STATICEDGE,HIDC_SUBTASKTIME_STATIC + CONTROL "",IDC_TASKCOUNT_PROGRESS,"msctls_progress32",0x0,311,272,165,6 + LTEXT "Task count:",IDC_TASKCOUNT_LABEL_STATIC,247,270,62,8 + LTEXT "Speed:",IDC_SUBTASKTRANSFER_LABEL_STATIC,247,165,62,8 + CONTROL "",IDC_SUBTASKTRANSFER_STATIC,"STATICEX",0x4,311,162,165,12,WS_EX_STATICEDGE,HIDC_SUBTASKTRANSFER_STATIC + LTEXT "Current phase:",IDC_SUBTASKNAME_LABEL_STATIC,247,125,62,8 + CONTROL "",IDC_SUBTASKNAME_STATIC,"STATICEX",0x4,311,122,165,12,WS_EX_STATICEDGE,HIDC_SUBTASKNAME_STATIC + CONTROL "",IDC_CURRENTOBJECT_PROGRESS,"msctls_progress32",0x0,311,179,165,6 + LTEXT "Current object:",IDC_CURRENTOBJECT_LABEL_STATIC,247,177,62,8 + GROUPBOX "Task information",IDC_TASKINFORMATION_GROUP_STATIC,238,7,246,98,0,WS_EX_TRANSPARENT + GROUPBOX "Current phase statistics",IDC_CURRENTPHASE_GROUP_STATIC,238,110,246,102,0,WS_EX_TRANSPARENT + GROUPBOX "Entire task statistics",IDC_ENTIRETASK_GROUP_STATIC,238,218,246,77,0,WS_EX_TRANSPARENT + GROUPBOX "Global statistics",IDC_GLOBAL_GROUP_STATIC,7,242,223,53,0,WS_EX_TRANSPARENT END IDD_FEEDBACK_NOTENOUGHSPACE_DIALOG DIALOGEX 0, 0, 255, 147 @@ -290,7 +304,7 @@ "Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,13,255,329,10,0,HIDC_IGNOREFOLDERS_CHECK CONTROL "Do not copy/move contents of files - only create it (empty)",IDC_ONLYSTRUCTURE_CHECK, "Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,13,277,329,10,0,HIDC_ONLYSTRUCTURE_CHECK - PUSHBUTTON "&OK",IDOK,186,297,50,14,0,0,HIDOK + PUSHBUTTON "&OK",IDOK,186,297,50,14,0,0,HIDCANCEL PUSHBUTTON "&Cancel",IDCANCEL,239,297,50,14,0,0,HIDCANCEL LTEXT "Source files/folders:",IDC_001_STATIC,7,7,337,8 LTEXT "Destination folder:",IDC_002_STATIC,7,76,337,8 @@ -347,7 +361,7 @@ CONTROL "Hidden",IDC_HIDDEN_CHECK,"Button",BS_AUTO3STATE | WS_TABSTOP,117,212,68,10,0,HIDC_HIDDEN_CHECK CONTROL "System",IDC_SYSTEM_CHECK,"Button",BS_AUTO3STATE | WS_TABSTOP,117,224,68,10,0,HIDC_SYSTEM_CHECK CONTROL "Directory",IDC_DIRECTORY_CHECK,"Button",BS_AUTO3STATE | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,191,212,93,10,0,HIDC_DIRECTORY_CHECK - DEFPUSHBUTTON "&OK",IDOK,127,245,50,14,0,0,HIDOK + DEFPUSHBUTTON "&OK",IDOK,127,245,50,14,0,0,HIDCANCEL PUSHBUTTON "&Cancel",IDCANCEL,179,245,50,14,0,0,HIDCANCEL CONTROL "",IDC_001_STATIC,"Static",SS_ETCHEDHORZ,7,238,276,1 PUSHBUTTON "&Help",IDC_HELP_BUTTON,234,245,50,14,0,0,HIDC_HELP_BUTTON @@ -365,7 +379,7 @@ PUSHBUTTON "&Add",IDC_ADD_BUTTON,17,160,50,14,0,0,HIDC_ADD_BUTTON PUSHBUTTON "&Update",IDC_CHANGE_BUTTON,69,160,50,14,0,0,HIDC_CHANGE_BUTTON PUSHBUTTON "&Delete",IDC_DELETE_BUTTON,121,160,50,14,0,0,HIDC_DELETE_BUTTON - DEFPUSHBUTTON "&OK",IDOK,156,185,50,14,0,0,HIDOK + DEFPUSHBUTTON "&OK",IDOK,156,185,50,14,0,0,HIDCANCEL PUSHBUTTON "&Cancel",IDCANCEL,211,185,50,14,0,0,HIDCANCEL LTEXT "Shortcuts:",IDC_001_STATIC,7,7,311,8 LTEXT "Name:",IDC_002_STATIC,18,126,53,8 @@ -387,7 +401,7 @@ PUSHBUTTON "&Add",IDC_ADD_BUTTON,20,141,50,14,0,0,HIDC_ADD_BUTTON PUSHBUTTON "&Update",IDC_CHANGE_BUTTON,72,141,50,14,0,0,HIDC_CHANGE_BUTTON PUSHBUTTON "&Delete",IDC_DELETE_BUTTON,124,141,50,14,0,0,HIDC_DELETE_BUTTON - DEFPUSHBUTTON "&OK",IDOK,156,169,50,14,0,0,HIDOK + DEFPUSHBUTTON "&OK",IDOK,156,169,50,14,0,0,HIDCANCEL PUSHBUTTON "&Cancel",IDCANCEL,211,169,50,14,0,0,HIDCANCEL LTEXT "Recently used paths:",IDC_001_STATIC,7,7,311,8 GROUPBOX "Path",IDC_002_STATIC,7,110,311,51 @@ -399,7 +413,7 @@ CAPTION "About ..." FONT 8, "Tahoma", 0, 0, 0x1 BEGIN - DEFPUSHBUTTON "&OK",IDOK,306,143,56,14,WS_GROUP,0,HIDOK + DEFPUSHBUTTON "&OK",IDOK,306,143,56,14,WS_GROUP,0,HIDCANCEL ICON IDR_MAINFRAME,IDC_STATIC,11,14,21,20 CTEXT "",IDC_COPYRIGHT_STATIC,40,93,322,8 CONTROL "",IDC_HOMEPAGELINK_STATIC,"STATICEX",0x1,208,32,154,8 @@ -502,9 +516,9 @@ IDD_STATUS_DIALOG, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 472 + RIGHTMARGIN, 484 TOPMARGIN, 7 - BOTTOMMARGIN, 243 + BOTTOMMARGIN, 295 END IDD_FEEDBACK_NOTENOUGHSPACE_DIALOG, DIALOG @@ -640,10 +654,10 @@ IDS_UNREGISTEROK_STRING "Integration with system disabled successfully." IDS_UNREGISTERERR_STRING "Encountered an error while trying to disable integration with system.\nError #%errno (%errdesc)." - IDS_CHEXT_ALREADY_UNREGISTERED "Integration with system already disabled." IDS_CRASH_STRING "Copy Handler encountered an internal problem and will be closed.\n\nIf you want to help correct this problem in the future releases of program you can send the crash information to the author of this program." IDS_COMMAND_LINE_FAILED_STRING "Cannot process command line arguments passed to Copy Handler." + IDS_CHEXT_ALREADY_UNREGISTERED "Integration with system already disabled." END STRINGTABLE @@ -828,7 +842,13 @@ STRINGTABLE BEGIN - IDS_STATUS_FASTMOVE_STRING "Fast moving" + IDS_STATUS_INITIALIZING_STRING "Initializing" + IDS_STATUS_FASTMOVE_STRING "Fast moving" + IDS_EMPTYSUBTASKNAME_STRING "none" +END + +STRINGTABLE +BEGIN IDS_STATUS_SEARCHING_STRING "Searching" IDS_STATUS_COPYING_STRING "Copying" IDS_STATUS_MOVING_STRING "Moving" @@ -841,7 +861,6 @@ IDS_STATUS_WAITING_STRING "Waiting" IDS_STATUS_ONLY_FILES_STRING "Only files" IDS_STATUS_WITHOUT_CONTENTS_STRING "Without contents" - IDS_STATUS_INITIALIZING_STRING "Initializing" IDS_SHELLEXECUTEERROR_STRING "Error #%errno calling ShellExecute for file %path" IDS_BSDEFAULT_STRING "Default: " @@ -875,7 +894,7 @@ IDS_BSTWODISKS_STRING "Two disks: " IDS_BSCD_STRING "CD: " IDS_BSLAN_STRING "LAN: " - IDS_EMPTYASSOCFILE_STRING "not associated" + IDS_EMPTYTASKID_STRING "not associated" IDS_FILTERING_STRING " [with filter]" IDS_CONFIRMCANCEL_STRING "Selected task wasn't finished yet.\nDo you want to finish it now ?" @@ -1057,9 +1076,12 @@ "There was an error when trying to retrieve version information from the official web page (%errdesc)." IDS_UPDATER_WAITING_STRING "Please wait for the connection with %site to be established..." - IDS_SHELL_EXTENSION_MISMATCH_STRING "Copy Handler encountered incompatible version of component enabling integration with system installed on your system.\nWould you like to update it now (requires administrative rights)?" - IDS_SHELL_EXTENSION_UNREGISTERED_STRING "Copy Handler's component enabling integration with system is disabled.\nDo you want to enable it now (requires administrative rights)?" - IDS_SHELL_EXTENSION_REGISTERED_MISMATCH_STRING "Copy Handler's component enabling integration with system was updated.\nPlease reboot your system for changes to take effect." + IDS_SHELL_EXTENSION_MISMATCH_STRING + "Copy Handler encountered incompatible version of component enabling integration with system installed on your system.\nWould you like to update it now (requires administrative rights)?" + IDS_SHELL_EXTENSION_UNREGISTERED_STRING + "Copy Handler's component enabling integration with system is disabled.\nDo you want to enable it now (requires administrative rights)?" + IDS_SHELL_EXTENSION_REGISTERED_MISMATCH_STRING + "Copy Handler's component enabling integration with system was updated.\nPlease reboot your system for changes to take effect." IDS_CH_PORTABLE_STRING " (portable mode)" IDS_TASK_IMPORT_FAILED "Failed to import task '%path'." END Index: src/ch/ch.vc90.vcproj =================================================================== diff -u -rad6984ff22c68c728c018ef6ed3d33a8c44ea5ca -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision ad6984ff22c68c728c018ef6ed3d33a8c44ea5ca) +++ src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -1021,6 +1021,14 @@ RelativePath="ThemedButton.h" > + + + + ITimestampProviderPtr; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/MathFunctions.cpp =================================================================== diff -u --- src/libchcore/MathFunctions.cpp (revision 0) +++ src/libchcore/MathFunctions.cpp (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,25 @@ +#include "stdafx.h" +#include "MathFunctions.h" +#include + +BEGIN_CHCORE_NAMESPACE + +namespace Math +{ + double Div64(unsigned long long ullNumber, unsigned long long ullDenominator) + { + if(ullDenominator == 0) + return 0.0; + + const unsigned long long ullMaxInt32 = (unsigned long long)std::numeric_limits::max(); + while(ullNumber > ullMaxInt32 || ullDenominator > ullMaxInt32) + { + ullNumber >>= 1; + ullDenominator >>= 1; + } + + return boost::numeric_cast(ullNumber) / boost::numeric_cast(ullDenominator); + } +} + +END_CHCORE_NAMESPACE Index: src/libchcore/MathFunctions.h =================================================================== diff -u --- src/libchcore/MathFunctions.h (revision 0) +++ src/libchcore/MathFunctions.h (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,33 @@ +// ============================================================================ +// Copyright (C) 2001-2012 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __MATHFUNCTIONS_H__ +#define __MATHFUNCTIONS_H__ + +#include "libchcore.h" + +BEGIN_CHCORE_NAMESPACE + +namespace Math +{ + LIBCHCORE_API double Div64(unsigned long long ullNumber, unsigned long long ullDenominator); +} + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/TSimpleTimer.cpp =================================================================== diff -u --- src/libchcore/TSimpleTimer.cpp (revision 0) +++ src/libchcore/TSimpleTimer.cpp (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,79 @@ +// ============================================================================ +// Copyright (C) 2001-2013 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TSimpleTimer.h" +#include "TTimestampProviderTickCount.h" + +BEGIN_CHCORE_NAMESPACE + +TSimpleTimer::TSimpleTimer(bool bAutostart, const ITimestampProviderPtr& spTimestampProvider) : + m_spTimestampProvider(spTimestampProvider), + m_bStarted(false), + m_ullLastTime(0), + m_ullTotalTime(0) +{ + if(!spTimestampProvider) + m_spTimestampProvider = ITimestampProviderPtr(new TTimestampProviderTickCount); + + if(bAutostart) + Start(); +} + +TSimpleTimer::~TSimpleTimer() +{ +} + +void TSimpleTimer::Start() +{ + if(!m_bStarted) + { + m_bStarted = true; + m_ullLastTime = m_spTimestampProvider->GetCurrentTimestamp(); + } +} + +unsigned long long TSimpleTimer::Stop() +{ + if(m_bStarted) + { + Tick(); + m_bStarted = false; + } + + return m_ullTotalTime; +} + +unsigned long long TSimpleTimer::Tick() +{ + unsigned long long ullCurrent = m_spTimestampProvider->GetCurrentTimestamp(); + if(m_bStarted) + m_ullTotalTime += ullCurrent - m_ullLastTime; + m_ullLastTime = ullCurrent; + + return ullCurrent; +} + +void TSimpleTimer::Reset() +{ + m_bStarted = false; + m_ullLastTime = 0; + m_ullTotalTime = 0; +} + +END_CHCORE_NAMESPACE Index: src/libchcore/TSimpleTimer.h =================================================================== diff -u --- src/libchcore/TSimpleTimer.h (revision 0) +++ src/libchcore/TSimpleTimer.h (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,52 @@ +// ============================================================================ +// Copyright (C) 2001-2013 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TSIMPLETIMER_H__ +#define __TSIMPLETIMER_H__ + +#include "libchcore.h" +#include "ITimestampProvider.h" + +BEGIN_CHCORE_NAMESPACE + +class TSimpleTimer +{ +public: + TSimpleTimer(bool bAutostart = false, const ITimestampProviderPtr& spTimestampProvider = ITimestampProviderPtr()); + ~TSimpleTimer(); + + void Start(); + unsigned long long Stop(); // returns total time + unsigned long long Tick(); // returns current timestamp + + void Reset(); + + unsigned long long GetTotalTime() const { return m_ullTotalTime; } + unsigned long long GetLastTimestamp() const { return m_ullLastTime; } + +private: + ITimestampProviderPtr m_spTimestampProvider; + + bool m_bStarted; + unsigned long long m_ullTotalTime; // total time measured + unsigned long long m_ullLastTime; // last processed time +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/TSpeedTracker.cpp =================================================================== diff -u --- src/libchcore/TSpeedTracker.cpp (revision 0) +++ src/libchcore/TSpeedTracker.cpp (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,194 @@ +#include "stdafx.h" +#include "TSpeedTracker.h" +#include +#include +#include "ErrorCodes.h" +#include "TCoreException.h" +#include "MathFunctions.h" + +BEGIN_CHCORE_NAMESPACE + +TSpeedTracker::TSpeedTracker(unsigned long long ullTrackTime, unsigned long long ullSampleTime) : + m_stRequiredSamples(ullSampleTime ? boost::numeric_cast(ullTrackTime / ullSampleTime) : 0), + m_ullSampleTime(ullSampleTime), + m_dSamplesPerSecond(ullSampleTime != 0 ? 1000.0 / ullSampleTime : 0.0), + m_dPartialSpeedNotInSamples(0), + m_ullTimeIntervalNotInSamples(0), + m_stNextSamplePos(0), + m_ullLastTimestamp(std::numeric_limits::max()), + m_ullZeroIntervalData(0) +{ + if(m_ullSampleTime == 0 || m_stRequiredSamples == 0) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + std::fill_n(std::inserter(m_vSamples, m_vSamples.end()), m_stRequiredSamples, 0.0); +} + +void TSpeedTracker::Clear() +{ + m_dPartialSpeedNotInSamples = 0; + m_ullTimeIntervalNotInSamples = 0; + m_stNextSamplePos = 0; + m_ullLastTimestamp = std::numeric_limits::max(); + m_ullZeroIntervalData = 0; + std::fill(m_vSamples.begin(), m_vSamples.end(), 0.0); +} + +void TSpeedTracker::AddSample(unsigned long long ullValue, unsigned long long ullTimestamp) +{ + // if this is the first sample ever added (after construction or after clear) then + // we don't have time interval yet - just remember the timestamp and ignore value + if(m_ullLastTimestamp == std::numeric_limits::max()) + { + m_ullLastTimestamp = ullTimestamp; + return; + } + + // sanity check - make sure the data is valid + if(ullTimestamp < m_ullLastTimestamp) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + + // calculate the interval since the time last sample was added + unsigned long long ullInterval = ullTimestamp - m_ullLastTimestamp; + m_ullLastTimestamp = ullTimestamp; + + if(ullInterval == 0) // special case 0: if interval is 0 - put the data sample somewhere for future use + { + m_ullZeroIntervalData += ullValue; + return; + } + else if(ullInterval >= m_ullSampleTime * m_stRequiredSamples) // special case 1: interval is bigger than what we track + { + m_stNextSamplePos = 0; + m_dPartialSpeedNotInSamples = 0.0; + m_ullTimeIntervalNotInSamples = 0; + m_ullZeroIntervalData = 0; + + double dSpeed = NormalizeValueByTime(ullValue, ullInterval, m_ullSampleTime); + std::fill(m_vSamples.begin(), m_vSamples.end(), dSpeed); + return; + } + else + { + // append the data from previous zero-interval samples + ullValue += m_ullZeroIntervalData; + m_ullZeroIntervalData = 0; + } + + // calculate speed + double dSpeed = NormalizeValueByTime(ullValue, ullInterval, m_ullSampleTime); + + // finalize the incomplete sample and adjust the input data + FinalizeIncompleteSample(dSpeed, ullInterval); + + // deal with the full samples + AddCompleteSamples(dSpeed, ullInterval); + + // and finally prepare the incomplete sample data for future use + PrepareIncompleteSample(ullInterval, dSpeed); +} + +double TSpeedTracker::GetSpeed() const +{ + double dResult = 0.0; + + if(m_ullTimeIntervalNotInSamples != 0) + { + dResult = CalculateIncompleteSampleNormalizedSpeed(); + + for(size_t stIndex = 0; stIndex < m_vSamples.size(); ++stIndex) + { + if(stIndex != m_stNextSamplePos) + dResult += m_vSamples[stIndex]; + } + } + else + dResult = std::accumulate(m_vSamples.begin(), m_vSamples.end(), 0.0); + + return dResult / m_vSamples.size() * m_dSamplesPerSecond; +} + +void TSpeedTracker::AppendSamples(double dSpeed, size_t stSamplesCount) +{ + if(m_vSamples.size() != m_stRequiredSamples) + THROW_CORE_EXCEPTION(eErr_InternalProblem); + + stSamplesCount = std::min(stSamplesCount, m_stRequiredSamples); + while(stSamplesCount--) + { + m_vSamples[GetNextSampleIndexAndIncrease()] = dSpeed; + } +} + +size_t TSpeedTracker::GetNextSampleIndexAndIncrease() +{ + size_t stResult = m_stNextSamplePos++; + if(m_stNextSamplePos >= m_vSamples.size()) + m_stNextSamplePos = 0; + return stResult; +} + +double TSpeedTracker::NormalizeValueByTime(unsigned long long ullValue, unsigned long long ullTime, unsigned long long ullNormalizeTime) +{ + return Math::Div64(ullNormalizeTime, ullTime) * ullValue; +} + +void TSpeedTracker::FinalizeIncompleteSample(double dSpeed, unsigned long long& ullInterval) +{ + if(m_ullTimeIntervalNotInSamples == 0 || m_dPartialSpeedNotInSamples == 0.0 || ullInterval == 0) + return; + + // how much data do we need? + unsigned long long ullIntervalStillNeeded = m_ullSampleTime - m_ullTimeIntervalNotInSamples; + if(ullInterval < ullIntervalStillNeeded) + { + // we can only add the next partial sample, but cannot finalize + m_ullTimeIntervalNotInSamples += ullInterval; + m_dPartialSpeedNotInSamples += dSpeed * Math::Div64(ullInterval, m_ullSampleTime); + ullInterval = 0; + } + else + { + // going to finalize sample + m_dPartialSpeedNotInSamples += dSpeed * Math::Div64(ullIntervalStillNeeded, m_ullSampleTime); + + m_vSamples[GetNextSampleIndexAndIncrease()] = m_dPartialSpeedNotInSamples; + ullInterval -= ullIntervalStillNeeded; + + m_dPartialSpeedNotInSamples = 0.0; + m_ullTimeIntervalNotInSamples = 0; + } +} + +void TSpeedTracker::AddCompleteSamples(double dSpeed, unsigned long long& ullInterval) +{ + size_t stSamplesCount = boost::numeric_cast(std::min(ullInterval / m_ullSampleTime, (unsigned long long)m_stRequiredSamples)); + + // fill the container with full samples + while(stSamplesCount--) + { + m_vSamples[GetNextSampleIndexAndIncrease()] = dSpeed; + } + + ullInterval = ullInterval % m_ullSampleTime; +} + +double TSpeedTracker::CalculateIncompleteSampleNormalizedSpeed() const +{ + // get the speed for incomplete sample + double dIncompleteSamplePercentage = Math::Div64(m_ullTimeIntervalNotInSamples, m_ullSampleTime); + double dResult = m_dPartialSpeedNotInSamples + (1.0 - dIncompleteSamplePercentage) * m_vSamples[m_stNextSamplePos]; + + return dResult; +} + +void TSpeedTracker::PrepareIncompleteSample(unsigned long long ullInterval, double dSpeed) +{ + if(ullInterval > 0) + { + // we can only add the next partial sample, but cannot finalize + m_ullTimeIntervalNotInSamples = ullInterval; + m_dPartialSpeedNotInSamples = dSpeed * Math::Div64(ullInterval, m_ullSampleTime); + } +} + +END_CHCORE_NAMESPACE Index: src/libchcore/TSpeedTracker.h =================================================================== diff -u --- src/libchcore/TSpeedTracker.h (revision 0) +++ src/libchcore/TSpeedTracker.h (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,51 @@ +#ifndef __TSPEEDTRACKER_H__ +#define __TSPEEDTRACKER_H__ + +#include "libchcore.h" + +BEGIN_CHCORE_NAMESPACE + +class TSpeedTracker +{ +public: + TSpeedTracker(unsigned long long ullTrackTime, unsigned long long ullSampleTime); + + void AddSample(unsigned long long ullValue, unsigned long long ullTimestamp); + void Clear(); + + // retrieves speed per second + double GetSpeed() const; + +private: + TSpeedTracker(const TSpeedTracker&); + TSpeedTracker& operator=(const TSpeedTracker&); + + static double NormalizeValueByTime(unsigned long long ullValue, unsigned long long ullTime, unsigned long long ullNormalizeTime = 1000); + void AppendSamples(double dSpeed, size_t stSamplesCount); + + size_t GetNextSampleIndexAndIncrease(); + void FinalizeIncompleteSample(double dSpeed, unsigned long long& ullInterval); + void AddCompleteSamples(double dSpeed, unsigned long long& ullInterval); + void PrepareIncompleteSample( unsigned long long ullInterval, double dSpeed ); + double CalculateIncompleteSampleNormalizedSpeed() const; + +private: + // initialized in constructor (does not change throughout the whole lifetime) + const size_t m_stRequiredSamples; // how many samples of m_ullSampleTime do we want to keep? + const unsigned long long m_ullSampleTime; // interval covered by a single sample + const double m_dSamplesPerSecond; // how many samples fit in one second + + // vector of samples with pointer to the next element to be filled + std::vector m_vSamples; // speed per sample + size_t m_stNextSamplePos; // points to the element with the oldest sample + + unsigned long long m_ullLastTimestamp; // last time some sample was processed + + double m_dPartialSpeedNotInSamples; // specifies count of data processed in the m_ullTimeIntervalNotInSamples interval + unsigned long long m_ullTimeIntervalNotInSamples; // interval that was not enough to add m_ullDataNotInSamples to samples + unsigned long long m_ullZeroIntervalData; +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/TSubTaskCopyMove.cpp =================================================================== diff -u -r548382442cbf7bed7f744b279ce3f66b54992724 -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 548382442cbf7bed7f744b279ce3f66b54992724) +++ src/libchcore/TSubTaskCopyMove.cpp (.../TSubTaskCopyMove.cpp) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -236,6 +236,8 @@ // new stats m_tSubTaskStats.SetProcessedCount(stIndex); m_tSubTaskStats.SetCurrentPath(pathCurrent.ToString()); + m_tSubTaskStats.SetCurrentItemProcessedSize(0); + m_tSubTaskStats.SetCurrentItemTotalSize(spFileInfo->GetLength64()); // set dest path with filename ccp.pathDstFile = CalculateDestinationPath(spFileInfo, rTaskDefinition.GetDestinationPath(), ((int)bForceDirectories) << 1 | (int)bIgnoreFolders); @@ -252,6 +254,7 @@ // new stats m_tSubTaskStats.IncreaseProcessedSize(spFileInfo->GetLength64()); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(spFileInfo->GetLength64()); spFileInfo->SetFlags(FIF_PROCESSED, FIF_PROCESSED); } @@ -423,6 +426,7 @@ { // new stats m_tSubTaskStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); pData->bProcessed = false; return TSubTaskBase::eSubResult_Continue; @@ -452,6 +456,7 @@ { // new stats m_tSubTaskStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); pData->bProcessed = false; return TSubTaskBase::eSubResult_Continue; @@ -463,6 +468,7 @@ m_tProgressInfo.IncreaseCurrentFileProcessedSize(ulWritten); // new stats m_tSubTaskStats.IncreaseProcessedSize(ulWritten); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(ulWritten); // duplicate of m_tProgressInfo.IncreaseCurrentFileProcessedSize(ulWritten); } } while(!bLastPart); @@ -488,6 +494,7 @@ // invalid handle = operation skipped by user // new stats m_tSubTaskStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); pData->bProcessed = false; bSkip = true; @@ -515,6 +522,7 @@ { // new stats m_tSubTaskStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); pData->bProcessed = false; bSkip = true; @@ -531,6 +539,7 @@ { // new stats m_tSubTaskStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); pData->bProcessed = false; bSkip = true; @@ -545,6 +554,7 @@ // we don't copy contents, but need to increase processed size // new stats m_tSubTaskStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); return TSubTaskBase::eSubResult_Continue; } @@ -561,6 +571,7 @@ { // new stats m_tSubTaskStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); pData->bProcessed = false; return TSubTaskBase::eSubResult_Continue; @@ -574,6 +585,7 @@ // with either first or second seek we got 'skip' answer... // new stats m_tSubTaskStats.IncreaseProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(pData->spSrcFile->GetLength64() - m_tProgressInfo.GetCurrentFileProcessedSize()); pData->bProcessed = false; return TSubTaskBase::eSubResult_Continue; @@ -582,6 +594,7 @@ m_tProgressInfo.IncreaseCurrentFileProcessedSize(ullMove); // new stats m_tSubTaskStats.IncreaseProcessedSize(ullMove); + m_tSubTaskStats.IncreaseCurrentItemProcessedSize(ullMove); } // if the destination file already exists - truncate it to the current file position Index: src/libchcore/TSubTaskStatsInfo.cpp =================================================================== diff -u -r548382442cbf7bed7f744b279ce3f66b54992724 -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/libchcore/TSubTaskStatsInfo.cpp (.../TSubTaskStatsInfo.cpp) (revision 548382442cbf7bed7f744b279ce3f66b54992724) +++ src/libchcore/TSubTaskStatsInfo.cpp (.../TSubTaskStatsInfo.cpp) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -55,8 +55,10 @@ m_stProcessedCount(0), m_iCurrentBufferIndex(0), m_strCurrentPath(), - m_timeElapsed(0), - m_timeLast(-1) + m_tSizeSpeed(DefaultSpeedTrackTime, DefaultSpeedSampleTime), + m_tCountSpeed(DefaultSpeedTrackTime, DefaultSpeedSampleTime), + m_ullCurrentItemProcessedSize(0), + m_ullCurrentItemTotalSize(0) { } @@ -69,8 +71,11 @@ m_stProcessedCount = 0; m_iCurrentBufferIndex = 0; m_strCurrentPath.Clear(); - m_timeElapsed = 0; - m_timeLast = -1; + m_tTimer.Reset(); + m_tSizeSpeed.Clear(); + m_tCountSpeed.Clear(); + m_ullCurrentItemProcessedSize = 0; + m_ullCurrentItemTotalSize = 0; } void TSubTaskStatsInfo::GetSnapshot(TSubTaskStatsSnapshot& rStatsSnapshot) const @@ -85,10 +90,13 @@ rStatsSnapshot.SetTotalCount(m_stTotalCount); rStatsSnapshot.SetProcessedSize(m_ullProcessedSize); rStatsSnapshot.SetTotalSize(m_ullTotalSize); - rStatsSnapshot.SetProgressInPercent(CalculateProgressInPercent(lock)); rStatsSnapshot.SetCurrentBufferIndex(m_iCurrentBufferIndex); rStatsSnapshot.SetCurrentPath(m_strCurrentPath); - rStatsSnapshot.SetTimeElapsed(m_timeElapsed); + rStatsSnapshot.SetTimeElapsed(m_tTimer.GetTotalTime()); + rStatsSnapshot.SetSizeSpeed(m_tSizeSpeed.GetSpeed()); + rStatsSnapshot.SetCountSpeed(m_tCountSpeed.GetSpeed()); + rStatsSnapshot.SetCurrentItemProcessedSize(m_ullCurrentItemProcessedSize); + rStatsSnapshot.SetCurrentItemTotalSize(m_ullCurrentItemTotalSize); } // is running? @@ -108,6 +116,9 @@ { boost::unique_lock lock(m_lock); m_stProcessedCount += stIncreaseBy; + + m_tCountSpeed.AddSample(stIncreaseBy, m_tTimer.Tick()); + _ASSERTE(m_stProcessedCount <= m_stTotalCount); if(m_stProcessedCount > m_stTotalCount) THROW_CORE_EXCEPTION(eErr_InternalProblem); @@ -116,7 +127,11 @@ void TSubTaskStatsInfo::SetProcessedCount(size_t stProcessedCount) { boost::unique_lock lock(m_lock); + + m_tCountSpeed.AddSample(stProcessedCount - m_stProcessedCount, m_tTimer.Tick()); + m_stProcessedCount = stProcessedCount; + _ASSERTE(m_stProcessedCount <= m_stTotalCount); if(m_stProcessedCount > m_stTotalCount) THROW_CORE_EXCEPTION(eErr_InternalProblem); @@ -135,6 +150,9 @@ { boost::unique_lock lock(m_lock); m_ullProcessedSize += ullIncreaseBy; + + m_tSizeSpeed.AddSample(ullIncreaseBy, m_tTimer.Tick()); + _ASSERTE(m_ullProcessedSize <= m_ullTotalSize); if(m_ullProcessedSize > m_ullTotalSize) THROW_CORE_EXCEPTION(eErr_InternalProblem); @@ -143,6 +161,9 @@ void TSubTaskStatsInfo::SetProcessedSize(unsigned long long ullProcessedSize) { boost::unique_lock lock(m_lock); + + m_tSizeSpeed.AddSample(ullProcessedSize - m_ullProcessedSize, m_tTimer.Tick()); + m_ullProcessedSize = ullProcessedSize; _ASSERTE(m_ullProcessedSize <= m_ullTotalSize); if(m_ullProcessedSize > m_ullTotalSize) @@ -158,6 +179,36 @@ THROW_CORE_EXCEPTION(eErr_InternalProblem); } +// current item +void TSubTaskStatsInfo::IncreaseCurrentItemProcessedSize(unsigned long long ullIncreaseBy) +{ + boost::unique_lock lock(m_lock); + m_ullCurrentItemProcessedSize += ullIncreaseBy; + + _ASSERTE(m_ullCurrentItemProcessedSize <= m_ullCurrentItemTotalSize); + if(m_ullCurrentItemProcessedSize > m_ullCurrentItemTotalSize) + THROW_CORE_EXCEPTION(eErr_InternalProblem); +} + +void TSubTaskStatsInfo::SetCurrentItemProcessedSize(unsigned long long ullProcessedSize) +{ + boost::unique_lock lock(m_lock); + + m_ullCurrentItemProcessedSize = ullProcessedSize; + _ASSERTE(m_ullCurrentItemProcessedSize <= m_ullCurrentItemTotalSize); + if(m_ullCurrentItemProcessedSize > m_ullCurrentItemTotalSize) + THROW_CORE_EXCEPTION(eErr_InternalProblem); +} + +void TSubTaskStatsInfo::SetCurrentItemTotalSize(unsigned long long ullTotalSize) +{ + boost::unique_lock lock(m_lock); + m_ullCurrentItemTotalSize = ullTotalSize; + _ASSERTE(m_ullCurrentItemProcessedSize <= m_ullCurrentItemTotalSize); + if(m_ullCurrentItemProcessedSize > m_ullCurrentItemTotalSize) + THROW_CORE_EXCEPTION(eErr_InternalProblem); +} + // buffer index void TSubTaskStatsInfo::SetCurrentBufferIndex(int iCurrentIndex) { @@ -172,62 +223,24 @@ } // time -void TSubTaskStatsInfo::SetTimeElapsed(time_t timeElapsed) +void TSubTaskStatsInfo::EnableTimeTracking() { boost::unique_lock lock(m_lock); - m_timeElapsed = timeElapsed; + m_tTimer.Start(); } -void TSubTaskStatsInfo::EnableTimeTracking() -{ - boost::upgrade_lock lock(m_lock); - if(m_timeLast == -1) - { - boost::upgrade_to_unique_lock lock_upgraded(lock); - m_timeLast = time(NULL); - } -} - void TSubTaskStatsInfo::DisableTimeTracking() { - boost::upgrade_lock lock(m_lock); - - UpdateTime(lock); - - if(m_timeLast != -1) - { - boost::upgrade_to_unique_lock lock_upgraded(lock); - m_timeLast = -1; - } + boost::unique_lock lock(m_lock); + m_tTimer.Stop(); } void TSubTaskStatsInfo::UpdateTime(boost::upgrade_lock& lock) const { - 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; - } + boost::upgrade_to_unique_lock lock_upgraded(lock); + m_tTimer.Tick(); + m_tSizeSpeed.AddSample(0, m_tTimer.GetLastTimestamp()); + m_tCountSpeed.AddSample(0, m_tTimer.GetLastTimestamp()); } -double TSubTaskStatsInfo::CalculateProgressInPercent(boost::upgrade_lock& lock) const -{ - lock; // lock unused; enforced passing as parameter to ensure the code is executed in critical section - double dSizePercent = 0; - double dCountPercent = 0; - - if(m_ullTotalSize) - dSizePercent = 100.0 * boost::numeric_cast(m_ullProcessedSize) / boost::numeric_cast(m_ullTotalSize); - if(m_stTotalCount) - dCountPercent = 100.0 * boost::numeric_cast(m_stProcessedCount) / boost::numeric_cast(m_stTotalCount); - - if(m_ullTotalSize && m_stTotalCount) - return (dSizePercent + dCountPercent) / 2; - else - return dSizePercent + dCountPercent; -} - END_CHCORE_NAMESPACE Index: src/libchcore/TSubTaskStatsInfo.h =================================================================== diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/libchcore/TSubTaskStatsInfo.h (.../TSubTaskStatsInfo.h) (revision 12a1725bfd04b0f55fd0fda302975fdcd4174943) +++ src/libchcore/TSubTaskStatsInfo.h (.../TSubTaskStatsInfo.h) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -25,6 +25,8 @@ #include "libchcore.h" #include "TString.h" +#include "TSimpleTimer.h" +#include "TSpeedTracker.h" BEGIN_CHCORE_NAMESPACE @@ -48,6 +50,10 @@ class TSubTaskStatsInfo { +private: + static const unsigned long long DefaultSpeedTrackTime = 1000; // in miliseconds + static const unsigned long long DefaultSpeedSampleTime = 100; // in miliseconds + public: TSubTaskStatsInfo(); @@ -66,15 +72,18 @@ void SetTotalSize(unsigned long long ullTotalSize); + // current item + void IncreaseCurrentItemProcessedSize(unsigned long long ullIncreaseBy); + void SetCurrentItemProcessedSize(unsigned long long ullProcessedSize); + + void SetCurrentItemTotalSize(unsigned long long ullTotalSize); + // buffer index void SetCurrentBufferIndex(int iCurrentIndex); // current path void SetCurrentPath(const TString& strPath); - // time - void SetTimeElapsed(time_t timeElapsed); - private: TSubTaskStatsInfo(const TSubTaskStatsInfo&); TSubTaskStatsInfo& operator=(const TSubTaskStatsInfo&); @@ -88,25 +97,26 @@ void DisableTimeTracking(); void UpdateTime(boost::upgrade_lock& lock) const; - // calculates progress in percent - double CalculateProgressInPercent(boost::upgrade_lock& lock) const; - private: bool m_bSubTaskIsRunning; unsigned long long m_ullTotalSize; unsigned long long m_ullProcessedSize; + mutable TSpeedTracker m_tSizeSpeed; size_t m_stTotalCount; size_t m_stProcessedCount; + mutable TSpeedTracker m_tCountSpeed; + unsigned long long m_ullCurrentItemProcessedSize; + unsigned long long m_ullCurrentItemTotalSize; + + mutable TSimpleTimer m_tTimer; + int m_iCurrentBufferIndex; TString m_strCurrentPath; // currently processed path - mutable time_t m_timeElapsed; - mutable time_t m_timeLast; - #pragma warning(push) #pragma warning(disable: 4251) mutable boost::shared_mutex m_lock; Index: src/libchcore/TSubTaskStatsSnapshot.cpp =================================================================== diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/libchcore/TSubTaskStatsSnapshot.cpp (.../TSubTaskStatsSnapshot.cpp) (revision 12a1725bfd04b0f55fd0fda302975fdcd4174943) +++ src/libchcore/TSubTaskStatsSnapshot.cpp (.../TSubTaskStatsSnapshot.cpp) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -23,6 +23,8 @@ #include "stdafx.h" #include "TSubTaskStatsSnapshot.h" #include "DataBuffer.h" +#include +#include "MathFunctions.h" BEGIN_CHCORE_NAMESPACE @@ -36,7 +38,11 @@ m_stProcessedCount(0), m_iCurrentBufferIndex(TBufferSizes::eBuffer_Default), m_strCurrentPath(0), - m_timeElapsed(0) + m_timeElapsed(0), + m_dSizeSpeed(0), + m_dCountSpeed(0), + m_ullCurrentItemProcessedSize(0), + m_ullCurrentItemTotalSize(0) { } @@ -48,9 +54,12 @@ m_stProcessedCount(rSrc.m_stProcessedCount), m_iCurrentBufferIndex(rSrc.m_iCurrentBufferIndex), m_strCurrentPath(rSrc.m_strCurrentPath), - m_timeElapsed(rSrc.m_timeElapsed) + m_timeElapsed(rSrc.m_timeElapsed), + m_dSizeSpeed(rSrc.m_dSizeSpeed), + m_dCountSpeed(rSrc.m_dCountSpeed), + m_ullCurrentItemProcessedSize(rSrc.m_ullCurrentItemProcessedSize), + m_ullCurrentItemTotalSize(rSrc.m_ullCurrentItemTotalSize) { - } TSubTaskStatsSnapshot& TSubTaskStatsSnapshot::operator=(const TSubTaskStatsSnapshot& rSrc) @@ -63,6 +72,10 @@ m_iCurrentBufferIndex = rSrc.m_iCurrentBufferIndex; m_strCurrentPath = rSrc.m_strCurrentPath; m_timeElapsed = rSrc.m_timeElapsed; + m_dSizeSpeed = rSrc.m_dSizeSpeed; + m_dCountSpeed = rSrc.m_dCountSpeed; + m_ullCurrentItemProcessedSize = rSrc.m_ullCurrentItemProcessedSize; + m_ullCurrentItemTotalSize = rSrc.m_ullCurrentItemTotalSize; return *this; } @@ -77,6 +90,53 @@ m_iCurrentBufferIndex = TBufferSizes::eBuffer_Default; m_strCurrentPath = 0; m_timeElapsed = 0; + m_dSizeSpeed = 0; + m_dCountSpeed = 0; + m_ullCurrentItemProcessedSize = 0; + m_ullCurrentItemTotalSize = 0; } +double TSubTaskStatsSnapshot::CalculateProgressInPercent() const +{ + if(m_ullTotalSize != 0) + return Math::Div64(m_ullProcessedSize, m_ullTotalSize); + else + return 0.0; +} + +unsigned long long TSubTaskStatsSnapshot::GetEstimatedTotalTime() const +{ + double dProgress = CalculateProgressInPercent(); + if(dProgress == 0.0) + return std::numeric_limits::max(); + else + return (unsigned long long)(m_timeElapsed * (1.0 / dProgress)); +} + +void TSubTaskStatsSnapshot::SetSizeSpeed(double dSizeSpeed) +{ + m_dSizeSpeed = dSizeSpeed; +} + +void TSubTaskStatsSnapshot::SetCountSpeed(double dCountSpeed) +{ + m_dCountSpeed = dCountSpeed; +} + +double TSubTaskStatsSnapshot::GetAvgSizeSpeed() const +{ + if(m_timeElapsed) + return Math::Div64(m_ullProcessedSize, m_timeElapsed / 1000); + else + return 0.0; +} + +double TSubTaskStatsSnapshot::GetAvgCountSpeed() const +{ + if(m_timeElapsed) + return Math::Div64(m_stProcessedCount, m_timeElapsed / 1000); + else + return 0.0; +} + END_CHCORE_NAMESPACE Index: src/libchcore/TSubTaskStatsSnapshot.h =================================================================== diff -u -r12a1725bfd04b0f55fd0fda302975fdcd4174943 -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/libchcore/TSubTaskStatsSnapshot.h (.../TSubTaskStatsSnapshot.h) (revision 12a1725bfd04b0f55fd0fda302975fdcd4174943) +++ src/libchcore/TSubTaskStatsSnapshot.h (.../TSubTaskStatsSnapshot.h) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -56,9 +56,15 @@ void SetTotalSize(unsigned long long ullTotalSize) { m_ullTotalSize = ullTotalSize; } unsigned long long GetTotalSize() const { return m_ullTotalSize; } + // current file + void SetCurrentItemProcessedSize(unsigned long long ullProcessedSize) { m_ullCurrentItemProcessedSize = ullProcessedSize; } + unsigned long long GetCurrentItemProcessedSize() const { return m_ullCurrentItemProcessedSize; } + + void SetCurrentItemTotalSize(unsigned long long ullTotalSize) { m_ullCurrentItemTotalSize = ullTotalSize; } + unsigned long long GetCurrentItemTotalSize() const { return m_ullCurrentItemTotalSize; } + // progress in percent - void SetProgressInPercent(double dPercent) { m_dProgressInPercent = dPercent; } - double GetProgressInPercent() const { return m_dProgressInPercent; } + double GetProgressInPercent() const { return CalculateProgressInPercent(); } // buffer index void SetCurrentBufferIndex(int iCurrentIndex) { m_iCurrentBufferIndex = iCurrentIndex; } @@ -69,25 +75,46 @@ const TString& GetCurrentPath() const { return m_strCurrentPath; } // time - void SetTimeElapsed(time_t timeElapsed) { m_timeElapsed = timeElapsed; } - time_t GetTimeElapsed() { return m_timeElapsed; } + void SetTimeElapsed(unsigned long long timeElapsed) { m_timeElapsed = timeElapsed; } + unsigned long long GetTimeElapsed() { return m_timeElapsed; } + // time estimations + unsigned long long GetEstimatedTotalTime() const; + + // speed + void SetSizeSpeed(double dSizeSpeed); + double GetSizeSpeed() const { return m_dSizeSpeed; } + void SetCountSpeed(double dCountSpeed); + double GetCountSpeed() const { return m_dCountSpeed; } + + double GetAvgSizeSpeed() const; + double GetAvgCountSpeed() const; + private: + double CalculateProgressInPercent() const; + +private: bool m_bSubTaskIsRunning; + // subtask size and size speed per second unsigned long long m_ullTotalSize; unsigned long long m_ullProcessedSize; + double m_dSizeSpeed; + // subtask count of items and its speed per second size_t m_stTotalCount; size_t m_stProcessedCount; + double m_dCountSpeed; - double m_dProgressInPercent; + // current item size + unsigned long long m_ullCurrentItemTotalSize; + unsigned long long m_ullCurrentItemProcessedSize; int m_iCurrentBufferIndex; TString m_strCurrentPath; // currently processed path - time_t m_timeElapsed; + unsigned long long m_timeElapsed; // time really elapsed for the subtask }; END_CHCORE_NAMESPACE Index: src/libchcore/TTask.cpp =================================================================== diff -u -r548382442cbf7bed7f744b279ce3f66b54992724 -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/libchcore/TTask.cpp (.../TTask.cpp) (revision 548382442cbf7bed7f744b279ce3f66b54992724) +++ src/libchcore/TTask.cpp (.../TTask.cpp) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -315,19 +315,18 @@ void TTask::GetSnapshot(TASK_DISPLAY_DATA *pData) { - TTaskStatsSnapshot tStats; - m_tSubTasksArray.GetTaskStats(tStats); + m_tSubTasksArray.GetTaskStats(pData->m_tTaskSnapshot); - pData->m_strFullFilePath = tStats.GetCurrentSubTaskStats().GetCurrentPath(); + pData->m_strFullFilePath = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetCurrentPath(); pData->m_strFileName = chcore::PathFromString(pData->m_strFullFilePath).GetFileName().ToString(); - pData->m_stIndex = tStats.GetCurrentSubTaskStats().GetProcessedCount(); - pData->m_stSize = tStats.GetCurrentSubTaskStats().GetTotalCount(); - pData->m_ullProcessedSize = tStats.GetCurrentSubTaskStats().GetProcessedSize(); - pData->m_ullSizeAll = tStats.GetCurrentSubTaskStats().GetTotalSize(); - pData->m_eSubOperationType = tStats.GetCurrentSubOperationType(); - pData->m_iCurrentBufferIndex = tStats.GetCurrentSubTaskStats().GetCurrentBufferIndex(); - pData->m_dPercent = tStats.GetTaskProgressInPercent(); - pData->m_timeElapsed = tStats.GetTimeElapsed(); + pData->m_stIndex = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetProcessedCount(); + pData->m_stSize = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetTotalCount(); + pData->m_ullProcessedSize = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetProcessedSize(); + pData->m_ullSizeAll = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetTotalSize(); + pData->m_eSubOperationType = pData->m_tTaskSnapshot.GetCurrentSubOperationType(); + pData->m_iCurrentBufferIndex = pData->m_tTaskSnapshot.GetCurrentSubTaskStats().GetCurrentBufferIndex(); + pData->m_dPercent = pData->m_tTaskSnapshot.GetTaskProgressInPercent(); + pData->m_timeElapsed = pData->m_tTaskSnapshot.GetTimeElapsed(); boost::shared_lock lock(m_lock); Index: src/libchcore/TTask.h =================================================================== diff -u -r1e687d59f0e622a610cbf97cf79febd12641d159 -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/libchcore/TTask.h (.../TTask.h) (revision 1e687d59f0e622a610cbf97cf79febd12641d159) +++ src/libchcore/TTask.h (.../TTask.h) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -32,6 +32,7 @@ #include "TFileInfoArray.h" #include "TSubTaskArray.h" #include "TSubTaskContext.h" +#include "TTaskStatsSnapshot.h" BEGIN_CHCORE_NAMESPACE @@ -55,6 +56,8 @@ // structure for getting status of a task struct TASK_DISPLAY_DATA { + chcore::TTaskStatsSnapshot m_tTaskSnapshot; + TString m_strFullFilePath; TString m_strFileName; Index: src/libchcore/TTimestampProviderTickCount.cpp =================================================================== diff -u --- src/libchcore/TTimestampProviderTickCount.cpp (revision 0) +++ src/libchcore/TTimestampProviderTickCount.cpp (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,43 @@ +// ============================================================================ +// Copyright (C) 2001-2013 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TTimestampProviderTickCount.h" + +BEGIN_CHCORE_NAMESPACE + +TTimestampProviderTickCount::TTimestampProviderTickCount() : + m_dwLastTimestamp(0), + m_ullTimestampAdjustment(0) +{ +} + +unsigned long long TTimestampProviderTickCount::GetCurrentTimestamp() const +{ + DWORD dwTimestamp = GetTickCount(); + if(dwTimestamp < m_dwLastTimestamp) + { + m_ullTimestampAdjustment += (1ULL << 32); + } + m_dwLastTimestamp = dwTimestamp; + + return m_ullTimestampAdjustment + dwTimestamp; +} + + +END_CHCORE_NAMESPACE Index: src/libchcore/TTimestampProviderTickCount.h =================================================================== diff -u --- src/libchcore/TTimestampProviderTickCount.h (revision 0) +++ src/libchcore/TTimestampProviderTickCount.h (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,41 @@ +// ============================================================================ +// Copyright (C) 2001-2013 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TTIMESTAMPPROVIDERTICKCOUNT_H__ +#define __TTIMESTAMPPROVIDERTICKCOUNT_H__ + +#include "libchcore.h" +#include "ITimestampProvider.h" + +BEGIN_CHCORE_NAMESPACE + +class TTimestampProviderTickCount : public ITimestampProvider +{ +public: + TTimestampProviderTickCount(); + + virtual unsigned long long GetCurrentTimestamp() const; + +private: + mutable unsigned long long m_ullTimestampAdjustment; + mutable DWORD m_dwLastTimestamp; +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/Tests/TestsTSimpleTimer.cpp =================================================================== diff -u --- src/libchcore/Tests/TestsTSimpleTimer.cpp (revision 0) +++ src/libchcore/Tests/TestsTSimpleTimer.cpp (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,90 @@ +#include "stdafx.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "../TSimpleTimer.h" +#include "../ITimestampProvider.h" + +class ITimestampProviderMock : public chcore::ITimestampProvider +{ +public: + MOCK_CONST_METHOD0(GetCurrentTimestamp, unsigned long long()); +}; + +using namespace testing; +using namespace chcore; + +TEST(TSimpleTimerTests, SimpleStartStop_CalculatesTimeProperly) +{ + boost::shared_ptr > spTimestampProviderMock(new StrictMock); + + EXPECT_CALL(*spTimestampProviderMock, GetCurrentTimestamp()) + .WillOnce(Return(30)) + .WillOnce(Return(100)); + + TSimpleTimer tTimer(false, spTimestampProviderMock); + tTimer.Start(); + EXPECT_EQ(70, tTimer.Stop()); + EXPECT_EQ(70, tTimer.GetTotalTime()); + EXPECT_EQ(100, tTimer.GetLastTimestamp()); +} + +TEST(TSimpleTimerTests, TickWithoutStarting_UpdatesLastTimestamp) +{ + boost::shared_ptr > spTimestampProviderMock(new StrictMock); + + EXPECT_CALL(*spTimestampProviderMock, GetCurrentTimestamp()) + .WillOnce(Return(30)); + + TSimpleTimer tTimer(false, spTimestampProviderMock); + tTimer.Tick(); + EXPECT_EQ(30, tTimer.GetLastTimestamp()); +} + +TEST(TSimpleTimerTests, StartAndTicking_CorrectlyCountsTime) +{ + boost::shared_ptr > spTimestampProviderMock(new StrictMock); + + EXPECT_CALL(*spTimestampProviderMock, GetCurrentTimestamp()) + .WillOnce(Return(30)) + .WillOnce(Return(40)) + .WillOnce(Return(990)); + + TSimpleTimer tTimer(false, spTimestampProviderMock); + tTimer.Start(); + tTimer.Tick(); + EXPECT_EQ(10, tTimer.GetTotalTime()); + tTimer.Tick(); + EXPECT_EQ((990 - 30), tTimer.GetTotalTime()); +} + +TEST(TSimpleTimerTests, StartAndTicking_TickReturnsLastTimestamp) +{ + boost::shared_ptr > spTimestampProviderMock(new StrictMock); + + EXPECT_CALL(*spTimestampProviderMock, GetCurrentTimestamp()) + .WillOnce(Return(30)) + .WillOnce(Return(40)) + .WillOnce(Return(990)); + + TSimpleTimer tTimer(false, spTimestampProviderMock); + tTimer.Start(); + EXPECT_EQ(40, tTimer.Tick()); + EXPECT_EQ(990, tTimer.Tick()); +} + +TEST(TSimpleTimerTests, Reset_StopsTimeCountingAndResetsTime) +{ + boost::shared_ptr > spTimestampProviderMock(new StrictMock); + + EXPECT_CALL(*spTimestampProviderMock, GetCurrentTimestamp()) + .WillOnce(Return(30)) + .WillOnce(Return(40)); + + TSimpleTimer tTimer(false, spTimestampProviderMock); + tTimer.Start(); + tTimer.Tick(); + + tTimer.Reset(); + EXPECT_EQ(tTimer.GetTotalTime(), 0); + EXPECT_EQ(tTimer.GetLastTimestamp(), 0); +} Index: src/libchcore/Tests/TestsTSpeedTracker.cpp =================================================================== diff -u --- src/libchcore/Tests/TestsTSpeedTracker.cpp (revision 0) +++ src/libchcore/Tests/TestsTSpeedTracker.cpp (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -0,0 +1,227 @@ +#include "stdafx.h" +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "../TSpeedTracker.h" +#include "../TCoreException.h" + +using namespace chcore; + +TEST(TSpeedTrackerTests, FirstSample_DoesNotChangeSpeed) +{ + TSpeedTracker tTracker(1000, 100); // track last second with 100ms samples + tTracker.AddSample(100, 0); // 100 bytes at timestamp 0 + EXPECT_DOUBLE_EQ(0.0, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, SingleCorrectSample_ExactSingleSampleBoundary) +{ + TSpeedTracker tTracker(1000, 100); // track last second with 100ms samples + tTracker.AddSample(0, 0); + tTracker.AddSample(8000, 100); // 100 bytes at timestamp 100 + + // should be a single sample of 80k/s (due to the normalization) + // with all other samples equal to 0 giving finally 8000/s; + // (or from a different perspective - we processes 8000 items in the entire + // second that we track) + EXPECT_DOUBLE_EQ(8000.0, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, SingleCorrectSample_NotAtSampleBoundary) +{ + TSpeedTracker tTracker(1000, 100); // track last second with 100ms samples + tTracker.AddSample(0, 0); + tTracker.AddSample(8000, 333); // 100 bytes at timestamp 333 + + // processed 8000 items in entire second (as there were no other samples) + EXPECT_DOUBLE_EQ(8000.0, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, ClearContents) +{ + TSpeedTracker tTracker(1000, 100); // track last second with 100ms samples + tTracker.AddSample(0, 0); + tTracker.AddSample(8000, 100); // 100 bytes at timestamp 333 + + tTracker.Clear(); + + EXPECT_DOUBLE_EQ(0.0, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, MultipleAlignedSamples_SampleRollOver) +{ + TSpeedTracker tTracker(1000, 100); // track last second with 100ms samples + tTracker.AddSample(0, 0); // start + tTracker.AddSample(8000, 100); + tTracker.AddSample(4000, 500); + tTracker.AddSample(5000, 1500); // one second sample; should overwrite entire sample cache + + // processed 8000 items in entire second (as there were no other samples) + EXPECT_DOUBLE_EQ(5000.0, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, MultipleUnAlignedSamplesWithNoPartialSamples_SampleRollOver) +{ + TSpeedTracker tTracker(1000, 100); // track last second with 100ms samples + tTracker.AddSample(0, 0); // start + tTracker.AddSample(8000, 110); + tTracker.AddSample(4000, 530); + tTracker.AddSample(5000, 1530); // one second sample; should overwrite entire sample cache + + // processed 8000 items in entire second (as there were no other samples) + EXPECT_DOUBLE_EQ(5000.0, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, MultipleUnAlignedSamplesWithPartialSamples_SampleRollOver) +{ + TSpeedTracker tTracker(1000, 100); // track last second with 100ms samples + tTracker.AddSample(0, 0); // start + tTracker.AddSample(8000, 110); + tTracker.AddSample(4000, 140); // a partial sample (30ms) + tTracker.AddSample(5000, 1140); // one second sample; should overwrite entire sample cache + + // processed 8000 items in entire second (as there were no other samples) + EXPECT_DOUBLE_EQ(5000.0, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, MultipleSamplesRecedingInTime_ThrowsException) +{ + TSpeedTracker tTracker(1000, 100); // track last second with 100ms samples + tTracker.AddSample(0, 0); // start + tTracker.AddSample(8000, 110); + EXPECT_THROW(tTracker.AddSample(4000, 40), TCoreException); +} + +TEST(TSpeedTrackerTests, MultipleSamplesCornerCase_VeryLargeInterval) +{ + TSpeedTracker tTracker(1000, 100); // track last second with 100ms samples + tTracker.AddSample(0, 0); // start + // interval exceeds 32bit by a lot (was causing problems on 32-bit windows) + EXPECT_NO_THROW(tTracker.AddSample(40000, 18446744073709551546)); +} + +TEST(TSpeedTrackerTests, SingleSampleWithEqualTrackTimeAndSampleTime) +{ + TSpeedTracker tTracker(1000, 1000); // track last second with 1 second samples + tTracker.AddSample(0, 0); // start + tTracker.AddSample(8000, 1000); + + // processed 8000 items in entire second (as there were no other samples) + EXPECT_DOUBLE_EQ(8000.0, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, MultipleSamplesWithEqualTrackTimeAndSampleTime) +{ + TSpeedTracker tTracker(1000, 1000); // track last second with 1 second samples + tTracker.AddSample(0, 0); // start + tTracker.AddSample(8000, 1000); + tTracker.AddSample(1000, 1500); + tTracker.AddSample(30000, 1800); + + // processed 8000 items in entire second (as there were no other samples) + EXPECT_DOUBLE_EQ(32600, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, MultipleSamplesWithBigTrackTime) +{ + TSpeedTracker tTracker(5000, 1000); // track last 5 seconds with 1 second samples + tTracker.AddSample(0, 0); // start + tTracker.AddSample(8000, 900); + tTracker.AddSample(1000, 1700); // 800 + tTracker.AddSample(30000, 2600); // 900 + + // processed 39000 items in last 5s, so speed is 7800 + EXPECT_DOUBLE_EQ(7800, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, MultipleSamplesWithBigTrackTimeAndSampleTime) +{ + TSpeedTracker tTracker(5000, 5000); // track last 5 seconds with 1 second samples + tTracker.AddSample(0, 0); // start + tTracker.AddSample(8000, 900); + tTracker.AddSample(1000, 1700); // 800 + tTracker.AddSample(30000, 2600); // 900 + + // processed 39000 items in last 5s, so speed is 7800 + EXPECT_DOUBLE_EQ(7800, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, MultipleSamplesWithTrackTimeAndSampleTimeDoesntMatch) +{ + TSpeedTracker tTracker(1000, 300); // there should be 3 samples inside + tTracker.AddSample(0, 0); // start + tTracker.AddSample(8000, 400); + tTracker.AddSample(1000, 800); + tTracker.AddSample(27000, 900); + + // processed 39000 items in last 5s, so speed is 7800 + EXPECT_DOUBLE_EQ(40000, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, ConstructionWithBadParams) +{ + // zero length sample is not allowed + EXPECT_THROW(TSpeedTracker tTracker(5000, 0), TCoreException); + // tracking time less than sample time is not allowed + EXPECT_THROW(TSpeedTracker tTracker(0, 1000), TCoreException); +} + +TEST(TSpeedTrackerTests, MultipleVeryShortSamplesWithZeroIntervalData_CornerCase) +{ + TSpeedTracker tTracker(1000, 100); + tTracker.AddSample(0, 0); // start + tTracker.AddSample(80, 10); + tTracker.AddSample(120, 10); + tTracker.AddSample(10, 10); + tTracker.AddSample(50, 10); + tTracker.AddSample(0, 10); + tTracker.AddSample(0, 10); + tTracker.AddSample(10, 20); + tTracker.AddSample(10, 20); + tTracker.AddSample(10, 20); + tTracker.AddSample(0, 20); + tTracker.AddSample(10, 30); + tTracker.AddSample(10, 30); + tTracker.AddSample(0, 30); + tTracker.AddSample(10, 40); + tTracker.AddSample(20, 40); // <-- this sample might be skipped when calculating speed + tTracker.AddSample(0, 40); + tTracker.AddSample(0, 40); + + // 340 in 1000ms = 340 items/s + // however 320 is reported, because the sample (marked above) is not counted + // in the speed calculation (has the same timestamp as previous sample) + // and this is the last timestamp used in the sample list. + + EXPECT_DOUBLE_EQ(320, tTracker.GetSpeed()); +} + +TEST(TSpeedTrackerTests, MultipleVeryShortSamplesWithZeroIntervalData) +{ + TSpeedTracker tTracker(1000, 100); + tTracker.AddSample(0, 0); // start + tTracker.AddSample(80, 10); + tTracker.AddSample(120, 10); + tTracker.AddSample(10, 10); + tTracker.AddSample(50, 10); + tTracker.AddSample(0, 10); + tTracker.AddSample(0, 10); + tTracker.AddSample(10, 20); + tTracker.AddSample(10, 20); + tTracker.AddSample(10, 20); + tTracker.AddSample(0, 20); + tTracker.AddSample(10, 30); + tTracker.AddSample(10, 30); + tTracker.AddSample(0, 30); + tTracker.AddSample(10, 40); + tTracker.AddSample(20, 40); + tTracker.AddSample(0, 40); + tTracker.AddSample(0, 40); + tTracker.AddSample(0, 50); + + // 340 in 1000ms = 340 items/s + // this case is similar to MultipleVeryShortSamplesWithZeroIntervalData_CornerCase + // but here we have additional empty sample added at the end with newer timestamp + // that should trigger inclusion of the previous same-timestamp samples + + EXPECT_DOUBLE_EQ(340, tTracker.GetSpeed()); +} Index: src/libchcore/libchcore.vc90.vcproj =================================================================== diff -u -r34362ad5984183ca77d47d185d285b4426381dd5 -r9b8cccbee0fcfeca28a112cc0253a7641f73f74f --- src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 34362ad5984183ca77d47d185d285b4426381dd5) +++ src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 9b8cccbee0fcfeca28a112cc0253a7641f73f74f) @@ -673,233 +673,321 @@ > - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - + - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -908,6 +996,14 @@ > + + + + @@ -936,6 +1032,14 @@ > + + + + @@ -944,6 +1048,46 @@ > + + + + + + + + + + + + + + + + + + + + @@ -968,6 +1112,22 @@ > + + + + + + + + @@ -1016,6 +1176,14 @@ > + + + + @@ -1025,164 +1193,24 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + #include #include +#include #include #include #include