#############################################################  -*- c -*-
## generic include for XXX. Do not use directly.
##
## $Id: parent-set.m2i 12851 2005-09-27 15:43:39Z rstory $
########################################################################
@if $m2c_mark_boundary == 1@
/** START code generated by $RCSfile$ $Revision: 12851 $ */
@end@
########################################################################
##//####################################################################
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@if $m2c_processing_type eq 'h'@

int ${context}_undo_setup( ${context}_rowreq_ctx *rowreq_ctx);
int ${context}_undo_cleanup( ${context}_rowreq_ctx *rowreq_ctx);
int ${context}_undo( ${context}_rowreq_ctx *rowreq_ctx);
int ${context}_commit( ${context}_rowreq_ctx *rowreq_ctx);
int ${context}_undo_commit( ${context}_rowreq_ctx *rowreq_ctx);
@   if $m2c_irreversible_commit == 1@
int ${context}_irreversible_commit( ${context}_rowreq_ctx *rowreq_ctx);
@   end@

@end@ // m2c_processing_type eq 'h'
########################################################################
##//####################################################################
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@if $m2c_processing_type eq 'c'@
##
## MASTER COPY OF THIS FLOWCHART IS IN agent/helpers/baby_steps.c
##
    /*
     * NOTE: if you update this chart, please update the versions in
     *       local/mib2c-conf.d/parent-set.m2i
     *       agent/mibgroup/helpers/baby_steps.c
     * while you're at it.
     */
    /*
     ***********************************************************************
     * Baby Steps Flow Chart (2004.06.05)                                  *
     *                                                                     *
     * +--------------+    +================+    U = unconditional path    *
     * |optional state|    ||required state||    S = path for success      *
     * +--------------+    +================+    E = path for error        *
     ***********************************************************************
     *
     *                        +--------------+
     *                        |     pre      |
     *                        |   request    |
     *                        +--------------+
     *                               | U
@if $m2c_table_row_creation == 1@
     * +-------------+        +==============+
     * |    row    |f|<-------||  object    ||
     * |  create   |1|      E ||  lookup    ||
     * +-------------+        +==============+
     *     E |   | S                 | S
     *       |   +------------------>|
     *       |                +==============+
     *       |              E ||   check    ||
     *       |<---------------||   values   ||
@else@
     *                        +==============+
     *       +----------------||  object    ||
     *       |              E ||  lookup    ||
     *       |                +==============+
     *       |                       | S
     *       |                +==============+
     *       |              E ||   check    ||
     *       |<---------------||   values   ||
@end@ # row creation
     *       |                +==============+
     *       |                       | S
     *       |                +==============+
     *       |       +<-------||   undo     ||
     *       |       |      E ||   setup    ||
     *       |       |        +==============+
     *       |       |               | S
     *       |       |        +==============+
     *       |       |        ||    set     ||-------------------------->+
     *       |       |        ||   value    || E                         |
     *       |       |        +==============+                           |
     *       |       |               | S                                 |
     *       |       |        +--------------+                           |
     *       |       |        |    check     |-------------------------->|
     *       |       |        |  consistency | E                         |
     *       |       |        +--------------+                           |
     *       |       |               | S                                 |
     *       |       |        +==============+         +==============+  |
     *       |       |        ||   commit   ||-------->||     undo   ||  |
     *       |       |        ||            || E       ||    commit  ||  |
     *       |       |        +==============+         +==============+  |
     *       |       |               | S                     U |<--------+
     *       |       |        +--------------+         +==============+
     *       |       |        | irreversible |         ||    undo    ||
     *       |       |        |    commit    |         ||     set    ||
     *       |       |        +--------------+         +==============+
     *       |       |               | U                     U |
     *       |       +-------------->|<------------------------+
     *       |                +==============+
     *       |                ||   undo     ||
     *       |                ||  cleanup   ||
     *       |                +==============+
     *       +---------------------->| U
@if $m2c_table_row_creation == 1@
     *                               |
     *                          (err && f1)------------------->+
     *                               |                         |
     *                        +--------------+         +--------------+
     *                        |    post      |<--------|      row     |
     *                        |   request    |       U |    release   |
     *                        +--------------+         +--------------+
@else@
     *                        +--------------+
     *                        |    post      |
     *                        |   request    |
     *                        +--------------+
@end@ # row creation
     *
     */

