功能简介
bgapi主要功能如下:
- 异步执行api命令, 异步, 从实现上面来说跟线程有关.
- 在刚调用的时候, 立即返回backgroup-uuid
- 在命令真正执行结束后, 会抛出一个事件, 事件中包含真正的返回结果.
代码文件
文件: mod_commands.c
函数: SWITCH_STANDARD_API(bgapi_function)
封装命令执行信息
因为需要异步执行, 所以必然有一个数据结构来封装待执行的命令信息, 传递给异步执行的线程.
此处的数据结构是:
struct bg_job {
char *cmd;
char *arg;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
switch_memory_pool_t *pool;
};
结构很简单, 包括命令、命令参数、后台任务uuid、线程池。
基本逻辑
SWITCH_STANDARD_API(bgapi_function)
{
struct bg_job *job;
switch_uuid_t uuid;
switch_memory_pool_t *pool;
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
if (!cmd) {
stream->write_function(stream, "-ERR Invalid syntax\n");
return SWITCH_STATUS_SUCCESS;
}
//申请线程池,存储bg_job, 便于传递给后面的异步线程
switch_core_new_memory_pool(&pool);
job = switch_core_alloc(pool, sizeof(*job));
//将命令拷贝到新pool里面
job->cmd = switch_core_strdup(pool, cmd);
job->pool = pool;
//创建uuid, 用于跟踪这个后台执行的任务
//调用者先收到这个任务uuid, 后续根据这个uuid,来过滤事件,获取真正的执行结果
switch_uuid_get(&uuid);
switch_uuid_format(job->uuid_str, &uuid);
//创建线程,用于异步执行任务
switch_threadattr_create(&thd_attr, job->pool);
switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
stream->write_function(stream, "+OK Job-UUID: %s\n", job->uuid_str);
//线程中异步执行的函数是bgapi_exec
switch_thread_create(&thread, thd_attr, bgapi_exec, job, job->pool);
return SWITCH_STATUS_SUCCESS;
}
上面代码的主要逻辑如下:
- 申请内存池, 用于保存异步任务信息
- 创建uuid,标识异步任务,并返回该uuid给调用者
- 创建线程,将异步任务和执行异步任务的函数传递过去
异步执行的逻辑也很简单:
使用下面的函数执行命令:
if ((status = switch_api_execute(job->cmd, arg, NULL, &stream)) == SWITCH_STATUS_SUCCESS) {
reply = stream.data;
} else {
freply = switch_mprintf("%s: Command not found!\n", job->cmd);
reply = freply;
}
通过BACKGROUND_JOB事件返回命令执行结果:
if (switch_event_create(&event, SWITCH_EVENT_BACKGROUND_JOB) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-UUID", job->uuid_str);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command", job->cmd);
if (arg) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command-Arg", arg);
}
switch_event_add_body(event, "%s", reply);
switch_event_fire(&event);
}