X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=afs.c;h=04eed5503d18cb6d3b6e4d0cb127f98637d36b5d;hp=cea8f2707491f00bab0f457a3463fd4762147a21;hb=HEAD;hpb=9055c71be97f1095dcdbd83da305b600f204f763 diff --git a/afs.c b/afs.c index cea8f270..445d5871 100644 --- a/afs.c +++ b/afs.c @@ -437,18 +437,18 @@ static int activate_mood_or_playlist(const char *arg, struct para_buffer *pb) int ret; char *msg; - if (!arg) { - ret = mood_load(NULL, &msg); + if (!arg) { /* load dummy mood */ + ret = mood_load(NULL, NULL, &msg); mode = PLAY_MODE_MOOD; } else if (!strncmp(arg, "p/", 2)) { - ret = playlist_load(arg + 2, &msg); + ret = playlist_load(arg + 2, NULL, &msg); mode = PLAY_MODE_PLAYLIST; } else if (!strncmp(arg, "m/", 2)) { - ret = mood_load(arg + 2, &msg); + ret = mood_load(arg + 2, NULL, &msg); mode = PLAY_MODE_MOOD; } else { ret = -ERRNO_TO_PARA_ERROR(EINVAL); - msg = make_message("%s: parse error", arg); + msg = make_message("%s: parse error\n", arg); } if (pb) para_printf(pb, "%s", msg); @@ -525,59 +525,12 @@ static void flush_and_free_pb(struct para_buffer *pb) free(pb->buf); } -static int com_select_callback(struct afs_callback_arg *aca) -{ - const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SELECT); - const char *arg; - int ret; - - ret = lls_deserialize_parse_result(aca->query.data, cmd, &aca->lpr); - assert(ret >= 0); - arg = lls_input(0, aca->lpr); - score_clear(); - if (current_play_mode == PLAY_MODE_MOOD) - mood_unload(); - else - playlist_unload(); - ret = activate_mood_or_playlist(arg, &aca->pbout); - if (ret >= 0) - goto free_lpr; - /* ignore subsequent errors (but log them) */ - if (current_mop && strcmp(current_mop, arg) != 0) { - int ret2; - para_printf(&aca->pbout, "switching back to %s\n", current_mop); - ret2 = activate_mood_or_playlist(current_mop, &aca->pbout); - if (ret2 >= 0) - goto free_lpr; - para_printf(&aca->pbout, "could not reactivate %s: %s\n", - current_mop, para_strerror(-ret2)); - } - activate_mood_or_playlist(NULL, &aca->pbout); -free_lpr: - lls_free_parse_result(aca->lpr, cmd); - return ret; -} - -static int com_select(struct command_context *cc, struct lls_parse_result *lpr) -{ - const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SELECT); - char *errctx; - int ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx)); - - if (ret < 0) { - send_errctx(cc, errctx); - return ret; - } - return send_lls_callback_request(com_select_callback, cmd, lpr, cc); -} -EXPORT_SERVER_CMD_HANDLER(select); - static void init_admissible_files(const char *arg) { int ret = activate_mood_or_playlist(arg, NULL); if (ret < 0) { - PARA_WARNING_LOG("could not activate %s: %s\n", arg, - para_strerror(-ret)); + PARA_WARNING_LOG("could not activate %s: %s\n", arg? + arg : "dummy", para_strerror(-ret)); if (arg) activate_mood_or_playlist(NULL, NULL); } @@ -627,17 +580,6 @@ static void get_database_dir(void) PARA_INFO_LOG("afs_database dir %s\n", database_dir); } -static int make_database_dir(void) -{ - int ret; - - get_database_dir(); - ret = para_mkdir(database_dir, 0777); - if (ret >= 0 || ret == -ERRNO_TO_PARA_ERROR(EEXIST)) - return 1; - return ret; -} - static int open_afs_tables(void) { int i, ret; @@ -775,6 +717,43 @@ err: return ret; } +/** + * Format and send an error message to the command handler. + * + * To pass an error message from the callback of an afs command to the client, + * this function should be called. It formats the message into a buffer which + * is passed as a shared memory area to the command handler from where it + * propagates to the client. + * + * The message will be tagged with the ERROR_LOG sideband designator so that + * the client writes it to its stderr stream rather than to stdout as with + * aca->pbout. In analogy to the default Unix semantics of stderr, the message + * is sent without buffering. + * + * If sending the error message fails, an error is logged on the server side, + * but no other action is taken. + * + * \param aca Used to obtain the fd to send the shmid to. + * \param fmt Usual format string. + */ +__printf_2_3 void afs_error(const struct afs_callback_arg *aca, + const char *fmt,...) +{ + va_list argp; + char *msg; + unsigned n; + int ret; + + va_start(argp, fmt); + n = xvasprintf(&msg, fmt, argp); + va_end(argp); + ret = pass_buffer_as_shm(aca->fd, SBD_ERROR_LOG, msg, n + 1); + if (ret < 0) + PARA_ERROR_LOG("Could not send %s: %s\n", msg, + para_strerror(-ret)); + free(msg); +} + static int call_callback(int fd, int query_shmid) { void *query_shm; @@ -972,7 +951,8 @@ __noreturn void afs_init(int socket_fd) } ret = schedule(&s); sched_shutdown(&s); - mood_unload(); + mood_unload(NULL); + playlist_unload(NULL); out_close: close_afs_tables(); out: @@ -985,6 +965,57 @@ out: exit(EXIT_FAILURE); } +static int com_select_callback(struct afs_callback_arg *aca) +{ + const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SELECT); + const char *arg; + int ret; + struct para_buffer *pbout; + + ret = lls_deserialize_parse_result(aca->query.data, cmd, &aca->lpr); + assert(ret >= 0); + arg = lls_input(0, aca->lpr); + pbout = SERVER_CMD_OPT_GIVEN(SELECT, VERBOSE, aca->lpr)? + &aca->pbout : NULL; + score_clear(); + if (current_play_mode == PLAY_MODE_MOOD) + mood_unload(NULL); + else + playlist_unload(NULL); + ret = activate_mood_or_playlist(arg, pbout); + if (ret >= 0) + goto free_lpr; + /* ignore subsequent errors (but log them) */ + if (current_mop && strcmp(current_mop, arg) != 0) { + int ret2; + afs_error(aca, "switching back to %s\n", current_mop); + ret2 = activate_mood_or_playlist(current_mop, pbout); + if (ret2 >= 0) + goto free_lpr; + afs_error(aca, "could not reactivate %s: %s\n", current_mop, + para_strerror(-ret2)); + } + activate_mood_or_playlist(NULL, pbout); +free_lpr: + lls_free_parse_result(aca->lpr, cmd); + return ret; +} + +static int com_select(struct command_context *cc, struct lls_parse_result *lpr) +{ + const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SELECT); + char *errctx; + int ret = lls(lls_check_arg_count(lpr, 1, 1, &errctx)); + + if (ret < 0) { + send_errctx(cc, errctx); + return ret; + } + ret = send_lls_callback_request(com_select_callback, cmd, lpr, cc); + return ret == osl(-E_OSL_RB_KEY_NOT_FOUND)? -E_BAD_MOP : ret; +} +EXPORT_SERVER_CMD_HANDLER(select); + static int com_init_callback(struct afs_callback_arg *aca) { uint32_t table_mask = *(uint32_t *)aca->query.data; @@ -1001,8 +1032,7 @@ static int com_init_callback(struct afs_callback_arg *aca) continue; ret = t->ops->create(database_dir); if (ret < 0) { - para_printf(&aca->pbout, "cannot create table %s\n", - t->name); + afs_error(aca, "cannot create table %s\n", t->name); goto out; } para_printf(&aca->pbout, "successfully created %s table\n", @@ -1010,7 +1040,7 @@ static int com_init_callback(struct afs_callback_arg *aca) } ret = open_afs_tables(); if (ret < 0) - para_printf(&aca->pbout, "cannot open afs tables: %s\n", + afs_error(aca, "cannot open afs tables: %s\n", para_strerror(-ret)); out: return ret; @@ -1024,7 +1054,8 @@ static int com_init(struct command_context *cc, struct lls_parse_result *lpr) .size = sizeof(table_mask)}; unsigned num_inputs = lls_num_inputs(lpr); - ret = make_database_dir(); + get_database_dir(); + ret = para_mkdir(database_dir); if (ret < 0) return ret; if (num_inputs > 0) {