#文件管理

YFS提供了下列文件管理接口:

  • 命令行下通过yfscmd管理文件。

  • 通过C API在程序中操作YFS文件。

指定YFS文件路径:

  • /开头为本地文件系统路径。
  • +开头为YFS路径,例如'+DG0/data'。

# 通过yfscmd管理

通过yfscmd工具,用户可以使用与Linux shell类似的文件操作命令,对YFS中的文件进行查询和管理。

# 启动yfscmd shell

成功启动yfscmd shell的前提:

  • YFS服务已启动(通过ycsctl status查看)。
  • YASCS_HOME环境变量已正确设置。
$ yfscmd

成功进入shell后即可执行下述命令。

# 查看当前目录

通过pwd查看当前工作目录。

yfscmd启动时的工作路径为YFS的根目录+

YFSCMD >  pwd
+

# 切换目录

通过cd命令切换工作目录,可以指定YFS绝对路径或相对路径。

YFSCMD >  cd +DG2

# 创建目录

通过mkdir创建目录,新目录不能与同级的任何文件或目录同名。

根目录+下一级目录是DiskGroup的虚拟目录,不能通过mkdir在此创建目录。仅可以通过创建DiskGroup实现在此创建目录的目的。

YFSCMD >  mkdir data1
YFSCMD >  ls
data1

# 复制

通过cp命令复制文件或目录。如果第一个参数是目录,则递归复制。

cp不仅支持YFS内部文件、目录的复制,也可以YFS和本地文件系统互相复制。

cp命令通过参数的第一个字符识别文件系统:

  • /开始为本地文件系统路径。
  • +开始为YFS路径。
  • 相对路径为YFS路径。
# 系统复制到YFS
YFSCMD > cp  /home/yashan/data2.dat data2
cp OK: SYS:/home/yashan/data2.dat --> YFS:+DG2/data2
YFSCMD >  ls
data1
data2
# YFS复制到系统
YFSCMD >  cp data1 /home/yashan/data1
cp OK: YFS:+DG2/data1 --> SYS:/home/yashan/data1
# YFS内复制
YFSCMD >  cp data2 data3.dat
cp OK: YFS:+DG2/data2 --> YFS:+DG2/data3.dat

Note:

与一般文件系统缺省创建同名对象不同,cp命令的第二个参数需明确指明新名称。

# 查看文件清单

通过ls指令查看文件清单,详细使用请参考yfscmd说明文档。

YFSCMD >  ls
data1
data2
data3.dat

# 创建文件快照

通过snapshot命令可以为任何YFS文件创建快照。快照仅保存文件在某一时刻的状态(存储分配单元列表),不复制实际数据。

Note:

仅全新安装的YashanDB v27.1.1及以上版本完整支持快照功能。若由旧版本升级至YashanDB v27.1.1或以上版本,存量磁盘组将无法使用相应功能。

YFSCMD > snapshot +DG0/datafile

单个文件只能记录一个快照版本,多次创建仍只会关联最后一次创建的快照。删除文件时,如果该文件存在快照,快照会自动被删除。

# 借助快照闪回文件

对于存在快照的文件,通过reset命令将其快速恢复到快照时的状态。

Note:

仅全新安装的YashanDB v27.1.1及以上版本完整支持文件闪回功能。若由旧版本升级至YashanDB v27.1.1或以上版本,存量磁盘组将无法使用相应功能。

YFSCMD > reset +DG0/clone_file

始终只能闪回到最近一次创建的快照,无法指定快照版本。闪回后,原文件与快照文件共享存储分配单元数据。

# 创建克隆文件

YFS具备文件克隆功能,通过执行cp -C命令可以为源文件以克隆方式在同一磁盘组内创建一个即时副本。

Note:

仅全新安装的YashanDB v27.1.1及以上版本完整支持文件克隆功能。若由旧版本升级至YashanDB v27.1.1或以上版本,存量磁盘组将无法使用相应功能。

YFSCMD > cp -C data data_clone
cp OK: YFS:+DG2/data --> YFS:+DG2/data_clone

在创建克隆文件时,并不会即刻复制文件数据,而是仅与源文件共享存储分配单元。只有当对源文件或克隆文件执行写入操作时,克隆文件才会进行数据复制,即采用写时复制(COW, Copy-on-Write)机制。

在创建克隆文件时,会自动为其创建一次快照,如需手动创建新版本的快照,请查阅创建文件快照

借助快照可以将克隆文件快速闪回至快照创建时刻的版本,具体操作请查阅借助快照闪回文件

# 重命名文件或目录

通过mv重命名文件或目录,第二个参数必须明确指定新名称。

根目录 + 下一级目录是DiskGroup的虚拟目录,不能被重命名。

YFSCMD >  mv data2 data1
mv: YFS:+DG2/data2 --> YFS:+DG2/data1.
YFSCMD >  ls
data1
data3.dat

