Example #1
0
int lmgr_commit( lmgr_t * p_mgr )
{
    if ( lmgr_config.commit_behavior == 0 )
        return DB_SUCCESS;
    else if ( lmgr_config.commit_behavior == 1 )
        return db_exec_sql( &p_mgr->conn, "COMMIT", NULL );
    else
    {
        /* if the transaction count is reached:
         * commit operations and result transction count
         */
        if ( ( p_mgr->last_commit % lmgr_config.commit_behavior == 0 ) || p_mgr->force_commit )
        {
            int            rc;
            rc = db_exec_sql( &p_mgr->conn, "COMMIT", NULL );
            if ( rc )
                return rc;

            p_mgr->last_commit = 0;
        }
    }
    return DB_SUCCESS;
}
Example #2
0
int lmgr_get_var(db_conn_t *pconn, const char *varname, char *value, int bufsize)
{
    int             rc;
    result_handle_t result;
    char           *str_val = NULL;
    GString        *req = NULL;

    if (!varname || !value)
        return DB_INVALID_ARG;

    req = g_string_new("SELECT value FROM "VAR_TABLE" WHERE varname=");
    g_string_append_printf(req, "'%s'", varname);

    /* execute the request */
    rc = db_exec_sql(pconn, req->str, &result);
    if (rc)
        goto free_str;

    rc = db_next_record(pconn, &result, &str_val, 1);

    if (rc == DB_END_OF_LIST)
        rc = DB_NOT_EXISTS;

    if (rc)
        goto free_res;

    if (str_val == NULL)
    {
        rc = DB_REQUEST_FAILED;
        goto free_res;
    }

    /* copy the result */
    if (strlen(str_val) >= bufsize)
    {
        rc = DB_BUFFER_TOO_SMALL;
    }
    else
    {
        strcpy(value, str_val);
        rc = DB_SUCCESS;
    }

free_res:
    db_result_free(pconn, &result);
free_str:
    g_string_free(req, TRUE);
    return rc;
}
Example #3
0
/**
 *  Continue a recovery process (returns an iterator on entry list),
 *  possibly using the specified filter.
 *  \retval iterator must be release using ListMgr_CloseIterator()
 */
struct lmgr_iterator_t * ListMgr_RecovResume( lmgr_t * p_mgr,
                                              const char * dir_path,
                                              int retry, /* also retry previously erroneous entries */
                                              const lmgr_iter_opt_t * p_opt )
{
    char query[4096];
    char * curr;
    lmgr_iterator_t * it;
    int rc;

    strcpy( query, "SELECT id,recov_status,"GET_RECOV_LIST_FIELDS" FROM "RECOV_TABLE" WHERE " );
    curr = query + strlen(query);
    if ( retry )
        curr += sprintf( curr, "(recov_status IS NULL OR recov_status=%u)",
                         RS_ERROR );
    else
        curr += sprintf( curr, "recov_status IS NULL" );

    if ( dir_path )
    {
        char rel[RBH_PATH_MAX] = "";
        /* Recovery table contains path from DB (<root_id>/<rel_path>),
         * and dirpath is absolute. So convert it. */
        if (fullpath_attr2db(dir_path, rel))
            return NULL;
#ifdef _MYSQL
        /* MySQL is case insensitive.
         * To force case-sensitivity, use BINARY keyword. */
        curr += sprintf( curr, " AND relpath LIKE BINARY '%s/%%'", rel );
#else
        curr += sprintf( curr, " AND relpath LIKE '%s/%%'", rel );
#endif
    }

    /* allocate a new iterator */
    it = ( lmgr_iterator_t * ) MemAlloc( sizeof( lmgr_iterator_t ) );
    it->p_mgr = p_mgr;

    /* execute request */
    rc = db_exec_sql( &p_mgr->conn, query, &it->select_result );

    if ( rc )
    {
        MemFree( it );
        return NULL;
    }
    else
        return it;
}
Example #4
0
int lmgr_flush_commit( lmgr_t * p_mgr )
{
    int            rc;
    if ( ( lmgr_config.commit_behavior > 1 ) && ( p_mgr->last_commit != 0 ) )
    {
        rc = db_exec_sql( &p_mgr->conn, "COMMIT", NULL );
        if ( rc )
            return rc;

        p_mgr->last_commit = 0;
        return DB_SUCCESS;
    }
    else
        return DB_SUCCESS;
}
Example #5
0
/* Retrieve the FID from the database given the parent FID and the file name. */
int ListMgr_Get_FID_from_Path( lmgr_t * p_mgr, const entry_id_t * parent_fid,
                               const char *name, entry_id_t * fid)
{
    result_handle_t result;
    GString        *req = NULL;
    char            escaped[RBH_NAME_MAX*2+1];
    DEF_PK(pk);
    int rc;
    char            *str_info[1];
    int             retry_status;

    entry_id2pk(parent_fid, PTR_PK(pk));

    db_escape_string(&p_mgr->conn, escaped, sizeof(escaped), name);

    req = g_string_new("SELECT id FROM "DNAMES_TABLE" WHERE pkn=");
    g_string_append_printf(req, HNAME_FMT, pk, escaped);

retry:
    rc = db_exec_sql(&p_mgr->conn, req->str, &result);
    retry_status = lmgr_delayed_retry(p_mgr, rc);
    if (retry_status == 1)
        goto retry;
    else if (retry_status == 2) {
        rc = DB_RBH_SIG_SHUTDOWN;
        goto free_str;
    } else if (rc)
        goto free_str;

    rc = db_next_record(&p_mgr->conn, &result, str_info, 1);

    retry_status = lmgr_delayed_retry(p_mgr, rc);
    if (retry_status == 1)
        goto retry;
    else if (retry_status == 2) {
        rc = DB_RBH_SIG_SHUTDOWN;
        goto free_res;
    } else if (rc != DB_SUCCESS)
        goto free_res;

    rc = pk2entry_id(p_mgr, str_info[0], fid);

free_res:
    db_result_free(&p_mgr->conn, &result);
free_str:
    g_string_free(req, TRUE);
    return rc;
}
Example #6
0
/* check that validator is matching for a given entry */
int ListMgr_CheckStripe( lmgr_t * p_mgr, const entry_id_t * p_id )
{
    char           query[1024];
    char          *res;
    result_handle_t result;
    int            rc = DB_SUCCESS;
    DEF_PK(pk);

    rc = entry_id2pk( p_mgr, p_id, FALSE, PTR_PK(pk) );
    if (rc)
        return rc;

    sprintf( query, "SELECT validator FROM " STRIPE_INFO_TABLE " WHERE id="DPK, pk );

    rc = db_exec_sql( &p_mgr->conn, query, &result );
    if ( rc )
        goto out;

    rc = db_next_record( &p_mgr->conn, &result, &res, 1 );

    if ( rc == DB_END_OF_LIST )
        rc = DB_NOT_EXISTS;

    if ( rc )
        goto res_free;

    if ( res == NULL )
    {
        rc = DB_ATTR_MISSING;
        goto res_free;
    }

    if ( atoi( res ) != VALID(p_id) )
    {
        delete_stipe_info( p_mgr, pk );
        rc = DB_OUT_OF_DATE;
    }
    else
        rc = DB_SUCCESS;

  res_free:
    db_result_free( &p_mgr->conn, &result );
  out:
    return rc;
}
Example #7
0
fsal_posixdb_status_t fsal_posixdb_deleteHandle(fsal_posixdb_conn * p_conn,     /* IN */
                                                posixfsal_handle_t *
                                                p_parent_directory_handle /* IN */ )
{
/*    char           handleid_str[MAX_HANDLEIDSTR_SIZE];
    char           handlets_str[MAX_HANDLETSSTR_SIZE];
    const char    *paramValues[2]; */
  int found;
  result_handle_t res;
  fsal_posixdb_status_t st;
  char query[2048];

  BeginTransaction(p_conn);

  LogFullDebug(COMPONENT_FSAL, "Deleting %llu.%u\n", p_parent_directory_handle->data.id,
         p_parent_directory_handle->data.ts);

  snprintf(query, 2048,
           "SELECT Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype "
           "FROM Handle WHERE handleid=%llu AND handlets=%u FOR UPDATE",
           p_parent_directory_handle->data.id, p_parent_directory_handle->data.ts);

  st = db_exec_sql(p_conn, query, &res);
  if(FSAL_POSIXDB_IS_ERROR(st))
    goto rollback;

  found = mysql_num_rows(res);
  mysql_free_result(res);

  if(found)
    {
      /* entry found */
      st = fsal_posixdb_recursiveDelete(p_conn, p_parent_directory_handle->data.id,
                                        p_parent_directory_handle->data.ts, FSAL_TYPE_DIR);
      if(FSAL_POSIXDB_IS_ERROR(st))
        goto rollback;
    }

  return EndTransaction(p_conn);

 rollback:
  RollbackTransaction(p_conn);
  return st;

}
Example #8
0
/**
 *  List entries by recovery status.
 *  \param st type of entries to be listed
 *  (done, failed, to be done, all)
 */
struct lmgr_iterator_t * ListMgr_RecovList( lmgr_t * p_mgr,recov_type_e st )
{
    char query[4096];
    char * curr;
    lmgr_iterator_t * it;
    int rc;

    strcpy( query, "SELECT id,recov_status,"GET_RECOV_LIST_FIELDS" FROM "RECOV_TABLE );
    curr = query + strlen(query);
    switch(st)
    {
        case RT_ALL:
            /* add no filter */
            break;
        case RT_TODO:
            strcpy(curr, " WHERE recov_status is NULL");
            break;
        case RT_DONE:
            sprintf(curr, " WHERE recov_status in (%u, %u, %u, %u, %u)",
                    RS_FILE_OK, RS_FILE_DELTA, RS_FILE_EMPTY, RS_NON_FILE, RS_NOBACKUP );
            break;
        case RT_FAILED:
            sprintf(curr, " WHERE recov_status=%u", RS_ERROR);
            break;
    }

    /* allocate a new iterator */
    it = ( lmgr_iterator_t * ) MemAlloc( sizeof( lmgr_iterator_t ) );
    it->p_mgr = p_mgr;

    /* execute request */
    rc = db_exec_sql( &p_mgr->conn, query, &it->select_result );