##----------------------------------------------------------------------
/**
 * Setup up context with information needed to undo a set request.
 *
 * This function will be called before the individual node undo setup
 * functions are called. If you need to do any undo setup that is not
 * related to a specific column, you can do it here.
 *
@if $m2c_undo_embed == 0@
@   if $m2c_data_init == 1@
 * Note that the undo context has been allocated with
 * ${context}_allocate_data(), but may need extra
 * initialization similar to what you may have done in
 * ${context}_rowreq_ctx_init().
@   end@
@end@
 * Note that an individual node's undo_setup function will only be called
 * if that node is being set to a new value.
 *
 * If there is any setup specific to a particular column (e.g. allocating
 * memory for a string), you should do that setup in the node's undo_setup
 * function, so it won't be done unless it is necessary.
 *
 * @param rowreq_ctx
 *        Pointer to the table context (${context}_rowreq_ctx)
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error. set will fail.
 */
int
${context}_undo_setup( ${context}_rowreq_ctx *rowreq_ctx)
{
    int rc = MFD_SUCCESS;

    DEBUGMSGTL(("verbose:${context}:${context}_undo_setup","called\n"));

    /** we should have a non-NULL pointer */
    netsnmp_assert( NULL != rowreq_ctx );

    /*
     * TODO:451:M: |-> Setup $context undo.
     * set up $context undo information, in preparation for a set.
     * Undo storage is in ${m2c_ctx_lh}*
     */

    return rc;
} /* ${context}_undo_setup */

/**
 * Undo a set request.
 *
 * This function will be called before the individual node undo
 * functions are called. If you need to do any undo that is not
 * related to a specific column, you can do it here.
 *
 * Note that an individual node's undo function will only be called
 * if that node is being set to a new value.
 *
 * If there is anything  specific to a particular column (e.g. releasing
 * memory for a string), you should do that setup in the node's undo
 * function, so it won't be done unless it is necessary.
 *
 * @param rowreq_ctx
 *        Pointer to the table context (${context}_rowreq_ctx)
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error. set will fail.
 */
int
${context}_undo( ${context}_rowreq_ctx *rowreq_ctx)
{
    int rc = MFD_SUCCESS;

    DEBUGMSGTL(("verbose:${context}:${context}_undo","called\n"));

    /** we should have a non-NULL pointer */
    netsnmp_assert( NULL != rowreq_ctx );

    /*
     * TODO:451:M: |-> $context undo.
     * $context undo information, in response to a failed set.
     * Undo storage is in ${m2c_ctx_lh}*
     */

    return rc;
} /* ${context}_undo_setup */

/**
 * Cleanup up context undo information.
 *
 * This function will be called after set/commit processing. If you
 * allocated any resources in undo_setup, this is the place to release
 * those resources.
 *
 * This function is called regardless of the success or failure of the set
 * request. If you need to perform different steps for cleanup depending
 * on success or failure, you can add a flag to the rowreq_ctx.
 *
 * @param rowreq_ctx
 *        Pointer to the table context (${context}_rowreq_ctx)
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error
 */
int
${context}_undo_cleanup( ${context}_rowreq_ctx *rowreq_ctx)
{
    int rc = MFD_SUCCESS;

    DEBUGMSGTL(("verbose:${context}:${context}_undo_cleanup","called\n"));

    /** we should have a non-NULL pointer */
    netsnmp_assert( NULL != rowreq_ctx );

    /*
     * TODO:452:M: |-> Cleanup $context undo.
     * Undo storage is in ${m2c_ctx_lh}*
     */

    return rc;
} /* ${context}_undo_cleanup */

##----------------------------------------------------------------------
/**
 * commit new values.
 *
 * At this point, you should have done everything you can to ensure that
 * this commit will not fail.
 *
 * Should you need different behavior depending on which columns were
 * set, rowreq_ctx->column_set_flags will indicate which writeable columns were
 * set. The definitions for the COLUMN_*_FLAG bits can be found in
@if $m2c_create_fewer_files != 1@
 * ${context}_oids.h.
@else@
 * ${context}.h.
@end@
 * A new row will have the MFD_ROW_CREATED bit set in rowreq_flags.
 *
 * @param ${context}_rowreq_ctx
 *        Pointer to the users context.
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error
 */
