Aerospike C客户端手册———最佳实践—记录使用

来源:互联网 发布:ubuntu创建新用户密码 编辑:程序博客网 时间:2024/05/18 00:26


记录使用

记录是Aerospike表示存储在数据库中数据的形式。记录由元数据和多个bin组成。这些bin保存记录的数据。每个bin有一个名称与一个值。元数据是关于记录的附加信息。在数据库中使用键(key)查找记录。

初始化记录

通过下列函数之一可初始化一条记录:

  • as_record_inita() — 在栈上初始化一条记录及其bin。
  • as_record_init()  — 在栈上初始化一条记录,但在堆上分配bin。
  • as_record_new()    — 在堆上分配一条记录及其bin并初始化。

无论何时初始化的记录,不再使用时应通过as_record_destroy()释放资源。

栈上分配记录

as_record_inita()与as_record_init()都在栈上分配且初始化一个记录,但它们分配记录bin的行为不同。

  • as_record_inita() 在栈上分配bin。
  • as_record_init()   在堆上分配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并初始化。
    来源: <http://www.aerospike.com/docs/client/c/best_practices/records.html>
     
0 0
原创粉丝点击