Index: src/ch/ClipboardMonitor.cpp =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/ClipboardMonitor.cpp (.../ClipboardMonitor.cpp) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/ClipboardMonitor.cpp (.../ClipboardMonitor.cpp) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -23,7 +23,8 @@ #include "../libchcore/TWorkerThreadController.h" #include "ClipboardMonitor.h" #include "ch.h" -#include "../libchcore/task.h" +#include "../libchcore/TTaskManager.h" +#include "../libchcore/TTask.h" #include "CfgProperties.h" #include "FolderDialog.h" #include "ShutdownDlg.h" @@ -39,7 +40,7 @@ Stop(); } -void CClipboardMonitor::StartMonitor(chcore::CTaskArray* pTasks) +void CClipboardMonitor::StartMonitor(chcore::TTaskManager* pTasks) { CClipboardMonitor::S_ClipboardMonitor.Start(pTasks); } @@ -49,7 +50,7 @@ return CClipboardMonitor::S_ClipboardMonitor.Stop(); } -void CClipboardMonitor::Start(chcore::CTaskArray* pTasks) +void CClipboardMonitor::Start(chcore::TTaskManager* pTasks) { m_pTasks = pTasks; @@ -180,7 +181,7 @@ chcore::SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_FIRSTCOPY_STRING)); chcore::SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_NEXTCOPY_STRING)); - chcore::CTaskPtr spTask = pData->m_pTasks->CreateTask(tTaskDefinition); + chcore::TTaskPtr spTask = pData->m_pTasks->CreateTask(tTaskDefinition); // write spTask to a file spTask->Store(); Index: src/ch/ClipboardMonitor.h =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/ClipboardMonitor.h (.../ClipboardMonitor.h) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/ClipboardMonitor.h (.../ClipboardMonitor.h) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -24,16 +24,16 @@ namespace chcore { - class CTaskArray; + class TTaskManager; } class CClipboardMonitor { public: - static void StartMonitor(chcore::CTaskArray* pTasks); + static void StartMonitor(chcore::TTaskManager* pTasks); static void StopMonitor(); - void Start(chcore::CTaskArray* pTasks); + void Start(chcore::TTaskManager* pTasks); void Stop(); protected: @@ -45,7 +45,7 @@ protected: static CClipboardMonitor S_ClipboardMonitor; - chcore::CTaskArray* m_pTasks; + chcore::TTaskManager* m_pTasks; // thread control chcore::TWorkerThreadController m_threadWorker; Index: src/ch/MainWnd.cpp =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -381,7 +381,7 @@ ///////////////////////////////////////////////////////////////////////////// // CMainWnd/CTrayIcon menu message handlers -void CMainWnd::ShowStatusWindow(const chcore::CTaskPtr& spSelect) +void CMainWnd::ShowStatusWindow(const chcore::TTaskPtr& spSelect) { m_pdlgStatus=new CStatusDlg(&m_tasks, this); // self deleting m_pdlgStatus->m_spInitialSelection = spSelect; @@ -502,7 +502,7 @@ chcore::SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_NEXTCOPY_STRING)); // create task with the above definition - chcore::CTaskPtr spTask = m_tasks.CreateTask(tTaskDefinition); + chcore::TTaskPtr spTask = m_tasks.CreateTask(tTaskDefinition); // add to task list and start processing spTask->BeginProcessing(); @@ -550,7 +550,7 @@ try { - chcore::CTaskPtr spTask = m_tasks.ImportTask(strPath); + chcore::TTaskPtr spTask = m_tasks.ImportTask(strPath); if(spTask) spTask->Store(); bImported = true; @@ -612,7 +612,7 @@ chcore::SetTaskPropValue(tTaskDefinition.GetConfiguration(), GetResManager().LoadString(IDS_NEXTCOPY_STRING)); // new task - chcore::CTaskPtr spTask = m_tasks.CreateTask(tTaskDefinition); + chcore::TTaskPtr spTask = m_tasks.CreateTask(tTaskDefinition); // start spTask->BeginProcessing(); @@ -625,7 +625,7 @@ { case WM_MINIVIEWDBLCLK: { - chcore::CTaskPtr spTask = m_tasks.GetTaskBySessionUniqueID(lParam); + chcore::TTaskPtr spTask = m_tasks.GetTaskBySessionUniqueID(lParam); ShowStatusWindow(spTask); break; } Index: src/ch/MainWnd.h =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/MainWnd.h (.../MainWnd.h) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/MainWnd.h (.../MainWnd.h) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -22,7 +22,7 @@ #include "TrayIcon.h" #include "structs.h" -#include "../libchcore/task.h" +#include "../libchcore/TTaskManager.h" #include "../libchcore/TSharedMemory.h" class CMiniViewDlg; @@ -40,7 +40,7 @@ public: CTrayIcon m_ctlTray; - chcore::CTaskArray m_tasks; + chcore::TTaskManager m_tasks; chcore::IFeedbackHandlerFactory* m_pFeedbackFactory; chcore::TSharedMemory m_tCHExtharedMemory; @@ -68,7 +68,7 @@ protected: BOOL RegisterClass(); int ShowTrayIcon(); - void ShowStatusWindow(const chcore::CTaskPtr& spSelect = chcore::CTaskPtr()); + void ShowStatusWindow(const chcore::TTaskPtr& spSelect = chcore::TTaskPtr()); void PrepareToExit(); void ProcessCommandLine(const TCommandLineParser& rCommandLine); Index: src/ch/MiniViewDlg.cpp =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/MiniViewDlg.cpp (.../MiniViewDlg.cpp) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/MiniViewDlg.cpp (.../MiniViewDlg.cpp) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -17,7 +17,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "stdafx.h" -#include "../libchcore/task.h" +#include "../libchcore/TTaskManager.h" +#include "../libchcore/TTask.h" #include "MiniViewDlg.h" #include "ch.h" #include @@ -42,7 +43,7 @@ ///////////////////////////////////////////////////////////////////////////// // CMiniViewDlg dialog -CMiniViewDlg::CMiniViewDlg(chcore::CTaskArray* pArray, bool *pbHide, CWnd* pParent /*=NULL*/) +CMiniViewDlg::CMiniViewDlg(chcore::TTaskManager* pArray, bool *pbHide, CWnd* pParent /*=NULL*/) :ictranslate::CLanguageDialog(IDD_MINIVIEW_DIALOG, pParent, &m_bLock) { //{{AFX_DATA_INIT(CMiniViewDlg) @@ -184,7 +185,7 @@ { for(size_t stIndex = 0; stIndex < m_pTasks->GetSize(); ++stIndex) { - chcore::CTaskPtr spTask = m_pTasks->GetAt(stIndex); + chcore::TTaskPtr spTask = m_pTasks->GetAt(stIndex); spTask->GetMiniSnapshot(&m_tMiniDisplayData); if(m_tMiniDisplayData.m_eTaskState != chcore::eTaskState_Finished && m_tMiniDisplayData.m_eTaskState != chcore::eTaskState_Cancelled) @@ -410,7 +411,7 @@ if (iSel == LB_ERR || (size_t)iSel >= pDlg->m_ctlStatus.m_vItems.size()) return; - chcore::CTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask; + chcore::TTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask; if(spTask) spTask->PauseProcessing(); else @@ -517,7 +518,7 @@ int iSel=pDlg->m_ctlStatus.GetCurSel(); if (iSel == LB_ERR || (size_t)iSel >= pDlg->m_ctlStatus.m_vItems.size()) return; - chcore::CTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask; + chcore::TTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask; if (spTask) { if(spTask->GetTaskState() == chcore::eTaskState_Waiting) @@ -561,7 +562,7 @@ int iSel=pDlg->m_ctlStatus.GetCurSel(); if (iSel == LB_ERR || (size_t)iSel >= pDlg->m_ctlStatus.m_vItems.size()) return; - chcore::CTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask; + chcore::TTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask; if(spTask) spTask->CancelProcessing(); else @@ -615,7 +616,7 @@ int iSel=pDlg->m_ctlStatus.GetCurSel(); if (iSel == LB_ERR || (size_t)iSel >= pDlg->m_ctlStatus.m_vItems.size()) return; - chcore::CTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask; + chcore::TTaskPtr spTask = pDlg->m_ctlStatus.m_vItems.at(iSel)->m_spTask; if(spTask) spTask->RestartProcessing(); else @@ -809,7 +810,7 @@ if(iSel == LB_ERR || (size_t)iSel >= m_ctlStatus.m_vItems.size()) return; - chcore::CTaskPtr spTask = m_ctlStatus.m_vItems.at(iSel)->m_spTask; + chcore::TTaskPtr spTask = m_ctlStatus.m_vItems.at(iSel)->m_spTask; if(spTask) GetParent()->PostMessage(WM_MINIVIEWDBLCLK, 0, (LPARAM)spTask->GetSessionUniqueID()); else Index: src/ch/MiniViewDlg.h =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/MiniViewDlg.h (.../MiniViewDlg.h) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/MiniViewDlg.h (.../MiniViewDlg.h) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -22,10 +22,11 @@ ///////////////////////////////////////////////////////////////////////////// // CMiniViewDlg dialog #include "ProgressListBox.h" +#include "..\libchcore\TTask.h" namespace chcore { - class chcore::CTaskArray; + class chcore::TTaskManager; } #define BTN_COUNT 5 @@ -51,7 +52,7 @@ // Construction public: - CMiniViewDlg(chcore::CTaskArray* pArray, bool* pbHide, CWnd* pParent = NULL); // standard constructor + CMiniViewDlg(chcore::TTaskManager* pArray, bool* pbHide, CWnd* pParent = NULL); // standard constructor void ShowWindow(); void HideWindow(); @@ -69,7 +70,7 @@ virtual void OnLanguageChanged(); // from CMainWnd - chcore::CTaskArray *m_pTasks; + chcore::TTaskManager *m_pTasks; CBrush m_brBackground; int m_iLastHeight; Index: src/ch/ProgressListBox.cpp =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/ProgressListBox.cpp (.../ProgressListBox.cpp) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/ProgressListBox.cpp (.../ProgressListBox.cpp) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -17,7 +17,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "stdafx.h" -#include "../libchcore/task.h" +#include "../libchcore/TTaskManager.h" #include "ProgressListBox.h" #include "MemDC.h" Index: src/ch/ProgressListBox.h =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/ProgressListBox.h (.../ProgressListBox.h) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/ProgressListBox.h (.../ProgressListBox.h) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -30,7 +30,7 @@ COLORREF m_crColor; - chcore::CTaskPtr m_spTask; + chcore::TTaskPtr m_spTask; }; class CProgressListBox : public CListBox Index: src/ch/StatusDlg.cpp =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/StatusDlg.cpp (.../StatusDlg.cpp) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/StatusDlg.cpp (.../StatusDlg.cpp) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -18,7 +18,8 @@ ***************************************************************************/ #include "stdafx.h" #include "ch.h" -#include "../libchcore/task.h" +#include "../libchcore/TTaskManager.h" +#include "../libchcore/TTask.h" #include "resource.h" #include "StatusDlg.h" #include "BufferSizeDlg.h" @@ -37,7 +38,7 @@ ///////////////////////////////////////////////////////////////////////////// // CStatusDlg dialog -CStatusDlg::CStatusDlg(chcore::CTaskArray* pTasks, CWnd* pParent /*=NULL*/) +CStatusDlg::CStatusDlg(chcore::TTaskManager* pTasks, CWnd* pParent /*=NULL*/) : ictranslate::CLanguageDialog(CStatusDlg::IDD, pParent, &m_bLock) { //{{AFX_DATA_INIT(CStatusDlg) @@ -216,7 +217,7 @@ CLanguageDialog::OnTimer(nIDEvent); } -void CStatusDlg::AddTaskInfo(int nPos, const chcore::CTaskPtr& spTask, DWORD dwCurrentTime) +void CStatusDlg::AddTaskInfo(int nPos, const chcore::TTaskPtr& spTask, DWORD dwCurrentTime) { _ASSERTE(spTask != NULL); if(spTask == NULL) @@ -338,7 +339,7 @@ void CStatusDlg::OnSetBuffersizeButton() { - chcore::CTaskPtr spTask = GetSelectedItemPointer(); + chcore::TTaskPtr spTask = GetSelectedItemPointer(); if(!spTask) return; @@ -349,17 +350,17 @@ spTask->SetBufferSizes(dlg.m_bsSizes); } -chcore::CTaskPtr CStatusDlg::GetSelectedItemPointer() +chcore::TTaskPtr CStatusDlg::GetSelectedItemPointer() { - // returns ptr to a CTask for a given element in listview + // returns ptr to a TTask for a given element in listview if(m_ctlStatusList.GetSelectedCount() == 1) { POSITION pos = m_ctlStatusList.GetFirstSelectedItemPosition(); int nPos = m_ctlStatusList.GetNextSelectedItem(pos); return m_pTasks->GetTaskBySessionUniqueID(m_ctlStatusList.GetItemData(nPos)); } - return chcore::CTaskPtr(); + return chcore::TTaskPtr(); } void CStatusDlg::OnRollUnrollButton() @@ -411,7 +412,7 @@ void CStatusDlg::ApplyButtonsState() { - // remember ptr to CTask + // remember ptr to TTask m_spSelectedItem=GetSelectedItemPointer(); // set status of buttons pause/resume/cancel @@ -528,7 +529,7 @@ void CStatusDlg::OnPauseButton() { - chcore::CTaskPtr spTask = GetSelectedItemPointer(); + chcore::TTaskPtr spTask = GetSelectedItemPointer(); if(spTask) { TRACE("PauseProcessing call...\n"); @@ -540,7 +541,7 @@ void CStatusDlg::OnResumeButton() { - chcore::CTaskPtr spTask = GetSelectedItemPointer(); + chcore::TTaskPtr spTask = GetSelectedItemPointer(); if(spTask) { if(spTask->GetTaskState() == chcore::eTaskState_Waiting) @@ -554,7 +555,7 @@ void CStatusDlg::OnCancelButton() { - chcore::CTaskPtr spTask = GetSelectedItemPointer(); + chcore::TTaskPtr spTask = GetSelectedItemPointer(); if(spTask) { spTask->CancelProcessing(); @@ -564,7 +565,7 @@ void CStatusDlg::OnRestartButton() { - chcore::CTaskPtr spTask = GetSelectedItemPointer(); + chcore::TTaskPtr spTask = GetSelectedItemPointer(); if(spTask) { spTask->RestartProcessing(); @@ -574,7 +575,7 @@ void CStatusDlg::OnDeleteButton() { - chcore::CTaskPtr spTask = GetSelectedItemPointer(); + chcore::TTaskPtr spTask = GetSelectedItemPointer(); if(spTask) { chcore::ETaskCurrentState eTaskState = spTask->GetTaskState(); @@ -639,7 +640,7 @@ break; case VK_SPACE: { - chcore::CTaskPtr spTask = GetSelectedItemPointer(); + chcore::TTaskPtr spTask = GetSelectedItemPointer(); if (!spTask) return; @@ -780,16 +781,16 @@ void CStatusDlg::OnShowLogButton() { // show log - chcore::CTaskPtr spTask = GetSelectedItemPointer(); + chcore::TTaskPtr spTask = GetSelectedItemPointer(); if (!spTask) return; - unsigned long lResult = (unsigned long)(ShellExecute(this->m_hWnd, _T("open"), _T("notepad.exe"), spTask->GetRelatedPath(chcore::CTask::ePathType_TaskLogFile).ToString(), NULL, SW_SHOWNORMAL)); + unsigned long lResult = (unsigned long)(ShellExecute(this->m_hWnd, _T("open"), _T("notepad.exe"), spTask->GetRelatedPath(chcore::TTask::ePathType_TaskLogFile).ToString(), NULL, SW_SHOWNORMAL)); if(lResult < 32) { ictranslate::CFormat fmt(GetResManager().LoadString(IDS_SHELLEXECUTEERROR_STRING)); fmt.SetParam(_t("%errno"), lResult); - fmt.SetParam(_t("%path"), spTask->GetRelatedPath(chcore::CTask::ePathType_TaskLogFile).ToString()); + fmt.SetParam(_t("%path"), spTask->GetRelatedPath(chcore::TTask::ePathType_TaskLogFile).ToString()); AfxMessageBox(fmt); } } Index: src/ch/StatusDlg.h =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/ch/StatusDlg.h (.../StatusDlg.h) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/ch/StatusDlg.h (.../StatusDlg.h) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -23,9 +23,9 @@ namespace chcore { - class CTaskArray; - class CTask; - typedef boost::shared_ptr CTaskPtr; + class TTaskManager; + class TTask; + typedef boost::shared_ptr TTaskPtr; } #define WM_UPDATESTATUS WM_USER+6 @@ -39,7 +39,7 @@ // Construction public: - CStatusDlg(chcore::CTaskArray* pTasks, CWnd* pParent = NULL); // standard constructor + CStatusDlg(chcore::TTaskManager* pTasks, CWnd* pParent = NULL); // standard constructor ~CStatusDlg(); void PostCloseMessage(); @@ -50,9 +50,9 @@ void ApplyButtonsState(); void ApplyDisplayDetails(bool bInitial=false); - chcore::CTaskPtr GetSelectedItemPointer(); + chcore::TTaskPtr GetSelectedItemPointer(); - void AddTaskInfo(int nPos, const chcore::CTaskPtr& spTask, DWORD dwCurrentTime); + void AddTaskInfo(int nPos, const chcore::TTaskPtr& spTask, DWORD dwCurrentTime); void EnableControls(bool bEnable=true); protected: @@ -89,14 +89,14 @@ DECLARE_MESSAGE_MAP() public: - chcore::CTaskPtr m_spInitialSelection; + chcore::TTaskPtr m_spInitialSelection; static bool m_bLock; // locker protected: - chcore::CTaskArray* m_pTasks; - chcore::CTaskPtr m_spSelectedItem; - chcore::CTaskPtr m_spLastSelected; + chcore::TTaskManager* m_pTasks; + chcore::TTaskPtr m_spSelectedItem; + chcore::TTaskPtr m_spLastSelected; TCHAR m_szData[_MAX_PATH]; TCHAR m_szTimeBuffer1[40]; Index: src/common/version.h =================================================================== diff -u -r4e49aeca468facb7584f1da8c4a3a22bbd1519c0 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/common/version.h (.../version.h) (revision 4e49aeca468facb7584f1da8c4a3a22bbd1519c0) +++ src/common/version.h (.../version.h) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -11,10 +11,10 @@ // Version of program #define PRODUCT_VERSION1 1 #define PRODUCT_VERSION2 40 -#define PRODUCT_VERSION3 413 -#define PRODUCT_VERSION4 0 +#define PRODUCT_VERSION3 440 +#define PRODUCT_VERSION4 1 -#define PRODUCT_VERSION "1.40internal-svn413" +#define PRODUCT_VERSION "1.40internal-svn440_M" #if SETUP_COMPILER != 1 #define SHELLEXT_PRODUCT_FULL_VERSION SHELLEXT_PRODUCT_NAME " " PRODUCT_VERSION @@ -30,3 +30,4 @@ #define CONTACT_INFO "http://www.copyhandler.com/contact" #endif + Index: src/libchcore/FeedbackHandlerBase.h =================================================================== diff -u -r249b191b71fb9dde75cf47ff3a04eddbab822698 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/libchcore/FeedbackHandlerBase.h (.../FeedbackHandlerBase.h) (revision 249b191b71fb9dde75cf47ff3a04eddbab822698) +++ src/libchcore/FeedbackHandlerBase.h (.../FeedbackHandlerBase.h) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -24,6 +24,9 @@ BEGIN_CHCORE_NAMESPACE +class TFileInfo; +typedef boost::shared_ptr TFileInfoPtr; + enum EFileError { eDeleteError, ///< Problem occured when tried to delete the fs object Index: src/libchcore/TTask.cpp =================================================================== diff -u --- src/libchcore/TTask.cpp (revision 0) +++ src/libchcore/TTask.cpp (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -0,0 +1,860 @@ +/*************************************************************************** +* Copyright (C) 2001-2010 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 "TTask.h" + +#pragma warning(push) +#pragma warning(disable: 4996) + #include + #include + #include +#pragma warning(pop) + +#include +#include "TSubTaskContext.h" +#include "TSubTaskScanDirectory.h" +#include "TSubTaskCopyMove.h" +#include "TSubTaskDelete.h" +#include "TBinarySerializer.h" +#include "SerializationHelpers.h" +#include +#include "../libicpf/exception.h" +#include +#include "DataBuffer.h" + +BEGIN_CHCORE_NAMESPACE + +//////////////////////////////////////////////////////////////////////////// +// TTask members + +TTask::TTask(IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID) : + m_log(), + m_piFeedbackHandler(piFeedbackHandler), + m_arrSourcePathsInfo(m_tTaskDefinition.GetSourcePaths()), + m_files(m_tTaskDefinition.GetSourcePaths()), + m_bForce(false), + m_bContinue(false), + m_bRareStateModified(false), + m_bOftenStateModified(false), + m_stSessionUniqueID(stSessionUniqueID), + m_localStats(), + m_eCurrentState(eTaskState_None) +{ + BOOST_ASSERT(piFeedbackHandler); +} + +TTask::~TTask() +{ + KillThread(); + if(m_piFeedbackHandler) + m_piFeedbackHandler->Delete(); +} + +void TTask::SetTaskDefinition(const TTaskDefinition& rTaskDefinition) +{ + m_tTaskDefinition = rTaskDefinition; + + m_arrSourcePathsInfo.SetCount(m_tTaskDefinition.GetSourcePathCount()); + m_files.Clear(); +} + +void TTask::OnRegisterTask(TTasksGlobalStats& rtGlobalStats) +{ + m_localStats.ConnectGlobalStats(rtGlobalStats); +} + +void TTask::OnUnregisterTask() +{ + m_localStats.DisconnectGlobalStats(); +} + +void TTask::SetTaskState(ETaskCurrentState eTaskState) +{ + // NOTE: we could check some transition rules here + boost::unique_lock lock(m_lock); + m_eCurrentState = eTaskState; +} + +ETaskCurrentState TTask::GetTaskState() const +{ + boost::shared_lock lock(m_lock); + return m_eCurrentState; +} + +void TTask::SetBufferSizes(const TBufferSizes& bsSizes) +{ + m_tTaskDefinition.GetConfiguration().DelayNotifications(); + SetTaskPropValue(m_tTaskDefinition.GetConfiguration(), bsSizes.GetDefaultSize()); + SetTaskPropValue(m_tTaskDefinition.GetConfiguration(), bsSizes.GetOneDiskSize()); + SetTaskPropValue(m_tTaskDefinition.GetConfiguration(), bsSizes.GetTwoDisksSize()); + SetTaskPropValue(m_tTaskDefinition.GetConfiguration(), bsSizes.GetCDSize()); + SetTaskPropValue(m_tTaskDefinition.GetConfiguration(), bsSizes.GetLANSize()); + SetTaskPropValue(m_tTaskDefinition.GetConfiguration(), bsSizes.IsOnlyDefault()); + m_tTaskDefinition.GetConfiguration().ResumeNotifications(); +} + +void TTask::GetBufferSizes(TBufferSizes& bsSizes) +{ + bsSizes.SetDefaultSize(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); + bsSizes.SetOneDiskSize(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); + bsSizes.SetTwoDisksSize(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); + bsSizes.SetCDSize(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); + bsSizes.SetLANSize(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); + bsSizes.SetOnlyDefault(GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); +} + +int TTask::GetCurrentBufferIndex() +{ + return m_localStats.GetCurrentBufferIndex(); +} + +// thread +void TTask::SetPriority(int nPriority) +{ + SetTaskPropValue(m_tTaskDefinition.GetConfiguration(), nPriority); +} + +void TTask::CalculateProcessedSize() +{ + boost::shared_lock lock(m_lock); + CalculateProcessedSizeNL(); +} + +void TTask::CalculateProcessedSizeNL() +{ + m_localStats.SetProcessedSize(m_files.CalculatePartialSize(m_tTaskBasicProgressInfo.GetCurrentIndex())); +} + +void TTask::Load(const TSmartPath& strPath) +{ + using Serializers::Serialize; + + boost::unique_lock lock(m_lock); + + //////////////////////////////// + // First load task description + m_tTaskDefinition.Load(strPath); + m_strFilePath = strPath; + + // update members according to the task definition + // make sure to resize paths info array size to match source paths count + m_arrSourcePathsInfo.SetCount(m_tTaskDefinition.GetSourcePathCount()); + GetTaskPropValue(m_tTaskDefinition.GetConfiguration(), m_afFilters); + + //////////////////////////////// + // now rarely changing task progress data + TSmartPath pathRarelyChangingPath = GetRelatedPathNL(ePathType_TaskRarelyChangingState); + TReadBinarySerializer readSerializer; + readSerializer.Init(pathRarelyChangingPath); + + m_arrSourcePathsInfo.Serialize(readSerializer, true); + m_files.Serialize(readSerializer, false); + + CalculateTotalSizeNL(); + + /////////////////////////////////// + // and often changing data + TSmartPath pathOftenChangingPath = GetRelatedPathNL(ePathType_TaskOftenChangingState); + readSerializer.Init(pathOftenChangingPath); + + Serialize(readSerializer, m_tTaskBasicProgressInfo); + + CalculateProcessedSizeNL(); + + // load task state, convert "waiting" state to "processing" + int iState = eTaskState_None; + Serialize(readSerializer, iState); + if(iState >= eTaskState_None && iState < eTaskState_Max) + { + if(iState == eTaskState_Waiting) + iState = eTaskState_Processing; + m_eCurrentState = (ETaskCurrentState)iState; + } + else + { + BOOST_ASSERT(false); + THROW_CORE_EXCEPTION(eErr_InvalidSerializationData); + } + + time_t timeElapsed = 0; + Serialize(readSerializer, timeElapsed); + m_localStats.SetTimeElapsed(timeElapsed); + + m_arrSourcePathsInfo.Serialize(readSerializer, false); + m_files.Serialize(readSerializer, true); +} + +void TTask::Store() +{ + using Serializers::Serialize; + + boost::upgrade_lock lock(m_lock); + + BOOST_ASSERT(!m_strTaskDirectory.IsEmpty()); + if(m_strTaskDirectory.IsEmpty()) + THROW_CORE_EXCEPTION(eErr_MissingTaskSerializationPath); + + // generate file path if not available yet + if(m_strFilePath.IsEmpty()) + { + boost::upgrade_to_unique_lock upgraded_lock(lock); + m_strFilePath = m_strTaskDirectory + PathFromWString(m_tTaskDefinition.GetTaskUniqueID() + _T(".cht")); + } + + // store task definition only if changed + m_tTaskDefinition.Store(GetRelatedPathNL(ePathType_TaskDefinition), true); + + // rarely changing data + if(m_bRareStateModified) + { + TWriteBinarySerializer writeSerializer; + writeSerializer.Init(GetRelatedPathNL(ePathType_TaskRarelyChangingState)); + + m_arrSourcePathsInfo.Serialize(writeSerializer, true); + + ESubOperationType eSubOperation = m_tTaskDefinition.GetOperationPlan().GetSubOperationAt(m_tTaskBasicProgressInfo.GetSubOperationIndex()); + if(eSubOperation != eSubOperation_Scanning) + m_files.Serialize(writeSerializer, false); + else + { + size_t stFakeSize(0); + Serialize(writeSerializer, stFakeSize); + } + } + + if(m_bOftenStateModified) + { + TWriteBinarySerializer writeSerializer; + writeSerializer.Init(GetRelatedPathNL(ePathType_TaskOftenChangingState)); + + Serialize(writeSerializer, m_tTaskBasicProgressInfo); + + // store current state (convert from waiting to processing state before storing) + int iState = m_eCurrentState; + if(iState == eTaskState_Waiting) + iState = eTaskState_Processing; + + Serialize(writeSerializer, iState); + + time_t timeElapsed = m_localStats.GetTimeElapsed(); + Serialize(writeSerializer, timeElapsed); + + m_arrSourcePathsInfo.Serialize(writeSerializer, false); + + ESubOperationType eSubOperation = m_tTaskDefinition.GetOperationPlan().GetSubOperationAt(m_tTaskBasicProgressInfo.GetSubOperationIndex()); + if(eSubOperation != eSubOperation_Scanning) + m_files.Serialize(writeSerializer, true); + else + { + size_t stFakeSize(0); + Serialize(writeSerializer, stFakeSize); + } + } +} + +void TTask::KillThread() +{ + m_workerThread.StopThread(); +} + +void TTask::BeginProcessing() +{ + boost::unique_lock lock(m_lock); + + m_bRareStateModified = true; + m_bOftenStateModified = true; + + m_workerThread.StartThread(DelegateThreadProc, this, GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); +} + +void TTask::ResumeProcessing() +{ + // the same as retry but less demanding + if(GetTaskState() == eTaskState_Paused) + { + SetTaskState(eTaskState_Processing); + BeginProcessing(); + } +} + +bool TTask::RetryProcessing() +{ + // retry used to auto-resume, after loading + if(GetTaskState() != eTaskState_Paused && GetTaskState() != eTaskState_Finished && GetTaskState() != eTaskState_Cancelled) + { + BeginProcessing(); + return true; + } + return false; +} + +void TTask::RestartProcessing() +{ + KillThread(); + + SetTaskState(eTaskState_None); + + m_localStats.SetTimeElapsed(0); + m_tTaskBasicProgressInfo.SetCurrentIndex(0); + + BeginProcessing(); +} + +void TTask::PauseProcessing() +{ + if(GetTaskState() != eTaskState_Finished && GetTaskState() != eTaskState_Cancelled) + { + KillThread(); + SetTaskState(eTaskState_Paused); + + m_bOftenStateModified = true; + } +} + +void TTask::CancelProcessing() +{ + // change to ST_CANCELLED + if(GetTaskState() != eTaskState_Finished) + { + KillThread(); + SetTaskState(eTaskState_Cancelled); + m_bOftenStateModified = true; + } +} + +void TTask::GetMiniSnapshot(TASK_MINI_DISPLAY_DATA *pData) +{ + boost::shared_lock lock(m_lock); + size_t stCurrentIndex = m_tTaskBasicProgressInfo.GetCurrentIndex(); + + if(stCurrentIndex < m_files.GetSize()) + pData->m_strPath = m_files.GetAt(stCurrentIndex)->GetFullFilePath().GetFileName().ToString(); + else + { + if(m_files.GetSize() > 0) + pData->m_strPath = m_files.GetAt(0)->GetFullFilePath().GetFileName().ToString(); + else + { + if(m_tTaskDefinition.GetSourcePathCount() > 0) + pData->m_strPath = m_tTaskDefinition.GetSourcePathAt(0).GetFileName().ToString(); + else + pData->m_strPath.Clear(); + } + } + + pData->m_eTaskState = m_eCurrentState; + + // percents + pData->m_nPercent = m_localStats.GetProgressInPercent(); +} + +void TTask::GetSnapshot(TASK_DISPLAY_DATA *pData) +{ + boost::unique_lock lock(m_lock); + + size_t stCurrentIndex = m_tTaskBasicProgressInfo.GetCurrentIndex(); + if(stCurrentIndex < m_files.GetSize()) + { + pData->m_strFullFilePath = m_files.GetAt(stCurrentIndex)->GetFullFilePath().ToString(); + pData->m_strFileName = m_files.GetAt(stCurrentIndex)->GetFullFilePath().GetFileName().ToString(); + } + else + { + if(m_files.GetSize() > 0) + { + pData->m_strFullFilePath = m_files.GetAt(0)->GetFullFilePath().ToString(); + pData->m_strFileName = m_files.GetAt(0)->GetFullFilePath().GetFileName().ToString(); + } + else + { + if(m_tTaskDefinition.GetSourcePathCount() > 0) + { + pData->m_strFullFilePath = m_tTaskDefinition.GetSourcePathAt(0).ToString(); + pData->m_strFileName = m_tTaskDefinition.GetSourcePathAt(0).GetFileName().ToString(); + } + else + { + pData->m_strFullFilePath.Clear(); + pData->m_strFileName.Clear(); + } + } + } + + pData->m_nPriority = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + pData->m_pathDstPath = m_tTaskDefinition.GetDestinationPath(); + pData->m_pafFilters = &m_afFilters; + pData->m_eTaskState = m_eCurrentState; + pData->m_stIndex = stCurrentIndex; + pData->m_ullProcessedSize = m_localStats.GetProcessedSize(); + pData->m_stSize=m_files.GetSize(); + pData->m_ullSizeAll = m_localStats.GetTotalSize(); + pData->m_strUniqueName = m_tTaskDefinition.GetTaskUniqueID(); + pData->m_eOperationType = m_tTaskDefinition.GetOperationType(); + pData->m_eSubOperationType = m_tTaskDefinition.GetOperationPlan().GetSubOperationAt(m_tTaskBasicProgressInfo.GetSubOperationIndex()); + + pData->m_bIgnoreDirectories = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + pData->m_bCreateEmptyFiles = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + + if(m_files.GetSize() > 0) + pData->m_iCurrentBufferIndex = m_localStats.GetCurrentBufferIndex(); + else + pData->m_iCurrentBufferIndex = TBufferSizes::eBuffer_Default; + + switch(pData->m_iCurrentBufferIndex) + { + case TBufferSizes::eBuffer_Default: + pData->m_iCurrentBufferSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + break; + case TBufferSizes::eBuffer_OneDisk: + pData->m_iCurrentBufferSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + break; + case TBufferSizes::eBuffer_TwoDisks: + pData->m_iCurrentBufferSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + break; + case TBufferSizes::eBuffer_CD: + pData->m_iCurrentBufferSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + break; + case TBufferSizes::eBuffer_LAN: + pData->m_iCurrentBufferSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + break; + default: + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + //BOOST_ASSERT(false); // assertions are dangerous here, because we're inside critical section + // (and there could be conflict with Get(Mini)Snapshot called OnTimer in several places. + } + + // percents + pData->m_nPercent = m_localStats.GetProgressInPercent(); + + // time + pData->m_timeElapsed = m_localStats.GetTimeElapsed(); +} + +void TTask::DeleteProgress() +{ + TPathContainer vFilesToRemove; + + // separate scope for shared locking + { + boost::shared_lock lock(m_lock); + + vFilesToRemove.Add(GetRelatedPath(ePathType_TaskDefinition)); + vFilesToRemove.Add(GetRelatedPath(ePathType_TaskRarelyChangingState)); + vFilesToRemove.Add(GetRelatedPath(ePathType_TaskOftenChangingState)); + vFilesToRemove.Add(GetRelatedPath(ePathType_TaskLogFile)); + } + + for(size_t stIndex = 0; stIndex < vFilesToRemove.GetCount(); ++stIndex) + { + DeleteFile(vFilesToRemove.GetAt(stIndex).ToString()); + } +} + +bool TTask::CanBegin() +{ + bool bRet=true; + boost::unique_lock lock(m_lock); + + if(GetContinueFlagNL() || GetForceFlagNL()) + { + m_localStats.MarkTaskAsRunning(); + SetForceFlagNL(false); + SetContinueFlagNL(false); + } + else + bRet = false; + + return bRet; +} + +void TTask::SetTaskDirectory(const TSmartPath& strDir) +{ + boost::unique_lock lock(m_lock); + m_strTaskDirectory = strDir; +} + +TSmartPath TTask::GetTaskDirectory() const +{ + boost::shared_lock lock(m_lock); + return m_strTaskDirectory; +} + +void TTask::SetTaskFilePath(const TSmartPath& strFilePath) +{ + boost::unique_lock lock(m_lock); + m_strFilePath = strFilePath; +} + +TSmartPath TTask::GetTaskFilePath() const +{ + boost::shared_lock lock(m_lock); + return m_strFilePath; +} + +void TTask::SetForceFlag(bool bFlag) +{ + boost::unique_lock lock(m_lock); + m_bForce=bFlag; +} + +bool TTask::GetForceFlag() +{ + boost::shared_lock lock(m_lock); + return m_bForce; +} + +void TTask::SetContinueFlag(bool bFlag) +{ + boost::unique_lock lock(m_lock); + m_bContinue=bFlag; +} + +bool TTask::GetContinueFlag() +{ + boost::shared_lock lock(m_lock); + return m_bContinue; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void TTask::CalculateTotalSizeNL() +{ + m_localStats.SetTotalSize(m_files.CalculateTotalSize()); +} + +void TTask::SetForceFlagNL(bool bFlag) +{ + m_bForce=bFlag; +} + +bool TTask::GetForceFlagNL() +{ + return m_bForce; +} + +void TTask::SetContinueFlagNL(bool bFlag) +{ + m_bContinue=bFlag; +} + +bool TTask::GetContinueFlagNL() +{ + return m_bContinue; +} + +TSubTaskBase::ESubOperationResult TTask::CheckForWaitState() +{ + // limiting operation count + SetTaskState(eTaskState_Waiting); + bool bContinue = false; + while(!bContinue) + { + if(CanBegin()) + { + SetTaskState(eTaskState_Processing); + bContinue = true; + + m_log.logi(_T("Finished waiting for begin permission")); + + // return; // skips sleep and kill flag checking + } + + Sleep(50); // not to make it too hard for processor + + if(m_workerThread.KillRequested()) + { + // log + m_log.logi(_T("Kill request while waiting for begin permission (wait state)")); + return TSubTaskBase::eSubResult_KillRequest; + } + } + + return TSubTaskBase::eSubResult_Continue; +} + +DWORD WINAPI TTask::DelegateThreadProc(LPVOID pParam) +{ + BOOST_ASSERT(pParam); + if(!pParam) + return 1; + + TTask* pTask = (TTask*)pParam; + return pTask->ThrdProc(); +} + +DWORD TTask::ThrdProc() +{ + try + { + TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue; + + // initialize log file + TSmartPath pathLogFile = GetRelatedPath(ePathType_TaskLogFile); + + m_log.init(pathLogFile.ToString(), 262144, icpf::log_file::level_debug, false, false); + + // start operation + OnBeginOperation(); + + // enable configuration changes tracking + m_tTaskDefinition.GetConfiguration().ConnectToNotifier(TTaskConfigTracker::NotificationProc, &m_cfgTracker); + m_tTaskDefinition.GetConfiguration().ConnectToNotifier(TTask::OnCfgOptionChanged, this); + + // set thread options + HANDLE hThread = GetCurrentThread(); + ::SetThreadPriorityBoost(hThread, GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); + + // determine when to scan directories + bool bReadTasksSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + + // wait for permission to really start (but only if search for files is not allowed to start regardless of the lock) + size_t stSubOperationIndex = m_tTaskBasicProgressInfo.GetSubOperationIndex(); + if(!bReadTasksSize || stSubOperationIndex != 0 || m_tTaskDefinition.GetOperationPlan().GetSubOperationsCount() == 0 || m_tTaskDefinition.GetOperationPlan().GetSubOperationAt(0) != eSubOperation_Scanning) + eResult = CheckForWaitState(); // operation limiting + + // start tracking time for this thread + m_localStats.EnableTimeTracking(); + + // prepare context for subtasks + TSubTaskContext tSubTaskContext(m_tTaskDefinition, m_arrSourcePathsInfo, m_files, m_localStats, m_tTaskBasicProgressInfo, m_cfgTracker, m_log, m_piFeedbackHandler, m_workerThread, m_fsLocal); + + for(; stSubOperationIndex < m_tTaskDefinition.GetOperationPlan().GetSubOperationsCount() && eResult == TSubTaskBase::eSubResult_Continue; ++stSubOperationIndex) + { + // set current sub-operation index to allow resuming + m_tTaskBasicProgressInfo.SetSubOperationIndex(stSubOperationIndex); + + ESubOperationType eSubOperation = m_tTaskDefinition.GetOperationPlan().GetSubOperationAt(stSubOperationIndex); + switch(eSubOperation) + { + case eSubOperation_Scanning: + { + // start searching + TSubTaskScanDirectories tSubTaskScanDir(tSubTaskContext); + eResult = tSubTaskScanDir.Exec(); + + // if we didn't wait for permission to start earlier, then ask now (but only in case this is the first search) + if(eResult == TSubTaskBase::eSubResult_Continue && bReadTasksSize && stSubOperationIndex == 0) + { + m_localStats.DisableTimeTracking(); + + eResult = CheckForWaitState(); + + m_localStats.EnableTimeTracking(); + } + + break; + } + + case eSubOperation_Copying: + { + TSubTaskCopyMove tSubTaskCopyMove(tSubTaskContext); + + eResult = tSubTaskCopyMove.Exec(); + break; + } + + case eSubOperation_Deleting: + { + TSubTaskDelete tSubTaskDelete(tSubTaskContext); + eResult = tSubTaskDelete.Exec(); + break; + } + + default: + BOOST_ASSERT(false); + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + } + + // change status to finished + if(eResult == TSubTaskBase::eSubResult_Continue) + SetTaskState(eTaskState_Finished); + + // refresh time + m_localStats.DisableTimeTracking(); + + // finishing processing + // change task status + switch(eResult) + { + case TSubTaskBase::eSubResult_Error: + m_piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_OperationError, NULL); + SetTaskState(eTaskState_Error); + break; + + case TSubTaskBase::eSubResult_CancelRequest: + SetTaskState(eTaskState_Cancelled); + break; + + case TSubTaskBase::eSubResult_PauseRequest: + SetTaskState(eTaskState_Paused); + break; + + case TSubTaskBase::eSubResult_KillRequest: + // the only operation + if(GetTaskState() == eTaskState_Waiting) + SetTaskState(eTaskState_Processing); + break; + + case TSubTaskBase::eSubResult_Continue: + m_piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_OperationFinished, NULL); + SetTaskState(eTaskState_Finished); + break; + + default: + BOOST_ASSERT(false); + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } + + // perform cleanup dependent on currently executing subtask + switch(m_tTaskDefinition.GetOperationPlan().GetSubOperationAt(m_tTaskBasicProgressInfo.GetSubOperationIndex())) + { + case eSubOperation_Scanning: + m_files.Clear(); // get rid of m_files contents + m_bRareStateModified = true; + break; + } + + // save progress before killed + m_bOftenStateModified = true; + Store(); + + // reset flags + SetContinueFlag(false); + SetForceFlag(false); + + // mark this task as dead, so other can start + m_localStats.MarkTaskAsNotRunning(); + + m_tTaskDefinition.GetConfiguration().DisconnectFromNotifier(TTaskConfigTracker::NotificationProc); + m_tTaskDefinition.GetConfiguration().DisconnectFromNotifier(TTask::OnCfgOptionChanged); + + // and the real end + OnEndOperation(); + } + catch(...) + { + m_tTaskDefinition.GetConfiguration().DisconnectFromNotifier(TTaskConfigTracker::NotificationProc); + m_tTaskDefinition.GetConfiguration().DisconnectFromNotifier(TTask::OnCfgOptionChanged); + + // refresh time + m_localStats.DisableTimeTracking(); + + // log + m_log.loge(_T("Caught exception in ThrdProc")); + + // let others know some error happened + m_piFeedbackHandler->RequestFeedback(IFeedbackHandler::eFT_OperationError, NULL); + SetTaskState(eTaskState_Error); + + m_localStats.MarkTaskAsNotRunning(); + + SetContinueFlag(false); + SetForceFlag(false); + + OnEndOperation(); + return 1; + } + + return 0; +} + +void TTask::OnBeginOperation() +{ + CTime tm=CTime::GetCurrentTime(); + + TString strFormat = _T("\r\n# COPYING THREAD STARTED #\r\nBegan processing data (dd:mm:yyyy) %day.%month.%year at %hour:%minute.%second"); + strFormat.Replace(_t("%year"), boost::lexical_cast(tm.GetYear()).c_str()); + strFormat.Replace(_t("%month"), boost::lexical_cast(tm.GetMonth()).c_str()); + strFormat.Replace(_t("%day"), boost::lexical_cast(tm.GetDay()).c_str()); + strFormat.Replace(_t("%hour"), boost::lexical_cast(tm.GetHour()).c_str()); + strFormat.Replace(_t("%minute"), boost::lexical_cast(tm.GetMinute()).c_str()); + strFormat.Replace(_t("%second"), boost::lexical_cast(tm.GetSecond()).c_str()); + m_log.logi(strFormat); +} + +void TTask::OnEndOperation() +{ + CTime tm=CTime::GetCurrentTime(); + + TString strFormat = _T("Finished processing data (dd:mm:yyyy) %day.%month.%year at %hour:%minute.%second"); + strFormat.Replace(_t("%year"), boost::lexical_cast(tm.GetYear()).c_str()); + strFormat.Replace(_t("%month"), boost::lexical_cast(tm.GetMonth()).c_str()); + strFormat.Replace(_t("%day"), boost::lexical_cast(tm.GetDay()).c_str()); + strFormat.Replace(_t("%hour"), boost::lexical_cast(tm.GetHour()).c_str()); + strFormat.Replace(_t("%minute"), boost::lexical_cast(tm.GetMinute()).c_str()); + strFormat.Replace(_t("%second"), boost::lexical_cast(tm.GetSecond()).c_str()); + m_log.logi(strFormat); +} + +void TTask::RequestStopThread() +{ + m_workerThread.SignalThreadToStop(); +} + +TSmartPath TTask::GetRelatedPath(EPathType ePathType) +{ + boost::shared_lock lock(m_lock); + + return GetRelatedPathNL(ePathType); +} + +TSmartPath TTask::GetRelatedPathNL(EPathType ePathType) +{ + BOOST_ASSERT(!m_strTaskDirectory.IsEmpty() || !m_strFilePath.IsEmpty()); + if(m_strTaskDirectory.IsEmpty() && m_strFilePath.IsEmpty()) + THROW_CORE_EXCEPTION(eErr_MissingTaskSerializationPath); + + // in all cases we would like to have task definition path defined + TSmartPath strFilePath = m_strFilePath; + if(strFilePath.IsEmpty()) + strFilePath = m_strTaskDirectory + PathFromWString(m_tTaskDefinition.GetTaskUniqueID() + _T(".cht")); + + switch(ePathType) + { + case ePathType_TaskDefinition: + return strFilePath; + + case ePathType_TaskRarelyChangingState: + return strFilePath.AppendCopy(PathFromString(_T(".rstate")), false); + + case ePathType_TaskOftenChangingState: + return strFilePath.AppendCopy(PathFromString(_T(".ostate")), false); + + case ePathType_TaskLogFile: + return strFilePath.AppendCopy(PathFromString(_T(".log")), false); + + default: + THROW_CORE_EXCEPTION(eErr_UnhandledCase); + } +} + +void TTask::OnCfgOptionChanged(const TStringSet& rsetChanges, void* pParam) +{ + TTask* pTask = (TTask*)pParam; + if(!pTask) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + + if(rsetChanges.HasValue(TaskPropData::GetPropertyName())) + { + pTask->m_workerThread.ChangePriority(GetTaskPropValue(pTask->GetTaskDefinition().GetConfiguration())); + } +} + +END_CHCORE_NAMESPACE Fisheye: tag 0cf74c78280b58c363868caafb9bf493a57aa006 is not in file src/libchcore/TTask.h Fisheye: Tag 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 refers to a dead (removed) revision in file `src/libchcore/task.h'. Fisheye: No comparison available. Pass `N' to diff? Index: src/libchcore/TTaskManager.cpp =================================================================== diff -u --- src/libchcore/TTaskManager.cpp (revision 0) +++ src/libchcore/TTaskManager.cpp (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -0,0 +1,440 @@ +/*************************************************************************** +* Copyright (C) 2001-2010 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 "TTaskManager.h" +#include "TTask.h" + +#include +#include "../libicpf/exception.h" +#include "TLogger.h" + +BEGIN_CHCORE_NAMESPACE + +//////////////////////////////////////////////////////////////////////////////// +// TTaskManager members +TTaskManager::TTaskManager() : + m_piFeedbackFactory(NULL), + m_stNextSessionUniqueID(NO_TASK_SESSION_UNIQUE_ID + 1) +{ +} + +TTaskManager::~TTaskManager() +{ + // NOTE: do not delete the feedback factory, since we are not responsible for releasing it +} + +void TTaskManager::Create(IFeedbackHandlerFactory* piFeedbackHandlerFactory) +{ + BOOST_ASSERT(piFeedbackHandlerFactory); + + m_piFeedbackFactory = piFeedbackHandlerFactory; +} + +TTaskPtr TTaskManager::CreateTask(const TTaskDefinition& tTaskDefinition) +{ + TTaskPtr spTask = CreateEmptyTask(); + if(spTask) + { + spTask->SetTaskDefinition(tTaskDefinition); + Add(spTask); + spTask->Store(); + } + + return spTask; +} + +TTaskPtr TTaskManager::ImportTask(const TSmartPath& strTaskPath) +{ + // load task definition from the new location + TTaskDefinition tTaskDefinition; + tTaskDefinition.Load(strTaskPath); + + return CreateTask(tTaskDefinition); +} + +TTaskPtr TTaskManager::CreateEmptyTask() +{ + BOOST_ASSERT(m_piFeedbackFactory); + if(!m_piFeedbackFactory) + return TTaskPtr(); + + IFeedbackHandler* piHandler = m_piFeedbackFactory->Create(); + if(!piHandler) + return TTaskPtr(); + + BOOST_ASSERT(m_stNextSessionUniqueID != NO_TASK_SESSION_UNIQUE_ID); + TTaskPtr spTask(new TTask(piHandler, m_stNextSessionUniqueID++)); + + // NO_TASK_SESSION_UNIQUE_ID is a special value so it should not be used to identify tasks + if(m_stNextSessionUniqueID == NO_TASK_SESSION_UNIQUE_ID) + ++m_stNextSessionUniqueID; + + return spTask; +} + +size_t TTaskManager::GetSize() const +{ + boost::shared_lock lock(m_lock); + return m_vTasks.size(); +} + +TTaskPtr TTaskManager::GetAt(size_t nIndex) const +{ + boost::shared_lock lock(m_lock); + + _ASSERTE(nIndex >= 0 && nIndex < m_vTasks.size()); + if(nIndex >= m_vTasks.size()) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + + return m_vTasks.at(nIndex); +} + +TTaskPtr TTaskManager::GetTaskBySessionUniqueID(size_t stSessionUniqueID) const +{ + if(stSessionUniqueID == NO_TASK_SESSION_UNIQUE_ID) + return TTaskPtr(); + + TTaskPtr spFoundTask; + + boost::shared_lock lock(m_lock); + BOOST_FOREACH(const TTaskPtr& spTask, m_vTasks) + { + if(spTask->GetSessionUniqueID() == stSessionUniqueID) + { + spFoundTask = spTask; + break; + } + } + + return spFoundTask; +} + +size_t TTaskManager::Add(const TTaskPtr& spNewTask) +{ + if(!spNewTask) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + + boost::unique_lock lock(m_lock); + // here we know load succeeded + spNewTask->SetTaskDirectory(m_pathTasksDir); + + m_vTasks.push_back(spNewTask); + + spNewTask->OnRegisterTask(m_globalStats); + + return m_vTasks.size() - 1; +} + +void TTaskManager::RemoveAt(size_t stIndex, size_t stCount) +{ + boost::unique_lock lock(m_lock); + + _ASSERTE(stIndex >= m_vTasks.size() || stIndex + stCount > m_vTasks.size()); + if(stIndex >= m_vTasks.size() || stIndex + stCount > m_vTasks.size()) + THROW_CORE_EXCEPTION(eErr_InvalidArgument); + + for(std::vector::iterator iterTask = m_vTasks.begin() + stIndex; iterTask != m_vTasks.begin() + stIndex + stCount; ++iterTask) + { + TTaskPtr& spTask = *iterTask; + + // kill task if needed + spTask->KillThread(); + + spTask->OnUnregisterTask(); + } + + // remove elements from array + m_vTasks.erase(m_vTasks.begin() + stIndex, m_vTasks.begin() + stIndex + stCount); +} + +void TTaskManager::RemoveAll() +{ + boost::unique_lock lock(m_lock); + + StopAllTasksNL(); + + m_vTasks.clear(); +} + +void TTaskManager::RemoveAllFinished() +{ + std::vector vTasksToRemove; + + // separate scope for locking + { + boost::unique_lock lock(m_lock); + + size_t stIndex = m_vTasks.size(); + while(stIndex--) + { + TTaskPtr spTask = m_vTasks.at(stIndex); + + // delete only when the thread is finished + if((spTask->GetTaskState() == eTaskState_Finished || spTask->GetTaskState() == eTaskState_Cancelled)) + { + spTask->OnUnregisterTask(); + + vTasksToRemove.push_back(spTask); + m_vTasks.erase(m_vTasks.begin() + stIndex); + } + } + } + + BOOST_FOREACH(TTaskPtr& spTask, vTasksToRemove) + { + // delete associated files + spTask->DeleteProgress(); + } +} + +void TTaskManager::RemoveFinished(const TTaskPtr& spSelTask) +{ + boost::unique_lock lock(m_lock); + + // this might be optimized by copying tasks to a local table in critical section, and then deleting progress files outside of the critical section + for(std::vector::iterator iterTask = m_vTasks.begin(); iterTask != m_vTasks.end(); ++iterTask) + { + TTaskPtr& spTask = *iterTask; + + if(spTask == spSelTask && (spTask->GetTaskState() == eTaskState_Finished || spTask->GetTaskState() == eTaskState_Cancelled)) + { + // kill task if needed + spTask->KillThread(); + + spTask->OnUnregisterTask(); + + // delete associated files + spTask->DeleteProgress(); + + m_vTasks.erase(iterTask); + + return; + } + } +} + +void TTaskManager::StopAllTasks() +{ + boost::unique_lock lock(m_lock); + + StopAllTasksNL(); +} + +void TTaskManager::ResumeWaitingTasks(size_t stMaxRunningTasks) +{ + boost::unique_lock lock(m_lock); + + if(stMaxRunningTasks == 0 || m_globalStats.GetRunningTasksCount() < stMaxRunningTasks) + { + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + // turn on some thread - find something with wait state + if(spTask->GetTaskState() == eTaskState_Waiting && (stMaxRunningTasks == 0 || m_globalStats.GetRunningTasksCount() < stMaxRunningTasks)) + { + spTask->m_localStats.MarkTaskAsRunning(); + spTask->SetContinueFlagNL(true); + } + } + } +} + +void TTaskManager::SaveData() +{ + boost::shared_lock lock(m_lock); + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + spTask->Store(); + } +} + +void TTaskManager::LoadDataProgress() +{ + if(m_pathTasksDir.IsEmpty()) + THROW_CORE_EXCEPTION(eErr_MissingTaskSerializationPath); + + TTaskPtr spTask; + TSmartPath pathFound; + WIN32_FIND_DATA wfd; + bool bExceptionEncountered = false; + + const size_t stMaxMsgSize = 4096; + boost::shared_array spMsgBuffer(new wchar_t[stMaxMsgSize]); + spMsgBuffer[0] = _T('\0'); + + // find all CH Task files + TSmartPath pathToFind = m_pathTasksDir + PathFromString(_T("*.cht")); + + HANDLE hFind = ::FindFirstFile(pathToFind.ToString(), &wfd); + BOOL bContinue = TRUE; + while(hFind != INVALID_HANDLE_VALUE && bContinue) + { + pathFound = m_pathTasksDir + PathFromString(wfd.cFileName); + // load data + spTask = CreateEmptyTask(); + try + { + spTask->Load(pathFound); + + // add read task to array + Add(spTask); + } + catch(icpf::exception& e) + { + e.get_info(spMsgBuffer.get(), stMaxMsgSize); + bExceptionEncountered = true; + } + catch(std::exception& e) + { + _tcsncpy_s(spMsgBuffer.get(), stMaxMsgSize, CA2CT(e.what()), _TRUNCATE); + bExceptionEncountered = true; + } + + if(bExceptionEncountered) + { + TString strFmt = _T("Cannot load task data: %path (reason: %reason)"); + strFmt.Replace(_T("%path"), pathFound.ToString()); + strFmt.Replace(_T("%reason"), spMsgBuffer.get()); + + LOG_ERROR(strFmt); + + bExceptionEncountered = false; + } + bContinue = ::FindNextFile(hFind, &wfd); + } + + ::FindClose(hFind); +} + +void TTaskManager::TasksBeginProcessing() +{ + boost::shared_lock lock(m_lock); + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + spTask->BeginProcessing(); + } +} + +void TTaskManager::TasksPauseProcessing() +{ + boost::shared_lock lock(m_lock); + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + spTask->PauseProcessing(); + } +} + +void TTaskManager::TasksResumeProcessing() +{ + boost::shared_lock lock(m_lock); + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + spTask->ResumeProcessing(); + } +} + +void TTaskManager::TasksRestartProcessing() +{ + boost::shared_lock lock(m_lock); + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + spTask->RestartProcessing(); + } +} + +bool TTaskManager::TasksRetryProcessing() +{ + boost::shared_lock lock(m_lock); + bool bChanged=false; + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + if(spTask->RetryProcessing()) + bChanged = true; + } + + return bChanged; +} + +void TTaskManager::TasksCancelProcessing() +{ + boost::shared_lock lock(m_lock); + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + spTask->CancelProcessing(); + } +} + +ull_t TTaskManager::GetPosition() +{ + return m_globalStats.GetGlobalProcessedSize(); +} + +ull_t TTaskManager::GetRange() +{ + return m_globalStats.GetGlobalTotalSize(); +} + +int TTaskManager::GetPercent() +{ + return m_globalStats.GetProgressPercents(); +} + +bool TTaskManager::AreAllFinished() +{ + bool bFlag=true; + + if(m_globalStats.GetRunningTasksCount() != 0) + bFlag = false; + else + { + boost::shared_lock lock(m_lock); + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + ETaskCurrentState eState = spTask->GetTaskState(); + bFlag = (eState == eTaskState_Finished || eState == eTaskState_Cancelled || eState == eTaskState_Paused || eState == eTaskState_Error); + + if(!bFlag) + break; + } + } + + return bFlag; +} + +void TTaskManager::SetTasksDir(const TSmartPath& pathDir) +{ + boost::unique_lock lock(m_lock); + m_pathTasksDir = pathDir; +} + +void TTaskManager::StopAllTasksNL() +{ + // kill all unfinished tasks - send kill request + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + spTask->RequestStopThread(); + } + + // wait for finishing + BOOST_FOREACH(TTaskPtr& spTask, m_vTasks) + { + spTask->KillThread(); + } +} + +END_CHCORE_NAMESPACE Index: src/libchcore/TTaskManager.h =================================================================== diff -u --- src/libchcore/TTaskManager.h (revision 0) +++ src/libchcore/TTaskManager.h (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -0,0 +1,108 @@ +/*************************************************************************** +* Copyright (C) 2001-2008 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 __TASKMANAGER_H__ +#define __TASKMANAGER_H__ + +#include "libchcore.h" +#include "FeedbackHandlerBase.h" +#include "TTaskGlobalStats.h" +#include "TPath.h" + +BEGIN_CHCORE_NAMESPACE + +class TTaskDefinition; +class TTask; +typedef boost::shared_ptr TTaskPtr; + +// special value representing no task +#define NO_TASK_SESSION_UNIQUE_ID 0 + +/////////////////////////////////////////////////////////////////////////// +// TTaskManager + +class LIBCHCORE_API TTaskManager +{ +public: + TTaskManager(); + ~TTaskManager(); + + void Create(IFeedbackHandlerFactory* piFeedbackHandlerFactory); + + TTaskPtr CreateTask(const TTaskDefinition& tTaskDefinition); + TTaskPtr ImportTask(const TSmartPath& strTaskPath); + + size_t GetSize() const; + + TTaskPtr GetAt(size_t stIndex) const; + TTaskPtr GetTaskBySessionUniqueID(size_t stSessionUniqueID) const; + + size_t Add(const TTaskPtr& spNewTask); + + void RemoveAt(size_t stIndex, size_t stCount = 1); + void RemoveAll(); + void RemoveAllFinished(); + void RemoveFinished(const TTaskPtr& spSelTask); + + void ResumeWaitingTasks(size_t stMaxRunningTasks); + void StopAllTasks(); + + void SaveData(); + void LoadDataProgress(); + + void TasksBeginProcessing(); + void TasksPauseProcessing(); + void TasksResumeProcessing(); + void TasksRestartProcessing(); + bool TasksRetryProcessing(); + void TasksCancelProcessing(); + + ull_t GetPosition(); + ull_t GetRange(); + int GetPercent(); + + bool AreAllFinished(); + + void SetTasksDir(const TSmartPath& pathDir); + +protected: + void StopAllTasksNL(); + + TTaskPtr CreateEmptyTask(); + +public: + TSmartPath m_pathTasksDir; + +private: +#pragma warning(push) +#pragma warning(disable: 4251) + mutable boost::shared_mutex m_lock; + std::vector m_vTasks; // vector with tasks objects +#pragma warning(pop) + + TTasksGlobalStats m_globalStats; // global stats for all tasks + + size_t m_stNextSessionUniqueID; // global counter for providing unique ids for tasks per session (launch of the program) + +protected: + IFeedbackHandlerFactory* m_piFeedbackFactory; +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/libchcore.vc90.vcproj =================================================================== diff -u -r0cf74c78280b58c363868caafb9bf493a57aa006 -r1d8d51e0dd4d8ebcf0bd457d01fab984585220c0 --- src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -364,14 +364,6 @@ > - - - - @@ -408,6 +400,14 @@ > + + + + @@ -435,6 +435,14 @@ RelativePath=".\TTaskLocalStats.h" > + + + +