return 1;
}
-static int com_select_callback(const struct osl_object *query,
- struct osl_object *result)
+static void com_select_callback(int fd, const struct osl_object *query)
{
- struct para_buffer pb = {.buf = NULL};
+ struct para_buffer pb = {
+ .max_size = SHMMAX,
+ .private_data = &fd,
+ .max_size_handler = pass_buffer_as_shm
+ };
char *arg = query->data;
- int num_admissible, ret;
+ int num_admissible, ret, ret2;
ret = clear_score_table();
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ ret2 = para_printf(&pb, "%s\n", para_strerror(-ret));
+ goto out;
+ }
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\n", para_strerror(-ret));
- para_printf(&pb, "switching back to %s\n", current_mop?
+ 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) {
- para_printf(&pb, "failed, switching to dummy\n");
+ if (ret2 >= 0)
+ ret2 = para_printf(&pb, "failed, switching to dummy\n");
activate_mood_or_playlist(NULL, &num_admissible);
}
- }
- para_printf(&pb, "activated %s (%d admissible files)\n", current_mop?
- current_mop : "dummy mood", num_admissible);
- result->data = pb.buf;
- result->size = pb.offset;
- return 1;
+ } else
+ ret2 = para_printf(&pb, "activated %s (%d admissible files)\n", current_mop?
+ current_mop : "dummy mood", num_admissible);
+out:
+ if (ret2 >= 0 && pb.offset)
+ pass_buffer_as_shm(pb.buf, pb.offset, &fd);
+ free(pb.buf);
}
int send_result(struct osl_object *result, void *private_result_data)
t->ret = 1;
}
+int pass_buffer_as_shm(char *buf, size_t size, void *private_data)
+{
+ int ret, shmid, fd = *(int *)private_data;
+ void *shm;
+ struct callback_result *cr;
+
+ if (!buf || !size)
+ return 0;
+ ret = shm_new(size + sizeof(struct callback_result));
+ if (ret < 0)
+ return ret;
+ shmid = ret;
+ ret = shm_attach(shmid, ATTACH_RW, &shm);
+ if (ret < 0)
+ goto err;
+ cr = shm;
+ cr->result_size = size;
+ memcpy(shm + sizeof(*cr), buf, size);
+ ret = shm_detach(shm);
+ if (ret < 0)
+ goto err;
+ ret = send_bin_buffer(fd, (char *)&shmid, sizeof(int));
+ if (ret >= 0)
+ return ret;
+err:
+ if (shm_destroy(shmid) < 0)
+ PARA_ERROR_LOG("destroy result failed\n");
+ return ret;
+}
+
/*
* On errors, negative value is written to fd.
* On success: If query produced a result, the result_shmid is written to fd.
*/
static int call_callback(int fd, int query_shmid)
{
- void *query_shm, *result_shm;
+ void *query_shm;
struct callback_query *cq;
- struct callback_result *cr;
- struct osl_object query, result = {.data = NULL};
- int result_shmid = -1, ret, ret2;
+ struct osl_object query;
+ int ret;
ret = shm_attach(query_shmid, ATTACH_RW, &query_shm);
if (ret < 0)
- goto out;
+ return ret;
cq = query_shm;
query.data = (char *)query_shm + sizeof(*cq);
query.size = cq->query_size;
- ret = cq->handler(&query, &result);
- ret2 = shm_detach(query_shm);
- if (ret2 < 0 && ret >= 0)
- ret = ret2;
- if (ret < 0)
- goto out;
- ret = 0;
- if (!result.data || !result.size)
- goto out;
- ret = shm_new(result.size + sizeof(struct callback_result));
- if (ret < 0)
- goto out;
- result_shmid = ret;
- ret = shm_attach(result_shmid, ATTACH_RW, &result_shm);
- if (ret < 0)
- goto out;
- cr = result_shm;
- cr->result_size = result.size;
- memcpy(result_shm + sizeof(*cr), result.data, result.size);
- ret = shm_detach(result_shm);
- if (ret < 0)
- goto out;
- ret = result_shmid;
-out:
- free(result.data);
- ret2 = send_bin_buffer(fd, (char *)&ret, sizeof(int));
- if (ret < 0 || ret2 < 0) {
- if (result_shmid >= 0)
- if (shm_destroy(result_shmid) < 0)
- PARA_ERROR_LOG("destroy result failed\n");
- if (ret >= 0)
- ret = ret2;
- }
- return ret;
+ cq->handler(fd, &query);
+ return 1;
}
static void execute_server_command(void)
char buf[sizeof(cookie) + sizeof(query_shmid)];
int ret = recv_bin_buffer(fd, buf, sizeof(buf));
- if (ret < 0) {
- PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
- return;
- }
+ if (ret < 0)
+ goto err;
if (ret != sizeof(buf)) {
PARA_NOTICE_LOG("short read (%d bytes, expected %lu)\n",
ret, (long unsigned) sizeof(buf));
query_shmid);
return;
}
- /* Ignore return value: Errors might be OK here. */
- call_callback(fd, query_shmid);
+ ret = call_callback(fd, query_shmid);
+ if (ret >= 0)
+ return;
+err:
+ PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
}
/** Shutdown connection if query has not arrived until this many seconds. */
exit(EXIT_FAILURE);
}
-static int create_tables_callback(const struct osl_object *query,
- __a_unused struct osl_object *result)
+static void create_tables_callback(int fd, const struct osl_object *query)
{
uint32_t table_mask = *(uint32_t *)query->data;
int i, ret;
+ char *buf;
close_afs_tables();
for (i = 0; i < NUM_AFS_TABLES; i++) {
continue;
ret = t->create(database_dir);
if (ret < 0)
- return ret;
+ goto out;
}
ret = open_afs_tables();
- return ret < 0? ret: 0;
+out:
+ if (ret >= 0)
+ buf = make_message("successfully created afs table(s)\n");
+ else
+ buf = make_message("%s\n", para_strerror(-ret));
+ pass_buffer_as_shm(buf, strlen(buf), &fd);
+ free(buf);
}
int com_init(int fd, int argc, char * const * const argv)
}
ret = send_callback_request(create_tables_callback, &query, NULL, NULL);
if (ret < 0)
- return ret;
- return send_va_buffer(fd, "successfully created afs table(s)\n");
+ return send_va_buffer(fd, "%s\n", para_strerror(-ret));
+ return ret;
}
/**