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; }
/** * 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 ); }