X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=afs.c;h=0c615747435657b65ec5302192561fd902c84348;hp=0b2a4765b16f82fbde4674ac230bda4d2b5f9e18;hb=134e02f7e90d37a3056198d8ba374e0271415d15;hpb=79bfc7a2a6577000c405be6344ba91ec3f8745e9 diff --git a/afs.c b/afs.c index 0b2a4765..0c615747 100644 --- a/afs.c +++ b/afs.c @@ -166,13 +166,8 @@ static int dispatch_result(int result_shmid, callback_result_handler *handler, } result.size = cr->result_size; result.data = result_shm + sizeof(*cr); - if (result.size) { - assert(handler); - ret = handler(&result, cr->band, private_result_data); - if (ret < 0) - PARA_NOTICE_LOG("result handler error: %s\n", - para_strerror(-ret)); - } + assert(handler); + ret = handler(&result, cr->band, private_result_data); ret2 = shm_detach(result_shm); if (ret2 < 0) { PARA_ERROR_LOG("detach failed: %s\n", para_strerror(-ret2)); @@ -261,12 +256,10 @@ int send_callback_request(callback_function *f, struct osl_object *query, ret = *(int *) buf; assert(ret > 0); result_shmid = ret; - if (!dispatch_error) { - ret = dispatch_result(result_shmid, result_handler, - private_result_data); - if (ret < 0) - dispatch_error = 1; - } + ret = dispatch_result(result_shmid, result_handler, + private_result_data); + if (ret < 0 && dispatch_error >= 0) + dispatch_error = ret; ret = shm_destroy(result_shmid); if (ret < 0) PARA_CRIT_LOG("destroy result failed: %s\n", @@ -278,8 +271,11 @@ out: PARA_CRIT_LOG("shm destroy error\n"); if (fd >= 0) close(fd); -// PARA_DEBUG_LOG("callback_ret: %d\n", ret); - return ret < 0? ret : num_dispatched; + if (dispatch_error < 0) + return dispatch_error; + if (ret < 0) + return ret; + return num_dispatched; } /** @@ -505,6 +501,7 @@ static int activate_mood_or_playlist(char *arg, int *num_admissible) enum play_mode mode; int ret; + PARA_INFO_LOG("new playlist: %s\n", arg); if (!arg) { ret = change_current_mood(NULL); /* always successful */ mode = PLAY_MODE_MOOD; @@ -559,9 +556,22 @@ int afs_cb_result_handler(struct osl_object *result, uint8_t band, struct command_context *cc = private; assert(cc); - if (!result->size) - return 1; - return send_sb(&cc->scc, result->data, result->size, band, true); + switch (band) { + case SBD_OUTPUT: + case SBD_DEBUG_LOG: + case SBD_INFO_LOG: + case SBD_NOTICE_LOG: + case SBD_WARNING_LOG: + case SBD_ERROR_LOG: + case SBD_CRIT_LOG: + case SBD_EMERG_LOG: + assert(result->size > 0); + return send_sb(&cc->scc, result->data, result->size, band, true); + case SBD_AFS_CB_FAILURE: + return *(int *)(result->data); + default: + return -E_BAD_BAND; + } } void flush_and_free_pb(struct para_buffer *pb) @@ -578,7 +588,7 @@ void flush_and_free_pb(struct para_buffer *pb) free(pb->buf); } -static void com_select_callback(int fd, const struct osl_object *query) +static int com_select_callback(int fd, const struct osl_object *query) { struct para_buffer pb = { .max_size = shm_get_shmmax(), @@ -593,30 +603,32 @@ static void com_select_callback(int fd, const struct osl_object *query) ret = clear_score_table(); if (ret < 0) { - para_printf(&pb, "%s\n", para_strerror(-ret)); - goto out; + para_printf(&pb, "could not clear score table: %s\n", + para_strerror(-ret)); + return ret; } if (current_play_mode == PLAY_MODE_MOOD) close_current_mood(); else playlist_close(); ret = activate_mood_or_playlist(arg, &num_admissible); - if (ret < 0) { - para_printf(&pb, "%s\nswitching back to %s\n", - para_strerror(-ret), current_mop? - current_mop : "dummy"); - ret = activate_mood_or_playlist(current_mop, &num_admissible); - if (ret < 0) { - para_printf(&pb, "failed (%s), switching to dummy\n", - para_strerror(-ret)); - activate_mood_or_playlist(NULL, &num_admissible); - } - } else - para_printf(&pb, "activated %s (%d admissible files)\n", - current_mop? current_mop : "dummy mood", - num_admissible); + if (ret >= 0) + goto out; + para_printf(&pb, "could not activate %s: %s\n" + "switching back to %s\n", + arg, para_strerror(-ret), current_mop? current_mop : "dummy"); + /* ignore subsequent errors (but log them) */ + ret = activate_mood_or_playlist(current_mop, &num_admissible); + if (ret >= 0) + goto out; + para_printf(&pb, "could not activate %s: %s\nswitching to dummy\n", + current_mop, para_strerror(-ret)); + activate_mood_or_playlist(NULL, &num_admissible); out: + para_printf(&pb, "activated %s (%d admissible files)\n", + current_mop? current_mop : "dummy mood", num_admissible); flush_and_free_pb(&pb); + return ret; } int com_select(struct command_context *cc) @@ -807,8 +819,8 @@ int pass_buffer_as_shm(int fd, uint8_t band, const char *buf, size_t size) void *shm; struct callback_result *cr; - if (!buf || !size) - return 0; + if (size == 0) + assert(band != SBD_OUTPUT); ret = shm_new(size + sizeof(*cr)); if (ret < 0) return ret; @@ -819,7 +831,8 @@ int pass_buffer_as_shm(int fd, uint8_t band, const char *buf, size_t size) cr = shm; cr->result_size = size; cr->band = band; - memcpy(shm + sizeof(*cr), buf, size); + if (size > 0) + memcpy(shm + sizeof(*cr), buf, size); ret = shm_detach(shm); if (ret < 0) goto err; @@ -837,7 +850,7 @@ static int call_callback(int fd, int query_shmid) void *query_shm; struct callback_query *cq; struct osl_object query; - int ret; + int ret, ret2; ret = shm_attach(query_shmid, ATTACH_RW, &query_shm); if (ret < 0) @@ -845,8 +858,23 @@ static int call_callback(int fd, int query_shmid) cq = query_shm; query.data = (char *)query_shm + sizeof(*cq); query.size = cq->query_size; - cq->handler(fd, &query); - return shm_detach(query_shm); + ret = cq->handler(fd, &query); + ret2 = shm_detach(query_shm); + if (ret2 < 0) { + if (ret < 0) /* ignore (but log) detach error */ + PARA_ERROR_LOG("could not detach sma: %s\n", + para_strerror(-ret2)); + else + ret = ret2; + } + if (ret < 0) { + ret2 = pass_buffer_as_shm(fd, SBD_AFS_CB_FAILURE, + (const char *)&ret, sizeof(ret)); + if (ret2 < 0) + PARA_ERROR_LOG("could not pass cb failure packet: %s\n", + para_strerror(-ret)); + } + return ret; } static int execute_server_command(fd_set *rfds) @@ -1005,7 +1033,7 @@ out: exit(EXIT_FAILURE); } -static void create_tables_callback(int fd, const struct osl_object *query) +static int com_init_callback(int fd, const struct osl_object *query) { uint32_t table_mask = *(uint32_t *)query->data; int i, ret; @@ -1026,15 +1054,18 @@ static void create_tables_callback(int fd, const struct osl_object *query) if (!t->create) continue; ret = t->create(database_dir); - if (ret < 0) + if (ret < 0) { + para_printf(&pb, "cannot create table %s\n", t->name); goto out; + } para_printf(&pb, "successfully created %s table\n", t->name); } ret = open_afs_tables(); -out: if (ret < 0) - para_printf(&pb, "%s\n", para_strerror(-ret)); + para_printf(&pb, "cannot open afs tables\n"); +out: flush_and_free_pb(&pb); + return ret; } int com_init(struct command_context *cc) @@ -1062,7 +1093,7 @@ int com_init(struct command_context *cc) return -E_BAD_TABLE_NAME; } } - return send_callback_request(create_tables_callback, &query, + return send_callback_request(com_init_callback, &query, afs_cb_result_handler, cc); }