}
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));
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",
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;
}
/**
name = (char *)name_obj.data;
if ((!name || !*name) && (pmd->pm_flags & PM_SKIP_EMPTY_NAME))
return 1;
- if (!pmd->patterns.size && (pmd->pm_flags & PM_NO_PATTERN_MATCHES_EVERYTHING))
+ if (pmd->patterns.size == 0 &&
+ (pmd->pm_flags & PM_NO_PATTERN_MATCHES_EVERYTHING)) {
+ pmd->num_matches++;
return pmd->action(pmd->table, row, name, pmd->data);
+ }
for (p = pattern_txt; p < pattern_txt + pmd->patterns.size;
p += strlen(p) + 1) {
ret = fnmatch(p, name, pmd->fnmatch_flags);
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;
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)
+{
+ int ret;
+ struct afs_max_size_handler_data *amshd = pb->private_data;
+
+ if (pb->buf && pb->size > 0) {
+ ret = pass_buffer_as_shm(amshd->fd, amshd->band, pb->buf,
+ pb->offset);
+ if (ret < 0)
+ PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+ }
+ 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(),
.max_size_handler = afs_max_size_handler,
};
char *arg = query->data;
- int num_admissible, ret, ret2;
+ int num_admissible, ret;
ret = clear_score_table();
if (ret < 0) {
- ret2 = 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) {
- ret2 = 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) {
- if (ret2 >= 0)
- ret2 = para_printf(&pb, "failed, switching to dummy\n");
- activate_mood_or_playlist(NULL, &num_admissible);
- }
- } else
- ret2 = 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:
- if (ret2 >= 0 && pb.offset)
- pass_buffer_as_shm(fd, SBD_OUTPUT, pb.buf, pb.offset);
- free(pb.buf);
+ 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)
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;
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;
return ret;
}
-/*
- * On errors, negative value is written to fd.
- * On success: If query produced a result, the result_shmid is written to fd.
- * Otherwise, zero is written.
- */
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)
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)
exit(EXIT_FAILURE);
}
-static void create_tables_callback(int fd, const struct osl_object *query)
+static int create_tables_callback(int fd, const struct osl_object *query)
{
uint32_t table_mask = *(uint32_t *)query->data;
int i, ret;
out:
if (ret < 0)
para_printf(&pb, "%s\n", para_strerror(-ret));
- if (pb.buf)
- pass_buffer_as_shm(fd, SBD_OUTPUT, pb.buf, pb.offset);
- free(pb.buf);
+ flush_and_free_pb(&pb);
+ return 0;
}
int com_init(struct command_context *cc)
return -E_BAD_TABLE_NAME;
}
}
- ret = send_callback_request(create_tables_callback, &query,
+ return send_callback_request(create_tables_callback, &query,
afs_cb_result_handler, cc);
- return ret;
}
/**