DAOS 源码解析之 daos_array

举报
debugzhang 发表于 2021/04/03 17:56:29 2021/04/03
【摘要】 DAOS (Distributed Asynchronous Object Storage) 是一个开源的对象存储系统,专为大规模分布式非易失性内存设计,利用了 SCM 和 NVMe 等的下一代 NVM 技术。 DAOS 同时在硬件之上提供了键值存储接口,提供了诸如事务性非阻塞 I/O、具有自我修复的高级数据保护、端到端数据完整性、细粒度数据控制和弹性存储的高级数据保护,从而优化性能并降低成本。

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_TRUNCglob 中的缓冲区过小,要求更大的缓冲区。在这种情况下,要求的缓冲区大学会被写入 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 是与 readvwirtev 操作相关的结构体。readvwritev 函数用于在一次原子操作中读、写多个非连续缓冲区。有时也将这两个函数称为分散读 (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

DAOS: https://github.com/daos-stack/daos

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。