Home > User Guide > Model Management
Failsafe Behavior
The usual behavior of an ACIS API function is to return an outcome object, which indicates the success or failure of the API. If the API encounters an error during its execution, the ENTITYs passed into the API are rolled back to their initial state, and the error code is returned as a failed outcome object ( outcome::ok() returns FALSE).
For certain APIs, such as tolerizing edges, this "all or nothing" behavior is undesired. For example, if a list of 100 edges is passed into api_check_edge_errors, then an error when tolerizing one of them should not prevent the tolerization of the other 99. For these special APIs, Spatial has introduced a failsafe behavior.
- Failsafe Behavior
- APIs with Failsafe Behavior
- Sample Code to Demonstrate How to Use the Failsafe Behavior of api_check_edge_errors
Failsafe Behavior
When an API is failsafe it will attempt to do as much as possible and not fail, even when it encounters errors during the operation. A failsafe API is broken up internally into atomic operations, for example tolerizing an individual edge in api_check_edge_errors. If a particular atomic operation raises an error in a failsafe API, that atomic operation is undone, an error_info object with severity SPA_OUTCOME_ERROR is added to the outcome (refer to the Error Handling Technical Article under Kernel Component), a flag is set that the API encountered an error in an atomic operation, and the failsafe API proceeds to the next atomic operation. In this case, the fact that an error occurred is signaled to the caller through the outcome::encountered_errors() method of the outcome, which returns TRUE. The outcome::ok() method also returns TRUE, indicating partial success.
Note that a body produced by a failsafe API that has encountered errors, may have errors. For example, any edges not tolerized (due to an error condition) by api_check_edge_errors will continue to have gap errors. A body being stitched by a call to api_stitch that encountered errors, may have open edges, gap errors, or other problems. If a caller prefers to have a failsafe API rollback to its original state when it encounters errors (that is, act as a non-failsafe API), then one can turn the failsafe behavior off by pushing a value of TRUE into the careful option before calling the API and popping it out after the API completes. When careful is TRUE, the failsafe behavior for all failsafe APIs is turned off.
Certain errors will cause a failsafe API to fail completely. These are usually programmatic errors in the input parameters, such as passing a NULL pointer in a place where a non-NULL pointer is expected, rather than geometric or topological faults in the input body. In this case outcome::ok() will return FALSE and outcome::encountered_errors() will return TRUE.
Customers can know the result of a failsafe API by using the return values of the following methods:
a. If outcome::encountered_errors() returns FALSE, then it means that the API has completely succeeded,that is neither errors were encountered nor unacceptable entities were detected by the API. outcome::ok() should always return TRUE in this case.
b. If outcome::ok() returns FALSE, then the API has failed and rolled the model back to the state before the API was called. outcome::encountered_errors() should always return TRUE in this case.
c. If the methods outcome::encountered_errors() and outcome::ok() return TRUE, then it means that the API has encountered error(s), yet it proceeded further successfully. This combination should only occur for failsafe APIs.
APIs with Failsafe Behavior
When running with an ACIS version of R12 or later,
are failsafe. In addition, the stitching portion of api_hh_auto_heal() is also failsafe. Errors encountered during the stitch phase of autoheal will be handled in a failsafe manner, while errors encountered outside the stitch phase are considered fatal (non-failsafe). These APIs behave in a non-failsafe manner when called with an ACIS version earlier than R12.
- the tolerant stitch API functions api_stitch(..,tolerant_stitch_options,..) and api_stitch(.., edge_tolstitch_options,..),
- api_hh_stitch_analyze(),
- api_hh_stitch_calculate(),
- api_hh_stitch_fix(),
- api_hh_stitch_auto() and
- the tolerization API functions api_check_edge_errors(), api_check_vertex_errors()
- the geometry simplification API function api_simplify_entity()
Sample Code to Demonstrate How to Use the Failsafe Behavior of api_check_edge_errors
This section contains snippets of C++ code to illustrate how to use the failsafe behavior of api_check_edge_errors. These snippets are designed to be very simple starting points for developing your own code - they are not complete, compiling and runtime programs.
The code snippet demonstrates the following:
- how to enable the failsafe behavior of api_check_edge_errors
- how to know the result of api_check_edge_errors
- how to identify edges that are classified bad and failed to tolerize when using api_check_edge_errors
#include "kernapi.hxx"
// User function
logical user-function (arguments ....)
{
...
// List of edges
ENTITY_LIST edges;
...
// User code to get the edges that are to be checked for errors
...
// List of bad edges and new tolerized edges
ENTITY_LIST bad_edges, new_edges;
ENTITY *worst_entity = NULL;
double worst_error = 0.0;
// Make the careful option OFF to enable failsafe behavior
// By default the "careful" option is OFF
option_header *careful_opt = find_option(careful);
if (NULL != careful_opt)
{
careful_opt->push(FALSE);
}
// Note: To disable the failsafe behavior, set the "careful" option ON (push TRUE)
// Call the api_check_edge_errors
outcome o_chk_errs = api_check_edge_errors(edges, // List of edges to be checked
bad_edges, // List of bad edges returned
worst_entity, // Worst entity returned
worst_error, // Worst error returned
SPAresabs, // Tolerance to use for checking
FALSE, // Do not stop immediately
new_edges, // List of new tolerized edges
NULL); // NULL AcisOptions
// Restore the original value of careful_opt
if (NULL != careful_opt)
{
careful_opt->pop();
}
// Check the result of api_check_edge_errors
if (!o_chk_errs.ok()) // This means the API has completely failed
{
// User may want to know about the fatal error due to which the API failed.
error_info* einf = o_chk_errs.get_error_info();
// User code to report information on errors. A sample function
// "display_problems_encountered" for such reporting is given at
// the bottom of the code snippet.
display_problems_encountered(einf);
// Reasons for error
if (einf->has_reasons())
{
// User code to mention that the following are reasons for the error,
// the user may print as
printf("Following are the reasons for the error: \n");
// error_info_list owns all the error_info objects inside it and cleans
// them up on destruction. User need not worry about memory cleanup of
// the error_info objects.
error_info_list reasons_eil;
einf->reasons(reasons_eil);
const error_info* reason_einf = NULL;
for ( reasons_eil.init(); NULL != (reason_einf = reasons_eil.next()); )
{
display_problems_encountered(reason_einf);
}
}
// User code to handle failure of api_check_edge_errors
...
}
else if (o_chk_errs.encountered_errors()) // This means the API has succeeded, but proceeded after errors
{
// User may want to handle this situation separately
// May be to detect edges that are checked bad, but not tolerized
EDGE *checked_edge = NULL;
for (new_edges.init(); NULL != (checked_edge = (EDGE *)new_edges.next()) ; )
{
if (FALSE == is_TEDGE(checked_edge))
{
// User code to handle edge that is bad and not tolerized
...
}
}
}
// Problem reporting by API.
error_info_list eil;
o_chk_errs.get_error_info_list(eil);
const error_info* einf = NULL;
for ( eil.init(); NULL != (einf = eil.next()); )
{
// User code to report information on problems. A sample function
// "display_problems_encountered" for such reporting is given at
// the bottom of the code snippet.
display_problems_encountered(einf);
// Reasons for the problem
if (einf->has_reasons())
{
// User code to mention that the following are reasons for the problem,
// the user may print as
printf("Following are the reasons for the problem: \n");
// error_info_list owns all the error_info objects inside it and cleans
// them up on destruction. User need not worry about memory cleanup of
// the error_info objects.
error_info_list reasons_eil;
einf->reasons(reasons_eil);
const error_info* reason_einf = NULL;
for ( reasons_eil.init(); NULL != (reason_einf = reasons_eil.next()); )
{
display_problems_encountered(reason_einf);
}
}
}
...
// Rest of the user code
...
}
// Utility function for displaying entity_error_info based problems encountered by
// api_check_edge_errors
void display_problems_encountered(const error_info *einf)
{
if ( NULL == einf )
{ return;}
char const *err_message = einf->error_message();
spa_outcome_severity_type err_severity = einf->severity();
// User code to display message and severity
// for example, the user can do the following
printf("Problem encountered: %s\n", err_message);
if (SPA_OUTCOME_FATAL == err_severity)
// Represents a fatal error
{ printf("Severity: FATAL \n"); }
else if (SPA_OUTCOME_ERROR == err_severity)
// Represents an error encountered by a failsafe routine during an atomic operation
{ printf("Severity: ERROR \n"); }
else if (SPA_OUTCOME_PROBLEM == err_severity)
// Represents a problem encountered during an operation
{ printf("Severity: PROBLEM \n"); }
else if (SPA_OUTCOME_INSANITY == err_severity)
// Represents an insanity in the model
{ printf("Severity: INSANITY \n"); }
int ent_id_cnt = get_error_info_entity_id_count(einf);
// If ent_id_cnt returns positive count,
// then einf has atleast one entity, dead or live
if ( 0 < ent_id_cnt && einf->type() == entity_error_info::id() )
{
const entity_error_info* ent_einf = (const entity_error_info *)einf;
if ( /* the user wants to report problems on dead entities too */ )
// LIVE and DEAD entities
{
for (int i = 0; i < ent_id_cnt; i++)
{
tag_id_type ent_id = ent_einf->get_entity_id(i);
ENTITY *err_entity = NULL;
outcome res_get_ent = api_get_entity_from_id(ent_id, err_entity);
if ( !res_get_ent.ok() )
{
// Handle API failure and continue or exit as user thinks suitable
...
}
if (NULL != err_entity) // err_entity is LIVE
{
// User code to report a live entity associated with a problem,
// for example the user may want to highlight the entity
}
else
{
// Report problem for a dead entity
}
}
}
else
// Only LIVE entities
{
ENTITY_LIST live_entities;
ent_einf->get_entities_alive(live_entities);
ENTITY *live_err_entity = NULL;
for (live_entities.init(); NULL != (live_err_entity = live_entities.next()); )
{
// User code to report a live entity associated with a problem,
// for example the user may want to highlight the entity
}
}
}
}[Top]
© 1989-2007 Spatial Corp., a Dassault Systèmes company. All rights reserved.