Index: src/libchcore/TSQLiteTaskSchema.cpp =================================================================== diff -u -r19925be73ffcadd9f345f10e03e55aadb3f0eeac -rff16e23b043c1c3f3ea883372b6f81d7ad4adca3 --- src/libchcore/TSQLiteTaskSchema.cpp (.../TSQLiteTaskSchema.cpp) (revision 19925be73ffcadd9f345f10e03e55aadb3f0eeac) +++ src/libchcore/TSQLiteTaskSchema.cpp (.../TSQLiteTaskSchema.cpp) (revision ff16e23b043c1c3f3ea883372b6f81d7ad4adca3) @@ -72,6 +72,9 @@ tStatement.Prepare(_T("CREATE TABLE subtasks(id BIGINT UNIQUE, type INT NOT NULL, is_current boolean NOT NULL, is_estimation boolean NOT NULL)")); tStatement.Step(); + tStatement.Prepare(_T("CREATE TABLE subtasks_info(id BIGINT UNIQUE, operation INT NOT NULL)")); + tStatement.Step(); + tStatement.Prepare(_T("CREATE TABLE subtask_fastmove(id BIGINT UNIQUE, current_index INT NOT NULL, is_running boolean NOT NULL, total_size BIGINT NOT NULL, processed_size BIGINT NOT NULL, size_speed varchar(1024) NOT NULL, ") _T("total_count BIGINT NOT NULL, processed_count BIGINT NOT NULL, count_speed varchar(1024) NOT NULL, ci_processed_size BIGINT NOT NULL, ci_total_size BIGINT NOT NULL, timer BIGINT NOT NULL, ") _T("buffer_index INT NOT NULL, current_path varchar(32768) NOT NULL, suboperation_type INT NOT NULL)")); Index: src/libchcore/TSubTaskArray.cpp =================================================================== diff -u -r19925be73ffcadd9f345f10e03e55aadb3f0eeac -rff16e23b043c1c3f3ea883372b6f81d7ad4adca3 --- src/libchcore/TSubTaskArray.cpp (.../TSubTaskArray.cpp) (revision 19925be73ffcadd9f345f10e03e55aadb3f0eeac) +++ src/libchcore/TSubTaskArray.cpp (.../TSubTaskArray.cpp) (revision ff16e23b043c1c3f3ea883372b6f81d7ad4adca3) @@ -42,18 +42,20 @@ TSubTasksArray::TSubTasksArray(TSubTaskContext& rSubTaskContext) : m_rSubTaskContext(rSubTaskContext), - m_eOperationType(eOperation_None), + m_eOperationType(m_setModifications, eOperation_None), m_lSubOperationIndex(0), m_lLastStoredIndex(-1) { + m_setModifications[eMod_Added] = true; } TSubTasksArray::TSubTasksArray(const TOperationPlan& rOperationPlan, TSubTaskContext& rSubTaskContext) : m_rSubTaskContext(rSubTaskContext), - m_eOperationType(eOperation_None), + m_eOperationType(m_setModifications, eOperation_None), m_lSubOperationIndex(0), m_lLastStoredIndex(-1) { + m_setModifications[eMod_Added] = true; Init(rOperationPlan); } @@ -172,50 +174,74 @@ void TSubTasksArray::Store(const ISerializerPtr& spSerializer) const { - ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("subtasks")); - ISerializerRowDataPtr spRow; + bool bAdded = m_setModifications[eMod_Added]; - // base data - long lCurrentIndex = m_lSubOperationIndex.load(boost::memory_order_acquire); - bool bAdded = (m_lLastStoredIndex == -1); - - // subtasks are stored only once when added as they don't change (at least in context of their order and type) - if(bAdded) + /////////////////////////////////////////////////////////////////////// { - for(size_t stSubOperationIndex = 0; stSubOperationIndex < m_vSubTasks.size(); ++stSubOperationIndex) - { - if(bAdded) - spRow = spContainer->AddRow(stSubOperationIndex); + ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("subtasks_info")); + ISerializerRowDataPtr spRow; - const std::pair& rCurrentSubTask = m_vSubTasks[stSubOperationIndex]; + if(bAdded) + spRow = spContainer->AddRow(0); + else + spRow = spContainer->GetRow(0); - *spRow - % TRowData(_T("type"), rCurrentSubTask.first->GetSubOperationType()) - % TRowData(_T("is_current"), false) - % TRowData(_T("is_estimation"), rCurrentSubTask.second); - } + *spRow + % TRowData(_T("operation"), m_eOperationType.Get()); } - // serialize current index - if(bAdded || lCurrentIndex != m_lLastStoredIndex) + /////////////////////////////////////////////////////////////////////// { - // mark subtask at current index as "current"; don't do that if we just finished. - if(lCurrentIndex != m_vSubTasks.size()) + ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("subtasks")); + ISerializerRowDataPtr spRow; + + // base data + long lCurrentIndex = m_lSubOperationIndex.load(boost::memory_order_acquire); + + // subtasks are stored only once when added as they don't change (at least in context of their order and type) + if(bAdded) { - spRow = spContainer->GetRow(lCurrentIndex); - *spRow % TRowData(_T("is_current"), true); + if(m_lLastStoredIndex != -1) + THROW_CORE_EXCEPTION(eErr_InternalProblem); + + for(size_t stSubOperationIndex = 0; stSubOperationIndex < m_vSubTasks.size(); ++stSubOperationIndex) + { + if(bAdded) + spRow = spContainer->AddRow(stSubOperationIndex); + + const std::pair& rCurrentSubTask = m_vSubTasks[stSubOperationIndex]; + + *spRow + % TRowData(_T("type"), rCurrentSubTask.first->GetSubOperationType()) + % TRowData(_T("is_current"), false) + % TRowData(_T("is_estimation"), rCurrentSubTask.second); + } } - // unmark the old "current" subtask - if(m_lLastStoredIndex != -1) + // serialize current index + if(bAdded || lCurrentIndex != m_lLastStoredIndex) { - spRow = spContainer->GetRow(m_lLastStoredIndex); - *spRow % TRowData(_T("is_current"), false); + // mark subtask at current index as "current"; don't do that if we just finished. + if(lCurrentIndex != m_vSubTasks.size()) + { + spRow = spContainer->GetRow(lCurrentIndex); + *spRow % TRowData(_T("is_current"), true); + } + + // unmark the old "current" subtask + if(m_lLastStoredIndex != -1) + { + spRow = spContainer->GetRow(m_lLastStoredIndex); + *spRow % TRowData(_T("is_current"), false); + } } + + m_lLastStoredIndex = lCurrentIndex; } - m_lLastStoredIndex = lCurrentIndex; + m_setModifications.reset(); + /////////////////////////////////////////////////////////////////////// // store all the subtasks for(size_t stSubOperationIndex = 0; stSubOperationIndex < m_vSubTasks.size(); ++stSubOperationIndex) { @@ -226,48 +252,66 @@ void TSubTasksArray::Load(const ISerializerPtr& spSerializer) { - m_lLastStoredIndex = -1; + /////////////////////////////////////////////////////////////////////// + { + ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("subtasks_info")); + ISerializerRowReaderPtr spRowReader = spContainer->GetRowReader(); - ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("subtasks")); - ISerializerRowReaderPtr spRowReader = spContainer->GetRowReader(); + IColumnsDefinitionPtr spColumns = spRowReader->GetColumnsDefinitions(); + if(spColumns->IsEmpty()) + *spColumns % _T("id") % _T("operation"); - IColumnsDefinitionPtr spColumns = spRowReader->GetColumnsDefinitions(); - if(spColumns->IsEmpty()) - *spColumns % _T("id") % _T("type") % _T("is_current") % _T("is_estimation"); + if(spRowReader->Next()) + spRowReader->GetValue(_T("operation"), *(int*)&m_eOperationType.Modify()); + } - while(spRowReader->Next()) + /////////////////////////////////////////////////////////////////////// { - long lID = 0; - int iType = 0; - bool bIsCurrent = false; - bool bIsEstimation = false; + m_lLastStoredIndex = -1; - spRowReader->GetValue(_T("id"), lID); - spRowReader->GetValue(_T("type"), iType); - spRowReader->GetValue(_T("is_current"), bIsCurrent); - spRowReader->GetValue(_T("is_estimation"), bIsEstimation); + ISerializerContainerPtr spContainer = spSerializer->GetContainer(_T("subtasks")); + ISerializerRowReaderPtr spRowReader = spContainer->GetRowReader(); - if(bIsCurrent) + IColumnsDefinitionPtr spColumns = spRowReader->GetColumnsDefinitions(); + if(spColumns->IsEmpty()) + *spColumns % _T("id") % _T("type") % _T("is_current") % _T("is_estimation"); + + while(spRowReader->Next()) { - m_lSubOperationIndex.store(lID, boost::memory_order_release); - m_lLastStoredIndex = lID; - } + long lID = 0; + int iType = 0; + bool bIsCurrent = false; + bool bIsEstimation = false; - // create subtask, load it and put into the array - TSubTaskBasePtr spSubTask = CreateSubtask((ESubOperationType)iType, m_rSubTaskContext); - spSubTask->Load(spSerializer); + spRowReader->GetValue(_T("id"), lID); + spRowReader->GetValue(_T("type"), iType); + spRowReader->GetValue(_T("is_current"), bIsCurrent); + spRowReader->GetValue(_T("is_estimation"), bIsEstimation); - if(lID != m_vSubTasks.size()) - THROW_CORE_EXCEPTION(eErr_InvalidData); + if(bIsCurrent) + { + m_lSubOperationIndex.store(lID, boost::memory_order_release); + m_lLastStoredIndex = lID; + } - m_vSubTasks.push_back(std::make_pair(spSubTask, bIsEstimation)); - } + // create subtask, load it and put into the array + TSubTaskBasePtr spSubTask = CreateSubtask((ESubOperationType)iType, m_rSubTaskContext); + spSubTask->Load(spSerializer); - if(m_lLastStoredIndex == -1) - { - m_lSubOperationIndex.store(boost::numeric_cast(m_vSubTasks.size()), boost::memory_order_release); - m_lLastStoredIndex = boost::numeric_cast(m_vSubTasks.size()); + if(lID != m_vSubTasks.size()) + THROW_CORE_EXCEPTION(eErr_InvalidData); + + m_vSubTasks.push_back(std::make_pair(spSubTask, bIsEstimation)); + } + + if(m_lLastStoredIndex == -1) + { + m_lSubOperationIndex.store(boost::numeric_cast(m_vSubTasks.size()), boost::memory_order_release); + m_lLastStoredIndex = boost::numeric_cast(m_vSubTasks.size()); + } } + + m_setModifications.reset(); } TSubTaskBasePtr TSubTasksArray::CreateSubtask(ESubOperationType eType, TSubTaskContext& rContext) Index: src/libchcore/TSubTaskArray.h =================================================================== diff -u -r19925be73ffcadd9f345f10e03e55aadb3f0eeac -rff16e23b043c1c3f3ea883372b6f81d7ad4adca3 --- src/libchcore/TSubTaskArray.h (.../TSubTaskArray.h) (revision 19925be73ffcadd9f345f10e03e55aadb3f0eeac) +++ src/libchcore/TSubTaskArray.h (.../TSubTaskArray.h) (revision ff16e23b043c1c3f3ea883372b6f81d7ad4adca3) @@ -29,6 +29,8 @@ #include "TTaskLocalStats.h" #include "TSubTaskArrayStatsSnapshot.h" #include +#include "TSharedModificationTracker.h" +#include BEGIN_CHCORE_NAMESPACE @@ -65,17 +67,32 @@ static TSubTaskBasePtr CreateSubtask(ESubOperationType eType, TSubTaskContext& rContext); private: + enum EModifications + { + eMod_Added, + eMod_OperationType, + + // last element + eMod_Last + }; + + typedef std::bitset Bitset; + TSubTaskContext& m_rSubTaskContext; - EOperationType m_eOperationType; #pragma warning(push) #pragma warning(disable: 4251) + mutable Bitset m_setModifications; + + TSharedModificationTracker m_eOperationType; + std::vector > m_vSubTasks; // pointer to the subtask object / is this the part of estimation? mutable boost::atomic m_lSubOperationIndex; // index of sub-operation from TOperationDescription - mutable long m_lLastStoredIndex; #pragma warning(pop) + mutable long m_lLastStoredIndex; + friend class TTaskProcessingGuard; };