LVM源码分析2-libdaemon
2019独角兽企业重金招聘Python工程师标准>>>
LVM的libdaemon库实现了守护进程与命令工具之间使用UNIX本地套接字进行CS通信的基础模型。
报文
配置树结构
$ cat libdm/libdevmapper.h
...typedef enum {DM_CFG_INT,DM_CFG_FLOAT,DM_CFG_STRING,DM_CFG_EMPTY_ARRAY
} dm_config_value_type_t;struct dm_config_value {dm_config_value_type_t type;union {int64_t i;float f;double d; /* Unused. */const char *str;} v;struct dm_config_value *next; /* For arrays */uint32_t format_flags;
};struct dm_config_node {const char *key;struct dm_config_node *parent, *sib, *child;struct dm_config_value *v;int id;
};struct dm_config_tree {struct dm_config_node *root;struct dm_config_tree *cascade;struct dm_pool *mem;void *custom;
};...
请求和响应报文
服务端:
$ cat libdaemon/server/daemon-server.h
...typedef struct {struct dm_config_tree *cft;struct buffer buffer;
} request;typedef struct {int error;struct dm_config_tree *cft;struct buffer buffer;
} response;...
客户端:
$ cat libdaemon/client/daemon-client.h
...typedef struct {struct buffer buffer;/** The request looks like this:* request = "id"* arg_foo = "something"* arg_bar = 3* arg_wibble {* something_special = "here"* amount = 75* knobs = [ "twiddle", "tweak" ]* }*/struct dm_config_tree *cft;
} daemon_request;typedef struct {int error; /* 0 for success */struct buffer buffer;struct dm_config_tree *cft; /* parsed reply, if available */
} daemon_reply;...
服务端
守护服务状态
$ cat libdaemon/server/daemon-server.h
...typedef struct daemon_state {/** The maximal stack size for individual daemon threads. This is* essential for daemons that need to be locked into memory, since* pthread's default is 10M per thread.*/int thread_stack_size;/* Flags & attributes affecting the behaviour of the daemon. */unsigned avoid_oom:1;unsigned foreground:1;const char *name;const char *pidfile;const char *socket_path;const char *protocol;int protocol_version;handle_request handler;int (*daemon_init)(struct daemon_state *st);int (*daemon_fini)(struct daemon_state *st);int (*daemon_main)(struct daemon_state *st);/* Global runtime info maintained by the framework. */int socket_fd;log_state *log;struct thread_state *threads;/* suport for shutdown on idle */daemon_idle *idle;void *private; /* the global daemon state */
} daemon_state;...
守护服务启动、接管和停止
$ cat libdaemon/server/daemon-server.h
.../** Start serving the requests. This does all the daemonisation, socket setup* work and so on. This function takes over the process, and upon failure, it* will terminate execution. It may be called at most once.*/
void daemon_start(daemon_state s);/** Take over from an already running daemon. This function handles connecting* to the running daemon and telling it we are going to take over. The takeover* request may be customised by passing in a non-NULL request.** The takeover sequence: the old daemon stops accepting new clients, then it* waits until all current client connections are closed. When that happens, it* serializes its current state and sends that as a reply, which is then* returned by this function (therefore, this function won't return until the* previous instance has shut down).** The daemon, after calling daemon_takeover is expected to set up its* daemon_state using the reply from this function and call daemon_start as* usual.*/
daemon_reply daemon_takeover(daemon_info i, daemon_request r);/* Call this to request a clean shutdown of the daemon. Async safe. */
void daemon_stop(void);...
客户端句柄
每个客户端连接时都会创建一个新的线程和客户端句柄来处理与之对应的请求。
$ cat libdaemon/server/daemon-server.h
...typedef struct {int socket_fd; /* the fd we use to talk to the client */pthread_t thread_id;char *read_buf;void *private; /* this holds per-client state */
} client_handle;...
守护服务回调函数
$ cat libdaemon/server/daemon-server.h
.../** The callback. Called once per request issued, in the respective client's* thread. It is presented by a parsed request (in the form of a config tree).* The output is a new config tree that is serialised and sent back to the* client. The client blocks until the request processing is done and reply is* sent.*/
typedef response (*handle_request)(struct daemon_state s, client_handle h, request r);...
响应请求
$ cat libdaemon/server/daemon-server.h
.../** Craft a simple reply, without the need to construct a config_tree. See* daemon_send_simple in daemon-client.h for the description of the parameters.*/
response daemon_reply_simple(const char *id, ...);static inline int daemon_request_int(request r, const char *path, int def) {if (!r.cft)return def;return dm_config_find_int(r.cft->root, path, def);
}static inline const char *daemon_request_str(request r, const char *path, const char *def) {if (!r.cft)return def;return dm_config_find_str(r.cft->root, path, def);
}...
客户端
守护服务句柄与信息
$ cat libdaemon/client/daemon-client.h
...typedef struct {int socket_fd; /* the fd we use to talk to the daemon */const char *protocol;int protocol_version; /* version of the protocol the daemon uses */int error;
} daemon_handle;typedef struct {const char *path; /* the binary of the daemon */const char *socket; /* path to the comms socket */unsigned autostart:1; /* start the daemon if not running? *//** If the following are not NULL/0, an attempt to talk to a daemon which* uses a different protocol or version will fail.*/const char *protocol;int protocol_version;
} daemon_info;...
打开和关闭与守护服务的连接
$ cat libdaemon/client/daemon-client.h
.../** Open the communication channel to the daemon. If the daemon is not running,* it may be autostarted based on the binary path provided in the info (this* will only happen if autostart is set to true). If the call fails for any* reason, daemon_handle_valid(h) for the response will return false. Otherwise,* the connection is good to start serving requests.*/
daemon_handle daemon_open(daemon_info i);
.../* Shut down the communication to the daemon. Compulsory. */
void daemon_close(daemon_handle h);...
构造请求
辅助函数:
$ cat libdaemon/client/config-util.h
...struct buffer {int allocated;int used;char *mem;
};int buffer_append_vf(struct buffer *buf, va_list ap);
int buffer_append_f(struct buffer *buf, ...);
int buffer_append(struct buffer *buf, const char *string);
void buffer_init(struct buffer *buf);
void buffer_destroy(struct buffer *buf);
int buffer_realloc(struct buffer *buf, int required);int buffer_line(const char *line, void *baton);int set_flag(struct dm_config_tree *cft, struct dm_config_node *parent,const char *field, const char *flag, int want);void chain_node(struct dm_config_node *cn,struct dm_config_node *parent,struct dm_config_node *pre_sib);struct dm_config_node *make_config_node(struct dm_config_tree *cft,const char *key,struct dm_config_node *parent,struct dm_config_node *pre_sib);int compare_value(struct dm_config_value *a, struct dm_config_value *b);
int compare_config(struct dm_config_node *a, struct dm_config_node *b);struct dm_config_node *make_text_node(struct dm_config_tree *cft,const char *key,const char *value,struct dm_config_node *parent,struct dm_config_node *pre_sib);struct dm_config_node *make_int_node(struct dm_config_tree *cft,const char *key,int64_t value,struct dm_config_node *parent,struct dm_config_node *pre_sib);struct dm_config_node *config_make_nodes_v(struct dm_config_tree *cft,struct dm_config_node *parent,struct dm_config_node *pre_sib,va_list ap);
struct dm_config_node *config_make_nodes(struct dm_config_tree *cft,struct dm_config_node *parent,struct dm_config_node *pre_sib,...);...
构建及销毁请求和响应数据:
$ cat libdaemon/client/daemon-client.h
...daemon_request daemon_request_make(const char *id);
int daemon_request_extend(daemon_request r, ...);
int daemon_request_extend_v(daemon_request r, va_list ap);
void daemon_request_destroy(daemon_request r);void daemon_reply_destroy(daemon_reply r);...
发送请求和等待响应
辅助函数:
$ cat libdaemon/client/daemon-io.h
...int buffer_read(int fd, struct buffer *buffer);
int buffer_write(int fd, const struct buffer *buffer);...
发送请求并等待响应:
$ cat libdaemon/client/daemon-client.h
.../** Send a request to the daemon, waiting for the reply. All communication with* the daemon is synchronous. The function handles the IO details and parses the* response, handling common error conditions. See "daemon_reply" for details.** In case the request contains a non-NULL buffer pointer, this buffer is sent* *verbatim* to the server. In this case, the cft pointer may be NULL (but will* be ignored even if non-NULL). If the buffer is NULL, the cft is required to* be a valid pointer, and is used to build up the request.*/
daemon_reply daemon_send(daemon_handle h, daemon_request r);/** A simple interface to daemon_send. This function just takes the command id* and possibly a list of parameters (of the form "name = %?", "value"). The* type (string, integer) of the value is indicated by a character substituted* for ? in %?: d for integer, s for string.*/
daemon_reply daemon_send_simple(daemon_handle h, const char *id, ...);
daemon_reply daemon_send_simple_v(daemon_handle h, const char *id, va_list ap);...
解析响应
$ cat libdaemon/client/daemon-client.h
...static inline int64_t daemon_reply_int(daemon_reply r, const char *path, int64_t def)
{return dm_config_find_int64(r.cft->root, path, def);
}static inline const char *daemon_reply_str(daemon_reply r, const char *path, const char *def)
{return dm_config_find_str_allow_empty(r.cft->root, path, def);
}...
转载于:https://my.oschina.net/LastRitter/blog/1532169
LVM源码分析2-libdaemon相关推荐
- LVM源码分析1-概览
获取CentOS LVM源码 $ which lvmetad /usr/sbin/lvmetad $ rpm -qf /usr/sbin/lvmetad lvm2-2.02.130-5.el7_2.5 ...
- LVM源码分析3-lvextend
2019独角兽企业重金招聘Python工程师标准>>> 命令参数定义: $ cat tools/command.h ...xx(lvextend,"Add space to ...
- openstack冷迁移/Resize源码分析(二)
接上一篇 openstack冷迁移/Resize源码分析(一) 执行冷迁移/Resize /nova_queens/nova/compute/manager.py @wrap_exception()@ ...
- Lua源码分析 - 虚拟机篇 - 语义解析之Opcode执行(18)
目录 一.虚拟机篇 - 指令执行状态机luaV_execute 二.虚拟机篇 - 状态机的具体实现原理 一.虚拟机篇 - 指令执行状态机luaV_execute 在<Lua源码分析 - 主流程篇 ...
- Openstack liberty 云主机迁移源码分析之在线迁移3
这是在线迁移 源码分析的第三篇,Openstack liberty 云主机迁移源码分析之在线迁移2中分析了prepare准备阶段nova-compute的处理过程,本文将会分析execute执行阶段的 ...
- 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析
目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...
- SpringBoot-web开发(四): SpringMVC的拓展、接管(源码分析)
[SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...
- SpringBoot-web开发(二): 页面和图标定制(源码分析)
[SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) 目录 一.首页 1. 源码分析 2. 访问首页测试 二.动态页面 1. 动态资源目录t ...
- SpringBoot-web开发(一): 静态资源的导入(源码分析)
目录 方式一:通过WebJars 1. 什么是webjars? 2. webjars的使用 3. webjars结构 4. 解析源码 5. 测试访问 方式二:放入静态资源目录 1. 源码分析 2. 测 ...
最新文章
- 层化(stratification)的方法
- updateStateByKey--word count
- 成功解决pml.Simple derived_col_names[int(obj[‘split_feature‘])],\ IndexError: list index out of range
- 【转】C++调用Matlab的.m文件
- 异步复位同步释放_简谈同步复位和异步复位
- wingdows安装psutil_python 第一步
- 自定义权限 android,如何在Android中使用自定义权限?
- 【linux】学习6
- java 柯里化_函数式编程(Java描述)——Java中的函数及其柯里化
- FireFox下表单无法刷新重置问题的分析与解决(转)
- 【TWVRP】基于matalb粒子群算法求解带时间窗的车辆路径规划问题【含Matlab源码 1272期】
- ibm x3850装oracle,Oracle数据库服务器:x3850 X5
- python实现坐标求取_根据相机位姿求指定点的世界坐标及其python实现
- C++ 调用Asprise OCR识别图片中的文字
- 优麒麟搜狗输入法简繁切换
- 射频工程师——中兴笔试题
- 设计模式之禅【组合模式】
- 2021年服创国赛参赛小结
- 技术小黑屋投稿开放了
- 公众号商城怎么做_分享超市小程序商城开发制作介绍
热门文章
- 猴子选大王 (20 分)
- 6-8 先序输出叶结点 (15 分)
- linux文件内上下移动,Linux中有多个查看文件的命令,如果希望在查看文件内容过程中用光标可以上下移动来查看文件内容,则符合要求的那一个命令是( )。...
- 使用 TRESTClient 與 TRESTRequest 作為 HTTP Client 之二 (POST 檔案)
- 如何定义 Java 中的方法
- 软件工程趣盒软件设计
- 3-JAVA中的JSON操作
- ThreadLocal 在web环境下使用的边界问题
- 解决DesignMode不能正确反应是否处于设计模式的问题
- Python中几个操作列表的内置函数filter(),map(),reduce(),lambda