/** * print parent condition depending on parent list count: * parent_id == xxx or parent_id IN ( xxx, yyy, zzz ) * \return db error code */ static int append_parent_cond(lmgr_t *p_mgr, GString *str, const wagon_t *parent_list, unsigned int parent_count, const char *prefix) { DEF_PK(pk); if (unlikely(parent_count == 0)) { DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Warning: parent list is empty in %s()", __func__ ); return DB_INVALID_ARG; } if (likely(parent_count == 1)) /* the only expected for now */ { entry_id2pk(&parent_list[0].id, PTR_PK(pk)); g_string_append_printf(str, "%sparent_id="DPK, prefix ? prefix : "", pk); } else { int i; g_string_append_printf(str, "%sparent_id IN (", prefix ? prefix : ""); for (i = 0; i < parent_count; i++) { entry_id2pk(&parent_list[i].id, PTR_PK(pk)); g_string_append_printf(str, "%s"DPK, (i == 0)? "":",", pk); } g_string_append(str,")"); } return DB_SUCCESS; }
int ListMgr_Get( lmgr_t * p_mgr, const entry_id_t * p_id, attr_set_t * p_info ) { int rc; DEF_PK(pk); entry_id2pk(p_id, PTR_PK(pk)); retry: rc = listmgr_get_by_pk(p_mgr, pk, p_info); if (lmgr_delayed_retry(p_mgr, rc)) goto retry; return rc; }
int ListMgr_SetStripe( lmgr_t * p_mgr, const entry_id_t * p_id, stripe_info_t * p_stripe_info, stripe_items_t * p_stripe_items ) { DEF_PK(pk); int rc = entry_id2pk( p_mgr, p_id, FALSE, PTR_PK(pk) ); if (rc) return rc; return insert_stripe_info( p_mgr, pk, VALID(p_id), p_stripe_info, p_stripe_items, TRUE ); }
/** * print parent condition depending on parent list count: * parent_id == xxx or parent_id IN ( xxx, yyy, zzz ) */ static char * parent_cond(lmgr_t * p_mgr, char * buff, size_t buffsz, const wagon_t * parent_list, unsigned int parent_count, const char * prefix) { DEF_PK(pk); if (parent_count == 0) { DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Warning: parent list is empty in %s()", __func__ ); return NULL; } if (parent_count == 1) { entry_id2pk(&parent_list[0].id, PTR_PK(pk)); sprintf(buff, "%sparent_id="DPK, prefix ? prefix : "", pk); } else { int i; char * curr = buff; curr += sprintf(curr, "%sparent_id IN (", prefix ? prefix : ""); for (i = 0; i < parent_count; i++) { entry_id2pk(&parent_list[i].id, PTR_PK(pk)); if ((ssize_t)(curr - buff) + strlen(pk) + 2 >= buffsz) { DisplayLog(LVL_CRIT, LISTMGR_TAG, "ERROR: request overflow in %s(): parent_list length=%u, current buff_usage=%zu", __func__, parent_count, (size_t)(curr - buff)); return NULL; } if (i == 0) curr += sprintf(curr, DPK, pk); else curr += sprintf(curr, ","DPK, pk); } strcpy(curr, ")"); } return buff; }
int ListMgr_Exists(lmgr_t *p_mgr, const entry_id_t *p_id) { GString *req; int rc; result_handle_t result; char *str_count = NULL; DEF_PK(pk); int retry_status; /* retrieve primary key */ entry_id2pk(p_id, PTR_PK(pk)); /* verify it exists in main table */ req = g_string_new("SELECT id FROM " MAIN_TABLE " WHERE id="); g_string_append_printf(req, DPK, pk); retry: /* execute the request (must return negative value on error) */ rc = -db_exec_sql(&p_mgr->conn, req->str, &result); retry_status = lmgr_delayed_retry(p_mgr, -rc); if (retry_status == 1) goto retry; else if (retry_status == 2) { rc = -DB_RBH_SIG_SHUTDOWN; goto free_str; } else if (rc) goto free_str; rc = db_next_record(&p_mgr->conn, &result, &str_count, 1); if (rc == 0) rc = 1; /* return 1 if entry exists */ else if (rc != DB_END_OF_LIST) { retry_status = lmgr_delayed_retry(p_mgr, -rc); if (retry_status == 1) goto retry; else if (retry_status == 2) { rc = -DB_RBH_SIG_SHUTDOWN; goto free_result; } } else rc = 0; free_result: db_result_free(&p_mgr->conn, &result); free_str: g_string_free(req, TRUE); return rc; }
int ListMgr_RecovSetState( lmgr_t * p_mgr, const entry_id_t * p_id, recov_status_t status ) { char query[4096]; DEF_PK(pk); entry_id2pk(p_id, PTR_PK(pk)); sprintf( query, "UPDATE "RECOV_TABLE" SET recov_status=%u WHERE id="DPK, status, pk ); /* execute request */ return db_exec_sql( &p_mgr->conn, query, NULL ); }
/* Retrieve the FID from the database given the parent FID and the file name. */ int ListMgr_Get_FID_from_Path( lmgr_t * p_mgr, const entry_id_t * parent_fid, const char *name, entry_id_t * fid) { result_handle_t result; GString *req = NULL; char escaped[RBH_NAME_MAX*2+1]; DEF_PK(pk); int rc; char *str_info[1]; int retry_status; entry_id2pk(parent_fid, PTR_PK(pk)); db_escape_string(&p_mgr->conn, escaped, sizeof(escaped), name); req = g_string_new("SELECT id FROM "DNAMES_TABLE" WHERE pkn="); g_string_append_printf(req, HNAME_FMT, pk, escaped); retry: rc = db_exec_sql(&p_mgr->conn, req->str, &result); retry_status = lmgr_delayed_retry(p_mgr, rc); if (retry_status == 1) goto retry; else if (retry_status == 2) { rc = DB_RBH_SIG_SHUTDOWN; goto free_str; } else if (rc) goto free_str; rc = db_next_record(&p_mgr->conn, &result, str_info, 1); retry_status = lmgr_delayed_retry(p_mgr, rc); if (retry_status == 1) goto retry; else if (retry_status == 2) { rc = DB_RBH_SIG_SHUTDOWN; goto free_res; } else if (rc != DB_SUCCESS) goto free_res; rc = pk2entry_id(p_mgr, str_info[0], fid); free_res: db_result_free(&p_mgr->conn, &result); free_str: g_string_free(req, TRUE); return rc; }
int ListMgr_Get( lmgr_t * p_mgr, const entry_id_t * p_id, attr_set_t * p_info ) { int rc; DEF_PK(pk); int retry_status; entry_id2pk(p_id, PTR_PK(pk)); retry: rc = listmgr_get_by_pk(p_mgr, pk, p_info); retry_status = lmgr_delayed_retry(p_mgr, rc); if (retry_status == 1) goto retry; else if (retry_status == 2) rc = DB_RBH_SIG_SHUTDOWN; return rc; }
static void no_name_warning(PK_PARG_T pk, attr_set_t *p_attrs, unsigned int count) { DEF_PK(ppk); char msg[256]; entry_id2pk(&ATTR(p_attrs, parent_id), PTR_PK(ppk)); if (count > 1) snprintf(msg, sizeof(msg), "%u entries", count); else rh_strncpy(msg, "entry", sizeof(msg)); DisplayLog(LVL_MAJOR, LISTMGR_TAG, "WARNING: %s created without" " name or parent information: pk="DPK", name='%s', parent='%s'", msg, pk, ATTR_MASK_TEST(p_attrs, name) ? ATTR(p_attrs, name) : "", ATTR_MASK_TEST(p_attrs, parent_id) ? ppk : ""); }
int ListMgr_RecovGetNext( struct lmgr_iterator_t *p_iter, entry_id_t * p_id, attr_set_t * p_info, recov_status_t * last_status ) { int rc = 0; char *result_tab[2+RECOV_FIELD_COUNT]; /* +2 for id and recov_status */ DEF_PK(pk); int entry_disappeared = FALSE; do { entry_disappeared = FALSE; rc = db_next_record( &p_iter->p_mgr->conn, &p_iter->select_result, result_tab, RECOV_FIELD_COUNT+2 ); if ( rc ) return rc; if ( result_tab[0] == NULL ) /* no id? */ return DB_REQUEST_FAILED; if ( sscanf( result_tab[0], SPK, PTR_PK(pk) ) != 1 ) return DB_REQUEST_FAILED; if ( result_tab[1] == NULL ) { /* no status */ if (last_status) *last_status = -1; } else if (last_status) *last_status = str2int(result_tab[1]); /* retrieve entry id (except validator) */ rc = pk2entry_id( p_iter->p_mgr, pk, p_id ); /* /!\ If the entry disappeared from DB, we must go to next record */ if ( rc == DB_NOT_EXISTS ) entry_disappeared = TRUE; else if ( rc ) return rc; } while ( entry_disappeared ); /* goto next record if entry desappered */ return result2attrset( T_RECOV, result_tab + 2, RECOV_FIELD_COUNT, p_info ); }
/* check that validator is matching for a given entry */ int ListMgr_CheckStripe( lmgr_t * p_mgr, const entry_id_t * p_id ) { char query[1024]; char *res; result_handle_t result; int rc = DB_SUCCESS; DEF_PK(pk); rc = entry_id2pk( p_mgr, p_id, FALSE, PTR_PK(pk) ); if (rc) return rc; sprintf( query, "SELECT validator FROM " STRIPE_INFO_TABLE " WHERE id="DPK, pk ); rc = db_exec_sql( &p_mgr->conn, query, &result ); if ( rc ) goto out; rc = db_next_record( &p_mgr->conn, &result, &res, 1 ); if ( rc == DB_END_OF_LIST ) rc = DB_NOT_EXISTS; if ( rc ) goto res_free; if ( res == NULL ) { rc = DB_ATTR_MISSING; goto res_free; } if ( atoi( res ) != VALID(p_id) ) { delete_stipe_info( p_mgr, pk ); rc = DB_OUT_OF_DATE; } else rc = DB_SUCCESS; res_free: db_result_free( &p_mgr->conn, &result ); out: return rc; }
int ListMgr_GetNext( struct lmgr_iterator_t *p_iter, entry_id_t * p_id, attr_set_t * p_info ) { int rc = 0; char *idstr; DEF_PK(pk); int entry_disappeared = FALSE; do { entry_disappeared = FALSE; rc = db_next_record( &p_iter->p_mgr->conn, &p_iter->select_result, &idstr, 1 ); if ( rc ) return rc; if ( idstr == NULL ) return DB_REQUEST_FAILED; if ( sscanf( idstr, SPK, PTR_PK(pk) ) != 1 ) return DB_REQUEST_FAILED; /* retrieve entry id (except validator) */ rc = pk2entry_id( p_iter->p_mgr, pk, p_id ); /* /!\ If the entry disappeared from DB, we must go to next record */ if ( rc == DB_NOT_EXISTS ) entry_disappeared = TRUE; else if ( rc ) return rc; /* Idem */ rc = listmgr_get_by_pk( p_iter->p_mgr, pk, p_info ); if ( rc == DB_NOT_EXISTS ) entry_disappeared = TRUE; } while ( entry_disappeared ); /* goto next record if entry desappered */ return rc; }
int ListMgr_SetStripe(lmgr_t *p_mgr, const entry_id_t *p_id, stripe_info_t *p_stripe_info, stripe_items_t *p_stripe_items) { DEF_PK(pk); int rc; #ifdef HAVE_LLAPI_FSWAP_LAYOUTS int validator = (p_stripe_info ? p_stripe_info->validator : VALID_NOSTRIPE); #else int validator = VALID(p_id); #endif entry_id2pk(p_id, PTR_PK(pk)); retry: rc = insert_stripe_info(p_mgr, pk, validator, p_stripe_info, p_stripe_items, true); if (lmgr_delayed_retry(p_mgr, rc)) goto retry; return rc; }
int ListMgr_Exists( lmgr_t * p_mgr, const entry_id_t * p_id ) { char request[4096]; int rc; result_handle_t result; char *str_count = NULL; DEF_PK( pk ); /* retrieve primary key */ entry_id2pk(p_id, PTR_PK(pk)); /* verify it exists in main table */ sprintf( request, "SELECT id FROM " MAIN_TABLE " WHERE id="DPK, pk ); retry: /* execute the request */ rc = db_exec_sql(&p_mgr->conn, request, &result); if (lmgr_delayed_retry(p_mgr, rc)) goto retry; else if (rc) return -rc; rc = db_next_record( &p_mgr->conn, &result, &str_count, 1 ); if (rc == 0) rc = 1; else if (rc != DB_END_OF_LIST) { if (lmgr_delayed_retry(p_mgr, rc)) goto retry; rc = -rc; } else rc = 0; db_result_free( &p_mgr->conn, &result ); return rc; }
/* Retrieve the FID from the database given the parent FID and the file name. */ int ListMgr_Get_FID_from_Path( lmgr_t * p_mgr, const entry_id_t * parent_fid, const char *name, entry_id_t * fid) { result_handle_t result; char query[4096]; char escaped[RBH_NAME_MAX*2]; DEF_PK(pk); int rc; char *str_info[1]; entry_id2pk(parent_fid, PTR_PK(pk)); db_escape_string(&p_mgr->conn, escaped, RBH_NAME_MAX*2, name); sprintf(query, "SELECT id FROM "DNAMES_TABLE" WHERE pkn="HNAME_FMT, pk, escaped); retry: rc = db_exec_sql(&p_mgr->conn, query, &result); if (lmgr_delayed_retry(p_mgr, rc)) goto retry; else if (rc) return rc; rc = db_next_record( &p_mgr->conn, &result, str_info, 1 ); if (lmgr_delayed_retry(p_mgr, rc)) goto retry; else if (rc != DB_SUCCESS) goto free_res; rc = pk2entry_id(p_mgr, str_info[0], fid); free_res: db_result_free( &p_mgr->conn, &result ); return rc; }
/** check that validator is matching for a given entry */ int ListMgr_CheckStripe(lmgr_t *p_mgr, const entry_id_t *p_id, int validator) { char *res; result_handle_t result; int rc = DB_SUCCESS; GString *req = NULL; DEF_PK(pk); #ifndef HAVE_LLAPI_FSWAP_LAYOUTS if (validator != VALID_EXISTS) validator = VALID(p_id); #endif entry_id2pk(p_id, PTR_PK(pk)); req = g_string_new("SELECT validator FROM " STRIPE_INFO_TABLE " WHERE id="); g_string_append_printf(req, DPK, pk); retry: rc = db_exec_sql(&p_mgr->conn, req->str, &result); if (lmgr_delayed_retry(p_mgr, rc)) goto retry; else if (rc) goto out; rc = db_next_record(&p_mgr->conn, &result, &res, 1); if (lmgr_delayed_retry(p_mgr, rc)) goto retry; if (rc == DB_END_OF_LIST) rc = DB_NOT_EXISTS; if (rc) goto res_free; if (res == NULL) { rc = DB_ATTR_MISSING; goto res_free; } if (validator == VALID_EXISTS) { DisplayLog(LVL_FULL, LISTMGR_TAG, DFID ": validator exists (%s): OK", PFID(p_id), res); /* just check it exists */ rc = DB_SUCCESS; } else if (atoi(res) != validator) { DisplayLog(LVL_FULL, LISTMGR_TAG, DFID ": stripe change detected: gen %s->%d", PFID(p_id), res, validator); rc = DB_OUT_OF_DATE; } else { /* validator matches */ DisplayLog(LVL_FULL, LISTMGR_TAG, DFID ": stripe gen is unchanged (%d)", PFID(p_id), validator); rc = DB_SUCCESS; } res_free: db_result_free(&p_mgr->conn, &result); out: g_string_free(req, TRUE); DisplayLog(LVL_FULL, LISTMGR_TAG, DFID ": %s returns with status=%d", PFID(p_id), __func__, rc); return rc; }
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 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; }