aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2016-10-22 12:50:50 +0200
committerGitHub <noreply@github.com>2016-10-22 12:50:50 +0200
commit31df051ed9a3f8cc9ad7a4e408e3ba03a1c5272b (patch)
tree5e62dbb09dc5d02818d2a080b08af2168f306f8b /src
parente9041862776715cfb24e29fb7f18fa0830bd5555 (diff)
parentf6968dc0f7775591108aebbfe30e597dd0882c91 (diff)
downloadrneovim-31df051ed9a3f8cc9ad7a4e408e3ba03a1c5272b.tar.gz
rneovim-31df051ed9a3f8cc9ad7a4e408e3ba03a1c5272b.tar.bz2
rneovim-31df051ed9a3f8cc9ad7a4e408e3ba03a1c5272b.zip
Merge pull request #4568 from bfredl/multirequest
atomic multi request for async remote plugins
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/buffer.c4
-rw-r--r--src/nvim/api/private/defs.h4
-rw-r--r--src/nvim/api/private/dispatch.h1
-rw-r--r--src/nvim/api/vim.c89
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/msgpack_rpc/channel.c2
-rw-r--r--src/nvim/msgpack_rpc/helpers.c2
7 files changed, 95 insertions, 9 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index c4415ddf94..09d717bff6 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -191,7 +191,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
Object str = STRING_OBJ(cstr_to_string(bufstr));
// Vim represents NULs as NLs, but this may confuse clients.
- if (channel_id != INVALID_CHANNEL) {
+ if (channel_id != INTERNAL_CALL) {
strchrsub(str.data.string.data, '\n', '\0');
}
@@ -312,7 +312,7 @@ void nvim_buf_set_lines(uint64_t channel_id,
// line and convert NULs to newlines to avoid truncation.
lines[i] = xmallocz(l.size);
for (size_t j = 0; j < l.size; j++) {
- if (l.data[j] == '\n' && channel_id != INVALID_CHANNEL) {
+ if (l.data[j] == '\n' && channel_id != INTERNAL_CALL) {
api_set_error(err, Exception, _("string cannot contain newlines"));
new_len = i + 1;
goto end;
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h
index a6710193ff..1d5ecd3071 100644
--- a/src/nvim/api/private/defs.h
+++ b/src/nvim/api/private/defs.h
@@ -33,8 +33,8 @@ typedef enum {
/// Used as the message ID of notifications.
#define NO_RESPONSE UINT64_MAX
-/// Used as channel_id when the call is local
-#define INVALID_CHANNEL UINT64_MAX
+/// Used as channel_id when the call is local.
+#define INTERNAL_CALL UINT64_MAX
typedef struct {
ErrorType type;
diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h
index c12cf9e698..39aabd708a 100644
--- a/src/nvim/api/private/dispatch.h
+++ b/src/nvim/api/private/dispatch.h
@@ -4,7 +4,6 @@
#include "nvim/api/private/defs.h"
typedef Object (*ApiDispatchWrapper)(uint64_t channel_id,
- uint64_t request_id,
Array args,
Error *error);
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index d8cdad961b..9f3a84c88b 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -663,6 +663,95 @@ Array nvim_get_api_info(uint64_t channel_id)
return rv;
}
+/// Call many api methods atomically
+///
+/// This has two main usages: Firstly, to perform several requests from an
+/// async context atomically, i.e. without processing requests from other rpc
+/// clients or redrawing or allowing user interaction in between. Note that api
+/// methods that could fire autocommands or do event processing still might do
+/// so. For instance invoking the :sleep command might call timer callbacks.
+/// Secondly, it can be used to reduce rpc overhead (roundtrips) when doing
+/// many requests in sequence.
+///
+/// @param calls an array of calls, where each call is described by an array
+/// with two elements: the request name, and an array of arguments.
+/// @param[out] err Details of a validation error of the nvim_multi_request call
+/// itself, i e malformatted `calls` parameter. Errors from called methods will
+/// be indicated in the return value, see below.
+///
+/// @return an array with two elements. The first is an array of return
+/// values. The second is NIL if all calls succeeded. If a call resulted in
+/// an error, it is a three-element array with the zero-based index of the call
+/// which resulted in an error, the error type and the error message. If an
+/// error ocurred, the values from all preceding calls will still be returned.
+Array nvim_call_atomic(uint64_t channel_id, Array calls, Error *err)
+ FUNC_API_NOEVAL
+{
+ Array rv = ARRAY_DICT_INIT;
+ Array results = ARRAY_DICT_INIT;
+ Error nested_error = ERROR_INIT;
+
+ size_t i; // also used for freeing the variables
+ for (i = 0; i < calls.size; i++) {
+ if (calls.items[i].type != kObjectTypeArray) {
+ api_set_error(err,
+ Validation,
+ _("All items in calls array must be arrays"));
+ goto validation_error;
+ }
+ Array call = calls.items[i].data.array;
+ if (call.size != 2) {
+ api_set_error(err,
+ Validation,
+ _("All items in calls array must be arrays of size 2"));
+ goto validation_error;
+ }
+
+ if (call.items[0].type != kObjectTypeString) {
+ api_set_error(err,
+ Validation,
+ _("name must be String"));
+ goto validation_error;
+ }
+ String name = call.items[0].data.string;
+
+ if (call.items[1].type != kObjectTypeArray) {
+ api_set_error(err,
+ Validation,
+ _("args must be Array"));
+ goto validation_error;
+ }
+ Array args = call.items[1].data.array;
+
+ MsgpackRpcRequestHandler handler = msgpack_rpc_get_handler_for(name.data,
+ name.size);
+ Object result = handler.fn(channel_id, args, &nested_error);
+ if (nested_error.set) {
+ // error handled after loop
+ break;
+ }
+
+ ADD(results, result);
+ }
+
+ ADD(rv, ARRAY_OBJ(results));
+ if (nested_error.set) {
+ Array errval = ARRAY_DICT_INIT;
+ ADD(errval, INTEGER_OBJ((Integer)i));
+ ADD(errval, INTEGER_OBJ(nested_error.type));
+ ADD(errval, STRING_OBJ(cstr_to_string(nested_error.msg)));
+ ADD(rv, ARRAY_OBJ(errval));
+ } else {
+ ADD(rv, NIL);
+ }
+ return rv;
+
+validation_error:
+ api_free_array(results);
+ return rv;
+}
+
+
/// Writes a message to vim output or error buffer. The string is split
/// and flushed after each newline. Incomplete lines are kept for writing
/// later.
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index dce2f32707..76f33e7d8c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -7133,7 +7133,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
Error err = ERROR_INIT;
- Object result = fn(INVALID_CHANNEL, NO_RESPONSE, args, &err);
+ Object result = fn(INTERNAL_CALL, args, &err);
if (err.set) {
nvim_err_writeln(cstr_as_string(err.msg));
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index fef1d08db7..98636263b9 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -452,7 +452,7 @@ static void on_request_event(void **argv)
Array args = e->args;
uint64_t request_id = e->request_id;
Error error = ERROR_INIT;
- Object result = handler.fn(channel->id, request_id, args, &error);
+ Object result = handler.fn(channel->id, args, &error);
if (request_id != NO_RESPONSE) {
// send the response
msgpack_packer response;
diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c
index 33e9bb1c07..14e1c2d978 100644
--- a/src/nvim/msgpack_rpc/helpers.c
+++ b/src/nvim/msgpack_rpc/helpers.c
@@ -455,7 +455,6 @@ void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res)
/// Handler executed when an invalid method name is passed
Object msgpack_rpc_handle_missing_method(uint64_t channel_id,
- uint64_t request_id,
Array args,
Error *error)
{
@@ -466,7 +465,6 @@ Object msgpack_rpc_handle_missing_method(uint64_t channel_id,
/// Handler executed when malformated arguments are passed
Object msgpack_rpc_handle_invalid_arguments(uint64_t channel_id,
- uint64_t request_id,
Array args,
Error *error)
{