Пример #1
0
static int recov_status(void)
{
    int rc;
    lmgr_recov_stat_t stats;

    rc = ListMgr_RecovStatus(&lmgr, &stats);
    if (rc) {
        if (rc == DB_NOT_EXISTS)
            fprintf(stderr, "ERROR: There is no pending recovery\n");
        return rc;
    }

    printf("Current recovery status:\n");
    print_recov_stats(false, &stats);
    printf("\n");
    return 0;
}
Пример #2
0
static int recov_reset(int force)
{
    int rc;

    /* ask confirmation */
    if ( !force )
    {
        lmgr_recov_stat_t stats;
        char * buff = malloc(1024);
        size_t sz = 1024;

        rc = ListMgr_RecovStatus( &lmgr, &stats );
        if (rc)
        {
            if ( rc == DB_NOT_EXISTS )
                fprintf( stderr, "ERROR: There is no pending recovery\n" );
            return rc;
        }

        printf( "\nWARNING: you are about to abort the current recovery.\n" );
        printf( "All entries not yet recovered will be definitely lost!\n\n");

        printf( "Current recovery status:\n");
        print_recov_stats( FALSE, &stats );
        printf("\n");

        do {
            printf( "Do you really want to proceed [y/n]: " );
            if ( getline( &buff, &sz, stdin ) > 0 )
            {
                if ( !strcasecmp(buff, "y\n") || !strcasecmp(buff, "yes\n") )
                    break;
                else
                {
                    printf("Aborted\n");
                    free(buff);
                    return -ECANCELED;
                }
            }
        } while(1);
        free(buff);
    }
    return ListMgr_RecovReset( &lmgr );
}
Пример #3
0
int ListMgr_RecovComplete( lmgr_t * p_mgr, lmgr_recov_stat_t * p_stats )
{
    long long int diff;
    int rc;

    /* Check there is no more unprocessed entries */
    rc = ListMgr_RecovStatus( p_mgr, p_stats );
    if (rc)
        return rc;

    diff = p_stats->total - p_stats->status_count[RS_FILE_OK] - p_stats->status_count[RS_FILE_DELTA]
            - p_stats->status_count[RS_FILE_EMPTY] - p_stats->status_count[RS_NON_FILE]
           - p_stats->status_count[RS_NOBACKUP] - p_stats->status_count[RS_ERROR];
    if (diff > 0)
    {
        DisplayLog( LVL_CRIT, LISTMGR_TAG, "Cannot complete recovery: there are still %lld unprocessed files",
                    diff );
        return DB_NOT_ALLOWED;
    }
    /* clear all */
    return ListMgr_RecovReset( p_mgr );
}
Пример #4
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 );
}