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