ok,
Ack from me.

Thanks,
Neel.

On 2016/08/29 06:09 PM, Rafael Odzakow wrote:
> For nodesForSingleStep only PLs are allowed for now. There is a plan 
> to include SCs but that is for the future.
>
> Also having procedures with SCs in the campaign is not possible until 
> SI swap is implemented.
>
>
> On 08/29/2016 02:30 PM, Neelakanta Reddy wrote:
>> Hi Rafel,
>>
>> Reviewed and tested the patch.
>>  minor comments inline.
>>
>> Questions:
>>
>> 1. For the new attribute "nodesForSingleStep" only PLs are allowed?
>> 2. I tested giving  controllers
>>  immcfg -a numberOfSingleSteps=2  -a nodesForSingleStep=SC-1 -a 
>> nodesForSingleStep=SC-2  openSafSmfExecControl=MergeCampToSS2
>>
>> The steps created are   "SmfBalancedProcedure" are created  for PL 
>> and normal "safSmfProc=proc2 " created for SCs
>>
>> Thanks,
>> Neel.
>>
>> On 2016/08/27 01:59 PM, Rafael Odzakow wrote:
>>> osaf/services/saf/smfsv/config/smfsv_classes.xml |   13 +
>>>   osaf/services/saf/smfsv/smfd/Makefile.am            |    6 +-
>>>   osaf/services/saf/smfsv/smfd/SmfCampState.cc        |  126 +----
>>>   osaf/services/saf/smfsv/smfd/SmfCampaign.cc         |   78 ++-
>>>   osaf/services/saf/smfsv/smfd/SmfCampaign.hh         |    1 +
>>>   osaf/services/saf/smfsv/smfd/SmfExecControl.cc      |  423 
>>> ++++++++++++++++++++
>>>   osaf/services/saf/smfsv/smfd/SmfExecControl.h       |   64 +++
>>>   osaf/services/saf/smfsv/smfd/SmfProcState.cc        |    7 +-
>>>   osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc  |   32 +-
>>>   osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh  |   24 +-
>>>   osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc |   14 +-
>>>   osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh |   20 +-
>>>   osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh      |   13 +-
>>>   osaf/services/saf/smfsv/smfd/smfd.h                 |    2 +-
>>>   14 files changed, 638 insertions(+), 185 deletions(-)
>>>
>>>
>>> diff --git a/osaf/services/saf/smfsv/config/smfsv_classes.xml 
>>> b/osaf/services/saf/smfsv/config/smfsv_classes.xml
>>> --- a/osaf/services/saf/smfsv/config/smfsv_classes.xml
>>> +++ b/osaf/services/saf/smfsv/config/smfsv_classes.xml
>>> @@ -531,5 +531,18 @@
>>>               <flag>SA_WRITABLE</flag>
>>>               <default-value>0</default-value>
>>>           </attr>
>>> +        <attr>
>>> +            <name>numberOfSingleSteps</name>
>>> +            <type>SA_UINT32_T</type>
>>> +            <category>SA_CONFIG</category>
>>> +            <flag>SA_WRITABLE</flag>
>>> +        </attr>
>>> +        <attr>
>>> +            <name>nodesForSingleStep</name>
>>> +            <type>SA_STRING_T</type>
>>> +            <category>SA_CONFIG</category>
>>> +      <flag>SA_WRITABLE</flag>
>>> +            <flag>SA_MULTI_VALUE</flag>
>>> +        </attr>
>>>       </class>
>>>   </imm:IMM-contents>
>>> diff --git a/osaf/services/saf/smfsv/smfd/Makefile.am 
>>> b/osaf/services/saf/smfsv/smfd/Makefile.am
>>> --- a/osaf/services/saf/smfsv/smfd/Makefile.am
>>> +++ b/osaf/services/saf/smfsv/smfd/Makefile.am
>>> @@ -49,7 +49,8 @@ noinst_HEADERS = \
>>>       SmfCampaignWrapup.hh \
>>>       SmfCampaignInit.hh \
>>>       SmfCallback.hh \
>>> -    SmfCbkUtil.hh
>>> +    SmfCbkUtil.hh \
>>> +    SmfExecControl.h
>>>     osafsmfd_CXXFLAGS = $(AM_CXXFLAGS) @XML2_CFLAGS@
>>>   @@ -87,7 +88,8 @@ osafsmfd_SOURCES = \
>>>       SmfCampaignInit.cc \
>>>       SmfCampaignWrapup.cc \
>>>       SmfCallback.cc \
>>> -    SmfCbkUtil.cc
>>> +    SmfCbkUtil.cc \
>>> +    SmfExecControl.cc
>>>     osafsmfd_LDFLAGS = \
>>>       $(AM_LDFLAGS) \
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfCampState.cc 
>>> b/osaf/services/saf/smfsv/smfd/SmfCampState.cc
>>> --- a/osaf/services/saf/smfsv/smfd/SmfCampState.cc
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfCampState.cc
>>> @@ -32,8 +32,10 @@
>>>   #include "SmfCampaignThread.hh"
>>>   #include "SmfCampaign.hh"
>>>   #include "SmfProcedureThread.hh"
>>> +#include "smfsv_defs.h"
>>>   #include <immutil.h>
>>>   #include <sstream>
>>> +#include "SmfUpgradeAction.hh"
>>>   /* 
>>> ======================================================================== 
>>>
>>>    *   DEFINITIONS
>>>    * 
>>> ======================================================================== 
>>>
>>> @@ -764,12 +766,7 @@ SmfCampStateExecuting::execute(SmfUpgrad
>>>       //must be restarted. The execution shall continue at step 
>>> execution phase. The procedure initialization
>>>       //and step calculation was performed before the move of control.
>>>   -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>             std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>       bool execProcFound = false;
>>> @@ -817,13 +814,7 @@ SmfCampStateExecuting::executeProc(SmfUp
>>>       //The procedure vector is sorted in execution level order (low 
>>> -> high)
>>>       //Lowest number shall be executed first.
>>>   -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> -
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>       std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>       int execLevel = -1;
>>>   @@ -912,12 +903,7 @@ SmfCampStateExecuting::suspend(SmfUpgrad
>>>       TRACE("SmfCampStateExecuting::suspend implementation");
>>>         /* Send suspend message to all procedures */
>>> -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>   @@ -966,12 +952,7 @@ SmfCampStateExecuting::procResult(SmfUpg
>>>                   LOG_NO("CAMP: Procedure %s returned STEPUNDONE", 
>>> i_procedure->getProcName().c_str());
>>>                     /* Send suspend message to all procedures */
>>> -                std::vector < SmfUpgradeProcedure * > procedures;
>>> -                if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -                } else {
>>> -                        procedures = i_camp->getProcedures();
>>> -                }
>>> +                std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>                 std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>               for (iter = procedures.begin(); iter != 
>>> procedures.end(); ++iter) {
>>> @@ -1114,21 +1095,8 @@ SmfCampStateExecCompleted::commit(SmfUpg
>>>           i_camp->resetMaintenanceState(); // No action if it fails
>>>             //Remove the procedure runtime objects
>>> -       if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> -                i_camp->getMergedProc()->commit();
>>> -
>>> -        } else {
>>> -               std::vector < SmfUpgradeProcedure * > procedures;
>>> -               if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -               } else {
>>> -                       procedures = i_camp->getProcedures();
>>> -               }
>>> -
>>> -                std::vector < SmfUpgradeProcedure * >::iterator iter;
>>> -                for (iter = procedures.begin(); iter != 
>>> procedures.end(); ++iter) {
>>> -                        (*iter)->commit();
>>> -                }
>>> +        for (auto proc: i_camp->getProcedures()) {
>>> +            proc->commit();
>>>           }
>>>             i_camp->removeRunTimeObjects(); // No action if it fails
>>> @@ -1213,12 +1181,7 @@ SmfCampStateSuspendingExec::execute(SmfU
>>>       //in while in SuspendingExec state
>>> i_camp->setProcExecutionMode(smfd_cb->procExecutionMode);
>>>   -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>       bool initialFound = false;
>>> @@ -1358,12 +1321,7 @@ SmfCampStateExecSuspended::execute(SmfUp
>>> i_camp->setProcExecutionMode(smfd_cb->procExecutionMode);
>>>         /* Send execute to all suspended procedures */
>>> -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>   @@ -1423,12 +1381,7 @@ SmfCampStateExecSuspended::rollback(SmfU
>>>       }
>>>         /* Send rollback to all suspended procedures */
>>> -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>   @@ -1728,12 +1681,7 @@ SmfCampStateSuspendedByErrorDetected::ex
>>> i_camp->setProcExecutionMode(smfd_cb->procExecutionMode);
>>>         /* Send execute to all suspended/undone procedures */
>>> -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>   @@ -1789,12 +1737,7 @@ SmfCampStateSuspendedByErrorDetected::ro
>>>       }
>>>         /* Send rollback to all suspended/undone procedures */
>>> -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>   @@ -1873,12 +1816,7 @@ SmfCampRollingBack::rollback(SmfUpgradeC
>>>       TRACE_ENTER();
>>>       TRACE("SmfCampRollingBack::rollback implementation");
>>>   -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::reverse_iterator iter;
>>>   @@ -1960,12 +1898,7 @@ SmfCampRollingBack::rollbackProc(SmfUpgr
>>>       //The procedure vector is sorted in execution level order (low 
>>> -> high)
>>>       //Highest number shall be rolled back first so start from end 
>>> of list.
>>>   -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> - procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -                procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::reverse_iterator iter;
>>>   @@ -2017,7 +1950,8 @@ SmfCampRollingBack::rollbackSingleMergeP
>>>   {
>>>       TRACE_ENTER();
>>>       LOG_NO("CAMP:: Rollback merged single step procedure only");
>>> -        SmfUpgradeProcedure * mergedProc = i_camp->getMergedProc();
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>> +        SmfUpgradeProcedure * mergedProc = procedures.at(0);
>>>           if (mergedProc->getState() == SA_SMF_PROC_COMPLETED) {
>>>                   SmfProcedureThread *procThread = 
>>> mergedProc->getProcThread();
>>>                   PROCEDURE_EVT *evt = new PROCEDURE_EVT();
>>> @@ -2046,12 +1980,7 @@ SmfCampRollingBack::suspend(SmfUpgradeCa
>>>       TRACE("SmfCampRollingBack::suspend implementation");
>>>         /* Send suspend message to all procedures */
>>> -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> -          procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -          procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>   @@ -2172,12 +2101,7 @@ SmfCampRollbackSuspended::rollback(SmfUp
>>>       TRACE("SmfCampRollbackSuspended::rollback implementation");
>>>         /* Send rollback to all suspended procedures */
>>> -        std::vector < SmfUpgradeProcedure * > procedures;
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> -          procedures.push_back(i_camp->getMergedProc());
>>> -        } else {
>>> -          procedures = i_camp->getProcedures();
>>> -        }
>>> +        std::vector<SmfUpgradeProcedure*> procedures = 
>>> i_camp->getProcedures();
>>>         std::vector < SmfUpgradeProcedure * >::iterator iter;
>>>   @@ -2345,16 +2269,8 @@ SmfCampRollbackCompleted::commit(SmfUpgr
>>>           i_camp->resetMaintenanceState(); // No action if it fails
>>>             //Remove the procedure runtime objects
>>> -        if (i_camp->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> -                i_camp->getMergedProc()->commit();
>>> -
>>> -        } else {
>>> -                const std::vector < SmfUpgradeProcedure * >& 
>>> procedures = i_camp->getProcedures();
>>> -                std::vector < SmfUpgradeProcedure * 
>>> >::const_iterator iter;
>>> -
>>> -                for (iter = procedures.begin(); iter != 
>>> procedures.end(); ++iter) {
>>> -                        (*iter)->commit();
>>> -                }
>>> +        for (auto proc: i_camp->getProcedures()) {
>>> +            proc->commit();
>>>           }
>>>                     i_camp->removeRunTimeObjects(); // No action if 
>>> it fails
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfCampaign.cc 
>>> b/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
>>> --- a/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfCampaign.cc
>>> @@ -18,6 +18,7 @@
>>>   #include <sys/stat.h>
>>>   #include <new>
>>>   #include <vector>
>>> +#include <algorithm>
>>>   #include <string>
>>>   #include <sys/time.h>
>>>   @@ -30,7 +31,9 @@
>>>   #include "SmfUpgradeProcedure.hh"
>>>   #include "SmfUpgradeMethod.hh"
>>>   #include "SmfProcedureThread.hh"
>>> +#include "SmfUpgradeAction.hh"
>>>   #include "SmfUtils.hh"
>>> +#include "SmfExecControl.h"
>>>     #include "saAis.h"
>>>   #include <saSmf.h>
>>> @@ -661,6 +664,10 @@ SmfCampaign::initExecution(void)
>>>   SaAisErrorT
>>>   SmfCampaign::startProcedureThreads()
>>>   {
>>> +        // If any procedure start goes badly two things happen: 
>>> delete of the
>>> +        // upgrade campaign pointer to terminate and remove 
>>> previously started
>>> +        // procedures. Return SA_AIS_OK to not change campaign 
>>> state and allow
>>> +        // reexecution
>>>           TRACE_ENTER();
>>>           SmfUpgradeCampaign *p_uc = getUpgradeCampaign();
>>>           if (p_uc->getProcExecutionMode() == 
>>> SMF_MERGE_TO_SINGLE_STEP) {
>>> @@ -676,25 +683,26 @@ SmfCampaign::startProcedureThreads()
>>>                   std::string singleProcDN = 
>>> singleProc->getProcName() + "," +
>>> SmfCampaignThread::instance()->campaign()->getDn();
>>>                   singleProc->setDn(singleProcDN);
>>> -                p_uc->setMergedProc(singleProc);
>>> +                p_uc->addModifiedProcedure(singleProc);
>>>   -                /* Start procedure thread */
>>> -                SmfProcedureThread *procThread = new 
>>> SmfProcedureThread(singleProc);
>>> -                /* The procThread will set itself when started 
>>> correctly */
>>> -                singleProc->setProcThread(NULL);
>>> -
>>> -                LOG_NO("SmfCampaign::startProcedureThreads, 
>>> Starting procedure thread %s",
>>> -                       singleProc->getProcName().c_str());
>>> -                procThread->start();
>>> -                /* Check if procedure thread started correctly */
>>> -                if (singleProc->getProcThread() == NULL) {
>>> -                        std::string error = "Start of procedure 
>>> thread failed for " + singleProcDN;
>>> -                        LOG_ER("%s", error.c_str());
>>> - SmfCampaignThread::instance()->campaign()->setError(error);
>>> -                        delete p_uc; // To terminate and remove any 
>>> previously started procedure threads
>>> -                        /* Don't change campaign state to allow 
>>> reexecution */
>>> +                if (startProcedure(singleProc) == false) {
>>> +                        delete p_uc;
>>>                           return SA_AIS_OK;
>>>                   }
>>> +        } else if (p_uc->getProcExecutionMode() == 
>>> SMF_BALANCED_MODE) {
>>> +                SmfExecControl execc;
>>> +                if (!execc.initBalancedMode()) {
>>> +                  return SA_AIS_ERR_INIT;
>>> +                }
>>> +                auto procedures = p_uc->getProcedures();
>>> +                TRACE("SmfCampaign::startProcedureThreads, number 
>>> of procedures=[%zu]", procedures.size());
>>> +                for (auto proc: procedures) {
>>> +                    if (startProcedure(proc) == false) {
>>> +                        delete p_uc;
>>> +                        return SA_AIS_OK;
>>> +                    }
>>> +                }
>>> +
>>>           } else {
>>>                   const std::vector < SmfUpgradeProcedure * >& 
>>> procedures = p_uc->getProcedures();
>>>                   std::vector < SmfUpgradeProcedure * 
>>> >::const_iterator iter;
>>> @@ -718,24 +726,10 @@ SmfCampaign::startProcedureThreads()
>>>                           }
>>>                           (*iter)->setDn(dn);
>>>   -                        /* Start procedure thread */
>>> -                        SmfProcedureThread *procThread = new 
>>> SmfProcedureThread(*iter);
>>> -                        /* The procThread will set itself when 
>>> started correctly */
>>> -                        (*iter)->setProcThread(NULL);
>>> -
>>> - TRACE("SmfCampaign::startProcedureThreads, Starting procedure 
>>> thread %s", (*iter)->getProcName().c_str());
>>> -                        procThread->start();
>>> -
>>> -                        /* Check if procedure thread started 
>>> correctly */
>>> -                        if ((*iter)->getProcThread() == NULL) {
>>> -                                std::string error = "Start of 
>>> procedure thread failed for " + dn;
>>> -                                LOG_ER("%s", error.c_str());
>>> - SmfCampaignThread::instance()->campaign()->setError(error);
>>> -                                delete p_uc; // To terminate and 
>>> remove any previously started procedure threads
>>> -                                /* Don't change campaign state to 
>>> allow reexecution */
>>> +                        if (startProcedure(*iter) == false) {
>>> +                                delete p_uc;
>>>                                   return SA_AIS_OK;
>>>                           }
>>> -
>>>                           iter++;
>>>                   }
>>>           }
>>> @@ -743,6 +737,26 @@ SmfCampaign::startProcedureThreads()
>>>           return SA_AIS_OK; //Will never return here, just for compiler
>>>   }
>>> +//--------------------------------------------------------------------------
>>>  
>>>
>>> +// Starts one upgrade procedure thread, return false on failure
>>> +//--------------------------------------------------------------------------
>>>  
>>>
>>> +bool
>>> +SmfCampaign::startProcedure(SmfUpgradeProcedure* procedure) {
>>> +        SmfProcedureThread *procedure_thread = new 
>>> SmfProcedureThread(procedure);
>>> +        // The procThread will set itself when started correctly
>>> +        procedure->setProcThread(nullptr);
>>> +        TRACE("SmfCampaign::startProcedure dn: %s", 
>>> procedure->getDn().c_str());
>>> +        procedure_thread->start();
>>> +
>>> +        if (procedure->getProcThread() == nullptr) {
>>> +                std::string error = "Start of procedure thread 
>>> failed for " + procedure->getDn();
>>> +                LOG_ER("%s", error.c_str());
>>> + SmfCampaignThread::instance()->campaign()->setError(error);
>>> +                return false;
>>> +        }
>>> +        return true;
>>> +}
>>> +
>>>   /**
>>>    * procResult
>>>    * Takes care of procedure result
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfCampaign.hh 
>>> b/osaf/services/saf/smfsv/smfd/SmfCampaign.hh
>>> --- a/osaf/services/saf/smfsv/smfd/SmfCampaign.hh
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfCampaign.hh
>>> @@ -107,6 +107,7 @@ class SmfCampaign {
>>>           void stopElapsedTime();
>>>      private:
>>> +        bool startProcedure(SmfUpgradeProcedure* procedure);
>>>         std::string m_dn;
>>>       std::string m_cmpg;
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfExecControl.cc 
>>> b/osaf/services/saf/smfsv/smfd/SmfExecControl.cc
>>> new file mode 100644
>>> --- /dev/null
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfExecControl.cc
>>> @@ -0,0 +1,423 @@
>>> +/*
>>> + *
>>> + * (C) Copyright 2009 The OpenSAF 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. This file and program are 
>>> licensed
>>> + * under the GNU Lesser General Public License Version 2.1, 
>>> February 1999.
>>> + * The complete license can be accessed from the following location:
>>> + * http://opensource.org/licenses/lgpl-license.php
>>> + * See the Copying file included with the OpenSAF distribution for 
>>> full
>>> + * licensing terms.
>>> + *
>>> + * Author(s): Ericsson AB
>>> + *
>>> + */
>>> +
>>> +#include "SmfExecControl.h"
>>> +#include <list>
>>> +#include <limits>
>>> +#include <algorithm>
>>> +#include "logtrace.h"
>>> +#include "immutil.h"
>>> +#include "SmfUpgradeProcedure.hh"
>>> +#include "SmfUpgradeMethod.hh"
>>> +#include "SmfUtils.hh"
>>> +#include "SmfUpgradeAction.hh"
>>> +#include "SmfUpgradeCampaign.hh"
>>> +
>>> +
>>> +bool readExecControlObject(unsigned int* numberOfSingleSteps,
>>> +                           std::vector<std::string>* 
>>> nodesForSingleStep);
>>> +
>>> +bool removeDuplicateActivationUnits(SmfUpgradeProcedure * i_newproc,
>>> +                                    SmfUpgradeStep *newStep);
>>> +
>>> +static bool isNodeInGroup(const std::string& node,
>>> +                          const std::vector<std::string>& group) {
>>> +  return std::find(group.begin(), group.end(), node) != group.end();
>>> +}
>>> +
>>> +
>>> +SmfExecControl::SmfExecControl() : m_numberofss(1) {
>>> +  m_campaign = SmfCampaignThread::instance()->campaign();
>>> +}
>>> +
>>> +bool SmfExecControl::initBalancedMode() {
>>> +  TRACE_ENTER();
>>> +  // Enable balanced mode by adding and modifying the procedures in 
>>> the
>>> +  // campaign. Calls calculateSteps before the procedures are 
>>> started in order
>>> +  // to get the activation units of the steps.
>>> +  m_originalprocs = m_campaign->getUpgradeCampaign()->getProcedures();
>>> +  for (auto proc : m_originalprocs) {
>>> +    proc->setDn(proc->getProcName() + "," + m_campaign->getDn());
>>> +    if (!proc->calculateSteps()) {
>>> +      TRACE("Step calculation failed");
>>> +      return false;
>>> +    }
>>> +  }
>>> +  if (!readExecControlObject(&m_numberofss, &m_nodesforss)) {
>>> +    return false;
>>> +  }
>>> +  if (!setNodesForSingleStep()) {
>>> +    return false;
>>> +  }
>>> +  createBalancedProcedures();
>>> +
>>> +  for (auto bproc : m_balancedprocs) {
>>> +    std::vector<SmfUpgradeStep*> steps;
>>> +    std::vector<SmfUpgradeAction*> initactions;
>>> +    std::vector<SmfUpgradeAction*> wrapupactions;
>>> +    // Each new balanced procedure needs to copy some steps from 
>>> the original
>>> +    // procedures.
>>> +    for (auto step : getStepsMatchingBalancedGroup(bproc)) {
>>> +      // copy the steps together with actions and callbacks
>>> +      auto oproc = step->getProcedure();
>>> +      steps.insert(steps.end(),
>>> +                   oproc->getProcSteps().begin(),
>>> +                   oproc->getProcSteps().end());
>>> +      initactions.insert(initactions.end(),
>>> +                         oproc->getInitActions().begin(),
>>> +                         oproc->getInitActions().end());
>>> +      wrapupactions.insert(wrapupactions.end(),
>>> + oproc->getWrapupActions().begin(),
>>> + oproc->getWrapupActions().end());
>>> + bproc->getCallbackList(oproc->getUpgradeMethod());
>>> +    }
>>> +    if (!steps.empty()) {
>>> +      SmfUpgradeStep* newstep = createMergedStep(bproc, steps);
>>> +      addInitAndWrapupActionsToProcedure(bproc, initactions, 
>>> wrapupactions);
>>> +      removeDuplicateActivationUnits(bproc, newstep);
>>> +      bproc->addProcStep(newstep);
>>> +    }
>>> +  }
>>> +
>>> +  // add all the procedures
>>> +  for (auto proc : m_originalprocs) {
>>> +    if (!proc->getIsMergedProcedure()) {
>>> +      TRACE("adding original procedure %s to upgrade campaign", 
>>> proc->getDn().c_str());
>>> + m_campaign->getUpgradeCampaign()->addModifiedProcedure(proc);
>>> +    } else {
>>> +      TRACE("skipping original procedure %s", proc->getDn().c_str());
>>> +    }
>>> +    proc->setIsMergedProcedure(false);  // Clear the flag
>>> +  }
>>> +  for (auto proc : m_balancedprocs) {
>>> +    TRACE("adding balanced procedure %s to upgrade campaign", 
>>> proc->getDn().c_str());
>>> + m_campaign->getUpgradeCampaign()->addModifiedProcedure(proc);
>>> +  }
>>> +
>>> +  TRACE_LEAVE();
>>> +  return true;
>>> +}
>>> +
>>> +std::vector<SmfUpgradeStep*> 
>>> SmfExecControl::getStepsMatchingBalancedGroup(
>>> +    SmfUpgradeProcedure* procedure) {
>>> +  TRACE_ENTER();
>>> +  // Check if the steps are in the balanced group of the procedure. 
>>> If so mark
>>> +  // as completed and return the matching steps.
>>> +  std::vector<SmfUpgradeStep*> steps;
>>> +  for (auto oproc : m_originalprocs) {
>>> +    for (auto ostep : oproc->getProcSteps()) {
>>> +      if (isNodeInGroup(ostep->getSwNode(), 
>>> procedure->getBalancedGroup())) {
>>> +        if (ostep->getState() != SA_SMF_STEP_COMPLETED) {
>>> +          // step will be started in a new merged step
>>> +          ostep->setStepState(SA_SMF_STEP_COMPLETED);
>>> +          steps.push_back(ostep);
>>> +        }
>>> +      }
>>> +    }
>>> +  }
>>> +  TRACE_LEAVE();
>>> +  return steps;
>>> +}
>>> +
>>> +bool SmfExecControl::setNodesForSingleStep() {
>>> +  // nodesForSingleStep might contain nodes outside of our scope. 
>>> Modify this
>>> +  // list to only use the nodes that are found in the campaign.
>>> +  TRACE_ENTER();
>>> +  std::vector<std::string> nodes_included;
>>> +  for (auto proc : m_originalprocs) {
>>> +    proc->setIsMergedProcedure(true);  // Mark the procedures to be 
>>> modified
>>> +    if (proc->getUpgradeMethod()->getUpgradeMethod() == 
>>> SA_SMF_ROLLING) {
>>> +      for (auto step : proc->getProcSteps()) {
>>> +        if (isNodeInGroup(step->getSwNode(), m_nodesforss)) {
>>> +          if (!isNodeInGroup(step->getSwNode(), nodes_included)) {
>>> +            nodes_included.push_back(step->getSwNode());
>>> +          }
>>> +        } else {
>>> +          // This procedure is not to be modified
>>> +          proc->setIsMergedProcedure(false);
>>> +        }
>>> +      }
>>> +    }
>>> +  }
>>> +  m_nodesforss = nodes_included;
>>> +  TRACE_LEAVE();
>>> +  return true;
>>> +}
>>> +
>>> +void SmfExecControl::createBalancedProcedures() {
>>> +  // Creates new procedures based on the ExecControl configuration
>>> +  TRACE_ENTER();
>>> +  // chunk is the size of the balanced group
>>> +  unsigned int chunk = (m_nodesforss.size() + m_numberofss - 1) / 
>>> m_numberofss;
>>> +  TRACE("balanced group size will be %i", chunk);
>>> +  std::vector<std::string>::iterator itr;
>>> +  std::vector<std::string>::iterator iend;
>>> +  // Set the procedure exec level to be as high as possible
>>> +  int procExecLvl = std::numeric_limits<int>::max() - m_numberofss 
>>> - 1;
>>> +  for (itr = m_nodesforss.begin(); iend < m_nodesforss.end(); itr 
>>> += chunk) {
>>> +    iend = itr + chunk;
>>> +    SmfUpgradeProcedure *ssproc = new(std::nothrow) 
>>> SmfUpgradeProcedure;
>>> +    if (iend >= m_nodesforss.end()) {
>>> +      iend = m_nodesforss.end();
>>> +    }
>>> +    ssproc->setUpgradeMethod(new(std::nothrow) SmfSinglestepUpgrade);
>>> +    ssproc->setProcName("safSmfProc=SmfBalancedProcedure" + 
>>> std::to_string(procExecLvl));
>>> +    std::string cdn = 
>>> SmfCampaignThread::instance()->campaign()->getDn();
>>> +    ssproc->setDn(ssproc->getProcName() + "," + cdn);
>>> +    ssproc->setExecLevel(std::to_string(procExecLvl));
>>> +    ssproc->setIsMergedProcedure(true);  // For cleanup purposes
>>> +    // Each new procedure holds the balanced group it steps over
>>> + ssproc->setBalancedGroup(std::vector<std::string>(itr, iend));
>>> +    m_balancedprocs.push_back(ssproc);
>>> +    procExecLvl++;
>>> +  }
>>> +  TRACE_LEAVE();
>>> +}
>>> +
>>> +SmfUpgradeStep* SmfExecControl::createMergedStep(
>>> +    SmfUpgradeProcedure* procedure,
>>> +    const std::vector<SmfUpgradeStep*>& steps) {
>>> +  // Create a merged step based on the upgrade steps passed in.
>>> +  // The in/out-parameter procedure shall be one of the procedures 
>>> that was
>>> +  // created with help of the createBalancedProcedures() method.
>>> +  TRACE_ENTER();
>>> +  SmfUpgradeStep* newstep = new(std::nothrow)SmfUpgradeStep;
>>> +  osafassert(newstep != nullptr);
>>> +  newstep->setRdn("safSmfStep=0001");
>>> +  newstep->setDn(newstep->getRdn() + "," + procedure->getDn());
>>> +  newstep->setMaxRetry(0);
>>> +  newstep->setRestartOption(0);
>>> +  std::list <unitNameAndState> deact;
>>> +  for (auto step : steps) {
>>> +    if (isNodeInGroup(step->getSwNode(), 
>>> procedure->getBalancedGroup())) {
>>> +      TRACE("adding modifications, deact and bundle ref from node:%s",
>>> +            step->getSwNode().c_str());
>>> + newstep->addModifications(step->getModifications());
>>> +      deact.insert(deact.end(),
>>> + step->getDeactivationUnitList().begin(),
>>> +                   step->getDeactivationUnitList().end());
>>> + procedure->mergeBundleRefRollingToSingleStep(newstep, step);
>>> +    }
>>> +  }
>>> +  TRACE_LEAVE();
>>> +  return newstep;
>>> +}
>>> +
>>> +void SmfExecControl::addInitAndWrapupActionsToProcedure(
>>> +    SmfUpgradeProcedure* procedure,
>>> +    const std::vector<SmfUpgradeAction*>& initactions,
>>> +    const std::vector<SmfUpgradeAction*>& wrapupactions) {
>>> +  // Add Init/WrapupActions to the procedure. The Actions themself 
>>> contain a
>>> +  // pointer to the procedure.
>>> +  TRACE_ENTER();
>>> +  procedure->addInitActions(initactions);
>>> +  procedure->addWrapupActions(wrapupactions);
>>> +  for (auto iac : initactions) {
>>> +    const SmfCallbackAction* cba = dynamic_cast<const 
>>> SmfCallbackAction*>(iac);
>>> +    if (cba != nullptr) {
>>> + const_cast<SmfCallbackAction*>(cba)->setCallbackProcedure(procedure);
>>> +    }
>>> +  }
>>> +  for (auto wac : wrapupactions) {
>>> +    const SmfCallbackAction* cba = dynamic_cast<const 
>>> SmfCallbackAction*>(wac);
>>> +    if (cba != nullptr) {
>>> + const_cast<SmfCallbackAction*>(cba)->setCallbackProcedure(procedure);
>>> +    }
>>> +  }
>>> +  TRACE_LEAVE();
>>> +}
>>> +
>>> +void SmfExecControl::trace() {
>>> +  for (auto proc : 
>>> m_campaign->getUpgradeCampaign()->getProcedures()) {
>>> +    TRACE("-procedure %s to upgrade campaign", proc->getDn().c_str());
>>> +    TRACE("-merged procedure %i", proc->getIsMergedProcedure());
>>> +    for (auto step : proc->getProcSteps()) {
>>> +      TRACE("-step : %s, state %i", step->getDn().c_str(), 
>>> step->getState());
>>> +    }
>>> +    for (auto iact : proc->getInitActions()) {
>>> +      auto cba = dynamic_cast<SmfCallbackAction*>(iact);
>>> +      TRACE("-iact cb label : %s", 
>>> cba->getCallback().getCallbackLabel().c_str());
>>> +    }
>>> +  }
>>> +}
>>> +
>>> +bool readExecControlObject(unsigned int* numberOfSingleSteps,
>>> +                           std::vector<std::string>* 
>>> nodesForSingleStep) {
>>> +  // Read the attributes from the exec control object from the IMM. 
>>> The OI
>>> +  // will prevent any changes once a campaign is running.
>>> +  SmfImmUtils immutil;
>>> +  SaImmAttrValuesT_2 **attributes;
>>> +  if (immutil.getObject(SMF_CONFIG_OBJECT_DN, &attributes) == false) {
>>> +    LOG_ER("Could not get SMF config object from IMM %s", 
>>> SMF_CONFIG_OBJECT_DN);
>>> +    return false;
>>> +  }
>>> +  const char* execdn = immutil_getStringAttr(
>>> +      (const SaImmAttrValuesT_2 **)attributes, 
>>> OPENSAF_SMF_EXEC_CONTROL, 0);
>>> +  if (execdn == NULL || strcmp(execdn, "") == 0) {
>>> +    LOG_ER("Could not get %s attrs from SmfConfig", 
>>> OPENSAF_SMF_EXEC_CONTROL);
>>> +    return false;
>>> +  }
>>> +  if (immutil.getObject(execdn, &attributes) == false) {
>>> +    LOG_ER("Failed to get object from attribute %s", 
>>> OPENSAF_SMF_EXEC_CONTROL);
>>> +    return false;
>>> +  }
>>> +  SaAisErrorT rc;
>>> +  SaUint32T numnodes;
>>> +  rc = 
>>> immutil_getAttrValuesNumber(const_cast<char*>("nodesForSingleStep"),
>>> +                                   (const SaImmAttrValuesT_2 
>>> **)attributes,
>>> +                                   &numnodes);
>>> +  if (rc != SA_AIS_OK) {
>>> +    LOG_ER("nodesForSingleStep not configured");
>>> +    return false;
>>> +  }
>>> +  const char* node;
>>> +  for (unsigned int i = 0; i < numnodes; i++) {
>>> +    node = immutil_getStringAttr((const 
>>> SaImmAttrValuesT_2**)attributes,
>>> +                                      "nodesForSingleStep", i);
>>> +    if (node == NULL) {
>>> +        break;
>>> +    }
>>> +    nodesForSingleStep->push_back("safAmfNode=" + std::string(node) +
>>> + ",safAmfCluster=myAmfCluster");
>>> +  }
>>> +  const SaUint32T* numss = immutil_getUint32Attr(
>>> +      (const SaImmAttrValuesT_2 **)attributes, 
>>> "numberOfSingleSteps", 0);
>>> +  if (numss == NULL) {
>>> +    LOG_ER("could not read numberOfSingleSteps");
>>> +    return false;
>>> +  }
>>> +
>>> +  *numberOfSingleSteps = *numss;
>>> +
>>> +  TRACE("numberOfSingleSteps %i", *numberOfSingleSteps);
>>> +  for (auto node : *nodesForSingleStep) {
>>> +    TRACE("nodesForSingleStep %s", node.c_str());
>>> +  }
>>> +  osafassert(numberOfSingleSteps != 0);
>>> +  return true;
>>> +}
>>> +
>>> +bool removeDuplicateActivationUnits(SmfUpgradeProcedure * i_newproc,
>>> + SmfUpgradeStep *newStep) {
>>> +  // Remove any (de)activation unit duplicates and add them to the 
>>> step.
>>> +  // Activation and deactivation units are the same because rolling 
>>> and
>>> +  // formodify is symetric.
>>> +  TRACE_ENTER();
>>> +  std::list < unitNameAndState > tmpDU;
>>> +  std::multimap<std::string, objectInst> objInstances;
>>> +  if (i_newproc->getImmComponentInfo(objInstances) == false) {
>>> +    TRACE("Config info from IMM could not be read");
>>> +    return false;
>>> +  }
>>> +
>>> +  // Remove DU duplicates
>>> +  tmpDU.sort(compare_du_part);
>>> +  tmpDU.unique(unique_du_part);
>>> +
>>> +  // Reduce the DU list, check if smaller scope is within bigger 
>>> scope.
>>> +  std::pair<std::multimap<std::string, objectInst>::iterator,
>>> +            std::multimap<std::string, objectInst>::iterator> 
>>> nodeName_mm;
>>> +  std::multimap<std::string, objectInst>::iterator iter;
>>> +
>>> +  std::list < unitNameAndState > nodeLevelDU;
>>> +  std::list < unitNameAndState >::iterator unit_iter;
>>> +  // Find DU on node level and save them in a separate list
>>> +  for (unit_iter = tmpDU.begin(); unit_iter != tmpDU.end();) {
>>> +    if ((*unit_iter).name.find("safAmfNode=") == 0) {  // DU is a 
>>> node node
>>> +      // A node will never be optimized away, save it
>>> +      nodeLevelDU.push_back(*unit_iter);
>>> +      // Remove the node and update iterator
>>> +      unit_iter = tmpDU.erase(unit_iter);
>>> +    } else {
>>> +      ++unit_iter;
>>> +    }
>>> +  }
>>> +
>>> +  // For all found nodes, look if some other DU (comp/SU) is within 
>>> scope
>>> +  // tmpDU contain all DU except the node level ones which was 
>>> removed above
>>> +  // and saved in nodeLevelDU list
>>> +  std::list < unitNameAndState >::iterator itr;
>>> +  for (itr = nodeLevelDU.begin(); itr != nodeLevelDU.end(); ++itr) {
>>> +    // For all comp/SU found in the scope of the node.  Find out if 
>>> any
>>> +    // remaining DU is within it.
>>> +    // Get all components/SU within the node
>>> +    nodeName_mm = objInstances.equal_range((*itr).name);
>>> +    for (iter = nodeName_mm.first;  iter != nodeName_mm.second;  
>>> ++iter) {
>>> +      // For all comp/SU sound in the scope of the node.
>>       sound --> found
>>> +      // Find out if any remaininf DU is within it
>> remaininf --> remaining
>>> +      for (unit_iter = tmpDU.begin(); unit_iter != tmpDU.end();) {
>>> +        if ((*unit_iter).name == (*iter).second.suDN) {  // Check SU
>>> +          TRACE("[%s] is in scope of [%s], remove it from DU list",
>>> +                 (*unit_iter).name.c_str(), (*itr).name.c_str());
>>> +          // Remove the node and update iterator
>>> +          unit_iter = tmpDU.erase(unit_iter);
>>> +        } else if ((*unit_iter).name == (*iter).second.compDN) {  
>>> // Check comp
>>> +          TRACE("[%s] is in scope of [%s], remove it from DU list",
>>> +                 (*unit_iter).name.c_str(), (*itr).name.c_str());
>>> +          // Remove the node and update iterator
>>> +          unit_iter = tmpDU.erase(unit_iter);
>>> +        } else {
>>> +          ++unit_iter;
>>> +        }
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +  // tmpDU contain all DU which was not in the scope of an included 
>>> node Find
>>> +  // DU on SU level and save them in a separate list. Remove SU 
>>> from tmpDU list
>>> +  std::list < unitNameAndState > suLevelDU;
>>> +  for (unit_iter = tmpDU.begin(); unit_iter != tmpDU.end();) {
>>> +    if ((*unit_iter).name.find("safSu=") == 0) {  // DU is a SU
>>> +      // A node will never be optimized away, save it
>>> +      suLevelDU.push_back(*unit_iter);
>>> +      unit_iter = tmpDU.erase(unit_iter);  // Remove the SU and 
>>> update iterator
>>> +    } else {
>>> +      ++unit_iter;
>>> +    }
>>> +  }
>>> +
>>> +  // For all SU in the suLevelDU list, look if remaining DU in 
>>> tmpDU is within
>>> +  // scope of the SU
>>> +  std::list < unitNameAndState >::iterator su_iter;
>>> +  for (su_iter = suLevelDU.begin(); su_iter != suLevelDU.end(); 
>>> ++su_iter) {
>>> +    for (unit_iter = tmpDU.begin(); unit_iter != tmpDU.end();) {
>>> +      if ((*unit_iter).name.find((*su_iter).name) != 
>>> std::string::npos) {
>>> +        // The component was in the scope of the SU
>>> +        TRACE("[%s] is in scope of [%s], remove it from DU list",
>>> +              (*unit_iter).name.c_str(), (*su_iter).name.c_str());
>>> +        // Remove the Component and update iterator
>>> +        unit_iter = tmpDU.erase(unit_iter);
>>> +      } else {
>>> +        ++unit_iter;
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +  newStep->addDeactivationUnits(nodeLevelDU);  // Add the node 
>>> level DU
>>> +  newStep->addDeactivationUnits(suLevelDU);  // Add the SU level DU
>>> +  newStep->addDeactivationUnits(tmpDU);  // Add the comp level DU
>>> +
>>> +  // Rolling and forModify are symetric, add the node level DU
>>> +  newStep->addActivationUnits(nodeLevelDU);
>>> +  // Rolling and forModify are symetric, Add the SU level DU
>>> +  newStep->addActivationUnits(suLevelDU);
>>> +  // Rolling and forModify are symetric, Add the comp level DU
>>> +  newStep->addActivationUnits(tmpDU);
>>> +
>>> +  TRACE_LEAVE();
>>> +  return true;
>>> +}
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfExecControl.h 
>>> b/osaf/services/saf/smfsv/smfd/SmfExecControl.h
>>> new file mode 100644
>>> --- /dev/null
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfExecControl.h
>>> @@ -0,0 +1,64 @@
>>> +/*
>>> + *
>>> + * (C) Copyright 2009 The OpenSAF 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. This file and program are 
>>> licensed
>>> + * under the GNU Lesser General Public License Version 2.1, 
>>> February 1999.
>>> + * The complete license can be accessed from the following location:
>>> + * http://opensource.org/licenses/lgpl-license.php
>>> + * See the Copying file included with the OpenSAF distribution for 
>>> full
>>> + * licensing terms.
>>> + *
>>> + * Author(s): Ericsson AB
>>> + *
>>> + */
>>> +#ifndef OPENSAF_STAGING_OSAF_SERVICES_SAF_SMFSV_SMFD_SMFEXECCONTROL_H_
>>> +#define OPENSAF_STAGING_OSAF_SERVICES_SAF_SMFSV_SMFD_SMFEXECCONTROL_H_
>>> +
>>> +#include <vector>
>>> +#include <string>
>>> +#include "base/macros.h"
>>> +#include "SmfUpgradeStep.hh"
>>> +#include "SmfUpgradeAction.hh"
>>> +
>>> +/*
>>> +* This class enables the balanced mode feature. This mode changes 
>>> the execution
>>> +* of rolling procedures to be merged into one or several single 
>>> steps that are
>>> +* spread out across the cluster nodes. This feature is used to give 
>>> a faster
>>> +* upgrade time compared to rolling one node at a time, possibly 
>>> several times
>>> +* for each node. By splittting the procedures it into several 
>>> single steps
>>> +* across the nodes a total service outage can be avoided.
>>> +*/
>>> +
>>> +class SmfExecControl {
>>> + public:
>>> +  SmfExecControl();
>>> +  bool initBalancedMode();
>>> +
>>> +  const std::vector<SmfUpgradeProcedure*>& getProcedures() {
>>> +    return m_balancedprocs; }
>>> +
>>> + private:
>>> +  bool setNodesForSingleStep();
>>> +  void createBalancedProcedures();
>>> +  SmfUpgradeStep* createMergedStep(SmfUpgradeProcedure* procedure,
>>> +                                   const 
>>> std::vector<SmfUpgradeStep*>& steps);
>>> +  std::vector<SmfUpgradeStep*> 
>>> getStepsMatchingBalancedGroup(SmfUpgradeProcedure* procedure);
>>> +  void addInitAndWrapupActionsToProcedure(
>>> +      SmfUpgradeProcedure* procedure,
>>> +      const std::vector<SmfUpgradeAction*>& initactions,
>>> +      const std::vector<SmfUpgradeAction*>& wrapupactions);
>>> +  void trace();
>>> +
>>> +  unsigned int m_numberofss;
>>> +  SmfCampaign* m_campaign;
>>> +  std::vector<std::string> m_nodesforss;
>>> +  std::vector<SmfUpgradeProcedure*> m_balancedprocs;
>>> +  std::vector<SmfUpgradeProcedure*> m_originalprocs;
>>> +
>>> +  DELETE_COPY_AND_MOVE_OPERATORS(SmfExecControl);
>>> +};
>>> +
>>> +#endif  // 
>>> OPENSAF_STAGING_OSAF_SERVICES_SAF_SMFSV_SMFD_SMFEXECCONTROL_H_
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfProcState.cc 
>>> b/osaf/services/saf/smfsv/smfd/SmfProcState.cc
>>> --- a/osaf/services/saf/smfsv/smfd/SmfProcState.cc
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfProcState.cc
>>> @@ -36,6 +36,7 @@
>>>   #include "SmfRollback.hh"
>>>   #include "SmfUtils.hh"
>>>   #include "smfd.h"
>>> +#include "SmfExecControl.h"
>>>     /* 
>>> ======================================================================== 
>>>
>>>    *   DEFINITIONS
>>> @@ -241,8 +242,8 @@ SmfProcStateInitial::executeInit(SmfUpgr
>>>   {
>>>       TRACE_ENTER();
>>>       LOG_NO("PROC: Start procedure init actions");
>>> -        if 
>>> (SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode()
>>> -        == SMF_MERGE_TO_SINGLE_STEP) {
>>> +        int procExecMode = 
>>> SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode();
>>> +        if (procExecMode == SMF_MERGE_TO_SINGLE_STEP) {
>>>                   LOG_NO("SmfProcStateInitial::executeInit, Merge 
>>> procedures into single step");
>>>                   if( !i_proc->mergeStepIntoSingleStep(i_proc)) {
>>>                           changeState(i_proc, 
>>> SmfProcStateExecFailed::instance());
>>> @@ -250,6 +251,8 @@ SmfProcStateInitial::executeInit(SmfUpgr
>>>                           TRACE_LEAVE();
>>>                           return SMF_PROC_FAILED;
>>>                   }
>>> +        } else if (procExecMode == SMF_BALANCED_MODE) {
>>> +                TRACE("SmfProcStateInitial::executeInit, In 
>>> balanced mode, calculation already done");
>>>           } else {
>>>                   TRACE("SmfProcStateInitial::executeInit, Calculate 
>>> steps");
>>>                   if( !i_proc->calculateSteps() ) {
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc 
>>> b/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc
>>> --- a/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.cc
>>> @@ -84,22 +84,26 @@ class SmfUpgradeProcedure;
>>>   // 
>>> ------------------------------------------------------------------------------
>>>   SmfUpgradeCampaign::~SmfUpgradeCampaign()
>>>   {
>>> -    TRACE_ENTER();
>>> -        //Delete merged procedure first since it contain references 
>>> to other proc
>>> -    //Check campaign state, if verify fails the campaign is still 
>>> in state initial
>>> -    //and the merged procedure is not yet created.
>>> -    if ((getProcExecutionMode() == SMF_MERGE_TO_SINGLE_STEP) &&
>>> -        (m_state->getState() != SA_SMF_CMPG_INITIAL)) {
>>> -                delete(m_mergedProcedure);
>>> +        TRACE_ENTER();
>>> +        for (auto &it: m_procedure) {
>>> +                delete it;
>>>           }
>>> +        m_procedure.clear();
>>> +        m_originalProcedures.clear();
>>> +        TRACE_LEAVE();
>>> +}
>>>   -    std::vector < SmfUpgradeProcedure * >::iterator iter;
>>> -
>>> -    for (iter = m_procedure.begin(); iter != m_procedure.end(); 
>>> ++iter) {
>>> -        delete(*iter);
>>> -    }
>>> -
>>> -    TRACE_LEAVE();
>>> +// 
>>> ------------------------------------------------------------------------------
>>> +// addModifiedProcedure()
>>> +// 
>>> ------------------------------------------------------------------------------
>>> +void SmfUpgradeCampaign::addModifiedProcedure(SmfUpgradeProcedure* 
>>> procedure) {
>>> +        int execMode = getProcExecutionMode();
>>> +        osafassert(execMode != SMF_STANDARD_MODE);
>>> +        if (m_originalProcedures.size() == 0) {
>>> +                m_originalProcedures = m_procedure;
>>> +                m_procedure.clear();
>>> +        }
>>> +        m_procedure.push_back(procedure);
>>>   }
>>>     // 
>>> ------------------------------------------------------------------------------
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh 
>>> b/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh
>>> --- a/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeCampaign.hh
>>> @@ -400,23 +400,19 @@ void verify();
>>>           SaAisErrorT checkSmfRestartIndicator();
>>>     ///
>>> -/// Purpose: get procedure list
>>> -/// @param   None.
>>> -/// @return  list of procedures.
>>> +/// Purpose: Get the unmodified procedures, no merged procedures 
>>> included
>>>   ///
>>> -    const std::vector < SmfUpgradeProcedure * >& getProcedures() { 
>>> return m_procedure; }
>>> +    const std::vector<SmfUpgradeProcedure*>& 
>>> getOriginalProcedures() { return m_originalProcedures; };
>>>   -/// Purpose: set the merged procedure
>>> -/// @param   A SmfUpgradeProcedure *
>>> -/// @return  the procedure.
>>>   ///
>>> -    void setMergedProc(SmfUpgradeProcedure * proc) { 
>>> m_mergedProcedure = proc; }
>>> +/// Purpose: Add the merged procedure while saving the original
>>> +///
>>> +    void addModifiedProcedure(SmfUpgradeProcedure* procedure);
>>>   -/// Purpose: get the merged procedure
>>> -/// @param   None.
>>> -/// @return  the procedure.
>>>   ///
>>> -    SmfUpgradeProcedure * getMergedProc() { return 
>>> m_mergedProcedure; }
>>> +/// Purpose: Can be used with any procedure execution mode
>>> +///
>>> +    const std::vector<SmfUpgradeProcedure*>& getProcedures() { 
>>> return m_procedure; }
>>>     /// Purpose: Set the procedure ecxecution mode
>>>   /// @param   The execution mode.
>>> @@ -482,8 +478,8 @@ private:
>>>           std::string m_configurationBase;
>>>       SmfCampaignInit m_campInit;
>>>       SmfCampaignWrapup m_campWrapup;
>>> -        std::vector < SmfUpgradeProcedure * >m_procedure;
>>> -        SmfUpgradeProcedure * m_mergedProcedure;
>>> +        std::vector<SmfUpgradeProcedure*> m_procedure;
>>> +        std::vector<SmfUpgradeProcedure*> m_originalProcedures;
>>>           SaTimeT m_waitToCommit;
>>>           SaTimeT m_waitToAllowNewCampaign;
>>>       int m_noOfExecutingProc;
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc 
>>> b/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc
>>> --- a/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.cc
>>> @@ -51,6 +51,7 @@
>>>   #include "SmfUpgradeAction.hh"
>>>   #include "SmfUtils.hh"
>>>   #include "smfd.h"
>>> +#include "SmfExecControl.h"
>>>     // This static member variable is the object counter for upgrade 
>>> procedures
>>>   unsigned long SmfUpgradeProcedure::s_procCounter = 1;
>>> @@ -1171,7 +1172,7 @@ SmfUpgradeProcedure::mergeStepIntoSingle
>>>           std::list < unitNameAndState > forAddRemoveDU;
>>>       std::list < unitNameAndState > tmpDU;
>>>           SmfUpgradeCampaign * camp = 
>>> SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
>>> -        const std::vector < SmfUpgradeProcedure * >& procedures = 
>>> camp->getProcedures();
>>> +        const std::vector < SmfUpgradeProcedure * >& procedures = 
>>> camp->getOriginalProcedures();
>>>           std::vector < SmfUpgradeProcedure * >::const_iterator 
>>> proc_iter;
>>>           for (proc_iter = procedures.begin(); proc_iter != 
>>> procedures.end(); proc_iter++) {
>>>                   LOG_NO("Merging [%s] into a single step 
>>> procedure", (*proc_iter)->getName().c_str());
>>> @@ -2779,10 +2780,13 @@ SmfUpgradeProcedure::getImmSteps()
>>>           TRACE("Rolling upgrade");
>>>           rc = getImmStepsRolling();
>>>       } else if (upgradeMethod->getUpgradeMethod() == 
>>> SA_SMF_SINGLE_STEP) {
>>> -                if 
>>> (SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode()
>>> -            == SMF_MERGE_TO_SINGLE_STEP) {  //This is a merged 
>>> single step
>>> +                unsigned int execMode = 
>>> SmfCampaignThread::instance()->campaign()->getUpgradeCampaign()->getProcExecutionMode();
>>> +                if (execMode == SMF_MERGE_TO_SINGLE_STEP) { //This 
>>> is a merged single step
>>>                           TRACE("Merged single step upgrade");
>>>                           rc = getImmStepsMergedSingleStep();
>>> +                } else if (execMode == SMF_BALANCED_MODE) {
>>> +                        TRACE("Balanced single step upgrade");
>>> +                        rc = getImmStepsSingleStep();
>>>                   } else { //This is a written normal single step
>>>                           TRACE("Single step upgrade");
>>>                           rc = getImmStepsSingleStep();
>>> @@ -3140,7 +3144,7 @@ SmfUpgradeProcedure::getImmStepsMergedSi
>>>           int initActionId = 1;
>>>           int wrapupActionId = 1;
>>>           SmfUpgradeCampaign * camp = 
>>> SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
>>> -        const std::vector < SmfUpgradeProcedure * >& procedures = 
>>> camp->getProcedures();
>>> +        const std::vector < SmfUpgradeProcedure * >& procedures = 
>>> camp->getOriginalProcedures();
>>>           std::vector < SmfUpgradeProcedure * >::const_iterator 
>>> proc_iter;
>>>           for (proc_iter = procedures.begin(); proc_iter != 
>>> procedures.end(); proc_iter++) {
>>> LOG_NO("SmfUpgradeProcedure::getImmStepsMergedSingleStep: Fetch 
>>> callbacks and wrapup actions from [%s]",
>>> @@ -3415,7 +3419,7 @@ SmfUpgradeProcedure::bundleRefFromSsCamp
>>> //----------------------------------------------------------------
>>>       //Read all the bundles to add/remove from the parsed camaign
>>>           SmfUpgradeCampaign * camp = 
>>> SmfCampaignThread::instance()->campaign()->getUpgradeCampaign();
>>> -    const std::vector < SmfUpgradeProcedure * >& procedures = 
>>> camp->getProcedures();
>>> +    const std::vector < SmfUpgradeProcedure * >& procedures = 
>>> camp->getOriginalProcedures();
>>>       std::vector < SmfUpgradeProcedure * >::const_iterator proc_iter;
>>>       std::list < SmfBundleRef > bundlesOldProcSS;
>>>       std::list < SmfBundleRef *> bundlesOldProcRO;
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh 
>>> b/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh
>>> --- a/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeProcedure.hh
>>> @@ -551,7 +551,7 @@ class SmfUpgradeProcedure {
>>>   /// @param    -
>>>   /// @return   The list of upgrade steps.
>>>   ///
>>> -        const std::vector < SmfUpgradeStep * >& getProcSteps() { 
>>> return m_procSteps; }
>>> +        std::vector < SmfUpgradeStep * >& getProcSteps() { return 
>>> m_procSteps; }
>>>     ///
>>>   /// Purpose:  Add the list of upgrade steps
>>> @@ -706,6 +706,7 @@ class SmfUpgradeProcedure {
>>>   ///
>>>           void setIsMergedProcedure(bool i_state)
>>>                   { m_isMergedProcedure = i_state; }
>>> +        bool getIsMergedProcedure() {return m_isMergedProcedure; }
>>>     ///
>>>   /// Purpose:  Reset the object counter of upgrade procedures
>>> @@ -717,8 +718,6 @@ class SmfUpgradeProcedure {
>>>       friend class SmfProcState;
>>>       friend class SmfCampStateSuspendingExec;
>>>   - private:
>>> -
>>>   ///
>>>   /// Purpose:  Get iformation from AMF config in IMM about 
>>> Components, SUs and nodes needed for upgrade
>>>   /// @param    A reference to a std::multimap<std::string, objectInst>
>>> @@ -726,6 +725,20 @@ class SmfUpgradeProcedure {
>>>   ///
>>>       bool getImmComponentInfo(std::multimap<std::string, 
>>> objectInst> &i_objects);
>>>   +
>>> +///
>>> +/// Purpose: When merging with SMF_BALANCED_MODE we need to keep 
>>> track of which balanced group procedures belong to.
>>> +///
>>> +        const std::vector<std::string>& getBalancedGroup() { return 
>>> m_balancedGroup; }
>>> +
>>> +///
>>> +/// Purpose: When merging with SMF_BALANCED_MODE we need to keep 
>>> track of which balanced group procedures belong to.
>>> +///
>>> +        void setBalancedGroup(std::vector<std::string> group) { 
>>> m_balancedGroup = group; }
>>> +
>>> + private:
>>> +
>>> +
>>>   ///
>>>   /// Purpose:  Change the procedure stste. If i_onlyInternalState 
>>> == false, the IMM procedure object is updated and
>>>   ///           a state change event is sent
>>> @@ -765,6 +778,7 @@ class SmfUpgradeProcedure {
>>>           std::list < SmfCallback * >m_afterUnlock; //Container of 
>>> the procedure callbacks to be invoked onstep, ataction
>>>       sem_t m_semaphore;
>>>           bool m_isMergedProcedure;
>>> +        std::vector<std::string> m_balancedGroup;
>>>   };
>>>     //////////////////////////////////////////////////
>>> diff --git a/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh 
>>> b/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh
>>> --- a/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh
>>> +++ b/osaf/services/saf/smfsv/smfd/SmfUpgradeStep.hh
>>> @@ -707,6 +707,12 @@ class SmfUpgradeStep {
>>>   /// @return   true on success else false
>>>   ///
>>>       bool readSmfClusterControllers();
>>> +///
>>> +/// Purpose:  Set step state
>>> +/// @param    The state
>>> +/// @return   None
>>> +///
>>> +    void setStepState(SaSmfStepStateT i_state);
>>>             friend class SmfStepState;
>>>   @@ -761,13 +767,6 @@ class SmfUpgradeStep {
>>>       void setImmStateAndSendNotification(SaSmfStepStateT i_state);
>>>     ///
>>> -/// Purpose:  Set step state
>>> -/// @param    The state
>>> -/// @return   None
>>> -///
>>> -    void setStepState(SaSmfStepStateT i_state);
>>> -
>>> -///
>>>   /// Purpose: Disables copy constructor
>>>   ///
>>>        SmfUpgradeStep(const SmfUpgradeStep &);
>>> diff --git a/osaf/services/saf/smfsv/smfd/smfd.h 
>>> b/osaf/services/saf/smfsv/smfd/smfd.h
>>> --- a/osaf/services/saf/smfsv/smfd/smfd.h
>>> +++ b/osaf/services/saf/smfsv/smfd/smfd.h
>>> @@ -60,7 +60,7 @@ extern "C" {
>>>   /* SMF execution modes */
>>>   #define SMF_STANDARD_MODE 0
>>>   #define SMF_MERGE_TO_SINGLE_STEP 1
>>> -#define SMF_MERGE_TO_NODE_ROLLING 2
>>> +#define SMF_BALANCED_MODE 2
>>>     /* 
>>> ======================================================================== 
>>>
>>>    *   TYPE DEFINITIONS
>>
>


------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to