A test program, ccbhdl_test, is added to the demo directory that tests
combined CCBs, data ownership and reusage of created objects escpecially
the CCB handling object

* Fixed bugs found during testing. Fixed some review comments.
* Still some TODOs. These are more like comments about possible changes
  in the future. Will not be removed for now
* LLDTEST Tags still remains. Will be removed before pushing
* All review commits will be concatenated into one commit before pushing
---
 src/smf/Makefile.am                                |  37 +-
 .../smfd/imm_modify_config/add_operation_to_ccb.cc |   5 -
 src/smf/smfd/imm_modify_config/attribute.cc        |   1 -
 src/smf/smfd/imm_modify_config/attribute.h         |   2 -
 src/smf/smfd/imm_modify_config/immccb.cc           |  48 +--
 src/smf/smfd/imm_modify_config/immccb.h            |  51 +--
 src/smf/smfd/imm_modify_demo/Makefile              |   2 +-
 src/smf/smfd/imm_modify_demo/ccbhdl_test.cc        | 377 +++++++++++++++++++++
 src/smf/smfd/imm_om_api/om_admin_owner_clear.h     |  11 +
 src/smf/smfd/imm_om_api/om_admin_owner_handle.h    |   8 +
 src/smf/smfd/imm_om_api/om_admin_owner_set.h       |   6 +
 src/smf/smfd/imm_om_api/om_ccb_handle.cc           |   3 +-
 src/smf/smfd/imm_om_api/om_ccb_handle.h            |   7 +
 src/smf/smfd/imm_om_api/om_ccb_object_create.h     |   5 +
 src/smf/smfd/imm_om_api/om_ccb_object_delete.h     |   5 +
 src/smf/smfd/imm_om_api/om_ccb_object_modify.h     |   5 +
 src/smf/smfd/imm_om_api/om_handle.cc               |   8 +-
 src/smf/smfd/imm_om_api/om_handle.h                |  13 +-
 18 files changed, 518 insertions(+), 76 deletions(-)
 create mode 100644 src/smf/smfd/imm_modify_demo/ccbhdl_test.cc

diff --git a/src/smf/Makefile.am b/src/smf/Makefile.am
index 673387db6..016da30c8 100644
--- a/src/smf/Makefile.am
+++ b/src/smf/Makefile.am
@@ -258,7 +258,7 @@ endif
 # Demos and test
 if ENABLE_TESTS
 
-bin_PROGRAMS += bin/ccbdemo_create bin/ccbdemo_delete bin/ccbdemo_modify
+bin_PROGRAMS += bin/ccbdemo_create bin/ccbdemo_delete bin/ccbdemo_modify 
bin/ccbhdl_test
 
 dist_pkgimmxml_svc_DATA += \
        src/smf/smfd/imm_modify_demo/democlass.xml
@@ -368,4 +368,39 @@ bin_ccbdemo_modify_LDADD = \
        lib/libSaImmOm.la \
        lib/libopensaf_core.la
 
+# CCBHDL Test
+# -----------
+bin_ccbhdl_test_CFLAGS = $(AM_CFLAGS) -Wformat=1
+
+bin_ccbhdl_test_CPPFLAGS = \
+       -DSA_EXTENDED_NAME_SOURCE \
+       $(AM_CPPFLAGS)
+
+bin_ccbhdl_test_SOURCES = \
+       src/smf/smfd/imm_modify_demo/ccbhdl_test.cc
+
+# IMM configuration modifier
+bin_ccbhdl_test_SOURCES += \
+       src/smf/smfd/imm_modify_config/attribute.cc \
+       src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc \
+       src/smf/smfd/imm_modify_config/immccb.cc
+
+# IMM OM C++ APIs
+bin_ccbhdl_test_SOURCES += \
+       src/smf/smfd/imm_om_api/common/common.cc \
+       src/smf/smfd/imm_om_api/common/imm_attribute.cc \
+       src/smf/smfd/imm_om_api/om_admin_owner_clear.cc \
+       src/smf/smfd/imm_om_api/om_admin_owner_handle.cc \
+       src/smf/smfd/imm_om_api/om_admin_owner_set.cc \
+       src/smf/smfd/imm_om_api/om_ccb_handle.cc \
+       src/smf/smfd/imm_om_api/om_ccb_object_create.cc \
+       src/smf/smfd/imm_om_api/om_ccb_object_delete.cc \
+       src/smf/smfd/imm_om_api/om_ccb_object_modify.cc \
+       src/smf/smfd/imm_om_api/om_handle.cc
+
+bin_ccbhdl_test_LDADD = \
+       lib/libosaf_common.la \
+       lib/libSaImmOm.la \
+       lib/libopensaf_core.la
+
 endif
diff --git a/src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc 
b/src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc
index 6948aa89c..6658182ff 100644
--- a/src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc
+++ b/src/smf/smfd/imm_modify_config/add_operation_to_ccb.cc
@@ -18,11 +18,6 @@
 
 #include "add_operation_to_ccb.h"
 
-#if 1 // TODO(Lennart) Remove
-#include <stdio.h>
-#include <iostream>
-#endif
-
 #include <limits.h>
 
 #include <string>
diff --git a/src/smf/smfd/imm_modify_config/attribute.cc 
b/src/smf/smfd/imm_modify_config/attribute.cc
index 72d5e8828..4b9f63817 100644
--- a/src/smf/smfd/imm_modify_config/attribute.cc
+++ b/src/smf/smfd/imm_modify_config/attribute.cc
@@ -44,7 +44,6 @@ using namespace modelmodify;
 //      - A numeric IMM type, SaImmValueTypeT
 // out: - A filled in numeric vector
 // return false on error. Type of error is logged in syslog