    if ( rc )
    {
        MemFree( it );
        return NULL;
    }
    else
        return it;
}
Example #9
0
int ListMgr_Exists(lmgr_t *p_mgr, const entry_id_t *p_id)
{
    GString        *req;
    int             rc;
    result_handle_t result;
    char           *str_count = NULL;
    DEF_PK(pk);

    /* retrieve primary key */
    entry_id2pk(p_id, PTR_PK(pk));

    /* verify it exists in main table */
    req = g_string_new("SELECT id FROM " MAIN_TABLE " WHERE id=");
    g_string_append_printf(req, DPK, pk);

retry:
    /* execute the request (must return negative value on error) */
    rc = -db_exec_sql(&p_mgr->conn, req->str, &result);
    if (lmgr_delayed_retry(p_mgr, -rc))
        goto retry;
    else if (rc)
        goto free_str;

    rc = db_next_record(&p_mgr->conn, &result, &str_count, 1);
    if (rc == 0)
        rc = 1; /* return 1 if entry exists */
    else if (rc != DB_END_OF_LIST)
    {
        if (lmgr_delayed_retry(p_mgr, -rc))
            goto retry;
    }
    else
        rc = 0;

    db_result_free(&p_mgr->conn, &result);

free_str:
    g_string_free(req, TRUE);
    return rc;
}
Example #10
0
int ListMgr_Exists( lmgr_t * p_mgr, const entry_id_t * p_id )
{
    char           request[4096];
    int            rc;
    result_handle_t result;
    char          *str_count = NULL;
    DEF_PK( pk );

    /* retrieve primary key */
    entry_id2pk(p_id, PTR_PK(pk));

    /* verify it exists in main table */

    sprintf( request, "SELECT id FROM " MAIN_TABLE " WHERE id="DPK, pk );

retry:
    /* execute the request */
    rc = db_exec_sql(&p_mgr->conn, request, &result);
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    else if (rc)
        return -rc;

    rc = db_next_record( &p_mgr->conn, &result, &str_count, 1 );
    if (rc == 0)
        rc = 1;
    else if (rc != DB_END_OF_LIST)
    {
        if (lmgr_delayed_retry(p_mgr, rc))
            goto retry;
        rc = -rc;
    }
    else
        rc = 0;

    db_result_free( &p_mgr->conn, &result );
    return rc;
}
Example #11
0
/* Retrieve the FID from the database given the parent FID and the file name. */
int ListMgr_Get_FID_from_Path( lmgr_t * p_mgr, const entry_id_t * parent_fid,
                               const char *name, entry_id_t * fid)
{
    result_handle_t result;
    char           query[4096];
    char           escaped[RBH_NAME_MAX*2];
    DEF_PK(pk);
    int rc;
    char            *str_info[1];

    entry_id2pk(parent_fid, PTR_PK(pk));

    db_escape_string(&p_mgr->conn, escaped, RBH_NAME_MAX*2, name);

    sprintf(query, "SELECT id FROM "DNAMES_TABLE" WHERE pkn="HNAME_FMT,
            pk, escaped);

retry:
    rc = db_exec_sql(&p_mgr->conn, query, &result);
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    else if (rc)
        return rc;

    rc = db_next_record( &p_mgr->conn, &result, str_info, 1 );

    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    else if (rc != DB_SUCCESS)
        goto free_res;

    rc = pk2entry_id(p_mgr, str_info[0], fid);

  free_res:
    db_result_free( &p_mgr->conn, &result );
    return rc;
}
Example #12
0
int ListMgr_EntryCount(lmgr_t * p_mgr, uint64_t *count)
{
    int            rc;
    result_handle_t result;
    char          *str_count = NULL;

    /* execute the request */
retry:
    rc = db_exec_sql( &p_mgr->conn, "SELECT COUNT(*) FROM " MAIN_TABLE, &result );
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    else if (rc)
        return rc;

    rc = db_next_record( &p_mgr->conn, &result, &str_count, 1 );
    if (rc)
        return rc;

    if ( sscanf( str_count, "%"SCNu64, count ) != 1 )
        rc = DB_REQUEST_FAILED;

    db_result_free( &p_mgr->conn, &result );
    return rc;
}
Example #13
0
int insert_stripe_info( lmgr_t * p_mgr, PK_ARG_T pk, 
                        int validator, const stripe_info_t * p_stripe,
                        const stripe_items_t * p_items,
                        int update_if_exists )
{
    int            i, rc;
    int            created = FALSE;

    if ( p_stripe == NULL )
        return DB_INVALID_ARG;

    do
    {
        char short_query[4096];
        /* First insert info into STRIPE_INFO_TABLE,
         * so if a file is already present with the same id,
         * we will remove its previous stripe info */

        sprintf( short_query, "INSERT INTO " STRIPE_INFO_TABLE
                 "(id,validator, stripe_count,stripe_size,pool_name) "
                 "VALUES ("DPK",%u,%u,%u,'%s')", pk, validator,
                 p_stripe->stripe_count, ( unsigned int ) p_stripe->stripe_size,
                 p_stripe->pool_name );

        if ( update_if_exists )
            rc = db_exec_sql_quiet( &p_mgr->conn, short_query, NULL );
        else
            rc = db_exec_sql( &p_mgr->conn, short_query, NULL );

        if ( rc == 0 )
        {
            created = TRUE;
        }
        else if ( (rc == DB_ALREADY_EXISTS) && update_if_exists )
        {
            /* remove previous stripe info */
            DisplayLog( LVL_EVENT, LISTMGR_TAG,
                        "A stripe info already exists with this identifier, removing it" );
            rc = delete_stipe_info( p_mgr, pk );
        }

        if ( rc != 0 )
        {
            DisplayLog( LVL_CRIT, LISTMGR_TAG,
                        "DB query failed in %s line %d: code=%d: %s",
                        __FUNCTION__, __LINE__, rc, db_errmsg( &p_mgr->conn, short_query, 4096 ) );
            return rc;
        }

    }
    while ( !created );         /* retry loop in case a similar entry already exists */

    /* then insert stripe items */
    if ( (p_items != NULL) && (p_items->count > 0) )
    {
        ssize_t         len;
        unsigned int    est_len;
        char            *query = NULL;
        
        /* estimate query size = fix part + stripe_count * ( 4 + pklen + ost_idx_len )
         *                     = ~64(oversize to 128) + stripe_count * 4 + 128
         */
        est_len = 128 + p_items->count * 128;
        DisplayLog( LVL_FULL, LISTMGR_TAG, "Estimated query size for %u stripe = %u",  p_items->count, est_len );
        query = MemAlloc(est_len);
        if (query == NULL) {
            DisplayLog( LVL_CRIT, LISTMGR_TAG, "Not enough memory to build SQL query (length = %u)", est_len );
            return DB_NO_MEMORY;
        }

        strcpy( query, "INSERT INTO " STRIPE_ITEMS_TABLE "(id, storage_item) VALUES " );
        len = strlen( query );

        /* first stripe item */
        len += snprintf( query + len, est_len - len, "("DPK",%u)", pk, p_items->stripe_units[0] );

        /* next items */
        for ( i = 1; i < p_items->count; i++ )
        {
            len += snprintf( query + len, est_len - len, ",("DPK",%u)", pk, p_items->stripe_units[i] );

            if ( len >= est_len )
            {
                DisplayLog( LVL_CRIT, LISTMGR_TAG,
                            "Error in %s(): query too long (>%u bytes long), stripe_count=%d",
                            __FUNCTION__, est_len, p_items->count );
                MemFree( query );
                return DB_BUFFER_TOO_SMALL;
            }
        }

        rc = db_exec_sql( &p_mgr->conn, query, NULL );
        if ( rc )
        {
            DisplayLog( LVL_CRIT, LISTMGR_TAG,
                        "DB query failed in %s line %d: code=%d: %s",
                        __FUNCTION__, __LINE__, rc, db_errmsg( &p_mgr->conn, query, 4096 ) );
            MemFree( query );
            return rc;
        }
        MemFree( query );
    }

    return 0;
}
Example #14
0
int listmgr_batch_insert_no_tx(lmgr_t * p_mgr, entry_id_t **p_ids,
                               attr_set_t **p_attrs,
                               unsigned int count,
                               int update_if_exists)
{
    int            rc = 0;
    int            i, full_mask;
    char           fields[1024]; /* field list */
    pktype        *pklist = NULL;
    var_str        query = VAR_STR_NULL;
    char           values[4096] = "";
    char          *values_curr = NULL;
    bool           first;
    /* fake attribute struct, to write generic name fields */
    attr_set_t fake_attrs = *(p_attrs[0]);

    full_mask = sum_masks(p_attrs, count, ~0);
    fake_attrs.attr_mask = full_mask;

    pklist = (pktype *)MemCalloc(count, sizeof(pktype));
    if (pklist == NULL)
        return DB_NO_MEMORY;

    for (i = 0; i < count; i++)
    {
        /* check attr mask */
        if (!lmgr_batch_compat(full_mask, p_attrs[i]->attr_mask))
        {
            DisplayLog(LVL_MAJOR, LISTMGR_TAG, "Incompatible attr mask in batched operation: %#x vs. %#x",
                       p_attrs[i]->attr_mask, full_mask);
            rc = DB_INVALID_ARG;
            goto out_free;
        }
        /* fill pk array */
        entry_id2pk(p_ids[i], PTR_PK(pklist[i])); /* The same for all tables? */
    }

    /* build batch request for main table */
    attrmask2fieldlist(fields, full_mask, T_MAIN, TRUE, FALSE, "", "");

    var_str_append(&query, "INSERT INTO " MAIN_TABLE "(id");
    var_str_append(&query, fields);
    var_str_append(&query, ") VALUES ");

    first = true;
    for (i = 0; i < count; i++)
    {
        /* don't set this entry if no attribute is in main table */
        if ((p_attrs[i]->attr_mask & main_attr_set) == 0)
            continue;

        values_curr = values + sprintf(values, DPK, pklist[i]);
        attrset2valuelist(p_mgr, values_curr, p_attrs[i], T_MAIN, TRUE);

        /* add "[,](values)" to query */
        var_str_append(&query, first ? "(" : ",(");
        var_str_append(&query, values);
        var_str_append(&query, ")");
        first = false;
    }

    if (update_if_exists)
    {
        /* append "on duplicate key ..." */
        attrset2updatelist(p_mgr, values, &fake_attrs, T_MAIN, FALSE, TRUE);
        var_str_append(&query, " ON DUPLICATE KEY UPDATE ");
        var_str_append(&query, values);
    }

    rc = db_exec_sql(&p_mgr->conn, VAR_STR_START(query), NULL);
    if (rc)
        goto out_free;

    var_str_reset(&query);

    /* allow inserting entries in MAIN_TABLE, without name information */

    /* both parent and name are defined */
    if ((full_mask & ATTR_MASK_name) && (full_mask & ATTR_MASK_parent_id))
    {
        /* build batch request for names table */
        attrmask2fieldlist(fields, full_mask, T_DNAMES, TRUE, FALSE, "", "");

        var_str_append(&query, "INSERT INTO " DNAMES_TABLE "(id");
        var_str_append(&query, fields);
        var_str_append(&query, ",pkn) VALUES ");

        first = true;
        for (i = 0; i < count; i++)
        {
            /* don't set this entry if parent or name is missing */
            if (!ATTR_MASK_TEST(p_attrs[i], name) || !ATTR_MASK_TEST(p_attrs[i], parent_id))
            {
                /* warn for create operations without name information */
                if (!update_if_exists)
                    no_name_warning(pklist[i], p_attrs[i], 1);

                continue;
            }

            values_curr = values + sprintf(values, DPK, pklist[i]);
            attrset2valuelist(p_mgr, values_curr, p_attrs[i], T_DNAMES, TRUE);

            /* add "[,](values,<pk>)" to query */
            var_str_append(&query, first ? "(" : ",(");
            var_str_append(&query, values);
            var_str_append(&query, ","HNAME_DEF")");
            first = false;
        }

        values_curr = values + sprintf(values, "id=VALUES(id)"); /* not part of the PK */
        attrset2updatelist(p_mgr, values_curr, &fake_attrs, T_DNAMES, TRUE, TRUE);
        var_str_append(&query, " ON DUPLICATE KEY UPDATE ");
        var_str_append(&query, values);

        rc = db_exec_sql(&p_mgr->conn, VAR_STR_START(query), NULL);
        if (rc)
            goto out_free;

    } else if (!update_if_exists) { /* only warn for create operations */

        /* if we get here, the name information is missing in all fields.
         * use entry[0] as example for the warning message. */
        no_name_warning(pklist[0], p_attrs[0], count);
    }

    var_str_reset(&query);

    /* insert all info in annex table, if any */
    if (annex_table && (full_mask & annex_attr_set))
    {
        /* Create field and values lists.
         * Do nothing if no fields are to be set.
         */
        if (attrmask2fieldlist(fields, full_mask, T_ANNEX, TRUE, FALSE, "", "") > 0)
        {

            var_str_append(&query, "INSERT INTO "ANNEX_TABLE "(id");
            var_str_append(&query, fields);
            var_str_append(&query, ") VALUES ");

            first = true;
            for (i = 0; i < count; i++)
            {
                char           values[4096] = "";
                char          *values_curr = NULL;

                /* don't set this entry if no attribute is in annex table */
                if ((p_attrs[i]->attr_mask & annex_attr_set) == 0)
                    continue;

                sprintf(values, DPK, pklist[i]);
                values_curr = values + strlen(values);
                attrset2valuelist(p_mgr, values_curr, p_attrs[i], T_ANNEX, TRUE);

                /* add "[,](values)" to query */
                var_str_append(&query, first ? "(" : ",(");
                var_str_append(&query, values);
                var_str_append(&query, ")");
                first = false;
            }

            /* always update as having the entry in the main table
             * is the reference to know if we knew the entry */
            /* append "on duplicate key ..." */
            attrset2updatelist(p_mgr, values, &fake_attrs, T_ANNEX, FALSE, TRUE);
            var_str_append(&query, " ON DUPLICATE KEY UPDATE ");
            var_str_append(&query, values);

            rc = db_exec_sql(&p_mgr->conn, VAR_STR_START(query), NULL);
            if (rc)
                goto out_free;
        }
    }

#ifdef _LUSTRE
    /* batch insert of striping info */
    if (ATTR_MASK_TEST(&fake_attrs, stripe_info) || ATTR_MASK_TEST(&fake_attrs, stripe_items))
    {
        /* create validator list */
        int *validators = (int*)MemCalloc(count, sizeof(int));
        if (!validators)
        {
            rc =  DB_NO_MEMORY;
            goto out_free;
        }
        for (i = 0; i < count; i++)
#ifdef HAVE_LLAPI_FSWAP_LAYOUTS
            validators[i] = ATTR_MASK_TEST(p_attrs[i], stripe_info)?
                                ATTR(p_attrs[i],stripe_info).validator:VALID_NOSTRIPE;
#else
            validators[i] = VALID(p_ids[i]);
#endif

        rc = batch_insert_stripe_info(p_mgr, pklist, validators, p_attrs,
                                      count, TRUE);
        MemFree(validators);
        if (rc)
            goto out_free;
    }
#endif

out_free:
    var_str_free(&query);
    MemFree(pklist);
    return rc;
}
Example #15
0
int get_stripe_info( lmgr_t * p_mgr, PK_ARG_T pk, stripe_info_t * p_stripe_info,
                     stripe_items_t * p_items )
{
    char           query[1024];
    char          *res[3];
    result_handle_t result;
    int            i;
    int            rc = DB_SUCCESS;

    /* retrieve basic stripe info */
    sprintf( query,
             "SELECT stripe_count, stripe_size, pool_name FROM " STRIPE_INFO_TABLE " WHERE id="DPK,
             pk );

    rc = db_exec_sql( &p_mgr->conn, query, &result );
    if ( rc )
        goto out;

    rc = db_next_record( &p_mgr->conn, &result, res, 3 );
    if ( rc == DB_END_OF_LIST )
        rc = DB_NOT_EXISTS;
    if ( rc )
        goto res_free;

    if ( res[0] == NULL || res[1] == NULL || res[2] == NULL )
    {
        rc = DB_ATTR_MISSING;
        goto res_free;
    }

    p_stripe_info->stripe_count = atoi( res[0] );
    p_stripe_info->stripe_size = atoi( res[1] );
    strncpy( p_stripe_info->pool_name, res[2], MAX_POOL_LEN );

    db_result_free( &p_mgr->conn, &result );

    if ( p_items )
    {
        /* retrieve stripe list */
        sprintf( query, "SELECT storage_item FROM " STRIPE_ITEMS_TABLE " WHERE id="DPK, pk );

        rc = db_exec_sql( &p_mgr->conn, query, &result );
        if ( rc )
            goto out;

        if ( p_stripe_info->stripe_count != db_result_nb_records( &p_mgr->conn, &result ) )
        {
            DisplayLog( LVL_MAJOR, LISTMGR_TAG,
                        "Warning: the number of stripe items (%d) doesn't match stripe count (%u)! (Pk="DPK")",
                        db_result_nb_records( &p_mgr->conn, &result ), p_stripe_info->stripe_count, pk );
        }
        p_items->count = db_result_nb_records( &p_mgr->conn, &result );

        if ( p_items->count > 0 )
        {

            /* allocate stripe array */
            p_items->stripe_units = MemCalloc( p_items->count, sizeof( storage_unit_id_t ) );

            if ( !p_items->stripe_units )
            {
                rc = DB_NO_MEMORY;
                goto res_free;
            }

            /* fill stripe units */
            for ( i = 0; i < p_items->count; i++ )
            {
                rc = db_next_record( &p_mgr->conn, &result, res, 1 );
                if ( rc )
                    goto stripe_free;

                if ( res[0] == NULL )
                {
                    rc = DB_ATTR_MISSING;
                    goto stripe_free;
                }

                p_items->stripe_units[i] = atoi( res[0] );
            }
        }
        else
            p_items->stripe_units = NULL;

        /* last query result must be freed */
        rc = DB_SUCCESS;
        goto res_free;
    }

    /* nothing to free */
    return DB_SUCCESS;

    stripe_free:
    MemFree( p_items->stripe_units );
    p_items->stripe_units = NULL;
    p_items->count = 0;
    p_stripe_info->stripe_count = 0;
    res_free:
    db_result_free( &p_mgr->conn, &result );
    out:
    return rc;
}
Example #16
0
int db_exec_sql_quiet( db_conn_t * conn, const char *query, result_handle_t * p_result )
{
    return db_exec_sql( conn, query, p_result);
}
Example #17
0
fsal_posixdb_status_t fsal_posixdb_getInfoFromHandle(fsal_posixdb_conn * p_conn,        /* IN */
                                                     posixfsal_handle_t * p_object_handle,      /* IN/OUT */
                                                     fsal_path_t * p_paths,     /* OUT */
                                                     int paths_size,    /* IN */
                                                     int *p_count /* OUT */ )
{
  fsal_posixdb_status_t st;
  result_handle_t res;
  MYSQL_ROW row;
  posixfsal_handle_t parent_directory_handle;
  int i_path;
  int toomanypaths = 0;
  char query[2048];

  /* sanity check */
  if(!p_conn || !p_object_handle || ((!p_paths || !p_count) && paths_size > 0))
    {
      ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0);
    }
  LogFullDebug(COMPONENT_FSAL, "OBJECT_ID=%lli\n", p_object_handle->data.id);

  BeginTransaction(p_conn);

  /* lookup for the handle of the file */

  if(!fsal_posixdb_GetInodeCache(p_object_handle))
    {

      snprintf(query, 2048,
               "SELECT Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype "
               "FROM Handle WHERE handleid=%llu AND handlets=%u", p_object_handle->data.id,
               p_object_handle->data.ts);

      st = db_exec_sql(p_conn, query, &res);
      if(FSAL_POSIXDB_IS_ERROR(st))
        goto rollback;

      /* p_res contains : Handle.deviceId, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype  */

      LogDebug(COMPONENT_FSAL, "lookupHandle(%llu,%u)", p_object_handle->data.id,
                 (unsigned int)p_object_handle->data.ts);
      if((mysql_num_rows(res) != 1) || ((row = mysql_fetch_row(res)) == NULL))
        {
          LogDebug(COMPONENT_FSAL, "lookupHandle=%d entries", mysql_num_rows(res));
          mysql_free_result(res);
          RollbackTransaction(p_conn);
          ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0);
        }

      posixdb_internal_fillFileinfoFromStrValues(&(p_object_handle->data.info),
                                                 row[0], row[1], row[2], row[3], row[4]);
      mysql_free_result(res);

      /* update the inode */
      fsal_posixdb_UpdateInodeCache(p_object_handle);
    }

  /* Build the paths of the object */
  if(p_paths)
    {
      /* find all the paths to the object */

      snprintf(query, 2048, "SELECT name, handleidparent, handletsparent "
               "FROM Parent WHERE handleid=%llu AND handlets=%u",
               p_object_handle->data.id, p_object_handle->data.ts);

      st = db_exec_sql(p_conn, query, &res);
      if(FSAL_POSIXDB_IS_ERROR(st))
        goto rollback;

      /* res contains name, handleidparent, handletsparent */
      *p_count = mysql_num_rows(res);
      if(*p_count == 0)
        {
          mysql_free_result(res);
          RollbackTransaction(p_conn);
          ReturnCodeDB(ERR_FSAL_POSIXDB_NOPATH, 0);
        }
      else if(*p_count > paths_size)
        {
          toomanypaths = 1;

          LogCrit(COMPONENT_FSAL, "Too many paths found for object %llu.%u: found=%u, max=%d",
                     p_object_handle->data.id, p_object_handle->data.ts, *p_count, paths_size);

          *p_count = paths_size;
        }

      for(i_path = 0; i_path < *p_count; i_path++)
        {
          unsigned int tmp_len;

          row = mysql_fetch_row(res);
          if(row == NULL)
            {
              mysql_free_result(res);
              RollbackTransaction(p_conn);
              ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0);
            }

          /* build the path of the parent directory */
          parent_directory_handle.data.id = atoll(row[1]);
          parent_directory_handle.data.ts = atoi(row[2]);

          st = fsal_posixdb_buildOnePath(p_conn, &parent_directory_handle,
                                         &p_paths[i_path]);
          if(FSAL_POSIXDB_IS_ERROR(st))
            goto free_res;

          tmp_len = p_paths[i_path].len;

          if((tmp_len > 0) && (p_paths[i_path].path[tmp_len - 1] == '/'))
            {
              /* then concatenate the name of the file */
              /* but not concatenate '/' */
              if((tmp_len + strlen(row[0]) >= FSAL_MAX_PATH_LEN))
                {
                  mysql_free_result(res);
                  RollbackTransaction(p_conn);
                  ReturnCodeDB(ERR_FSAL_POSIXDB_PATHTOOLONG, 0);
                }
              strcpy(&p_paths[i_path].path[tmp_len], row[0]);
              p_paths[i_path].len += strlen(row[0]);

            }
          else
            {
              /* then concatenate the name of the file */
              if((tmp_len + 1 + strlen(row[0]) >= FSAL_MAX_PATH_LEN))
                {
                  mysql_free_result(res);
                  RollbackTransaction(p_conn);
                  ReturnCodeDB(ERR_FSAL_POSIXDB_PATHTOOLONG, 0);
                }
              p_paths[i_path].path[tmp_len] = '/';
              strcpy(&p_paths[i_path].path[tmp_len + 1], row[0]);
              p_paths[i_path].len += 1 + strlen(row[0]);
            }

          /* insert the object into cache */
          fsal_posixdb_CachePath(p_object_handle, &p_paths[i_path]);

        }

      mysql_free_result(res);
    }

  st = EndTransaction(p_conn);

  if(toomanypaths)
    ReturnCodeDB(ERR_FSAL_POSIXDB_TOOMANYPATHS, 0);
  else
    return st;

 free_res:
  mysql_free_result(res);
 rollback:
  RollbackTransaction(p_conn);
  return st;
}
Example #18
0
fsal_posixdb_status_t fsal_posixdb_getInfoFromName(fsal_posixdb_conn * p_conn,  /* IN */
                                                   posixfsal_handle_t * p_parent_directory_handle,      /* IN/OUT */
                                                   fsal_name_t * p_objectname,  /* IN */
                                                   fsal_path_t * p_path,        /* OUT */
                                                   posixfsal_handle_t *
                                                   p_handle /* OUT */ )
{
  fsal_posixdb_status_t st;
  char query[2048];
  result_handle_t res;
  MYSQL_ROW row;

  /* sanity check */
  if(!p_conn || !p_handle)
    {
      ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0);
    }
  LogFullDebug(COMPONENT_FSAL, "object_name='%s'\n", p_objectname->name ? p_objectname->name : "/");

  BeginTransaction(p_conn);
  /* lookup for the handle of the file */
  if(p_parent_directory_handle && p_parent_directory_handle->data.id)
    {
      snprintf(query, 2048,
               "SELECT Parent.handleid, Parent.handlets, Handle.deviceid, "
               "Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype "
               "FROM Parent INNER JOIN Handle ON Parent.handleid = Handle.handleid AND Parent.handlets=Handle.handlets "
               "WHERE handleidparent=%llu AND handletsparent=%u AND name='%s'",
               p_parent_directory_handle->data.id,
               p_parent_directory_handle->data.ts, p_objectname->name);

      st = db_exec_sql(p_conn, query, &res);
      if(FSAL_POSIXDB_IS_ERROR(st))
        goto rollback;
    }
  else
    {
      /* get root handle: */

      st = db_exec_sql(p_conn,
                       "SELECT Parent.handleid, Parent.handlets, Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype "
                       "FROM Parent INNER JOIN Handle ON Parent.handleid = Handle.handleid AND Parent.handlets=Handle.handlets "
                       "WHERE Parent.handleidparent=Parent.handleid AND Parent.handletsparent=Parent.handlets",
                       &res);
      if(FSAL_POSIXDB_IS_ERROR(st))
        goto rollback;
    }
  /* res contains : Parent.handleid, Parent.handlets, Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype  */

  /* entry not found */
  if((mysql_num_rows(res) != 1) || ((row = mysql_fetch_row(res)) == NULL))
    {
      mysql_free_result(res);
      RollbackTransaction(p_conn);
      ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0);
    }

  p_handle->data.id = atoll(row[0]);
  p_handle->data.ts = atoi(row[1]);
  posixdb_internal_fillFileinfoFromStrValues(&(p_handle->data.info), row[2], row[3], /* devid, inode */
                                             row[4],    /* nlink */
                                             row[5],    /* ctime */
                                             row[6]);   /* ftype */
  mysql_free_result(res);

  /* Build the path of the object */
  if(p_path && p_objectname)
    {
      /* build the path of the Parent */
      st = fsal_posixdb_buildOnePath(p_conn, p_parent_directory_handle, p_path);
      if(FSAL_POSIXDB_IS_ERROR(st))
        goto rollback;

      /* then concatenate the filename */
      if(!(p_path->len + 1 + p_objectname->len < FSAL_MAX_PATH_LEN))
        {
          RollbackTransaction(p_conn);
          ReturnCodeDB(ERR_FSAL_POSIXDB_PATHTOOLONG, 0);
        }
      p_path->path[p_path->len] = '/';
      strcpy(&p_path->path[p_path->len + 1], p_objectname->name);
      p_path->len += 1 + p_objectname->len;

      /* add the the path to cache */
      fsal_posixdb_CachePath(p_handle, p_path);
    }
  else
    {
      /* update handle if it was in cache */
      fsal_posixdb_UpdateInodeCache(p_handle);
    }

  return EndTransaction(p_conn);

 rollback:
  RollbackTransaction(p_conn);
  return st;
}
Example #19
0
int ListMgr_Update( lmgr_t * p_mgr, const entry_id_t * p_id, const attr_set_t * p_update_set )
{
    int            rc, main_count, annex_count;
    char           query[4096];
    char           fields[4096];
    char           annex_fields[4096];
    DEF_PK(pk);
    int            nb_tables = 0;

    /* read only fields in info mask? */
    if ( readonly_attr_set & p_update_set->attr_mask )
    {
        DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Error: trying to update read only values: attr_mask=%#x",
                    readonly_attr_set & p_update_set->attr_mask );
        return DB_INVALID_ARG;
    }

    rc = entry_id2pk( p_mgr, p_id, FALSE, PTR_PK(pk) );
    if (rc)
        return rc;

    /* check how many tables are to be updated */
    if ( main_fields( p_update_set->attr_mask ) )
    {
        main_count = attrset2updatelist( p_mgr, fields, p_update_set, T_MAIN, FALSE );
        if ( main_count < 0 )
            return -main_count;
        if ( main_count > 0 )
            nb_tables++;
    }
    else
        main_count = 0;

    if ( annex_table && annex_fields( p_update_set->attr_mask ) )
    {
        annex_count = attrset2updatelist( p_mgr, annex_fields, p_update_set, T_ANNEX, FALSE );
        if ( annex_count < 0 )
            return -annex_count;
        if ( annex_count > 0 )
            nb_tables++;
    }
    else
        annex_count = 0;


    if ( stripe_fields( p_update_set->attr_mask ) )
        nb_tables += 2;

    /* if only 1 table is impacted, switch to autocommit mode */
    if ( nb_tables > 1 )
    {
        /* @todo in the case of sqlite, we may want to do periodic commit
         * instead of systematic one. */
        rc = lmgr_begin( p_mgr );
        if ( rc )
            return rc;
    }

    /* update main table */

    if ( main_count > 0 )
    {
        sprintf( query, "UPDATE " MAIN_TABLE " SET %s WHERE id="DPK, fields, pk );
        rc = db_exec_sql( &p_mgr->conn, query, NULL );
        if ( rc )
            goto rollback;
    }

    /* update annex table (if any) */
    if ( annex_count > 0 )
    {
        sprintf( query, "UPDATE " ANNEX_TABLE " SET %s WHERE id="DPK, annex_fields, pk );
        rc = db_exec_sql( &p_mgr->conn, query, NULL );
        if ( rc )
            goto rollback;
    }

    /* insert new stripe info if provided (and eventually remove previous values) */
    if ( ATTR_MASK_TEST( p_update_set, stripe_info ) )
    {
        rc = insert_stripe_info( p_mgr, pk, VALID(p_id), &ATTR( p_update_set, stripe_info ),
                                 ATTR_MASK_TEST( p_update_set, stripe_items ) ?
                                    &ATTR( p_update_set, stripe_items ) : NULL, TRUE );
        if ( rc )
            goto rollback;
    }


    if ( nb_tables > 1 )
        return lmgr_commit( p_mgr );
    else
        return DB_SUCCESS;

  rollback:
    lmgr_rollback( p_mgr );
    return rc;
}
Example #20
0
/**
 * Get the list of children of a given parent (or list of parents).
 * \param parent_list       [in]  list of parents to get the child of
 * \param parent_count      [in]  number of ids in parent list
 * \param attr_mask         [in]  required attributes for children
 * \param child_id_list     [out] ptr to array of child ids
 * \param child_attr_list   [out] ptr to array of child attrs
 * \param child_count       [out] number of returned children
 */
