/** * 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 */
/** * 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 {