-// TODO(Lennart) Make static
 template<typename T>
 static bool StringToNumericValue(const std::string& str_value,
                           T& num_value, const SaImmValueTypeT imm_type) {
diff --git a/src/smf/smfd/imm_modify_config/attribute.h 
b/src/smf/smfd/imm_modify_config/attribute.h
index 7cb0e316c..61db1d8c8 100644
--- a/src/smf/smfd/imm_modify_config/attribute.h
+++ b/src/smf/smfd/imm_modify_config/attribute.h
@@ -32,8 +32,6 @@
 #ifndef ATTRVAL_HDL_H
 #define ATTRVAL_HDL_H
 
-// TODO(Lennart) Place within namespace modelmodify?
-
 // Convert std::string to SaNameT or SaAnyT.
 // Shall be used with AttributeDescriptor object where SaNametToString or
 // SaAnytToString has been used to convert the data to std::string
diff --git a/src/smf/smfd/imm_modify_config/immccb.cc 
b/src/smf/smfd/imm_modify_config/immccb.cc
index e52d6b9e6..968306499 100644
--- a/src/smf/smfd/imm_modify_config/immccb.cc
+++ b/src/smf/smfd/imm_modify_config/immccb.cc
@@ -66,20 +66,23 @@ ModelModification::ModelModification()
       imm_ccb_handle_(nullptr),
       imm_ao_handle_(nullptr),
       imm_ao_owner_set_(nullptr),
-      error_info_{"No error", SA_AIS_OK},
       modification_timeout_(120000),
       ccb_flags_(0) {
+    TRACE_ENTER2("LLDTEST");
     // Create a unique admin owner name for this ObjectModification object
     instance_number_ = next_instance_number_++;
     admin_owner_name_ = "SmfObjectModification" +
         std::to_string(instance_number_);
+    TRACE_LEAVE2("LLDTEST");
   }
 
 ModelModification::~ModelModification() {
   // If an OM handle exists, cleanup the CCB handling by finalizing the handle
   // Note that releaseOwnershipFinalize must be set when creating an OM admin
   // owner handle so that admin ownership is released
+  TRACE_ENTER2("LLDTEST");
   FinalizeHandles();
+  TRACE_LEAVE2("LLDTEST");
 }
 
 bool ModelModification::DoModelModification(CcbDescriptor modifications) {
@@ -88,10 +91,6 @@ bool ModelModification::DoModelModification(CcbDescriptor 
modifications) {
   int recovery_info = kNotSet;
   base::Timer modification_time(modification_timeout_);
 
-  // Creating a CCB is a sequence of calls to different IMM APIs. Each API call
-  // may fail. But in some cases, based on the API return code, it is possible
-  // to recover by redoing the sequence from start. To prevent indefinite
-  // re-tries the recovery loop is timed out
   while (modification_time.is_timeout() == false) {
     // If CCB creation fail invalid handles shall be finalized
     // Note: This function is safe to call also if there are no handles
@@ -220,17 +219,19 @@ int ModelModification::CreateObjectManager() {
     RetryTiming.interval = base::kFourtyMilliseconds;
     RetryTiming.timeout = 60000;
     imm_om_handle_->ChangeDefaultRetryControl(RetryTiming);
+  } else {
+    TRACE("LLDTEST %s: OM handle object exists", __FUNCTION__);
   }
 
   bool return_state = imm_om_handle_->InitializeHandle();
   if (return_state == false) {
     // No recovery is possible
-    LOG_NO("LLDTEST %s: OM-handle, InitializeHandle(), Fail", __FUNCTION__);
+    LOG_NO("LLDTEST %s: OM-handle, RestoreHandle(), Fail", __FUNCTION__);
     recovery_info = kFail;
   } else {
     recovery_info = kContinue;
   }
-  TRACE_LEAVE2("LLDTEST");
+  TRACE_LEAVE2("LLDTEST, %s", RecoveryTxt(recovery_info));
   return recovery_info;
 }
 
@@ -248,12 +249,15 @@ int ModelModification::CreateAdminOwner() {
   TRACE_ENTER2("LLDTEST");
   int recovery_info = kNotSet;
   if (imm_ao_handle_ == nullptr) {
-    SaImmHandleT om_handle = imm_om_handle_->GetHandle();
     imm_ao_handle_ = std::unique_ptr<immom::ImmOmAdminOwnerHandle>
-        (new immom::ImmOmAdminOwnerHandle(om_handle, admin_owner_name_));
+        (new immom::ImmOmAdminOwnerHandle(0, admin_owner_name_));
+  } else {
+    TRACE("LLDTEST %s: OM handle object exists", __FUNCTION__);
   }
 
-  bool rc = imm_ao_handle_->InitializeHandle();
+  SaImmHandleT om_handle = imm_om_handle_->GetHandle();
+  imm_ao_handle_->ReleaseOwnershipOnFinalize();
+  bool rc = imm_ao_handle_->InitializeHandle(om_handle);
   if (rc == false) {
     SaAisErrorT ais_rc = imm_ao_handle_->ais_error();
     if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
@@ -266,14 +270,16 @@ int ModelModification::CreateAdminOwner() {
       recovery_info = kFail;
     }
   } else {
+    SaImmAdminOwnerHandleT ao_handle = imm_ao_handle_->GetHandle();
     if (imm_ao_owner_set_ == nullptr) {
-      SaImmAdminOwnerHandleT ao_handle = imm_ao_handle_->GetHandle();
       imm_ao_owner_set_ = std::unique_ptr<immom::ImmOmAdminOwnerSet>
           (new immom::ImmOmAdminOwnerSet(ao_handle));
+    } else {
+      imm_ao_owner_set_->UpdateHandle(ao_handle);
     }
     recovery_info = kContinue;
   }
-  TRACE_LEAVE2("LLDTEST");
+  TRACE_LEAVE2("LLDTEST, %s", RecoveryTxt(recovery_info));
   return recovery_info;
 }
 
@@ -285,12 +291,12 @@ int ModelModification::CreateCcb() {
   TRACE_ENTER2("LLDTEST");
   int recovery_info = kNotSet;
   if (imm_ccb_handle_ == nullptr) {
-    SaImmAdminOwnerHandleT ao_handle = imm_ao_handle_->GetHandle();
     imm_ccb_handle_ = std::unique_ptr<immom::ImmOmCcbHandle>
-        (new immom::ImmOmCcbHandle(ao_handle, ccb_flags_));
+        (new immom::ImmOmCcbHandle(0, ccb_flags_));
   }
 
-  bool rc = imm_ccb_handle_->InitializeHandle();
+  SaImmAdminOwnerHandleT ao_handle = imm_ao_handle_->GetHandle();
+  bool rc = imm_ccb_handle_->InitializeHandle(ao_handle);
   if (rc == false) {
     SaAisErrorT ais_rc = imm_ccb_handle_->ais_error();
     if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
@@ -352,8 +358,12 @@ int 
ModelModification::AdminOwnerSet(std::vector<std::string>& objects,
     return kFail;
   }
 
+  // The ImmOmAdminOwnerSet exists and may have been used earlier so clean the
+  // object list before adding new objects
+  imm_ao_owner_set_->ClearObjectNames();
   // Set objects to become admin owner of
   for (auto& object : objects) {
+    TRACE("LLDTEST* %s: Set AO for object = '%s'", __FUNCTION__, 
object.c_str());
     if (object.empty()) {
       // Do not add empty strings (IMM root)
       continue;
@@ -412,15 +422,13 @@ int 
ModelModification::AdminOwnerSet(std::vector<std::string>& objects,
 //        has an admin owner if the same admin owner name is used, meaning that
 //        this is not needed to check
 // Recovery:  BAD HANDLE; Restart CCB handling
-//            FAILED OPERATION; Restart CCB handling
+//            FAILED OPERATION; Restart CCB handling if resource abort
 // Return:  Recovery information
 int ModelModification::AddCreates(std::vector<CreateDescriptor>&
       create_descriptors) {
   TRACE_ENTER2("LLDTEST");
   int recovery_info = kNotSet;
 
-  // TODO(Lennart) The code below for setting admin owner is the same (almost)
-  // for all configuration operations (redundant). Fix
   // Do this for all create descriptors
   for (auto& create_descriptor : create_descriptors) {
     if (create_descriptor.parent_name.empty() == false) {
@@ -475,7 +483,7 @@ int ModelModification::AddCreate(CreateDescriptor& 
create_descriptor) {
 // Add delete requests for all objects to be deleted
 // Set admin ownership for objects to be deleted with scope SA_IMM_SUBTREE.
 // Add all delete operations to the CCB
-// Note1: We have to be owner of the object(s) and the sub tree
+// Note1: We have to be owner of the object(s) and the sub tree(s)
 // Note2: It is not a problem to set admin ownership of an object that already
 //        has an admin owner if the same admin owner name is used, meaning that
 //        this is not needed to check
@@ -550,7 +558,7 @@ int ModelModification::AddDelete(DeleteDescriptor& 
delete_descriptor) {
 //        has an admin owner if the same admin owner name is used, meaning that
 //        this is not needed to check
 // Recovery:  BAD HANDLE; Restart CCB handling
-//            FAILED OPERATION; Restart CCB handling
+//            FAILED OPERATION; Restart CCB handling if resource abort
 // Return:  Recovery information
 int ModelModification::AddModifies(std::vector<ModifyDescriptor>&
                                     modify_descriptors) {
diff --git a/src/smf/smfd/imm_modify_config/immccb.h 
b/src/smf/smfd/imm_modify_config/immccb.h
index 6fc71eee4..744306a6a 100644
--- a/src/smf/smfd/imm_modify_config/immccb.h
+++ b/src/smf/smfd/imm_modify_config/immccb.h
@@ -70,7 +70,8 @@
  * RETRY handling is done in three levels:
  * 1. For each IMM API. This is mainly try again loops
  * 2. For sequences of APIs. The main reason is if the OM handle has to be
- *    recreated (SA_AIS_ERR_BAD_HANDLE)
+ *    recreated (SA_AIS_ERR_BAD_HANDLE) however there are some other
+ *    recoverable problems as well
  * 3. For failing to apply a CCB if the reason is not un-recoverable e.g.
  *    a validation error
  *
@@ -81,8 +82,6 @@
  * does not have to log any detailed information.
  * Example of user logging:
  * LOG_NO("%s: DoModification() Fail", __FUNCTION__);
- * TODO(Lennart) More detailed information about a fail is saved and can be
- * requested.
  *
  * Possible reasons for a fail:
  *  * An IMM API has returned an unrecoverable error. This includes try again
@@ -91,15 +90,12 @@
  *  * Other unrecoverable error from an Object Implementer
  *  * All CCB apply retries has failed
  *  * A general timeout for the whole modify sequence has happened before
- *    the CCB was applied
+ *    the CCB was applied successfully
  */
 
-// TODO(Lennart) Recovery is not possible if CcbApply returns FAILED OPERATION
-// since this error is returned if an OI validation fails. Note that if the
-// SA_IMM_CCB_REGISTERED_OI flag is set no OI verification will be done
-// This is also the case for Create and Modify
-// Investigate!
-
+// Functions for converting some SAF sepcific types to string. For numeric
+// values the STL to_string can be used
+// -----------------------------------------------------------------------
 // Convert SaNameT to a std::string to be used with an AttributeDescriptor
 // Note: Both types may contain data that cannot be read as text string but
 //       their data can still be contained in a std::string object
@@ -124,6 +120,8 @@ namespace modelmodify {
 //  * Multiple values of the given value_type. This is allowed only if the
 //    attribute is defined as a multi value attribute
 // Used with IMM object creation and value modifications
+// Note: Use <object name>.values_as_strings.clear() before adding any values
+//       to remove any previous values if the object is reused
 //
 struct AttributeDescriptor {
   std::string attribute_name;
@@ -169,7 +167,7 @@ struct AttributeModifyDescriptor {
 // Possible modifications are:
 //  * Create an IMM object
 //  * Delete an IMM object
-//  * Modify the value(s) of one attribute in an IMM object
+//  * Modify the value(s) of one or more attribute(s) in an IMM object
 // Note:  Several modifications can be added to one CCB.
 //
 // Some general notes:
@@ -207,6 +205,7 @@ struct DeleteDescriptor {
 };
 
 // ModifyDescriptor: Modify value(s) of one or several attributes in one object
+// Note: Use only one ModifyDescriptor per object in the same CCB
 //
 struct ModifyDescriptor {
   // Full DN of the object to be modified
@@ -241,15 +240,6 @@ struct CcbDescriptor {
   }
 };
 
-// TODO(Lennart) Is this really needed? If not remove
-// ErrorInfo: Used as out-parameter to give information about an operation
-struct ErrorInfo {
-  // Name of the failed function / method
-  std::string function_name;
-  // Holds the ais_error code of the last called IMM API
-  SaAisErrorT ais_error;
-};
-
 // Internal recovery information
 // -----------------------------
 // An operation may Fail and no recovery is possible but it may also fail
@@ -272,6 +262,7 @@ const uint64_t kExistTimeout = 30000; // 30 sec
 const uint64_t kExistWait = 2000; // 2 sec
 
 // Recovery code to text
+// Used with log and trace
 inline static const char* RecoveryTxt(int recovery_info) {
   switch (recovery_info) {
     case modelmodify::kContinue:
@@ -300,9 +291,6 @@ inline static const char* RecoveryTxt(int recovery_info) {
 // Note2: All IMM resources needed for the operation will be allocated
 //        internally when needed and released before DoModification returns.
 //
-// TODO(Lennart) We may also need:
-//  * Method to set some timeout for the operation(s) (other settings?)
-//
 // Example: Create an IMM object Obj1 based on IMM class Class1. The rdn
 //          attribute name is obj1Name and the object name (rdn) shall be
 //          obj1=1. Parent is safApp=safSmfService. No other attributes will be
@@ -310,7 +298,7 @@ inline static const char* RecoveryTxt(int recovery_info) {
 //
 //  // 1. Fill in an attribute descriptor for the object name:
 //  modelmodify::AttributeDescriptor object_name("obj1Name");
-//  object_name.AddValue<SaStringT>("obj1=1");
+//  object_name.AddValue("obj1=1");
 //
 //  // 2. Fill in a create descriptor:
 //  modelmodify::CreateDescriptor create_obj1;
@@ -332,7 +320,7 @@ inline static const char* RecoveryTxt(int recovery_info) {
 class ModelModification {
  public:
   ModelModification();
-  ~ModelModification(); // TODO(Lennart) Finalize the Object Manager
+  ~ModelModification();
 
   // Set CCB Flags
   // If flag SA_IMM_CCB_REGISTERED_OI is set then an Object Implementer must
@@ -345,9 +333,6 @@ class ModelModification {
   // a validation error
   bool DoModelModification(CcbDescriptor modifications);
 
-  // Get more information if DoModification return Fail
-  ErrorInfo GetErrorInfo(void) { return error_info_; }
-
  private:
   void FinalizeHandles(void);
   int CreateHandles(void);
@@ -378,7 +363,7 @@ class ModelModification {
 
   // Instance number for this class used to create a unique applier name
   // This is needed if instances are used in several threads
-  // By using a unique name we can avoid taking admin ownership form some other
+  // By using a unique name we can avoid taking admin ownership from some other
   // thread that has an ongoing modification
   // At construction time the static instance number is copied to the local
   // instance number and the global instance number is incremented for next
@@ -390,8 +375,6 @@ class ModelModification {
   CcbDescriptor ccb_descriptor_;
   // A list of all objects to become admin owner of
   std::vector<std::string> admin_owner_objects_;
-  // Store information about each step in the IMM API sequence
-  ErrorInfo error_info_;
   // Main timeout for DoModification()
   uint64_t modification_timeout_;
   SaImmCcbFlagsT ccb_flags_;
@@ -401,12 +384,6 @@ class ModelModification {
 
 } // namespace modelmodify
 
-// TODO(Lennart) For now functions are added here for converting SaNameT and
-//               SaAnyT to std::string. May be inline methods in the
-//               AttributeDescriptor structure?
-//
-//               Maybe part of modelmodify namespace?
-
 static inline std::string SaNametToString(SaNameT* name_value) {
   std::string out_string;
   if (osaf_is_extended_name_empty(name_value)) {
diff --git a/src/smf/smfd/imm_modify_demo/Makefile 
b/src/smf/smfd/imm_modify_demo/Makefile
index 9492d3272..8dc274034 100644
--- a/src/smf/smfd/imm_modify_demo/Makefile
+++ b/src/smf/smfd/imm_modify_demo/Makefile
@@ -15,5 +15,5 @@
 #
 
 all:
-       $(MAKE) -C ../../../.. bin/ccbdemo_create bin/ccbdemo_delete 
bin/ccbdemo_modify
+       $(MAKE) -C ../../../.. bin/ccbdemo_create bin/ccbdemo_delete 
bin/ccbdemo_modify bin/ccbhdl_test
 
diff --git a/src/smf/smfd/imm_modify_demo/ccbhdl_test.cc 
b/src/smf/smfd/imm_modify_demo/ccbhdl_test.cc
new file mode 100644
index 000000000..fca3759db
--- /dev/null
+++ b/src/smf/smfd/imm_modify_demo/ccbhdl_test.cc
@@ -0,0 +1,377 @@
+/*      -*- OpenSAF  -*-
+ *
+ * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
+ *
+ * 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 <limits.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <utility>
+#include <iostream>
+
+#include "ais/include/saImm.h"
+#include "ais/include/saAis.h"
+#include "base/osaf_extended_name.h"
+#include "osaf/configmake.h"
+
+#include "smf/smfd/imm_modify_config/immccb.h"
+
+#include "smf/smfd/imm_om_api/common/common.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_clear.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_handle.h"
+#include "smf/smfd/imm_om_api/om_admin_owner_set.h"
+#include "smf/smfd/imm_om_api/om_ccb_handle.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_create.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_delete.h"
+#include "smf/smfd/imm_om_api/om_ccb_object_modify.h"
+#include "smf/smfd/imm_om_api/om_handle.h"
+
+using namespace std;
+
+// Before this program can be used the class defined in democlass.xml has to be
+// installed.
+
+// Create one object. The whole procedure is done here including applying the
+// CCB
+// DN = Test1=1,safApp=safSmfService
+// Several attributes are set
+void CreateOneObject(void) {
+
+  // Create an object description
+  // ============================
+  modelmodify::AttributeDescriptor attribute;
+  modelmodify::CreateDescriptor imm_object;
+  std::string object_name = "Test1=1";
+
+  // Define the object
+  // -----------------
+  imm_object.class_name = "ImmTestValuesConfig";
+  imm_object.parent_name = "safApp=safSmfService";
+  // Set IMM Object name
+  attribute.attribute_name = "immTestValuesCfg";
+  attribute.value_type = SA_IMM_ATTR_SASTRINGT;
+  attribute.AddValue(object_name);
+  imm_object.AddAttribute(attribute);
+
+  // Set some attributes
+  // -------------------
+
+  // SA_UINT32_T multi-value attribute
+  attribute.attribute_name = "SaUint32TValues";
+  attribute.value_type = SA_IMM_ATTR_SAUINT32T;
+  // We are reusing so remove "old" values and add new ones
+  attribute.values_as_strings.clear();
+  attribute.AddValue(std::to_string(1));
+  attribute.AddValue(std::to_string(2));
+  // Add the attribute to the object
+  imm_object.AddAttribute(attribute);
+
+  // SA_INT32_T multi-value attribute
+  attribute.attribute_name = "SaInt32TValues";
+  attribute.value_type = SA_IMM_ATTR_SAINT32T;
+  attribute.values_as_strings.clear();
+  attribute.AddValue(std::to_string(3));
+  attribute.AddValue(std::to_string(4));
+  // Add the attribute to the object
+  imm_object.AddAttribute(attribute);
+
+  // SA_NAME_T multi-value attribute
+  SaNameT a_name;
+  attribute.attribute_name = "SaNameTValues";
+  attribute.value_type = SA_IMM_ATTR_SANAMET;
+  attribute.values_as_strings.clear();
+  // Add two short names
+  osaf_extended_name_lend("a_name1", &a_name);
+  attribute.AddValue(SaNametToString(&a_name));
+  osaf_extended_name_lend("a_name2", &a_name);
+  attribute.AddValue(SaNametToString(&a_name));
+  // Add a long name and a third short name
+  char long_name[300];
+  for (size_t i = 0; i < 299; i++) {
+    long_name[i] = 'a';
+  }
+  long_name[299] = '\0';
+  osaf_extended_name_lend(long_name, &a_name);
+  attribute.AddValue(SaNametToString(&a_name));
+  osaf_extended_name_lend("a_name3", &a_name);
+  attribute.AddValue(SaNametToString(&a_name));
+  imm_object.AddAttribute(attribute);
+
+  // SA_UINT32_T single-value attribute
+  attribute.attribute_name = "SaUint32TValue";
+  attribute.value_type = SA_IMM_ATTR_SAUINT32T;
+  attribute.values_as_strings.clear();
+  // Note: Single value attribute so only one value can be added
+  attribute.AddValue(std::to_string(10));
+  imm_object.AddAttribute(attribute);
+
+  // Create a CCB descriptor and add the description of the object to create
+  // =======================================================================
+  modelmodify::CcbDescriptor CcbDescriptor;
+
+  CcbDescriptor.AddCreate(imm_object);
+
+  // Create a modification handler and use it to create the object as defined
+  // above
+  // ========================================================================
+
+  modelmodify::ModelModification ModelModifier;
+
+  // Set CCB flag to inform IMM that there is no Object Implementer
+  ModelModifier.SetCcbFlags(0);
+
+  // Create the IMM object
+  if (ModelModifier.DoModelModification(CcbDescriptor) == false) {
+    cout << "Creation of '" << object_name << "' FAIL" << endl;
+  } else {
+    cout << "Creation of '" << object_name << "' SUCCESS" << endl;
+  }
+}
+
+// Remove all modifications from a CCB descriptor so it can be reused
+void CcbDescriptorCleaner(modelmodify::CcbDescriptor& ccb_descriptor) {
+  ccb_descriptor.create_descriptors.clear();
+  ccb_descriptor.delete_descriptors.clear();
+  ccb_descriptor.modify_descriptors.clear();
+}
+
+// Fill in a create descriptor.
+// The created object will be given the name in 'object_name'
+// Class name and parent is filled in here
+// Values set are:
+// SaInt32TValues: 1, 2, 3
+// SaUint64TValues: 100, 200
+// SaTimeTValues: 10000
+void SetupObjectCreate1(std::string object_name,
+                          modelmodify::CreateDescriptor& create_desc) {
+  modelmodify::AttributeDescriptor attribute;
+  // Prepare the create descriptor
+  create_desc.class_name = "ImmTestValuesConfig";
+  create_desc.parent_name = "safApp=safSmfService";
+  create_desc.attributes.clear();
+
+  // Set object name
+  attribute.attribute_name = "immTestValuesCfg";
+  attribute.value_type = SA_IMM_ATTR_SASTRINGT;
+  attribute.AddValue(object_name);
+  create_desc.AddAttribute(attribute);
+
+  // Set SaInt32TValues
+  attribute.values_as_strings.clear();
+  attribute.attribute_name = "SaInt32TValues";
+  attribute.value_type = SA_IMM_ATTR_SAINT32T;
+  attribute.AddValue(std::to_string(1));
+  attribute.AddValue(std::to_string(2));
+  attribute.AddValue(std::to_string(3));
+  create_desc.AddAttribute(attribute);
+
+  // Set SaUint64TValues
+  attribute.values_as_strings.clear();
+  attribute.attribute_name = "SaUint64TValues";
+  attribute.value_type = SA_IMM_ATTR_SAUINT64T;
+  attribute.AddValue(std::to_string(100));
+  attribute.AddValue(std::to_string(200));
+  create_desc.AddAttribute(attribute);
+
+  // Set SaTimeTValues
+  attribute.values_as_strings.clear();
+  attribute.attribute_name = "SaTimeTValues";
+  attribute.value_type = SA_IMM_ATTR_SATIMET;
+  attribute.AddValue(std::to_string(10000));
+  create_desc.AddAttribute(attribute);
+}
+
+void WaitForUserAction(std::string message) {
+  cout << message << endl;
+  cout << endl << "Press Enter to continue" << endl << endl;
+  getchar();
+}
+
+int main() {
+  cout << "ccbhdl_test" << endl;
+  cout << "IMM class used for test: ImmTestValuesConfig" << endl;
+
+#if 0 // Enable trace
+  unsigned int category_mask = 0xffffffff;
+  const char* logPath = PKGLOGDIR "/osafccbdemo1";
+  if (logtrace_init("ccbdemo1", logPath, category_mask) == -1) {
+    syslog(LOG_ERR, "osafntfimcnd logtrace_init FAILED");
+    /* We allow to execute anyway. */
+    cout << "logtrace_init() Fail" << endl;
+  } else {
+    //cout << "logtrace enabled" << endl;
+  }
+#endif
+
+  // Prepare/enable extended name
+  // ----------------------------
+  setenv("SA_ENABLE_EXTENDED_NAMES", "1", 1);
+  osaf_extended_name_init();
+  // Note: Long DN must be configured in IMM configuration object before
+  // running ccbdemo_...
+  // DN for that object is opensafImm=opensafImm,safApp=safImmService
+
+  // ==================== TEST START 
===========================================
+
+  // Create a first object
+  // ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
+  // This is done in a separate function where also the CCB is applied
+  cout << "Creating: Test1=1,safApp=safSmfService" << endl;
+  CreateOneObject();
+  cout << endl;
+
+  // Wait for the user to verify in another node and press Enter in this node
+  WaitForUserAction("Verify creation of Test1=1,safApp=safSmfService");
+
+  // Create a modifier to be used here in main() and set CCB flag to handle
+  // that there is no Object Implementer for objects handled here
+  // ----------------------------------------------------------------------
+  modelmodify::ModelModification modifier;
+  modifier.SetCcbFlags(0);
+  // A CCB descriptor for the modifier
+  modelmodify::CcbDescriptor ccb_descriptor;
+
+  // We also need some model modification descriptors
+  modelmodify::CreateDescriptor create_descriptor;
+  modelmodify::ModifyDescriptor modify_descriptor;
+  modelmodify::DeleteDescriptor delete_descriptor;
+  // an attribute modify descriptor
+  modelmodify::AttributeDescriptor attribute_descriptor;
+  // and an attribute modify descriptor
+  modelmodify::AttributeModifyDescriptor attribute_modify_descriptor;
+
+  // Create and apply a CCB that creates two more objects
+  // ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
+
+  SetupObjectCreate1("Test1=2", create_descriptor);
+  ccb_descriptor.AddCreate(create_descriptor);
+  SetupObjectCreate1("Test1=3", create_descriptor);
+  ccb_descriptor.AddCreate(create_descriptor);
+  if (modifier.DoModelModification(ccb_descriptor) == false) {
+    cout << "Create two more objects in the same CCB, FAIL" << endl;
+  } else {
+    cout << "Create two more objects using one CCB, SUCCESS" << endl;
+  }
+  cout << endl;
+
+  WaitForUserAction("Verify creation of Test1=2 and Test1=3 objects "
+                    "(,safApp=safSmfService)");
+
+  // Modify the model using a new CCB with mixed modifications
+  // ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
+
+  // Create one new object "Test1=4"
+  // Delete "Test1=2" and "Test1=3" parent "Test1=2,safApp=safSmfService"
+  // Modify "Test1=1":
+  //  Add 4 to SaUint32TValues
+  //  Delete "a_name1" from SaNameTValues
+  //  Replace SaInt32TValues 3 and 4 with 5, 6, 7
+  // All is done in the same CCB
+
+  // We are reusing the CCB descriptor so:
+  // Clean the CCB descriptor from the previous object creation
+  CcbDescriptorCleaner(ccb_descriptor);
+
+  // Add a new object to the CBB. The new object is created within a function
+  // that uses an attribute descriptor that is local to this function. This 
will
+  // test that data is correctly handed over to the create descriptor
+  SetupObjectCreate1("Test1=4", create_descriptor);
+  ccb_descriptor.AddCreate(create_descriptor);
+
+  // Add two objects deletions
+  delete_descriptor.object_name = "Test1=2,safApp=safSmfService";
+  ccb_descriptor.AddDelete(delete_descriptor);
+  delete_descriptor.object_name = "Test1=3,safApp=safSmfService";
+  ccb_descriptor.AddDelete(delete_descriptor);
+
+  // Setup the modifications for the "test1=1" object:
+  modify_descriptor.object_name = "Test1=1,safApp=safSmfService";
+  // Add a value to SaUint32TValues
+  // Clean attribute descriptor from any possible previous usage
+  attribute_descriptor.values_as_strings.clear();
+  attribute_descriptor.attribute_name = "SaUint32TValues";
+  attribute_descriptor.value_type = SA_IMM_ATTR_SAUINT32T;
+  attribute_descriptor.AddValue(std::to_string(4));
+  attribute_modify_descriptor.modification_type = SA_IMM_ATTR_VALUES_ADD;
+  attribute_modify_descriptor.attribute_descriptor = attribute_descriptor;
+  modify_descriptor.AddAttributeModification(attribute_modify_descriptor);
+  // Delete a value from SaNameTValues
+  attribute_descriptor.values_as_strings.clear();
+  SaNameT a_name; // Use a real SaNameT
+  osaf_extended_name_lend("a_name1", &a_name);
+  attribute_descriptor.attribute_name = "SaNameTValues";
+  attribute_descriptor.value_type = SA_IMM_ATTR_SANAMET;
+  attribute_descriptor.AddValue(SaNametToString(&a_name));
+  attribute_modify_descriptor.modification_type = SA_IMM_ATTR_VALUES_DELETE;
+  attribute_modify_descriptor.attribute_descriptor = attribute_descriptor;
+  modify_descriptor.AddAttributeModification(attribute_modify_descriptor);
+  // Replace the values in SaInt32TValues
+  attribute_descriptor.attribute_name = "SaInt32TValues";
+  attribute_descriptor.value_type = SA_IMM_ATTR_SAINT32T;
+  attribute_descriptor.values_as_strings.clear();
+  attribute_descriptor.AddValue(std::to_string(5));
+  attribute_descriptor.AddValue(std::to_string(6));
+  attribute_descriptor.AddValue(std::to_string(7));
+  attribute_modify_descriptor.modification_type = SA_IMM_ATTR_VALUES_REPLACE;
+  attribute_modify_descriptor.attribute_descriptor = attribute_descriptor;
+  modify_descriptor.AddAttributeModification(attribute_modify_descriptor);
+
+  // Add the modifications to the CCB
+  ccb_descriptor.AddModify(modify_descriptor);
+
+  cout << "Modify the model using a mixed CCB START" << endl;
+
+  // The modifier object is used here for the second time
+  if (modifier.DoModelModification(ccb_descriptor) == false) {
+    cout << "Modify the model using a mixed CCB, FAIL" << endl;
+  } else {
+    cout << "Modify the model using a mixed CCB, SUCCESS" << endl;
+  }
+
+  cout << "Test sequence DONE" << endl << endl;
+
+  cout << "Verify that:" << endl;
+  cout << "  - The Test1=2 and Test1=3 objects are deleted" << endl;
+  cout << "  - A new Test1=4 object is created" << endl;
+  cout << "  - Test1=1 is modified:" << endl;
+  cout << "       SaUint32TValues: Added '4'" << endl;
+  cout << "       SaNameTValues:   Deleted 'a_name1'" << endl;
+  cout << "       SaInt32TValues:  Values '3, 4' "
+                                  "replaced by '5, 6, 7'" << endl << endl;
+
+  WaitForUserAction("After pressing Enter the remaining objects "
+      "will be deleted");
+
+  cout << "Cleanup by deleting the remaining Test1=1 and Test1=4 objects"
+       << endl;
+
+  CcbDescriptorCleaner(ccb_descriptor);
+  delete_descriptor.object_name = "Test1=1,safApp=safSmfService";
+  ccb_descriptor.AddDelete(delete_descriptor);
+  delete_descriptor.object_name = "Test1=4,safApp=safSmfService";
+  ccb_descriptor.AddDelete(delete_descriptor);
+
+  // The modifier object is used here for the third time
+  if (modifier.DoModelModification(ccb_descriptor) == false) {
+    cout << "Delete Test1=1 and Test1=4, FAIL" << endl;
+  } else {
+    cout << "Delete Test1=1 and Test1=4, SUCCESS" << endl;
+  }
+
+  return 0;
+}
\ No newline at end of file
diff --git a/src/smf/smfd/imm_om_api/om_admin_owner_clear.h 
b/src/smf/smfd/imm_om_api/om_admin_owner_clear.h
index 89bb8bf47..b2d2ba4a7 100644
--- a/src/smf/smfd/imm_om_api/om_admin_owner_clear.h
+++ b/src/smf/smfd/imm_om_api/om_admin_owner_clear.h
@@ -55,6 +55,17 @@ class ImmOmAdminOwnerClear : public ImmBase {
 
   ~ImmOmAdminOwnerClear();
 
+  // Set a new OM handle. Needed when recovering from BAD_HANDLE
+  void UpdateHandle(const SaImmHandleT& om_handle) {
+    om_handle_ = om_handle;
+  }
+
+  // Set new objects to clear
+  void SetObjectList(const std::vector<std::string>& list_of_object_names) {
+    object_names_.clear();
+    object_names_ = list_of_object_names;
+  }
+
   // Clear admin owner of object names on given scope.
   // Use ais_error() to get returned AIS code.
   bool ClearAdminOwner(SaImmScopeT scope = SA_IMM_SUBTREE);
diff --git a/src/smf/smfd/imm_om_api/om_admin_owner_handle.h 
b/src/smf/smfd/imm_om_api/om_admin_owner_handle.h
index 93080a8e7..515c1f23c 100644
--- a/src/smf/smfd/imm_om_api/om_admin_owner_handle.h
+++ b/src/smf/smfd/imm_om_api/om_admin_owner_handle.h
@@ -54,6 +54,7 @@ class ImmOmAdminOwnerHandle : public ImmBase {
                                  const std::string& admin_owner_name);
   ~ImmOmAdminOwnerHandle();
 
+
   // Use before InitializeHandle() if admin ownership shall be kept when handle
   // is finalized
   ImmOmAdminOwnerHandle& KeepOwnershipOnFinalize() {
@@ -73,6 +74,13 @@ class ImmOmAdminOwnerHandle : public ImmBase {
   // or finalized, false otherwise.
   // Use ais_error() to get AIS return code.
   bool InitializeHandle();
+  // Initialize with a new OM handle. Needed for recovery
+  bool InitializeHandle(const SaImmHandleT& om_handle) {
+    FinalizeHandle();
+    om_handle_ = om_handle;
+    admin_owner_handle_ = 0;
+    return InitializeHandle();
+  }
   bool FinalizeHandle();
 
   // Get the IMM Admin Owner handle and implicitly do initializing if the 
handle
diff --git a/src/smf/smfd/imm_om_api/om_admin_owner_set.h 
b/src/smf/smfd/imm_om_api/om_admin_owner_set.h
index 762954530..9638c63e6 100644
--- a/src/smf/smfd/imm_om_api/om_admin_owner_set.h
+++ b/src/smf/smfd/imm_om_api/om_admin_owner_set.h
@@ -62,6 +62,12 @@ class ImmOmAdminOwnerSet : public ImmBase {
     object_names_.push_back(object_name);
   }
 
+  // Set a new OM handle. Needed when recovering from BAD_HANDLE
+  void UpdateHandle(const SaImmAdminOwnerHandleT& admin_owner_handle) {
+    admin_owner_handle_ = admin_owner_handle;
+    is_set_admin_owner_invoked_ = false;
+  }
+
   // Clear the list of object names
   // Note: this will not release the admin owner
   void ClearObjectNames(void) {
diff --git a/src/smf/smfd/imm_om_api/om_ccb_handle.cc 
b/src/smf/smfd/imm_om_api/om_ccb_handle.cc
index 0916b45c3..9f6098f13 100644
--- a/src/smf/smfd/imm_om_api/om_ccb_handle.cc
+++ b/src/smf/smfd/imm_om_api/om_ccb_handle.cc
@@ -35,7 +35,7 @@ ImmOmCcbHandle::ImmOmCcbHandle(
     : ImmOmCcbHandle{admin_owner_handle, SA_IMM_CCB_REGISTERED_OI} {}
 
 ImmOmCcbHandle::~ImmOmCcbHandle() {
-  TRACE_ENTER();
+  TRACE_ENTER2("LLDTESTOOO");
   FinalizeHandle();
 }
 
@@ -69,6 +69,7 @@ bool ImmOmCcbHandle::FinalizeHandle() {
   base::Timer wtime(retry_ctrl_.timeout);
   while (wtime.is_timeout() == false) {
     ais_error_ = saImmOmCcbFinalize(ccb_handle_);
+    TRACE("LLDTESTOOO %s: saImmOmCcbFinalize() = %s", __FUNCTION__, 
saf_error(ais_error_));
     if (ais_error_ == SA_AIS_ERR_TRY_AGAIN) {
       base::Sleep(retry_ctrl_.interval);
       continue;
diff --git a/src/smf/smfd/imm_om_api/om_ccb_handle.h 
b/src/smf/smfd/imm_om_api/om_ccb_handle.h
index be335d9e7..72ba05cbf 100644
--- a/src/smf/smfd/imm_om_api/om_ccb_handle.h
+++ b/src/smf/smfd/imm_om_api/om_ccb_handle.h
@@ -61,6 +61,13 @@ class ImmOmCcbHandle : public ImmBase {
   // Returns false on error.
   // Use ais_error() to get AIS return code.
   bool InitializeHandle();
+  // Initialize with a new AO handle. Needed for recovery
+  bool InitializeHandle(const SaImmAdminOwnerHandleT& admin_owner_handle) {
+    FinalizeHandle();
+    admin_owner_handle_ = admin_owner_handle;
+    ccb_handle_ = 0;
+    return InitializeHandle();
+  }
   bool FinalizeHandle();
   bool ApplyCcb();
 
diff --git a/src/smf/smfd/imm_om_api/om_ccb_object_create.h 
b/src/smf/smfd/imm_om_api/om_ccb_object_create.h
index 656b9bfcb..ac799a415 100644
--- a/src/smf/smfd/imm_om_api/om_ccb_object_create.h
+++ b/src/smf/smfd/imm_om_api/om_ccb_object_create.h
@@ -89,6 +89,11 @@ class ImmOmCcbObjectCreate : public ImmBase {
   explicit ImmOmCcbObjectCreate(const SaImmCcbHandleT& ccb_handle);
   ~ImmOmCcbObjectCreate();
 
+  // Set a new CCB handle. Needed when recovering from BAD_HANDLE
+  void UpdateHandle(const SaImmCcbHandleT& ccb_handle) {
+    ccb_handle_ = ccb_handle;
+  }
+
   // If this method is not called the object will be created as a top level
   // object
   ImmOmCcbObjectCreate& SetParentName(const std::string& parent_object);
diff --git a/src/smf/smfd/imm_om_api/om_ccb_object_delete.h 
b/src/smf/smfd/imm_om_api/om_ccb_object_delete.h
index 9474e063d..93fc9858f 100644
--- a/src/smf/smfd/imm_om_api/om_ccb_object_delete.h
+++ b/src/smf/smfd/imm_om_api/om_ccb_object_delete.h
@@ -59,6 +59,11 @@ class ImmOmCcbObjectDelete : public ImmBase {
   explicit ImmOmCcbObjectDelete(const SaImmCcbHandleT& ccb_handle);
   ~ImmOmCcbObjectDelete();
 
+  // Set a new CCB handle. Needed when recovering from BAD_HANDLE
+  void UpdateHandle(const SaImmCcbHandleT& ccb_handle) {
+    ccb_handle_ = ccb_handle;
+  }
+
   // Returns false if failing
   // Use ais_error() to get returned AIS code.
   bool AddObjectDeleteToCcb(const std::string& object_name);
diff --git a/src/smf/smfd/imm_om_api/om_ccb_object_modify.h 
b/src/smf/smfd/imm_om_api/om_ccb_object_modify.h
index fd94a084b..e46806b81 100644
--- a/src/smf/smfd/imm_om_api/om_ccb_object_modify.h
+++ b/src/smf/smfd/imm_om_api/om_ccb_object_modify.h
@@ -67,6 +67,11 @@ class ImmOmCcbObjectModify : public ImmBase {
                                 const std::string& object_name);
   ~ImmOmCcbObjectModify();
 
+  // Set a new CCB handle. Needed when recovering from BAD_HANDLE
+  void UpdateHandle(const SaImmCcbHandleT& ccb_handle) {
+    ccb_handle_ = ccb_handle;
+  }
+
   // Replace all existing values with a new set of values
   // T must be AIS data types or std::string.
   // NOTE: must explicitly give typename T if passing NULL value.
diff --git a/src/smf/smfd/imm_om_api/om_handle.cc 
b/src/smf/smfd/imm_om_api/om_handle.cc
index 58a3e8cb3..c942e0fb3 100644
--- a/src/smf/smfd/imm_om_api/om_handle.cc
+++ b/src/smf/smfd/imm_om_api/om_handle.cc
@@ -40,7 +40,7 @@ ImmOmHandle::~ImmOmHandle() {
 }
 
 // Initialize @om_handle_ from IMM
-bool ImmOmHandle::InitializeHandle() {
+bool ImmOmHandle::OmInitialize() {
   TRACE_ENTER();
   SaVersionT version = version_;
   ais_error_ = SA_AIS_OK;
@@ -84,7 +84,7 @@ bool ImmOmHandle::FinalizeHandle() {
 
 SaImmHandleT ImmOmHandle::GetHandle() {
   // Implicitly initialize handle
-  if (om_handle_ == 0) InitializeHandle();
+  if (om_handle_ == 0) OmInitialize();
   return om_handle_;
 }
 
@@ -135,6 +135,9 @@ bool ImmOmHandle::DispatchBlocking() {
   return Dispatch(SA_DISPATCH_BLOCKING);
 }
 
+// TODO(Lennart) Removed like this. We may want this back if this becomes a
+// library again in the future
+#if 0
 // To enable tracing early when the library is loaded.
 __attribute__((constructor))
 static void logtrace_init_constructor(void) {
@@ -147,5 +150,6 @@ static void logtrace_init_constructor(void) {
     }
   }
 }
+#endif
 
 }  // namespace immom
diff --git a/src/smf/smfd/imm_om_api/om_handle.h 
b/src/smf/smfd/imm_om_api/om_handle.h
index 6c71fa14a..8b4eee2ab 100644
--- a/src/smf/smfd/imm_om_api/om_handle.h
+++ b/src/smf/smfd/imm_om_api/om_handle.h
@@ -55,12 +55,14 @@ class ImmOmHandle : public ImmBase {
                        const SaImmCallbacksT* callbacks = nullptr);
   ~ImmOmHandle();
 
-  void SetDummy(int i) { dummy_ = 1; }
-  int GetDummy(void) { return dummy_; }
-
-  // Return true if IMM OM handle is successfully initialized/finalized.
+// Return true if IMM OM handle is successfully initialized/finalized.
   // Use ais_error() to get AIS return code.
-  bool InitializeHandle();
+  bool InitializeHandle() {
+    FinalizeHandle();
+    om_handle_ = 0;
+    return OmInitialize();
+  }
+  bool OmInitialize();
   bool FinalizeHandle();
 
   // Fetch the operating system handle associated with the handle OM handle.
@@ -93,7 +95,6 @@ class ImmOmHandle : public ImmBase {
   SaVersionT version_;
   SaVersionT supported_version_;
   SaImmHandleT om_handle_;
-  int dummy_;
 
   DELETE_COPY_AND_MOVE_OPERATORS(ImmOmHandle);
 };
-- 
2.15.1


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to