From bb7a63e2165d0ea7557e8098750125bb5c58f1de Mon Sep 17 00:00:00 2001 From: Nedko Arnaudov Date: Wed, 5 May 2010 01:09:42 +0300 Subject: [PATCH] daemon: handle start_app requests asynchronously --- daemon/app_supervisor.c | 58 ++++++++--------- daemon/app_supervisor.h | 4 ++ daemon/cmd.h | 2 + daemon/cmd_start_app.c | 137 ++++++++++++++++++++++++++++++++++++++++ wscript | 1 + 5 files changed, 170 insertions(+), 32 deletions(-) create mode 100644 daemon/cmd_start_app.c diff --git a/daemon/app_supervisor.c b/daemon/app_supervisor.c index cb024e9e..a717dd20 100644 --- a/daemon/app_supervisor.c +++ b/daemon/app_supervisor.c @@ -105,7 +105,7 @@ ladish_app_supervisor_create( return true; } -struct ladish_app * ladish_app_supervisor_find_app_by_id(struct ladish_app_supervisor * supervisor_ptr, uint64_t id) +struct ladish_app * ladish_app_supervisor_find_app_by_id_internal(struct ladish_app_supervisor * supervisor_ptr, uint64_t id) { struct list_head * node_ptr; struct ladish_app * app_ptr; @@ -193,6 +193,11 @@ ladish_app_handle ladish_app_supervisor_find_app_by_name(ladish_app_supervisor_h return NULL; } +ladish_app_handle ladish_app_supervisor_find_app_by_id(ladish_app_supervisor_handle supervisor_handle, uint64_t id) +{ + return (ladish_app_handle)ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id); +} + ladish_app_handle ladish_app_supervisor_add( ladish_app_supervisor_handle supervisor_handle, @@ -347,6 +352,8 @@ ladish_app_supervisor_enum( bool ladish_app_supervisor_run(ladish_app_supervisor_handle supervisor_handle, ladish_app_handle app_handle) { + app_ptr->zombie = false; + if (!loader_execute(supervisor_ptr->name, app_ptr->name, "/", app_ptr->terminal, app_ptr->commandline, &app_ptr->pid)) { return false; @@ -361,6 +368,16 @@ void ladish_app_supervisor_remove(ladish_app_supervisor_handle supervisor_handle remove_app_internal(supervisor_ptr, app_ptr); } +bool ladish_app_is_running(ladish_app_handle app_handle) +{ + return app_ptr->pid != 0; +} + +const char * ladish_app_get_name(ladish_app_handle app_handle) +{ + return app_ptr->name; +} + #undef app_ptr void ladish_app_supervisor_autorun(ladish_app_supervisor_handle supervisor_handle) @@ -386,8 +403,6 @@ void ladish_app_supervisor_autorun(ladish_app_supervisor_handle supervisor_handl log_error("Execution of '%s' failed", app_ptr->commandline); return; } - - emit_app_state_changed(supervisor_ptr, app_ptr); } } @@ -591,7 +606,6 @@ static void run_custom(struct dbus_method_call * call_ptr) static void start_app(struct dbus_method_call * call_ptr) { uint64_t id; - struct ladish_app * app_ptr; if (!dbus_message_get_args( call_ptr->message, @@ -604,30 +618,10 @@ static void start_app(struct dbus_method_call * call_ptr) return; } - app_ptr = ladish_app_supervisor_find_app_by_id(supervisor_ptr, id); - if (app_ptr == NULL) + if (ladish_command_start_app(call_ptr, ladish_studio_get_cmd_queue(), supervisor_ptr->opath, id)) { - lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id); - return; + method_return_new_void(call_ptr); } - - if (app_ptr->pid != 0) - { - lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App %s is already running", app_ptr->name); - return; - } - - app_ptr->zombie = false; - if (!ladish_app_supervisor_run((ladish_app_supervisor_handle)supervisor_ptr, (ladish_app_handle)app_ptr)) - { - lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Execution of '%s' failed", app_ptr->commandline); - return; - } - - emit_app_state_changed(supervisor_ptr, app_ptr); - log_info("%s pid is %lu", app_ptr->name, (unsigned long)app_ptr->pid); - - method_return_new_void(call_ptr); } static void stop_app(struct dbus_method_call * call_ptr) @@ -646,7 +640,7 @@ static void stop_app(struct dbus_method_call * call_ptr) return; } - app_ptr = ladish_app_supervisor_find_app_by_id(supervisor_ptr, id); + app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id); if (app_ptr == NULL) { lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id); @@ -680,7 +674,7 @@ static void kill_app(struct dbus_method_call * call_ptr) return; } - app_ptr = ladish_app_supervisor_find_app_by_id(supervisor_ptr, id); + app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id); if (app_ptr == NULL) { lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id); @@ -716,7 +710,7 @@ static void get_app_properties(struct dbus_method_call * call_ptr) return; } - app_ptr = ladish_app_supervisor_find_app_by_id(supervisor_ptr, id); + app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id); if (app_ptr == NULL) { lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id); @@ -780,7 +774,7 @@ static void set_app_properties(struct dbus_method_call * call_ptr) return; } - app_ptr = ladish_app_supervisor_find_app_by_id(supervisor_ptr, id); + app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id); if (app_ptr == NULL) { lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id); @@ -874,7 +868,7 @@ static void remove_app(struct dbus_method_call * call_ptr) return; } - app_ptr = ladish_app_supervisor_find_app_by_id(supervisor_ptr, id); + app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id); if (app_ptr == NULL) { lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id); @@ -911,7 +905,7 @@ static void is_app_running(struct dbus_method_call * call_ptr) return; } - app_ptr = ladish_app_supervisor_find_app_by_id(supervisor_ptr, id); + app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id); if (app_ptr == NULL) { lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id); diff --git a/daemon/app_supervisor.h b/daemon/app_supervisor.h index 9154046b..c595b3e4 100644 --- a/daemon/app_supervisor.h +++ b/daemon/app_supervisor.h @@ -84,9 +84,13 @@ ladish_app_supervisor_search_app( const char * ladish_app_supervisor_get_name(ladish_app_supervisor_handle supervisor_handle); unsigned int ladish_app_supervisor_get_running_app_count(ladish_app_supervisor_handle supervisor_handle); ladish_app_handle ladish_app_supervisor_find_app_by_name(ladish_app_supervisor_handle supervisor_handle, const char * name); +ladish_app_handle ladish_app_supervisor_find_app_by_id(ladish_app_supervisor_handle supervisor_handle, uint64_t id); const char * ladish_app_supervisor_get_opath(ladish_app_supervisor_handle supervisor_handle); bool ladish_app_supervisor_run(ladish_app_supervisor_handle supervisor_handle, ladish_app_handle app_handle); void ladish_app_supervisor_remove(ladish_app_supervisor_handle supervisor_handle, ladish_app_handle app_handle); +const char * ladish_app_get_commandline(ladish_app_handle app_handle); +bool ladish_app_is_running(ladish_app_handle app_handle); +const char * ladish_app_get_name(ladish_app_handle app_handle); extern const struct dbus_interface_descriptor g_iface_app_supervisor; diff --git a/daemon/cmd.h b/daemon/cmd.h index 5435348e..353aaa56 100644 --- a/daemon/cmd.h +++ b/daemon/cmd.h @@ -80,4 +80,6 @@ ladish_command_new_app( const char * name, uint8_t level); +bool ladish_command_start_app(void * call_ptr, struct ladish_cqueue * queue_ptr, const char * opath, uint64_t id); + #endif /* #ifndef CMD_H__28542C9B_7CB8_40F8_BBB6_DCE13CBB1E7F__INCLUDED */ diff --git a/daemon/cmd_start_app.c b/daemon/cmd_start_app.c new file mode 100644 index 00000000..5ae16a6a --- /dev/null +++ b/daemon/cmd_start_app.c @@ -0,0 +1,137 @@ +/* -*- Mode: C ; c-basic-offset: 2 -*- */ +/* + * LADI Session Handler (ladish) + * + * Copyright (C) 2010 Nedko Arnaudov + * + ************************************************************************** + * This file contains implementation of the "start app" command + ************************************************************************** + * + * LADI Session Handler is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LADI Session Handler is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LADI Session Handler. If not, see + * or write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "cmd.h" +#include "studio.h" +#include "../dbus/error.h" +#include "../proxies/notify_proxy.h" + +struct ladish_command_start_app +{ + struct ladish_command command; /* must be the first member */ + char * opath; + uint64_t id; +}; + +#define cmd_ptr ((struct ladish_command_start_app *)context) + +static bool run(void * context) +{ + ladish_app_supervisor_handle supervisor; + ladish_app_handle app; + + ASSERT(cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING); + + log_info("start_app command. opath='%s'", cmd_ptr->opath); + + if (!ladish_studio_is_started()) + { + log_error("cannot start app because studio is not started", cmd_ptr->opath); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot start app because studio is not started", NULL); + return false; + } + + supervisor = ladish_studio_find_app_supervisor(cmd_ptr->opath); + if (supervisor == NULL) + { + log_error("cannot find supervisor '%s' to start app", cmd_ptr->opath); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot start app because of internal error (unknown supervisor)", NULL); + return false; + } + + app = ladish_app_supervisor_find_app_by_id(supervisor, cmd_ptr->id); + if (app == NULL) + { + log_error("App with ID %"PRIu64" not found", cmd_ptr->id); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot start app because it is not found", NULL); + return false; + } + + if (ladish_app_is_running(app)) + { + log_error("App %s is already running", ladish_app_get_name(app)); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot start app because it is already running", NULL); + return false; + } + + if (!ladish_app_supervisor_run(supervisor, app)) + { + ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot start app (execution failed)", NULL); + return false; + } + + cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE; + return true; +} + +static void destructor(void * context) +{ + log_info("start_app command destructor"); + free(cmd_ptr->opath); +} + +#undef cmd_ptr + +bool ladish_command_start_app(void * call_ptr, struct ladish_cqueue * queue_ptr, const char * opath, uint64_t id) +{ + struct ladish_command_start_app * cmd_ptr; + char * opath_dup; + + opath_dup = strdup(opath); + if (opath_dup == NULL) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "strdup('%s') failed.", opath_dup); + goto fail; + } + + cmd_ptr = ladish_command_new(sizeof(struct ladish_command_start_app)); + if (cmd_ptr == NULL) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "ladish_command_new() failed."); + goto fail_free_opath; + } + + cmd_ptr->command.run = run; + cmd_ptr->command.destructor = destructor; + cmd_ptr->opath = opath_dup; + cmd_ptr->id = id; + + if (!ladish_cqueue_add_command(queue_ptr, &cmd_ptr->command)) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "ladish_cqueue_add_command() failed."); + goto fail_destroy_command; + } + + return true; + +fail_destroy_command: + free(cmd_ptr); +fail_free_opath: + free(opath_dup); +fail: + return false; +} diff --git a/wscript b/wscript index 0c849e71..3582c217 100644 --- a/wscript +++ b/wscript @@ -229,6 +229,7 @@ def build(bld): 'cmd_stop_studio.c', 'cmd_unload_studio.c', 'cmd_new_app.c', + 'cmd_start_app.c', 'cmd_exit.c', 'cqueue.c', 'app_supervisor.c',