Exemple #1
0
int
candidate_validate(clicon_handle h, char *candidate, char *running)
{
    struct dbdiff      df;
    dbdep_dd_t        *ddvec = NULL;
    int                nvec;
    int                retval = -1;
    struct stat        sb;
    void              *firsterr = NULL;

    /* Sanity checks that databases exists. */
    if (stat(running, &sb) < 0){
	clicon_err(OE_DB, errno, "%s", running);
	goto done;
    }
    if (stat(candidate, &sb) < 0){
	clicon_err(OE_DB, errno, "%s", candidate);
	goto done;
    }
    memset(&df, 0, sizeof(df));

    /* Find the differences between the two databases and store it in df vector. */
    if (db_diff(running, candidate,
		__FUNCTION__,
		clicon_dbspec_key(h),
		&df
	    ) < 0)
	goto done;
    /* 1. Get commit processing dbdiff vector (df): one entry per key that 
       changed. changes are registered as if they exist in the 1st(candidate) 
       or 2nd(running) dbs.
     */
    if (dbdep_commitvec(h, &df, &nvec, &ddvec) < 0)
	goto done;
    
    /* 2. Call plugin pre-commit hooks */
    if (plugin_begin_hooks(h, candidate) < 0)
	goto done;

    /* call generic cv_validate() on all new or changed keys. */
    if (generic_validate(h, candidate, &df) < 0)
	goto done;

    /* user-defined callbacks */
    if (validate_db(h, nvec, ddvec, candidate) < 0)
	goto done;

    /* Call plugin post-commit hooks */
    if (plugin_complete_hooks(h, candidate) < 0)
	goto done;

    retval = 0;
  done:
    if (retval < 0) /* Call plugin fail-commit hooks */
	plugin_abort_hooks(h, candidate);
    if (ddvec)
	free(ddvec);
    unchunk_group(__FUNCTION__); 
    if (firsterr)
	clicon_err_restore(firsterr);
    return retval;
}
Exemple #2
0
int
main(int argc, char **argv)
{
    int i = 0;
    int diff_state = 0;
    struct bu_ptbl results;
    struct db_i *dbip1 = DBI_NULL;
    struct db_i *dbip2 = DBI_NULL;
    /*struct bu_vls diff_log = BU_VLS_INIT_ZERO;*/
    struct bn_tol *diff_tol;
    BU_GET(diff_tol, struct bn_tol);
    diff_tol->dist = BN_TOL_DIST;

    BU_PTBL_INIT(&results);

    if (argc != 3) {
	bu_log("Error - please specify two .g files\n");
	bu_exit(EXIT_FAILURE, NULL);
    }

    if (!bu_file_exists(argv[1], NULL)) {
	bu_exit(1, "Cannot stat file %s\n", argv[1]);
    }

    if (!bu_file_exists(argv[2], NULL)) {
	bu_exit(1, "Cannot stat file %s\n", argv[2]);
    }

    if ((dbip1 = db_open(argv[1], DB_OPEN_READONLY)) == DBI_NULL) {
	bu_exit(1, "Cannot open geometry database file %s\n", argv[1]);
    }
    RT_CK_DBI(dbip1);
    if (db_dirbuild(dbip1) < 0) {
	db_close(dbip1);
	bu_exit(1, "db_dirbuild failed on geometry database file %s\n", argv[1]);
    }

    /* Reset the material head so we don't get warnings when the global
     * is overwritten.  This will go away when material_head ceases to
     * be a librt global.*/
    rt_new_material_head(MATER_NULL);

    if ((dbip2 = db_open(argv[2], DB_OPEN_READONLY)) == DBI_NULL) {
	bu_exit(1, "Cannot open geometry database file %s\n", argv[2]);
    }
    RT_CK_DBI(dbip2);
    if (db_dirbuild(dbip2) < 0) {
	db_close(dbip1);
	db_close(dbip2);
	bu_exit(1, "db_dirbuild failed on geometry database file %s\n", argv[1]);
    }


    diff_state = db_diff(dbip1, dbip2, diff_tol, DB_COMPARE_ALL, &results);
    if (diff_state == DIFF_UNCHANGED) {
	bu_log("No differences found.\n");
    } else {
	print_diff_summary(&results);
    }

    for (i = 0; i < (int)BU_PTBL_LEN(&results); i++) {
	struct diff_result *result = (struct diff_result *)BU_PTBL_GET(&results, i);
	diff_free_result(result);
    }

    bu_ptbl_free(&results);
    BU_PUT(diff_tol, struct bn_tol);

    db_close(dbip1);
    db_close(dbip2);
    return 0;
}
Exemple #3
0
/*
 * candidate_commit
 * Do a diff between candidate and running, and then call plugins to
 * commit the changes. 
 * The code reverts changes if the commit fails. But if the revert
 * fails, we just ignore the errors and proceed. Maybe we should
 * do something more drastic?
 * Arguments:
 * running:   The current database. The state of the router corresponds
 *            to these values. Also called db1.
 * candidate: The candidate database. We are aiming to put the router in this 
 *            state.   Also called db2.

                      (_dp) [op, callback] (dpe_)
                      +---------------+    +---------------+
                      |    dbdep_t    |--> |  dbdep_ent_t  | [key, var] 
                      +---------------+    +---------------+
                      ^ Database dependency description
from dbdep_commit()   |
+---------------+*    |dd_dep
|  dbdep_dd_t   |-----+
+---------------+     |dd_dbdiff
(dd_)                 |
                      v
+---------------+     +---------------+  
|   dbdiff      |---->|    dbdiff_ent |  [key1, key2, add/change/rm] (dfe_)
+---------------+     +---------------+  
(df_) from dbdiff(),   (dfe_)
                     
 */