int ListMgr_GetChild(lmgr_t *p_mgr, const lmgr_filter_t *p_filter,
                     const wagon_t *parent_list, unsigned int parent_count,
                     attr_mask_t attr_mask,
                     wagon_t **child_id_list, attr_set_t **child_attr_list,
                     unsigned int *child_count)
{
    result_handle_t result;
    char *path = NULL;
    int path_len;
    int                rc, i;
    GString           *req = NULL;
    GString           *fields = NULL;
    GString           *from = NULL;
    GString           *where = NULL;
    struct field_count field_cnt = {0};
    struct field_count filter_cnt = {0};
    table_enum         query_tab = T_DNAMES;
    bool               distinct = false;
    int                retry_status;

    /* XXX: querying children from several parent cannot work, since
     * we need to get the paths of the children. Or we could do a
     * lookup into parent_list to find the right one. In the meantime,
     * try not to mess up the code. */
    if (unlikely(parent_count != 1))
        RBH_BUG("cannot get children for several parent simultaneously");

    /* always request for name to build fullpath in wagon */
    attr_mask_set_index(&attr_mask, ATTR_INDEX_name);

    fields = g_string_new(NULL);

    /* append fields for all tables */
    if (!attr_mask_is_null(attr_mask))
    {
        /* retrieve source info for generated fields */
        add_source_fields_for_gen(&attr_mask.std);

        field_cnt.nb_names = attrmask2fieldlist(fields, attr_mask, T_DNAMES,
                                                DNAMES_TABLE".", "",
                                                AOF_LEADING_SEP);

        field_cnt.nb_main = attrmask2fieldlist(fields, attr_mask, T_MAIN,
                                               MAIN_TABLE".", "",
                                               AOF_LEADING_SEP);

        field_cnt.nb_annex = attrmask2fieldlist(fields, attr_mask, T_ANNEX,
                                                ANNEX_TABLE".", "",
                                                AOF_LEADING_SEP);
    }
    else
    {
        /* no returned attrs */
        if (child_attr_list != NULL)
            *child_attr_list = NULL;
    }

    where = g_string_new(NULL);

    /* starts with condition on parent */
    rc = append_parent_cond(p_mgr, where, parent_list, parent_count, DNAMES_TABLE".");
    if (rc != DB_SUCCESS)
        goto free_str;

    /* check filters on other tables */
    if (!no_filter(p_filter))
    {
        if (unlikely(dir_filter(p_mgr, NULL, p_filter, NULL, NULL) != FILTERDIR_NONE))
        {
            DisplayLog(LVL_MAJOR, LISTMGR_TAG, "Directory filter not supported in %s()", __func__);
            rc = DB_NOT_SUPPORTED;
            goto free_str;
        }
        else if (unlikely(func_filter(p_mgr, NULL, p_filter, T_MAIN, 0)))
        {
            DisplayLog(LVL_MAJOR, LISTMGR_TAG, "Function filter not supported in %s()", __func__);
            rc = DB_NOT_SUPPORTED;
            goto free_str;
        }

        /* There is always a filter on T_DNAMES, which is the parent condition.
         * Look for optional filters.
         */
        filter_where(p_mgr, p_filter, &filter_cnt, where,
                     AOF_LEADING_SEP | AOF_SKIP_NAME);
        /** @FIXME process other filters on NAMES */
    }

    from = g_string_new(DNAMES_TABLE);

    /* add filter_count + field_count to build the FROM clause.
     * Preserve field count which is needed to interpret the result.
     */
    filter_cnt.nb_main += field_cnt.nb_main;
    filter_cnt.nb_annex += field_cnt.nb_annex;
    filter_cnt.nb_names += field_cnt.nb_names;
    /* query tab is DNAMES, skip_name=true, is_first_tab=T_DNAMES */
    filter_from(p_mgr, &filter_cnt, from, &query_tab, &distinct,
                AOF_LEADING_SEP | AOF_SKIP_NAME);

    /* request is always on the DNAMES table (which contains [parent_id, id] relationship */
    if (distinct)
        req = g_string_new("SELECT DISTINCT("DNAMES_TABLE".id) as id");
    else
        req = g_string_new("SELECT "DNAMES_TABLE".id as id");

    /* build the whole request */
    g_string_append_printf(req, "%s FROM %s WHERE %s", fields->str, from->str, where->str);

retry:
    rc = db_exec_sql(&p_mgr->conn, req->str, &result);
    retry_status = lmgr_delayed_retry(p_mgr, rc);
    if (retry_status == 1)
        goto retry;
    else if (retry_status == 2) {
        rc = DB_RBH_SIG_SHUTDOWN;
        goto free_str;
    } else if (rc)
        goto free_str;

    /* copy result to output structures */
    *child_count = db_result_nb_records(&p_mgr->conn, &result);

    /* allocate entry_id array */
    *child_id_list = MemCalloc(*child_count, sizeof(wagon_t));
    if (*child_id_list == NULL)
    {
        rc = DB_NO_MEMORY;
        goto free_str;
    }

    if (child_attr_list)
    {
        *child_attr_list = MemCalloc(*child_count, sizeof(attr_set_t));
        if (*child_attr_list == NULL)
        {
            rc = DB_NO_MEMORY;
            goto array_free;
        }
    }

    /* Allocate a string long enough to contain the parent path and a
     * child name. */
    path_len = strlen(parent_list[0].fullname) + RBH_NAME_MAX + 2;
    path = malloc(path_len);
    if (!path) {
        DisplayLog(LVL_MAJOR, LISTMGR_TAG, "Can't alloc enough memory (%d bytes)",
                    path_len);
        rc = DB_NO_MEMORY;
        goto array_free;
    }

    for (i = 0; i < *child_count; i++)
    {
        char *res[128]; /* 128 fields per record is large enough */

        rc = db_next_record(&p_mgr->conn, &result, res, sizeof(res)/sizeof(*res));
        if (rc)
            goto array_free;

        /* copy id to array */
        pk2entry_id(p_mgr, res[0], &((*child_id_list)[i].id));

        /* copy attributes to array */
        if (child_attr_list)
        {
            unsigned int shift = 1; /* first was NAMES.id */

            (*child_attr_list)[i].attr_mask = attr_mask;

            /* first id, then dnames attrs, then main attrs, then annex attrs */
            if (field_cnt.nb_names > 0)
            {
                /* shift of 1 for id */
                rc = result2attrset(T_DNAMES, res + shift, field_cnt.nb_names, &((*child_attr_list)[i]));
                if (rc)
                    goto array_free;
                shift += field_cnt.nb_names;
            }

            if (field_cnt.nb_main > 0)
            {
                /* first id, then main attrs, then annex attrs */
                /* shift of 1 for id */
                rc = result2attrset(T_MAIN, res + shift, field_cnt.nb_main, &((*child_attr_list)[i]));
                if (rc)
                    goto array_free;
                shift += field_cnt.nb_main;
            }

            if (field_cnt.nb_annex > 0)
            {
                /* shift of main_attrs count */
                rc = result2attrset(T_ANNEX, res + shift, field_cnt.nb_annex,
                                     &((*child_attr_list)[i]));
                if (rc)
                    goto array_free;
                shift += field_cnt.nb_annex;
            }

#ifdef _LUSTRE
            if (stripe_fields(attr_mask))
            {
                if (get_stripe_info(p_mgr, res[0], &ATTR(&(*child_attr_list)[i], stripe_info),
                                     &ATTR(&(*child_attr_list)[i], stripe_items)))
                {
                    ATTR_MASK_UNSET(&(*child_attr_list)[i], stripe_info);
                    ATTR_MASK_UNSET(&(*child_attr_list)[i], stripe_items);
                }
            }
#endif

            generate_fields(&((*child_attr_list)[i]));

            /* Note: path is properly sized already to not overflow. */
            snprintf(path, path_len, "%s/%s", parent_list[0].fullname,
                     (*child_attr_list)[i].attr_values.name);
            (*child_id_list)[i].fullname = strdup(path);
        }
    }

    if (path)
        free(path);

    db_result_free(&p_mgr->conn, &result);
    g_string_free(req, TRUE);
    g_string_free(fields, TRUE);
    g_string_free(from, TRUE);
    g_string_free(where, TRUE);
    return 0;

array_free:
    if (path)
        free(path);
    if (child_attr_list && *child_attr_list)
    {
        MemFree(*child_attr_list);
        *child_attr_list = NULL;
    }
    MemFree(*child_id_list);
    *child_id_list = NULL;
free_str:
    g_string_free(req, TRUE);
    g_string_free(fields, TRUE);
    g_string_free(from, TRUE);
    g_string_free(where, TRUE);
    return rc;
}
Example #21
0
/**
 *  Retrieve entry attributes from its primary key
 */
