]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - afs.c
com_addblob(): Return negative on errors
[paraslash.git] / afs.c
diff --git a/afs.c b/afs.c
index 0b2a4765b16f82fbde4674ac230bda4d2b5f9e18..0c615747435657b65ec5302192561fd902c84348 100644 (file)
--- 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);
 }