osaf/libs/common/immsv/immpbe_dump.cc         |  137 +++++++++++++++++++++++++-
 osaf/libs/common/immsv/include/immpbe_dump.hh |    3 +
 osaf/tools/safimm/immdump/imm_dumper.cc       |   38 ++++++-
 3 files changed, 172 insertions(+), 6 deletions(-)


The patch covers only aditing no dangling references. It's required by critical 
ticket #1377.
The patch first check no dangling references for multi-value attributes, then 
it checks no dangling references for non multi value attributes.
This is done in two steps because values for multi value attributes are stored 
in another table.

The patch is done in libs/common/immsv, so that it can be used by IMM PBE in 
later implementation.
If the audit fails, one line is written in the console. Other auditing details 
are logged in syslog.

diff --git a/osaf/libs/common/immsv/immpbe_dump.cc 
b/osaf/libs/common/immsv/immpbe_dump.cc
--- a/osaf/libs/common/immsv/immpbe_dump.cc
+++ b/osaf/libs/common/immsv/immpbe_dump.cc
@@ -3121,6 +3121,130 @@ void fsyncPbeJournalFile()
        }
 }
 
+static int pbeAuditNoDangling(sqlite3 *dbHandle) {
+       sqlite3_stmt *stmt = NULL;
+       sqlite3_stmt *tblStmt = NULL;
+       std::string query;
+       int rc;
+       int err = 0;
+       /* SA_IMM_ATTR_NO_DANGLING = 67108864
+        * SA_IMM_ATTR_MULTI_VALUE = 1
+        * SA_IMM_ATTR_NO_DANGLING | SA_IMM_ATTR_MULTI_VALUE = 67108865 */
+       const char *sqlMultiVal = "select distinct obj.dn, ad.attr_name, 
otm.text_val "
+                       "from attr_def ad, objects obj, objects_text_multi otm "
+                       "where (ad.attr_flags & 67108865) = 67108865 "
+                       "and obj.class_id = ad.class_id "
+                       "and otm.obj_id = obj.obj_id "
+                       "and otm.attr_name = ad.attr_name "
+                       "and otm.text_val != '' "
+                       "and not exists (select 1 "
+                       "from objects "
+                       "where dn = otm.text_val)";
+       const char *sqlSelectNoDanglingClasses = "select cls.class_name, 
ad.attr_name "
+                       "from attr_def ad, classes cls "
+                       "where (ad.attr_flags & 67108865) = 67108864 "
+                       "and cls.class_id = ad.class_id";
+
+       /* Audit NO_DANGLING multi-value attribute */
+       rc = sqlite3_prepare_v2(dbHandle, sqlMultiVal, -1, &stmt, NULL);
+       if(rc != SQLITE_OK) {
+               LOG_ER("Failed to prepare SQL statement for(%d): %s", rc, 
sqlMultiVal);
+               err = 1;
+               goto step2;
+       }
+
+       while((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
+               LOG_ER("Missing reference object '%s' from '%s:%s' (multi value 
check)",
+                               sqlite3_column_text(stmt, 2),
+                               sqlite3_column_text(stmt, 0),
+                               sqlite3_column_text(stmt, 1));
+               err = 1;
+       }
+
+       if(rc != SQLITE_DONE) {
+               LOG_ER("SQL statement ('%s') failed with error code: %d\n", 
sqlMultiVal, rc);
+               err = 1;
+       }
+
+step2:
+       if(stmt) {
+               sqlite3_reset(stmt);
+               stmt = NULL;
+       }
+
+       /* Audit non-multi-value NO_DANGLING attributes */
+       rc = sqlite3_prepare_v2(dbHandle, sqlSelectNoDanglingClasses, -1, 
&stmt, NULL);
+       if(rc != SQLITE_OK) {
+               LOG_ER("Failed to prepare SQL statement for(%d): %s", rc, 
sqlMultiVal);
+               err = 1;
+               goto end;
+       }
+
+       while((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
+               query = "select obj.dn, tbl.";
+               query.append((char *)sqlite3_column_text(stmt, 1));
+               query.append(" from ");
+               query.append((char *)sqlite3_column_text(stmt, 0));
+               query.append(" tbl, objects obj where obj.obj_id = tbl.obj_id 
and tbl.");
+               query.append((char *)sqlite3_column_text(stmt, 1));
+               query.append(" != '' and not exists (select 1 from objects o 
where o.dn = tbl.");
+               query.append((char *)sqlite3_column_text(stmt, 1));
+               query.append(")");
+
+               rc = sqlite3_prepare_v2(dbHandle, query.c_str(), -1, &tblStmt, 
NULL);
+               if(rc != SQLITE_OK) {
+                       LOG_ER("Failed to prepare SQL statement for(%d): %s", 
rc, query.c_str());
+                       err = 1;
+                       continue;
+               }
+
+               if(sqlite3_step(tblStmt) == SQLITE_ROW) {
+                       LOG_ER("Missing reference object '%s' from '%s':'%s'",
+                                       sqlite3_column_text(tblStmt, 1),
+                                       sqlite3_column_text(tblStmt, 0),
+                                       sqlite3_column_text(stmt, 1));
+                       err = 1;
+               }
+
+               sqlite3_reset(tblStmt);
+       }
+
+       if(rc != SQLITE_DONE) {
+               LOG_ER("SQL statement ('%s') failed with error code: %d\n",
+                               sqlSelectNoDanglingClasses, rc);
+               err = 1;
+       }
+
+end:
+       if(stmt) {
+               sqlite3_reset(stmt);
+       }
+
+       return err;
+}
+
+int pbeAudit(void *db_handle) {
+       return pbeAuditNoDangling((sqlite3 *)db_handle);
+}
+
+int pbeAuditFile(const char *filename) {
+       int rc;
+       sqlite3 *dbHandle = NULL;
+
+       rc = sqlite3_open(filename, &dbHandle);
+       if(rc != SQLITE_OK) {
+               LOG_ER("Can't open PBE file '%s', cause:%s",
+                               filename, sqlite3_errmsg(dbHandle));
+               return 1;
+       }
+
+       rc = pbeAudit(dbHandle);
+
+       sqlite3_close(dbHandle);
+
+       return rc;
+}
+
 #else
 
 bool pbeTransStarted()
@@ -3288,6 +3412,18 @@ void fsyncPbeJournalFile()
        abort();
 }
 
+int pbeAudit(void *db_handle) {
+       abort();
+       return 1;
+}
+
+int pbeAuditFile(const char *filename) {
+       /* pbeAuditFile should be used by tools, and should not abort.
+        * pbeAuditFile returns 2, which means that PBE was not enabled in the 
build.
+        */
+       return 2;
+}
+
 #endif
 
 /* Note: a version of this function exists as 'escalatePbe()' in 
@@ -3521,4 +3657,3 @@ std::list<std::string> getClassNames(SaI
        return classNamesList;
 }
 
-
diff --git a/osaf/libs/common/immsv/include/immpbe_dump.hh 
b/osaf/libs/common/immsv/include/immpbe_dump.hh
--- a/osaf/libs/common/immsv/include/immpbe_dump.hh
+++ b/osaf/libs/common/immsv/include/immpbe_dump.hh
@@ -125,5 +125,8 @@ SaAisErrorT getCcbOutcomeFromPbe(void* d
 void discardPbeFile(std::string filename);
 void fsyncPbeJournalFile();
 
+int pbeAudit(void *db_handle);
+int pbeAuditFile(const char *filename);
+
 
 #endif /* IMM_PBE_DUMP_HH_ */
diff --git a/osaf/tools/safimm/immdump/imm_dumper.cc 
b/osaf/tools/safimm/immdump/imm_dumper.cc
--- a/osaf/tools/safimm/immdump/imm_dumper.cc
+++ b/osaf/tools/safimm/immdump/imm_dumper.cc
@@ -61,6 +61,9 @@ static void usage(const char *progname)
     printf("\t-c, --class   {<class name>}\n");
     printf("\t\tOnly dump objects of this class\n\n");
 
+    printf("\t-a, --audit   {<pbe file name>}\n");
+    printf("\t\tAudit PBE database\n\n");
+
     printf("\nEXAMPLE\n");
     printf("\t%s /tmp/imm.xml\n", progname);
     printf("\t%s /tmp/imm.xml -c ClassA -c ClassB\n", progname);
@@ -88,6 +91,7 @@ int main(int argc, char* argv[])
         {"pbe", required_argument, 0, 'p'},
         {"xmlwriter", required_argument, 0, 'x'},
         {"class", required_argument, 0, 'c'},
+        {"audit", required_argument, 0, 'a'},
         {0, 0, 0, 0}
     };
     SaImmHandleT           immHandle;
@@ -113,6 +117,7 @@ int main(int argc, char* argv[])
     const char* logPath;
     unsigned int category_mask = 0;
     bool pbeDumpCase = false;
+    bool auditPbe = false;
     void* dbHandle=NULL;
     const char* dump_trace_label = "immdump";
     const char* trace_label = dump_trace_label;
@@ -141,7 +146,7 @@ int main(int argc, char* argv[])
     }
 
     while (1) {
-    if ((c = getopt_long(argc, argv, "hp:x:c:", long_options, NULL)) == -1)
+    if ((c = getopt_long(argc, argv, "hp:x:c:a:", long_options, NULL)) == -1)
             break;
 
             switch (c) {
@@ -151,9 +156,8 @@ int main(int argc, char* argv[])
                     break;
 
                 case 'p':
-                           pbeDumpCase = true;
-
-                   filename.append(optarg);
+                    pbeDumpCase = true;
+                    filename.append(optarg);
                     break;
 
                 case 'x':
@@ -164,6 +168,11 @@ int main(int argc, char* argv[])
                     selectedClassList.push_back(std::string(optarg));
                     break;
 
+                case 'a':
+                    auditPbe = true;
+                    filename.append(optarg);
+                    break;
+
                 default:
                     fprintf(stderr, "Try '%s --help' for more information\n", 
                         argv[0]);
@@ -172,6 +181,11 @@ int main(int argc, char* argv[])
         }
     }
 
+    if(pbeDumpCase && auditPbe) {
+       usage(basename(argv[0]));
+       exit(EXIT_FAILURE);
+    }
+
     version.releaseCode = RELEASE_CODE;
     version.majorVersion = MAJOR_VERSION;
     version.minorVersion = MINOR_VERSION;
@@ -192,7 +206,21 @@ int main(int argc, char* argv[])
         exit(1);
     }
 
-    if(pbeDumpCase) {
+    if(auditPbe) {
+       int rc;
+
+       rc = pbeAuditFile(filename.c_str());
+       if(!rc) {
+               std::cout << "Audit successful" << std::endl;
+       } else if(rc == 2) {
+               std::cerr << "Option --enable-imm-pbe must be enabled in the 
build to be able to audit PBE file"
+                               << std::endl;
+       } else {
+               std::cerr << "Audit failed. Check syslog for more details."
+                               << std::endl;
+       }
+       exit(rc);
+    } else if(pbeDumpCase) {
        /* Generate PBE database file from current IMM state */
 
        std::cout <<

------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to