int
candidate_commit(clicon_handle h, char *candidate, char *running)
{
    struct dbdiff      df;
    dbdep_t           *dp;
    struct dbdiff_ent *dfe;
    dbdep_dd_t        *ddvec = NULL;
    dbdep_dd_t        *dd;
    int                nvec;
    int                retval = -1;
    int                i, j;
    int                failed = 0;
    struct stat        sb;
    void              *firsterr = NULL;

    /* Sanity checks that databases exists. */
    if (stat(running, &sb) < 0){
	clicon_err(OE_DB, errno, "%s", running);
	goto done;
    }
    if (stat(candidate, &sb) < 0){
	clicon_err(OE_DB, errno, "%s", candidate);
	goto done;
    }
    memset(&df, 0, sizeof(df));

    /* Find the differences between the two databases and store it in dd vector. */
    if (db_diff(running, candidate,
		__FUNCTION__,
		clicon_dbspec_key(h),
		&df
	    ) < 0)
	goto done;
    /* 1. Get commit processing dbdiff vector: one entry per key that changed.
          changes are registered as if they exist in the 1st(candidate) or
	  2nd(running) dbs.
     */
    if (dbdep_commitvec(h, &df, &nvec, &ddvec) < 0)
	goto done;
    
    /* 2. Call plugin pre-commit hooks */
    if (plugin_begin_hooks(h, candidate) < 0)
	goto done;

    /* call generic cv_validate() on all new or changed keys. */
    if (generic_validate(h, candidate, &df) < 0)
	goto done;

    /* user-defined callbacks */
    if (validate_db(h, nvec, ddvec, candidate) < 0)
	goto done;

    /* Call plugin post-commit hooks */
    if (plugin_complete_hooks(h, candidate) < 0)
	goto done;

    /* Now follows commit rules in order.
    * 4. For all keys that are in candidate, delete key (from running). 
    */
    for (i = nvec-1; i >= 0; i--){
	dd = &ddvec[i];
	dfe = dd->dd_dbdiff; /* key1/key2/op */
	dp = dd->dd_dep;     /* op, callback, arg */
	if (dp->dp_type & TRANS_CB_COMMIT &&
	    dfe->dfe_op & DBDIFF_OP_FIRST &&
	    plugin_modify_key_value(h, running,        /* db */
				    dfe->dfe_key1,     /* key */
				    TRANS_CB_COMMIT, /* commit|validate */
				    LV_DELETE,         /* operation */
				    dp                 /* callback(arg) */
		) < 0){
	    firsterr = clicon_err_save(); /* save this error */
	    break;
	}
    }
    /* 5. Failed deletion of running, add the key value back (from running) */
    if (i >= 0){ /* failed */
	for (j=i+1; j<nvec; j++){ /* revert in opposite order */
	    dd = &ddvec[j];
	    dfe = dd->dd_dbdiff; /* key1/key2/op */
	    dp = dd->dd_dep;     /* op, callback, arg */
	    if (dp->dp_type & TRANS_CB_COMMIT &&
		dfe->dfe_op & DBDIFF_OP_FIRST &&
		plugin_modify_key_value(h, running,       /* db */
					dfe->dfe_key1,    /* key */
					TRANS_CB_COMMIT,  /* commit|validate */
					LV_SET,           /* operation */
					dp                 /* callback(arg) */
		    ) < 0)
		continue; /* ignore errors or signal major setback ? */
	}
	goto done;
    }

    /* 6. Set keys (from candidate) */
    for (i=0; i < nvec; i++){
	dd = &ddvec[i];
	dfe = dd->dd_dbdiff; /* key1/key2/op */
	dp = dd->dd_dep;     /* op, callback, arg */
	if (dp->dp_type & TRANS_CB_COMMIT &&
	    dfe->dfe_op & DBDIFF_OP_SECOND &&
	    plugin_modify_key_value(h, candidate,        /* db */
				    dfe->dfe_key2,     /* key */
				    TRANS_CB_COMMIT, /* commit|validate */
				    LV_SET,         /* operation */
				    dp                 /* callback(arg) */
		) < 0){
	    firsterr = clicon_err_save(); /* save this error */
	    failed++;
	    break;
	}
    }
    if (!failed)
	if (file_cp(candidate, running) < 0){
	    clicon_err(OE_UNIX, errno, "file_cp");
	    failed++;
	}
    /* 7. Failed setting keys in running, first remove the keys set */
    if (failed){ /* failed */
	for (j=i-1; j>=0; j--){ /* revert in opposite order */
	    dd = &ddvec[j];
	    dfe = dd->dd_dbdiff; /* key1/key2/op */
	    dp = dd->dd_dep;     /* op, callback, arg */
	    if (dp->dp_type & TRANS_CB_COMMIT &&
		dfe->dfe_op & DBDIFF_OP_SECOND &&
		plugin_modify_key_value(h, candidate,    /* db */
					dfe->dfe_key2,   /* key */
					TRANS_CB_COMMIT, /* commit|validate */
					LV_DELETE,       /* operation */
					dp               /* callback(arg) */
		    ) < 0)
		continue; /* ignore errors or signal major setback ? */
	}
	/* 7. Set back original running values */
	for (j=0; j < nvec; j++){ /* revert in opposite order */
	    dd = &ddvec[j];
	    dfe = dd->dd_dbdiff; /* key1/key2/op */
	    dp = dd->dd_dep;     /* op, callback, arg */
	    if (dp->dp_type & TRANS_CB_COMMIT &&
		dfe->dfe_op & DBDIFF_OP_FIRST &&
		plugin_modify_key_value(h, running,        /* db */
					dfe->dfe_key1,     /* key */
					TRANS_CB_COMMIT, /* commit|validate */
					LV_SET,         /* operation */
					dp                 /* callback(arg) */
		    ) < 0)
		continue; /* ignore errors or signal major setback ? */
	}
	goto done;
    }


    /* Copy running back to candidate in case end functions triggered 
       updates in running */
    /* XXX: check for errors */
    file_cp(running, candidate);

    /* Call plugin post-commit hooks */
    plugin_end_hooks(h, candidate);

    retval = 0;
  done:
    if (retval < 0) /* Call plugin fail-commit hooks */
	plugin_abort_hooks(h, candidate);
    if (ddvec)
	free(ddvec);
    unchunk_group(__FUNCTION__); 
    if (firsterr)
	clicon_err_restore(firsterr);
    return retval;
}