Index: src/ch/CfgProperties.h =================================================================== diff -u -r1d7d79169d480a02e335b8b0a4919f9c78d58325 -rca046f75806db6693a4b2dc6ddb255f76d0bbc3f --- src/ch/CfgProperties.h (.../CfgProperties.h) (revision 1d7d79169d480a02e335b8b0a4919f9c78d58325) +++ src/ch/CfgProperties.h (.../CfgProperties.h) (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -253,14 +253,15 @@ typename PropData::value_type GetPropValue(const TConfig& rConfig) { typename PropData::value_type tValue; - rConfig.GetValue(CString(PropData::GetPropertyNamePrefix()) + PropData::GetPropertyName(), tValue, PropData::GetDefaultValue()); + if(!rConfig.GetValue(CString(PropData::GetPropertyNamePrefix()) + PropData::GetPropertyName(), tValue)) + tValue = PropData::GetDefaultValue(); return tValue; } template bool GetPropValue(const TConfig& rConfig, typename PropData::value_type& rValue) { - return rConfig.GetValue(CString(PropData::GetPropertyNamePrefix()) + PropData::GetPropertyName(), rValue, PropData::GetDefaultValue()); + return rConfig.GetValue(CString(PropData::GetPropertyNamePrefix()) + PropData::GetPropertyName(), rValue); } template Index: src/ch/TConfig.cpp =================================================================== diff -u -r1d7d79169d480a02e335b8b0a4919f9c78d58325 -rca046f75806db6693a4b2dc6ddb255f76d0bbc3f --- src/ch/TConfig.cpp (.../TConfig.cpp) (revision 1d7d79169d480a02e335b8b0a4919f9c78d58325) +++ src/ch/TConfig.cpp (.../TConfig.cpp) (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -64,6 +64,41 @@ } ///////////////////////////////////////////////////////////////////////////////////////////// +// common set/get templates +template +bool GetValue(const boost::property_tree::wiptree& rTree, PCTSTR pszPropName, T& tOutValue, boost::shared_mutex& rLock) +{ + boost::shared_lock lock(rLock); + + boost::optional tValue = rTree.get_optional(pszPropName); + if(tValue.is_initialized()) + { + tOutValue = tValue.get(); + return true; + } + else + return false; +} + +template +bool SetValue(boost::property_tree::wiptree& rTree, bool& bModified, boost::shared_mutex& rLock, PCTSTR pszPropName, const T& tNewValue) +{ + // separate scope for mutex (to avoid calling notifier inside critical section) + boost::upgrade_lock lock(rLock); + + boost::optional tValue = rTree.get_optional(pszPropName); + if(tValue.is_initialized() && tValue.get() != tNewValue) + { + boost::upgrade_to_unique_lock upgraded_lock(lock); + rTree.put(pszPropName, tNewValue); + bModified = true; + return true; + } + + return false; +} + +///////////////////////////////////////////////////////////////////////////////////////////// // class TConfig TConfig::TConfig() : @@ -184,71 +219,44 @@ // value setting/retrieval bool TConfig::GetBool(PCTSTR pszPropName, bool bDefault) const { - boost::shared_lock lock(m_lock); - return m_propTree.get(pszPropName, bDefault); + bool bResult = bDefault; + if(!::GetValue(m_propTree, pszPropName, bResult, m_lock)) + bResult = bDefault; + return bResult; } -bool TConfig::GetValue(PCTSTR pszPropName, bool& bValue, bool bDefault) const +bool TConfig::GetValue(PCTSTR pszPropName, bool& bValue) const { - boost::optional tValue = m_propTree.get_optional(pszPropName); - if(tValue.is_initialized()) - { - bValue = tValue.get(); - return true; - } - else - { - bValue = bDefault; - return false; - } + return ::GetValue(m_propTree, pszPropName, bValue, m_lock); } TConfig& TConfig::SetValue(PCTSTR pszPropName, bool bValue) { - // separate scope for mutex (to avoid calling notifier inside critical section) - { - boost::unique_lock lock(m_lock); - m_propTree.put(pszPropName, bValue); - m_bModified = true; - } + if(::SetValue(m_propTree, m_bModified, m_lock, pszPropName, bValue)) + SendNotification(pszPropName); - SendNotification(pszPropName); return *this; } int TConfig::GetInt(PCTSTR pszPropName, int iDefault) const { - boost::shared_lock lock(m_lock); - return m_propTree.get(pszPropName, iDefault); + int iResult = 0; + if(!::GetValue(m_propTree, pszPropName, iResult, m_lock)) + iResult = iDefault; + return iResult; } - -bool TConfig::GetValue(PCTSTR pszPropName, int& iValue, int iDefault) const +bool TConfig::GetValue(PCTSTR pszPropName, int& iValue) const { - boost::optional tValue = m_propTree.get_optional(pszPropName); - if(tValue.is_initialized()) - { - iValue = tValue.get(); - return true; - } - else - { - iValue = iDefault; - return false; - } + return ::GetValue(m_propTree, pszPropName, iValue, m_lock); } TConfig& TConfig::SetValue(PCTSTR pszPropName, int iValue) { - // separate scope for mutex (to avoid calling notifier inside critical section) - { - boost::unique_lock lock(m_lock); - m_propTree.put(pszPropName, iValue); - m_bModified = true; - } + if(::SetValue(m_propTree, m_bModified, m_lock, pszPropName, iValue)) + SendNotification(pszPropName); - SendNotification(pszPropName); - return *this; + return *this; } unsigned int TConfig::GetUInt(PCTSTR pszPropName, unsigned int uiDefault) const @@ -257,32 +265,17 @@ return m_propTree.get(pszPropName, uiDefault); } -bool TConfig::GetValue(PCTSTR pszPropName, unsigned int& uiValue, unsigned int uiDefault) const +bool TConfig::GetValue(PCTSTR pszPropName, unsigned int& uiValue) const { - boost::optional tValue = m_propTree.get_optional(pszPropName); - if(tValue.is_initialized()) - { - uiValue = tValue.get(); - return true; - } - else - { - uiValue = uiDefault; - return false; - } + return ::GetValue(m_propTree, pszPropName, uiValue, m_lock); } TConfig& TConfig::SetValue(PCTSTR pszPropName, unsigned int uiValue) { - // separate scope for mutex (to avoid calling notifier inside critical section) - { - boost::unique_lock lock(m_lock); - m_propTree.put(pszPropName, uiValue); - m_bModified = true; - } + if(::SetValue(m_propTree, m_bModified, m_lock, pszPropName, uiValue)) + SendNotification(pszPropName); - SendNotification(pszPropName); - return *this; + return *this; } long long TConfig::GetLongLong(PCTSTR pszPropName, long long llDefault) const @@ -291,32 +284,17 @@ return m_propTree.get(pszPropName, llDefault); } -bool TConfig::GetValue(PCTSTR pszPropName, long long& llValue, long long llDefault) const +bool TConfig::GetValue(PCTSTR pszPropName, long long& llValue) const { - boost::optional tValue = m_propTree.get_optional(pszPropName); - if(tValue.is_initialized()) - { - llValue = tValue.get(); - return true; - } - else - { - llValue = llDefault; - return false; - } + return ::GetValue(m_propTree, pszPropName, llValue, m_lock); } TConfig& TConfig::SetValue(PCTSTR pszPropName, long long llValue) { - // separate scope for mutex (to avoid calling notifier inside critical section) - { - boost::unique_lock lock(m_lock); - m_propTree.put(pszPropName, llValue); - m_bModified = true; - } + if(::SetValue(m_propTree, m_bModified, m_lock, pszPropName, llValue)) + SendNotification(pszPropName); - SendNotification(pszPropName); - return *this; + return *this; } unsigned long long TConfig::GetULongLong(PCTSTR pszPropName, unsigned long long ullDefault) const @@ -325,32 +303,17 @@ return m_propTree.get(pszPropName, ullDefault); } -bool TConfig::GetValue(PCTSTR pszPropName, unsigned long long& ullValue, unsigned long long ullDefault) const +bool TConfig::GetValue(PCTSTR pszPropName, unsigned long long& ullValue) const { - boost::optional tValue = m_propTree.get_optional(pszPropName); - if(tValue.is_initialized()) - { - ullValue = tValue.get(); - return true; - } - else - { - ullValue = ullDefault; - return false; - } + return ::GetValue(m_propTree, pszPropName, ullValue, m_lock); } TConfig& TConfig::SetValue(PCTSTR pszPropName, unsigned long long ullValue) { - // separate scope for mutex (to avoid calling notifier inside critical section) - { - boost::unique_lock lock(m_lock); - m_propTree.put(pszPropName, ullValue); - m_bModified = true; - } + if(::SetValue(m_propTree, m_bModified, m_lock, pszPropName, ullValue)) + SendNotification(pszPropName); - SendNotification(pszPropName); - return *this; + return *this; } double TConfig::GetDouble(PCTSTR pszPropName, double dDefault) const @@ -359,32 +322,17 @@ return m_propTree.get(pszPropName, dDefault); } -bool TConfig::GetValue(PCTSTR pszPropName, double& dValue, double dDefault) const +bool TConfig::GetValue(PCTSTR pszPropName, double& dValue) const { - boost::optional tValue = m_propTree.get_optional(pszPropName); - if(tValue.is_initialized()) - { - dValue = tValue.get(); - return true; - } - else - { - dValue = dDefault; - return false; - } + return ::GetValue(m_propTree, pszPropName, dValue, m_lock); } TConfig& TConfig::SetValue(PCTSTR pszPropName, double dValue) { - // separate scope for mutex (to avoid calling notifier inside critical section) - { - boost::unique_lock lock(m_lock); - m_propTree.put(pszPropName, dValue); - m_bModified = true; - } + if(::SetValue(m_propTree, m_bModified, m_lock, pszPropName, dValue)) + SendNotification(pszPropName); - SendNotification(pszPropName); - return *this; + return *this; } CString TConfig::GetString(PCTSTR pszPropName, const CString& strDefault) const @@ -394,53 +342,29 @@ return wstrData.c_str(); } -bool TConfig::GetValue(PCTSTR pszPropName, CString& rstrValue, const CString& strDefault) const +bool TConfig::GetValue(PCTSTR pszPropName, CString& rstrValue) const { - boost::optional tValue = m_propTree.get_optional(pszPropName); - if(tValue.is_initialized()) - { - rstrValue = tValue.get().c_str(); - return true; - } - else - { - rstrValue = strDefault; - return false; - } + std::wstring wstrData; + bool bResult = ::GetValue(m_propTree, pszPropName, wstrData, m_lock); + rstrValue = wstrData.c_str(); + + return bResult; } TConfig& TConfig::SetValue(PCTSTR pszPropName, const CString& strValue) { - // separate scope for mutex (to avoid calling notifier inside critical section) - { - boost::unique_lock lock(m_lock); - m_propTree.put(pszPropName, std::wstring(strValue)); - m_bModified = true; - } + std::wstring wstrData = strValue; + if(::SetValue(m_propTree, m_bModified, m_lock, pszPropName, wstrData)) + SendNotification(pszPropName); - SendNotification(pszPropName); - return *this; + return *this; } bool TConfig::GetValue(PCTSTR pszPropName, std::vector& rvValues) const { boost::shared_lock lock(m_lock); - bool bResult = false; rvValues.clear(); - BOOST_FOREACH(const boost::property_tree::wiptree::value_type& rEntry, m_propTree.get_child(pszPropName)) - { - rvValues.push_back(rEntry.second.data().c_str()); - bResult = true; - } - return bResult; -} - -bool TConfig::GetValue(PCTSTR pszPropName, std::vector& rvValues, const std::vector& rvDefault) const -{ - boost::shared_lock lock(m_lock); - rvValues.clear(); - boost::optional children = m_propTree.get_child_optional(pszPropName); if(children.is_initialized()) { @@ -452,10 +376,7 @@ return true; } else - { - rvValues = rvDefault; return false; - } } void TConfig::SetValue(PCTSTR pszPropName, const std::vector& rvValues) Index: src/ch/TConfig.h =================================================================== diff -u -r1d7d79169d480a02e335b8b0a4919f9c78d58325 -rca046f75806db6693a4b2dc6ddb255f76d0bbc3f --- src/ch/TConfig.h (.../TConfig.h) (revision 1d7d79169d480a02e335b8b0a4919f9c78d58325) +++ src/ch/TConfig.h (.../TConfig.h) (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -71,36 +71,35 @@ void MarkAsNotModified(); // value setting/retrieval - bool GetBool(PCTSTR pszPropName, bool bDefault) const; - bool GetValue(PCTSTR pszPropName, bool& bValue, bool bDefault) const; + bool GetBool(PCTSTR pszPropName, bool bDefault = false) const; + bool GetValue(PCTSTR pszPropName, bool& bValue) const; TConfig& SetValue(PCTSTR pszPropName, bool bValue); - int GetInt(PCTSTR pszPropName, int iDefault) const; - bool GetValue(PCTSTR pszPropName, int& iValue, int iDefault) const; + int GetInt(PCTSTR pszPropName, int iDefault = 0) const; + bool GetValue(PCTSTR pszPropName, int& iValue) const; TConfig& SetValue(PCTSTR pszPropName, int iValue); unsigned int GetUInt(PCTSTR pszPropName, unsigned int uiDefault) const; - bool GetValue(PCTSTR pszPropName, unsigned int& uiValue, unsigned int uiDefault) const; + bool GetValue(PCTSTR pszPropName, unsigned int& uiValue) const; TConfig& SetValue(PCTSTR pszPropName, unsigned int uiValue); long long GetLongLong(PCTSTR pszPropName, long long llDefault) const; - bool GetValue(PCTSTR pszPropName, long long& llValue, long long llDefault) const; + bool GetValue(PCTSTR pszPropName, long long& llValue) const; TConfig& SetValue(PCTSTR pszPropName, long long llValue); unsigned long long GetULongLong(PCTSTR pszPropName, unsigned long long ullDefault) const; - bool GetValue(PCTSTR pszPropName, unsigned long long& ullValue, unsigned long long ullDefault) const; + bool GetValue(PCTSTR pszPropName, unsigned long long& ullValue) const; TConfig& SetValue(PCTSTR pszPropName, unsigned long long ullValue); double GetDouble(PCTSTR pszPropName, double dDefault) const; - bool GetValue(PCTSTR pszPropName, double& dValue, double dDefault) const; + bool GetValue(PCTSTR pszPropName, double& dValue) const; TConfig& SetValue(PCTSTR pszPropName, double dValue); CString GetString(PCTSTR pszPropName, const CString& strDefault) const; - bool GetValue(PCTSTR pszPropName, CString& rstrValue, const CString& strDefault) const; + bool GetValue(PCTSTR pszPropName, CString& rstrValue) const; TConfig& SetValue(PCTSTR pszPropName, const CString& strValue); bool GetValue(PCTSTR pszPropName, std::vector& rvValues) const; - bool GetValue(PCTSTR pszPropName, std::vector& rvValues, const std::vector& rvDefault) const; void SetValue(PCTSTR pszPropName, const std::vector& rvValues); // extraction of subtrees @@ -114,6 +113,37 @@ void DelayNotifications(); void ResumeNotifications(); + // template access + template + typename PropInfo::value_type GetPropValue() const + { + typename PropInfo::value_type tValue; + if(!GetValue(PropInfo::GetPropertyName(), tValue)) + tValue = PropInfo::GetDefaultValue(); + + PropInfo::ValidateRange(tValue); + return tValue; + } + + template + bool GetPropValue(typename PropInfo::value_type& rValue) const + { + bool bResult = GetValue(PropInfo::GetPropertyName(), rValue, PropInfo::GetDefaultValue()); + if(bResult) + PropInfo::ValidateRange(rValue); + return bResult; + } + + template + void SetPropValue(const typename PropInfo::value_type& rValue) + { + typename PropInfo::value_type tValue(rValue); + PropInfo::ValidateRange(tValue); + + SetValue(PropInfo::GetPropertyName(), tValue); + } + + protected: void SendNotification(const std::set& rsetInfo); void SendNotification(PCTSTR pszInfo); @@ -133,4 +163,18 @@ mutable boost::shared_mutex m_lock; }; +template +struct PropDataBase +{ + typedef DataType value_type; + + static void ValidateRange(value_type&) {} // does nothing +}; + +template +struct PropDataMinMaxBase +{ + typedef DataType value_type; +}; + #endif Index: src/ch/TTaskConfigTracker.cpp =================================================================== diff -u --- src/ch/TTaskConfigTracker.cpp (revision 0) +++ src/ch/TTaskConfigTracker.cpp (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -0,0 +1,240 @@ +// ============================================================================ +// 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. +// ============================================================================ +/// @file TTaskConfigTracker.cpp +/// @date 2010/10/04 +/// @brief Contains implementation of TTaskConfigTracker class. +// ============================================================================ +#include "stdafx.h" +#include "TTaskConfigTracker.h" +#include "CfgProperties.h" + +TOptionsSet& TOptionsSet::operator%(ETaskOptions eOption) +{ + m_setOptions.insert(eOption); + + return *this; +} + +std::set& TOptionsSet::Get() +{ + return m_setOptions; +} + +TTaskConfigTracker::TTaskConfigTracker() +{ +} + +TTaskConfigTracker::~TTaskConfigTracker() +{ +} + +bool TTaskConfigTracker::IsModified() const +{ + boost::shared_lock lock(m_lock); + return !m_setModified.empty(); +} + +bool TTaskConfigTracker::IsModified(ETaskOptions eOption) const +{ + boost::shared_lock lock(m_lock); + return m_setModified.find(eOption) != m_setModified.end(); +} + +bool TTaskConfigTracker::IsModified(TOptionsSet setOptions) const +{ + boost::shared_lock lock(m_lock); + + std::set setCommon; + std::set_intersection(setOptions.Get().begin(), setOptions.Get().end(), m_setModified.begin(), m_setModified.end(), std::inserter(setCommon, setCommon.begin())); + + return !setCommon.empty(); +} + +bool TTaskConfigTracker::IsModified(ETaskOptions eOption, bool bResetModificationState) +{ + boost::upgrade_lock lock(m_lock); + + std::set::iterator iterOption = m_setModified.find(eOption); + bool bModified = (iterOption != m_setModified.end()); + if(bModified && bResetModificationState) + { + boost::upgrade_to_unique_lock upgraded_lock(lock); + m_setModified.erase(iterOption); + } + + return bModified; +} + +bool TTaskConfigTracker::IsModified(bool bResetModificationState, TOptionsSet setOptions) +{ + boost::upgrade_lock lock(m_lock); + + std::set setCommon; + std::set_intersection(setOptions.Get().begin(), setOptions.Get().end(), m_setModified.begin(), m_setModified.end(), std::inserter(setCommon, setCommon.begin())); + + bool bModified = setCommon.empty(); + if(bModified && bResetModificationState) + { + boost::upgrade_to_unique_lock upgraded_lock(lock); + std::set::iterator iterOption; + BOOST_FOREACH(ETaskOptions eOption, setCommon) + { + iterOption = m_setModified.find(eOption); + if(iterOption != m_setModified.end()) + m_setModified.erase(iterOption); + } + } + + return bModified; +} + +void TTaskConfigTracker::AddModified(const CString& strModified) +{ + ETaskOptions eOption = TTaskConfigTracker::GetOptionFromString(strModified); + + boost::unique_lock lock(m_lock); + + m_setModified.insert(eOption); +} + +void TTaskConfigTracker::AddModified(ETaskOptions eModified) +{ + boost::unique_lock lock(m_lock); + m_setModified.insert(eModified); +} + +void TTaskConfigTracker::AddModified(TOptionsSet setOptions) +{ + boost::unique_lock lock(m_lock); + m_setModified.insert(setOptions.Get().begin(), setOptions.Get().end()); +} + +void TTaskConfigTracker::AddModified(const std::set& setModified) +{ + boost::unique_lock lock(m_lock); + BOOST_FOREACH(const CString& strVal, setModified) + { + AddModified(strVal); + } +} + +void TTaskConfigTracker::AddModified(const std::set& setModified) +{ + boost::unique_lock lock(m_lock); + + m_setModified.insert(setModified.begin(), setModified.end()); +} + +void TTaskConfigTracker::RemoveModification(ETaskOptions eModified) +{ + boost::upgrade_lock lock(m_lock); + std::set::iterator iterOption = m_setModified.find(eModified); + if(iterOption != m_setModified.end()) + { + boost::upgrade_to_unique_lock upgraded_lock(lock); + m_setModified.erase(iterOption); + } +} + +void TTaskConfigTracker::RemoveModificationSet(TOptionsSet setOptions) +{ + boost::unique_lock lock(m_lock); + + std::set setCommon; + std::set_intersection(setOptions.Get().begin(), setOptions.Get().end(), m_setModified.begin(), m_setModified.end(), std::inserter(setCommon, setCommon.begin())); + + std::set::iterator iterOption; + BOOST_FOREACH(ETaskOptions eOption, setCommon) + { + iterOption = m_setModified.find(eOption); + if(iterOption != m_setModified.end()) + m_setModified.erase(iterOption); + } +} + +void TTaskConfigTracker::RemoveModification(const CString& strModified) +{ + ETaskOptions eOption = TTaskConfigTracker::GetOptionFromString(strModified); + RemoveModification(eOption); +} + +void TTaskConfigTracker::Clear() +{ + boost::unique_lock lock(m_lock); + m_setModified.clear(); +} + +void TTaskConfigTracker::NotificationProc(const std::set& setModifications, void* pParam) +{ + if(!pParam) + THROW(_T("Invalid pointer"), 0, 0, 0); + + TTaskConfigTracker* pTracker = (TTaskConfigTracker*)pParam; + pTracker->AddModified(setModifications); +} + +ETaskOptions TTaskConfigTracker::GetOptionFromString(const CString& strOption) +{ + if(strOption == TaskPropData::GetPropertyName()) + return eTO_UseOnlyDefaultBuffer; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_DefaultBufferSize; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_OneDiskBufferSize; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_TwoDisksBufferSize; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_CDBufferSize; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_LANBufferSize; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_DisableBuffering; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_DisableBufferingMinSize; + + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_SetDestinationAttributes; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_SetDestinationDateTime; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_ProtectReadOnlyFiles; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_ScanDirectoriesBeforeBlocking; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_ThreadPriority; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_DisablePriorityBoost; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_DeleteInSeparateSubTask; + + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_CreateEmptyFiles; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_CreateDirectoriesRelativeToRoot; + else if(strOption == TaskPropData::GetPropertyName()) + return eTO_IgnoreDirectories; + else + { + BOOST_ASSERT(false); // unhandled case + THROW(_T("Unhandled case"), 0, 0, 0); + } + + // add new elements before this one + BOOST_STATIC_ASSERT(eTO_Last == eTO_IgnoreDirectories + 1); +} Index: src/ch/TTaskConfigTracker.h =================================================================== diff -u --- src/ch/TTaskConfigTracker.h (revision 0) +++ src/ch/TTaskConfigTracker.h (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -0,0 +1,72 @@ +// ============================================================================ +// 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. +// ============================================================================ +/// @file TConfigTracker.h +/// @date 2010/10/04 +/// @brief Contains declaration of the TTaskConfigTracker class. +// ============================================================================ +#ifndef __TCONFIGTRACKER_H__ +#define __TCONFIGTRACKER_H__ + +#include "CfgProperties.h" + +class TOptionsSet +{ +public: + TOptionsSet& operator%(ETaskOptions eOption); + + std::set& Get(); + +private: + std::set m_setOptions; +}; + +class TTaskConfigTracker +{ +public: + TTaskConfigTracker(); + ~TTaskConfigTracker(); + + bool IsModified() const; + bool IsModified(ETaskOptions eOption) const; + bool IsModified(TOptionsSet setOptions) const; + bool IsModified(ETaskOptions eOption, bool bResetModificationState); + bool IsModified(bool bResetModificationState, TOptionsSet setOptions); + + void AddModified(const CString& strModified); + void AddModified(ETaskOptions eModified); + void AddModified(TOptionsSet setOptions); + void AddModified(const std::set& setModified); + void AddModified(const std::set& setModified); + + void RemoveModification(ETaskOptions eModified); + void RemoveModificationSet(TOptionsSet setOptions); + void RemoveModification(const CString& strModified); + void Clear(); + + static void NotificationProc(const std::set& setModifications, void* pParam); + +protected: + static ETaskOptions GetOptionFromString(const CString& strOption); + +protected: + std::set m_setModified; + mutable boost::shared_mutex m_lock; +}; + +#endif // __TCONFIGTRACKER_H__ Index: src/ch/TTaskConfiguration.h =================================================================== diff -u -r1d7d79169d480a02e335b8b0a4919f9c78d58325 -rca046f75806db6693a4b2dc6ddb255f76d0bbc3f --- src/ch/TTaskConfiguration.h (.../TTaskConfiguration.h) (revision 1d7d79169d480a02e335b8b0a4919f9c78d58325) +++ src/ch/TTaskConfiguration.h (.../TTaskConfiguration.h) (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -23,7 +23,7 @@ #ifndef __TTASKCONFIGURATION_H__ #define __TTASKCONFIGURATION_H__ -class TConfig; +#include "TConfig.h" enum ETaskOptions { @@ -47,6 +47,9 @@ eTO_CreateEmptyFiles, eTO_CreateDirectoriesRelativeToRoot, eTO_IgnoreDirectories, + + // add new elements before this one + eTO_Last }; ///////////////////////////////////////////////////////////////////////////////////////////// @@ -55,19 +58,24 @@ template struct TaskPropData; #define TASK_PROPERTY(enum_id, val_type, val_name, def_value)\ - template<> struct TaskPropData\ + template<> struct TaskPropData : public PropDataBase\ {\ - typedef val_type value_type;\ static value_type GetDefaultValue() { return def_value; }\ static const wchar_t* GetPropertyName() { return val_name; }\ } #define TASK_PROPERTY_MINMAX(enum_id, val_type, val_name, def_value, min_val, max_val)\ - template<> struct TaskPropData\ + template<> struct TaskPropData : public PropDataMinMaxBase\ {\ - typedef val_type value_type;\ static value_type GetDefaultValue() { return def_value; }\ static const wchar_t* GetPropertyName() { return val_name; }\ + static void ValidateRange(value_type& rValue)\ + {\ + if(rValue < (min_val))\ + rValue = (min_val);\ + else if(rValue > (max_val))\ + rValue = (max_val);\ + }\ } TASK_PROPERTY(eTO_UseOnlyDefaultBuffer, bool, _T("Buffer.UseOnlyDefaultBuffer"), false); @@ -99,21 +107,19 @@ template typename TaskPropData::value_type GetTaskPropValue(const TConfig& rConfig) { - typename TaskPropData::value_type tValue; - rConfig.GetValue(TaskPropData::GetPropertyName(), tValue, TaskPropData::GetDefaultValue()); - return tValue; + return rConfig.GetPropValue >(); } template bool GetTaskPropValue(const TConfig& rConfig, typename TaskPropData::value_type& rValue) { - return rConfig.GetValue(TaskPropData::GetPropertyName(), rValue, TaskPropData::GetDefaultValue()); + return rConfig.GetPropValue >(rValue); } template void SetTaskPropValue(TConfig& rConfig, const typename TaskPropData::value_type& rValue) { - rConfig.SetValue(TaskPropData::GetPropertyName(), rValue); + rConfig.SetPropValue >(rValue); } #endif Index: src/ch/TTaskDefinition.cpp =================================================================== diff -u -r1d7d79169d480a02e335b8b0a4919f9c78d58325 -rca046f75806db6693a4b2dc6ddb255f76d0bbc3f --- src/ch/TTaskDefinition.cpp (.../TTaskDefinition.cpp) (revision 1d7d79169d480a02e335b8b0a4919f9c78d58325) +++ src/ch/TTaskDefinition.cpp (.../TTaskDefinition.cpp) (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -166,8 +166,7 @@ // get information from config file // task unique id - use if provided, generate otherwise - tTaskInfo.GetValue(_T("TaskDefinition.UniqueID"), m_strTaskUniqueID, _T("")); - if(m_strTaskUniqueID.IsEmpty()) + if(!tTaskInfo.GetValue(_T("TaskDefinition.UniqueID"), m_strTaskUniqueID) || m_strTaskUniqueID.IsEmpty()) { boost::uuids::random_generator gen; boost::uuids::uuid u = gen(); @@ -177,13 +176,19 @@ } // basic information - tTaskInfo.GetValue(_T("TaskDefinition.SourcePaths"), m_vSourcePaths); - tTaskInfo.GetValue(_T("TaskDefinition.DestinationPath"), m_strDestinationPath, _T("")); + if(!tTaskInfo.GetValue(_T("TaskDefinition.SourcePaths"), m_vSourcePaths) || m_vSourcePaths.empty()) + THROW(_T("Missing source paths"), 0, 0, 0); + + if(!tTaskInfo.GetValue(_T("TaskDefinition.DestinationPath"), m_strDestinationPath) || m_strDestinationPath.IsEmpty()) + THROW(_T("Missing destination path"), 0, 0, 0); + if(m_strDestinationPath.Right(1) != _T("\\")) m_strDestinationPath += _T("\\"); int iOperation = eOperation_None; - tTaskInfo.GetValue(_T("TaskDefinition.OperationType"), iOperation, eOperation_None); + if(!tTaskInfo.GetValue(_T("TaskDefinition.OperationType"), iOperation)) + THROW(_T("Missing operation type"), 0, 0, 0); + m_tOperationPlan.SetOperationType((EOperationType)iOperation); tTaskInfo.ExtractSubConfig(_T("TaskDefinition.TaskSettings"), m_tConfiguration); Index: src/ch/ch.vc90.vcproj =================================================================== diff -u -r1d7d79169d480a02e335b8b0a4919f9c78d58325 -rca046f75806db6693a4b2dc6ddb255f76d0bbc3f --- src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision 1d7d79169d480a02e335b8b0a4919f9c78d58325) +++ src/ch/ch.vc90.vcproj (.../ch.vc90.vcproj) (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -523,6 +523,14 @@ > + + + + Index: src/ch/task.cpp =================================================================== diff -u -r0a673d59b6baab3d616ce2570e5bf63378fa7e3c -rca046f75806db6693a4b2dc6ddb255f76d0bbc3f --- src/ch/task.cpp (.../task.cpp) (revision 0a673d59b6baab3d616ce2570e5bf63378fa7e3c) +++ src/ch/task.cpp (.../task.cpp) (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -1920,11 +1920,18 @@ } // recreate buffer if needed - if(!(*pData->dbBuffer.GetSizes() == *GetBufferSizes())) + if(m_cfgTracker.IsModified() && m_cfgTracker.IsModified(TOptionsSet() % eTO_DefaultBufferSize % eTO_OneDiskBufferSize % eTO_TwoDisksBufferSize % eTO_CDBufferSize % eTO_LANBufferSize % eTO_UseOnlyDefaultBuffer)) { + BUFFERSIZES bs; + bs.m_bOnlyDefault = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + bs.m_uiDefaultSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + bs.m_uiOneDiskSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + bs.m_uiTwoDisksSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + bs.m_uiCDSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + bs.m_uiLANSize = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + // log const BUFFERSIZES* pbs1 = pData->dbBuffer.GetSizes(); - const BUFFERSIZES* pbs2 = GetBufferSizes(); fmt.SetFormat(_T("Changing buffer size from [Def:%defsize, One:%onesize, Two:%twosize, CD:%cdsize, LAN:%lansize] to [Def:%defsize2, One:%onesize2, Two:%twosize2, CD:%cdsize2, LAN:%lansize2] wile copying %srcfile -> %dstfile (CustomCopyFileFB)")); @@ -1933,16 +1940,16 @@ fmt.SetParam(_t("%twosize"), pbs1->m_uiTwoDisksSize); fmt.SetParam(_t("%cdsize"), pbs1->m_uiCDSize); fmt.SetParam(_t("%lansize"), pbs1->m_uiLANSize); - fmt.SetParam(_t("%defsize2"), pbs2->m_uiDefaultSize); - fmt.SetParam(_t("%onesize2"), pbs2->m_uiOneDiskSize); - fmt.SetParam(_t("%twosize2"), pbs2->m_uiTwoDisksSize); - fmt.SetParam(_t("%cdsize2"), pbs2->m_uiCDSize); - fmt.SetParam(_t("%lansize2"), pbs2->m_uiLANSize); + fmt.SetParam(_t("%defsize2"), bs.m_uiDefaultSize); + fmt.SetParam(_t("%onesize2"), bs.m_uiOneDiskSize); + fmt.SetParam(_t("%twosize2"), bs.m_uiTwoDisksSize); + fmt.SetParam(_t("%cdsize2"), bs.m_uiCDSize); + fmt.SetParam(_t("%lansize2"), bs.m_uiLANSize); fmt.SetParam(_t("%srcfile"), pData->spSrcFile->GetFullFilePath()); fmt.SetParam(_t("%dstfile"), pData->strDstFile); m_log.logi(fmt); - SetBufferSizes(pData->dbBuffer.Create(GetBufferSizes())); + pData->dbBuffer.Create(GetBufferSizes()); } // establish count of data to read @@ -2083,6 +2090,10 @@ CUSTOM_COPY_PARAMS ccp; ccp.bProcessed = false; ccp.bOnlyCreate = GetTaskPropValue(m_tTaskDefinition.GetConfiguration()); + + // remove changes in buffer sizes to avoid re-creation later + m_cfgTracker.RemoveModificationSet(TOptionsSet() % eTO_DefaultBufferSize % eTO_OneDiskBufferSize % eTO_TwoDisksBufferSize % eTO_CDBufferSize % eTO_LANBufferSize % eTO_UseOnlyDefaultBuffer); + ccp.dbBuffer.Create(GetBufferSizes()); ccp.pDestPath = &m_tDestinationPath; @@ -2359,6 +2370,9 @@ // start operation OnBeginOperation(); + // enable configuration changes tracking + m_tTaskDefinition.GetConfiguration().ConnectToNotifier(TTaskConfigTracker::NotificationProc, &m_cfgTracker); + // set thread options HANDLE hThread = GetCurrentThread(); ::SetThreadPriorityBoost(hThread, GetTaskPropValue(m_tTaskDefinition.GetConfiguration())); @@ -2476,11 +2490,15 @@ // mark this task as dead, so other can start m_localStats.MarkTaskAsNotRunning(); + m_tTaskDefinition.GetConfiguration().DisconnectFromNotifier(TTaskConfigTracker::NotificationProc); + // and the real end OnEndOperation(); } catch(...) { + m_tTaskDefinition.GetConfiguration().DisconnectFromNotifier(TTaskConfigTracker::NotificationProc); + // refresh time m_localStats.DisableTimeTracking(); Index: src/ch/task.h =================================================================== diff -u -r0a673d59b6baab3d616ce2570e5bf63378fa7e3c -rca046f75806db6693a4b2dc6ddb255f76d0bbc3f --- src/ch/task.h (.../task.h) (revision 0a673d59b6baab3d616ce2570e5bf63378fa7e3c) +++ src/ch/task.h (.../task.h) (revision ca046f75806db6693a4b2dc6ddb255f76d0bbc3f) @@ -27,6 +27,7 @@ #include "FileFilter.h" #include "DestPath.h" #include "TTaskDefinition.h" +#include "TTaskConfigTracker.h" // enum representing current processing state of the task enum ETaskCurrentState @@ -406,6 +407,8 @@ // task initial information (needed to start a task); might be a bit processed. TTaskDefinition m_tTaskDefinition; + TTaskConfigTracker m_cfgTracker; + CClipboardArray m_arrSourcePaths; CDestPath m_tDestinationPath;