Index: src/ch/ClipboardMonitor.cpp =================================================================== diff -u -N -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 -N -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 -N -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 -N -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 -N -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 -N -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 -N -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 -N -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 -N -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 -N -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 -N -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 -N -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 -N --- 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 Index: src/libchcore/TTask.h =================================================================== diff -u -N --- src/libchcore/TTask.h (revision 0) +++ src/libchcore/TTask.h (revision 1d8d51e0dd4d8ebcf0bd457d01fab984585220c0) @@ -0,0 +1,264 @@ +/*************************************************************************** +* 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 __TASK_H__ +#define __TASK_H__ + +#include "libchcore.h" +#include "TWorkerThreadController.h" +#include "FeedbackHandlerBase.h" +#include "TTaskDefinition.h" +#include "TTaskConfigTracker.h" +#include "TBasePathData.h" +#include "TSubTaskBase.h" +#include "TTaskLocalStats.h" +#include "TBasicProgressInfo.h" +#include "..\libicpf\log.h" +#include "TLocalFilesystem.h" + +BEGIN_CHCORE_NAMESPACE + +class TBufferSizes; + +// enum representing current processing state of the task +enum ETaskCurrentState +{ + eTaskState_None, + eTaskState_Waiting, + eTaskState_Processing, + eTaskState_Paused, + eTaskState_Cancelled, + eTaskState_Error, + eTaskState_Finished, + + // insert new values before this one + eTaskState_Max +}; + +// structure for getting status of a task +struct TASK_DISPLAY_DATA +{ + TString m_strFullFilePath; + TString m_strFileName; + + int m_iCurrentBufferSize; + int m_iCurrentBufferIndex; + size_t m_stIndex; + size_t m_stSize; + + TSmartPath m_pathDstPath; + TFiltersArray* m_pafFilters; + + ETaskCurrentState m_eTaskState; + EOperationType m_eOperationType; + ESubOperationType m_eSubOperationType; + + int m_nPriority; + + ull_t m_ullProcessedSize; + ull_t m_ullSizeAll; + int m_nPercent; + + time_t m_timeElapsed; + + TString m_strUniqueName; // doesn't change from first setting + + bool m_bIgnoreDirectories; + bool m_bCreateEmptyFiles; +}; + +struct TASK_MINI_DISPLAY_DATA +{ + TString m_strPath; + + ETaskCurrentState m_eTaskState; + + int m_nPercent; +}; + +/////////////////////////////////////////////////////////////////////////// +// TTask + +class LIBCHCORE_API TTask +{ +public: + enum EPathType + { + ePathType_TaskDefinition, + ePathType_TaskRarelyChangingState, + ePathType_TaskOftenChangingState, + ePathType_TaskLogFile, + }; + +public: + ~TTask(); + + const TTaskDefinition& GetTaskDefinition() const { return m_tTaskDefinition; } + + void SetTaskState(ETaskCurrentState eTaskState); + ETaskCurrentState GetTaskState() const; + + // m_nBufferSize + void SetBufferSizes(const TBufferSizes& bsSizes); + void GetBufferSizes(TBufferSizes& bsSizes); + int GetCurrentBufferIndex(); + + // thread + void SetPriority(int nPriority); + + void Load(const TSmartPath& strPath); + void Store(); + + void BeginProcessing(); + + void PauseProcessing(); // pause + void ResumeProcessing(); // resume + bool RetryProcessing(); // retry + void RestartProcessing(); // from beginning + void CancelProcessing(); // cancel + + void GetSnapshot(TASK_DISPLAY_DATA *pData); + void GetMiniSnapshot(TASK_MINI_DISPLAY_DATA *pData); + + void SetTaskDirectory(const TSmartPath& strDir); + TSmartPath GetTaskDirectory() const; + + void SetTaskFilePath(const TSmartPath& strPath); + TSmartPath GetTaskFilePath() const; + + void SetForceFlag(bool bFlag = true); + bool GetForceFlag(); + + size_t GetSessionUniqueID() const { return m_stSessionUniqueID; } + + TSmartPath GetRelatedPath(EPathType ePathType); + +protected: + TTask(IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID); + + void SetTaskDefinition(const TTaskDefinition& rTaskDefinition); + + // methods are called when task is being added or removed from the global task array + /// Method is called when this task is being added to a TTaskManager object + void OnRegisterTask(TTasksGlobalStats& rtGlobalStats); + /// Method is called when task is being removed from the TTaskManager object + void OnUnregisterTask(); + + /// Method is called when processing is being started + void OnBeginOperation(); + /// Method is called when processing is being ended + void OnEndOperation(); + + // Processing operations + + /// Thread function that delegates call to the TTask::ThrdProc + static DWORD WINAPI DelegateThreadProc(LPVOID pParam); + + /// Main function for the task processing thread + DWORD WINAPI ThrdProc(); + + TSubTaskBase::ESubOperationResult CheckForWaitState(); + + // m_nStatus + void SetStatusNL(UINT nStatus, UINT nMask); + UINT GetStatusNL(UINT nMask = 0xffffffff); + + void CalculateProcessedSize(); + void CalculateProcessedSizeNL(); + + void CalculateTotalSizeNL(); + + void DeleteProgress(); + + void SetForceFlagNL(bool bFlag = true); + bool GetForceFlagNL(); + + void SetContinueFlag(bool bFlag = true); + bool GetContinueFlag(); + void SetContinueFlagNL(bool bFlag = true); + bool GetContinueFlagNL(); + + bool CanBegin(); + + void KillThread(); + void RequestStopThread(); + + TSmartPath GetRelatedPathNL(EPathType ePathType); + + static void OnCfgOptionChanged(const TStringSet& rsetChanges, void* pParam); + +private: + // task initial information (needed to start a task); might be a bit processed. + TTaskDefinition m_tTaskDefinition; + + TTaskConfigTracker m_cfgTracker; + + TBasePathDataContainer m_arrSourcePathsInfo; + + // current task state (derivatives of the task initial information) + // changing slowly or only partially + TFileInfoArray m_files; // list of files/directories found during operating on the task input data (filled by search for files) + + // changing fast + volatile ETaskCurrentState m_eCurrentState; // current state of processing this task represents + + TTaskBasicProgressInfo m_tTaskBasicProgressInfo; // task progress information + + // task control variables (per-session state) + TTaskLocalStats m_localStats; // local statistics + + // task settings + TFiltersArray m_afFilters; // filtering settings for files (will be filtered according to the rules inside when searching for files) + + bool m_bForce; // if the continuation of tasks should be independent of max concurrently running task limit + bool m_bContinue; // allows task to continue + + TSmartPath m_strTaskDirectory; // base path at which the files will be stored + TSmartPath m_strFilePath; // exact filename with path to the task definition file + + bool m_bRareStateModified; // rarely changing state has been modified + bool m_bOftenStateModified; // rarely changing state has been modified + + size_t m_stSessionUniqueID; ///< Per-session unique ID for this task + + // other helpers + icpf::log_file m_log; ///< Log file where task information will be stored + + // Local filesystem access + TLocalFilesystem m_fsLocal; + + /// Thread controlling object + TWorkerThreadController m_workerThread; + + /// Mutex for locking concurrent access to members of this class +#pragma warning(push) +#pragma warning(disable: 4251) + mutable boost::shared_mutex m_lock; +#pragma warning(pop) + + /// Pointer to the feedback handler, providing responses to feedback requests + IFeedbackHandler* m_piFeedbackHandler; + + friend class TTaskManager; +}; + +typedef boost::shared_ptr TTaskPtr; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/task.h =================================================================== diff -u -N --- src/libchcore/task.h (revision 0cf74c78280b58c363868caafb9bf493a57aa006) +++ src/libchcore/task.h (revision 0) @@ -1,340 +0,0 @@ -/*************************************************************************** -* 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 __TASK_H__ -#define __TASK_H__ - -#include "libchcore.h" -#include "TAutoHandles.h" -#include "TWorkerThreadController.h" -#include "FileInfo.h" -#include "DataBuffer.h" -#include "FeedbackHandlerBase.h" -#include "FileFilter.h" -#include "TTaskDefinition.h" -#include "TTaskConfigTracker.h" -#include "TBasePathData.h" -#include "TSubTaskBase.h" -#include "TTaskLocalStats.h" -#include "TTaskGlobalStats.h" -#include "TBasicProgressInfo.h" -#include "TLocalFilesystem.h" -#include "..\libicpf\log.h" - -BEGIN_CHCORE_NAMESPACE - -// enum representing current processing state of the task -enum ETaskCurrentState -{ - eTaskState_None, - eTaskState_Waiting, - eTaskState_Processing, - eTaskState_Paused, - eTaskState_Cancelled, - eTaskState_Error, - eTaskState_Finished, - - // insert new values before this one - eTaskState_Max -}; - -// special value representing no task -#define NO_TASK_SESSION_UNIQUE_ID 0 - -// structure for getting status of a task -struct TASK_DISPLAY_DATA -{ - TString m_strFullFilePath; - TString m_strFileName; - - int m_iCurrentBufferSize; - int m_iCurrentBufferIndex; - size_t m_stIndex; - size_t m_stSize; - - TSmartPath m_pathDstPath; - TFiltersArray* m_pafFilters; - - ETaskCurrentState m_eTaskState; - EOperationType m_eOperationType; - ESubOperationType m_eSubOperationType; - - int m_nPriority; - - ull_t m_ullProcessedSize; - ull_t m_ullSizeAll; - int m_nPercent; - - time_t m_timeElapsed; - - TString m_strUniqueName; // doesn't change from first setting - - bool m_bIgnoreDirectories; - bool m_bCreateEmptyFiles; -}; - -struct TASK_MINI_DISPLAY_DATA -{ - TString m_strPath; - - ETaskCurrentState m_eTaskState; - - int m_nPercent; -}; - -/////////////////////////////////////////////////////////////////////////// -// CTask - -class LIBCHCORE_API CTask -{ -public: - enum EPathType - { - ePathType_TaskDefinition, - ePathType_TaskRarelyChangingState, - ePathType_TaskOftenChangingState, - ePathType_TaskLogFile, - }; - -public: - ~CTask(); - - const TTaskDefinition& GetTaskDefinition() const { return m_tTaskDefinition; } - - void SetTaskState(ETaskCurrentState eTaskState); - ETaskCurrentState GetTaskState() const; - - // m_nBufferSize - void SetBufferSizes(const TBufferSizes& bsSizes); - void GetBufferSizes(TBufferSizes& bsSizes); - int GetCurrentBufferIndex(); - - // thread - void SetPriority(int nPriority); - - void Load(const TSmartPath& strPath); - void Store(); - - void BeginProcessing(); - - void PauseProcessing(); // pause - void ResumeProcessing(); // resume - bool RetryProcessing(); // retry - void RestartProcessing(); // from beginning - void CancelProcessing(); // cancel - - void GetSnapshot(TASK_DISPLAY_DATA *pData); - void GetMiniSnapshot(TASK_MINI_DISPLAY_DATA *pData); - - void SetTaskDirectory(const TSmartPath& strDir); - TSmartPath GetTaskDirectory() const; - - void SetTaskFilePath(const TSmartPath& strPath); - TSmartPath GetTaskFilePath() const; - - void SetForceFlag(bool bFlag = true); - bool GetForceFlag(); - - size_t GetSessionUniqueID() const { return m_stSessionUniqueID; } - - TSmartPath GetRelatedPath(EPathType ePathType); - -protected: - CTask(IFeedbackHandler* piFeedbackHandler, size_t stSessionUniqueID); - - void SetTaskDefinition(const TTaskDefinition& rTaskDefinition); - - // methods are called when task is being added or removed from the global task array - /// Method is called when this task is being added to a CTaskArray object - void OnRegisterTask(TTasksGlobalStats& rtGlobalStats); - /// Method is called when task is being removed from the CTaskArray object - void OnUnregisterTask(); - - /// Method is called when processing is being started - void OnBeginOperation(); - /// Method is called when processing is being ended - void OnEndOperation(); - - // Processing operations - - /// Thread function that delegates call to the CTask::ThrdProc - static DWORD WINAPI DelegateThreadProc(LPVOID pParam); - - /// Main function for the task processing thread - DWORD WINAPI ThrdProc(); - - TSubTaskBase::ESubOperationResult CheckForWaitState(); - - // m_nStatus - void SetStatusNL(UINT nStatus, UINT nMask); - UINT GetStatusNL(UINT nMask = 0xffffffff); - - void CalculateProcessedSize(); - void CalculateProcessedSizeNL(); - - void CalculateTotalSizeNL(); - - void DeleteProgress(); - - void SetForceFlagNL(bool bFlag = true); - bool GetForceFlagNL(); - - void SetContinueFlag(bool bFlag = true); - bool GetContinueFlag(); - void SetContinueFlagNL(bool bFlag = true); - bool GetContinueFlagNL(); - - bool CanBegin(); - - void KillThread(); - void RequestStopThread(); - - TSmartPath GetRelatedPathNL(EPathType ePathType); - - static void OnCfgOptionChanged(const TStringSet& rsetChanges, void* pParam); - -private: - // task initial information (needed to start a task); might be a bit processed. - TTaskDefinition m_tTaskDefinition; - - TTaskConfigTracker m_cfgTracker; - - TBasePathDataContainer m_arrSourcePathsInfo; - - // current task state (derivatives of the task initial information) - // changing slowly or only partially - TFileInfoArray m_files; // list of files/directories found during operating on the task input data (filled by search for files) - - // changing fast - volatile ETaskCurrentState m_eCurrentState; // current state of processing this task represents - - TTaskBasicProgressInfo m_tTaskBasicProgressInfo; // task progress information - - // task control variables (per-session state) - TTaskLocalStats m_localStats; // local statistics - - // task settings - TFiltersArray m_afFilters; // filtering settings for files (will be filtered according to the rules inside when searching for files) - - bool m_bForce; // if the continuation of tasks should be independent of max concurrently running task limit - bool m_bContinue; // allows task to continue - - TSmartPath m_strTaskDirectory; // base path at which the files will be stored - TSmartPath m_strFilePath; // exact filename with path to the task definition file - - bool m_bRareStateModified; // rarely changing state has been modified - bool m_bOftenStateModified; // rarely changing state has been modified - - size_t m_stSessionUniqueID; ///< Per-session unique ID for this task - - // other helpers - icpf::log_file m_log; ///< Log file where task information will be stored - - // Local filesystem access - TLocalFilesystem m_fsLocal; - - /// Thread controlling object - TWorkerThreadController m_workerThread; - - /// Mutex for locking concurrent access to members of this class -#pragma warning(push) -#pragma warning(disable: 4251) - mutable boost::shared_mutex m_lock; -#pragma warning(pop) - - /// Pointer to the feedback handler, providing responses to feedback requests - IFeedbackHandler* m_piFeedbackHandler; - - friend class CTaskArray; -}; - -typedef boost::shared_ptr CTaskPtr; - -/////////////////////////////////////////////////////////////////////////// -// CTaskArray - -class LIBCHCORE_API CTaskArray -{ -public: - CTaskArray(); - ~CTaskArray(); - - void Create(IFeedbackHandlerFactory* piFeedbackHandlerFactory); - - CTaskPtr CreateTask(const TTaskDefinition& tTaskDefinition); - CTaskPtr ImportTask(const TSmartPath& strTaskPath); - - size_t GetSize() const; - - CTaskPtr GetAt(size_t stIndex) const; - CTaskPtr GetTaskBySessionUniqueID(size_t stSessionUniqueID) const; - - size_t Add(const CTaskPtr& spNewTask); - - void RemoveAt(size_t stIndex, size_t stCount = 1); - void RemoveAll(); - void RemoveAllFinished(); - void RemoveFinished(const CTaskPtr& 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(); - - CTaskPtr 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/TTaskManager.cpp =================================================================== diff -u -N --- 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 -N --- 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 -N -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" > + + + +