diff options
Diffstat (limited to 'src/node/ext')
-rw-r--r-- | src/node/ext/call.cc | 56 | ||||
-rw-r--r-- | src/node/ext/call.h | 7 | ||||
-rw-r--r-- | src/node/ext/completion_queue_threadpool.cc | 27 | ||||
-rw-r--r-- | src/node/ext/completion_queue_uv.cc | 26 | ||||
-rw-r--r-- | src/node/ext/server.cc | 45 | ||||
-rw-r--r-- | src/node/ext/server.h | 2 | ||||
-rw-r--r-- | src/node/ext/server_generic.cc | 4 | ||||
-rw-r--r-- | src/node/ext/server_uv.cc | 15 |
8 files changed, 114 insertions, 68 deletions
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 5d573110da..bd60775aad 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -217,6 +217,8 @@ class SendMetadataOp : public Op { bool IsFinalOp() { return false; } + void OnComplete(bool success) { + } protected: std::string GetTypeString() const { return "send_metadata"; @@ -260,6 +262,8 @@ class SendMessageOp : public Op { bool IsFinalOp() { return false; } + void OnComplete(bool success) { + } protected: std::string GetTypeString() const { return "send_message"; @@ -280,6 +284,8 @@ class SendClientCloseOp : public Op { bool IsFinalOp() { return false; } + void OnComplete(bool success) { + } protected: std::string GetTypeString() const { return "client_close"; @@ -349,6 +355,8 @@ class SendServerStatusOp : public Op { bool IsFinalOp() { return true; } + void OnComplete(bool success) { + } protected: std::string GetTypeString() const { return "send_status"; @@ -381,6 +389,8 @@ class GetMetadataOp : public Op { bool IsFinalOp() { return false; } + void OnComplete(bool success) { + } protected: std::string GetTypeString() const { @@ -413,6 +423,8 @@ class ReadMessageOp : public Op { bool IsFinalOp() { return false; } + void OnComplete(bool success) { + } protected: std::string GetTypeString() const { @@ -454,6 +466,8 @@ class ClientStatusOp : public Op { bool IsFinalOp() { return true; } + void OnComplete(bool success) { + } protected: std::string GetTypeString() const { return "status"; @@ -478,6 +492,8 @@ class ServerCloseResponseOp : public Op { bool IsFinalOp() { return false; } + void OnComplete(bool success) { + } protected: std::string GetTypeString() const { @@ -499,36 +515,36 @@ tag::~tag() { delete ops; } -Local<Value> GetTagNodeValue(void *tag) { - EscapableHandleScope scope; +void CompleteTag(void *tag, const char *error_message) { + HandleScope scope; struct tag *tag_struct = reinterpret_cast<struct tag *>(tag); - Local<Object> tag_obj = Nan::New<Object>(); - for (vector<unique_ptr<Op> >::iterator it = tag_struct->ops->begin(); - it != tag_struct->ops->end(); ++it) { - Op *op_ptr = it->get(); - Nan::Set(tag_obj, op_ptr->GetOpType(), op_ptr->GetNodeValue()); + Callback *callback = tag_struct->callback; + if (error_message == NULL) { + Local<Object> tag_obj = Nan::New<Object>(); + for (vector<unique_ptr<Op> >::iterator it = tag_struct->ops->begin(); + it != tag_struct->ops->end(); ++it) { + Op *op_ptr = it->get(); + Nan::Set(tag_obj, op_ptr->GetOpType(), op_ptr->GetNodeValue()); + } + Local<Value> argv[] = {Nan::Null(), tag_obj}; + callback->Call(2, argv); + } else { + Local<Value> argv[] = {Nan::Error(error_message)}; + callback->Call(1, argv); } - return scope.Escape(tag_obj); -} - -Callback *GetTagCallback(void *tag) { - struct tag *tag_struct = reinterpret_cast<struct tag *>(tag); - return tag_struct->callback; -} - -void CompleteTag(void *tag) { - struct tag *tag_struct = reinterpret_cast<struct tag *>(tag); + bool success = (error_message == NULL); bool is_final_op = false; - if (tag_struct->call == NULL) { - return; - } for (vector<unique_ptr<Op> >::iterator it = tag_struct->ops->begin(); it != tag_struct->ops->end(); ++it) { Op *op_ptr = it->get(); + op_ptr->OnComplete(success); if (op_ptr->IsFinalOp()) { is_final_op = true; } } + if (tag_struct->call == NULL) { + return; + } tag_struct->call->CompleteBatch(is_final_op); } diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 53a5e4ab67..340e32682b 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -106,6 +106,7 @@ class Op { virtual ~Op(); v8::Local<v8::Value> GetOpType() const; virtual bool IsFinalOp() = 0; + virtual void OnComplete(bool success) = 0; protected: virtual std::string GetTypeString() const = 0; @@ -123,13 +124,9 @@ struct tag { call_persist; }; -v8::Local<v8::Value> GetTagNodeValue(void *tag); - -Nan::Callback *GetTagCallback(void *tag); - void DestroyTag(void *tag); -void CompleteTag(void *tag); +void CompleteTag(void *tag, const char *error_message); } // namespace node } // namespace grpc diff --git a/src/node/ext/completion_queue_threadpool.cc b/src/node/ext/completion_queue_threadpool.cc index 1917074dc2..72df5d1d65 100644 --- a/src/node/ext/completion_queue_threadpool.cc +++ b/src/node/ext/completion_queue_threadpool.cc @@ -34,14 +34,14 @@ /* I don't like using #ifndef, but I don't see a better way to do this */ #ifndef GRPC_UV -#include <node.h> #include <nan.h> +#include <node.h> +#include "call.h" +#include "completion_queue.h" #include "grpc/grpc.h" #include "grpc/support/log.h" #include "grpc/support/time.h" -#include "completion_queue.h" -#include "call.h" namespace grpc { namespace node { @@ -111,8 +111,8 @@ CompletionQueueAsyncWorker::CompletionQueueAsyncWorker() CompletionQueueAsyncWorker::~CompletionQueueAsyncWorker() {} void CompletionQueueAsyncWorker::Execute() { - result = - grpc_completion_queue_next(queue, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + result = grpc_completion_queue_next(queue, gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); if (!result.success) { SetErrorMessage("The async function encountered an error"); } @@ -141,16 +141,14 @@ void CompletionQueueAsyncWorker::Init(Local<Object> exports) { Nan::HandleScope scope; current_threads = 0; waiting_next_calls = 0; - queue = grpc_completion_queue_create(NULL); + queue = grpc_completion_queue_create_for_next(NULL); } void CompletionQueueAsyncWorker::HandleOKCallback() { Nan::HandleScope scope; current_threads -= 1; TryAddWorker(); - Nan::Callback *callback = GetTagCallback(result.tag); - Local<Value> argv[] = {Nan::Null(), GetTagNodeValue(result.tag)}; - callback->Call(2, argv); + CompleteTag(result.tag, NULL); DestroyTag(result.tag); } @@ -159,10 +157,7 @@ void CompletionQueueAsyncWorker::HandleErrorCallback() { Nan::HandleScope scope; current_threads -= 1; TryAddWorker(); - Nan::Callback *callback = GetTagCallback(result.tag); - Local<Value> argv[] = {Nan::Error(ErrorMessage())}; - - callback->Call(1, argv); + CompleteTag(result.tag, ErrorMessage()); DestroyTag(result.tag); } @@ -173,9 +168,7 @@ grpc_completion_queue *GetCompletionQueue() { return CompletionQueueAsyncWorker::GetQueue(); } -void CompletionQueueNext() { - CompletionQueueAsyncWorker::Next(); -} +void CompletionQueueNext() { CompletionQueueAsyncWorker::Next(); } void CompletionQueueInit(Local<Object> exports) { CompletionQueueAsyncWorker::Init(exports); @@ -184,4 +177,4 @@ void CompletionQueueInit(Local<Object> exports) { } // namespace node } // namespace grpc -#endif /* GRPC_UV */ +#endif /* GRPC_UV */ diff --git a/src/node/ext/completion_queue_uv.cc b/src/node/ext/completion_queue_uv.cc index 615973a6c9..9b60911d1e 100644 --- a/src/node/ext/completion_queue_uv.cc +++ b/src/node/ext/completion_queue_uv.cc @@ -33,10 +33,10 @@ #ifdef GRPC_UV -#include <uv.h> +#include <grpc/grpc.h> #include <node.h> +#include <uv.h> #include <v8.h> -#include <grpc/grpc.h> #include "call.h" #include "completion_queue.h" @@ -57,21 +57,17 @@ void drain_completion_queue(uv_prepare_t *handle) { grpc_event event; (void)handle; do { - event = grpc_completion_queue_next( - queue, gpr_inf_past(GPR_CLOCK_MONOTONIC), NULL); + event = grpc_completion_queue_next(queue, gpr_inf_past(GPR_CLOCK_MONOTONIC), + NULL); if (event.type == GRPC_OP_COMPLETE) { - Nan::Callback *callback = grpc::node::GetTagCallback(event.tag); + const char *error_message; if (event.success) { - Local<Value> argv[] = {Nan::Null(), - grpc::node::GetTagNodeValue(event.tag)}; - callback->Call(2, argv); + error_message = NULL; } else { - Local<Value> argv[] = {Nan::Error( - "The async function encountered an error")}; - callback->Call(1, argv); + error_message = "The async function encountered an error"; } - grpc::node::CompleteTag(event.tag); + CompleteTag(event.tag, error_message); grpc::node::DestroyTag(event.tag); pending_batches--; if (pending_batches == 0) { @@ -81,9 +77,7 @@ void drain_completion_queue(uv_prepare_t *handle) { } while (event.type != GRPC_QUEUE_TIMEOUT); } -grpc_completion_queue *GetCompletionQueue() { - return queue; -} +grpc_completion_queue *GetCompletionQueue() { return queue; } void CompletionQueueNext() { if (pending_batches == 0) { @@ -94,7 +88,7 @@ void CompletionQueueNext() { } void CompletionQueueInit(Local<Object> exports) { - queue = grpc_completion_queue_create(NULL); + queue = grpc_completion_queue_create_for_next(NULL); uv_prepare_init(uv_default_loop(), &prepare); pending_batches = 0; } diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index f0920c842a..5384305631 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -117,6 +117,8 @@ class NewCallOp : public Op { bool IsFinalOp() { return false; } + void OnComplete(bool success) { + } grpc_call *call; grpc_call_details details; @@ -126,6 +128,34 @@ class NewCallOp : public Op { std::string GetTypeString() const { return "new_call"; } }; +class TryShutdownOp: public Op { + public: + TryShutdownOp(Server *server, Local<Value> server_value) : server(server) { + server_persist.Reset(server_value); + } + Local<Value> GetNodeValue() const { + EscapableHandleScope scope; + return scope.Escape(Nan::New(server_persist)); + } + bool ParseOp(Local<Value> value, grpc_op *out) { + return true; + } + bool IsFinalOp() { + return false; + } + void OnComplete(bool success) { + if (success) { + server->DestroyWrappedServer(); + } + } + protected: + std::string GetTypeString() const { return "try_shutdown"; } + private: + Server *server; + Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>> + server_persist; +}; + void Server::Init(Local<Object> exports) { HandleScope scope; Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); @@ -147,6 +177,13 @@ bool Server::HasInstance(Local<Value> val) { return Nan::New(fun_tpl)->HasInstance(val); } +void Server::DestroyWrappedServer() { + if (this->wrapped_server != NULL) { + grpc_server_destroy(this->wrapped_server); + this->wrapped_server = NULL; + } +} + NAN_METHOD(Server::New) { /* If this is not a constructor call, make a constructor call and return the result */ @@ -242,7 +279,15 @@ NAN_METHOD(Server::TryShutdown) { return Nan::ThrowTypeError("tryShutdown can only be called on a Server"); } Server *server = ObjectWrap::Unwrap<Server>(info.This()); + if (server->wrapped_server == NULL) { + // Server is already shut down. Call callback immediately. + Nan::Callback callback(info[0].As<Function>()); + callback.Call(0, {}); + return; + } + TryShutdownOp *op = new TryShutdownOp(server, info.This()); unique_ptr<OpVec> ops(new OpVec()); + ops->push_back(unique_ptr<Op>(op)); grpc_server_shutdown_and_notify( server->wrapped_server, GetCompletionQueue(), new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(), diff --git a/src/node/ext/server.h b/src/node/ext/server.h index ab5fc210e8..c0f2e86554 100644 --- a/src/node/ext/server.h +++ b/src/node/ext/server.h @@ -53,6 +53,8 @@ class Server : public Nan::ObjectWrap { JavaScript constructor */ static bool HasInstance(v8::Local<v8::Value> val); + void DestroyWrappedServer(); + private: explicit Server(grpc_server *server); ~Server(); diff --git a/src/node/ext/server_generic.cc b/src/node/ext/server_generic.cc index 0cf20f754a..24573bd52f 100644 --- a/src/node/ext/server_generic.cc +++ b/src/node/ext/server_generic.cc @@ -35,8 +35,8 @@ #include "server.h" -#include <node.h> #include <nan.h> +#include <node.h> #include "grpc/grpc.h" #include "grpc/support/time.h" @@ -44,7 +44,7 @@ namespace grpc { namespace node { Server::Server(grpc_server *server) : wrapped_server(server) { - shutdown_queue = grpc_completion_queue_create(NULL); + shutdown_queue = grpc_completion_queue_create_for_pluck(NULL); grpc_server_register_non_listening_completion_queue(server, shutdown_queue, NULL); } diff --git a/src/node/ext/server_uv.cc b/src/node/ext/server_uv.cc index 82e7589fc8..789938318e 100644 --- a/src/node/ext/server_uv.cc +++ b/src/node/ext/server_uv.cc @@ -67,7 +67,7 @@ class ServerShutdownOp : public Op { } Local<Value> GetNodeValue() const { - return Nan::New<External>(reinterpret_cast<void *>(server)); + return Nan::Null(); } bool ParseOp(Local<Value> value, grpc_op *out) { @@ -76,6 +76,11 @@ class ServerShutdownOp : public Op { bool IsFinalOp() { return false; } + void OnComplete(bool success) { + /* Because cancel_all_calls was called, we assume that shutdown_and_notify + completes successfully */ + grpc_server_destroy(server); + } grpc_server *server; @@ -94,16 +99,10 @@ NAN_METHOD(ServerShutdownCallback) { if (!info[0]->IsNull()) { return Nan::ThrowError("forceShutdown failed somehow"); } - MaybeLocal<Object> maybe_result = Nan::To<Object>(info[1]); - Local<Object> result = maybe_result.ToLocalChecked(); - Local<Value> server_val = Nan::Get( - result, Nan::New("shutdown").ToLocalChecked()).ToLocalChecked(); - Local<External> server_extern = server_val.As<External>(); - grpc_server *server = reinterpret_cast<grpc_server *>(server_extern->Value()); - grpc_server_destroy(server); } void Server::ShutdownServer() { + Nan::HandleScope scope; if (this->wrapped_server != NULL) { if (shutdown_callback == NULL) { Local<FunctionTemplate>callback_tpl = |