DAOS 源码解析之 daos_array
DAOS (Distributed Asynchronous Object Storage) 是一个开源的对象存储系统,专为大规模分布式非易失性内存设计,利用了 SCM 和 NVMe 等的下一代 NVM 技术。 DAOS 同时在硬件之上提供了键值存储接口,提供了诸如事务性非阻塞 I/O、具有自我修复的高级数据保护、端到端数据完整性、细粒度数据控制和弹性存储的高级数据保护,从而优化性能并降低成本。
本文以 Release 1.1.4 版本为标准,解析 include/daos_array.h
中的具体实现。include/daos_array.h
包含了 DAOS 与数组相关的 API ,提供 DAOS 对象数据模型上的一维数组实现。
daos_range_t
结构图 daos_range_t
表示连续记录的区间:
typedef struct {
// 区间中第一条记录的索引
daos_off_t rg_idx;
// 区间中记录的数量
daos_size_t rg_len;
} daos_range_t;
daos_array_iod_t
结构体 daos_array_iod_t
表示要访问的 DAOS 数组对象区间的 IO 描述符:
typedef struct {
// arr_rgs 中数据项的数量
daos_size_t arr_nr;
// 数组区间:每个区间定义一个起始索引和一个区间长度。
daos_range_t *arr_rgs;
// 只读情况:
// 返回从最大的 dkey (distribution key) 中 short fetch 的记录数。
// 这有助于检查 short read。
// 如果该值不为零,则可以进行 short read,并应使用
// daos_array_get_size() 函数与正在读取的索引进行比较。
daos_size_t arr_nr_short_read;
daos_size_t arr_nr_read;
} daos_array_iod_t;
daos_array_generate_id
daos_array_generate_id
函数是一个辅助函数,通过编码对象地址空间的 DAOS 保留位(高 32 位)来生成 DAOS 对象 ID。
参数:
old [in, out]
:[in]
:设置了低 96 位且在容器内唯一的对象 ID。[out]
:完全填充的 DAOS 对象标识符,低 96 位不变,编码 DAOS 保留位(高32位)。
cid [in]
:类标识符。add_attr [in]
:指示用户操作的标志true
:元数据应存储在对象中false
:维护数组单元格和块大小。
args [in]
:预留参数。
返回值:
- 始终为 0。
static inline int
daos_array_generate_id(daos_obj_id_t *oid, daos_oclass_id_t cid,
bool add_attr, uint32_t args)
{
static daos_ofeat_t feat;
uint64_t hdr;
// DAOS_OF_DKEY_UINT64:
// 未进行散列和数字排序的 DKEY key
// key 按客户端的字节顺序接受,DAOS 负责操作正确
// DAOS_OF_KV_FLAT 预留:1-level flat KV store
feat = DAOS_OF_DKEY_UINT64 | DAOS_OF_KV_FLAT;
// 判断用户操作标志
if (add_attr)
// DAOS_OF_ARRAY 预留:多维数组
feat = feat | DAOS_OF_ARRAY;
// TODO:此处应增加检查,如果用户修改了 DAOS 保留位,则返回 error
// OID_FMT_INTR_BITS:DAOS 保留位 (32 bits)
// 版本 (OID_FMT_VER_BITS, 4 bits)
// 特征 (OID_FMT_FEAT_BITS, 16 bits)
// 类 ID (OID_FMT_CLASS_BITS, 12 bits)
oid->hi &= (1ULL << OID_FMT_INTR_BITS) - 1;
// OID_FMT_VER:当前对象 ID 的版本
// OID_FMT_VER_SHIFT:对象 ID 中版本位的相对位移
hdr = ((uint64_t)OID_FMT_VER << OID_FMT_VER_SHIFT);
// OID_FMT_FEAT_SHIFT:对象 ID 中特征位的相对位移
hdr |= ((uint64_t)feat << OID_FMT_FEAT_SHIFT);
// OID_FMT_CLASS_SHIFT:对象 ID 中类 ID 位的相对位移
hdr |= ((uint64_t)cid << OID_FMT_CLASS_SHIFT);
oid->hi |= hdr;
return 0;
}
结构体 daos_obj_id_t
表示对象 ID,共 128 位。有关 daos_obj_id_t
的更多操作细节将在 include/daos_obj.h
中解析。
typedef struct {
// 高 32 位是 DAOS 的保留位
// 低 96 位由用户提供,并假定在容器中是唯一的
uint64_t lo;
uint64_t hi;
} daos_obj_id_t;
daos_oclass_id_t
类型用来表示对象类 ID:
typedef uint16_t daos_oclass_id_t;
daos_ofeat_t
类型用来表示对象的特征位:
typedef uint16_t daos_ofeat_t;
daos_array_create
daos_array_create
函数用于创建数组对象。这将打开一个 DAOS KV 对象并添加元数据来定义单元大小和块大小。进一步访问 KV 对象需要通过句柄,这需要使用元数据存储数组元素。
数组的元数据存储在 DKEY 0 (distribution key) 的特定 AKEY (attribute key) 下。这意味着该对象是一个通用数组对象,它的元数据在 DAOS 对象中被跟踪。oid
中的特征位必须设置为
DAOS_OF_DKEY_UINT64 | DAOS_OF_KV_FLAT | DAOS_OF_ARRAY
如果特征位没有设置 DAOS_OF_ARRAY
,则需要由用户来负责记住数组元数据,因为 DAOS 不会存储这些元数据,并且不应该调用此 API,因为该 API 不会向数组对象写入任何内容。在这种情况下,可以使用 daos_array_open_with_attrs()
获取数组对象,并通过数组 API 进行访问。
元数据只是 KV 对象中的项,这意味着任何用户都可以打开该对象并覆盖该元数据。用户可以重新创建数组,这不会破坏现有的原始数据,只会覆盖元数据。但是,更改元数据将导致未定义的访问问题(在这种情况下,我们可以通过读取元数据来检查对象是否存在,从而发现错误,但这会增加额外的开销)。
参数:
coh [in]
:打开的容器句柄。oid [in]
:对象 ID,要求 dkey 的特征位必须设置为DAOS_OF_KV_FLAT | DAOS_OF_DKEY_UINT64 |DAOS_OF_ARRAY
。th [in]
:事务句柄。cell_size [in]
:数组的单元大小。chunk_size [in]
:在移动到其它 dkey 前每个 dkey 下存储的连续记录的数量。oh [out]
:返回的打开的数组对象句柄。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的容器句柄。-DER_INVAL
:无效的参数。-DER_NO_PERM
:没有访问权限。-DER_UNREACH
:无法访问网络。
int
daos_array_create(daos_handle_t coh, daos_obj_id_t oid, daos_handle_t th,
daos_size_t cell_size, daos_size_t chunk_size,
daos_handle_t *oh, daos_event_t *ev)
{
daos_array_create_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_create,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_create, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->coh = coh;
args->oid = oid;
args->th = th;
args->cell_size = cell_size;
args->chunk_size = chunk_size;
args->oh = oh;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
daos_size_t
是 64 位无符号整数:
typedef uint64_t daos_size_t;
结构体 daos_array_create_t
表示数组创建参数:
typedef struct {
//打开的容器句柄
daos_handle_t coh;
// 数组 ID
daos_obj_id_t oid;
// 打开的事务句柄
daos_handle_t th;
// 数组的单元大小
daos_size_t cell_size;
// 1 个 dkey 下存储的记录数量
daos_size_t chunk_size;
// 返回的打开的数组句柄
daos_handle_t *oh;
} daos_array_create_t;
daos_array_open
daos_array_open
函数打开一个数组对象。如果该数组之前没有被创建过(不存在数组元数据),该操作会失败。
参数:
coh [in]
:打开的容器句柄。oid [in]
:对象 ID,要求 dkey 的特征位必须设置为DAOS_OF_KV_FLAT | DAOS_OF_DKEY_UINT64 |DAOS_OF_ARRAY
。th [in]
:事务句柄。mode [in]
:打开模式:DAOS_OO_RO
或DAOS_OO_RW
。cell_size [out]
:数组的单元大小。chunk_size [out]
:在移动到其它 dkey 前每个 dkey 下存储的连续记录的数量。oh [out]
:返回的打开的数组对象句柄。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的容器句柄。-DER_INVAL
:无效的参数。-DER_NO_PERM
:没有访问权限。-DER_NONEXIST
:无法找到对象。-DER_UNREACH
:无法访问网络。
int
daos_array_open(daos_handle_t coh, daos_obj_id_t oid, daos_handle_t th,
unsigned int mode, daos_size_t *cell_size,
daos_size_t *chunk_size, daos_handle_t *oh,
daos_event_t *ev)
{
daos_array_open_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_open,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_open, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 初始状态下数组的单元大小和块大小均为 0
*cell_size = 0;
*chunk_size = 0;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->coh = coh;
args->oid = oid;
args->th = th;
args->mode = mode;
args->open_with_attr = 0;
args->cell_size = cell_size;
args->chunk_size = chunk_size;
args->oh = oh;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
结构体 daos_array_open_t
表示数组打开参数:
typedef struct {
// 打开的容器句柄
daos_handle_t coh;
// 数组 ID
daos_obj_id_t oid;
// 打开的事务句柄
daos_handle_t th;
// 打开模式
unsigned int mode;
// 标记单元大小和块大小是否由用户提供
// 如果为 1,表示由用户提供,否则为 0
unsigned int open_with_attr;
// 数组的单元大小
daos_size_t *cell_size;
// 1 个 dkey 下存储的记录数量
daos_size_t *chunk_size;
// 返回的打开的数组句柄
daos_handle_t *oh;
} daos_array_open_t;
daos_array_open_with_attr
daos_array_open_with_attr
函数打开具有用户指定属性的数组对象。如果对象不存在,这与调用 daos_array_create
的结果相同,只是对象中没有任何更新,该 API 只是向用户返回一个打开的数组句柄。如果以前使用不同的单元大小和块大小访问数组,再次访问它将导致数组数据损坏。
参数:
coh [in]
:打开的容器句柄。oid [in]
:对象 ID,要求 dkey 的特征位必须设置为DAOS_OF_KV_FLAT | DAOS_OF_DKEY_UINT64 |DAOS_OF_ARRAY
。th [in]
:事务句柄。mode [in]
:打开模式:DAOS_OO_RO
或DAOS_OO_RW
。cell_size [in]
:数组的单元大小。chunk_size [in]
:在移动到其它 dkey 前每个 dkey 下存储的连续记录的数量。oh [out]
:返回的打开的数组对象句柄。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的容器句柄。-DER_INVAL
:无效的参数。-DER_NO_PERM
:没有访问权限。
int
daos_array_open_with_attr(daos_handle_t coh, daos_obj_id_t oid,
daos_handle_t th, unsigned int mode,
daos_size_t cell_size, daos_size_t chunk_size,
daos_handle_t *oh, daos_event_t *ev)
{
daos_array_open_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_open,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_open, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->coh = coh;
args->oid = oid;
args->th = th;
args->mode = mode;
// 单元大小和块大小由用户提供
args->open_with_attr = 1;
args->cell_size = &cell_size;
args->chunk_size = &chunk_size;
args->oh = oh;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
daos_array_local2global
daos_array_local2global
函数将本地数组句柄转换为可与对等进程共享的全局表示数据。
如果 glob->iov_buf
被设置为NULL,则通过 glob->iov_buf_len
返回全局句柄的实际大小。
此功能不涉及任何通信,也不阻塞。
参数:
oh [in]
:将被共享的有效的本地数组对象的打开句柄。glob [out]
:指向 IO vector 缓冲区的指针,用于存储句柄信息。
返回值,在非阻塞模式下:
- 如果成功,写入 0。
- 如果失败:
-DER_INVAL
:无效的参数。-DER_NO_HDL
:数组句柄不存在。-DER_TRUNC
:glob
中的缓冲区过小,要求更大的缓冲区。在这种情况下,要求的缓冲区大学会被写入glob->iov_buf_len
。
int
daos_array_local2global(daos_handle_t oh, d_iov_t *glob)
{
return dc_array_local2global(oh, glob);
}
daos_array_global2local
daos_array_global2local
函数为全局表示数据创建本地数组打开句柄。
必须使用 daos_array_close()
关闭此句柄。
参数:
oh [in]
:将被共享的有效的本地数组对象的打开句柄。glob [in]
:要提取的集合句柄的全局(共享)表示。mode [in]
:改变对象的打开模式(可选)。传递 0 将继承全剧表示的打开模式。oh [out]
:返回的本地数组打开句柄。
返回值,在非阻塞模式下:
- 如果成功,写入 0。
- 如果失败:
-DER_INVAL
:无效的参数。-DER_NO_HDL
:数组句柄不存在。
int
daos_array_global2local(daos_handle_t coh, d_iov_t glob, unsigned int mode,
daos_handle_t *oh)
{
return dc_array_global2local(coh, glob, mode, oh);
}
daos_array_close
daos_array_close
函数关闭一个打开的数组对象。
参数:
oh [in]
:打开的数组对象句柄。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的打开句柄。
int
daos_array_close(daos_handle_t oh, daos_event_t *ev)
{
daos_array_close_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_close,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_close, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->oh = oh;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
结构体 daos_array_close_t
表示数组关闭参数:
typedef struct {
// 打开的数组句柄
daos_handle_t oh;
} daos_array_close_t;
daos_array_read
daos_array_read
函数从数组对象中读取数据。
参数:
oh [in]
:打开的数组对象句柄。th [in]
:事务句柄。iod [in]
:要读取的数组区间的 IO 描述符。sgl [in]
:存储数组数据的分散/聚集列表(sgl)。缓冲区大小不必与单个区间大小匹配,只要总大小匹配即可。用户需要分配缓冲区并设置每个缓冲区的长度。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的打开句柄。-DER_INVAL
:无效的参数。-DER_UNREACH
:无法访问网络。-DER_REC2BIG
:记录太大,无法放入输出缓冲区。
int
daos_array_read(daos_handle_t oh, daos_handle_t th, daos_array_iod_t *iod,
d_sg_list_t *sgl, daos_event_t *ev)
{
daos_array_io_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_read,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_read, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->oh = oh;
args->th = th;
args->iod = iod;
args->sgl = sgl;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
结构体 d_sg_list_t
表示内存缓冲区的分散/聚集列表:
typedef struct {
// I/O vector 总数
uint32_t sg_nr;
// 已使用的 I/O vector 数量
uint32_t sg_nr_out;
// 存储 I/O vector 的数组
d_iov_t *sg_iovs;
} d_sg_list_t;
I/O vector 是与 readv
和 wirtev
操作相关的结构体。readv
和 writev
函数用于在一次原子操作中读、写多个非连续缓冲区。有时也将这两个函数称为分散读 (scatter read) 和聚集写 (gather write)。
结构体 daos_array_io_t
表示数组读/写参数:
typedef struct {
// 打开的数组句柄
daos_handle_t oh;
// 打开的事务句柄
daos_handle_t th;
// 数组 IO 描述符
daos_array_iod_t *iod;
// 内存描述符
d_sg_list_t *sgl;
} daos_array_io_t;
adaos_array_write
daos_array_write
函数向数组对象写入数据。
参数:
oh [in]
:打开的数组对象句柄。th [in]
:事务句柄。iod [in]
:要写入的数组区间的 IO 描述符。sgl [in]
:存储数组数据的分散/聚集列表(sgl)。缓冲区大小不必与单个区间大小匹配,只要总大小匹配即可。用户需要分配缓冲区并设置每个缓冲区的长度。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的打开句柄。-DER_INVAL
:无效的参数。-DER_UNREACH
:无法访问网络。-DER_REC2BIG
:记录太大,无法放入输出缓冲区。
int
daos_array_write(daos_handle_t oh, daos_handle_t th, daos_array_iod_t *iod,
d_sg_list_t *sgl, daos_event_t *ev)
{
daos_array_io_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_write,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_write, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->oh = oh;
args->th = th;
args->iod = iod;
args->sgl = sgl;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
daos_array_get_size
daos_array_get_size
函数查询数组对象中的记录数量。
参数:
oh [in]
:打开的数组对象句柄。th [in]
:事务句柄。size [out]
:返回的数组大小(记录的数量)。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的打开句柄。-DER_INVAL
:无效的参数。-DER_UNREACH
:无法访问网络。
int
daos_array_get_size(daos_handle_t oh, daos_handle_t th, daos_size_t *size,
daos_event_t *ev)
{
daos_array_get_size_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_get_size,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_get_size, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->oh = oh;
args->th = th;
args->size = size;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
daos_size_t
类型是 64 位无符号整数:
typedef uint64_t daos_size_t;
结构体 daos_array_get_size_t
表示获取数组大小的参数:
typedef struct {
// 打开的数组句柄
daos_handle_t oh;
// 打开的事务句柄
daos_handle_t th;
// 返回的数组大小(记录数)
daos_size_t *size;
} daos_array_get_size_t;
daos_array_set_size
daos_array_set_size
函数在记录中设置数组大小(缩短)。
如果缩小数组,我们将按要求大小对 dkey/记录进行打孔 (punch) (“punch” 原意为打孔,这里的 punch 操作我个人理解是类似于截断,在原大小范围内制造一个空洞,清除所有数据,然后将空洞的前后拼接在一起)。
如果扩大数组,我们将以相应的大小插入一条记录。这并不等同于分配。
参数:
oh [in]
:打开的数组对象句柄。th [in]
:事务句柄。size [out]
:返回的数组大小(记录的数量)。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的打开句柄。-DER_INVAL
:无效的参数。-DER_UNREACH
:无法访问网络。
int
daos_array_set_size(daos_handle_t oh, daos_handle_t th, daos_size_t size,
daos_event_t *ev)
{
daos_array_set_size_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_set_size,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_set_size, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->oh = oh;
args->th = th;
args->size = size;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
结构体 daos_array_set_size_t
表示数组设置大小的参数:
typedef struct {
// 打开的数组句柄
daos_handle_t oh;
// 打开的事务句柄
daos_handle_t th;
// 数组需要缩短的大小
daos_size_t size;
} daos_array_set_size_t;
daos_array_destroy
daos_array_destroy
函数通过打孔数组对象中的所有数据(键),包括与数组关联的元数据,销毁数组对象。
daos_obj_punch()
将在接下来调用。在执行完该操作后仍然需要通过调用 daos_array_close()
来关闭打开的数组句柄,但是使用该句柄或其他打开的数组句柄进行的任何访问都将失败。销毁将在不考虑任何打开的句柄的情况下执行,因此用户有责任确保在执行销毁操作之前不再有对数组的访问。
参数:
oh [in]
:打开的数组对象句柄。th [in]
:事务句柄。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的打开句柄。-DER_INVAL
:无效的参数。-DER_UNREACH
:无法访问网络。
int
daos_array_destroy(daos_handle_t oh, daos_handle_t th, daos_event_t *ev)
{
daos_array_destroy_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_destroy,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_destroy, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->oh = oh;
args->th = th;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
结构体 daos_array_destroy_t
表示数组销毁参数:
typedef struct {
// 打开的数组句柄
daos_handle_t oh;
// 打开的事务句柄
daos_handle_t th;
} daos_array_destroy_t;
daos_array_punch
daos_array_punch
函数在 IO 描述符 (iod
) 中指定的数组区间中打孔。
参数:
oh [in]
:打开的数组对象句柄。th [in]
:事务句柄。iod [in]
:要打孔的数组区间的 IO 描述符。ev [in]
:结束事件,该参数是可选的,可以为NULL
。当该参数为NULL
时,该函数在阻塞模式下运行。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的打开句柄。-DER_INVAL
:无效的参数。-DER_UNREACH
:无法访问网络。
int
daos_array_punch(daos_handle_t oh, daos_handle_t th,
daos_array_iod_t *iod, daos_event_t *ev)
{
daos_array_io_t *args;
tse_task_t * task;
int rc;
// 创建新任务 dc_array_punch,并将其与输入事件 ev 关联
// 如果事件 ev 为 NULL,则将获取私有事件
rc = dc_task_create(dc_array_punch, NULL, ev, &task);
if (rc)
// dc_task_create 成功返回 0,失败返回负数
return rc;
// 从 task 中获取参数
args = dc_task_get_args(task);
args->oh = oh;
args->th = th;
args->iod = iod;
args->sgl = NULL;
// 调度创建的任务 task
// 如果该任务的关联事件是私有事件,则此函数将等待任务完成
// 否则它将立即返回,并通过测试事件或在 EQ 上轮询找到其完成情况
//
// 第二个参数 instant 为 true,表示任务将立即执行
return dc_task_schedule(task, true);
}
daos_array_get_attr
daos_array_get_attr
函数从打开的句柄中检索数组单元大小和块大小。
参数:
oh [in]
:打开的数组句柄。chunk_size [out]
:数组的块大小。cell_size [out]
:数组的单元大小。
返回值,在非阻塞模式下会被写入 ev::ev_error
:
- 如果成功,写入 0。
- 如果失败:
-DER_NO_HDL
:无效的打开句柄。-DER_INVAL
:无效的参数。
int
daos_array_get_attr(daos_handle_t oh, daos_size_t *chunk_size,
daos_size_t *cell_size)
{
return dc_array_get_attr(oh, chunk_size, cell_size);
}
相关信息
Emai: debugzhang@163.com
- 点赞
- 收藏
- 关注作者
评论(0)