glusterfs 4.0.1 api 分析笔记1 glusterfs 4.0.1 rpc 分析笔记1

一般来说,我们写个客户端程序大概的样子是这样的:

 /* glfs_example.c */  

// gcc -o glfs_example glfs_example.c -L /usr/lib64/ -lgfapi -I /usr/include/glusterfs/
    #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    *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;  
        }  
        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 (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;  
    }  

 我们这里按照程序执行的思路,一句一句的解读程序的执行过程。

1、 fs2 = glfs_new (argv[1]);

/* glfs_new: 创建一个 'virtual mount' 对象

  这应该是调用的一个函数.

  在这个新建立的对象(glfs_t类型), 你需要设置一个 volfile path
  (glfs_set_volfile)或者一个 volfile server (glfs_set_volfile_server).

  这个对象还需要使用 glfs_init()初始化,然后才能调用其他的文件操作.

  @volname: 卷名. 用来标记服务器端的卷以及获取来的卷文件 (等效于 glusterfsd --volfile-id 命令). 
当使用 glfs_set_volfile() 函数时,这个 @volname 就没有作用了。
*/ glfs_t *glfs_new (const char *volname) __THROW GFAPI_PUBLIC(glfs_new, 3.4.0);

     1.1  这句内部定义如下:在(glfs.c中)pub_glfs_new

        mem_pools_init_early ();    // 初始化mem_pool对象。
        mem_pools_init_late ();

        fs = glfs_new_fs (volname);    // 初始化struct glfs *fs 内部各个锁和链表 670行
        ctx = glusterfs_ctx_new ();    // 18行,建立一个对象 ctx.c


        /* first globals init, for gf_mem_acct_enable_set () */
        ret = glusterfs_globals_init (ctx); // 定义于globals.c 中,内部调用 glusterfs_this_init ()
// 定义了一个全局对象 xlator_t global_xlator,并初始化 old_THIS = THIS; // 通过线程本地存储来保存当前的 xlator_t *old_THIS, 如果还没有,则建议几个新的指针来存储,并设置为之前的全局的 &global_xlator ret = glfs_init_global_ctx (); /* then ctx_defaults_init, for xlator_mem_acct_init(THIS) */ //ret = glusterfs_ctx_defaults_init (ctx);
// 前移句内部会调用这句。初始化ctx:建立内部的iobuf_pool,建event_pool, frame_mem_pool 等一系列的内部资源池 // 这个函数非常重要!!!里面涉及其他资源的建立,请参考相关部分的分析。 fs->ctx = ctx; fs->ctx->process_mode = GF_CLIENT_PROCESS; ret = glfs_set_logging (fs, "/dev/null", 0); fs->ctx->cmd_args.volfile_id = gf_strdup (volname);

 到这里,基本内存资源都已经初始化完毕了,event_pool初始化也表示epoll模型也初始化完毕了。

 

2、glfs_set_volfile_server (fs2, "tcp", argv[2], 24007); 

pub_glfs_set_volfile_server // 441行

初始化协议,

3、glfs_init (fs2);            这里开始内部结构的初始化了。

 

pub_glfs_init (struct glfs *fs) // 1507行
{
     int   ret = glfs_init_common (fs);               // create_master (fs)创建一个xlator_t;建议线程启动epoll;而glfs_volumes_init则是其中最重要的部分!!!
     if (ret == 0)
     {
	        ret = glfs_init_wait (fs);            // 之所以有这句,说明前一句里面是异步的初始化,有连接服务器和初始化动作,所以需要等待完成。
     }
     if (ret >= 0) 
     {
                ret = glfs_chdir (fs, "/");           // 既然这里已经切换到根目录了,说明之前的两句作用还是很大的!!!
      }
}

 

 所以我们继续分析 glfs_volumes_init 该函数 确定当服务器不在当前主机,则执行了glfs_mgmt_init

 相关部分请参考:glusterfs 4.0.1 rpc 分析笔记1

// glfs-mgmt.c中
int glfs_mgmt_init (struct glfs *fs)
{
	cmd_args_t		*cmd_args = NULL;
	struct rpc_clnt		*rpc = NULL;
	dict_t			*options = NULL;
	int			ret = -1;
	int			port = GF_DEFAULT_BASE_PORT;
	char			*host = NULL;
	glusterfs_ctx_t		*ctx = NULL;

	ctx = fs->ctx;

	rpc = rpc_clnt_new (options, THIS, THIS->name, 8);           // 建立一个rcp_clnt类型,这个类型封装了客户端的基本操作,
        // 这个函数内部,加载rpc_tranport,并动态加载了socket.so模块,

ret = rpc_clnt_register_notify (rpc, mgmt_rpc_notify, THIS); // rcp_clnt对象遇到事件回调此函数,
// 这个函数很重要,当连接成功后,将调用glfs_volfile_fetch 进行初始命令交互 ret = rpcclnt_cbk_program_register (rpc, &mgmt_cbk_prog, THIS); // 注册接收数据时候的回调函数 ctx->notify = glusterfs_mgmt_notify; ctx->mgmt = rpc; // 设置管理器为rcp_clnt对象 ret = rpc_clnt_start (rpc); // 然后这个对象工作,内部调用 rpc_transport_connect,其实是调用socket.so的connet() return ret; }

 

 

猜你喜欢

转载自www.cnblogs.com/robinfox/p/8922199.html