Ack (not tested) with minor comments.

I think we should add to samples/immsv an imm.xml file that contains a 
new test-class that uses NO_DANGLING and has
an object (instance of the test-class) that contains a dangling 
reference.  The test file can be used for testing the audit tool.


On 06/05/2015 02:53 PM, Zoran Milinkovic wrote:
>   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.
                      "aditing" -> "adding".
> The patch first check no dangling references for multi-value attributes, then 
> it checks no dangling references for non multi value attributes.
             "check" ->  "checks".
> This is done in two steps because values for multi value attributes are 
> stored in another table.
                                        change to "..because multi 
valued attributes are stored in a different table".

/AndersBj
>
> 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


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

Reply via email to