Index: src/libchcore/TModificationTracker.cpp =================================================================== diff -u -N --- src/libchcore/TModificationTracker.cpp (revision 0) +++ src/libchcore/TModificationTracker.cpp (revision b7655a8f0721e5454befd29e3e067748eb0521e9) @@ -0,0 +1,26 @@ +// ============================================================================ +// Copyright (C) 2001-2014 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 "TModificationTracker.h" + +BEGIN_CHCORE_NAMESPACE + + + +END_CHCORE_NAMESPACE Index: src/libchcore/TModificationTracker.h =================================================================== diff -u -N --- src/libchcore/TModificationTracker.h (revision 0) +++ src/libchcore/TModificationTracker.h (revision b7655a8f0721e5454befd29e3e067748eb0521e9) @@ -0,0 +1,130 @@ +// ============================================================================ +// Copyright (C) 2001-2014 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 __TMODIFICATIONTRACKER_H__ +#define __TMODIFICATIONTRACKER_H__ + +#include "libchcore.h" + +BEGIN_CHCORE_NAMESPACE + +template +class TModificationTracker +{ +public: + TModificationTracker() : + m_tValue(), + m_bModified(false) + { + } + + template + TModificationTracker(const V& rValue) : + m_tValue(rValue), + m_bModified(true) + { + } + + template + TModificationTracker& operator=(const V& rValue) + { + m_tValue = rValue; + m_bModified = true; + } + + operator const T&() const + { + return m_tValue; + } + + operator T&() const + { + m_bModified = true; + return m_tValue; + } + + bool IsModified() const + { + return m_bModified; + } + +private: + T m_tValue; + bool m_bModified; +}; + +template +class TSharedModificationTracker +{ +private: + TSharedModificationTracker& operator=(const TSharedModificationTracker& rValue); + +public: + TSharedModificationTracker(bool& rbSharedFlag) : m_tValue(), m_rbModified(rbSharedFlag) + { + } + + template + TSharedModificationTracker(const V& rValue, bool& rbSharedFlag) : m_tValue(rValue), m_rbModified(rbSharedFlag) + { + } + + template + TSharedModificationTracker& operator=(const V& rValue) + { + m_tValue = rValue; + m_rbModified = true; + + return *this; + } + + operator const T&() const + { + return m_tValue; + } + + operator T&() + { + m_rbModified = true; + return m_tValue; + } + + const T* operator->() const + { + return &m_tValue; + } + + T* operator->() + { + m_rbModified = true; + return &m_tValue; + } + + bool IsModified() const + { + return m_rbModified; + } + +private: + T m_tValue; + bool& m_rbModified; +}; + +END_CHCORE_NAMESPACE + +#endif Index: src/libchcore/TSQLiteSerializerContainer.cpp =================================================================== diff -u -N -r31c4b1fc46687ed2cf35dd9fa0acec2543ae1886 -rb7655a8f0721e5454befd29e3e067748eb0521e9 --- src/libchcore/TSQLiteSerializerContainer.cpp (.../TSQLiteSerializerContainer.cpp) (revision 31c4b1fc46687ed2cf35dd9fa0acec2543ae1886) +++ src/libchcore/TSQLiteSerializerContainer.cpp (.../TSQLiteSerializerContainer.cpp) (revision b7655a8f0721e5454befd29e3e067748eb0521e9) @@ -69,12 +69,9 @@ { RowMap::iterator iterFnd = m_mapRows.find(stRowID); if(iterFnd != m_mapRows.end()) - { m_mapRows.erase(iterFnd); - m_setDeleteItems.insert(stRowID); - } - else - THROW_CORE_EXCEPTION(eErr_SerializeStoreError); + + m_setDeleteItems.insert(stRowID); } ISerializerRowReaderPtr TSQLiteSerializerContainer::GetRowReader() Index: src/libchcore/TSQLiteSerializerFactory.cpp =================================================================== diff -u -N -r30297d6aab17483da8e7b8323b4d17ff1a9f78d6 -rb7655a8f0721e5454befd29e3e067748eb0521e9 --- src/libchcore/TSQLiteSerializerFactory.cpp (.../TSQLiteSerializerFactory.cpp) (revision 30297d6aab17483da8e7b8323b4d17ff1a9f78d6) +++ src/libchcore/TSQLiteSerializerFactory.cpp (.../TSQLiteSerializerFactory.cpp) (revision b7655a8f0721e5454befd29e3e067748eb0521e9) @@ -46,20 +46,20 @@ case ISerializerFactory::eObj_Task: { TString strName(strNameHint); - if(strNameHint.IsEmpty()) + if(strName.IsEmpty()) { boost::uuids::random_generator gen; boost::uuids::uuid u = gen(); strName = boost::lexical_cast(u).c_str(); } - TSmartPath pathTask = PathFromString(strNameHint); + TSmartPath pathTask = PathFromString(strName); if(!pathTask.HasFileRoot()) { if(!strName.EndsWithNoCase(_T(".sqlite"))) strName += _T(".sqlite"); - TSmartPath pathTask(m_pathSerializeDir); + pathTask = m_pathSerializeDir; pathTask += PathFromString(strName); } Index: src/libchcore/TSQLiteTaskSchema.cpp =================================================================== diff -u -N -rd32a79f0e9220bad2c6eeb5e8a986228b6e832fb -rb7655a8f0721e5454befd29e3e067748eb0521e9 --- src/libchcore/TSQLiteTaskSchema.cpp (.../TSQLiteTaskSchema.cpp) (revision d32a79f0e9220bad2c6eeb5e8a986228b6e832fb) +++ src/libchcore/TSQLiteTaskSchema.cpp (.../TSQLiteTaskSchema.cpp) (revision b7655a8f0721e5454befd29e3e067748eb0521e9) @@ -20,6 +20,7 @@ #include "TSQLiteTaskSchema.h" #include "TSQLiteTransaction.h" #include "TSerializerVersion.h" +#include "TSQLiteStatement.h" BEGIN_CHCORE_NAMESPACE @@ -41,11 +42,9 @@ // if version is 0, then this is the fresh database with (almost) no tables inside if(tVersion.GetVersion() == 0) { -/* - TSQLiteStatement tStatement(spDatabase); - tStatement.Prepare(_T("CREATE TABLE tasks(task_id BIGINT UNIQUE, task_order INT, path VARCHAR(32768))")); + sqlite::TSQLiteStatement tStatement(spDatabase); + tStatement.Prepare(_T("CREATE TABLE task(id BIGINT UNIQUE, name varchar(256) NOT NULL, log_path VARCHAR(32768), current_state INT NOT NULL, destination_path varchar(32768) NOT NULL)")); tStatement.Step(); -*/ // and finally set the database version to current one tVersion.SetVersion(1); Index: src/libchcore/TString.cpp =================================================================== diff -u -N -r30297d6aab17483da8e7b8323b4d17ff1a9f78d6 -rb7655a8f0721e5454befd29e3e067748eb0521e9 --- src/libchcore/TString.cpp (.../TString.cpp) (revision 30297d6aab17483da8e7b8323b4d17ff1a9f78d6) +++ src/libchcore/TString.cpp (.../TString.cpp) (revision b7655a8f0721e5454befd29e3e067748eb0521e9) @@ -475,7 +475,7 @@ EnsureWritable(stLen); - const wchar_t* pszElementsEnd = pszElements + stLen; + const wchar_t* pszElementsEnd = pszElements + wcslen(pszElements); while(stLen -- > 0) { if(std::find(pszElements, pszElementsEnd, m_pszStringData[stLen]) != pszElementsEnd) Index: src/libchcore/TTask.cpp =================================================================== diff -u -N -r9479911a096555a7504c5c8a8eaee83ecb63440c -rb7655a8f0721e5454befd29e3e067748eb0521e9 --- src/libchcore/TTask.cpp (.../TTask.cpp) (revision 9479911a096555a7504c5c8a8eaee83ecb63440c) +++ src/libchcore/TTask.cpp (.../TTask.cpp) (revision b7655a8f0721e5454befd29e3e067748eb0521e9) @@ -34,23 +34,29 @@ #include "TTaskStatsSnapshot.h" #include "TCoreException.h" #include "ErrorCodes.h" +#include "TRowData.h" +#include "ISerializerRowData.h" BEGIN_CHCORE_NAMESPACE //////////////////////////////////////////////////////////////////////////// // TTask members TTask::TTask(const ISerializerPtr& spSerializer, IFeedbackHandler* piFeedbackHandler) : + m_strTaskName(m_bBaseDataChanged), + m_eCurrentState(eTaskState_None, m_bBaseDataChanged), + m_pathLog(m_bBaseDataChanged), + m_pathDestinationPath(m_bBaseDataChanged), m_log(), m_piFeedbackHandler(piFeedbackHandler), m_arrSourcePathsInfo(m_vSourcePaths), m_files(m_vSourcePaths), m_bForce(false), m_bContinue(false), - m_eCurrentState(eTaskState_None), m_tSubTaskContext(m_tConfiguration, m_arrSourcePathsInfo, m_files, m_cfgTracker, m_log, piFeedbackHandler, m_workerThread, m_fsLocal), m_tSubTasksArray(), - m_spSerializer(spSerializer) + m_spSerializer(spSerializer), + m_bWasSerialized(false) { if(!piFeedbackHandler || !spSerializer) THROW_CORE_EXCEPTION(eErr_InvalidPointer); @@ -128,114 +134,62 @@ void TTask::Load() { -/* - using Serializers::Serialize; + using namespace chcore; - boost::unique_lock lock(m_lock); + { + boost::unique_lock lock(m_lock); - //////////////////////////////// - // First load task description - m_tTaskDefinition.Load(strPath); - m_strFilePath = strPath; + ISerializerContainerPtr spContainer = m_spSerializer->GetContainer(_T("task")); + ISerializerRowReaderPtr spRowReader = spContainer->GetRowReader(); - // 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_tConfiguration, m_afFilters); + IColumnsDefinitionPtr spColumns = spRowReader->GetColumnsDefinitions(); + if(spColumns->IsEmpty()) + *spColumns % _T("name") % _T("log_path") % _T("current_state") % _T("destination_path"); - //////////////////////////////// - // 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); - - /////////////////////////////////// - // and often changing data - TSmartPath pathOftenChangingPath = GetRelatedPathNL(ePathType_TaskOftenChangingState); - readSerializer.Init(pathOftenChangingPath); - - m_tSubTasksArray.Init(m_tTaskDefinition.GetOperationPlan(), m_tSubTaskContext); - m_tSubTasksArray.SerializeProgress(readSerializer); - - // 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; + bool bResult = spRowReader->Next(); + if(bResult) + { + spRowReader->GetValue(_T("name"), m_strTaskName); + spRowReader->GetValue(_T("log_path"), m_pathLog); + spRowReader->GetValue(_T("current_state"), *(int*)(ETaskCurrentState*)&m_eCurrentState); + spRowReader->GetValue(_T("destination_path"), m_pathDestinationPath); + } + else + THROW_CORE_EXCEPTION(eErr_SerializeLoadError); } - 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);*/ + m_bBaseDataChanged = false; + m_bWasSerialized = true; } void TTask::Store() { -/* - using Serializers::Serialize; + using namespace chcore; - 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.GetTaskName() + _T(".cht")); - } + boost::shared_lock lock(m_lock); - // store task definition only if changed - m_tTaskDefinition.Store(GetRelatedPathNL(ePathType_TaskDefinition), true); + ISerializerContainerPtr spContainer = m_spSerializer->GetContainer(_T("task")); + ISerializerRowDataPtr spRow; - // rarely changing data - if(m_bRareStateModified) - { - TWriteBinarySerializer writeSerializer; - writeSerializer.Init(GetRelatedPathNL(ePathType_TaskRarelyChangingState)); + if(!m_bWasSerialized || m_bBaseDataChanged) + { + if(m_bWasSerialized) + spRow = spContainer->GetRow(0); + else + spRow = spContainer->AddRow(0); - m_arrSourcePathsInfo.Serialize(writeSerializer, true); - - m_files.Serialize(writeSerializer, false); + *spRow + % TRowData(_T("name"), m_strTaskName) + % TRowData(_T("log_path"), m_pathLog) + % TRowData(_T("current_state"), m_eCurrentState) + % TRowData(_T("destination_path"), m_pathDestinationPath); + } } - if(m_bOftenStateModified) - { - TWriteBinarySerializer writeSerializer; - writeSerializer.Init(GetRelatedPathNL(ePathType_TaskOftenChangingState)); - - m_tSubTasksArray.SerializeProgress(writeSerializer); - - // 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); - - m_files.Serialize(writeSerializer, true); - }*/ + m_spSerializer->Flush(); + m_bBaseDataChanged = false; + m_bWasSerialized = true; } void TTask::KillThread() @@ -315,7 +269,7 @@ spSnapshot->SetTaskName(m_strTaskName); spSnapshot->SetThreadPriority(GetTaskPropValue(m_tConfiguration)); - spSnapshot->SetDestinationPath(m_pathDestinationPath.ToString()); + spSnapshot->SetDestinationPath(m_pathDestinationPath->ToString()); spSnapshot->SetFilters(m_afFilters); spSnapshot->SetTaskState(m_eCurrentState); spSnapshot->SetOperationType(m_tSubTasksArray.GetOperationType()); @@ -462,7 +416,7 @@ TSubTaskBase::ESubOperationResult eResult = TSubTaskBase::eSubResult_Continue; // initialize log file - m_log.init(m_pathLog.ToString(), 262144, icpf::log_file::level_debug, false, false); + m_log.init(m_pathLog->ToString(), 262144, icpf::log_file::level_debug, false, false); // start operation OnBeginOperation(); Index: src/libchcore/TTask.h =================================================================== diff -u -N -rd32a79f0e9220bad2c6eeb5e8a986228b6e832fb -rb7655a8f0721e5454befd29e3e067748eb0521e9 --- src/libchcore/TTask.h (.../TTask.h) (revision d32a79f0e9220bad2c6eeb5e8a986228b6e832fb) +++ src/libchcore/TTask.h (.../TTask.h) (revision b7655a8f0721e5454befd29e3e067748eb0521e9) @@ -34,6 +34,7 @@ #include "TSubTaskContext.h" #include "TTaskStatsSnapshot.h" #include "ISerializer.h" +#include "TModificationTracker.h" BEGIN_CHCORE_NAMESPACE @@ -126,16 +127,28 @@ ISerializerPtr GetSerializer() const; private: + // serialization #pragma warning(push) #pragma warning(disable: 4251) ISerializerPtr m_spSerializer; #pragma warning(pop) + bool m_bWasSerialized; - TString m_strTaskName; + // base data +#pragma region Base data + bool m_bBaseDataChanged; +#pragma warning(push) +#pragma warning(disable: 4251) + TSharedModificationTracker m_strTaskName; + TSharedModificationTracker m_eCurrentState; // current state of processing this task represents + TSharedModificationTracker m_pathLog; + TSharedModificationTracker m_pathDestinationPath; +#pragma warning(pop) +#pragma endregion + // basic information TPathContainer m_vSourcePaths; - TSmartPath m_pathDestinationPath; // Global task settings TConfig m_tConfiguration; @@ -152,17 +165,13 @@ // 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 - // task settings TFileFiltersArray 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 // other helpers - TSmartPath m_pathLog; icpf::log_file m_log; ///< Log file where task information will be stored // Local filesystem access Index: src/libchcore/libchcore.vc90.vcproj =================================================================== diff -u -N -r31c4b1fc46687ed2cf35dd9fa0acec2543ae1886 -rb7655a8f0721e5454befd29e3e067748eb0521e9 --- src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision 31c4b1fc46687ed2cf35dd9fa0acec2543ae1886) +++ src/libchcore/libchcore.vc90.vcproj (.../libchcore.vc90.vcproj) (revision b7655a8f0721e5454befd29e3e067748eb0521e9) @@ -1112,6 +1112,14 @@ > + + + +