Пример #1
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 */
Пример #2
0
/**
 * check if the entry exists in the database and what info
 * must be retrieved.
 */
int EntryProc_get_info_db( struct entry_proc_op_t *p_op, lmgr_t * lmgr )
{
    int      rc = 0;
    int      next_stage = -1; /* -1 = skip */
    attr_mask_t attr_allow_cached = null_mask;
    attr_mask_t attr_need_fresh = null_mask;
    uint32_t status_scope = 0; /* status mask only */
    attr_mask_t tmp;

    const pipeline_stage_t *stage_info =
        &entry_proc_pipeline[p_op->pipeline_stage];

    /* check if entry is in policies scope */
    add_matching_scopes_mask(&p_op->entry_id, &p_op->fs_attrs, true,
                             &status_scope);

    /* XXX also retrieve needed attributes to check the scope? */

    /* get diff attributes from DB and FS (to allow comparison) */
    p_op->db_attr_need = attr_mask_or(&p_op->db_attr_need, &diff_mask);

    tmp = attr_mask_and_not(&diff_mask, &p_op->fs_attrs.attr_mask);
    p_op->fs_attr_need = attr_mask_or(&p_op->fs_attr_need, &tmp);

    if (entry_proc_conf.detect_fake_mtime)
        attr_mask_set_index(&p_op->db_attr_need, ATTR_INDEX_creation_time);

    attr_allow_cached = attrs_for_status_mask(status_scope, false);
    attr_need_fresh = attrs_for_status_mask(status_scope, true);
    /* XXX check if entry is in policy scope? */

    /* what must be retrieved from DB: */
    tmp = attr_mask_and_not(&attr_allow_cached, &p_op->fs_attrs.attr_mask);
    p_op->db_attr_need = attr_mask_or(&p_op->db_attr_need, &tmp);

    /* no dircount for non-dirs */
    if (ATTR_MASK_TEST(&p_op->fs_attrs, type) &&
        !strcmp(ATTR(&p_op->fs_attrs, type), STR_TYPE_DIR))
    {
        attr_mask_unset_index(&p_op->db_attr_need, ATTR_INDEX_dircount);
    }

    /* no readlink for non symlinks */
    if (ATTR_MASK_TEST(&p_op->fs_attrs, type)) /* likely */
    {
        if (!strcmp(ATTR(&p_op->fs_attrs, type), STR_TYPE_LINK))
        {
            attr_mask_set_index(&p_op->db_attr_need, ATTR_INDEX_link); /* check if it is known */
            /* no stripe for symlinks */
            attr_mask_unset_index(&p_op->db_attr_need, ATTR_INDEX_stripe_info);
            attr_mask_unset_index(&p_op->db_attr_need, ATTR_INDEX_stripe_items);
        }
        else
            attr_mask_unset_index(&p_op->db_attr_need, ATTR_INDEX_link);
    }

    if (!attr_mask_is_null(p_op->db_attr_need))
    {
        p_op->db_attrs.attr_mask = p_op->db_attr_need;
        rc = ListMgr_Get(lmgr, &p_op->entry_id, &p_op->db_attrs);

        if (rc == DB_SUCCESS)
        {
            p_op->db_exists = 1;
        }
        else if (rc == DB_NOT_EXISTS )
        {
            p_op->db_exists = 0;
            ATTR_MASK_INIT( &p_op->db_attrs );
        }
        else
        {
            /* ERROR */
            DisplayLog(LVL_CRIT, ENTRYPROC_TAG,
                       "Error %d retrieving entry "DFID" from DB: %s.", rc,
                       PFID(&p_op->entry_id), lmgr_err2str(rc));
            p_op->db_exists = 0;
            ATTR_MASK_INIT( &p_op->db_attrs );
        }
    }
    else
    {
        p_op->db_exists = ListMgr_Exists( lmgr, &p_op->entry_id );
    }

    /* get status for all policies with a matching scope */
    add_matching_scopes_mask(&p_op->entry_id, &p_op->fs_attrs, true,
                             &p_op->fs_attr_need.status);
    tmp = attr_mask_and_not(&attr_need_fresh, &p_op->fs_attrs.attr_mask);
    p_op->fs_attr_need = attr_mask_or(&p_op->fs_attr_need, &tmp);

    if ( !p_op->db_exists )
    {
        /* new entry */
        p_op->db_op_type = OP_TYPE_INSERT;

        /* set creation time if it was not set by scan module */
        if (!ATTR_MASK_TEST(&p_op->fs_attrs, creation_time))
        {
            ATTR_MASK_SET( &p_op->fs_attrs, creation_time );
            ATTR( &p_op->fs_attrs, creation_time ) = time(NULL); /* XXX min(atime,mtime,ctime)? */
        }

#ifdef _LUSTRE
        if (ATTR_MASK_TEST(&p_op->fs_attrs, type)
            && !strcmp(ATTR( &p_op->fs_attrs, type ), STR_TYPE_FILE )
                /* only if it was not retrieved during the scan */
                && !(ATTR_MASK_TEST(&p_op->fs_attrs, stripe_info)
                    && ATTR_MASK_TEST(&p_op->fs_attrs, stripe_items)))
        {
            attr_mask_set_index(&p_op->fs_attr_need, ATTR_INDEX_stripe_info);
            attr_mask_set_index(&p_op->fs_attr_need, ATTR_INDEX_stripe_items);
        }
#endif

        /* readlink for symlinks (if not already known) */
        if (ATTR_MASK_TEST(&p_op->fs_attrs, type)
            && !strcmp(ATTR( &p_op->fs_attrs, type ), STR_TYPE_LINK)
            && !ATTR_MASK_TEST(&p_op->fs_attrs, link))
        {
            attr_mask_set_index(&p_op->fs_attr_need, ATTR_INDEX_link);
        }
        else
        {
            attr_mask_unset_index(&p_op->fs_attr_need, ATTR_INDEX_link);
        }

#ifdef ATTR_INDEX_status /** @FIXME RBHv3 drop old-style status reference */
        if (ATTR_MASK_TEST(&p_op->fs_attrs, type)
#ifdef _LUSTRE_HSM
            && !strcmp( ATTR(&p_op->fs_attrs, type), STR_TYPE_FILE ))
#elif defined (_HSM_LITE)
            && (strcmp( ATTR(&p_op->fs_attrs, type), STR_TYPE_DIR ) != 0)
            && !p_op->extra_info.not_supp)
#endif
        {
            p_op->fs_attr_need |= ATTR_MASK_status;
#ifdef _HSM_LITE
            p_op->fs_attr_need |= (attr_need_fresh & ~p_op->fs_attrs.attr_mask);
#endif
        }
        else
        {