diff --git a/Plugins/org.mitk.core.jobs/src/internal/mitkDataStorageAccessRule.cpp b/Plugins/org.mitk.core.jobs/src/internal/mitkDataStorageAccessRule.cpp index 15cc85a95c..d7160aa205 100644 --- a/Plugins/org.mitk.core.jobs/src/internal/mitkDataStorageAccessRule.cpp +++ b/Plugins/org.mitk.core.jobs/src/internal/mitkDataStorageAccessRule.cpp @@ -1,197 +1,197 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 18503 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkDataStorageAccessRule.h" #include mitk::DataStorageAccessRule ::DataStorageAccessRule (mitk::DataStorage::Pointer myDataStorage, mitk::DataNode::Pointer myDataNode, mitk::DataStorageAccessRule::RuleType myRule) :m_Rule(myRule), m_sptrMyDataStorage(myDataStorage), m_sptrMyDataNode(myDataNode) { mitk::DataStorage::SetOfObjects::ConstPointer sptr_parentsNodesFirstRule = m_sptrMyDataStorage->GetSources(m_sptrMyDataNode); // checks if the DataNode does exists within the specified DataTree, if not an // Poco NotFoundException is thrown since the rule is useless bool exsists = false ; for(mitk::DataStorage::SetOfObjects::const_iterator it = sptr_parentsNodesFirstRule->begin(); it != sptr_parentsNodesFirstRule->end(); ++ it) { if (*it == m_sptrMyDataNode ) exsists = true ; } if (exsists == false) throw Poco::NotFoundException() ; } bool mitk::DataStorageAccessRule - ::Contains(berry::ISchedulingRule::Pointer rule) + ::Contains(berry::ISchedulingRule::Pointer rule) const { DataStorageAccessRule::Pointer sptr_temp = rule.Cast(); // test if the ISchedulingRule is a DataStorageAccessRule if( sptr_temp == 0 ) return false ; // test if the DataStorageAccessRule object is exactly the instance else { if ( this == sptr_temp.GetPointer() ) return true ; return false ; } } bool mitk::DataStorageAccessRule - ::IsConflicting(berry::ISchedulingRule::Pointer sptr_otherISchedulingRule) + ::IsConflicting(berry::ISchedulingRule::Pointer sptr_otherISchedulingRule) const { // test if the stored dataNode // cast to check if the ISchedulingRule is a DataStorageAccessRule DataStorageAccessRule::Pointer sptr_DataStorageAccessRule = sptr_otherISchedulingRule.Cast(); // checks if the Rule of the type ISchedulingRule is a DataStorageAccessRule if(sptr_DataStorageAccessRule == 0) return false ; // the rule to be compared with is a DataStorageAccessRule else { // testing if both jobs holding each rule do operate on the same DataStorage if not false is returned if( !CompareDataStorages(sptr_DataStorageAccessRule->GetDataStorage()) ) return false ; // checks if to rules to be compared are two add rules if (m_Rule == ADD_RULE && m_Rule == sptr_DataStorageAccessRule->GetRuleType()) return CompareTwoAddorRemoveRules() ; // checks if to the two rules to be compared are two remove rules if(m_Rule == REMOVE_RULE && m_Rule == sptr_DataStorageAccessRule->GetRuleType()) return CompareTwoAddorRemoveRules() ; // an add and remove rule needs to be compared else { return CompareAddandRemoveRules(sptr_DataStorageAccessRule) ; } } } bool mitk::DataStorageAccessRule ::CompareAddandRemoveRules(mitk::DataStorageAccessRule::Pointer sptr_otherDataStorageAccessRule) const { mitk::DataStorage::SetOfObjects::ConstPointer sptr_parentsNodesFirstRule = m_sptrMyDataStorage->GetSources(m_sptrMyDataNode); // checks if the DataStorageNode of to be compared DataStorageAccessRule is a parent node // if so the job holding this DataStorageAccessRule need to wait until the operation on the parent node is performed for(mitk::DataStorage::SetOfObjects::const_iterator it = sptr_parentsNodesFirstRule->begin(); it != sptr_parentsNodesFirstRule->end(); ++ it) { if (*it == sptr_otherDataStorageAccessRule->GetDataNode()) return true ; } mitk::DataStorage::SetOfObjects::ConstPointer sptr_derivedNodesRule = m_sptrMyDataStorage->GetDerivations(m_sptrMyDataNode); // checks if the DataStorage node of to be compared DataStorageAccessRule is a child node // if so the job holding this DataStorageAccessRule needs to wait until the operation on the parent node is performed for(mitk::DataStorage::SetOfObjects::const_iterator it = sptr_derivedNodesRule->begin(); it != sptr_derivedNodesRule->end(); ++it) { if(*it == sptr_otherDataStorageAccessRule->GetDataNode()) return true ; } // jobs operating on nodes on different branches do not cause conflicts thus they can be performed in different // threads concurrently return false ; } bool mitk::DataStorageAccessRule ::CompareDataStorages(mitk::DataStorage::Pointer otherDataStorage) const { if(m_sptrMyDataStorage == otherDataStorage) return true ; else return false; } bool mitk::DataStorageAccessRule ::CompareTwoAddorRemoveRules() const { return false ; } bool mitk::DataStorageAccessRule ::TestDataNode(mitk::DataNode::Pointer /*dataTreeToBeStored*/) const { mitk::DataStorage::SetOfObjects::ConstPointer tempAllNodes = m_sptrMyDataStorage->GetAll(); for(mitk::DataStorage::SetOfObjects::const_iterator it = tempAllNodes->begin(); it !=tempAllNodes->end(); ++ it){ if (m_sptrMyDataNode == *it ) return true ; } return false ; } mitk::DataNode::Pointer mitk::DataStorageAccessRule ::GetDataNode() const { return mitk::DataStorageAccessRule::m_sptrMyDataNode ; } mitk::DataStorage::Pointer mitk::DataStorageAccessRule ::GetDataStorage() const { return mitk::DataStorageAccessRule::m_sptrMyDataStorage ; } mitk::DataStorageAccessRule::RuleType mitk::DataStorageAccessRule ::GetRuleType() const { if (m_Rule == ADD_RULE) return ( mitk::DataStorageAccessRule::ADD_RULE ) ; else { return ( mitk::DataStorageAccessRule::REMOVE_RULE ) ; } } diff --git a/Plugins/org.mitk.core.jobs/src/mitkDataStorageAccessRule.h b/Plugins/org.mitk.core.jobs/src/mitkDataStorageAccessRule.h index 124bf2ee61..a77a81d62f 100644 --- a/Plugins/org.mitk.core.jobs/src/mitkDataStorageAccessRule.h +++ b/Plugins/org.mitk.core.jobs/src/mitkDataStorageAccessRule.h @@ -1,159 +1,159 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef MITKDATASTORAGEACCESSRULE_H_HEADER_INCLUDED_ #define MITKDATASTORAGEACCESSRULE_H_HEADER_INCLUDED_ #include #include "berryISchedulingRule.h" #include "berryObject.h" #include "mitkDataNode.h" #include "mitkDataStorage.h" #include "mitkStandaloneDataStorage.h" namespace mitk { /** *@class DataStorageAccessRule * *@brief The DataStorageAccessRule inherits from the ISchedulingRule class. DataStorageAccessRule are used to restrict the adding and * removing of DataStorage nodes in multi-threaded scenarios. Only DataStorageNodes within different branches can be modified * concurrently. The idea and its restrictions is explained in the sections and diagrams below. * *