int
${context}_commit( ${context}_rowreq_ctx *rowreq_ctx)
{
    int rc = MFD_SUCCESS;
    int             save_flags;

    DEBUGMSGTL(("verbose:${context}:${context}_commit","called\n"));

    /** we should have a non-NULL pointer */
    netsnmp_assert( NULL != rowreq_ctx );

    /*
     * save flags, then clear until we actually do something
     */
    save_flags = rowreq_ctx->column_set_flags;
    rowreq_ctx->column_set_flags = 0;

    /*
     * commit $context data
     * 1) check the column's flag in save_flags to see if it was set.
     * 2) clear the flag when you handle that column
     * 3) set the column's flag in column_set_flags if it needs undo
     *    processing in case of a failure.
     */
@   foreach $node nonindex@
@      include m2c_setup_node.m2i@
@      if $node.settable == 0@
@          next@
@      end@
    if (save_flags & COLUMN_$node.uc_FLAG) {
       save_flags &= ~COLUMN_$node.uc_FLAG; /* clear $node */
       /*
        * TODO:482:o: |-> commit column $node.
        */
       rc = -1;
       if(-1 == rc) {
           snmp_log(LOG_ERR,"$context column $node commit failed\n");
       }
       else {
            /*
             * set flag, in case we need to undo $node
             */
            rowreq_ctx->column_set_flags |= COLUMN_$node.uc_FLAG;
       }
    }

@   end@ # foreach $node
    /*
     * if we successfully commited this row, set the dirty flag.
     */
    if (MFD_SUCCESS == rc) {
        rowreq_ctx->rowreq_flags |= MFD_ROW_DIRTY;
    }

    if (save_flags) {
       snmp_log(LOG_ERR, "unhandled columns (0x%x) in commit\n", save_flags);
       return MFD_ERROR;
    }

    return rc;
} /* ${context}_commit */

/**
 * undo commit new values.
 *
 * Should you need different behavior depending on which columns were
 * set, rowreq_ctx->column_set_flags will indicate which writeable columns were
 * set. The definitions for the COLUMN_*_FLAG bits can be found in
@if $m2c_create_fewer_files != 1@
 * ${context}_oids.h.
@else@
 * ${context}.h.
@end@
 * A new row will have the MFD_ROW_CREATED bit set in rowreq_flags.
 *
 * @param ${context}_rowreq_ctx
 *        Pointer to the users context.
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : error
 */
int
${context}_undo_commit( ${context}_rowreq_ctx *rowreq_ctx)
{
    int rc = MFD_SUCCESS;

    DEBUGMSGTL(("verbose:${context}:${context}_undo_commit","called\n"));

    /** we should have a non-NULL pointer */
    netsnmp_assert( NULL != rowreq_ctx );

    /*
     * TODO:485:M: |-> Undo $context commit.
     * check the column's flag in rowreq_ctx->column_set_flags to see
     * if it was set during commit, then undo it.
     *
     * eg: if (rowreq_ctx->column_set_flags & COLUMN_$node.uc_FLAG) {}
     */

    
    /*
     * if we successfully un-commited this row, clear the dirty flag.
     */
    if (MFD_SUCCESS == rc) {
        rowreq_ctx->rowreq_flags &= ~MFD_ROW_DIRTY;
    }

    return rc;
} /* ${context}_undo_commit */

@if $m2c_irreversible_commit == 1@
##----------------------------------------------------------------------
/**
 * perform commit actions that are not reversible
 *
 * THERE IS NO ATTEMPT AT RECOVERY FOR ERRORS FROM THIS STATE!
 *
 * @param ${context}_rowreq_ctx
 *        Pointer to the users context.
 *
 * @retval MFD_SUCCESS : success
 * @retval MFD_ERROR   : other error
 */
int
${context}_irreversible_commit( ${context}_rowreq_ctx *rowreq_ctx)
{
    int rc;

    DEBUGMSGTL(("verbose:${context}:${context}_irreversible_commit","called\n"));

    /** we should have a non-NULL pointer */
    netsnmp_assert( NULL != rowreq_ctx );

    /*
     * TODO:495:o: Irreversible $context commit.
     */
##$example_start
##$example_end

    return MFD_SUCCESS;
} /* ${context}_irreversible_commit */

@end@ // irreversable commit
##
########################################################################
@end@ // m2c_processing_type eq 'c'
########################################################################
@if $m2c_mark_boundary == 1@
/** END code generated by $RCSfile$ $Revision: 12851 $ */
@end@
