Example #1
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 #2
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 #3
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;
}