the IsScheduling(...) method :

* returns true or false depending if conflictions with another rule are found * *

* *

*

the rule behavior if jobs holing add rules of an DataTree node

* * two add rules are always allowed since there are no conflictions when adding nodes concurrently. The final order the nodes are finally added has * to be checked by the programmer of the particular job * * *

the rule behavior when two jobs holding remove rules of a DataNode

* * two jobs holding remove rules can be executed concurrently since all removing scenarios do not cause conflictions. If two jobs are * trying to remove the same DataTree node the job by itself needs to check if the node is still available before executing the removing * command * * *

the rule behavior of a jobs that is holding an add rule compared with a job that is holding a remove rule on a * DataNode

* * adding and removing of DataTree nodes concurrently can cause serious errors and needs to be restricted. Performing add and remove * operations on different DataStorage branches can be done concurrently since no conflictions are expected. * the performing of add and remove operation on the same DataNode, its parent nodes or child nodes of the same branch * by different jobs is not allowed. Jobs holding rules that are trying to perform such operations are blocked until the running job is done. * *

* *

*

the Contains method (...) method :

* only necessary for a specific type of scheduling rules. Has to be used if IScheduling rules are composed into hierarchies. * In such scenarios the contains(...) method specifies the hierarchical relationships among the locks. For example if a method tries to acquire a specific * rule to lock a specific directory it needs to check if no job is holding a rule for one or more subdirectories. For all cases in which no composing of * IScheduling rules is needed the Contains(...) method only needs to check if two jobs are holding exactly the same IScheduling rule on the same object. * Normally this can be achieved by just calling the IsConflicting(...) method. *

