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; }
int batch_insert_stripe_info(lmgr_t *p_mgr, pktype *pklist, int *validators, attr_set_t **p_attrs, unsigned int count, bool update_if_exists) { bool first; int i, rc = 0; int total_si; GString *req = g_string_new(""); attr_mask_t tmp_mask = { ATTR_MASK_stripe_info, 0, 0LL }; if (!attr_mask_is_null(sum_masks(p_attrs, count, tmp_mask))) { /* build batch request for STRIPE_INFO table */ g_string_assign(req, "INSERT INTO " STRIPE_INFO_TABLE " (" STRIPE_INFO_FIELDS ") VALUES "); first = true; for (i = 0; i < count; i++) { /* no request if the entry has no stripe info */ if (!ATTR_MASK_TEST(p_attrs[i], stripe_info)) continue; g_string_append_printf(req, "%s(" DPK ",%d,%u,%u,'%s')", first ? "" : ",", pklist[i], validators[i], ATTR(p_attrs[i], stripe_info).stripe_count, (unsigned int)ATTR(p_attrs[i], stripe_info).stripe_size, ATTR(p_attrs[i], stripe_info).pool_name); first = false; } if (update_if_exists) /* append "on duplicate key ..." */ g_string_append(req, " ON DUPLICATE KEY UPDATE " STRIPE_INFO_SET_VALUES); if (!first) { /* do nothing if no entry had stripe info */ rc = db_exec_sql(&p_mgr->conn, req->str, NULL); if (rc) goto out; } /* reset the string */ g_string_assign(req, ""); } /* Stripe items more tricky because we want to delete previous items * on update. */ /* If update_if_exists is false, insert them all as a batch. * For the update case, remove previous items before bluk insert. */ if (update_if_exists) { for (i = 0; i < count; i++) { /* no request if the entry has no stripe items */ if (!ATTR_MASK_TEST(p_attrs[i], stripe_items)) continue; g_string_printf(req, "DELETE FROM " STRIPE_ITEMS_TABLE " WHERE id=" DPK, pklist[i]); rc = db_exec_sql(&p_mgr->conn, req->str, NULL); if (rc) goto out; } } /* bulk insert stripe items (if any is set) */ tmp_mask.std = ATTR_MASK_stripe_items; if (attr_mask_is_null(sum_masks(p_attrs, count, tmp_mask))) goto out; total_si = 0; first = true; g_string_assign(req, "INSERT INTO " STRIPE_ITEMS_TABLE " (" STRIPE_ITEMS_FIELDS ") VALUES "); /* loop on all entries and all stripe items */ for (i = 0; i < count; i++) { int s; const stripe_items_t *p_items; /* skip the entry if it has no stripe items */ if (!ATTR_MASK_TEST(p_attrs[i], stripe_items)) continue; p_items = &ATTR(p_attrs[i], stripe_items); for (s = 0; s < p_items->count; s++) { char buff[2 * STRIPE_DETAIL_SZ + 1]; total_si++; if (buf2hex (buff, sizeof(buff), (unsigned char *)(&p_items->stripe[s].ost_gen), STRIPE_DETAIL_SZ) < 0) { DisplayLog(LVL_CRIT, LISTMGR_TAG, "Buffer too small to store details stripe info"); memset(buff, 0, sizeof(buff)); } g_string_append_printf(req, "%s(" DPK ",%u,%u,x'%s')", first && (s == 0) ? "" : ",", pklist[i], s, p_items->stripe[s].ost_idx, buff); first = false; } } /* only execute it if there was some stripe items */ if (total_si > 0) rc = db_exec_sql(&p_mgr->conn, req->str, NULL); out: g_string_free(req, TRUE); return rc; }