在熟悉了glusterfs的基本原理和操作之后,今天对glusterfs的外部编程接口函数进行了学习,进一步加深了对glusterfs的理解。对glusterfs的使用也有了一些新的想法。查阅网上的资料发现,glusterfsAPI函数库方面的资料很少,于是选择了阅读API的源代码来学习。
GlusterFS从3.4版本开始提供了libgfapi接口,通过缩减I/O路径,帮助各种应用进一步提升性能。Libgfapi是一个用户空间的GlusterFS数据访问接口API函数库,可以绕开FUSE挂载点直接访问glusterfs卷,直接在应用程序通过调用API来访问数据。它缩减了FUSE和内核VFS层的I/O访问路径,通过它访问glusterfs卷,性能和latency均可以得到大幅提升。
Libgfapi中所有的库函数都使用了glfs这一结构体对象,这一对象包含了卷名、上下文及分卷等标签性信息。任何程序在使用libgfapi这一函数库之前都必须先创建一个新的glfs对象:
//glfs_t 为glfs结构体类型。@volname为卷名 glfs_t glfs_new (const char volname) ;glfs_new函数返回一个新的glfs对象,在这一对象基础上我们还需要调用Libgfapi库函数配置静态的配置文件或者动态设置master节点。
/* 使用配置文件进行静态配置 @fs: 使用配置文件进行配置的glfs对象 @volfile: glusterfs配置文件的路径 返回值 0 : Success. -1 : Failure.. */ int glfs_set_volfile (glfs_t *fs, const char *volfile) __THROW GFAPI_PUBLIC(glfs_set_volfile, 3.4.0); /** 动态配置volume @fs: glfs对象 @transport: 传输形式 "tcp", "rdma", "unix" 等 @host: master节点位置.形式可以为: - FQDN: storage01.company.com - ASCII : 192.168.22.1 - Socket:/var/run/glusterd.socket @port: glusterfs进行监听的TCP端口号。当使用socket传输时此参数不 需要 返回值 0 : Success. -1 : Failure. */ int glfs_set_volfile_server (glfs_t *fs, const char *transport, const char *host, int port) __THROW GFAPI_PUBLIC(glfs_set_volfile_server, 3.4.0); //配置失败后清除已经配置的环境 int glfs_unset_volfile_server (glfs_t fs, const char transport,const char *host, int port) ;
配置完后还需要设置log操作以及对glfs对象进行初始化
/* @logfile:日志文件 @loglevel:日志等级 */ int glfs_set_logging (glfs_t fs, const char logfile, int loglevel) ; //初始化glfs对象 int glfs_init (glfs_t *fs) ;
当初始化完成之后就可以访问glusterfs系统进行各种操作。Libgfapi提供了超过一百个库函数(详细请参考:https://github.com/gluster/glusterfs/blob/master/api/src/glfs.h),里面涵盖了打开、读/写等与标准POSIX C库函数功能及定义很类似的函数,也有设置组/用户ID、设置权限等针对glusterfs系统的函数。,下面参考网上的资料给出一个简单的C示例程序:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include "api/glfs.h" #include "api/glfs-handles.h" #include <string.h> #include <time.h> int main (int argc, char *argv[]) { //glfs_t为glfs对象 glfs_t *fs2 = NULL; int ret = 0; //文件描述指针 glfs_fd_t *fd = NULL; glfs_fd_t *fd2 = NULL; //读写缓存 char readbuf[32]; char writebuf[32]; //文件名 char*filename = "/filename2"; if (argc != 3) { printf ("Expect following args\n\t%s <volname> hostname>\n", argv[0]); return -1; } /* 初始化gluster环境 */
fs2 = glfs_new (argv[1]); if (!fs2) { fprintf (stderr, "glfs_new: returned NULL\n"); return 1; } //配置master节点 ret = glfs_set_volfile_server (fs2, "tcp", argv[2], 24007); //设置日志信息 ret = glfs_set_logging (fs2, "/dev/stderr", 1); //进行初始化 ret = glfs_init (fs2); //打印初始化信息 fprintf (stderr, "glfs_init: returned %d\n", ret); /* 进行libgfapi函数调用 */ fd = glfs_creat (fs2, filename, O_RDWR, 0644); fprintf (stderr, "%s: (%p) %s\n", filename, fd, strerror (errno)); //打开挂载目录下文件,准备写入 fd2 = glfs_open (fs2, filename, O_RDWR); fprintf (stderr, "%s: (%p) %s\n", filename, fd, strerror (errno)); sprintf (writebuf, "hi there\n"); ret = glfs_write (fd, writebuf, 32, 0); //glfs_lseek函数功能与POSIX C库函数相同 glfs_lseek (fd2, 0, SEEK_SET); //读取数据至读缓存 ret = glfs_read (fd2, readbuf, 32, 0); printf ("read %d, %s", ret, readbuf); //读写完成后关闭文件 glfs_close (fd); glfs_close (fd2); //Gluster环境释放,所有程序在完成各项操作后都必须执行的函数 glfs_fini (fs2); return ret; }
编译时需要指定头文件和库文件路径,并链接libgfapi.so动态库。
由于时间仓促,对其他glusterfs系统方面的函数并没有理解透彻,在本机上的调试还未成功,仍需进一步学习。