void test_class_end(void) { db_result_free(result); result = NULL; db_result_free(result2); result2 = NULL; CU_PASS("db_result_free"); db_value_set_free(value_set); value_set = NULL; db_value_set_free(value_set2); value_set2 = NULL; CU_PASS("db_value_set_free"); db_object_field_list_free(object_field_list); object_field_list = NULL; CU_PASS("db_object_field_list_free"); CU_PASS("db_object_field_free"); db_connection_free(connection); connection = NULL; CU_PASS("db_connection_free"); db_backend_free(backend); backend = NULL; CU_PASS("db_backend_handle_free"); CU_PASS("db_backend_free"); }
/* create a new note */ int db_new(char* search) { /* search by name */ sql_result *result; result = db_get("SELECT * FROM nodau WHERE name = '%s'",search); if (result) { /* there's already a note with that name, so error and return */ if (result->num_rows) { printf("There is already a note called '%s'\n",search); db_result_free(result); return 1; } /* free the search result */ db_result_free(result); } /* create the new entry */ db_insert(search,"new entry"); if (error_msg) printf("%s\n",error_msg); /* open for editing */ return db_edit(search); }
CWERROR db_cont_get_list(CW_DB_CONNECTION *db, CW_CONTACT **clist, CW_UINT32 *count) { static const char query[] = "SELECT cid,sid,uid,name,mname,lname,addr,phone,mphone,fax,www,email,company,notes FROM contacts"; CW_DB_RESULT res; CW_DB_RESULT_ROW *row; CW_CONTACT *list = NULL; CW_UINT32 n, i = 0; CWERROR err = CW_ER_OK; if ((err = db_query(db, &res, query, sizeof(query)-1, NULL, 0)) != CW_ER_OK) { DEBUG_ERROR(); db_result_free(&res); return err; } if ((n = *count = DB_RESULT_ROW_COUNT(res)) == 0) { db_result_free(&res); return CW_ER_OK; } if ((list = *clist = DLL_MALLOC(sizeof(CW_CONTACT) * n)) == NULL) { DEBUG_ERROR(); db_result_free(&res); return CW_ER_MEMORY; } row = DB_RESULT_ROW_FIRST(res); do { list[i].cid = DB_RESULT_AS_INT64(row, 0); list[i].sid = (CW_UINT32)DB_RESULT_AS_INT64(row, 1); list[i].uid = (CW_UINT32)DB_RESULT_AS_INT64(row, 2); #define WSTRCPY(to, n) \ if (wcscpy_s((to), DB_RESULT_AS_BLOB(row, (n)), sizeof((to))) == NULL) { \ DEBUG_ERROR(); \ DLL_FREE(list); \ db_result_free(&res); \ return CW_ER_INTERNAL; \ } WSTRCPY(list[i].name, 3); WSTRCPY(list[i].mname, 4); WSTRCPY(list[i].lname, 5); WSTRCPY(list[i].addr, 6); WSTRCPY(list[i].phone, 7); WSTRCPY(list[i].mphone, 8); WSTRCPY(list[i].fax, 9); WSTRCPY(list[i].www, 10); WSTRCPY(list[i].email, 11); WSTRCPY(list[i].comp, 12); WSTRCPY(list[i].notes, 13); #undef WSTRCPY ++i; } while (((row = DB_RESULT_ROW_NEXT(row)) != NULL) && (--n)); db_result_free(&res); return CW_ER_OK; }
CWERROR db_cont_get_by_id(CW_DB_CONNECTION *db, CW_CONTACT *cont, CW_BOOL *exists, const CW_UINT32 sid, const CW_UINT32 uid) { static const char query[] = "SELECT cid,sid,uid,name,mname,lname,addr,phone,mphone,fax,www,email,company,notes FROM contacts WHERE sid=? AND uid=?"; CW_DB_RESULT res; CW_DB_RESULT_ROW *row; CW_DB_VALUE binds[2] = {{DB_INT64, (CW_INT64)sid}, {DB_INT64, (CW_INT64)uid}}; CWERROR err = CW_ER_OK; *exists = FALSE; if ((err = db_query(db, &res, query, sizeof(query)-1, &binds[0], 2)) != CW_ER_OK) { DEBUG_ERROR(); db_result_free(&res); return err; } if (DB_RESULT_ROW_COUNT(res) == 0) { db_result_free(&res); return CW_ER_OK; } row = DB_RESULT_ROW_FIRST(res); cont->cid = DB_RESULT_AS_INT64(row, 0); cont->sid = (CW_UINT32)DB_RESULT_AS_INT64(row, 1); cont->uid = (CW_UINT32)DB_RESULT_AS_INT64(row, 2); #define WSTRCPY(to, n) \ if (wcscpy_s((to), DB_RESULT_AS_BLOB(row, (n)), sizeof((to))) == NULL) { \ DEBUG_ERROR(); \ db_result_free(&res); \ return CW_ER_INTERNAL; \ } WSTRCPY(cont->name, 3); WSTRCPY(cont->mname, 4); WSTRCPY(cont->lname, 5); WSTRCPY(cont->addr, 6); WSTRCPY(cont->phone, 7); WSTRCPY(cont->mphone, 8); WSTRCPY(cont->fax, 9); WSTRCPY(cont->www, 10); WSTRCPY(cont->email, 11); WSTRCPY(cont->comp, 12); WSTRCPY(cont->notes, 13); #undef WSTRCPY *exists = TRUE; db_result_free(&res); return CW_ER_OK; }
/* list notes according to search criteria */ int db_list(char* search) { sql_result *res; int i; char* pref = "match"; /* if search is null, list all */ if (search == NULL) { pref = "note"; res = db_get("SELECT * FROM nodau"); /* nothing there */ if (res->num_rows == 0) { printf("No notes to list\n"); db_result_free(res); return 0; } } else { /* first try a name search */ res = db_get("SELECT * FROM nodau WHERE name LIKE '%%%s%%'",search); /* if there's nothing then try a time search */ if (res->num_rows == 0) { unsigned int idate; db_result_free(res); /* at time */ if (strncmp(search,"t@",2) == 0) { idate = db_getstamp(search+2); res = db_get("SELECT * FROM nodau WHERE date = %u", idate); /* after time */ } else if (strncmp(search,"t+",2) == 0) { idate = db_getstamp(search+2); res = db_get("SELECT * FROM nodau WHERE date > %u", idate); /* before time */ } else if (strncmp(search,"t-",2) == 0) { idate = db_getstamp(search+2); res = db_get("SELECT * FROM nodau WHERE date < %u", idate); } } /* nothing there */ if (!res || !res->num_rows || !res->num_cols) { printf("No notes match '%s'\n",search); return 0; } } /* print the list */ for (i=0; i<res->num_rows; i++) { printf("%s %d: %s\n",pref,i+1,res->data[COLUMN(i,COL_NAME)]); } /* free the result */ db_result_free(res); return 0; }
CWERROR db_reports_get_list(CW_DB_CONNECTION *db, CW_REPORT **rlist, CW_UINT32 *count) { static const char query[] = "SELECT rid,sid,uid,datetime(add_dt,'localtime'),code FROM reports ORDER BY add_dt COLLATE NOCASE DESC"; CW_DB_RESULT res; CW_DB_RESULT_ROW *row; CW_REPORT *list = NULL; CW_UINT32 n, i = 0; CWERROR err = CW_ER_OK; if ((err = db_query(db, &res, query, sizeof(query)-1, NULL, 0)) != CW_ER_OK) { DEBUG_ERROR(); db_result_free(&res); return err; } if ((n = *count = DB_RESULT_ROW_COUNT(res)) == 0) { db_result_free(&res); return CW_ER_OK; } if ((list = *rlist = DLL_MALLOC(sizeof(CW_REPORT) * n)) == NULL) { DEBUG_ERROR(); db_result_free(&res); return CW_ER_MEMORY; } row = DB_RESULT_ROW_FIRST(res); do { list[i].rid = DB_RESULT_AS_INT64(row, 0); list[i].pckt.rcpt_sid = (CW_UINT32)DB_RESULT_AS_INT64(row, 1); list[i].pckt.rcpt_uid = (CW_UINT32)DB_RESULT_AS_INT64(row, 2); if (strcpy_s(list[i].add_dt, DB_RESULT_AS_TEXT(row, 3), sizeof(list[i].add_dt)) == NULL) { DEBUG_ERROR(); DLL_FREE(list); db_result_free(&res); return CW_ER_INTERNAL; } list[i].pckt.code = (CW_UINT32)DB_RESULT_AS_INT64(row, 4); ++i; } while (((row = DB_RESULT_ROW_NEXT(row)) != NULL) && (--n)); db_result_free(&res); return CW_ER_OK; }
/* open an existing note */ int db_edit(char* search) { char* date; char* name; char* text; char* crypt; int r; /* get the note by name */ sql_result *result; result = db_get("SELECT * FROM nodau WHERE name = '%s'",search); /* nothing there */ if (result->num_rows == 0) { db_result_free(result); if (config_read("edit_autocreate","false")) { printf("No notes match '%s'\n",search); } else { return db_new(search); } return 0; } /* get the data */ date = db_gettime(result->data[COLUMN(0,COL_DATE)]); name = result->data[COLUMN(0,COL_NAME)]; text = result->data[COLUMN(0,COL_TEXT)]; crypt = result->data[COLUMN(0,COL_CRYPT)]; /* get the passphrase if it's encrypted */ if (!strcmp(crypt,"true")) { crypt = crypt_get_key(); text = note_decrypt(text,crypt); if (!text) return 1; } /* edit the note */ r = edit(name, date, text); /* free the result */ db_result_free(result); return r; }
void ListMgr_CloseReport(struct lmgr_report_t *p_iter) { db_result_free(&p_iter->p_mgr->conn, &p_iter->select_result); if (p_iter->str_tab != NULL) MemFree(p_iter->str_tab); MemFree(p_iter->result); MemFree(p_iter); }
/* encrypt an existing note, or create a new encrypted note */ int db_encrypt(char* search) { /* search by name */ sql_result *result; char* crypt; int r; result = db_get("SELECT * FROM nodau WHERE name = '%s'",search); /* there's already a note with that name */ if (result->num_rows) { char* name; char* text; /* get the data */ name = result->data[COLUMN(0,COL_NAME)]; text = result->data[COLUMN(0,COL_TEXT)]; crypt = result->data[COLUMN(0,COL_CRYPT)]; /* encrypt it if it's not already */ if (!strcmp(crypt,"false")) { crypt = crypt_get_key(); r = db_update(name,text); } else { printf("Note '%s' is already encrypted\n",search); } db_result_free(result); return r; } /* free the search result */ db_result_free(result); /* create the new entry */ db_insert(search,"new entry"); if (error_msg) fprintf(stderr,"%s\n",error_msg); crypt = crypt_get_key(); /* open for editing */ return db_edit(search); }
/* decrypt an existing note or create a new encrypted note */ int db_decrypt(char* search) { /* search by name */ sql_result *result; int r; result = db_get("SELECT * FROM nodau WHERE name = '%s'",search); /* found the note */ if (result->num_rows) { char* text; char* crypt; /* get the data */ text = result->data[COLUMN(0,COL_TEXT)]; crypt = result->data[COLUMN(0,COL_CRYPT)]; /* decrypt it if it is encrypted */ if (!strcmp(crypt,"true")) { char* t; crypt = crypt_get_key(); t = note_decrypt(text,crypt); if (!t) return 1; free(crypt_key); crypt_key = NULL; r = db_update(search,t); db_result_free(result); return r; } else { printf("Note '%s' is not encrypted\n",search); db_result_free(result); } return 0; } printf("No notes matches '%s'\n",search); db_result_free(result); return 0; }
/* show an existing note */ int db_show(char* search) { char* date; char* name; char* text; char* crypt; /* get the note by name */ sql_result *result; result = db_get("SELECT * FROM nodau WHERE name = '%s'",search); /* nothing there */ if (result->num_rows == 0) { printf("No notes match '%s'\n",search); db_result_free(result); return 0; } /* get the data */ date = db_gettime(result->data[COLUMN(0,COL_DATE)]); name = result->data[COLUMN(0,COL_NAME)]; text = result->data[COLUMN(0,COL_TEXT)]; crypt = result->data[COLUMN(0,COL_CRYPT)]; /* get the passphrase if it's encrypted */ if (!strcmp(crypt,"true")) { crypt = crypt_get_key(); text = note_decrypt(text,crypt); if (!text) return 1; } /* display the note */ printf("%s (%s):\n%s\n",name,date,text); /* free the result */ db_result_free(result); return 0; }
/** * \retval DB_NOT_EXISTS if the recovery table does not exist */ int ListMgr_RecovStatus( lmgr_t * p_mgr, lmgr_recov_stat_t * p_stats ) { int rc, i; result_handle_t result; char * status[3]; /* test if a RECOVERY table already exist, and contains entries */ rc = db_exec_sql_quiet( &p_mgr->conn, "SELECT recov_status,COUNT(*),SUM(size) FROM "RECOV_TABLE " GROUP BY recov_status", &result ); if (rc) return rc; /* table exists, fill status tab */ p_stats->total = 0; for (i = 0; i < RS_COUNT; i++ ) { p_stats->status_count[i] = 0; p_stats->status_size[i] = 0; } while ( (rc = db_next_record( &p_mgr->conn, &result, status, 3 )) != DB_END_OF_LIST ) { long long cnt; uint64_t sz; if (rc) return rc; cnt = str2bigint( status[1] ); if ( cnt == -1LL) return DB_INVALID_ARG; sz = str2size( status[2] ); if ( sz == -1LL) return DB_INVALID_ARG; p_stats->total += cnt; if ( status[0] != NULL ) { int idx = str2int( status[0] ); if ((idx >= RS_COUNT) || (idx == -1) ) return DB_REQUEST_FAILED; p_stats->status_count[idx] = cnt; p_stats->status_size[idx] = sz; } } db_result_free( &p_mgr->conn, &result ); return 0; }
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; }
CWERROR db_outbox_get_by_id(CW_DB_CONNECTION *db, CW_MSG_DESC *msg, const CW_INT64 mid) { static const char query[] = "SELECT mid,sid,uid,add_dt,msg_sz,file FROM outbox_mail WHERE mid=?"; CW_DB_VALUE bind = {DB_INT64, mid}; CW_DB_RESULT res; CW_DB_RESULT_ROW *row; CW_UINT32 n, i = 0; CWERROR err = CW_ER_OK; if ((err = db_query(db, &res, query, sizeof(query)-1, &bind, 1)) != CW_ER_OK) { DEBUG_ERROR(); db_result_free(&res); return err; } row = DB_RESULT_ROW_FIRST(res); msg->mid = DB_RESULT_AS_INT64(row, 0); msg->sid = (CW_UINT32)DB_RESULT_AS_INT64(row, 1); msg->uid = (CW_UINT32)DB_RESULT_AS_INT64(row, 2); if (strcpy_s(msg->add_dt, DB_RESULT_AS_TEXT(row, 3), sizeof(msg->add_dt)) == NULL) { DEBUG_ERROR(); db_result_free(&res); return CW_ER_INTERNAL; } msg->sz = (CW_UINT64)DB_RESULT_AS_INT64(row, 4); if (strcpy_s(msg->file, DB_RESULT_AS_TEXT(row, 5), sizeof(msg->file)) == NULL) { DEBUG_ERROR(); db_result_free(&res); return CW_ER_INTERNAL; } db_result_free(&res); return CW_ER_OK; }
int lmgr_get_var(db_conn_t *pconn, const char *varname, char *value, int bufsize) { int rc; result_handle_t result; char *str_val = NULL; GString *req = NULL; if (!varname || !value) return DB_INVALID_ARG; req = g_string_new("SELECT value FROM "VAR_TABLE" WHERE varname="); g_string_append_printf(req, "'%s'", varname); /* execute the request */ rc = db_exec_sql(pconn, req->str, &result); if (rc) goto free_str; rc = db_next_record(pconn, &result, &str_val, 1); if (rc == DB_END_OF_LIST) rc = DB_NOT_EXISTS; if (rc) goto free_res; if (str_val == NULL) { rc = DB_REQUEST_FAILED; goto free_res; } /* copy the result */ if (strlen(str_val) >= bufsize) { rc = DB_BUFFER_TOO_SMALL; } else { strcpy(value, str_val); rc = DB_SUCCESS; } free_res: db_result_free(pconn, &result); free_str: g_string_free(req, TRUE); 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; 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; }
CWERROR db_inbox_get_list(CW_DB_CONNECTION *db, CW_MSG_DESC **dlist, CW_UINT32 *count) { static const char query[] = "SELECT mid,sid,uid,datetime(add_dt,'localtime'),read_flag,msg_sz,file FROM inbox_mail ORDER BY add_dt COLLATE NOCASE DESC"; CW_DB_RESULT res; CW_DB_RESULT_ROW *row; CW_MSG_DESC *list = NULL; CW_UINT32 n, i = 0; CWERROR err = CW_ER_OK; if ((err = db_query(db, &res, query, sizeof(query)-1, NULL, 0)) != CW_ER_OK) { DEBUG_ERROR(); db_result_free(&res); return err; } if ((n = *count = DB_RESULT_ROW_COUNT(res)) == 0) { db_result_free(&res); return CW_ER_OK; } if ((list = *dlist = DLL_MALLOC(sizeof(CW_MSG_DESC) * n)) == NULL) { DEBUG_ERROR(); db_result_free(&res); return CW_ER_MEMORY; } row = DB_RESULT_ROW_FIRST(res); do { list[i].mid = DB_RESULT_AS_INT64(row, 0); list[i].sid = (CW_UINT32)DB_RESULT_AS_INT64(row, 1); list[i].uid = (CW_UINT32)DB_RESULT_AS_INT64(row, 2); if (strcpy_s(list[i].add_dt, DB_RESULT_AS_TEXT(row, 3), sizeof(list[i].add_dt)) == NULL) { DEBUG_ERROR(); DLL_FREE(list); db_result_free(&res); return CW_ER_INTERNAL; } list[i].read_flag = ((strcmp(DB_RESULT_AS_TEXT(row, 4), "Y") == 0) ? TRUE : FALSE); list[i].sz = (CW_UINT64)DB_RESULT_AS_INT64(row, 5); if (strcpy_s(list[i].file, DB_RESULT_AS_TEXT(row, 6), sizeof(list[i].file)) == NULL) { DEBUG_ERROR(); DLL_FREE(list); db_result_free(&res); return CW_ER_INTERNAL; } ++i; } while (((row = DB_RESULT_ROW_NEXT(row)) != NULL) && (--n)); db_result_free(&res); return CW_ER_OK; }
/* 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; }
/* delete notes */ int db_del(char* search) { char sql[512]; unsigned int date = 0; /* try a name search */ sql_result *result; result = db_get("SELECT * FROM nodau WHERE name = '%s'",search); /* TODO: request passphrase before deleting encrypted notes? * File can be deleted without the passphrase anyway, * or the db can be edited with sqlite3 shell, so is there a * point to protecting from deletion? */ /* if we got something, delete it */ if (result->num_rows) { sprintf(sql, "DELETE FROM nodau WHERE name = '%s'", search); /* or try a delete by time at */ } else if (strncmp(search,"t@",2) == 0) { date = db_getstamp(search+2); sprintf(sql, "DELETE FROM nodau WHERE date = %u", date); /* or try a delete by later than */ } else if (strncmp(search,"t+",2) == 0) { date = db_getstamp(search+2); sprintf(sql, "DELETE FROM nodau WHERE date > %u", date); /* or try a delete by earlier than */ } else if (strncmp(search,"t-",2) == 0) { date = db_getstamp(search+2); sprintf(sql, "DELETE FROM nodau WHERE date < %u", date); /* or print an error */ } else { printf("No notes matches '%s'\n",search); return 0; } /* run the statement */ sqlite3_exec(db, sql, NULL, 0, &error_msg); /* free the earlier result */ db_result_free(result); return 0; }
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; }
int ListMgr_EntryCount(lmgr_t * p_mgr, uint64_t *count) { int rc; result_handle_t result; char *str_count = NULL; /* execute the request */ retry: rc = db_exec_sql( &p_mgr->conn, "SELECT COUNT(*) FROM " MAIN_TABLE, &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) return rc; if ( sscanf( str_count, "%"SCNu64, count ) != 1 ) rc = DB_REQUEST_FAILED; db_result_free( &p_mgr->conn, &result ); return rc; }
void ListMgr_CloseIterator( struct lmgr_iterator_t *p_iter ) { db_result_free( &p_iter->p_mgr->conn, &p_iter->select_result ); MemFree( p_iter ); }
int get_stripe_info( lmgr_t * p_mgr, PK_ARG_T pk, stripe_info_t * p_stripe_info, stripe_items_t * p_items ) { char query[1024]; char *res[3]; result_handle_t result; int i; int rc = DB_SUCCESS; /* retrieve basic stripe info */ sprintf( query, "SELECT stripe_count, stripe_size, pool_name 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, 3 ); if ( rc == DB_END_OF_LIST ) rc = DB_NOT_EXISTS; if ( rc ) goto res_free; if ( res[0] == NULL || res[1] == NULL || res[2] == NULL ) { rc = DB_ATTR_MISSING; goto res_free; } p_stripe_info->stripe_count = atoi( res[0] ); p_stripe_info->stripe_size = atoi( res[1] ); strncpy( p_stripe_info->pool_name, res[2], MAX_POOL_LEN ); db_result_free( &p_mgr->conn, &result ); if ( p_items ) { /* retrieve stripe list */ sprintf( query, "SELECT storage_item FROM " STRIPE_ITEMS_TABLE " WHERE id="DPK, pk ); rc = db_exec_sql( &p_mgr->conn, query, &result ); if ( rc ) goto out; if ( p_stripe_info->stripe_count != db_result_nb_records( &p_mgr->conn, &result ) ) { DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Warning: the number of stripe items (%d) doesn't match stripe count (%u)! (Pk="DPK")", db_result_nb_records( &p_mgr->conn, &result ), p_stripe_info->stripe_count, pk ); } p_items->count = db_result_nb_records( &p_mgr->conn, &result ); if ( p_items->count > 0 ) { /* allocate stripe array */ p_items->stripe_units = MemCalloc( p_items->count, sizeof( storage_unit_id_t ) ); if ( !p_items->stripe_units ) { rc = DB_NO_MEMORY; goto res_free; } /* fill stripe units */ for ( i = 0; i < p_items->count; i++ ) { rc = db_next_record( &p_mgr->conn, &result, res, 1 ); if ( rc ) goto stripe_free; if ( res[0] == NULL ) { rc = DB_ATTR_MISSING; goto stripe_free; } p_items->stripe_units[i] = atoi( res[0] ); } } else p_items->stripe_units = NULL; /* last query result must be freed */ rc = DB_SUCCESS; goto res_free; } /* nothing to free */ return DB_SUCCESS; stripe_free: MemFree( p_items->stripe_units ); p_items->stripe_units = NULL; p_items->count = 0; p_stripe_info->stripe_count = 0; res_free: db_result_free( &p_mgr->conn, &result ); out: return rc; }
/** retrieve directory attributes (nbr of entries, avg size of entries)*/ int listmgr_get_dirattrs( lmgr_t * p_mgr, PK_ARG_T dir_pk, attr_set_t * p_attrs ) { GString *req; result_handle_t result; char *str_info[1]; int rc = 0; int tmp_val; long long tmp_long; if (ATTR_MASK_TEST(p_attrs, type) && (strcmp(ATTR(p_attrs, type), STR_TYPE_DIR) != 0)) { DisplayLog(LVL_FULL, LISTMGR_TAG, "Type='%s' != 'dir' => unsetting dirattrs in attr mask", ATTR(p_attrs, type)); p_attrs->attr_mask = attr_mask_and_not(&p_attrs->attr_mask, &dir_attr_set); return 0; } req = g_string_new(NULL); /* get child entry count from DNAMES_TABLE */ if (ATTR_MASK_TEST(p_attrs, dircount)) { g_string_printf(req, "SELECT %s FROM "DNAMES_TABLE" WHERE parent_id="DPK, dirattr2str(ATTR_INDEX_dircount), dir_pk); rc = db_exec_sql(&p_mgr->conn, req->str, &result); if (rc) goto free_str; rc = db_next_record(&p_mgr->conn, &result, str_info, 1); if (rc == DB_END_OF_LIST) { ATTR_MASK_UNSET(p_attrs, dircount); rc = DB_SUCCESS; } else if (rc == DB_SUCCESS) { if (str_info[0] == NULL) /* count(*) should at least return 0 */ rc = DB_REQUEST_FAILED; else { tmp_val = str2int(str_info[0]); if (tmp_val != -1) { ATTR_MASK_SET(p_attrs, dircount); ATTR(p_attrs, dircount) = tmp_val; rc = DB_SUCCESS; } else /* invalid output format */ rc = DB_REQUEST_FAILED; } } db_result_free(&p_mgr->conn, &result); if (rc) goto free_str; } /* get avgsize of child entries from MAIN_TABLE */ if (ATTR_MASK_TEST(p_attrs, avgsize)) { g_string_printf(req, "SELECT %s FROM "MAIN_TABLE" m, "DNAMES_TABLE" d" " WHERE m.id = d.id and type='file' and d.parent_id="DPK, dirattr2str(ATTR_INDEX_avgsize), dir_pk); rc = db_exec_sql(&p_mgr->conn, req->str, &result); if (rc) goto free_str; rc = db_next_record(&p_mgr->conn, &result, str_info, 1); if (rc == DB_END_OF_LIST) ATTR_MASK_UNSET(p_attrs, avgsize); else if (rc == DB_SUCCESS) { if (str_info[0] == NULL) { /* NULL if no entry matches the criteria */ ATTR_MASK_UNSET(p_attrs, avgsize); rc = DB_SUCCESS; } else { tmp_long = str2bigint(str_info[0]); if (tmp_long != -1LL) { ATTR_MASK_SET(p_attrs, avgsize); ATTR(p_attrs, avgsize) = tmp_long; rc = DB_SUCCESS; } else /* invalid output format */ rc = DB_REQUEST_FAILED; } } db_result_free(&p_mgr->conn, &result); } free_str: g_string_free(req, TRUE); return rc; }
/** * 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 */
/** * Get the list of children of a given parent (or list of parents). * \param parent_list [in] list of parents to get the child of * \param parent_count [in] number of ids in parent list * \param attr_mask [in] required attributes for children * \param child_id_list [out] ptr to array of child ids * \param child_attr_list [out] ptr to array of child attrs * \param child_count [out] number of returned children */ int ListMgr_GetChild(lmgr_t *p_mgr, const lmgr_filter_t *p_filter, const wagon_t *parent_list, unsigned int parent_count, attr_mask_t attr_mask, wagon_t **child_id_list, attr_set_t **child_attr_list, unsigned int *child_count) { result_handle_t result; char *path = NULL; int path_len; int rc, i; GString *req = NULL; GString *fields = NULL; GString *from = NULL; GString *where = NULL; struct field_count field_cnt = {0}; struct field_count filter_cnt = {0}; table_enum query_tab = T_DNAMES; bool distinct = false; int retry_status; /* XXX: querying children from several parent cannot work, since * we need to get the paths of the children. Or we could do a * lookup into parent_list to find the right one. In the meantime, * try not to mess up the code. */ if (unlikely(parent_count != 1)) RBH_BUG("cannot get children for several parent simultaneously"); /* always request for name to build fullpath in wagon */ attr_mask_set_index(&attr_mask, ATTR_INDEX_name); fields = g_string_new(NULL); /* append fields for all tables */ if (!attr_mask_is_null(attr_mask)) { /* retrieve source info for generated fields */ add_source_fields_for_gen(&attr_mask.std); field_cnt.nb_names = attrmask2fieldlist(fields, attr_mask, T_DNAMES, DNAMES_TABLE".", "", AOF_LEADING_SEP); field_cnt.nb_main = attrmask2fieldlist(fields, attr_mask, T_MAIN, MAIN_TABLE".", "", AOF_LEADING_SEP); field_cnt.nb_annex = attrmask2fieldlist(fields, attr_mask, T_ANNEX, ANNEX_TABLE".", "", AOF_LEADING_SEP); } else { /* no returned attrs */ if (child_attr_list != NULL) *child_attr_list = NULL; } where = g_string_new(NULL); /* starts with condition on parent */ rc = append_parent_cond(p_mgr, where, parent_list, parent_count, DNAMES_TABLE"."); if (rc != DB_SUCCESS) goto free_str; /* check filters on other tables */ if (!no_filter(p_filter)) { if (unlikely(dir_filter(p_mgr, NULL, p_filter, NULL, NULL) != FILTERDIR_NONE)) { DisplayLog(LVL_MAJOR, LISTMGR_TAG, "Directory filter not supported in %s()", __func__); rc = DB_NOT_SUPPORTED; goto free_str; } else if (unlikely(func_filter(p_mgr, NULL, p_filter, T_MAIN, 0))) { DisplayLog(LVL_MAJOR, LISTMGR_TAG, "Function filter not supported in %s()", __func__); rc = DB_NOT_SUPPORTED; goto free_str; } /* There is always a filter on T_DNAMES, which is the parent condition. * Look for optional filters. */ filter_where(p_mgr, p_filter, &filter_cnt, where, AOF_LEADING_SEP | AOF_SKIP_NAME); /** @FIXME process other filters on NAMES */ } from = g_string_new(DNAMES_TABLE); /* add filter_count + field_count to build the FROM clause. * Preserve field count which is needed to interpret the result. */ filter_cnt.nb_main += field_cnt.nb_main; filter_cnt.nb_annex += field_cnt.nb_annex; filter_cnt.nb_names += field_cnt.nb_names; /* query tab is DNAMES, skip_name=true, is_first_tab=T_DNAMES */ filter_from(p_mgr, &filter_cnt, from, &query_tab, &distinct, AOF_LEADING_SEP | AOF_SKIP_NAME); /* request is always on the DNAMES table (which contains [parent_id, id] relationship */ if (distinct) req = g_string_new("SELECT DISTINCT("DNAMES_TABLE".id) as id"); else req = g_string_new("SELECT "DNAMES_TABLE".id as id"); /* build the whole request */ g_string_append_printf(req, "%s FROM %s WHERE %s", fields->str, from->str, where->str); 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; /* copy result to output structures */ *child_count = db_result_nb_records(&p_mgr->conn, &result); /* allocate entry_id array */ *child_id_list = MemCalloc(*child_count, sizeof(wagon_t)); if (*child_id_list == NULL) { rc = DB_NO_MEMORY; goto free_str; } if (child_attr_list) { *child_attr_list = MemCalloc(*child_count, sizeof(attr_set_t)); if (*child_attr_list == NULL) { rc = DB_NO_MEMORY; goto array_free; } } /* Allocate a string long enough to contain the parent path and a * child name. */ path_len = strlen(parent_list[0].fullname) + RBH_NAME_MAX + 2; path = malloc(path_len); if (!path) { DisplayLog(LVL_MAJOR, LISTMGR_TAG, "Can't alloc enough memory (%d bytes)", path_len); rc = DB_NO_MEMORY; goto array_free; } for (i = 0; i < *child_count; i++) { char *res[128]; /* 128 fields per record is large enough */ rc = db_next_record(&p_mgr->conn, &result, res, sizeof(res)/sizeof(*res)); if (rc) goto array_free; /* copy id to array */ pk2entry_id(p_mgr, res[0], &((*child_id_list)[i].id)); /* copy attributes to array */ if (child_attr_list) { unsigned int shift = 1; /* first was NAMES.id */ (*child_attr_list)[i].attr_mask = attr_mask; /* first id, then dnames attrs, then main attrs, then annex attrs */ if (field_cnt.nb_names > 0) { /* shift of 1 for id */ rc = result2attrset(T_DNAMES, res + shift, field_cnt.nb_names, &((*child_attr_list)[i])); if (rc) goto array_free; shift += field_cnt.nb_names; } if (field_cnt.nb_main > 0) { /* first id, then main attrs, then annex attrs */ /* shift of 1 for id */ rc = result2attrset(T_MAIN, res + shift, field_cnt.nb_main, &((*child_attr_list)[i])); if (rc) goto array_free; shift += field_cnt.nb_main; } if (field_cnt.nb_annex > 0) { /* shift of main_attrs count */ rc = result2attrset(T_ANNEX, res + shift, field_cnt.nb_annex, &((*child_attr_list)[i])); if (rc) goto array_free; shift += field_cnt.nb_annex; } #ifdef _LUSTRE if (stripe_fields(attr_mask)) { if (get_stripe_info(p_mgr, res[0], &ATTR(&(*child_attr_list)[i], stripe_info), &ATTR(&(*child_attr_list)[i], stripe_items))) { ATTR_MASK_UNSET(&(*child_attr_list)[i], stripe_info); ATTR_MASK_UNSET(&(*child_attr_list)[i], stripe_items); } } #endif generate_fields(&((*child_attr_list)[i])); /* Note: path is properly sized already to not overflow. */ snprintf(path, path_len, "%s/%s", parent_list[0].fullname, (*child_attr_list)[i].attr_values.name); (*child_id_list)[i].fullname = strdup(path); } } if (path) free(path); db_result_free(&p_mgr->conn, &result); g_string_free(req, TRUE); g_string_free(fields, TRUE); g_string_free(from, TRUE); g_string_free(where, TRUE); return 0; array_free: if (path) free(path); if (child_attr_list && *child_attr_list) { MemFree(*child_attr_list); *child_attr_list = NULL; } MemFree(*child_id_list); *child_id_list = NULL; free_str: g_string_free(req, TRUE); g_string_free(fields, TRUE); g_string_free(from, TRUE); g_string_free(where, TRUE); return rc; }
/** * Get the list of children of a given parent (or list of parents). * \param parent_list [in] list of parents to get the child of * \param parent_count [in] number of ids in parent list * \param attr_mask [in] required attributes for children * \param child_id_list [out] ptr to array of child ids * \param child_attr_list [out] ptr to array of child attrs * \param child_count [out] number of returned children */ int ListMgr_GetChild( lmgr_t * p_mgr, const lmgr_filter_t * p_filter, const wagon_t * parent_list, unsigned int parent_count, int attr_mask, wagon_t ** child_id_list, attr_set_t ** child_attr_list, unsigned int * child_count) { result_handle_t result; char *curr; int filter_main = 0; int filter_annex = 0; int main_attrs = 0; int dnames_attrs = 0; int annex_attrs = 0; char query[4096]; char fieldlist_main[1024] = ""; char fieldlist_dnames[1024] = ""; char fieldlist_annex[1024] = ""; char filter_str_main[1024] = ""; char filter_str_annex[1024] = ""; char tmp[2048]; char *path = NULL; int path_len; char * pc; int rc, i; /* TODO: querying children from several parent cannot work, since * we need to get the paths of the children. Or we could do a * lookup into parent_list to find the right one. In the meantime, * try not to mess up the code. */ if (parent_count != 1) RBH_BUG("cannot get children for several parent simultaneously"); /* always request for name to build fullpath in wagon */ attr_mask |= ATTR_MASK_name; /* request is always on the MAIN table (which contains [parent_id, id] relationship */ /* /!\ possible cases: * - simplest: the fields of the filter and the attributes to be retrieved are in the MAIN table * - harder: the fields of the filter and attributes are in a different table */ /* 1) location of filters */ if ( p_filter ) { char dummy_str[1024]; unsigned int dummy_uint; if (dir_filter(p_mgr, dummy_str, p_filter, &dummy_uint) != FILTERDIR_NONE) { DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Directory filter not supported in %s()", __func__ ); return DB_NOT_SUPPORTED; } else if (func_filter(p_mgr, dummy_str, p_filter, T_MAIN, FALSE, FALSE)) { DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Function filter not supported in %s()", __func__ ); return DB_NOT_SUPPORTED; } /* There is always a filter on T_DNAMES, which is the parent condition. * Look for optional filters: */ filter_main = filter2str( p_mgr, filter_str_main, p_filter, T_MAIN, FALSE, TRUE ); if ( annex_table ) filter_annex = filter2str( p_mgr, filter_str_annex, p_filter, T_ANNEX, FALSE, TRUE ); else filter_annex = 0; /* @TODO to be implemented */ #if 0 filter_stripe_info = filter2str( p_mgr, filter_str_stripe_info, p_filter, T_STRIPE_INFO, ( filter_main > 0 ) || ( filter_annex > 0 ), TRUE ); filter_stripe_items = filter2str( p_mgr, filter_str_stripe_items, p_filter, T_STRIPE_ITEMS, ( filter_main > 0 ) || ( filter_annex > 0 ) || ( filter_stripe_info > 0 ), TRUE ); #endif } /* 2) location of requested attributes */ if (attr_mask) { /* retrieve source info for generated fields */ add_source_fields_for_gen( &attr_mask ); main_attrs = attrmask2fieldlist( fieldlist_main, attr_mask, T_MAIN, /* leading comma */ TRUE, /* for update */ FALSE, /* prefix */ MAIN_TABLE".", /* postfix */ "" ); dnames_attrs += attrmask2fieldlist( fieldlist_dnames, attr_mask, T_DNAMES, /* leading comma */ TRUE, /* for update */ FALSE, /* prefix */ DNAMES_TABLE".", /* postfix */ "" ); if ( annex_table ) annex_attrs = attrmask2fieldlist( fieldlist_annex, attr_mask, T_ANNEX, /* leading comma */ TRUE, /* for update */ FALSE, /* prefix */ ANNEX_TABLE".", /* postfix */ "" ); else annex_attrs = 0; } else { /* no returned attrs */ if (child_attr_list) *child_attr_list = NULL; } pc = parent_cond(p_mgr, tmp, sizeof(tmp), parent_list, parent_count, DNAMES_TABLE"."); if (!pc) return DB_BUFFER_TOO_SMALL; curr = query; /* SELECT clause */ /* id + dname fields */ curr += sprintf(curr, "SELECT "DNAMES_TABLE".id%s", fieldlist_dnames); /* main attrs */ if (main_attrs) curr += sprintf(curr, "%s", fieldlist_main); /* annex attrs */ if (annex_attrs) curr += sprintf(curr, "%s", fieldlist_annex); /* FROM clause */ curr += sprintf(curr, " FROM "DNAMES_TABLE); if (main_attrs || filter_main) curr += sprintf(curr, " LEFT JOIN "MAIN_TABLE " ON "DNAMES_TABLE".id="MAIN_TABLE".id"); if (annex_attrs || filter_annex) curr += sprintf(curr, " LEFT JOIN "ANNEX_TABLE " ON "DNAMES_TABLE".id="ANNEX_TABLE".id"); /* WHERE clause */ curr += sprintf(curr, " WHERE %s", pc); if (filter_main) curr += sprintf(curr, " AND %s", filter_str_main); if (filter_annex) curr += sprintf(curr, " AND %s", filter_str_annex); retry: rc = db_exec_sql(&p_mgr->conn, query, &result); if (lmgr_delayed_retry(p_mgr, rc)) goto retry; else if (rc) return rc; /* copy result to output structures */ *child_count = db_result_nb_records(&p_mgr->conn, &result); /* allocate entry_id array */ *child_id_list = MemCalloc(*child_count, sizeof(wagon_t)); if (*child_id_list == NULL) return DB_NO_MEMORY; if (child_attr_list) { *child_attr_list = MemCalloc(*child_count, sizeof(attr_set_t)); if (*child_attr_list == NULL) { rc = DB_NO_MEMORY; goto array_free; } } /* Allocate a string long enough to contain the parent path and a * child name. */ path_len = strlen(parent_list[0].fullname) + RBH_NAME_MAX + 2; path = malloc(path_len); if (!path) { DisplayLog( LVL_MAJOR, LISTMGR_TAG, "Can't alloc enough memory (%d bytes)", path_len ); rc = DB_NO_MEMORY; goto array_free; } for (i = 0; i < *child_count; i++) { char *res[128]; /* 128 fields per row is large enough */ rc = db_next_record(&p_mgr->conn, &result, res, 128); if ( rc ) goto array_free; /* copy id to array */ pk2entry_id(p_mgr, res[0], &((*child_id_list)[i].id)); /* copy attributes to array */ if (child_attr_list) { (*child_attr_list)[i].attr_mask = attr_mask; /* first id, then dnames attrs, then main attrs, then annex attrs */ if (dnames_attrs) { /* shift of 1 for id */ rc = result2attrset( T_DNAMES, res + 1, dnames_attrs, &((*child_attr_list)[i]) ); if ( rc ) goto array_free; } if (main_attrs) { /* first id, then main attrs, then annex attrs */ /* shift of 1 for id */ rc = result2attrset( T_MAIN, res + dnames_attrs + 1, main_attrs, &((*child_attr_list)[i]) ); if ( rc ) goto array_free; } if (annex_attrs) { /* shift of main_attrs count */ rc = result2attrset( T_ANNEX, res + dnames_attrs + main_attrs + 1, annex_attrs, &((*child_attr_list)[i]) ); if ( rc ) goto array_free; } #ifdef _LUSTRE if (stripe_fields(attr_mask)) { if (get_stripe_info( p_mgr, res[0], &ATTR(&(*child_attr_list)[i], stripe_info), &ATTR(&(*child_attr_list)[i], stripe_items) )) { ATTR_MASK_UNSET(&(*child_attr_list)[i], stripe_info); ATTR_MASK_UNSET(&(*child_attr_list)[i], stripe_items); } } #endif generate_fields(&((*child_attr_list)[i])); /* Note: path is properly sized already to not overflow. */ sprintf(path, "%s/%s", parent_list[0].fullname, (*child_attr_list)[i].attr_values.name); (*child_id_list)[i].fullname = strdup(path); } } if (path) free(path); db_result_free( &p_mgr->conn, &result ); return 0; array_free: if (path) free(path); if (child_attr_list && *child_attr_list) { MemFree(*child_attr_list); *child_attr_list = NULL; } MemFree(*child_id_list); *child_id_list = NULL; return rc; }
/** * \retval DB_NOT_EXISTS if the recovery table does not exist */ static int expected_recov_status( lmgr_t * p_mgr, lmgr_recov_stat_t * p_stats ) { int rc, i; result_handle_t result; char * status[5]; /* test if a RECOVERY table already exist, and contains entries */ rc = db_exec_sql_quiet( &p_mgr->conn, "SELECT status,type,COUNT(*),(size=0) as empty,SUM(size) FROM "RECOV_TABLE " GROUP BY status,type,empty", &result ); if (rc) return rc; /* @TODO manage dirs and symlinks differently */ p_stats->total = 0; for (i = 0; i < RS_COUNT; i++ ) { p_stats->status_count[i] = 0; p_stats->status_size[i] = 0; } while ( (rc = db_next_record( &p_mgr->conn, &result, status, 5 )) != DB_END_OF_LIST ) { long long cnt; uint64_t sz; int isempty; if (rc) return rc; cnt = str2bigint( status[2] ); if ( cnt == -1LL) return DB_INVALID_ARG; isempty = str2int( status[3] ); if ( isempty == -1) return DB_INVALID_ARG; sz = str2size( status[4] ); if ( sz == -1LL) return DB_INVALID_ARG; p_stats->total += cnt; if ( status[0] != NULL ) { int st = str2int( status[0] ); /* archived entries: file and (optionally) symlinks */ if (!strcasecmp(status[1], STR_TYPE_FILE)) { if (isempty) { p_stats->status_count[RS_FILE_EMPTY] += cnt; p_stats->status_size[RS_FILE_EMPTY] += sz; } else { switch (st) { case STATUS_NEW: p_stats->status_count[RS_NOBACKUP] += cnt; p_stats->status_size[RS_NOBACKUP] += sz; break; case STATUS_MODIFIED: case STATUS_ARCHIVE_RUNNING: p_stats->status_count[RS_FILE_DELTA] += cnt; p_stats->status_size[RS_FILE_DELTA] += sz; break; case STATUS_SYNCHRO: case STATUS_RELEASED: p_stats->status_count[RS_FILE_OK] += cnt; p_stats->status_size[RS_FILE_OK] += sz; break; } } } else if (!strcasecmp(status[1], STR_TYPE_LINK) || !strcasecmp(status[1], STR_TYPE_DIR)) { /* symlinks and dirs always recoverable from DB */ p_stats->status_count[RS_NON_FILE] += cnt; p_stats->status_size[RS_NON_FILE] += sz; } else { /* non recoverable : special entry like fifo, blk, ... */ p_stats->status_count[RS_NOBACKUP] += cnt; p_stats->status_size[RS_NOBACKUP] += sz; } } } db_result_free( &p_mgr->conn, &result ); return 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 fieldlist[4096] = ""; char *first_table = NULL; char from[1024] = ""; char query[4096] = ""; /* we assume there is not more than 128 fields */ char *result_tab[128]; result_handle_t result; int checkmain = 1; int main_count = 0, annex_count = 0, name_count = 0; if (p_info == NULL) return 0; /* init entry info */ memset( &p_info->attr_values, 0, sizeof( entry_info_t ) ); fieldlist[0] = '\0'; /* retrieve source info for generated fields */ add_source_fields_for_gen( &p_info->attr_mask ); /* get info from main table (if asked) */ main_count = attrmask2fieldlist(fieldlist, p_info->attr_mask, T_MAIN, FALSE, FALSE, "", ""); if (main_count < 0) return -main_count; else if (main_count > 0) { checkmain = 0; first_table = MAIN_TABLE; sprintf(from, MAIN_TABLE); } annex_count = attrmask2fieldlist(fieldlist + strlen(fieldlist), p_info->attr_mask, T_ANNEX, first_table != NULL, FALSE, "", ""); if (annex_count < 0) return -annex_count; else if (annex_count > 0) { if (first_table) sprintf(from + strlen(from), " LEFT JOIN "ANNEX_TABLE" ON %s.id=" ANNEX_TABLE".id", first_table); else { first_table = ANNEX_TABLE; sprintf(from, ANNEX_TABLE); } } name_count = attrmask2fieldlist(fieldlist + strlen(fieldlist), p_info->attr_mask, T_DNAMES, first_table != NULL, FALSE, "", ""); if (name_count < 0) return -name_count; 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. */ sprintf(from + strlen(from), " LEFT JOIN "DNAMES_TABLE" ON %s.id=" DNAMES_TABLE".id", first_table); else { first_table = DNAMES_TABLE; sprintf(from, DNAMES_TABLE); } } if (first_table != NULL) { int shift = 0; sprintf(query, "SELECT %s FROM %s WHERE %s.id="DPK, fieldlist, from, first_table, pk); rc = db_exec_sql(&p_mgr->conn, query, &result); if (rc) return rc; 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) 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; } 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 &= ~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 ) { p_info->attr_mask &= ~ATTR_MASK_stripe_info; if ( ATTR_MASK_TEST( p_info, stripe_items ) ) p_info->attr_mask &= ~ATTR_MASK_stripe_items; } else if ( rc ) return rc; else checkmain = 0; /* entry exists */ } #else /* always clean them */ p_info->attr_mask &= ~(ATTR_MASK_stripe_info | ATTR_MASK_stripe_items); #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 &= ~dir_attr_set; } } if (checkmain) { /* verify it exists in main table */ sprintf( query, "SELECT id FROM " MAIN_TABLE " WHERE id="DPK, pk ); /* execute the request */ rc = db_exec_sql( &p_mgr->conn, query, &result ); if ( rc ) return rc; rc = db_next_record( &p_mgr->conn, &result, result_tab, 1 ); db_result_free( &p_mgr->conn, &result ); if (rc) return DB_NOT_EXISTS; } /* compute generated fields if asked */ generate_fields( p_info ); p_mgr->nbop[OPIDX_GET]++; return DB_SUCCESS; free_res: db_result_free( &p_mgr->conn, &result ); return rc; } /* listmgr_get_by_pk */