# 删除文件或目录

通过rm命令删除文件或目录。

默认不能删除非空目录,但可以指定-r参数递归删除非空目录。

根目录+下一级目录是DiskGroup的虚拟目录,不能通过rm删除。只能通过删除DiskGroup,删除对应的虚拟目录。

删除文件时,同时会自动删除其关联的快照。

YFSCMD >  rm data1
DELETE +DG2/data1

# 通过C API管理

# 基本概念

YFS提供了一组C API(以下简称API),方便通过程序访问YFS。

通过API访问YFS的程序,称为YFS的客户端。YFS通过UDS和共享内存提供服务,仅允许客户端访问本地(部署在同一服务器上)的YFS服务,且要求客户端进程具备该UDS和共享内存的访问权限。

API通过YfsiConn抽象客户端与YFS服务间的连接,每个线程必须独立使用一个YfsiConn以获得更高的数据安全保障。所有API都需要传入YfsiConn,并确保开始操作前先创建连接,所有操作结束时及时关闭并释放连接,不要重复释放连接。

YFS通过uint32_t表示打开的文件fd。

YFS仅支持DIRECT IO,因此文件IO的offset、length及buffer的地址,都需按YFS_ALIGN_SIZE字节对齐,其定义为:

#define YFS_ALIGN_SIZE 512

请按以下流程操作YFS文件:

  1. 打开文件。
  2. 任意次数读写文件。
  3. 关闭文件。

YFS是高性能集群文件系统,各节点IO完全并行,客户端应妥善处理并发IO、并发文件增删等操作,避免出错。

API均为yfsi前缀的C函数,采用驼峰命名规范。

除返回void的函数外,返回int的函数遵循以下规范:

  • 返回0,表示执行成功。
  • 返回非零,表示执行失败,可以通过codGetErrorCode获取错误码,通过codGetErrorMsg获取错误信息。

# API说明

# yfsiAllocConn

int  yfsiAllocConn(YfsiConn** conn);

创建连接对象,必须在不同线程使用独立的连接。

参数 描述
conn 连接对象二级指针

# yfsiFreeConn

void yfsiFreeConn(YfsiConn* conn);

释放连接对象。

参数 描述
conn 连接对象指针

# yfsiConnect

int  yfsiConnect(YfsiConn* conn, const char* url);

连接到服务。

参数 描述
conn 连接对象指针
url 连接地址,请通过yfsiFormatUrl格式化该URL

示例

char linkUrl[1024] = {0};
yfsiFormatUrl("/YFS/home", linkUrl, 1024);

if (yfsiConnect(conn, linkUrl) != 0) {
    printf("failed to connect to YFS server. [%u] %s\n", codGetErrorCode(), codGetErrorMsg());
    // error handling
}

# yfsiDisconnect

void yfsiDisconnect(YfsiConn* conn);

断开连接。

参数 描述
conn 连接对象指针

# yfsiOpenFile

int yfsiOpenFile(YfsiConn* conn, const char* fileName, uint32_t* fd);

打开文件。仅支持打开YFS文件,试图打开目录或非YFS文件都会失败。

参数 描述
conn 连接对象指针
fileName 文件的绝对路径,仅支持YFS路径,格式为+磁盘组名称/目录/文件名
fd fd指针

示例

uint32_t fd = 0;
if (yfsiOpenFile(conn, "+DG0/testdir/testfile", &fd) != 0) {
    printf("failed to open file. [%u] %s\n", codGetErrorCode(), codGetErrorMsg());
    // error handling
}

# yfsiCloseFile

int yfsiCloseFile(YfsiConn* conn, uint32_t fd);

关闭文件。

参数 描述
conn 连接对象指针
fd 通过yfsiOpenFile打开的fd

示例

(void) yfsiCloseFile(conn, fd);

# yfsiWriteFile

int yfsiWriteFile(YfsiConn* conn, uint32_t fd, char* buf, uint64_t offset, uint32_t size);

向已打开的文件写入数据。YFS不支持文件自动扩展,请确保文件有足够的空间写入数据。

参数 描述
conn 连接对象指针
fd 通过yfsiOpenFile打开的fd
buf 待写入数据所在buffer,该buffer地址必须YFS_ALIGN_SIZE字节对齐
offset 写入文件的偏移,按YFS_ALIGN_SIZE字节对齐
size 写入数据大小,按YFS_ALIGN_SIZE字节对齐

示例

if (yfsiWriteFile(conn, fd, buffer, 0, 1024) != 0) {
    printf("failed to write file. [%u] %s\n", codGetErrorCode(), codGetErrorMsg());
    // error handling
}

# yfsiReadFile

int yfsiReadFile(YfsiConn* conn, uint32_t fd, char* buf, uint64_t offset, uint32_t size, uint32_t* actualSize);