int listmgr_get_by_pk( lmgr_t * p_mgr, PK_ARG_T pk, attr_set_t * p_info )
{
    int             rc;
    char           *first_table = NULL;
    GString        *req, *from;
    /* attribute count is up to 1 per bit (8 per byte).
     * x2 for bullet proofing */
    char           *result_tab[2*8*sizeof(p_info->attr_mask)];
    result_handle_t result;
    bool            checkmain   = true;
    int             main_count  = 0,
                    annex_count = 0,
                    name_count  = 0;
    attr_mask_t     gen = gen_fields(p_info->attr_mask);

    if (p_info == NULL)
        return 0;

    /* init entry info */
    memset(&p_info->attr_values, 0, sizeof(entry_info_t));
    req = g_string_new("SELECT ");
    from = g_string_new(" FROM ");

    /* retrieve source info for generated fields (only about std fields)*/
    add_source_fields_for_gen(&p_info->attr_mask.std);

    /* don't get fields that are not in main, names, annex, stripe...
     * This allows the caller to set all bits 'on' to get everything.
     * Note: this also clear generated fields. They will be restored after.
     */
    supported_bits_only(&p_info->attr_mask);

    /* get info from main table (if asked) */
    main_count = attrmask2fieldlist(req, p_info->attr_mask, T_MAIN, "", "", 0);
    if (main_count < 0)
    {
        rc = -main_count;
        goto free_str;
    }
    else if (main_count > 0)
    {
        checkmain = false;
        first_table = MAIN_TABLE;
        g_string_append(from, MAIN_TABLE);
    }

    annex_count = attrmask2fieldlist(req, p_info->attr_mask, T_ANNEX, "", "",
                                     first_table != NULL ? AOF_LEADING_SEP : 0);
    if (annex_count < 0)
    {
        rc = -annex_count;
        goto free_str;
    }
    else if (annex_count > 0)
    {
        if (first_table != NULL)
            g_string_append_printf(from, " LEFT JOIN "ANNEX_TABLE" ON %s.id="
                                   ANNEX_TABLE".id", first_table);
        else
        {
            first_table = ANNEX_TABLE;
            g_string_append(from, ANNEX_TABLE);
        }
    }

    name_count = attrmask2fieldlist(req, p_info->attr_mask, T_DNAMES, "", "",
                                    first_table != NULL ? AOF_LEADING_SEP : 0);
    if (name_count < 0)
    {
        rc = -name_count;
        goto free_str;
    }
    else if (name_count > 0)
    {
        if (first_table)
            /* it's OK to JOIN with NAMES table here even if there are multiple paths,
             * as we only take one result record. The important thing is to return
             * consistent values for parent_id, name and fullpath. */
            g_string_append_printf(from, " LEFT JOIN "DNAMES_TABLE" ON %s.id="
                                   DNAMES_TABLE".id", first_table);
        else
        {
            first_table = DNAMES_TABLE;
            g_string_append(from, DNAMES_TABLE);
        }
    }

    if (first_table != NULL)
    {
        int shift = 0;

        g_string_append_printf(req, "%s WHERE %s.id="DPK, from->str,
                               first_table, pk);

        rc = db_exec_sql(&p_mgr->conn, req->str, &result);
        if (rc)
            goto free_str;

        rc = db_next_record(&p_mgr->conn, &result, result_tab,
                            main_count + annex_count + name_count);
        /* END_OF_LIST means it does not exist */
        if (rc == DB_END_OF_LIST)
        {
            clean_std_table_bits(&p_info->attr_mask);

            /* not found, but did not check MAIN yet */
            if (checkmain)
                goto next_table;

            rc = DB_NOT_EXISTS;
        }
        if (rc)
            goto free_res;

        /* set info from result */
        if (main_count)
        {
            rc = result2attrset(T_MAIN, result_tab + shift, main_count, p_info);
            shift += main_count;
            if (rc)
                goto free_res;
        }
        if (annex_count)
        {
            rc = result2attrset(T_ANNEX, result_tab + shift, annex_count,
                                p_info);
            shift += annex_count;
            if (rc)
                goto free_res;
        }
        if (name_count)
        {
            rc = result2attrset(T_DNAMES, result_tab + shift, name_count,
                                p_info);
            shift += name_count;
            if (rc)
                goto free_res;
        }

next_table:
        db_result_free(&p_mgr->conn, &result);
    }

    /* remove stripe info if it is not a file */
    if (stripe_fields(p_info->attr_mask) && ATTR_MASK_TEST(p_info, type)
        && strcmp(ATTR(p_info, type), STR_TYPE_FILE) != 0)
    {
        p_info->attr_mask = attr_mask_and_not(&p_info->attr_mask, &stripe_attr_set);
    }

    /* get stripe info if asked */
#ifdef _LUSTRE
    if (stripe_fields(p_info->attr_mask))
    {
        rc = get_stripe_info(p_mgr, pk, &ATTR(p_info, stripe_info),
                             ATTR_MASK_TEST(p_info, stripe_items)?
                                &ATTR(p_info, stripe_items) : NULL);
        if (rc == DB_ATTR_MISSING || rc == DB_NOT_EXISTS)
        {
            /* stripe info is in std mask */
            p_info->attr_mask.std &= ~ATTR_MASK_stripe_info;

            if (ATTR_MASK_TEST(p_info, stripe_items))
                p_info->attr_mask.std &= ~ATTR_MASK_stripe_items;
        }
        else if (rc)
            goto free_str;
        else
            checkmain = false; /* entry exists */
    }
#else
    /* POSIX: always clean stripe bits */
    p_info->attr_mask = attr_mask_and_not(&p_info->attr_mask, &stripe_attr_set);
#endif

    /* special field dircount */
    if (dirattr_fields(p_info->attr_mask))
    {
        if (listmgr_get_dirattrs(p_mgr, pk, p_info))
        {
            DisplayLog(LVL_MAJOR, LISTMGR_TAG, "listmgr_get_dirattrs failed for "DPK, pk);
            p_info->attr_mask = attr_mask_and_not(&p_info->attr_mask, &dir_attr_set);
        }
    }

    if (checkmain)
    {
        /* verify it exists in main table */
        g_string_printf(req, "SELECT id FROM " MAIN_TABLE " WHERE id="DPK, pk);

        /* execute the request */
        rc = db_exec_sql(&p_mgr->conn, req->str, &result);
        if (rc)
            goto free_str;

        rc = db_next_record(&p_mgr->conn, &result, result_tab, 1);
        db_result_free(&p_mgr->conn, &result);
        if (rc)
        {
            rc = DB_NOT_EXISTS;
            goto free_str;
        }
    }

    /* restore generated fields in attr mask */
    p_info->attr_mask = attr_mask_or(&p_info->attr_mask, &gen);
    /* generate them */
    generate_fields(p_info);

    /* update operation stats */
    p_mgr->nbop[OPIDX_GET]++;

    rc = DB_SUCCESS;
    goto free_str;

  free_res:
    db_result_free(&p_mgr->conn, &result);
  free_str:
    g_string_free(req, TRUE);
    g_string_free(from, TRUE);
    return rc;
} /* listmgr_get_by_pk */
Example #22
0
/**
 * Get the list of children of a given parent (or list of parents).
 * \param parent_list       [in]  list of parents to get the child of
 * \param parent_count      [in]  number of ids in parent list
 * \param attr_mask         [in]  required attributes for children
 * \param child_id_list     [out] ptr to array of child ids
 * \param child_attr_list   [out] ptr to array of child attrs
 * \param child_count       [out] number of returned children
 */
int ListMgr_GetChild( lmgr_t * p_mgr, const lmgr_filter_t * p_filter,
                      const wagon_t * parent_list, unsigned int parent_count,
                      int attr_mask,
                      wagon_t ** child_id_list, attr_set_t ** child_attr_list,
                      unsigned int * child_count)
{
    result_handle_t result;
    char *curr;
    int  filter_main = 0;
    int  filter_annex = 0;
    int main_attrs = 0;
    int dnames_attrs = 0;
    int annex_attrs = 0;
    char query[4096];
    char fieldlist_main[1024] = "";
    char fieldlist_dnames[1024] = "";
    char fieldlist_annex[1024] = "";
    char filter_str_main[1024] = "";
    char filter_str_annex[1024] = "";
    char tmp[2048];
    char *path = NULL;
    int path_len;
    char * pc;
    int rc, i;

    /* TODO: querying children from several parent cannot work, since
     * we need to get the paths of the children. Or we could do a
     * lookup into parent_list to find the right one. In the meantime,
     * try not to mess up the code. */
    if (parent_count != 1)
        RBH_BUG("cannot get children for several parent simultaneously");

    /* always request for name to build fullpath in wagon */
    attr_mask |= ATTR_MASK_name;

    /* request is always on the MAIN table (which contains [parent_id, id] relationship */

    /* /!\ possible cases:
     * - simplest: the fields of the filter and the attributes to be retrieved are in the MAIN table
     * - harder: the fields of the filter and attributes are in a different table
     */

    /* 1) location of filters */
    if ( p_filter )
    {
        char           dummy_str[1024];
        unsigned int   dummy_uint;
        if (dir_filter(p_mgr, dummy_str, p_filter, &dummy_uint) != FILTERDIR_NONE)
        {
            DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Directory filter not supported in %s()", __func__ );
            return DB_NOT_SUPPORTED;
        }
        else if (func_filter(p_mgr, dummy_str, p_filter, T_MAIN, FALSE, FALSE))
        {
            DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Function filter not supported in %s()", __func__ );
            return DB_NOT_SUPPORTED;
        }

        /* There is always a filter on T_DNAMES, which is the parent condition.
         * Look for optional filters:
         */
        filter_main = filter2str( p_mgr, filter_str_main, p_filter, T_MAIN,
                                  FALSE, TRUE );

        if ( annex_table )
            filter_annex = filter2str( p_mgr, filter_str_annex, p_filter,
                                       T_ANNEX, FALSE, TRUE );
        else
            filter_annex = 0;

        /* @TODO to be implemented */
#if 0
        filter_stripe_info =
            filter2str( p_mgr, filter_str_stripe_info, p_filter, T_STRIPE_INFO,
                        ( filter_main > 0 ) || ( filter_annex > 0 ), TRUE );

        filter_stripe_items =
            filter2str( p_mgr, filter_str_stripe_items, p_filter, T_STRIPE_ITEMS,
                        ( filter_main > 0 ) || ( filter_annex > 0 )
                        || ( filter_stripe_info > 0 ), TRUE );
#endif
    }

    /* 2) location of requested attributes */
    if (attr_mask)
    {
        /* retrieve source info for generated fields */
        add_source_fields_for_gen( &attr_mask );

        main_attrs = attrmask2fieldlist( fieldlist_main, attr_mask, T_MAIN,
                                         /* leading comma */ TRUE, /* for update */ FALSE,
                                         /* prefix */ MAIN_TABLE".", /* postfix */ "" );

        dnames_attrs += attrmask2fieldlist( fieldlist_dnames, attr_mask, T_DNAMES,
                                            /* leading comma */ TRUE, /* for update */ FALSE,
                                            /* prefix */ DNAMES_TABLE".", /* postfix */ "" );

        if ( annex_table )
            annex_attrs = attrmask2fieldlist( fieldlist_annex, attr_mask, T_ANNEX,
                                             /* leading comma */ TRUE, /* for update */ FALSE,
                                             /* prefix */ ANNEX_TABLE".", /* postfix */ "" );
        else
            annex_attrs = 0;
    }
    else
    {
        /* no returned attrs */
        if (child_attr_list)
            *child_attr_list = NULL;
    }
    pc = parent_cond(p_mgr, tmp, sizeof(tmp), parent_list, parent_count, DNAMES_TABLE".");
    if (!pc)
        return DB_BUFFER_TOO_SMALL;

    curr = query;

    /* SELECT clause */
    /* id + dname fields */
    curr += sprintf(curr, "SELECT "DNAMES_TABLE".id%s", fieldlist_dnames);
    /* main attrs */
    if (main_attrs)
        curr += sprintf(curr, "%s", fieldlist_main);
    /* annex attrs */
    if (annex_attrs)
        curr += sprintf(curr, "%s", fieldlist_annex);

    /* FROM clause */
    curr += sprintf(curr, " FROM "DNAMES_TABLE);
    if (main_attrs || filter_main)
        curr += sprintf(curr, " LEFT JOIN "MAIN_TABLE
                              " ON "DNAMES_TABLE".id="MAIN_TABLE".id");
    if (annex_attrs || filter_annex)
        curr += sprintf(curr, " LEFT JOIN "ANNEX_TABLE
                              " ON "DNAMES_TABLE".id="ANNEX_TABLE".id");

    /* WHERE clause */
    curr += sprintf(curr, " WHERE %s", pc);
    if (filter_main)
        curr += sprintf(curr, " AND %s", filter_str_main);
    if (filter_annex)
        curr += sprintf(curr, " AND %s", filter_str_annex);

retry:
    rc = db_exec_sql(&p_mgr->conn, query, &result);
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    else if (rc)
        return rc;

    /* copy result to output structures */
    *child_count = db_result_nb_records(&p_mgr->conn, &result);

    /* allocate entry_id array */
    *child_id_list = MemCalloc(*child_count, sizeof(wagon_t));
    if (*child_id_list == NULL)
        return DB_NO_MEMORY;

    if (child_attr_list)
    {
        *child_attr_list = MemCalloc(*child_count, sizeof(attr_set_t));
        if (*child_attr_list == NULL)
        {
            rc = DB_NO_MEMORY;
            goto array_free;
        }
    }

    /* Allocate a string long enough to contain the parent path and a
     * child name. */
    path_len = strlen(parent_list[0].fullname) + RBH_NAME_MAX + 2;
    path = malloc(path_len);
    if (!path) {
        DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Can't alloc enough memory (%d bytes)",
                    path_len );
        rc = DB_NO_MEMORY;
        goto array_free;
    }

    for (i = 0; i < *child_count; i++)
    {
        char *res[128]; /* 128 fields per row is large enough */
        rc = db_next_record(&p_mgr->conn, &result, res, 128);
        if ( rc )
            goto array_free;

        /* copy id to array */
        pk2entry_id(p_mgr, res[0], &((*child_id_list)[i].id));

        /* copy attributes to array */
        if (child_attr_list)
        {
            (*child_attr_list)[i].attr_mask = attr_mask;

            /* first id, then dnames attrs, then main attrs, then annex attrs */
            if (dnames_attrs)
            {
                /* shift of 1 for id */
                rc = result2attrset( T_DNAMES, res + 1, dnames_attrs, &((*child_attr_list)[i]) );
                if ( rc )
                    goto array_free;
            }

            if (main_attrs)
            {
                /* first id, then main attrs, then annex attrs */
                /* shift of 1 for id */
                rc = result2attrset( T_MAIN, res + dnames_attrs + 1, main_attrs, &((*child_attr_list)[i]) );
                if ( rc )
                    goto array_free;
            }

            if (annex_attrs)
            {
                /* shift of main_attrs count */
                rc = result2attrset( T_ANNEX, res + dnames_attrs + main_attrs + 1, annex_attrs,
                                     &((*child_attr_list)[i]) );
                if ( rc )
                    goto array_free;
            }

#ifdef _LUSTRE
            if (stripe_fields(attr_mask))
            {
                if (get_stripe_info( p_mgr, res[0], &ATTR(&(*child_attr_list)[i], stripe_info),
                                     &ATTR(&(*child_attr_list)[i], stripe_items) ))
                {
                    ATTR_MASK_UNSET(&(*child_attr_list)[i], stripe_info);
                    ATTR_MASK_UNSET(&(*child_attr_list)[i], stripe_items);
                }
            }
#endif

            generate_fields(&((*child_attr_list)[i]));

            /* Note: path is properly sized already to not overflow. */
            sprintf(path, "%s/%s", parent_list[0].fullname,
                    (*child_attr_list)[i].attr_values.name);
            (*child_id_list)[i].fullname = strdup(path);
        }
    }

    if (path)
        free(path);
    db_result_free( &p_mgr->conn, &result );
    return 0;

