Ejemplo n.º 1
0
int EntryProc_db_flag_op( struct entry_proc_op_t *p_op, lmgr_t * lmgr )
{
    int            rc;

    /* insert to DB */
    switch ( p_op->db_op_type )
    {
        attr_set_t     attr_chg;
        lmgr_filter_t  filter;
        filter_value_t val;

    case OP_TYPE_UPDATE:
        /* set previous_scan flag */
        ATTR_MASK_INIT( &attr_chg );
        ATTR_MASK_SET( &attr_chg, previous_scan );
        ATTR( &attr_chg, previous_scan ) = TRUE;

        rc = ListMgr_MassUpdate( lmgr, NULL, &attr_chg );
        break;
    case OP_TYPE_REMOVE:
        val.val_bool = TRUE;
        lmgr_simple_filter_init( &filter );
        lmgr_simple_filter_add( &filter, ATTR_INDEX_previous_scan, EQUAL, val );

        /* remove entries with previous_scan flag */
        rc = ListMgr_MassRemove( lmgr, &filter );

        lmgr_simple_filter_free( &filter );
        break;
    default:
        printf( "unhandled\n" );
        rc = -1;
    }
    if ( rc )
        printf( "ERROR: ListMgr mass operation returned %d\n", rc );

    if ( p_op->callback_func )
        p_op->callback_func( lmgr, p_op, p_op->callback_param );

    rc = EntryProcessor_Acknowledge( p_op, 0, TRUE );

    return rc;
}
Ejemplo n.º 2
0
/**
 *  Initialize a recovery process.
 *  \param p_filter[in] (optional) filter partial filesystem recovery
 *  \retval DB_SUCCESS the recovery process successfully started;
 *          the stats indicate the recovery states we can expect.
 *  \retval DB_ALREADY_EXISTS a recovery process already started
 *          and was not properly completed. stats indicate the current status.
 *  \retval error   another error occurred.
 */