* *@author Jan Woerner */ class MITK_JOBS_EXPORT DataStorageAccessRule : public berry::ISchedulingRule { public: enum RuleType {ADD_RULE = 0, REMOVE_RULE} ; RuleType m_Rule; berryObjectMacro(DataStorageAccessRule) DataStorageAccessRule (mitk::DataStorage::Pointer myDataStorage, mitk::DataNode::Pointer myDataNode, DataStorageAccessRule::RuleType myRule) ; - bool Contains (berry::ISchedulingRule::Pointer otherISchedulingRule) ; - bool IsConflicting (berry::ISchedulingRule::Pointer otherISchedulingRule) ; + bool Contains (berry::ISchedulingRule::Pointer otherISchedulingRule) const; + bool IsConflicting (berry::ISchedulingRule::Pointer otherISchedulingRule) const; private: /** * Returns false, identifying no conflictions between two DataStorageAccessRules. * Two add and remove rules do work together. From importance is that jobs using this rule need to check if the * node operating on is still available or already deleted by another job. The DataStorageAccessRule only checks if conflictions could * occur if the removing or adding of nodes is performed currently. */ bool CompareTwoAddorRemoveRules() const ; /** * searches for conflictions of an add DataStorageAccessRule with a remove DataStorageAccess rule * if the add and remove rule do operate in different branches, no conflictions are expected and false is returned */ bool CompareAddandRemoveRules(mitk::DataStorageAccessRule::Pointer sptr_otherDataStorageAccessRule) const; /** * for internal use only, * checks if the jobs that are to be compared do hold DataStorageAccessRule on the same * DataStorage. Jobs that do operate on different DataStorage do not conflict and false is returned */ bool CompareDataStorages(mitk::DataStorage::Pointer otherDataStorage) const; /** * for internal use only * validates if the DataTree node of a particular DataStorageAccess rule belongs to the DataStorage specified within the particular rule. * if not the rule is invalid and false is returned. No conflictions can be expected */ bool TestDataNode(mitk::DataNode::Pointer dataTreeToBeStored) const; /** * returns a pointer to the specified DataStorage node */ mitk::DataNode::Pointer GetDataNode() const; /** * returns a pointer to the specified DataStorage */ mitk::DataStorage::Pointer GetDataStorage() const; mitk::DataStorageAccessRule::RuleType GetRuleType() const; DataStorage::Pointer m_sptrMyDataStorage ; DataNode::Pointer m_sptrMyDataNode ; }; } #endif /*MITKDATASTORAGEACCESSRULE_H_HEADER_INCLUDED_ */