array_free:
    if (path)
        free(path);
    if (child_attr_list && *child_attr_list)
    {
        MemFree(*child_attr_list);
        *child_attr_list = NULL;
    }
    MemFree(*child_id_list);
    *child_id_list = NULL;
    return rc;
}
Example #23
0
struct lmgr_iterator_t *ListMgr_Iterator( lmgr_t * p_mgr,
                                          const lmgr_filter_t * p_filter,
                                          const lmgr_sort_type_t *
                                          p_sort_type, const lmgr_iter_opt_t * p_opt )
{
    char           query[4096];
    char           filter_str_main[2048];
    char           filter_str_annex[2048];
    char           filter_str_stripe_info[2048];
    char           filter_str_stripe_items[2048];
    int            filter_main = 0;
    int            filter_annex = 0;
    int            filter_stripe_info = 0;
    int            filter_stripe_items = 0;
    int            rc;
    char           fields[2048];
    char           tables[2048];
    lmgr_iterator_t *it;
    table_enum     sort_table = T_NONE;
    int            do_sort = 0;

    filter_str_main[0] = '\0';
    filter_str_annex[0] = '\0';
    filter_str_stripe_info[0] = '\0';
    filter_str_stripe_items[0] = '\0';

    char          *query_end;

    /* Iterator only select a sorted list of ids.
     * Entry attributes are retrieved afterward in ListMgr_GetNext() call.
     */

    /* is there a sort order ? */
    do_sort = ( p_sort_type && ( p_sort_type->order != SORT_NONE ) );

    /* check sort order */
    if ( do_sort )
    {
        if ( is_main_field( p_sort_type->attr_index ) )
            sort_table = T_MAIN;
        else if ( is_annex_field( p_sort_type->attr_index ) )
            sort_table = T_ANNEX;
        else if ( field_infos[p_sort_type->attr_index].db_type == DB_STRIPE_INFO )
            sort_table = T_STRIPE_INFO;
        else if ( field_infos[p_sort_type->attr_index].db_type == DB_STRIPE_ITEMS )
            sort_table = T_STRIPE_ITEMS;
        else
        {
            DisplayLog( LVL_CRIT, LISTMGR_TAG, "Invalid field for sort order (index=%d)", p_sort_type->attr_index );
            return NULL;
        }
    }

    /* check filter location */

    /* /!\ possible cases:
     * - simplest: the fields of the filter and the attributes to be changed are in the same table
     * - harder: the fields of the filter are in the same table and attributes are in another different table 
     */

    /* 1) check the location of filters */

    if ( p_filter )
    {
        filter_main = filter2str( p_mgr, filter_str_main, p_filter, T_MAIN,
                                  FALSE, TRUE );

        if ( annex_table )
            filter_annex = filter2str( p_mgr, filter_str_annex, p_filter,
                                       T_ANNEX, ( filter_main > 0 ), TRUE );
        else
            filter_annex = 0;

        filter_stripe_info =
            filter2str( p_mgr, filter_str_stripe_info, p_filter, T_STRIPE_INFO,
                        ( filter_main > 0 ) || ( filter_annex > 0 ), TRUE );

        filter_stripe_items =
            filter2str( p_mgr, filter_str_stripe_items, p_filter, T_STRIPE_ITEMS,
                        ( filter_main > 0 ) || ( filter_annex > 0 )
                        || ( filter_stripe_info > 0 ), TRUE );


        if ( ( filter_main == 0 ) && ( filter_annex == 0 ) && ( filter_stripe_items == 0 )
             && ( filter_stripe_info == 0 ) )
        {
            /* all records */
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Empty filter: all records will be affected" );
            if ( do_sort )
            {
                /* entries must be selected depending on sort order */
                if ( sort_table == T_MAIN )
                    strcpy( query, "SELECT id FROM " MAIN_TABLE );
                else if ( sort_table == T_ANNEX )
                    strcpy( query, "SELECT id FROM " ANNEX_TABLE );
                else if ( sort_table == T_STRIPE_INFO )
                    strcpy( query, "SELECT id FROM " STRIPE_INFO_TABLE );
                else if ( sort_table == T_STRIPE_ITEMS )
                    strcpy( query, "SELECT DISTINCT(id) FROM " STRIPE_ITEMS_TABLE );
            }
            else
            {
                strcpy( query, "SELECT id FROM " MAIN_TABLE );
            }
        }
        else if ( filter_main && !( filter_annex || filter_stripe_items || filter_stripe_info )
                  && ( !do_sort || ( sort_table == T_MAIN ) ) )
        {
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Filter is only on " MAIN_TABLE " table" );
            sprintf( query, "SELECT id FROM " MAIN_TABLE " WHERE %s", filter_str_main );
        }
        else if ( filter_annex && !( filter_main || filter_stripe_items || filter_stripe_info )
                  && ( !do_sort || ( sort_table == T_ANNEX ) ) )
        {
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Filter is only on " ANNEX_TABLE " table" );
            sprintf( query, "SELECT id FROM " ANNEX_TABLE " WHERE %s", filter_str_annex );
        }
        else if ( filter_stripe_info && !( filter_main || filter_annex || filter_stripe_items )
                  && ( !do_sort || ( sort_table == T_STRIPE_INFO ) ) )
        {
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Filter is only on " STRIPE_INFO_TABLE " table" );
            sprintf( query,
                     "SELECT id FROM " STRIPE_INFO_TABLE " WHERE %s", filter_str_stripe_info );
        }
        else if ( filter_stripe_items && !( filter_main || filter_annex || filter_stripe_info )
                  && ( !do_sort || ( sort_table == T_STRIPE_ITEMS ) ) )
        {
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Filter is only on " STRIPE_ITEMS_TABLE " table" );
            sprintf( query,
                     "SELECT DISTINCT(id) FROM " STRIPE_ITEMS_TABLE
                     " WHERE %s", filter_str_stripe_items );
        }
        else
        {
            char          *curr_fields = fields;
            char          *curr_tables = tables;
            char          *first_table = NULL;

            DisplayLog( LVL_FULL, LISTMGR_TAG,
                        "Filter or sort order on several tables: "
                        MAIN_TABLE ":%d, " ANNEX_TABLE ":%d, "
                        STRIPE_INFO_TABLE ":%d, "
                        STRIPE_ITEMS_TABLE ":%d",
                        filter_main, filter_annex, filter_stripe_info, filter_stripe_items );

            if ( ( filter_main > 0 ) || ( do_sort && ( sort_table == T_MAIN ) ) )
            {
                first_table = MAIN_TABLE;

                if ( filter_main > 0 )
                    curr_fields += sprintf( curr_fields, "%s", filter_str_main );

                curr_tables += sprintf( curr_tables, "%s", MAIN_TABLE );
            }

            if ( ( filter_annex > 0 ) || ( do_sort && ( sort_table == T_ANNEX ) ) )
            {
                if ( filter_annex > 0 )
                    curr_fields += sprintf( curr_fields, "%s", filter_str_annex );

                if ( ( filter_main > 0 ) || ( do_sort && ( sort_table == T_MAIN ) ) )
                {
                    *curr_tables = ',';
                    curr_tables++;

                    /* also add junction condition */
                    curr_fields +=
                        sprintf( curr_fields, " AND %s.id=%s.id", MAIN_TABLE, ANNEX_TABLE );
                }
                else
                    first_table = ANNEX_TABLE;

                curr_tables += sprintf( curr_tables, "%s", ANNEX_TABLE );
            }

            if ( ( filter_stripe_items > 0 ) || ( do_sort && ( sort_table == T_STRIPE_ITEMS ) ) )
            {
                if ( filter_stripe_items > 0 )
                    curr_fields += sprintf( curr_fields, "%s", filter_str_stripe_items );

                if ( ( filter_main > 0 )
                     || ( do_sort && ( sort_table == T_MAIN ) )
                     || ( filter_annex > 0 ) || ( do_sort && ( sort_table == T_ANNEX ) ) )
                {
                    *curr_tables = ',';
                    curr_tables++;

                    /* add junction condition */
                    if ( ( filter_main > 0 ) || ( do_sort && ( sort_table == T_MAIN ) ) )
                        curr_fields +=
                            sprintf( curr_fields, " AND %s.id=%s.id",
                                     MAIN_TABLE, STRIPE_ITEMS_TABLE );
                    if ( ( filter_annex > 0 ) || ( do_sort && ( sort_table == T_ANNEX ) ) )
                        curr_fields +=
                            sprintf( curr_fields, " AND %s.id=%s.id",
                                     ANNEX_TABLE, STRIPE_ITEMS_TABLE );
                }
                else
                    first_table = STRIPE_ITEMS_TABLE;

                curr_tables += sprintf( curr_tables, "%s", STRIPE_ITEMS_TABLE );
            }

            if ( ( filter_stripe_info > 0 ) || ( do_sort && ( sort_table == T_STRIPE_INFO ) ) )
            {
                if ( filter_stripe_info > 0 )
                    curr_fields += sprintf( curr_fields, "%s", filter_str_stripe_info );

                if ( ( filter_main > 0 )
                     || ( do_sort && ( sort_table == T_MAIN ) )
                     || ( filter_annex > 0 ) || ( do_sort && ( sort_table == T_ANNEX ) )
                     || ( filter_stripe_items > 0 ) || ( do_sort
                                                         && ( sort_table == T_STRIPE_ITEMS ) ) )
                {
                    *curr_tables = ',';
                    curr_tables++;

                    /* add junction condition */
                    if ( ( filter_main > 0 ) || ( do_sort && ( sort_table == T_MAIN ) ) )
                        curr_fields +=
                            sprintf( curr_fields, " AND %s.id=%s.id",
                                     MAIN_TABLE, STRIPE_INFO_TABLE );
                    if ( ( filter_annex > 0 ) || ( do_sort && ( sort_table == T_ANNEX ) ) )
                        curr_fields +=
                            sprintf( curr_fields, " AND %s.id=%s.id",
                                     ANNEX_TABLE, STRIPE_INFO_TABLE );
                    if ( ( filter_stripe_items > 0 )
                         || ( do_sort && ( sort_table == T_STRIPE_ITEMS ) ) )
                        curr_fields +=
                            sprintf( curr_fields, " AND %s.id=%s.id", STRIPE_ITEMS_TABLE,
                                     STRIPE_INFO_TABLE );

                }
                else
                    first_table = STRIPE_INFO_TABLE;

                curr_tables += sprintf( curr_tables, "%s", STRIPE_INFO_TABLE );
            }

            sprintf( query, "SELECT %s.id AS id FROM %s WHERE %s", first_table, tables, fields );

        }
    }
    else if ( do_sort )
    {

        /* entries must be selected depending on sort order */
        if ( sort_table == T_MAIN )
            strcpy( query, "SELECT id FROM " MAIN_TABLE );
        else if ( sort_table == T_ANNEX )
            strcpy( query, "SELECT id FROM " ANNEX_TABLE );
        else if ( sort_table == T_STRIPE_ITEMS )
            strcpy( query, "SELECT DISTINCT(id) FROM " STRIPE_ITEMS_TABLE );
        else if ( sort_table == T_STRIPE_INFO )
            strcpy( query, "SELECT id FROM " STRIPE_INFO_TABLE );

    }
    else
    {
        DisplayLog( LVL_FULL, LISTMGR_TAG, "Empty filter: all records will be selected" );
        strcpy( query, "SELECT id FROM " MAIN_TABLE );
    }

    query_end = query + strlen( query );

    /* sort order */
    if ( do_sort )
    {

        if ( sort_table == T_MAIN )
        {
            query_end +=
                sprintf( query_end, " ORDER BY " MAIN_TABLE ".%s ",
                         field_infos[p_sort_type->attr_index].field_name );
        }
        else if ( sort_table == T_ANNEX )
        {
            query_end +=
                sprintf( query_end, " ORDER BY " ANNEX_TABLE ".%s ",
                         field_infos[p_sort_type->attr_index].field_name );
        }
        else if ( sort_table == T_STRIPE_ITEMS )
        {
            query_end += sprintf( query_end, " ORDER BY " STRIPE_ITEMS_TABLE ".storage_unit " );
        }
        else if ( sort_table == T_STRIPE_INFO )
        {
            query_end += sprintf( query_end, " ORDER BY " STRIPE_INFO_TABLE ".pool_name " );
        }

        if ( p_sort_type->order == SORT_ASC )
            query_end += sprintf( query_end, "ASC" );
        else
            query_end += sprintf( query_end, "DESC" );
    }

    /* iterator opt */
    if ( p_opt && ( p_opt->list_count_max > 0 ) )
    {
        query_end += sprintf( query_end, " LIMIT %u", p_opt->list_count_max );
    }

    /* allocate a new iterator */
    it = ( lmgr_iterator_t * ) MemAlloc( sizeof( lmgr_iterator_t ) );
    it->p_mgr = p_mgr;

#ifdef _DEBUG_DB
    printf( "Iterator is specified by: %s\n", query );
#endif

    /* execute request */
    rc = db_exec_sql( &p_mgr->conn, query, &it->select_result );

    if ( rc )
    {
        MemFree( it );
        return NULL;
    }
    else
        return it;

}
Example #24
0
int ListMgr_MassUpdate( lmgr_t * p_mgr,
                        const lmgr_filter_t * p_filter, const attr_set_t * p_attr_set )
{
    char           query[4096];
    char           filter_str_main[2048];
    char           filter_str_annex[2048];
    char           filter_str_stripe_info[2048];
    char           filter_str_stripe_units[2048];
    int            filter_main = 0;
    int            filter_annex = 0;
    int            filter_stripe_info = 0;
    int            filter_stripe_units = 0;
    int            rc, count;
    int            impact_all = FALSE;
    int            filter_unic = FALSE;
    char           fields[2048];
    char           tmp_table_name[256];
    int            tmp_table_created = FALSE;

    filter_str_main[0] = '\0';
    filter_str_annex[0] = '\0';
    filter_str_stripe_info[0] = '\0';
    filter_str_stripe_units[0] = '\0';

    /* /!\ possible cases:
     * - simplest: the fields of the filter and the attributes to be changed are in the same table
     * - harder: the fields of the filter are in the same table and attributes are in another different table 
     */

    /* 1) check the location of filters */

    if ( p_filter )
    {
        filter_main = filter2str( p_mgr, filter_str_main, p_filter, T_MAIN,
                                  FALSE, FALSE );

        if ( annex_table )
            filter_annex = filter2str( p_mgr, filter_str_annex, p_filter,
                                       T_ANNEX, FALSE, FALSE );
        else
            filter_annex = 0;

        filter_stripe_info =
            filter2str( p_mgr, filter_str_stripe_info, p_filter, T_STRIPE_INFO,
                        FALSE, FALSE );

        filter_stripe_units =
            filter2str( p_mgr, filter_str_stripe_units, p_filter,
                        T_STRIPE_ITEMS,FALSE, FALSE );

        if ( filter_main + filter_annex + filter_stripe_info + filter_stripe_units == 0 )
        {
            /* all records */
            impact_all = TRUE;
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Empty filter: all records will be affected" );
        }
        else if ( filter_main && !( filter_annex || filter_stripe_info || filter_stripe_units ) )
        {
            filter_unic = TRUE;
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Filter is only on " MAIN_TABLE " table" );
        }
        else if ( filter_annex && !( filter_main || filter_stripe_info || filter_stripe_units ) )
        {
            filter_unic = TRUE;
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Filter is only on " ANNEX_TABLE " table" );
        }
        else if ( filter_stripe_info && !( filter_main || filter_annex || filter_stripe_units ) )
        {
            filter_unic = TRUE;
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Filter is only on " STRIPE_INFO_TABLE " table" );
        }
        else if ( filter_stripe_units && !( filter_main || filter_annex || filter_stripe_info ) )
        {
            filter_unic = TRUE;
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Filter is only on " STRIPE_ITEMS_TABLE " table" );
        }
        else
            DisplayLog( LVL_FULL, LISTMGR_TAG,
                        "Filter on several tables: " MAIN_TABLE ":%d, "
                        ANNEX_TABLE ":%d, " STRIPE_INFO_TABLE ":%d, "
                        STRIPE_ITEMS_TABLE ":%d",
                        filter_main, filter_annex, filter_stripe_info, filter_stripe_units );
    }
    else
    {
        impact_all = TRUE;
        DisplayLog( LVL_FULL, LISTMGR_TAG, "Empty filter: all records will be affected" );
    }

    /* 2) check if attributes to be changed are in MAIN table */
    /* 3) if filters are in MAIN table too, make a simple update statement */
    /* 4) if not, make a compound request: update xxx set xxx WHERE pk in ( select pk from ... where ... ) */

    rc = lmgr_begin( p_mgr );
    if ( rc )
        return rc;

    /* perform updates on MAIN TABLE */
    count = attrset2updatelist( p_mgr, fields, p_attr_set, T_MAIN, FALSE );
    if ( count < 0 )
        return -count;
    if ( count > 0 )
    {
        DisplayLog( LVL_FULL, LISTMGR_TAG, "Update on " MAIN_TABLE " table" );

        if ( impact_all )
        {
            /* all records are impacted */
            sprintf( query, "UPDATE " MAIN_TABLE " SET %s", fields );
        }
        else if ( filter_unic && filter_main )
        {
            /* update on the same table as filter */
            sprintf( query, "UPDATE " MAIN_TABLE " SET %s WHERE %s", fields, filter_str_main );
        }
        else if ( filter_unic )
        {
            /* update is on a different table than filter */
            if ( filter_annex )
            {
                if ( !tmp_table_created )
                {
                    /* create temp table */
                    sprintf( tmp_table_name, "TMP_TABLE_%u_%u",
                             ( unsigned int ) getpid(  ), ( unsigned int ) pthread_self(  ) );

                    sprintf( query,
                             "CREATE TEMPORARY TABLE %s AS SELECT id FROM "
                             ANNEX_TABLE " WHERE %s", tmp_table_name, filter_str_annex );

                    rc = db_exec_sql( &p_mgr->conn, query, NULL );
                    if ( rc )
                        goto rollback;

                    tmp_table_created = TRUE;
                }

                DisplayLog( LVL_MAJOR, LISTMGR_TAG, "WARNING: passing through unoptimized algorithm" );
                sprintf( query,
                         "UPDATE " MAIN_TABLE
                         " SET %s WHERE id IN (SELECT id FROM %s)", fields, tmp_table_name );

            }
            else if ( filter_stripe_units )
            {
                if ( !tmp_table_created )
                {
                    sprintf( tmp_table_name, "TMP_TABLE_%u_%u",
                             ( unsigned int ) getpid(  ), ( unsigned int ) pthread_self(  ) );

                    /* create temp table */
                    sprintf( query,
                             "CREATE TEMPORARY TABLE %s AS SELECT id FROM "
                             STRIPE_ITEMS_TABLE " WHERE %s", tmp_table_name,
                             filter_str_stripe_units );

                    rc = db_exec_sql( &p_mgr->conn, query, NULL );
                    if ( rc )
                        goto rollback;

                    tmp_table_created = TRUE;
                }

                DisplayLog( LVL_MAJOR, LISTMGR_TAG, "WARNING: passing through unoptimized algorithm" );

                sprintf( query,
                         "UPDATE " MAIN_TABLE
                         " SET %s WHERE id IN (SELECT id FROM %s)", fields, tmp_table_name );
            }
            else if ( filter_stripe_info )
            {
                if ( !tmp_table_created )
                {
                    sprintf( tmp_table_name, "TMP_TABLE_%u_%u",
                             ( unsigned int ) getpid(  ), ( unsigned int ) pthread_self(  ) );

                    /* create temp table */
                    sprintf( query,
                             "CREATE TEMPORARY TABLE %s AS SELECT id FROM "
                             STRIPE_INFO_TABLE " WHERE %s", tmp_table_name,
                             filter_str_stripe_info );

                    rc = db_exec_sql( &p_mgr->conn, query, NULL );
                    if ( rc )
                        goto rollback;

                    tmp_table_created = TRUE;
                }

                DisplayLog( LVL_MAJOR, LISTMGR_TAG, "WARNING: passing through unoptimized algorithm" );

                sprintf( query,
                         "UPDATE " MAIN_TABLE
                         " SET %s WHERE id IN (SELECT id FROM %s)", fields, tmp_table_name );
            }

        }
        else
        {
            /* @todo mixed filter :-s */
            rc = DB_NOT_SUPPORTED;
            goto rollback;
        }

        rc = db_exec_sql( &p_mgr->conn, query, NULL );
        if ( rc )
            goto rollback;
    }


    /* update on annex table ? */
    if ( annex_table )
    {
        count = attrset2updatelist( p_mgr, fields, p_attr_set, T_ANNEX, FALSE );
        if ( count < 0 )
            return -count;
        if ( count > 0 )
        {
            DisplayLog( LVL_FULL, LISTMGR_TAG, "Update on " ANNEX_TABLE " table" );

            if ( impact_all )
            {
                /* all records are impacted */
                sprintf( query, "UPDATE " ANNEX_TABLE " SET %s", fields );
            }
            else if ( filter_unic && filter_annex )
            {
                /* update on the same table as filter */
                sprintf( query,
                         "UPDATE " ANNEX_TABLE " SET %s WHERE %s", fields, filter_str_annex );
            }
            else if ( filter_unic )
            {
                /* update is on a different table than filter */
                if ( filter_main )
                {
                    if ( !tmp_table_created )
                    {
                        /* create temp table */
                        sprintf( tmp_table_name, "TMP_TABLE_%u_%u",
                                 ( unsigned int ) getpid(  ), ( unsigned int ) pthread_self(  ) );

                        sprintf( query,
                                 "CREATE TEMPORARY TABLE %s AS SELECT id FROM "
                                 MAIN_TABLE " WHERE %s", tmp_table_name, filter_str_main );

                        rc = db_exec_sql( &p_mgr->conn, query, NULL );
                        if ( rc )
                            goto rollback;

                        tmp_table_created = TRUE;
                    }

                    DisplayLog( LVL_MAJOR, LISTMGR_TAG, "WARNING: passing through unoptimized algorithm" );

                    sprintf( query,
                             "UPDATE " ANNEX_TABLE
                             " SET %s WHERE id IN (SELECT id FROM %s)", fields, tmp_table_name );

                }
                else if ( filter_stripe_units )
                {

                    if ( !tmp_table_created )
                    {
                        /* create temp table */
                        sprintf( tmp_table_name, "TMP_TABLE_%u_%u",
                                 ( unsigned int ) getpid(  ), ( unsigned int ) pthread_self(  ) );

                        sprintf( query,
                                 "CREATE TEMPORARY TABLE %s AS SELECT id FROM "
                                 STRIPE_ITEMS_TABLE " WHERE %s",
                                 tmp_table_name, filter_str_stripe_units );

                        rc = db_exec_sql( &p_mgr->conn, query, NULL );
                        if ( rc )
                            goto rollback;

                        tmp_table_created = TRUE;
                    }

                    DisplayLog( LVL_MAJOR, LISTMGR_TAG, "WARNING: passing through unoptimized algorithm" );

                    sprintf( query,
                             "UPDATE " ANNEX_TABLE
                             " SET %s WHERE id IN (SELECT id FROM %s)", fields, tmp_table_name );
                }
                else if ( filter_stripe_info )
                {

                    if ( !tmp_table_created )
                    {
                        /* create temp table */
                        sprintf( tmp_table_name, "TMP_TABLE_%u_%u",
                                 ( unsigned int ) getpid(  ), ( unsigned int ) pthread_self(  ) );

                        sprintf( query,
                                 "CREATE TEMPORARY TABLE %s AS SELECT id FROM "
                                 STRIPE_INFO_TABLE " WHERE %s",
                                 tmp_table_name, filter_str_stripe_info );

                        rc = db_exec_sql( &p_mgr->conn, query, NULL );
                        if ( rc )
                            goto rollback;

                        tmp_table_created = TRUE;
                    }

                    DisplayLog( LVL_MAJOR, LISTMGR_TAG, "WARNING: passing through unoptimized algorithm" );

                    sprintf( query,
                             "UPDATE " ANNEX_TABLE
                             " SET %s WHERE id IN (SELECT id FROM %s)", fields, tmp_table_name );
                }
            }
            else
            {
                /* @todo mixed filter :-s */
                rc = DB_NOT_SUPPORTED;
                goto rollback;
            }

            rc = db_exec_sql( &p_mgr->conn, query, NULL );
            if ( rc )
                goto rollback;
        }
    }


    if ( ATTR_MASK_TEST( p_attr_set, stripe_info ) || ATTR_MASK_TEST( p_attr_set, stripe_items ) )
    {
        /* XXX is there a case where stripe info is to be updated massively ? */
        rc = DB_NOT_SUPPORTED;
        goto rollback;
    }

    if ( tmp_table_created )
    {
        sprintf( query, "DROP TABLE %s", tmp_table_name );
        rc = db_exec_sql( &p_mgr->conn, query, NULL );
        if ( rc )
            goto rollback;
    }

    return lmgr_commit( p_mgr );

  rollback:
    lmgr_rollback( p_mgr );
    return rc;
}
Example #25
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 );
}
Example #26
0
/** retrieve directory attributes (nbr of entries, avg size of entries)*/
int listmgr_get_dirattrs( lmgr_t * p_mgr, PK_ARG_T dir_pk, attr_set_t * p_attrs )
{
    GString         *req;
    result_handle_t  result;
    char            *str_info[1];
    int              rc = 0;
    int              tmp_val;
    long long        tmp_long;

    if (ATTR_MASK_TEST(p_attrs, type) &&
        (strcmp(ATTR(p_attrs, type), STR_TYPE_DIR) != 0))
    {
        DisplayLog(LVL_FULL, LISTMGR_TAG,
                   "Type='%s' != 'dir' => unsetting dirattrs in attr mask",
                   ATTR(p_attrs, type));
        p_attrs->attr_mask = attr_mask_and_not(&p_attrs->attr_mask, &dir_attr_set);
        return 0;
    }

    req = g_string_new(NULL);

    /* get child entry count from DNAMES_TABLE */
    if (ATTR_MASK_TEST(p_attrs, dircount))
    {
        g_string_printf(req, "SELECT %s FROM "DNAMES_TABLE" WHERE parent_id="DPK,
                        dirattr2str(ATTR_INDEX_dircount), dir_pk);

        rc = db_exec_sql(&p_mgr->conn, req->str, &result);
        if (rc)
            goto free_str;

        rc = db_next_record(&p_mgr->conn, &result, str_info, 1);
        if (rc == DB_END_OF_LIST)
        {
            ATTR_MASK_UNSET(p_attrs, dircount);
            rc = DB_SUCCESS;
        }
        else if (rc == DB_SUCCESS)
        {
            if (str_info[0] == NULL)
                /* count(*) should at least return 0 */
                rc = DB_REQUEST_FAILED;
            else
            {
                tmp_val = str2int(str_info[0]);
                if (tmp_val != -1)
                {
                    ATTR_MASK_SET(p_attrs, dircount);
                    ATTR(p_attrs, dircount) = tmp_val;
                    rc = DB_SUCCESS;
                }
                else
                    /* invalid output format */
                    rc = DB_REQUEST_FAILED;
            }
        }
        db_result_free(&p_mgr->conn, &result);
        if (rc)
            goto free_str;
    }

    /* get avgsize of child entries from MAIN_TABLE */
    if (ATTR_MASK_TEST(p_attrs, avgsize))
    {
        g_string_printf(req, "SELECT %s FROM "MAIN_TABLE" m, "DNAMES_TABLE" d"
                        " WHERE m.id = d.id and type='file' and d.parent_id="DPK,
                        dirattr2str(ATTR_INDEX_avgsize), dir_pk);

        rc = db_exec_sql(&p_mgr->conn, req->str, &result);
        if (rc)
            goto free_str;

        rc = db_next_record(&p_mgr->conn, &result, str_info, 1);
        if (rc == DB_END_OF_LIST)
            ATTR_MASK_UNSET(p_attrs, avgsize);
        else if (rc == DB_SUCCESS)
        {
            if (str_info[0] == NULL)
            {
                /* NULL if no entry matches the criteria */
                ATTR_MASK_UNSET(p_attrs, avgsize);
                rc = DB_SUCCESS;
            }
            else
            {
                tmp_long = str2bigint(str_info[0]);
                if (tmp_long != -1LL)
                {
                    ATTR_MASK_SET(p_attrs, avgsize);
                    ATTR(p_attrs, avgsize) = tmp_long;
                    rc = DB_SUCCESS;
                }
                else
                    /* invalid output format */
                    rc = DB_REQUEST_FAILED;
            }
        }
        db_result_free(&p_mgr->conn, &result);
    }

free_str:
    g_string_free(req, TRUE);
    return rc;
}
Example #27
0
/**
 *  Retrieve entry attributes from its primary key
 */
