daemon: on app stop, wait its client to disappear
This commit is contained in:
parent
76aba4487b
commit
18ba50dafb
|
@ -29,6 +29,7 @@
|
|||
#include "studio.h"
|
||||
#include "../dbus/error.h"
|
||||
#include "../proxies/notify_proxy.h"
|
||||
#include "virtualizer.h"
|
||||
|
||||
struct ladish_command_change_app_state
|
||||
{
|
||||
|
@ -36,11 +37,15 @@ struct ladish_command_change_app_state
|
|||
char * opath;
|
||||
uint64_t id;
|
||||
unsigned int target_state;
|
||||
const char * target_state_description;
|
||||
bool (* run_target)(struct ladish_command_change_app_state *, ladish_app_supervisor_handle, ladish_app_handle);
|
||||
void (* initiate_stop)(ladish_app_supervisor_handle supervisor, ladish_app_handle app);
|
||||
};
|
||||
|
||||
static bool run_target_start(struct ladish_command_change_app_state * cmd_ptr, ladish_app_supervisor_handle supervisor, ladish_app_handle app)
|
||||
{
|
||||
ASSERT(cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING);
|
||||
ASSERT(cmd_ptr->initiate_stop == NULL);
|
||||
|
||||
if (!ladish_studio_is_started())
|
||||
{
|
||||
|
@ -68,49 +73,38 @@ static bool run_target_start(struct ladish_command_change_app_state * cmd_ptr, l
|
|||
|
||||
static bool run_target_stop(struct ladish_command_change_app_state * cmd_ptr, ladish_app_supervisor_handle supervisor, ladish_app_handle app)
|
||||
{
|
||||
if (!ladish_app_is_running(app))
|
||||
const char * app_name;
|
||||
|
||||
ASSERT(cmd_ptr->initiate_stop != NULL);
|
||||
|
||||
app_name = ladish_app_get_name(app);
|
||||
|
||||
if (ladish_app_is_running(app))
|
||||
{
|
||||
if (cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING)
|
||||
{
|
||||
log_info("App %s is already stopped (stop)", ladish_app_get_name(app));
|
||||
cmd_ptr->initiate_stop(supervisor, app);
|
||||
cmd_ptr->command.state = LADISH_COMMAND_STATE_WAITING;
|
||||
return true;
|
||||
}
|
||||
cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE;
|
||||
|
||||
ASSERT(cmd_ptr->command.state == LADISH_COMMAND_STATE_WAITING);
|
||||
log_info("Waiting '%s' process termination (%s)...", app_name, cmd_ptr->target_state_description);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ladish_virtualizer_is_hidden_app(ladish_studio_get_virtualizer(), app_name))
|
||||
{
|
||||
log_info("Waiting '%s' client disappear (%s)...", app_name, cmd_ptr->target_state_description);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING)
|
||||
{
|
||||
ladish_app_supervisor_stop_app(supervisor, app);
|
||||
cmd_ptr->command.state = LADISH_COMMAND_STATE_WAITING;
|
||||
return true;
|
||||
log_info("App %s is already stopped (%s)", app_name, cmd_ptr->target_state_description);
|
||||
}
|
||||
|
||||
log_info("Waiting '%s' process termination (stop)...", ladish_app_get_name(app));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool run_target_kill(struct ladish_command_change_app_state * cmd_ptr, ladish_app_supervisor_handle supervisor, ladish_app_handle app)
|
||||
{
|
||||
if (!ladish_app_is_running(app))
|
||||
{
|
||||
if (cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING)
|
||||
{
|
||||
log_info("App %s is already stopped (kill)", ladish_app_get_name(app));
|
||||
}
|
||||
cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING)
|
||||
{
|
||||
ladish_app_supervisor_kill_app(supervisor, app);
|
||||
cmd_ptr->command.state = LADISH_COMMAND_STATE_WAITING;
|
||||
return true;
|
||||
}
|
||||
|
||||
log_info("Waiting '%s' process termination(kill)...", ladish_app_get_name(app));
|
||||
|
||||
cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -120,37 +114,16 @@ static bool run(void * context)
|
|||
{
|
||||
ladish_app_supervisor_handle supervisor;
|
||||
ladish_app_handle app;
|
||||
const char * target_state_description;
|
||||
bool (* run_target)(struct ladish_command_change_app_state *, ladish_app_supervisor_handle, ladish_app_handle);
|
||||
|
||||
switch (cmd_ptr->target_state)
|
||||
{
|
||||
case LADISH_APP_STATE_STARTED:
|
||||
target_state_description = "start";
|
||||
run_target = run_target_start;
|
||||
break;
|
||||
case LADISH_APP_STATE_STOPPED:
|
||||
target_state_description = "stopped";
|
||||
run_target = run_target_stop;
|
||||
break;
|
||||
case LADISH_APP_STATE_KILL:
|
||||
target_state_description = "kill";
|
||||
run_target = run_target_kill;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NO_PASS;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING)
|
||||
{
|
||||
log_info("%s app command. opath='%s'", target_state_description, cmd_ptr->opath);
|
||||
log_info("%s app command. opath='%s'", cmd_ptr->target_state_description, cmd_ptr->opath);
|
||||
}
|
||||
|
||||
supervisor = ladish_studio_find_app_supervisor(cmd_ptr->opath);
|
||||
if (supervisor == NULL)
|
||||
{
|
||||
log_error("cannot find supervisor '%s' to %s app", cmd_ptr->opath, target_state_description);
|
||||
log_error("cannot find supervisor '%s' to %s app", cmd_ptr->opath, cmd_ptr->target_state_description);
|
||||
ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot change app state because of internal error (unknown supervisor)", NULL);
|
||||
return false;
|
||||
}
|
||||
|
@ -158,12 +131,12 @@ static bool run(void * context)
|
|||
app = ladish_app_supervisor_find_app_by_id(supervisor, cmd_ptr->id);
|
||||
if (app == NULL)
|
||||
{
|
||||
log_error("App with ID %"PRIu64" not found (%s)", cmd_ptr->id, target_state_description);
|
||||
log_error("App with ID %"PRIu64" not found (%s)", cmd_ptr->id, cmd_ptr->target_state_description);
|
||||
ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot change app state because it is not found", NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
return run_target(cmd_ptr, supervisor, app);
|
||||
return cmd_ptr->run_target(cmd_ptr, supervisor, app);
|
||||
}
|
||||
|
||||
static void destructor(void * context)
|
||||
|
@ -199,6 +172,29 @@ bool ladish_command_change_app_state(void * call_ptr, struct ladish_cqueue * que
|
|||
cmd_ptr->id = id;
|
||||
cmd_ptr->target_state = target_state;
|
||||
|
||||
switch (target_state)
|
||||
{
|
||||
case LADISH_APP_STATE_STARTED:
|
||||
cmd_ptr->target_state_description = "start";
|
||||
cmd_ptr->run_target = run_target_start;
|
||||
cmd_ptr->initiate_stop = NULL;
|
||||
break;
|
||||
case LADISH_APP_STATE_STOPPED:
|
||||
cmd_ptr->target_state_description = "stop";
|
||||
cmd_ptr->run_target = run_target_stop;
|
||||
cmd_ptr->initiate_stop = ladish_app_supervisor_stop_app;
|
||||
break;
|
||||
case LADISH_APP_STATE_KILL:
|
||||
cmd_ptr->target_state_description = "kill";
|
||||
cmd_ptr->run_target = run_target_stop;
|
||||
cmd_ptr->initiate_stop = ladish_app_supervisor_kill_app;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NO_PASS;
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Invalid target state (internal error).", opath);
|
||||
goto fail_destroy_command;
|
||||
}
|
||||
|
||||
if (!ladish_cqueue_add_command(queue_ptr, &cmd_ptr->command))
|
||||
{
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "ladish_cqueue_add_command() failed.");
|
||||
|
|
|
@ -1910,6 +1910,20 @@ bool ladish_graph_client_looks_empty(ladish_graph_handle graph_handle, ladish_cl
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ladish_graph_client_is_hidden(ladish_graph_handle graph_handle, ladish_client_handle client_handle)
|
||||
{
|
||||
struct ladish_graph_client * client_ptr;
|
||||
|
||||
client_ptr = ladish_graph_find_client(graph_ptr, client_handle);
|
||||
if (client_ptr != NULL)
|
||||
{
|
||||
return client_ptr->hidden;
|
||||
}
|
||||
|
||||
ASSERT_NO_PASS;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ladish_try_connect_hidden_connections(ladish_graph_handle graph_handle)
|
||||
{
|
||||
struct list_head * node_ptr;
|
||||
|
|
|
@ -148,6 +148,7 @@ const char * ladish_graph_get_client_name(ladish_graph_handle graph_handle, ladi
|
|||
const char * ladish_graph_get_port_name(ladish_graph_handle graph, ladish_port_handle port);
|
||||
bool ladish_graph_client_is_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle);
|
||||
bool ladish_graph_client_looks_empty(ladish_graph_handle graph_handle, ladish_client_handle client_handle);
|
||||
bool ladish_graph_client_is_hidden(ladish_graph_handle graph_handle, ladish_client_handle client_handle);
|
||||
bool ladish_graph_is_port_present(ladish_graph_handle graph_handle, ladish_port_handle port_handle);
|
||||
void ladish_graph_show_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle);
|
||||
void ladish_graph_hide_port(ladish_graph_handle graph_handle, ladish_port_handle port_handle);
|
||||
|
|
|
@ -649,6 +649,11 @@ struct ladish_cqueue * ladish_studio_get_cmd_queue(void)
|
|||
return &g_studio.cmd_queue;
|
||||
}
|
||||
|
||||
ladish_virtualizer_handle ladish_studio_get_virtualizer(void)
|
||||
{
|
||||
return g_studio.virtualizer;
|
||||
}
|
||||
|
||||
struct ladish_studio_app_supervisor_match_context
|
||||
{
|
||||
const char * opath;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "app_supervisor.h"
|
||||
#include "graph.h"
|
||||
#include "room.h"
|
||||
#include "virtualizer.h"
|
||||
|
||||
bool ladish_studio_init(void);
|
||||
void ladish_studio_uninit(void);
|
||||
|
@ -53,6 +54,7 @@ ladish_studio_iterate_virtual_graphs(
|
|||
void ladish_studio_stop_app_supervisors(void);
|
||||
ladish_app_supervisor_handle ladish_studio_find_app_supervisor(const char * opath);
|
||||
struct ladish_cqueue * ladish_studio_get_cmd_queue(void);
|
||||
ladish_virtualizer_handle ladish_studio_get_virtualizer(void);
|
||||
|
||||
void ladish_studio_emit_room_appeared(ladish_room_handle room);
|
||||
void ladish_studio_emit_room_disappeared(ladish_room_handle room);
|
||||
|
|
|
@ -1035,6 +1035,113 @@ ladish_virtualizer_get_our_clients_count(
|
|||
return virtualizer_ptr->our_clients_count;
|
||||
}
|
||||
|
||||
bool
|
||||
ladish_virtualizer_is_hidden_app(
|
||||
ladish_virtualizer_handle handle,
|
||||
const char * app_name)
|
||||
{
|
||||
ladish_client_handle jclient;
|
||||
ladish_graph_handle vgraph;
|
||||
uuid_t vclient_uuid;
|
||||
ladish_client_handle vclient;
|
||||
|
||||
//ladish_graph_dump(g_studio.jack_graph);
|
||||
|
||||
jclient = ladish_graph_find_client_by_name(virtualizer_ptr->jack_graph, app_name);
|
||||
if (jclient == NULL)
|
||||
{
|
||||
ASSERT_NO_PASS;
|
||||
return true;
|
||||
}
|
||||
|
||||
vgraph = ladish_client_get_vgraph(jclient);
|
||||
if (vgraph == NULL)
|
||||
{
|
||||
ASSERT_NO_PASS;
|
||||
return true;
|
||||
}
|
||||
|
||||
//ladish_graph_dump(vgraph);
|
||||
|
||||
if (!ladish_graph_client_looks_empty(virtualizer_ptr->jack_graph, jclient) ||
|
||||
!ladish_graph_client_is_hidden(virtualizer_ptr->jack_graph, jclient))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ladish_client_get_interlink(jclient, vclient_uuid))
|
||||
{
|
||||
log_error("jack client of app '%s' has no interlinked vgraph client", app_name);
|
||||
ASSERT_NO_PASS;
|
||||
return true;
|
||||
}
|
||||
|
||||
vclient = ladish_graph_find_client_by_uuid(vgraph, vclient_uuid);
|
||||
if (vclient == NULL)
|
||||
{
|
||||
ASSERT_NO_PASS;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ladish_graph_client_looks_empty(vgraph, vclient))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT(ladish_graph_client_is_hidden(vgraph, vclient)); /* vclients are automatically hidden when they start looking empty (on port disappear) */
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ladish_virtualizer_remove_app(
|
||||
ladish_virtualizer_handle handle,
|
||||
const char * app_name)
|
||||
{
|
||||
ladish_client_handle jclient;
|
||||
ladish_graph_handle vgraph;
|
||||
uuid_t vclient_uuid;
|
||||
ladish_client_handle vclient;
|
||||
|
||||
//ladish_graph_dump(g_studio.jack_graph);
|
||||
|
||||
jclient = ladish_graph_find_client_by_name(virtualizer_ptr->jack_graph, app_name);
|
||||
if (jclient == NULL)
|
||||
{
|
||||
ASSERT_NO_PASS;
|
||||
return;
|
||||
}
|
||||
|
||||
vgraph = ladish_client_get_vgraph(jclient);
|
||||
if (vgraph == NULL)
|
||||
{
|
||||
ASSERT_NO_PASS;
|
||||
return;
|
||||
}
|
||||
|
||||
//ladish_graph_dump(vgraph);
|
||||
|
||||
ladish_graph_remove_client(virtualizer_ptr->jack_graph, jclient);
|
||||
if (!ladish_client_get_interlink(jclient, vclient_uuid))
|
||||
{
|
||||
log_error("jack client of app '%s' has no interlinked vgraph client", app_name);
|
||||
ladish_graph_dump(g_studio.jack_graph);
|
||||
ladish_graph_dump(vgraph);
|
||||
ASSERT_NO_PASS;
|
||||
return;
|
||||
}
|
||||
|
||||
vclient = ladish_graph_find_client_by_uuid(vgraph, vclient_uuid);
|
||||
if (vclient == NULL)
|
||||
{
|
||||
ASSERT_NO_PASS;
|
||||
return;
|
||||
}
|
||||
|
||||
ladish_graph_remove_client(vgraph, vclient);
|
||||
ladish_graph_dump(g_studio.jack_graph);
|
||||
ladish_graph_dump(vgraph);
|
||||
}
|
||||
|
||||
void
|
||||
ladish_virtualizer_destroy(
|
||||
ladish_virtualizer_handle handle)
|
||||
|
|
|
@ -48,6 +48,16 @@ unsigned int
|
|||
ladish_virtualizer_get_our_clients_count(
|
||||
ladish_virtualizer_handle handle);
|
||||
|
||||
bool
|
||||
ladish_virtualizer_is_hidden_app(
|
||||
ladish_virtualizer_handle handle,
|
||||
const char * app_name);
|
||||
|
||||
void
|
||||
ladish_virtualizer_remove_app(
|
||||
ladish_virtualizer_handle handle,
|
||||
const char * app_name);
|
||||
|
||||
void
|
||||
ladish_virtualizer_destroy(
|
||||
ladish_virtualizer_handle handle);
|
||||
|
|
Loading…
Reference in New Issue