读取已打开的文件。YFS不允许超出文件末尾的读操作。

参数 描述
conn 连接对象指针
fd 通过yfsiOpenFile打开的fd
buf 用于保存读出数据的buffer,该buff地址必须YFS_ALIGN_SIZE字节对齐
offset 写入文件的偏移,按YFS_ALIGN_SIZE字节对齐
size 写入数据大小,按YFS_ALIGN_SIZE字节对齐
actualSize 实际读入数据长度

示例

uint32_t realLen = 0;
if (yfsiReadFile(conn, fd, buffer, 0, 1024, &realLen) != 0) {
    printf("failed read file. [%u] %s\n", codGetErrorCode(), codGetErrorMsg());
    // error handling
}

# yfsiFormatUrl

void yfsiFormatUrl(const char *home, char *url, int len);

格式化YFS连接的URL。

参数 描述
home YFS的home路径,通常为YASCS_HOME环境变量的值,即YFS配置文件所在目录的父目录
url 输出url的buffer
len url buffer的长度

示例

char linkUrl[1024] = {0};
yfsiFormatUrl("/YFS/home", linkUrl, 1024);

# 错误信息

uint32_t codGetErrorCode();
char*    codGetErrorMsg();

获取错误码和错误信息。

# 完整示例

#include <stdio.h>
#include <stdlib.h>
// 引入YFS API头文件
#include "yfsi_include.h"

int main(int argc, const char ** argv) 
{
    if (argc < 2 || argv[1][0] != '+') {
        printf("expecting YFS path, like: +DG0/file/path\n");
        return 1;
    }

    const char* path = argv[1];

    /*
    * 获取YFS的home路径,通常为YASCS_HOME环境变量、yascs或yasfs进程的-D参数。
    * 这里以YASCS_HOME环境变量为例。
    */
    const char* home = getenv("YASCS_HOME");
    if (home == NULL || strlen(home) == 0) {
        printf("YASCS_HOME not set yet.\n");
        return 1;
    }

    /**
     * 申请buffer,必须按YFS_ALIGN_SIZE对齐.
    */
    char* buffer = NULL;
    if (posix_memalign((void **)&buffer, YFS_ALIGN_SIZE, 1024) != 0 ) {
        printf("failed to allocate buffer.\n");
        return 1;
    }

    /**
     * 创建连接
     */
    YfsiConn *conn = NULL;
    if (yfsiAllocConn(&conn) != 0) {
        printf("failed to allocate connection. [%u] %s\n", codGetErrorCode(), codGetErrorMsg());
        free(buffer);
        return 1;
    }

    /**
     * 生成连接url
     */
    char linkUrl[1024] = {0};
    yfsiFormatUrl(home, linkUrl, 1024);

    /**
     * 连接到服务
     */
    if (yfsiConnect(conn, linkUrl) != 0) {
        printf("failed to connect to the yfs server. [%u] %s\n", codGetErrorCode(), codGetErrorMsg());
        yfsiFreeConn(conn);
        free(buffer);
        return 1;
    }

    /**
     * 打开文件,获得fd
     */
    uint32_t fd;
    if (yfsiOpenFile(conn, path, &fd) != 0) {
        printf("failed to open file. [%u] %s\n", codGetErrorCode(), codGetErrorMsg());
        yfsiDisconnect(conn);
        yfsiFreeConn(conn);
        free(buffer);
        return 1;
    }

    printf("file opened.\n");

    /**
     * 读取文件,应确保读范围在文件大小内,否则失败。
    */
    uint32_t realLen = 0;
    if (yfsiReadFile(conn, fd, buffer, 0, 1024, &realLen) != 0) {
        printf("failed to read file. [%u] %s\n", codGetErrorCode(), codGetErrorMsg());
        yfsiCloseFile(conn, fd);
        yfsiDisconnect(conn);
        yfsiFreeConn(conn);
        free(buffer);
        return 1;
    }

    printf("read file, len = %u.\n", realLen);

    /**
     * 写入文件,应确保写入范围在文件大小内,否则失败。
    */
    if (yfsiWriteFile(conn, fd, buffer, 0, 1024) != 0) {
        printf("failed to write file. [%u] %s\n", codGetErrorCode(), codGetErrorMsg());
        yfsiCloseFile(conn, fd);
        yfsiDisconnect(conn);
        yfsiFreeConn(conn);
        free(buffer);
        return 1;
    }

    printf("write file, len = %u.\n", 1024);

    /**
     * 关闭打开的文件
     * 断开连接
     * 释放连接
     * 释放buffer内存
    */
    yfsiCloseFile(conn, fd);
    yfsiDisconnect(conn);
    yfsiFreeConn(conn);
    free(buffer);

    return 0;
}
edit-icon
反馈
coperate-icon
coperate
合作
communication-icon
communicate
交流