int listmgr_get_by_pk( lmgr_t * p_mgr, PK_ARG_T pk, attr_set_t * p_info )
{
    int            rc;
    char           fieldlist[4096] = "";
    char          *first_table = NULL;
    char           from[1024] = "";
    char           query[4096] = "";
    /* we assume there is not more than 128 fields */
    char          *result_tab[128];
    result_handle_t result;
    int checkmain = 1;
    int main_count = 0, annex_count = 0, name_count = 0;

    if (p_info == NULL)
        return 0;

    /* init entry info */
    memset( &p_info->attr_values, 0, sizeof( entry_info_t ) );
    fieldlist[0] = '\0';

    /* retrieve source info for generated fields */
    add_source_fields_for_gen( &p_info->attr_mask );

    /* get info from main table (if asked) */
    main_count = attrmask2fieldlist(fieldlist, p_info->attr_mask, T_MAIN, FALSE,
                                    FALSE, "", "");
    if (main_count < 0)
        return -main_count;
    else if (main_count > 0)
    {
        checkmain = 0;
        first_table = MAIN_TABLE;
        sprintf(from, MAIN_TABLE);
    }

    annex_count = attrmask2fieldlist(fieldlist + strlen(fieldlist),
                                     p_info->attr_mask, T_ANNEX,
                                     first_table != NULL, FALSE, "", "");
    if (annex_count < 0)
        return -annex_count;
    else if (annex_count > 0)
    {
        if (first_table)
            sprintf(from + strlen(from), " LEFT JOIN "ANNEX_TABLE" ON %s.id="
                    ANNEX_TABLE".id", first_table);
        else
        {
            first_table = ANNEX_TABLE;
            sprintf(from, ANNEX_TABLE);
        }
    }

    name_count = attrmask2fieldlist(fieldlist + strlen(fieldlist),
                                    p_info->attr_mask, T_DNAMES,
                                    first_table != NULL, FALSE, "", "");
    if (name_count < 0)
        return -name_count;
    else if (name_count > 0)
    {
        if (first_table)
            /* it's OK to JOIN with NAMES table here even if there are multiple paths,
             * as we only take one result record. The important thing is to return
             * consistent values for parent_id, name and fullpath. */
            sprintf(from + strlen(from), " LEFT JOIN "DNAMES_TABLE" ON %s.id="
                    DNAMES_TABLE".id", first_table);
        else
        {
            first_table = DNAMES_TABLE;
            sprintf(from, DNAMES_TABLE);
        }
    }

    if (first_table != NULL)
    {
        int shift = 0;
        sprintf(query, "SELECT %s FROM %s WHERE %s.id="DPK, fieldlist, from,
                first_table, pk);

        rc = db_exec_sql(&p_mgr->conn, query, &result);
        if (rc)
            return rc;

        rc = db_next_record(&p_mgr->conn, &result, result_tab,
                            main_count + annex_count + name_count);
        /* END_OF_LIST means it does not exist */
        if (rc == DB_END_OF_LIST)
            rc = DB_NOT_EXISTS;
        if (rc)
            goto free_res;

        /* set info from result */
        if (main_count)
        {
            rc = result2attrset(T_MAIN, result_tab + shift, main_count, p_info);
            shift += main_count;
            if (rc)
                goto free_res;
        }
        if (annex_count)
        {
            rc = result2attrset(T_ANNEX, result_tab + shift, annex_count,
                                p_info);
            shift += annex_count;
            if (rc)
                goto free_res;
        }
        if (name_count)
        {
            rc = result2attrset(T_DNAMES, result_tab + shift, name_count,
                                p_info);
            shift += name_count;
            if (rc)
                goto free_res;
        }

        db_result_free(&p_mgr->conn, &result);
    }

    /* remove stripe info if it is not a file */
    if (stripe_fields(p_info->attr_mask) && ATTR_MASK_TEST(p_info, type)
        && strcmp(ATTR(p_info, type), STR_TYPE_FILE) != 0)
    {
        p_info->attr_mask &= ~stripe_attr_set;
    }

    /* get stripe info if asked */
#ifdef _LUSTRE
    if (stripe_fields( p_info->attr_mask ))
    {
        rc = get_stripe_info( p_mgr, pk, &ATTR( p_info, stripe_info ),
                              ATTR_MASK_TEST( p_info, stripe_items ) ? &ATTR( p_info,
                                                                              stripe_items ) :
                              NULL );
        if ( rc == DB_ATTR_MISSING || rc == DB_NOT_EXISTS )
        {
            p_info->attr_mask &= ~ATTR_MASK_stripe_info;

            if ( ATTR_MASK_TEST( p_info, stripe_items ) )
                p_info->attr_mask &= ~ATTR_MASK_stripe_items;
        }
        else if ( rc )
            return rc;
        else
            checkmain = 0; /* entry exists */
    }
#else
    /* always clean them */
    p_info->attr_mask &= ~(ATTR_MASK_stripe_info | ATTR_MASK_stripe_items);
#endif

    /* special field dircount */
    if (dirattr_fields( p_info->attr_mask ))
    {
        if (listmgr_get_dirattrs(p_mgr, pk, p_info))
        {
            DisplayLog( LVL_MAJOR, LISTMGR_TAG, "listmgr_get_dirattrs failed for "DPK, pk );
            p_info->attr_mask &= ~dir_attr_set;
        }
    }

    if (checkmain)
    {
        /* verify it exists in main table */
        sprintf( query, "SELECT id FROM " MAIN_TABLE " WHERE id="DPK, pk );

        /* execute the request */
        rc = db_exec_sql( &p_mgr->conn, query, &result );
        if ( rc )
            return rc;

        rc = db_next_record( &p_mgr->conn, &result, result_tab, 1 );
        db_result_free( &p_mgr->conn, &result );
        if (rc)
            return DB_NOT_EXISTS;
    }

    /* compute generated fields if asked */
    generate_fields( p_info );

    p_mgr->nbop[OPIDX_GET]++;

    return DB_SUCCESS;

  free_res:
    db_result_free( &p_mgr->conn, &result );
    return rc;
}                               /* listmgr_get_by_pk */
Example #28
0
/**
 * Builds a report from database.
 */