int ListMgr_RecovInit( lmgr_t * p_mgr, const lmgr_filter_t * p_filter, lmgr_recov_stat_t * p_stats )
{
    int  rc;
    db_value_t report_val;
    unsigned int nb;
    struct lmgr_report_t * report;
    report_field_descr_t report_count = {-1, REPORT_COUNT, SORT_NONE, false, 0, FV_NULL};

/** @TODO use glib strings */
    char           query[4096];
    char           filter_str[4096] = "";
    char          *filter_curr = filter_str;
    #define has_filters (filter_curr != filter_str)
    int            distinct = 0;

    rc = ListMgr_RecovStatus( p_mgr, p_stats );
    if (rc == 0)
    {
        if (p_stats->total != 0) /* RECOVERY table exists and is not empty */
            return DB_ALREADY_EXISTS;
    }
    else if ( rc != DB_NOT_EXISTS ) /* other error */
        return rc;

    if ( rc == 0 )
    {
        DisplayLog( LVL_EVENT, LISTMGR_TAG, "Dropping any previous "RECOV_TABLE" table" );
        /* start from clean state (no table, no indexes, no addl field) */
        rc = db_drop_component(&p_mgr->conn, DBOBJ_TABLE, RECOV_TABLE);
        if ( rc )
            return rc;
    }

    if ( p_filter )
    {
        /* dummy vars */
        char           filter_dir_str[512] = "";
        unsigned int   filter_dir_index = 0;

        if (dir_filter(p_mgr, filter_dir_str, p_filter, &filter_dir_index, NULL) != FILTERDIR_NONE)
        {
            DisplayLog( LVL_CRIT, LISTMGR_TAG, "Directory filter not supported for recovery");
            return DB_NOT_SUPPORTED;
        }

        if (filter2str(p_mgr, filter_curr, p_filter, T_MAIN, AOF_PREFIX) > 0)
            filter_curr += strlen(filter_curr);

        if (filter2str(p_mgr, filter_curr, p_filter, T_ANNEX,
                       (has_filters ? AOF_LEADING_SEP : 0) | AOF_PREFIX) > 0)
            filter_curr += strlen(filter_curr);

        if (filter2str(p_mgr, filter_curr, p_filter, T_DNAMES,
                       (has_filters ? AOF_LEADING_SEP : 0) | AOF_PREFIX) > 0)
        {
            filter_curr += strlen(filter_curr);
            distinct = 1;
        }

        if (filter2str(p_mgr, filter_curr, p_filter, T_STRIPE_INFO,
                       (has_filters ? AOF_LEADING_SEP : 0) | AOF_PREFIX) > 0)
            filter_curr += strlen(filter_curr);

        if (filter2str(p_mgr, filter_curr, p_filter, T_STRIPE_ITEMS,
                       (has_filters ? AOF_LEADING_SEP : 0) | AOF_PREFIX) > 0)
        {
            filter_curr += strlen(filter_curr);
            distinct = 1;
        }
    }


    DisplayLog( LVL_EVENT, LISTMGR_TAG, "Populating "RECOV_TABLE" table (this can take a few minutes)..." );

    /* create the recovery table */
    if (distinct)
    {
        /* need to select only 1 instance of each object when joining with STRIPE_ITEMS or NAMES */
        strcpy(query, "CREATE TABLE "RECOV_TABLE
            " SELECT DISTINCT("MAIN_TABLE".id)," BUILD_RECOV_LIST_FIELDS_NAMES
            " FROM "MAIN_TABLE" LEFT JOIN "ANNEX_TABLE" ON "
            "("MAIN_TABLE".id = "ANNEX_TABLE".id)"
            " LEFT JOIN "DNAMES_TABLE" ON "
            "("MAIN_TABLE".id = "DNAMES_TABLE".id)"
            " LEFT JOIN "STRIPE_INFO_TABLE" ON "
            "("MAIN_TABLE".id = "STRIPE_INFO_TABLE".id)"
            " LEFT JOIN "STRIPE_ITEMS_TABLE" ON "
            "("MAIN_TABLE".id = "STRIPE_ITEMS_TABLE".id)");
    }
    else
    {
        strcpy(query, "CREATE TABLE "RECOV_TABLE
            " SELECT "MAIN_TABLE".id," BUILD_RECOV_LIST_FIELDS
            " FROM "MAIN_TABLE" LEFT JOIN "ANNEX_TABLE" ON "
            "("MAIN_TABLE".id = "ANNEX_TABLE".id)"
            " LEFT JOIN "STRIPE_INFO_TABLE" ON "
            "("MAIN_TABLE".id = "STRIPE_INFO_TABLE".id)");
    }

    if (has_filters)
    {
        strcat(query, " WHERE ");
        strcat(query, filter_str);
    }

    /* the whole function is not atomic as we try to preserve the progress
     * in case of DB engine failure. So we retry each step independently.
     */
retry1:
    rc = db_exec_sql(&p_mgr->conn, query, NULL);
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry1;
    else if (rc)
        return rc;

    DisplayLog( LVL_EVENT, LISTMGR_TAG, "Building indexes on "RECOV_TABLE" table..." );

    /* create pk */
retry2:
    rc = db_exec_sql( &p_mgr->conn, "ALTER TABLE "RECOV_TABLE" ADD PRIMARY KEY (id)", NULL );
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry2;
    else if (rc)
        return rc;

    /* add recov_status column */
retry3:
    rc = db_exec_sql( &p_mgr->conn, "ALTER TABLE "RECOV_TABLE" ADD COLUMN recov_status INTEGER", NULL );
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry3;
    else if (rc)
        return rc;

    /* add index on status */
retry4:
    rc = db_exec_sql( &p_mgr->conn,
                      "CREATE INDEX recov_st_index ON "RECOV_TABLE"(recov_status)",
                      NULL );
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry4;
    else if (rc)
        return rc;

    /* count entries of each status */
    expected_recov_status( p_mgr, p_stats );

    /* if there is a filter on OSTs, report distinct ids */
    if (distinct)
        report_count.report_type = REPORT_COUNT_DISTINCT;

    /* double check entry count before deleting entries */
    report = ListMgr_Report(p_mgr, &report_count, 1, NULL, p_filter, NULL);
    if (report == NULL)
        return DB_REQUEST_FAILED;

    nb = 1;
    rc = ListMgr_GetNextReportItem(report, &report_val, &nb, NULL);
    ListMgr_CloseReport(report);

    if (rc)
        return rc;


    if ( nb == 0 )
        return DB_REQUEST_FAILED;

    if ( report_val.value_u.val_biguint != p_stats->total )
    {
        DisplayLog( LVL_CRIT, LISTMGR_TAG, "ERROR: recovery count (%llu) is different from entry count in main table (%lld): preserving entries",
                    p_stats->total,  report_val.value_u.val_biguint );
        return DB_REQUEST_FAILED;
    }

    /* clean previous DB content */

    return ListMgr_MassRemove( p_mgr, p_filter, NULL );
}