無論何時初始化的記錄,不再使用時應通過as_record_destroy()釋放資源。
as_record_inita()與as_record_init()都在棧上分配且初始化一個記錄,但它們分配記錄bin的行為不同。
as_record_inita() 在棧上分配bin。下面是一個簡單的as_record_inita()例子。在使用上沒有區別,只是在如何分配空間上存在不同。
as_record rec;
as_record_inita(&rec, 3);
as_record_set_int64(&rec, 1);
as_record_set_int64(&rec, 2);
as_record_set_int64(&rec, 3);
as_record_destroy(&rec);
即使記錄和bin都是在棧上分配,bin值所用空間還是可能會從堆上分配。因此,應使用as_record_destroy()安全地釋放記錄及其相關資源。
堆上分配記錄
使用as_record_new()將在堆上分配記錄。
as_record *rec = as_record_new(10);
as_record_set_int64(rec, 1);
as_record_set_int64(rec, 2);
as_record_set_int64(rec, 3);
as_record_destroy(rec);
當不再需要此記錄時,應使用as_record_destroy()安全地釋放記錄及其相關資源。
訪問記錄的bin
API提供多種方法來訪問記錄的bin。
為訪問記錄的bin,首先需要初始化一條記錄並以bin數據填充。有兩種獲取記錄數據的方法:
初始化並填充記錄的bin。請參見【填充記錄的bin】。
從讀取操作的返回中獲取記錄數據。請參見【記錄與讀操作】。
一旦有個初始化完成的記錄,就可使用這些功能之一,讀取記錄的bin數據。
獲取Bin
API提供了一系列getter函數,從記錄中取出指定數據類型的bin數值。getter函數要求一個記錄對象與bin名稱做為參數。
下面的getter函數用於獲取bin的原生類型(native-type)數值:
as_record_get_int64()
as_record_get_str()
更詳細內容在【API文檔】。
以下是getter函數使用示例:
int64_t ibin = as_record_get_int64(rec, "ibin", 123);
char *sbin = as_record_get_str(rec, "sbin");
下面的getter函數返回非原生類型數值的指針:
as_record_get_integer()
as_record_get_string()
as_record_get_bytes()
as_record_get_list()
as_record_get_map()
若應用保存這些getter函數返回的數值指針,然後銷毀了這條記錄,那麼指針將指向無效數據。為防止出現這種情況,可通過as_val_reserve()增加這些getter函數返回值的引用計數。
as_list *lbin = (as_list*)as_val_reserve(as_record_get_list(&rec, "lbin"));
as_record_destroy(&rec);
int64_t i1 = as_arraylist_get_int64(lbin, 1);
int64_t i2 = as_arraylist_get_int64(lbin, 2);
int64_t i3 = as_arraylist_get_int64(lbin, 3);
as_list_destroy(lbin);
上面代碼中的5-7行會有效地讀取數據。若as_val_reserve()沒被調用,就會引起無效讀取,可能導致數據損壞。完成數據讀取後,應使用相應的銷毀函數釋放它。
填充記錄的bin
在能填充一條記錄數據前,必須先初始化它。有三個初始化記錄的方法。
as_record_inita() — 在棧上初始化一條記錄及其bin。
as_record_init() — 在棧上初始化一條記錄,但在堆上分配bin。
as_record_new() — 在堆上分配一條記錄及其bin並初始化。
這些函數都接受一個參數指明需分配bin的個數,初始化完成的記錄能用來填充數據。
設置Bin值
有一系列的setter函數,用來設置不同數據類型的bin。每個setter函數要求一個記錄對象、一個bin名稱和一個bin值做為參數,操作成功返回true。
下面是設置原生類型bin數據的setter函數:
as_record_set_int64() — 設置一個int64_t類型的值。
as_record_set_str() — 設置值為一個以空字符(NULL)結束的字符串。
as_record_set_strp() — 設置值為一個以空字符(NULL)結束的字符串,指定在記錄銷毀時是否釋放原值所占用的空間。
as_record_set_raw() — 設置一個字節數組類型的值
as_record_set_rawp() — 設置一個字節數組類型的值,指明在記錄銷毀時是否釋放原值所占用的空間。
具體細節請參見【API文檔】。
下面是一些使用setter函數的例子:
as_record_set_int64(rec, "ibin", 123);
as_record_set_str(rec, "sbin", "abc");
as_record_set_strp(rec, "spbin", strdup("ijk"), true);
as_record_set_raw(rec, "rbin", (uint8_t*)"xyz", 3);
下列setter函數保持對非原生類型數據的指針引用:
as_record_set_integer() — Sets an as_integer value.
as_record_set_string() — Sets an as_string value.
as_record_set_bytes() — Sets an as_bytes value.
as_record_set_list() — Sets an as_list value.
as_record_set_map() — Sets an as_map value.
當通過as_record_destroy()釋放一個記錄,使用這些調用設置的值也將被釋放。若在其它地方使用這些值,在向記錄設置這些值時應用通過as_val_reserver()增加其引用計數,防止它們在釋放記錄時被同時釋放。
下面是在將值增加到記錄前增加其引用計數的示例,當記錄被銷毀時,list將不受影響。若引用計數未被增加,那麼list將被銷毀,其內包含的數據也不再存在。
as_arraylist list;
as_arraylist_init(&list, 3);
as_arraylist_append_int64(&list, 1);
as_arraylist_append_int64(&list, 2);
as_arraylist_append_int64(&list, 3);
as_record rec;
as_record_inita(&rec, 1);
as_record_set_list(&rec, "lbin", (as_list*)as_val_reserve(&list));
as_record_destroy(&rec);
int64_t i1 = as_arraylist_get_int64(&list, 1);
int64_t i2 = as_arraylist_get_int64(&list, 2);
int64_t i3 = as_arraylist_get_int64(&list, 3);
as_arraylist_destroy(&list);
上面代碼中的13-15行會有效地讀取數據。若as_val_reserver()未被 調用,就會是無效的讀取,可能導致數據損壞。
設置分代編號
分代編號即一條記錄的版本號。每次對記錄的修改都會增加分代編號的值。可設置一條記錄的分代編號,但通常用來提示記錄所在的服務器一個期望的分代編號。
rec->gen = 0
設置生存時間
每條記錄還有一個生存時間(TTL),指定記錄何時過期或從數據庫中驅逐。此值定義從當前開始的秒數。
rec->ttl = 3600 * 24;
遍歷記錄的全部bin
你可能需要遍歷一條記錄的所有bin,Aerospike C客戶端提供兩個方法:
as_record_foreach() — 迭代一條記錄的每一個bin,並為每個bin調用一函數。
as_record_iterator() — 記錄全部bin的迭代器。
as_record_foreach
函數as_record_foreach()迭代一條記錄的每一個bin,並為每個bin調用一函數。此函數還接受一個用戶數據參數,可以是用戶提供的、在回調函數內使用的任何數據。
下面的例子填充一個記錄的數據,然後迭代遍歷它的全部bin。
as_record rec;
as_record_inita(&rec, 3);
as_record_set_int64(&rec, "a", 1);
as_record_set_int64(&rec, "b", 2);
as_record_set_int64(&rec, "c", 3);
as_record_foreach(&rec, callback, NULL);
這個例子使用的回調函數打印bin的名稱和數值:
bool callback(const char *name, const as_val *value, void *udata)
{
as_integer *ivalue = as_integer_fromval(value);
if (ivalue) {
printf("%s = %d\n", name, as_integer_get(ivalue));
}
else {
printf("%s is not an integer?!\n", name);
}
return true;
}
若回調函數返回true,繼續迭代下一個bin,否則迭代中止。
as_record_iterator
as_record_iterator是一數據結構,提供迭代一條記錄全部bin的能力。為使用as_record_iterator,首先需要初始化它:
as_record_iterator_init() — 初始化一個棧上分配的迭代器。
as_record_iterator_new() — 分配和初始化一個堆上分配的迭代器。
一旦迭代器初始化完成,就能使用下面的函數完成迭代器遍歷:
as_record_iterator_has_next() — 檢測是否還有更多的bin可遍歷。
as_record_iterator_next() — 將迭代器移動到下一個bin,並返回此bin。
下面的示例,是前面foreach示例的迭代器實現方式:
as_record_iterator it;
as_record_iterator_init(&it, &rec);
while (as_record_iterator_has_next(&it)) {
as_bin *bin = as_record_iterator_next(&it);
char *name = as_bin_get_name(bin);
as_val *value = (as_val*)as_bin_get_value(bin);
as_integer *ivalue = as_integer_fromval(value);
if (ivalue) {
printf("%s = %d\n", name, as_integer_get(ivalue));
}
else {
printf("%s is not an integer?!\n", name);
}
}
記錄與讀取操作
讀取操作從服務器取回數據並填充記錄對象。下面是一些從服務器上讀取記錄數據的操作。
aerospike_key_get() — 讀取一條記錄的全部bin。在【讀取記錄】章節進一步討論。
aerospike_key_select() — 讀取一條記錄的指定bin。在【讀取記錄】章節進一步討論。
aerospike_key_operate() — 在一條記錄上執行操作,包括讀取指定bin。在【讀取記錄】章節進一步討論。
每個操作接受一個記錄對象作為參數(as_record **),用來接收從服務器讀取的數據來。
下面解釋一個記錄對象如何被讀取操作所填充。
空指針(NULL)記錄
若記錄對象參數是一個空指針(NULL),則讀取操作會從堆上分配記錄的空間,並且用足夠多的bin個數初始化它,以容納服務器返回的全部bin數據。
as_record *rec = NULL;
aerospike_key_get(&as, &err, NULL, &key, &rec)
as_record_destroy(rec);
當不再需要此記錄對象時,必須通過as_record_destroy()釋放其資源。
初始化完成的記錄
初始化完成的記錄被用作讀取操作的參數。
若記錄對象是以非零的bin個數初始化,讀操作嘗試以記錄可用的bin盡可能多地填充它。作為一個例子,比如說初始化10個bin的一個記錄對象,若服務器返回3個bin的數據,那麼對象記錄只有3個bin會被填充值;若服務器返回20個bin的數據,那麼只有前10個bin數據會被填充到記錄對象中。或者,若記錄對象的10個bin只有5個bin可用,將它傳送給讀操作,那麼只有這5個bin被來自服務器的數據填寫。
若記錄對象被初始化成沒有bin,那讀取操作將嘗試從堆上分配足夠多的bin空間,以容納服務器端返回的全部bin數據。
在初始化記錄對象時,可選擇在棧上或堆上初始化它:
as_record_inita() — 在棧上初始化一條記錄及其bin。
as_record_init() — 在棧上初始化一條記錄,但在堆上分配bin。
as_record_new() — 在堆上分配一條記錄及其bin並初始化。