struct lmgr_report_t *ListMgr_Report(lmgr_t *p_mgr,
                                     const report_field_descr_t *
                                     report_desc_array,
                                     unsigned int report_descr_count,
                                     const profile_field_descr_t *
                                     profile_descr,
                                     const lmgr_filter_t *p_filter,
                                     const lmgr_iter_opt_t *p_opt)
{
    unsigned int i;
    char attrname[128];
    lmgr_report_t *p_report;
    int rc;
    table_enum query_tab;
    /* supported report fields: ENTRIES, ANNEX_INFO or ACCT */
    bool use_acct_table = false;
    lmgr_iter_opt_t opt = { 0 };
    unsigned int profile_len = 0;
    unsigned int ratio = 0;
    struct field_count fcnt = { 0 };
    GString *req = NULL;
    GString *fields = NULL;
    GString *where = NULL;
    GString *having = NULL;
    GString *group_by = NULL;
    GString *order_by = NULL;
    GString *filter_name = NULL;

    /* check profile argument and increase output array if needed */
    if (profile_descr != NULL) {
        if (profile_descr->attr_index != ATTR_INDEX_size) {
            DisplayLog(LVL_CRIT, LISTMGR_TAG,
                       "Profile on attribute '%s' (index=%u) is not supported",
                       field_name(profile_descr->attr_index),
                       profile_descr->attr_index);
            return NULL;
        }
        profile_len = SZ_PROFIL_COUNT;
        if (profile_descr->range_ratio_len > 0)
            ratio = 1;
    }

    /* allocate a new report structure */
    p_report = (lmgr_report_t *) MemAlloc(sizeof(lmgr_report_t));
    if (!p_report)
        return NULL;

    p_report->p_mgr = p_mgr;

    p_report->result = (struct result *)MemCalloc(report_descr_count
                                                  + profile_len + ratio,
                                                  sizeof(struct result));
    if (!p_report->result)
        goto free_report;

    p_report->result_count = report_descr_count + profile_len + ratio;
    p_report->profile_count = profile_len;
    p_report->ratio_count = ratio;
    if (profile_descr != NULL)
        p_report->profile_attr = ATTR_INDEX_size;

    /* initially, no char * tab allocated */
    p_report->str_tab = NULL;

    if (p_opt)
        opt = *p_opt;

    fields = g_string_new(NULL);
    group_by = g_string_new(NULL);
    order_by = g_string_new(NULL);
    having = g_string_new(NULL);
    where = g_string_new(NULL);

    if (full_acct(report_desc_array, report_descr_count, p_filter)
        && !opt.force_no_acct) {
        listmgr_optimizedstat(p_report, p_mgr, report_descr_count,
                              report_desc_array, profile_descr, fields,
                              group_by, order_by, having, where);
        use_acct_table = true;
    } else {    /* not only ACCT table */

        /* sorting by ratio first */
        if (profile_descr && profile_descr->range_ratio_len > 0) {
            if (profile_descr->attr_index == ATTR_INDEX_size) {
                coma_if_needed(order_by);
                if (profile_descr->range_ratio_sort == SORT_ASC)
                    g_string_append(order_by, "sizeratio ASC");
                else
                    g_string_append(order_by, "sizeratio DESC");
            }
        }

        for (i = 0; i < report_descr_count; i++) {
            /* no field for count or distinct count */
            if (report_desc_array[i].report_type != REPORT_COUNT &&
                report_desc_array[i].report_type != REPORT_COUNT_DISTINCT) {
                /* in what table is this field ? */
                if (is_main_field(report_desc_array[i].attr_index))
                    fcnt.nb_main++;
                else if (is_annex_field(report_desc_array[i].attr_index))
                    fcnt.nb_annex++;
                else {
                    /* Not supported yet */
                    DisplayLog(LVL_CRIT, LISTMGR_TAG,
                               "Error: report on attribute '%s' (index=%u) is not supported (report item #%u).",
                               field_name(report_desc_array[i].attr_index),
                               report_desc_array[i].attr_index, i);
                    rc = DB_NOT_SUPPORTED;
                    goto free_str;
                }
            }

            sprintf(attrname, "attr%u", i);

            /* what kind of stat on this field ? */
            switch (report_desc_array[i].report_type) {
            case REPORT_MIN:
                coma_if_needed(fields);
                g_string_append_printf(fields, "MIN(%s) as %s",
                                       field_str(report_desc_array[i].
                                                 attr_index), attrname);
                p_report->result[i].type =
                    field_type(report_desc_array[i].attr_index);
                break;

            case REPORT_MAX:
                coma_if_needed(fields);
                g_string_append_printf(fields, "MAX(%s) as %s",
                                       field_str(report_desc_array[i].
                                                 attr_index), attrname);
                p_report->result[i].type =
                    field_type(report_desc_array[i].attr_index);
                break;

            case REPORT_AVG:
                coma_if_needed(fields);
                g_string_append_printf(fields, "ROUND(AVG(%s)) as %s",
                                       field_str(report_desc_array[i].
                                                 attr_index), attrname);
                p_report->result[i].type =
                    field_type(report_desc_array[i].attr_index);
                break;

            case REPORT_SUM:
                coma_if_needed(fields);
                g_string_append_printf(fields, "SUM(%s) as %s",
                                       field_str(report_desc_array[i].
                                                 attr_index), attrname);
                p_report->result[i].type =
                    field_type(report_desc_array[i].attr_index);
                break;

            case REPORT_COUNT:
                coma_if_needed(fields);
                g_string_append_printf(fields, "COUNT(*) as %s", attrname);
                p_report->result[i].type = DB_BIGUINT;
                break;

            case REPORT_COUNT_DISTINCT:
                coma_if_needed(fields);
                g_string_append_printf(fields, "COUNT(DISTINCT(%s)) as %s",
                                       field_str(report_desc_array[i].
                                                 attr_index), attrname);
                p_report->result[i].type = DB_BIGUINT;
                break;

            case REPORT_GROUP_BY:
                coma_if_needed(fields);
                g_string_append_printf(fields, "%s as %s",
                                       field_str(report_desc_array[i].
                                                 attr_index), attrname);
                coma_if_needed(group_by);
                g_string_append(group_by, attrname);
                p_report->result[i].type =
                    field_type(report_desc_array[i].attr_index);
                break;
            }

            /* is this field sorted ? */
            append_sort_order(order_by, attrname,
                              report_desc_array[i].sort_flag);

            /* is this field filtered ? */
            listmgr_fieldfilter(p_report, p_mgr, report_desc_array, attrname,
                                having, where, i);

            p_report->result[i].flags =
                field_flag(report_desc_array[i].attr_index);
        }

        /* generate size profile */
        if (profile_descr != NULL) {
            if (profile_descr->attr_index == ATTR_INDEX_size) {
                coma_if_needed(fields);
                g_string_append(fields, "SUM(size=0)");

                for (i = 1; i < SZ_PROFIL_COUNT - 1; i++)
                    g_string_append_printf(fields,
                                           ",SUM(" SZRANGE_FUNC "(size)=%u)",
                                           i - 1);

                g_string_append_printf(fields,
                                       ",SUM(" SZRANGE_FUNC "(size)>=%u)",
                                       SZ_PROFIL_COUNT - 1);

                for (i = 0; i < SZ_PROFIL_COUNT; i++)
                    p_report->result[i + report_descr_count].type = DB_BIGUINT;

                if (profile_descr->range_ratio_len > 0) {
                    /* add ratio field and sort it */
                    coma_if_needed(fields);
                    g_string_append_printf(fields, "SUM(size>=%llu",
                                           SZ_MIN_BY_INDEX(profile_descr->
                                                           range_ratio_start));

                    /* is the last range = 1T->inf ? */
                    if (profile_descr->range_ratio_start +
                        profile_descr->range_ratio_len >= SZ_PROFIL_COUNT)
                        g_string_append(fields, ")");
                    else
                        g_string_append_printf(fields, " and size<%llu)",
                            SZ_MIN_BY_INDEX(profile_descr->range_ratio_start
                                            + profile_descr->range_ratio_len));

                    g_string_append(fields, "/COUNT(*) as sizeratio");
                }
            }
        }
    }

    /* process filter */
    if (!(no_filter(p_filter))) {
        if (full_acct(report_desc_array, report_descr_count, p_filter)
            && !opt.force_no_acct) {
            int filter_acct;

            /* filter on acct fields only */
            filter_acct = filter2str(p_mgr, where, p_filter, T_ACCT,
                               (!GSTRING_EMPTY(where) ? AOF_LEADING_SEP : 0)
                               | AOF_PREFIX);
            if (filter_acct > 0)
                use_acct_table = true;
        } else {
            /* process NAMES filters apart, as with must then join with
             * DISTINCT(id) */
            filter_where(p_mgr, p_filter, &fcnt, where,
                         (!GSTRING_EMPTY(where) ? AOF_LEADING_SEP : 0)
                         | AOF_SKIP_NAME);

            filter_name = g_string_new(NULL);
            fcnt.nb_names =
                filter2str(p_mgr, filter_name, p_filter, T_DNAMES, 0);
        }
    }

    /* start building the whole request */
    req = g_string_new("SELECT ");
    g_string_append_printf(req, "%s FROM ", fields->str);

    /* FROM clause */
    if (use_acct_table) {
        g_string_append(req, ACCT_TABLE);
        query_tab = T_ACCT;
    } else {
        bool distinct;

        filter_from(p_mgr, &fcnt, req, &query_tab, &distinct, AOF_SKIP_NAME);

        if (filter_name != NULL && !GSTRING_EMPTY(filter_name)) {
            g_string_append_printf(req, " INNER JOIN (SELECT DISTINCT(id)"
                                   " FROM " DNAMES_TABLE " WHERE %s) N"
                                   " ON %s.id=N.id", filter_name->str,
                                   table2name(query_tab));
            /* FIXME: what if NAMES is the query tab? */
        }
        /* FIXME: do the same for stripe items */
    }

    /* Build the request */
    if (!GSTRING_EMPTY(where))
        g_string_append_printf(req, " WHERE %s", where->str);

    if (!GSTRING_EMPTY(group_by))
        g_string_append_printf(req, " GROUP BY %s", group_by->str);

    if (!GSTRING_EMPTY(having))
        g_string_append_printf(req, " HAVING %s", having->str);

    if (!GSTRING_EMPTY(order_by))
        g_string_append_printf(req, " ORDER BY %s", order_by->str);

    /* iterator opt */
    if (opt.list_count_max > 0)
        g_string_append_printf(req, " LIMIT %u", opt.list_count_max);

 retry:
    /* execute request (expect that ACCT table does not exists) */
    if (use_acct_table)
        rc = db_exec_sql_quiet(&p_mgr->conn, req->str,
                               &p_report->select_result);
    else
        rc = db_exec_sql(&p_mgr->conn, req->str, &p_report->select_result);

    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;

    /* if the ACCT table does exist, switch to standard mode */
    if (use_acct_table && (rc == DB_NOT_EXISTS)) {
        lmgr_iter_opt_t new_opt;

        if (p_opt != NULL)
            new_opt = *p_opt;
        else
            new_opt.list_count_max = 0;

        new_opt.force_no_acct = true;

        DisplayLog(LVL_EVENT, LISTMGR_TAG,
                   "No accounting info: switching to standard query mode");

        g_string_free(req, TRUE);
        g_string_free(fields, TRUE);
        g_string_free(group_by, TRUE);
        g_string_free(order_by, TRUE);
        g_string_free(having, TRUE);
        g_string_free(where, TRUE);
        if (filter_name != NULL)
            g_string_free(filter_name, TRUE);

        return ListMgr_Report(p_mgr, report_desc_array, report_descr_count,
                              profile_descr, p_filter, &new_opt);
    }

 free_str:
    /* these are always allocated */
    g_string_free(fields, TRUE);
    g_string_free(group_by, TRUE);
    g_string_free(order_by, TRUE);
    g_string_free(having, TRUE);
    g_string_free(where, TRUE);
    /* these may not be allocated */
    if (req != NULL)
        g_string_free(req, TRUE);
    if (filter_name != NULL)
        g_string_free(filter_name, TRUE);

    if (rc == DB_SUCCESS)
        return p_report;

/* error */
    MemFree(p_report->result);

 free_report:
    MemFree(p_report);
    return NULL;
}   /* ListMgr_Report */
Example #29
0
/**
 * Main daemon routine
 */
int main( int argc, char **argv )
{
    int            c = 0;
    char          *bin = basename( argv[0] );
    int            rc;
    char           err_msg[4096];
    robinhood_config_t config;
    int chgd = 0;

    /* options */
    char           config_file[MAX_OPT_LEN] = "";
    char           badcfg[RBH_PATH_MAX];
    int            force_log_level = FALSE;
    int            log_level = 0;
    int            margin = 0;
    char           output_file[MAX_OPT_LEN] = "/tmp/lov_objid";

    lmgr_t         lmgr;
    FILE         * out;

    /* parse command line options */
    while ((c = getopt(argc, argv, OPT_STRING)) != -1)
    {
        switch (c)
        {
            case 'l':
                force_log_level = TRUE;
                log_level = str2debuglevel(optarg);
                if (log_level == -1)
                {
                    fprintf( stderr,
                             "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n",
                             optarg );
                    exit(1);
                }
                break;
            case 'f':
                rh_strncpy(config_file, optarg, MAX_OPT_LEN);
                break;
            case 'o':
                rh_strncpy(output_file, optarg, MAX_OPT_LEN);
                break;
            case 'm':
                margin = str2int(optarg);
                if (margin < 0)
                {
                    fprintf( stderr,
                             "Invalid parameter '%s' for '-m' option: positive integer expected\n",
                             optarg );
                    exit(1);
                }
                break;
            case ':':
            case '?':
            default:
                display_help(bin);
                exit( 1 );
                break;
        }
    }

    /* get default config file, if not specified */
    if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0)
    {
        fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg);
        exit(2);
    }
    else if (chgd)
    {
        fprintf(stderr, "Using config file '%s'.\n", config_file );
    }

    /* only read ListMgr config */

    if ( ReadRobinhoodConfig( 0, config_file, err_msg, &config, FALSE ) )
    {
        fprintf( stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg );
        exit( 1 );
    }
    process_config_file = config_file;

    /* set global configuration */
    global_config = config.global_config;

    if ( force_log_level )
        config.log_config.debug_level = log_level;
    else
        config.log_config.debug_level = LVL_MAJOR; /* no event message */

    /* set logging to stderr for this tool */
    strcpy( config.log_config.log_file, "stderr" );
    strcpy( config.log_config.report_file, "stderr" );
    strcpy( config.log_config.alert_file, "stderr" );

    /* Initialize logging */
    rc = InitializeLogs( bin, &config.log_config );
    if ( rc )
    {
        fprintf( stderr, "Error opening log files: rc=%d, errno=%d: %s\n",
                 rc, errno, strerror( errno ) );
        exit( rc );
    }

    /* Initialize list manager */
    rc = ListMgr_Init( &config.lmgr_config, TRUE );
    if ( rc )
    {
        DisplayLog( LVL_CRIT, TAG, "Error %d initializing list manager", rc );
        exit( rc );
    }
    else
        DisplayLog( LVL_DEBUG, TAG, "ListManager successfully initialized" );

    if ( CheckLastFS(  ) != 0 )
        exit( 1 );

    /* Create database access */
    rc = ListMgr_InitAccess( &lmgr );
    if ( rc )
    {
        DisplayLog( LVL_CRIT, TAG, "Error %d: cannot connect to database", rc );
        exit( rc );
    }

    out = fopen(output_file, "w");
    if (!out)
    {
        DisplayLog(LVL_CRIT, TAG, "Failed to open '%s' for writting: %s", output_file,
                   strerror(errno));
        return errno;
    }

    /* direct SQL request to retrieve the max object index from DB */
    result_handle_t res;
    /* FIXME max on the low weight 32bits of the 'objid' 64bits value */
    rc = db_exec_sql(&lmgr.conn, "SELECT ostidx, max(hex(cast(reverse(cast(details as binary(8))) as binary(4)))) "
                     "FROM "STRIPE_ITEMS_TABLE" GROUP BY ostidx ORDER BY ostidx", &res);
    if (rc)
        goto db_error;

    int index = -1;
    do
    {
        char *resstr[2];
        unsigned int ostidx;
        unsigned int objid;
        unsigned long long objid_long;
        resstr[0] = resstr[1] = NULL;

        rc = db_next_record( &lmgr.conn, &res, resstr, 2 );
        if (rc == DB_END_OF_LIST)
            break;
        else if (rc != DB_SUCCESS)
            goto db_error;

        index ++;

        if (resstr[0] == NULL || resstr[1] == NULL)
        {
            DisplayLog(LVL_MAJOR, TAG, "ERROR: got NULL record from DB at index %u", index);
            rc = EINVAL;
            goto out;
        }

        /* resstr[0] is ost_idx */
        if (sscanf(resstr[0], "%u", &ostidx) != 1)
        {
            DisplayLog(LVL_MAJOR, TAG, "ERROR: cannot parse OST index '%s' at index %u", resstr[0], index);
            rc = EINVAL;
            goto out;
        }
        else if (ostidx != index)
        {
            DisplayLog(LVL_MAJOR, TAG, "Warning: OST index %u not found in database, assuming current objid=1",
                       index);
            objid_long = 1 + margin;
            printf("ostidx=%u, max objid=%016LX\n", ostidx, objid_long);
            fwrite(&objid_long, sizeof(objid_long), 1, out);
            continue;
        }

        /* resstr[1] is objid (hexa) */
        if (sscanf(resstr[1], "%X", &objid) != 1)
        {
            DisplayLog(LVL_MAJOR, TAG, "ERROR: cannot parse objid '%s' at index %u", resstr[1], index);
            rc = EINVAL;
            goto out;
        }

        objid_long = objid + margin;
        printf("ostidx=%u, objid=%016LX\n", ostidx, objid_long);
        fwrite(&objid_long, sizeof(objid_long), 1, out);

    } while(rc == 0);

    fclose(out);
    ListMgr_CloseAccess( &lmgr );
    return 0;

