asys: Allow multiple results to be received
authorVolker Lendecke <vl@samba.org>
Mon, 24 Mar 2014 14:36:34 +0000 (14:36 +0000)
committerJeremy Allison <jra@samba.org>
Thu, 27 Mar 2014 05:06:12 +0000 (06:06 +0100)
This makes use of C99 dynamic arrays. In this performance-sensitive code, I
would like to avoid malloc/free, and I think 15 years after the standard we
might be able to use this feature. Alternatively, we could use the "results"
memory area and store the jobids in the upper range, playing some cast-tricks.
Should work as well.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/lib/asys/asys.c
source3/lib/asys/asys.h
source3/lib/asys/tests.c
source3/modules/vfs_default.c

index 1fd7700f9bfb76e332c15aa471569046f79985dc..906d8cf1c1e148eeb4ab19ea0ec814e9713014a9 100644 (file)
@@ -288,30 +288,41 @@ void asys_cancel(struct asys_context *ctx, void *private_data)
        }
 }
 
-int asys_result(struct asys_context *ctx, ssize_t *pret, int *perrno,
-               void *pdata)
+int asys_results(struct asys_context *ctx, struct asys_result *results,
+                unsigned num_results)
 {
-       void **pprivate_data = (void **)pdata;
-       struct asys_job *job;
-       int ret, jobid;
+       int jobids[num_results];
+       int i, ret;
 
-       ret = pthreadpool_finished_jobs(ctx->pool, &jobid, 1);
-       if (ret < 0) {
-               return -ret;
-       }
-       if ((jobid < 0) || (jobid >= ctx->num_jobs)) {
-               return EIO;
+       ret = pthreadpool_finished_jobs(ctx->pool, jobids, num_results);
+       if (ret <= 0) {
+               return ret;
        }
 
-       job = ctx->jobs[jobid];
+       for (i=0; i<ret; i++) {
+               struct asys_result *result = &results[i];
+               struct asys_job *job;
+               int jobid;
+
+               jobid = jobids[i];
+
+               if ((jobid < 0) || (jobid >= ctx->num_jobs)) {
+                       return -EIO;
+               }
+
+               job = ctx->jobs[jobid];
 
-       if (job->canceled) {
-               return ECANCELED;
+               if (job->canceled) {
+                       result->ret = -1;
+                       result->err = ECANCELED;
+               } else {
+                       result->ret = job->ret;
+                       result->err = job->err;
+               }
+               result->private_data = job->private_data;
+
+               job->busy = 0;
        }
 
-       *pret = job->ret;
-       *perrno = job->err;
-       *pprivate_data = job->private_data;
-       job->busy = 0;
-       return 0;
+       return ret;
 }
index 10805bdd1fe5648d6fd9b68c3d699211e8ac00d4..7c3dfdfbaf5d090e4e5d61b323f0b47d5bdbacf8 100644 (file)
@@ -104,18 +104,28 @@ void asys_set_log_fn(struct asys_context *ctx, asys_log_fn fn,
 
 int asys_signalfd(struct asys_context *ctx);
 
+struct asys_result {
+       ssize_t ret;
+       int err;
+       void *private_data;
+};
+
 /**
- * @brief Pull the result from an async operation
+ * @brief Pull the results from async operations
  *
- * Whe the fd returned from asys_signalfd() is readable, an async
- * operation has finished. The result from the async operation can be
- * pulled with asys_result().
+ * Whe the fd returned from asys_signalfd() is readable, one or more async
+ * operations have finished. The result from the async operations can be pulled
+ * with asys_results().
  *
- * @param[in]  ctx     The asys context
- * @return             success: 0, failure: errno
+ * @param[in]  ctx         The asys context
+ * @param[out]  results     The result strutcts
+ * @param[in]   num_results The length of the results array
+ * @return                 success: >=0, number of finished jobs
+ *                          failure: -errno
  */
-int asys_result(struct asys_context *ctx, ssize_t *pret, int *perrno,
-               void *pdata);
+int asys_results(struct asys_context *ctx, struct asys_result *results,
+                unsigned num_results);
+
 void asys_cancel(struct asys_context *ctx, void *private_data);
 
 int asys_pread(struct asys_context *ctx, int fildes, void *buf, size_t nbyte,
index 354f1bfbdb58acee8f05b22b38d0fe5e4915f994..e54e3ea2d22961d925f2260e4b5418c35fae4d06 100644 (file)
@@ -64,20 +64,18 @@ int main(int argc, const char *argv[])
        }
 
        for (i=0; i<ntasks; i++) {
-               void *priv;
-               ssize_t retval;
-               int err;
+               struct asys_result result;
                int *pidx;
 
-               ret = asys_result(ctx, &retval, &err, &priv);
-               if (ret == -1) {
-                       errno = ret;
+               ret = asys_results(ctx, &result, 1);
+               if (ret < 0) {
+                       errno = -ret;
                        perror("asys_result failed");
                        return 1;
                }
-               pidx = (int *)priv;
+               pidx = (int *)result.private_data;
 
-               printf("%d returned %d\n", *pidx, (int)retval);
+               printf("%d returned %d\n", *pidx, (int)result.ret);
        }
 
        ret = asys_context_destroy(ctx);
index 7dd9c0ca3ea0c5f4e2d21eecb4b57868f8bb6973..02ab35b1283ff42671a6034c0271dbe458fc431e 100644 (file)
@@ -793,44 +793,39 @@ static void vfswrap_asys_finished(struct tevent_context *ev,
                                        uint16_t flags, void *p)
 {
        struct asys_context *asys_ctx = (struct asys_context *)p;
-       struct tevent_req *req;
-       struct vfswrap_asys_state *state;
-       int res;
-       ssize_t ret;
-       int err;
-       void *private_data;
 
        if ((flags & TEVENT_FD_READ) == 0) {
                return;
        }
 
        while (true) {
-               res = asys_result(asys_ctx, &ret, &err, &private_data);
-               if (res == EINTR || res == EAGAIN) {
+               struct tevent_req *req;
+               struct vfswrap_asys_state *state;
+               struct asys_result result;
+               int res;
+
+               res = asys_results(asys_ctx, &result, 1);
+               if (res < 0) {
+                       DEBUG(1, ("asys_result returned %s\n",
+                                 strerror(-res)));
                        return;
                }
-#ifdef EWOULDBLOCK
-               if (res == EWOULDBLOCK) {
-                       return;
-               }
-#endif
-
-               if (res == ECANCELED) {
+               if (res == 0) {
                        return;
                }
 
-               if (res != 0) {
-                       DEBUG(1, ("asys_result returned %s\n", strerror(res)));
+               if ((result.ret == -1) && (result.err == ECANCELED)) {
                        return;
                }
 
-               req = talloc_get_type_abort(private_data, struct tevent_req);
+               req = talloc_get_type_abort(result.private_data,
+                                           struct tevent_req);
                state = tevent_req_data(req, struct vfswrap_asys_state);
 
                talloc_set_destructor(state, NULL);
 
-               state->ret = ret;
-               state->err = err;
+               state->ret = result.ret;
+               state->err = result.err;
                tevent_req_defer_callback(req, ev);
                tevent_req_done(req);
        }