daemon: on app stop, wait its client to disappear

This commit is contained in:
Nedko Arnaudov 2010-05-13 03:18:23 +03:00
parent 76aba4487b
commit 18ba50dafb
7 changed files with 192 additions and 57 deletions

View File

@ -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.");

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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);