db_error:
    DisplayLog( LVL_CRIT, TAG, "Database error %d\n", rc);
out:
    ListMgr_CloseAccess( &lmgr );
    return rc;
}
Example #30
0
/**
 * Builds a report from database.
 */
struct lmgr_report_t *ListMgr_Report( lmgr_t * p_mgr,
                                      const report_field_descr_t * report_desc_array,
                                      unsigned int report_descr_count,
                                      const profile_field_descr_t * profile_descr,
                                      const lmgr_filter_t * p_filter,
                                      const lmgr_iter_opt_t * p_opt )
{
    unsigned int   i;

    /* A query consists of 5 parts:
     *  - List of fields to be selected
     *  - FROM clause with joins
     *  - WHERE clause (filters)
     *  - GROUP BY clause
     *  - ORBER BY clause
     */
    char           fields[1024] = "";
    char           from[512] = "";
    char           where[2048] = "";
    char           having[2048] = "";
    char           group_by[512] = "";
    char           order_by[512] = "";
    char           query[4096] = "";

    /* filters on NAMES or STRIPE_ITEMS
     * must be managed differently, as they
     * can create duplicates (non uniq id) */
    char           name_filter_str[1024] = "";
    char           stripe_filter_str[1024] = "";

    char          *curr_field = fields;
    char          *curr_group_by = group_by;
    char          *curr_sort = order_by;
    char          *curr_query = query;
    char          *curr_where = where;
    char          *curr_having = having;

    char           attrname[128];
    char           attrstring[1024];

    lmgr_report_t *p_report;
    int            rc;

    table_enum     query_tab;
    /* supported report fields: ENTRIES, ANNEX_INFO or ACCT */
    int            main_table_flag = FALSE;
    int            annex_table_flag = FALSE;
    int            acct_table_flag = FALSE;
    int            filter_main = 0;
    int            filter_annex = 0;
    int            filter_stripe_info = 0;
    int            filter_stripe_items = 0;
    int            filter_names = 0;
    int            filter_acct = 0;
    int            full_acct = TRUE;
    lmgr_iter_opt_t opt = {0};
    unsigned int   profile_len = 0;
    unsigned int   ratio = 0;

    /* check profile argument and increase output array if needed */
    if (profile_descr != NULL)
    {
        if (profile_descr->attr_index != ATTR_INDEX_size)
        {
            DisplayLog(LVL_CRIT, LISTMGR_TAG, "Profile on attribute #%u is not supported",
                       profile_descr->attr_index);
            return NULL;
        }
        profile_len = SZ_PROFIL_COUNT;
        if (profile_descr->range_ratio_len > 0)
            ratio = 1;
    }

    /* allocate a new report structure */
    p_report = ( lmgr_report_t * ) MemAlloc( sizeof( lmgr_report_t ) );
    if ( !p_report )
        return NULL;

    p_report->p_mgr = p_mgr;

    p_report->result_type_array =
        ( db_type_t * ) MemCalloc( report_descr_count + profile_len + ratio,
                                   sizeof( db_type_t ) );
    if ( !p_report->result_type_array )
        goto free_report;

    p_report->result_count = report_descr_count + profile_len + ratio;
    p_report->profile_count = profile_len;
    p_report->ratio_count = ratio;
    if (profile_descr != NULL)
        p_report->profile_attr = ATTR_INDEX_size;

    /* initialy, no char * tab allocated */
    p_report->str_tab = NULL;

    if (p_opt)
        opt = *p_opt;

    for ( i = 0; i < report_descr_count; i++ )
    {
        if ( ( report_desc_array[i].report_type != REPORT_COUNT ) &&
#ifdef ATTR_INDEX_dircount
                report_desc_array[i].attr_index != ATTR_INDEX_dircount &&
#endif
                !is_acct_field( report_desc_array[i].attr_index ) &&
                !is_acct_pk( report_desc_array[i].attr_index ) )
            full_acct = FALSE;
    }
    if ( p_filter )
    {
        if ( p_filter->filter_type == FILTER_SIMPLE )
        {
            for ( i = 0; i < p_filter->filter_simple.filter_count; i++ )
            {
                if ( !is_acct_pk( p_filter->filter_simple.filter_index[i] ) &&
                        !is_acct_field( p_filter->filter_simple.filter_index[i] ) )
                    full_acct = FALSE;
            }
        }
    }

    if ( full_acct && !opt.force_no_acct )
    {
        listmgr_optimizedstat( p_report, p_mgr, report_descr_count, report_desc_array,
                               profile_descr,
                               fields, &curr_field, group_by, &curr_group_by, order_by, &curr_sort,
                               having, &curr_having, where, &curr_where);
        acct_table_flag = TRUE;
    }
    else /* not only ACCT table */
    {
        /* sorting by ratio first */
        if (profile_descr && profile_descr->range_ratio_len > 0)
        {
            if ( profile_descr->attr_index == ATTR_INDEX_size )
            {
                if (profile_descr->range_ratio_sort == SORT_ASC)
                    add_string( order_by, curr_sort, "sizeratio ASC");
                else
                    add_string( order_by, curr_sort, "sizeratio DESC");
            }
        }

        for ( i = 0; i < report_descr_count; i++ )
        {
            /* no field for count or distinct count */
            if ( report_desc_array[i].report_type != REPORT_COUNT &&
                 report_desc_array[i].report_type != REPORT_COUNT_DISTINCT )
            {
                /* in what table is this field ? */
                if ( is_main_field( report_desc_array[i].attr_index ) )
                    main_table_flag = TRUE;
                else if ( is_annex_field( report_desc_array[i].attr_index ) )
                    annex_table_flag = TRUE;
                else
                {
                    /* Not supported yet */
                    DisplayLog( LVL_CRIT, LISTMGR_TAG,
                                "Error: report on attribute #%u is not supported (report item #%u).",
                                report_desc_array[i].attr_index, i );
                    goto free_field_tab;
                }
            }

            sprintf( attrname, "attr%u", i );

            /* what kind of stat on this field ? */
            switch ( report_desc_array[i].report_type )
            {
            case REPORT_MIN:
                sprintf( attrstring, "MIN( %s ) as %s",
                         field_str( report_desc_array[i].attr_index ), attrname );
                add_string( fields, curr_field, attrstring );
                p_report->result_type_array[i] = field_type( report_desc_array[i].attr_index );
                break;
            case REPORT_MAX:
                sprintf( attrstring, "MAX( %s ) as %s",
                         field_str( report_desc_array[i].attr_index ), attrname );
                add_string( fields, curr_field, attrstring );
                p_report->result_type_array[i] = field_type( report_desc_array[i].attr_index );
                break;
            case REPORT_AVG:
                sprintf( attrstring, "ROUND(AVG( %s )) as %s",
                         field_str( report_desc_array[i].attr_index ), attrname );
                add_string( fields, curr_field, attrstring );
                p_report->result_type_array[i] = field_type( report_desc_array[i].attr_index );
                break;
            case REPORT_SUM:
                sprintf( attrstring, "SUM( %s ) as %s",
                         field_str( report_desc_array[i].attr_index ), attrname );
                add_string( fields, curr_field, attrstring );
                p_report->result_type_array[i] = field_type( report_desc_array[i].attr_index );
                break;
            case REPORT_COUNT:
                sprintf( attrstring, "COUNT(*) as %s", attrname );
                add_string( fields, curr_field, attrstring );
                p_report->result_type_array[i] = DB_BIGUINT;
                break;
            case REPORT_COUNT_DISTINCT:
                sprintf( attrstring, "COUNT(DISTINCT(%s)) as %s",
                field_str( report_desc_array[i].attr_index ), attrname );
                add_string( fields, curr_field, attrstring );
                p_report->result_type_array[i] = DB_BIGUINT;
                break;
            case REPORT_GROUP_BY:
                sprintf( attrstring, "%s as %s", field_str( report_desc_array[i].attr_index ),
                         attrname );
                add_string( fields, curr_field, attrstring );
                add_string( group_by, curr_group_by, attrname );
                p_report->result_type_array[i] = field_type( report_desc_array[i].attr_index );
                break;
            }

            /* is this field sorted ? */

            if ( report_desc_array[i].sort_flag == SORT_ASC )
            {
                sprintf( attrstring, "%s ASC", attrname );
                add_string( order_by, curr_sort, attrstring );
            }
            else if ( report_desc_array[i].sort_flag == SORT_DESC )
            {
                sprintf( attrstring, "%s DESC", attrname );
                add_string( order_by, curr_sort, attrstring );
            }

            /* is this field filtered ? */
            listmgr_fieldfilter( p_report, p_mgr, report_desc_array, attrstring, attrname,
                                having, &curr_having, where, &curr_where, i );
        }

        /* generate size profile */
        if (profile_descr != NULL)
        {
            if (profile_descr->attr_index == ATTR_INDEX_size)
            {
                add_string( fields, curr_field, "SUM(size=0)" );
                for (i=1; i < SZ_PROFIL_COUNT-1; i++)
                    curr_field += sprintf(curr_field, ",SUM("ACCT_SZ_VAL("size")"=%u)", i-1);
                curr_field += sprintf(curr_field, ",SUM("ACCT_SZ_VAL("size")">=%u)", i-1);

                for (i=0; i<SZ_PROFIL_COUNT; i++)
                    p_report->result_type_array[i+report_descr_count] = DB_BIGUINT;

                if (profile_descr->range_ratio_len > 0)
                {
                    /* add ratio field and sort it */
                    attrstring[0] = '\0';
                    char *curr_attr = attrstring;

                    curr_attr += sprintf(curr_attr, "SUM(size>=%Lu",
                                         SZ_MIN_BY_INDEX(profile_descr->range_ratio_start));

                    /* is the last range = 1T->inf ? */
                    if (profile_descr->range_ratio_start + profile_descr->range_ratio_len >= SZ_PROFIL_COUNT)
                        curr_attr += sprintf(curr_attr, ")");
                    else
                        curr_attr += sprintf(curr_attr, " and size<%Lu)",
                                         SZ_MIN_BY_INDEX(profile_descr->range_ratio_start+profile_descr->range_ratio_len));

                    curr_attr += sprintf(curr_attr, "/COUNT(*) as sizeratio");
                    add_string( fields, curr_field, attrstring );
                }
            }
        }

    }
    /* filter */

    if ( p_filter )
    {
        if ( ( full_acct && !opt.force_no_acct ) )
        {
            filter_acct = filter2str( p_mgr, curr_where, p_filter, T_ACCT,
                                      ( where != curr_where ), TRUE );
            curr_where += strlen( curr_where );
            if ( filter_acct )
                acct_table_flag =TRUE;
        }
        else
        {
            /* filter on main table? */
            filter_main = filter2str( p_mgr, curr_where, p_filter, T_MAIN,
                                      ( where != curr_where ), TRUE );
            curr_where += strlen( curr_where );

            if ( filter_main )
                main_table_flag = TRUE;

            /* filter on annex table? */
            if ( annex_table )
            {
                filter_annex = filter2str( p_mgr, curr_where, p_filter, T_ANNEX,
                                           (where != curr_where), TRUE );
                curr_where += strlen( curr_where );

                if ( filter_annex )
                    annex_table_flag = TRUE;
            }

            filter_stripe_info =
                filter2str( p_mgr, curr_where, p_filter, T_STRIPE_INFO,
                            (where != curr_where), TRUE );
            curr_where += strlen( curr_where );

           /*  filter on names table is particular as this may duplicate
             * entries when computing the report (multiple hardlinks) */
            filter_names = filter2str(p_mgr, name_filter_str, p_filter, T_DNAMES,
                                      FALSE, FALSE );

           /*  filter on stripe items table is particular as this may duplicate
             * entries when computing the report (multiple stripes) */
            filter_stripe_items = filter2str(p_mgr, stripe_filter_str, p_filter,
                                             T_STRIPE_ITEMS, FALSE, FALSE);
        }
    }

    /* FROM clause */

    if ( acct_table_flag )
    {
        strcpy( from, ACCT_TABLE );
        query_tab = T_ACCT;
    }
    else
    {
        const char * first_table = NULL;
        char * curr_from = from;
        if ( main_table_flag ) {
            strcpy(from, MAIN_TABLE);
            curr_from = from + strlen(from);
            first_table = MAIN_TABLE;
            query_tab = T_MAIN;
        }

        if ( annex_table_flag )
        {
            if (first_table)
                curr_from += sprintf(curr_from, " LEFT JOIN "ANNEX_TABLE" ON %s.id="ANNEX_TABLE".id",
                                     first_table);
            else
            {
                strcpy(from, ANNEX_TABLE);
                curr_from = from + strlen(from);
                first_table = ANNEX_TABLE;
                query_tab = T_ANNEX;
            }
        }
        if ( filter_stripe_info )
        {
            if (first_table)
                curr_from += sprintf(curr_from, " INNER JOIN "STRIPE_INFO_TABLE" ON %s.id="STRIPE_INFO_TABLE".id",
                                     first_table);
            else
            {
                strcpy(from, STRIPE_INFO_TABLE);
                curr_from = from + strlen(from);
                first_table = STRIPE_INFO_TABLE;
                query_tab = T_STRIPE_INFO;
            }
        }
        if (filter_names)
        {
            if (first_table)
                curr_from += sprintf(curr_from," INNER JOIN (SELECT DISTINCT(id)"
                                     " FROM "DNAMES_TABLE" WHERE %s) N"
                                     " ON %s.id=N.id", name_filter_str,
                                     first_table);
            else
            {
                DisplayLog(LVL_CRIT, LISTMGR_TAG, "Unexpected case: "DNAMES_TABLE
                           " table can't be the query table in %s()", __func__);
                goto free_field_tab;
            }
        }

        if (filter_stripe_items)
        {
            if (first_table)
                curr_from += sprintf(curr_from, " INNER JOIN (SELECT DISTINCT(id)"
                                     " FROM "STRIPE_ITEMS_TABLE" WHERE %s) SI"
                                     " ON %s.id=SI.id", stripe_filter_str,
                                     first_table);
            else
            {
                strcpy(from, STRIPE_ITEMS_TABLE);
                curr_from = from + strlen(from);
                strcpy(curr_where, stripe_filter_str);
                curr_where += strlen(curr_where);
                first_table = STRIPE_ITEMS_TABLE;
                query_tab = T_STRIPE_ITEMS;
                /* XXX the caller is supposed to select DISTINCT(id) in this case */
            }
        }
    }

    /* Build the request */

    curr_query += sprintf( query, "SELECT %s FROM %s", fields, from );

    if ( where[0] )
    {
        curr_query += sprintf( curr_query, " WHERE %s", where );
    }

    if ( group_by[0] )
    {
        curr_query += sprintf( curr_query, " GROUP BY %s", group_by );
    }

    if ( having[0] )
    {
        curr_query += sprintf( curr_query, " HAVING %s", having );
    }


    if ( order_by[0] )
    {
        curr_query += sprintf( curr_query, " ORDER BY %s", order_by );
    }

    /* iterator opt */
    if ( opt.list_count_max > 0 )
    {
        curr_query += sprintf( curr_query, " LIMIT %u", opt.list_count_max );
    }


#ifdef _DEBUG_DB
    printf( "Report is specified by: %s\n", query );
#endif

retry:
    /* execute request (expect that ACCT table does not exists) */
    if (acct_table_flag)
        rc = db_exec_sql_quiet( &p_mgr->conn, query, &p_report->select_result );
    else
        rc = db_exec_sql( &p_mgr->conn, query, &p_report->select_result );

    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;

    /* if the ACCT table does exist, switch to standard mode */
    if ( acct_table_flag && (rc == DB_NOT_EXISTS))
    {
        lmgr_iter_opt_t new_opt;
        if (p_opt != NULL)
            new_opt = *p_opt;
        else
            new_opt.list_count_max = 0;

        new_opt.force_no_acct = TRUE;

        DisplayLog( LVL_EVENT, LISTMGR_TAG, "No accounting info: switching to standard query mode" );

        return ListMgr_Report( p_mgr, report_desc_array, report_descr_count,
                               profile_descr,
                               p_filter, &new_opt );
    }

    if ( rc )
        goto free_field_tab;
    else
        return p_report;

/* error handlers */
  free_field_tab:
    MemFree( p_report->result_type_array );
  free_report:
    MemFree( p_report );
    return NULL;

}                               /* ListMgr_Report */