Ejemplo n.º 1
0
int ListMgr_Insert(lmgr_t *p_mgr, entry_id_t *p_id, attr_set_t *p_info,
                   int update_if_exists)
{
    int rc;
    char buff[4096];

    /* retry the whole transaction when the error is retryable */
retry:
    rc = lmgr_begin(p_mgr);
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    else if (rc)
        return rc;

    rc = listmgr_batch_insert_no_tx(p_mgr, &p_id, &p_info, 1, update_if_exists);
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    else if (rc)
    {
        lmgr_rollback(p_mgr);
        DisplayLog(LVL_CRIT, LISTMGR_TAG,
                   "DB query failed in %s line %d: code=%d: %s",
                   __FUNCTION__, __LINE__, rc, db_errmsg(&p_mgr->conn, buff, 4096));
        return rc;
    }
    rc = lmgr_commit(p_mgr);
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;

    /* success, count it */
    if (!rc)
        p_mgr->nbop[OPIDX_INSERT]++;
    return rc;
}
Ejemplo n.º 2
0
/**
 * Insert a batch of entries into the database.
 * All entries must have the same attr mask.
 */
int            ListMgr_BatchInsert(lmgr_t * p_mgr, entry_id_t ** p_ids,
                                   attr_set_t ** p_attrs,
                                   unsigned int count,
                                   int update_if_exists)
{
    int rc;
    char buff[4096];

    if (count == 0)
        return DB_SUCCESS;
    else if (p_ids == NULL || p_attrs == NULL)
        RBH_BUG("NULL pointer argument");

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

    /* retry the whole transaction when the error is retryable */
retry:
    /* We want insert operation set to be atomic */
    rc = lmgr_begin(p_mgr);
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    else if (rc)
        return rc;

    rc = listmgr_batch_insert_no_tx(p_mgr, p_ids, p_attrs, count, update_if_exists);

    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    else if (rc)
    {
        lmgr_rollback(p_mgr);
        DisplayLog(LVL_CRIT, LISTMGR_TAG,
                   "DB query failed in %s line %d: code=%d: %s",
                   __FUNCTION__, __LINE__, rc, db_errmsg(&p_mgr->conn, buff, 4096));
        return rc;
    }

    rc = lmgr_commit(p_mgr);
    if (lmgr_delayed_retry(p_mgr, rc))
        goto retry;
    /* success, count it */
    if (!rc)
    {
        if (update_if_exists)
            p_mgr->nbop[OPIDX_UPDATE] += count;
        else
            p_mgr->nbop[OPIDX_INSERT] += count;
    }
    return rc;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}