From a9b99c93e3ac7557eb0ad52c83fde013518eee92 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 5 Feb 2015 17:42:01 -0800 Subject: [PATCH 01/31] Part of the update to the new API --- src/node/ext/call.cc | 155 +++++++++++++++++++++- src/node/ext/node_grpc.cc | 31 +++++ src/node/ext/tag.cc | 263 +++++++++++++++++++++++++++++++++----- src/node/ext/tag.h | 28 ++-- 4 files changed, 434 insertions(+), 43 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 23aead07b29..d2e930bc0ff 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -31,6 +31,8 @@ * */ +#include + #include #include "grpc/support/log.h" @@ -68,6 +70,50 @@ using v8::Value; Persistent Call::constructor; Persistent Call::fun_tpl; +bool CreateMetadataArray(Handle metadata, grpc_metadata_array *array + vector *string_handles, + vector*> *handles) { + NanScope(); + Handle keys(metadata->GetOwnPropertyNames()); + for (unsigned int i = 0; i < keys->Length(); i++) { + Handle current_key(keys->Get(i)->ToString()); + if (!metadata->Get(current_key)->IsArray()) { + return false; + } + array->capacity += Local::Cast(metadata->Get(current_key))->Length(); + } + array->metadata = calloc(array->capacity, sizeof(grpc_metadata)); + for (unsigned int i = 0; i < keys->Length(); i++) { + Handle current_key(keys->Get(i)->ToString()); + NanUtf8String *utf8_key = new NanUtf8String(current_key); + string_handles->push_back(utf8_key); + Handle values = Local::Cast(metadata->Get(current_key)); + for (unsigned int j = 0; j < values->Length(); j++) { + Handle value = values->Get(j); + grpc_metadata *current = &array[array->count]; + grpc_call_error error; + current->key = **utf8_key; + if (Buffer::HasInstance(value)) { + current->value = Buffer::Data(value); + current->value_length = Buffer::Length(value); + Persistent *handle = new Persistent(); + NanAssignPersistent(handle, object); + handles->push_back(handle); + } else if (value->IsString()) { + Handle string_value = value->ToString(); + NanUtf8String *utf8_value = new NanUtf8String(string_value); + string_handles->push_back(utf8_value); + current->value = **utf8_value; + current->value_length = string_value->Length(); + } else { + return false; + } + array->count += 1; + } + } + return true; +} + Call::Call(grpc_call *call) : wrapped_call(call) {} Call::~Call() { grpc_call_destroy(wrapped_call); } @@ -152,9 +198,9 @@ NAN_METHOD(Call::New) { NanUtf8String method(args[1]); double deadline = args[2]->NumberValue(); grpc_channel *wrapped_channel = channel->GetWrappedChannel(); - grpc_call *wrapped_call = grpc_channel_create_call_old( - wrapped_channel, *method, channel->GetHost(), - MillisecondsToTimespec(deadline)); + grpc_call *wrapped_call = grpc_channel_create_call( + wrapped_channel, CompletionQueueAsyncWorker::GetQueue(), *method, + channel->GetHost(), MillisecondsToTimespec(deadline)); call = new Call(wrapped_call); args.This()->SetHiddenValue(String::NewSymbol("channel_"), channel_object); @@ -168,6 +214,109 @@ NAN_METHOD(Call::New) { } } +NAN_METHOD(Call::StartBatch) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("startBatch can only be called on Call objects"); + } + if (!args[0]->IsObject()) { + return NanThrowError("startBatch's first argument must be an object"); + } + if (!args[1]->IsFunction()) { + return NanThrowError("startBatch's second argument must be a callback"); + } + vector *> *handles = new vector>(); + vector *strings = new vector(); + Persistent *handle; + Handle keys = args[0]->GetOwnPropertyNames(); + size_t nops = keys->Length(); + grpc_op *ops = calloc(nops, sizeof(grpc_op)); + grpc_metadata_array array; + Handle server_status; + NanUtf8String *str; + for (unsigned int i = 0; i < nops; i++) { + if (!keys->Get(i)->IsUInt32()) { + return NanThrowError( + "startBatch's first argument's keys must be integers"); + } + uint32_t type = keys->Get(i)->UInt32Value(); + ops[i].op = type; + switch (type) { + case GRPC_OP_SEND_INITIAL_METADATA: + if (!args[0]->Get(type)->IsObject()) { + return NanThrowError("metadata must be an object"); + } + if (!CreateMetadataArray(args[0]->Get(type)->ToObject(), &array, + strings, handles)) { + return NanThrowError("failed to parse metadata"); + } + ops[i].data.send_initial_metadata.count = array.count; + ops[i].data.send_initial_metadata.metadata = array.metadata; + break + case GRPC_OP_SEND_MESSAGE: + if (!Buffer::HasInstance(args[0]->Get(type))) { + return NanThrowError("message must be a Buffer"); + } + ops[i].data.send_message = BufferToByteBuffer(args[0]->Get(type)); + handle = new Persistent(); + NanAssignPersistent(*handle, args[0]->Get(type)); + handles->push_back(handle); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + if (!args[0]->Get(type)->IsObject()) { + return NanThrowError("server status must be an object"); + } + server_status = args[0]->Get(type)->ToObject(); + if (!server_status->Get("metadata")->IsObject()) { + return NanThrowError("status metadata must be an object"); + } + if (!server_status->Get("code")->IsUInt32()) { + return NanThrowError("status code must be a positive integer"); + } + if (!server_status->Get("details")->IsString()) { + return NanThrowError("status details must be a string"); + } + if (!CreateMetadataArray(server_status->Get("metadata")->ToObject(), + &array, strings, handles)) { + return NanThrowError("Failed to parse status metadata"); + } + ops[i].data.send_status_from_server.trailing_metadata_count = + array.count; + ops[i].data.send_status_from_server.trailing_metadata = array.metadata; + ops[i].data.send_status_from_server.status = + server_status->Get("code")->UInt32Value(); + str = new NanUtf8String(server_status->Get("details")); + strings->push_back(str); + ops[i].data.send_status_from_server.status_details = **str; + break; + case GRPC_OP_RECV_INITIAL_METADATA: + ops[i].data.recv_initial_metadata = malloc(sizeof(grpc_metadata_array)); + grpc_metadata_array_init(ops[i].data.recv_initial_metadata); + break; + case GRPC_OP_RECV_MESSAGE: + ops[i].data.recv_message = malloc(sizeof(grpc_byte_buffer*)); + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + ops[i].data.recv_status_on_client.trailing_metadata = + malloc(sizeof(grpc_metadata_array)); + grpc_metadata_array_init(ops[i].data.recv_status_on_client); + ops[i].data.recv_status_on_client.status = + malloc(sizeof(grpc_status_code)); + ops[i].data.recv_status_on_client.status_details = + malloc(sizeof(char *)); + ops[i].data.recv_status_on_client.status_details_capacity = + malloc(sizeof(size_t)); + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + ops[i].data.recv_close_on_server = malloc(sizeof(int)); + break; + + } + } +} + NAN_METHOD(Call::AddMetadata) { NanScope(); if (!HasInstance(args.This())) { diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc index bc1dfaf8996..c9388940ad2 100644 --- a/src/node/ext/node_grpc.cc +++ b/src/node/ext/node_grpc.cc @@ -161,6 +161,36 @@ void InitCompletionTypeConstants(Handle exports) { completion_type->Set(NanNew("SERVER_RPC_NEW"), SERVER_RPC_NEW); } +void InitOpTypeConstants(Handle exports) { + NanScope(); + Handle op_type = Object::New(); + exports->Set(NanNew("opType"), op_type); + Handle SEND_INITIAL_METADATA( + NanNew(GRPC_OP_SEND_INITIAL_METADATA)); + op_type->Set(NanNew("SEND_INITIAL_METADATA"), SEND_INITIAL_METADATA); + Handle SEND_MESSAGE( + NanNew(GRPC_OP_SEND_MESSAGE)); + op_type->Set(NanNew("SEND_MESSAGE"), SEND_MESSAGE); + Handle SEND_CLOSE_FROM_CLIENT( + NanNew(GRPC_OP_SEND_CLOSE_FROM_CLIENT)); + op_type->Set(NanNew("SEND_CLOSE_FROM_CLIENT"), SEND_CLOSE_FROM_CLIENT); + Handle SEND_STATUS_FROM_SERVER( + NanNew(GRPC_OP_SEND_STATUS_FROM_SERVER)); + op_type->Set(NanNew("SEND_STATUS_FROM_SERVER"), SEND_STATUS_FROM_SERVER); + Handle RECV_INITIAL_METADATA( + NanNew(GRPC_OP_RECV_INITIAL_METADATA)); + op_type->Set(NanNew("RECV_INITIAL_METADATA"), RECV_INITIAL_METADATA); + Handle RECV_MESSAGE( + NanNew(GRPC_OP_RECV_MESSAGE)); + op_type->Set(NanNew("RECV_MESSAGE"), RECV_MESSAGE); + Handle RECV_STATUS_ON_CLIENT( + NanNew(GRPC_OP_RECV_STATUS_ON_CLIENT)); + op_type->Set(NanNew("RECV_STATUS_ON_CLIENT"), RECV_STATUS_ON_CLIENT); + Handle RECV_CLOSE_ON_SERVER( + NanNew(GRPC_OP_RECV_CLOSE_ON_SERVER)); + op_type->Set(NanNew("RECV_CLOSE_ON_SERVER"), RECV_CLOSE_ON_SERVER); +} + void init(Handle exports) { NanScope(); grpc_init(); @@ -168,6 +198,7 @@ void init(Handle exports) { InitCallErrorConstants(exports); InitOpErrorConstants(exports); InitCompletionTypeConstants(exports); + InitOpTypeConstants(exports); grpc::node::Call::Init(exports); grpc::node::Channel::Init(exports); diff --git a/src/node/ext/tag.cc b/src/node/ext/tag.cc index dc8e523e12e..4c41c3d20c6 100644 --- a/src/node/ext/tag.cc +++ b/src/node/ext/tag.cc @@ -31,68 +31,271 @@ * */ +#include +#include + +#include #include #include #include #include "tag.h" +#include "call.h" namespace grpc { namespace node { +using v8::Boolean; +using v8::Function; using v8::Handle; using v8::HandleScope; using v8::Persistent; using v8::Value; -struct tag { - tag(Persistent *tag, Persistent *call) - : persist_tag(tag), persist_call(call) {} +Handle ParseMetadata(grpc_metadata_array *metadata_array) { + NanEscapableScope(); + grpc_metadata *metadata_elements = metadata_array->metadata; + size_t length = metadata_array->count; + std::map size_map; + std::map index_map; + + for (unsigned int i = 0; i < length; i++) { + char *key = metadata_elements[i].key; + if (size_map.count(key)) { + size_map[key] += 1; + } + index_map[key] = 0; + } + Handle metadata_object = NanNew(); + for (unsigned int i = 0; i < length; i++) { + grpc_metadata* elem = &metadata_elements[i]; + Handle key_string = String::New(elem->key); + Handle array; + if (metadata_object->Has(key_string)) { + array = Handle::Cast(metadata_object->Get(key_string)); + } else { + array = NanNew(size_map[elem->key]); + metadata_object->Set(key_string, array); + } + array->Set(index_map[elem->key], + MakeFastBuffer( + NanNewBufferHandle(elem->value, elem->value_length))); + index_map[elem->key] += 1; + } + return NanEscapeScope(metadata_object); +} + +class OpResponse { + public: + explicit OpResponse(char *name): name(name) { + } + virtual Handle GetNodeValue() const = 0; + Handle GetOpType() const { + NanEscapableScope(); + return NanEscapeScope(NanNew(name)); + } + + private: + char *name; +}; + +class SendResponse : public OpResponse { + public: + explicit SendResponse(char *name): OpResponse(name) { + } + + Handle GetNodeValue() { + NanEscapableScope(); + return NanEscapeScope(NanTrue()); + } +} + +class MetadataResponse : public OpResponse { + public: + explicit MetadataResponse(grpc_metadata_array *recv_metadata): + recv_metadata(recv_metadata), OpResponse("metadata") { + } + + Handle GetNodeValue() const { + NanEscapableScope(); + return NanEscapeScope(ParseMetadata(recv_metadata)); + } + + private: + grpc_metadata_array *recv_metadata; +}; + +class MessageResponse : public OpResponse { + public: + explicit MessageResponse(grpc_byte_buffer **recv_message): + recv_message(recv_message), OpResponse("read") { + } + + Handle GetNodeValue() const { + NanEscapableScope(); + return NanEscapeScope(ByteBufferToBuffer(*recv_message)); + } + + private: + grpc_byte_buffer **recv_message +}; + +class ClientStatusResponse : public OpResponse { + public: + explicit ClientStatusResponse(grpc_metadata_array *metadata_array, + grpc_status_code *status, + char **status_details): + metadata_array(metadata_array), status(status), + status_details(status_details), OpResponse("status") { + } + + Handle GetNodeValue() const { + NanEscapableScope(); + Handle status_obj = NanNew(); + status_obj->Set(NanNew("code"), NanNew(*status)); + if (event->data.finished.details != NULL) { + status_obj->Set(NanNew("details"), String::New(*status_details)); + } + status_obj->Set(NanNew("metadata"), ParseMetadata(metadata_array)); + return NanEscapeScope(status_obj); + } + private: + grpc_metadata_array *metadata_array; + grpc_status_code *status; + char **status_details; +}; + +class ServerCloseResponse : public OpResponse { + public: + explicit ServerCloseResponse(int *cancelled): cancelled(cancelled), + OpResponse("cancelled") { + } + + Handle GetNodeValue() const { + NanEscapableScope(); + NanEscapeScope(NanNew(*cancelled)); + } + + private: + int *cancelled; +}; + +class NewCallResponse : public OpResponse { + public: + explicit NewCallResponse(grpc_call **call, grpc_call_details *details, + grpc_metadata_array *request_metadata) : + call(call), details(details), request_metadata(request_metadata), + OpResponse("call"){ + } + + Handle GetNodeValue() const { + NanEscapableScope(); + if (*call == NULL) { + return NanEscapeScope(NanNull()); + } + Handle obj = NanNew(); + obj->Set(NanNew("call"), Call::WrapStruct(*call)); + obj->Set(NanNew("method"), NanNew(details->method)); + obj->Set(NanNew("host"), NanNew(details->host)); + obj->Set(NanNew("deadline"), + NanNew(TimespecToMilliseconds(details->deadline))); + obj->Set(NanNew("metadata"), ParseMetadata(request_metadata)); + return NanEscapeScope(obj); + } + private: + grpc_call **call; + grpc_call_details *details; + grpc_metadata_array *request_metadata; +} +struct tag { + tag(NanCallback *callback, std::vector *responses) : + callback(callback), repsonses(responses) { + } ~tag() { - persist_tag->Dispose(); - if (persist_call != NULL) { - persist_call->Dispose(); + for (std::vector::iterator it = responses->begin(); + it != responses->end(); ++it) { + delete *it; } + delete callback; + delete responses; } - Persistent *persist_tag; - Persistent *persist_call; + NanCallback *callback; + std::vector *responses; }; -void *CreateTag(Handle tag, Handle call) { +void *CreateTag(Handle callback, grpc_op *ops, size_t nops) { NanScope(); - Persistent *persist_tag = new Persistent(); - NanAssignPersistent(*persist_tag, tag); - Persistent *persist_call; - if (call->IsNull() || call->IsUndefined()) { - persist_call = NULL; - } else { - persist_call = new Persistent(); - NanAssignPersistent(*persist_call, call); - } - struct tag *tag_struct = new struct tag(persist_tag, persist_call); + NanCallback *cb = new NanCallback(callback); + vector *responses = new vector(); + for (size_t i = 0; i < nops; i++) { + grpc_op *op = &ops[i]; + OpResponse *resp; + // Switching on the TYPE of the op + switch (op->op) { + case GRPC_OP_SEND_INITIAL_METADATA: + resp = new SendResponse("send metadata"); + break; + case GRPC_OP_SEND_MESSAGE: + resp = new SendResponse("write"); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + resp = new SendResponse("client close"); + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + resp = new SendResponse("server close"); + break; + case GRPC_OP_RECV_INITIAL_METADATA: + resp = new MetadataResponse(op->data.recv_initial_metadata); + break; + case GRPC_OP_RECV_MESSAGE: + resp = new MessageResponse(op->data.recv_message); + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + resp = new ClientStatusResponse( + op->data.recv_status_on_client.trailing_metadata, + op->data.recv_status_on_client.status, + op->data.recv_status_on_client.status_details); + break; + case GRPC_RECV_CLOSE_ON_SERVER: + resp = new ServerCloseResponse(op->data.recv_close_on_server.cancelled); + break; + default: + continue; + } + responses->push_back(resp); + } + struct tag *tag_struct = new struct tag(cb, responses); return reinterpret_cast(tag_struct); } -Handle GetTagHandle(void *tag) { +void *CreateTag(Handle callback, grpc_call **call, + grpc_call_details *details, + grpc_metadata_array *request_metadata) { NanEscapableScope(); - struct tag *tag_struct = reinterpret_cast(tag); - Handle tag_value = NanNew(*tag_struct->persist_tag); - return NanEscapeScope(tag_value); + NanCallback *cb = new NanCallback(callback); + vector *responses = new vector(); + OpResponse *resp = new NewCallResponse(call, details, request_metadata); + responses->push_back(resp); + struct tag *tag_struct = new struct tag(cb, responses); + return reinterpret_cast(tag_struct); } -bool TagHasCall(void *tag) { +NanCallback GetCallback(void *tag) { + NanEscapableScope(); struct tag *tag_struct = reinterpret_cast(tag); - return tag_struct->persist_call != NULL; + return NanEscapeScope(*tag_struct->callback); } -Handle TagGetCall(void *tag) { +Handle GetNodeValue(void *tag) { NanEscapableScope(); struct tag *tag_struct = reinterpret_cast(tag); - if (tag_struct->persist_call == NULL) { - return NanEscapeScope(NanNull()); + Handle obj = NanNew(); + for (std::vector::iterator it = tag_struct->responses->begin(); + it != tag_struct->responses->end(); ++it) { + OpResponse *resp = *it; + obj->Set(resp->GetOpType(), resp->GetNodeValue()); } - Handle call_value = NanNew(*tag_struct->persist_call); - return NanEscapeScope(call_value); + return NanEscapeScope(obj); } void DestroyTag(void *tag) { delete reinterpret_cast(tag); } diff --git a/src/node/ext/tag.h b/src/node/ext/tag.h index bdb09252d98..5c709743237 100644 --- a/src/node/ext/tag.h +++ b/src/node/ext/tag.h @@ -34,21 +34,29 @@ #ifndef NET_GRPC_NODE_TAG_H_ #define NET_GRPC_NODE_TAG_H_ +#include #include +#include namespace grpc { namespace node { -/* Create a void* tag that can be passed to various grpc_call functions from - a javascript value and the javascript wrapper for the call. The call can be - null. */ -void *CreateTag(v8::Handle tag, v8::Handle call); -/* Return the javascript value stored in the tag */ -v8::Handle GetTagHandle(void *tag); -/* Returns true if the call was set (non-null) when the tag was created */ -bool TagHasCall(void *tag); -/* Returns the javascript wrapper for the call associated with this tag */ -v8::Handle TagGetCall(void *call); +/* Create a void* tag that can be passed to grpc_call_start_batch from a callback + function and an ops array */ +void *CreateTag(v8::Handle callback, grpc_op *ops, size_t nops); + +/* Create a void* tag that can be passed to grpc_server_request_call from a + callback and the various out parameters to that function */ +void *CreateTag(v8::Handle callback, grpc_call **call, + grpc_call_details *details, + grpc_metadata_array *request_metadata); + +/* Get the callback from the tag */ +NanCallback GetCallback(void *tag); + +/* Get the combined output value from the tag */ +v8::Handle GetNodevalue(void *tag); + /* Destroy the tag and all resources it is holding. It is illegal to call any of these other functions on a tag after it has been destroyed. */ void DestroyTag(void *tag); From d4d67ade9b2183cfec08ecc241e2540f3494fe48 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 9 Feb 2015 10:43:21 -0800 Subject: [PATCH 02/31] More progress towards new API compatibility --- src/node/ext/call.cc | 648 +++++++++--------- src/node/ext/call.h | 49 +- src/node/ext/completion_queue_async_worker.cc | 22 +- src/node/ext/completion_queue_async_worker.h | 2 + src/node/ext/server.cc | 55 +- src/node/ext/tag.cc | 49 +- src/node/ext/tag.h | 13 +- 7 files changed, 494 insertions(+), 344 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index d2e930bc0ff..85dcb3cd079 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -31,24 +31,26 @@ * */ +#include #include #include #include "grpc/support/log.h" #include "grpc/grpc.h" +#include "grpc/support/alloc.h" #include "grpc/support/time.h" #include "byte_buffer.h" #include "call.h" #include "channel.h" #include "completion_queue_async_worker.h" #include "timeval.h" -#include "tag.h" namespace grpc { namespace node { using ::node::Buffer; +using std::unique_ptr; using v8::Arguments; using v8::Array; using v8::Exception; @@ -70,9 +72,11 @@ using v8::Value; Persistent Call::constructor; Persistent Call::fun_tpl; -bool CreateMetadataArray(Handle metadata, grpc_metadata_array *array - vector *string_handles, - vector*> *handles) { + +bool CreateMetadataArray( + Handle metadata, grpc_metadata_array *array, + std::vector > *string_handles, + std::vector > *handles) { NanScope(); Handle keys(metadata->GetOwnPropertyNames()); for (unsigned int i = 0; i < keys->Length(); i++) { @@ -82,27 +86,27 @@ bool CreateMetadataArray(Handle metadata, grpc_metadata_array *array } array->capacity += Local::Cast(metadata->Get(current_key))->Length(); } - array->metadata = calloc(array->capacity, sizeof(grpc_metadata)); + array->metadata = reinterpret_cast( + gpr_malloc(array->capacity * sizeof(grpc_metadata))); for (unsigned int i = 0; i < keys->Length(); i++) { Handle current_key(keys->Get(i)->ToString()); NanUtf8String *utf8_key = new NanUtf8String(current_key); - string_handles->push_back(utf8_key); + string_handles->push_back(unique_ptr values = Local::Cast(metadata->Get(current_key)); for (unsigned int j = 0; j < values->Length(); j++) { Handle value = values->Get(j); - grpc_metadata *current = &array[array->count]; - grpc_call_error error; + grpc_metadata *current = &array->metadata[array->count]; current->key = **utf8_key; if (Buffer::HasInstance(value)) { current->value = Buffer::Data(value); current->value_length = Buffer::Length(value); - Persistent *handle = new Persistent(); - NanAssignPersistent(handle, object); - handles->push_back(handle); + Persistent handle; + NanAssignPersistent(handle, value); + handles->push_back(PersistentHolder(handle)); } else if (value->IsString()) { Handle string_value = value->ToString(); NanUtf8String *utf8_value = new NanUtf8String(string_value); - string_handles->push_back(utf8_value); + string_handles->push_back(unique_ptr(utf8_value)); current->value = **utf8_value; current->value_length = string_value->Length(); } else { @@ -114,6 +118,294 @@ bool CreateMetadataArray(Handle metadata, grpc_metadata_array *array return true; } +Handle ParseMetadata(grpc_metadata_array *metadata_array) { + NanEscapableScope(); + grpc_metadata *metadata_elements = metadata_array->metadata; + size_t length = metadata_array->count; + std::map size_map; + std::map index_map; + + for (unsigned int i = 0; i < length; i++) { + char *key = metadata_elements[i].key; + if (size_map.count(key)) { + size_map[key] += 1; + } + index_map[key] = 0; + } + Handle metadata_object = NanNew(); + for (unsigned int i = 0; i < length; i++) { + grpc_metadata* elem = &metadata_elements[i]; + Handle key_string = String::New(elem->key); + Handle array; + if (metadata_object->Has(key_string)) { + array = Handle::Cast(metadata_object->Get(key_string)); + } else { + array = NanNew(size_map[elem->key]); + metadata_object->Set(key_string, array); + } + array->Set(index_map[elem->key], + MakeFastBuffer( + NanNewBufferHandle(elem->value, elem->value_length))); + index_map[elem->key] += 1; + } + return NanEscapeScope(metadata_object); +} + +class Op { + public: + Handle GetOpType() const { + NanEscapableScope(); + return NanEscapeScope(NanNew(GetTypeString())); + } +}; + +class SendMetadataOp : public Op { + public: + Handle GetNodeValue() { + NanEscapableScope(); + return NanEscapeScope(NanTrue()); + } + bool ParseOp(Handle value, grpc_op *out, + std::vector > *strings, + std::vector > *handles) { + if (!value->IsObject()) { + return false; + } + grpc_metadata_array array; + if (!CreateMetadataArray(value->ToObject(), &array, strings, handles)) { + return false; + } + out->data.send_initial_metadata.count = array.count; + out->data.send_initial_metadata.metadata = array.metadata; + return true; + } + protected: + char *GetTypeString() { + return "send metadata"; + } +}; + +class SendMessageOp : public Op { + public: + Handle GetNodeValue() { + NanEscapableScope(); + return NanEscapeScope(NanTrue()); + } + bool ParseOp(Handle value, grpc_op *out, + std::vector > *strings, + std::vector > *handles) { + if (!Buffer::HasInstance(value)) { + return false; + } + out->.data.send_message = BufferToByteBuffer(obj->Get(type)); + NanAssignPersistent(handle, value); + handles->push_back(PersistentHolder(handle)); + } + protected: + char *GetTypeString() { + return "send message"; + } +}; + +class SendClientCloseOp : public Op { + public: + Handle GetNodeValue() { + NanEscapableScope(); + return NanEscapeScope(NanTrue()); + } + bool ParseOp(Handle value, grpc_op *out, + std::vector > *strings, + std::vector > *handles) { + return true; + } + protected: + char *GetTypeString() { + return "client close"; + } +}; + +class SendServerStatusOp : public Op { + public: + Handle GetNodeValue() { + NanEscapableScope(); + return NanEscapeScope(NanTrue()); + } + bool ParseOp(Handle value, grpc_op *out, + std::vector > *strings, + std::vector > *handles) { + if (value->IsObject()) { + return false; + } + Handle server_status = value->ToObject(); + if (!server_status->Get(NanNew("metadata"))->IsObject()) { + return false; + } + if (!server_status->Get(NanNew("code"))->IsUint32()) { + return false; + } + if (!server_status->Get(NanNew("details"))->IsString()) { + return false; + } + grpc_metadata_array array; + if (!CreateMetadataArray(server_status->Get(NanNew("metadata"))-> + ToObject(), + &array, strings, handles)) { + return false; + } + out->data.send_status_from_server.trailing_metadata_count = array.count; + out->data.send_status_from_server.trailing_metadata = array.metadata; + out->data.send_status_from_server.status = + static_cast( + server_status->Get(NanNew("code"))->Uint32Value()); + NanUtf8String *str = new NanUtf8String( + server_status->Get(NanNew("details"))); + strings->push_back(unique_ptr(str)); + out->data.send_status_from_server.status_details = **str; + return true; + } + protected: + char *GetTypeString() { + return "send status"; + } +} + +class GetMetadataOp : public Op { + public: + GetMetadataOp() { + grpc_metadata_array_init(&recv_metadata); + } + + ~GetMetadataOp() { + grpc_metadata_array_destroy(&recv_metadata); + } + + Handle GetNodeValue() const { + NanEscapableScope(); + return NanEscapeScope(ParseMetadata(&recv_metadata)); + } + + bool ParseOp(Handle value, grpc_op *out, + std::vector > *strings, + std::vector > *handles) { + out->data.recv_initial_metadata = &recv_metadata; + } + + protected: + char *GetTypeString() { + return "metadata"; + } + + private: + grpc_metadata_array recv_metadata; +}; + +class ReadMessageOp : public Op { + public: + ReadMessageOp() { + recv_message = NULL; + } + ~ReadMessageOp() { + if (recv_message != NULL) { + gpr_free(recv_message); + } + } + Handle GetNodeValue() const { + NanEscapableScope(); + return NanEscapeScope(ByteBufferToBuffer(*recv_message)); + } + + bool ParseOp(Handle value, grpc_op *out, + std::vector > *strings, + std::vector > *handles) { + out->data.recv_message = &recv_message; + } + + protected: + char *GetTypeString() { + return "read"; + } + + private: + grpc_byte_buffer *recv_message; +}; + +class ClientStatusOp : public Op { + public: + ClientStatusOp() { + grpc_metadata_array_init(&metadata); + status_details = NULL; + } + + ~ClientStatusOp() { + gprc_metadata_array_destroy(&metadata_array); + gpr_free(status_details); + } + + bool ParseOp(Handle value, grpc_op *out, + std::vector > *strings, + std::vector > *handles) { + out->data.recv_status_on_client.trailing_metadata = &metadata_array; + out->data.recv_status_on_client.status = &status; + out->data.recv_status_on_client.status_details = &status_details; + out->data.recv_status_on_client.status_details_capacity = &details_capacity; + } + + Handle GetNodeValue() const { + NanEscapableScope(); + Handle status_obj = NanNew(); + status_obj->Set(NanNew("code"), NanNew(status)); + if (event->data.finished.details != NULL) { + status_obj->Set(NanNew("details"), String::New(status_details)); + } + status_obj->Set(NanNew("metadata"), ParseMetadata(&metadata_array)); + return NanEscapeScope(status_obj); + } + private: + grpc_metadata_array metadata_array; + grpc_status_code status; + char *status_details; + size_t details_capacity; +}; + +class ServerCloseResponseOp : public Op { + public: + Handle GetNodeValue() const { + NanEscapableScope(); + NanEscapeScope(NanNew(cancelled)); + } + + bool ParseOp(Handle value, grpc_op *out, + std::vector > *strings, + std::vector > *handles) { + out->data.recv_close_on_server.cancelled = &cancelled; + } + + private: + int cancelled; +}; + +struct tag { + tag(NanCallback *callback, std::vector > *ops, + std::vector > *handles, + std::vector > *strings) : + callback(callback), ops(ops), handles(handles), strings(strings){ + } + ~tag() { + if (strings != null) { + for (std::vector::iterator it = strings.begin(); + it != strings.end(); ++it) { + delete *it; + } + delete strings; + } + delete callback; + delete ops; + if (handles != null) { + delete handles; + } + } +}; + Call::Call(grpc_call *call) : wrapped_call(call) {} Call::~Call() { grpc_call_destroy(wrapped_call); } @@ -123,28 +415,10 @@ void Call::Init(Handle exports) { Local tpl = FunctionTemplate::New(New); tpl->SetClassName(NanNew("Call")); tpl->InstanceTemplate()->SetInternalFieldCount(1); - NanSetPrototypeTemplate(tpl, "addMetadata", - FunctionTemplate::New(AddMetadata)->GetFunction()); - NanSetPrototypeTemplate(tpl, "invoke", - FunctionTemplate::New(Invoke)->GetFunction()); - NanSetPrototypeTemplate(tpl, "serverAccept", - FunctionTemplate::New(ServerAccept)->GetFunction()); - NanSetPrototypeTemplate( - tpl, "serverEndInitialMetadata", - FunctionTemplate::New(ServerEndInitialMetadata)->GetFunction()); + NanSetPrototypeTemplate(tpl, "startBatch", + FunctionTemplate::New(StartBatch)->GetFunction()); NanSetPrototypeTemplate(tpl, "cancel", FunctionTemplate::New(Cancel)->GetFunction()); - NanSetPrototypeTemplate(tpl, "startWrite", - FunctionTemplate::New(StartWrite)->GetFunction()); - NanSetPrototypeTemplate( - tpl, "startWriteStatus", - FunctionTemplate::New(StartWriteStatus)->GetFunction()); - NanSetPrototypeTemplate(tpl, "writesDone", - FunctionTemplate::New(WritesDone)->GetFunction()); - NanSetPrototypeTemplate(tpl, "startReadMetadata", - FunctionTemplate::New(WritesDone)->GetFunction()); - NanSetPrototypeTemplate(tpl, "startRead", - FunctionTemplate::New(StartRead)->GetFunction()); NanAssignPersistent(fun_tpl, tpl); NanAssignPersistent(constructor, tpl->GetFunction()); constructor->Set(NanNew("WRITE_BUFFER_HINT"), @@ -225,211 +499,64 @@ NAN_METHOD(Call::StartBatch) { if (!args[1]->IsFunction()) { return NanThrowError("startBatch's second argument must be a callback"); } - vector *> *handles = new vector>(); - vector *strings = new vector(); - Persistent *handle; - Handle keys = args[0]->GetOwnPropertyNames(); + Call *call = ObjectWrap::Unwrap(args.This()); + std::vector > *handles = + new std::vector >(); + std::vector > *strings = + new std::vector >(); + Persistent handle; + Handle obj = args[0]->ToObject(); + Handle keys = obj->GetOwnPropertyNames(); size_t nops = keys->Length(); - grpc_op *ops = calloc(nops, sizeof(grpc_op)); - grpc_metadata_array array; - Handle server_status; - NanUtf8String *str; + grpc_op *ops = new grpc_op[nops]; + std::vector > *op_vector = new std::vector >(); for (unsigned int i = 0; i < nops; i++) { - if (!keys->Get(i)->IsUInt32()) { + Op *op; + if (!keys->Get(i)->IsUint32()) { return NanThrowError( "startBatch's first argument's keys must be integers"); } - uint32_t type = keys->Get(i)->UInt32Value(); - ops[i].op = type; + uint32_t type = keys->Get(i)->Uint32Value(); + ops[i].op = static_cast(type); switch (type) { case GRPC_OP_SEND_INITIAL_METADATA: - if (!args[0]->Get(type)->IsObject()) { - return NanThrowError("metadata must be an object"); - } - if (!CreateMetadataArray(args[0]->Get(type)->ToObject(), &array, - strings, handles)) { - return NanThrowError("failed to parse metadata"); - } - ops[i].data.send_initial_metadata.count = array.count; - ops[i].data.send_initial_metadata.metadata = array.metadata; - break + op = new SendMetadataOp(); + break; case GRPC_OP_SEND_MESSAGE: - if (!Buffer::HasInstance(args[0]->Get(type))) { - return NanThrowError("message must be a Buffer"); - } - ops[i].data.send_message = BufferToByteBuffer(args[0]->Get(type)); - handle = new Persistent(); - NanAssignPersistent(*handle, args[0]->Get(type)); - handles->push_back(handle); + op = new SendMessageOp(); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + op = new SendClientCloseOp(); break; case GRPC_OP_SEND_STATUS_FROM_SERVER: - if (!args[0]->Get(type)->IsObject()) { - return NanThrowError("server status must be an object"); - } - server_status = args[0]->Get(type)->ToObject(); - if (!server_status->Get("metadata")->IsObject()) { - return NanThrowError("status metadata must be an object"); - } - if (!server_status->Get("code")->IsUInt32()) { - return NanThrowError("status code must be a positive integer"); - } - if (!server_status->Get("details")->IsString()) { - return NanThrowError("status details must be a string"); - } - if (!CreateMetadataArray(server_status->Get("metadata")->ToObject(), - &array, strings, handles)) { - return NanThrowError("Failed to parse status metadata"); - } - ops[i].data.send_status_from_server.trailing_metadata_count = - array.count; - ops[i].data.send_status_from_server.trailing_metadata = array.metadata; - ops[i].data.send_status_from_server.status = - server_status->Get("code")->UInt32Value(); - str = new NanUtf8String(server_status->Get("details")); - strings->push_back(str); - ops[i].data.send_status_from_server.status_details = **str; + op = new SendServerStatusOp(); break; case GRPC_OP_RECV_INITIAL_METADATA: - ops[i].data.recv_initial_metadata = malloc(sizeof(grpc_metadata_array)); - grpc_metadata_array_init(ops[i].data.recv_initial_metadata); + op = new GetMetadataOp(); break; case GRPC_OP_RECV_MESSAGE: - ops[i].data.recv_message = malloc(sizeof(grpc_byte_buffer*)); + op = new ReadMessageOp(); break; case GRPC_OP_RECV_STATUS_ON_CLIENT: - ops[i].data.recv_status_on_client.trailing_metadata = - malloc(sizeof(grpc_metadata_array)); - grpc_metadata_array_init(ops[i].data.recv_status_on_client); - ops[i].data.recv_status_on_client.status = - malloc(sizeof(grpc_status_code)); - ops[i].data.recv_status_on_client.status_details = - malloc(sizeof(char *)); - ops[i].data.recv_status_on_client.status_details_capacity = - malloc(sizeof(size_t)); + op = new ClientStatusOp(); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: - ops[i].data.recv_close_on_server = malloc(sizeof(int)); + op = new ServerCloseResponseOp(); break; - + default: + return NanThrowError("Argument object had an unrecognized key"); } + op.ParseOp(obj.get(type), &ops[i], strings, handles); + op_vector.push_back(unique_ptr(op)); } -} - -NAN_METHOD(Call::AddMetadata) { - NanScope(); - if (!HasInstance(args.This())) { - return NanThrowTypeError("addMetadata can only be called on Call objects"); - } - Call *call = ObjectWrap::Unwrap(args.This()); - if (!args[0]->IsObject()) { - return NanThrowTypeError("addMetadata's first argument must be an object"); - } - Handle metadata = args[0]->ToObject(); - Handle keys(metadata->GetOwnPropertyNames()); - for (unsigned int i = 0; i < keys->Length(); i++) { - Handle current_key(keys->Get(i)->ToString()); - if (!metadata->Get(current_key)->IsArray()) { - return NanThrowTypeError( - "addMetadata's first argument's values must be arrays"); - } - NanUtf8String utf8_key(current_key); - Handle values = Local::Cast(metadata->Get(current_key)); - for (unsigned int j = 0; j < values->Length(); j++) { - Handle value = values->Get(j); - grpc_metadata metadata; - grpc_call_error error; - metadata.key = *utf8_key; - if (Buffer::HasInstance(value)) { - metadata.value = Buffer::Data(value); - metadata.value_length = Buffer::Length(value); - error = grpc_call_add_metadata_old(call->wrapped_call, &metadata, 0); - } else if (value->IsString()) { - Handle string_value = value->ToString(); - NanUtf8String utf8_value(string_value); - metadata.value = *utf8_value; - metadata.value_length = string_value->Length(); - gpr_log(GPR_DEBUG, "adding metadata: %s, %s, %d", metadata.key, - metadata.value, metadata.value_length); - error = grpc_call_add_metadata_old(call->wrapped_call, &metadata, 0); - } else { - return NanThrowTypeError( - "addMetadata values must be strings or buffers"); - } - if (error != GRPC_CALL_OK) { - return NanThrowError("addMetadata failed", error); - } - } - } - NanReturnUndefined(); -} - -NAN_METHOD(Call::Invoke) { - NanScope(); - if (!HasInstance(args.This())) { - return NanThrowTypeError("invoke can only be called on Call objects"); - } - if (!args[0]->IsFunction()) { - return NanThrowTypeError("invoke's first argument must be a function"); - } - if (!args[1]->IsFunction()) { - return NanThrowTypeError("invoke's second argument must be a function"); - } - if (!args[2]->IsUint32()) { - return NanThrowTypeError("invoke's third argument must be integer flags"); - } - Call *call = ObjectWrap::Unwrap(args.This()); - unsigned int flags = args[3]->Uint32Value(); - grpc_call_error error = grpc_call_invoke_old( - call->wrapped_call, CompletionQueueAsyncWorker::GetQueue(), - CreateTag(args[0], args.This()), CreateTag(args[1], args.This()), flags); - if (error == GRPC_CALL_OK) { - CompletionQueueAsyncWorker::Next(); - CompletionQueueAsyncWorker::Next(); - } else { - return NanThrowError("invoke failed", error); - } - NanReturnUndefined(); -} - -NAN_METHOD(Call::ServerAccept) { - NanScope(); - if (!HasInstance(args.This())) { - return NanThrowTypeError("accept can only be called on Call objects"); - } - if (!args[0]->IsFunction()) { - return NanThrowTypeError("accept's first argument must be a function"); - } - Call *call = ObjectWrap::Unwrap(args.This()); - grpc_call_error error = grpc_call_server_accept_old( - call->wrapped_call, CompletionQueueAsyncWorker::GetQueue(), - CreateTag(args[0], args.This())); - if (error == GRPC_CALL_OK) { - CompletionQueueAsyncWorker::Next(); - } else { - return NanThrowError("serverAccept failed", error); - } - NanReturnUndefined(); -} - -NAN_METHOD(Call::ServerEndInitialMetadata) { - NanScope(); - if (!HasInstance(args.This())) { - return NanThrowTypeError( - "serverEndInitialMetadata can only be called on Call objects"); - } - if (!args[0]->IsUint32()) { - return NanThrowTypeError( - "serverEndInitialMetadata's second argument must be integer flags"); - } - Call *call = ObjectWrap::Unwrap(args.This()); - unsigned int flags = args[1]->Uint32Value(); - grpc_call_error error = - grpc_call_server_end_initial_metadata_old(call->wrapped_call, flags); + grpc_call_error error = grpc_call_start_batch( + call->wrapped_call, ops, nops, new struct tag(args[1].As(), + op_vector, nops, handles, + strings)); if (error != GRPC_CALL_OK) { - return NanThrowError("serverEndInitialMetadata failed", error); + return NanThrowError("startBatch failed", error); } + CompletionQueueAsyncWorker::Next(); NanReturnUndefined(); } @@ -446,102 +573,5 @@ NAN_METHOD(Call::Cancel) { NanReturnUndefined(); } -NAN_METHOD(Call::StartWrite) { - NanScope(); - if (!HasInstance(args.This())) { - return NanThrowTypeError("startWrite can only be called on Call objects"); - } - if (!Buffer::HasInstance(args[0])) { - return NanThrowTypeError("startWrite's first argument must be a Buffer"); - } - if (!args[1]->IsFunction()) { - return NanThrowTypeError("startWrite's second argument must be a function"); - } - if (!args[2]->IsUint32()) { - return NanThrowTypeError( - "startWrite's third argument must be integer flags"); - } - Call *call = ObjectWrap::Unwrap(args.This()); - grpc_byte_buffer *buffer = BufferToByteBuffer(args[0]); - unsigned int flags = args[2]->Uint32Value(); - grpc_call_error error = grpc_call_start_write_old( - call->wrapped_call, buffer, CreateTag(args[1], args.This()), flags); - if (error == GRPC_CALL_OK) { - CompletionQueueAsyncWorker::Next(); - } else { - return NanThrowError("startWrite failed", error); - } - NanReturnUndefined(); -} - -NAN_METHOD(Call::StartWriteStatus) { - NanScope(); - if (!HasInstance(args.This())) { - return NanThrowTypeError( - "startWriteStatus can only be called on Call objects"); - } - if (!args[0]->IsUint32()) { - return NanThrowTypeError( - "startWriteStatus's first argument must be a status code"); - } - if (!args[1]->IsString()) { - return NanThrowTypeError( - "startWriteStatus's second argument must be a string"); - } - if (!args[2]->IsFunction()) { - return NanThrowTypeError( - "startWriteStatus's third argument must be a function"); - } - Call *call = ObjectWrap::Unwrap(args.This()); - NanUtf8String details(args[1]); - grpc_call_error error = grpc_call_start_write_status_old( - call->wrapped_call, (grpc_status_code)args[0]->Uint32Value(), *details, - CreateTag(args[2], args.This())); - if (error == GRPC_CALL_OK) { - CompletionQueueAsyncWorker::Next(); - } else { - return NanThrowError("startWriteStatus failed", error); - } - NanReturnUndefined(); -} - -NAN_METHOD(Call::WritesDone) { - NanScope(); - if (!HasInstance(args.This())) { - return NanThrowTypeError("writesDone can only be called on Call objects"); - } - if (!args[0]->IsFunction()) { - return NanThrowTypeError("writesDone's first argument must be a function"); - } - Call *call = ObjectWrap::Unwrap(args.This()); - grpc_call_error error = grpc_call_writes_done_old( - call->wrapped_call, CreateTag(args[0], args.This())); - if (error == GRPC_CALL_OK) { - CompletionQueueAsyncWorker::Next(); - } else { - return NanThrowError("writesDone failed", error); - } - NanReturnUndefined(); -} - -NAN_METHOD(Call::StartRead) { - NanScope(); - if (!HasInstance(args.This())) { - return NanThrowTypeError("startRead can only be called on Call objects"); - } - if (!args[0]->IsFunction()) { - return NanThrowTypeError("startRead's first argument must be a function"); - } - Call *call = ObjectWrap::Unwrap(args.This()); - grpc_call_error error = grpc_call_start_read_old( - call->wrapped_call, CreateTag(args[0], args.This())); - if (error == GRPC_CALL_OK) { - CompletionQueueAsyncWorker::Next(); - } else { - return NanThrowError("startRead failed", error); - } - NanReturnUndefined(); -} - } // namespace node } // namespace grpc diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 1924a1bf428..6ae370d02f1 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -34,6 +34,8 @@ #ifndef NET_GRPC_NODE_CALL_H_ #define NET_GRPC_NODE_CALL_H_ +#include + #include #include #include "grpc/grpc.h" @@ -43,6 +45,44 @@ namespace grpc { namespace node { +using std::unique_ptr; + +class PersistentHolder { + public: + explicit PersistentHolder(v8::Persistent persist) : persist(persist) { + } + + ~PersistentHolder() { + persist.Dispose(); + } + + private: + v8::Persistent persist; +}; + +class Op { + public: + virtual Handle GetNodeValue() const = 0; + virtual bool ParseOp(v8::Handle value, grpc_op *out, + std::vector > *strings, + std::vector > *handles) = 0; + Handle GetOpType(); + + protected: + virtual char *GetTypeString(); +}; + +struct tag { + tag(NanCallback *callback, std::vector > *ops, + std::vector > *handles, + std::vector > *strings); + ~tag(); + NanCallback *callback; + std::vector > *ops; + std::vector > *handles; + std::vector > *strings; +}; + /* Wrapper class for grpc_call structs. */ class Call : public ::node::ObjectWrap { public: @@ -60,15 +100,8 @@ class Call : public ::node::ObjectWrap { Call &operator=(const Call &); static NAN_METHOD(New); - static NAN_METHOD(AddMetadata); - static NAN_METHOD(Invoke); - static NAN_METHOD(ServerAccept); - static NAN_METHOD(ServerEndInitialMetadata); + static NAN_METHOD(StartBatch); static NAN_METHOD(Cancel); - static NAN_METHOD(StartWrite); - static NAN_METHOD(StartWriteStatus); - static NAN_METHOD(WritesDone); - static NAN_METHOD(StartRead); static v8::Persistent constructor; // Used for typechecking instances of this javascript class static v8::Persistent fun_tpl; diff --git a/src/node/ext/completion_queue_async_worker.cc b/src/node/ext/completion_queue_async_worker.cc index 8de7db66d50..bb0e39180e8 100644 --- a/src/node/ext/completion_queue_async_worker.cc +++ b/src/node/ext/completion_queue_async_worker.cc @@ -37,7 +37,6 @@ #include "grpc/grpc.h" #include "grpc/support/time.h" #include "completion_queue_async_worker.h" -#include "event.h" #include "tag.h" namespace grpc { @@ -58,6 +57,9 @@ CompletionQueueAsyncWorker::~CompletionQueueAsyncWorker() {} void CompletionQueueAsyncWorker::Execute() { result = grpc_completion_queue_next(queue, gpr_inf_future); + if (result->data.op_complete != GRPC_OP_OK) { + SetErrorMessage("The batch encountered an error"); + } } grpc_completion_queue *CompletionQueueAsyncWorker::GetQueue() { return queue; } @@ -75,14 +77,26 @@ void CompletionQueueAsyncWorker::Init(Handle exports) { void CompletionQueueAsyncWorker::HandleOKCallback() { NanScope(); - NanCallback event_callback(GetTagHandle(result->tag).As()); - Handle argv[] = {CreateEventObject(result)}; + NanCallback callback = GetTagCallback(result->tag); + Handle argv[] = {NanNull(), GetNodeValue(result->tag)}; DestroyTag(result->tag); grpc_event_finish(result); result = NULL; - event_callback.Call(1, argv); + callback.Call(2, argv); +} + +void CompletionQueueAsyncWorker::HandleErrorCallback() { + NanScope(); + NanCallback callback = GetTagCallback(result->tag); + Handle argv[] = {NanError(ErrorMessage())}; + + DestroyTag(result->tag); + grpc_event_finish(result); + result = NULL; + + callback.Call(1, argv); } } // namespace node diff --git a/src/node/ext/completion_queue_async_worker.h b/src/node/ext/completion_queue_async_worker.h index 2c928b7024f..c04a303283a 100644 --- a/src/node/ext/completion_queue_async_worker.h +++ b/src/node/ext/completion_queue_async_worker.h @@ -67,6 +67,8 @@ class CompletionQueueAsyncWorker : public NanAsyncWorker { completion_queue_next */ void HandleOKCallback(); + void HandleErrorCallback(); + private: grpc_event *result; diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index 6b8ccef9b17..c0ccf1f381c 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -31,6 +31,8 @@ * */ +#include + #include "server.h" #include @@ -49,6 +51,7 @@ namespace grpc { namespace node { +using std::unique_ptr; using v8::Arguments; using v8::Array; using v8::Boolean; @@ -67,6 +70,45 @@ using v8::Value; Persistent Server::constructor; Persistent Server::fun_tpl; +class NewCallOp : public Op { + public: + NewCallOp() { + call = NULL; + grpc_call_details_init(&details); + grpc_metadata_array_init(&request_metadata); + } + + ~NewCallOp() { + grpc_call_details_destroy(&details); + grpc_metadata_array_destroy(&details); + } + + Handle GetNodeValue() const { + NanEscapableScope(); + if (*call == NULL) { + return NanEscapeScope(NanNull()); + } + Handle obj = NanNew(); + obj->Set(NanNew("call"), Call::WrapStruct(call)); + obj->Set(NanNew("method"), NanNew(details.method)); + obj->Set(NanNew("host"), NanNew(details.host)); + obj->Set(NanNew("deadline"), + NanNew(TimespecToMilliseconds(details.deadline))); + obj->Set(NanNew("metadata"), ParseMetadata(&request_metadata)); + return NanEscapeScope(obj); + } + + bool ParseOp(Handle value, grpc_op *out, + std::vector > strings, + std::vector > handles) { + return true; + } + + grpc_call *call; + grpc_call_details details; + grpc_metadata_array request_metadata; +} + Server::Server(grpc_server *server) : wrapped_server(server) {} Server::~Server() { grpc_server_destroy(wrapped_server); } @@ -175,13 +217,16 @@ NAN_METHOD(Server::RequestCall) { return NanThrowTypeError("requestCall can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(args.This()); - grpc_call_error error = grpc_server_request_call_old( - server->wrapped_server, CreateTag(args[0], NanNull())); - if (error == GRPC_CALL_OK) { - CompletionQueueAsyncWorker::Next(); - } else { + Op *op = new NewCallOp(); + std::vector > *ops = { unique_ptr(op) }; + grpc_call_error error = grpc_server_request_call( + server->wrapped_server, &op->call, &op->details, &op->metadata, + CompletionQueueAsyncWorker::GetQueue(), + new struct tag(args[0].As(), ops, NULL, NULL)); + if (error != GRPC_CALL_OK) { return NanThrowError("requestCall failed", error); } + CompletionQueueAsyncWorker::Next(); NanReturnUndefined(); } diff --git a/src/node/ext/tag.cc b/src/node/ext/tag.cc index 4c41c3d20c6..27baa94a8ea 100644 --- a/src/node/ext/tag.cc +++ b/src/node/ext/tag.cc @@ -89,6 +89,7 @@ class OpResponse { explicit OpResponse(char *name): name(name) { } virtual Handle GetNodeValue() const = 0; + virtual bool ParseOp() = 0; Handle GetOpType() const { NanEscapableScope(); return NanEscapeScope(NanNew(name)); @@ -136,16 +137,23 @@ class MessageResponse : public OpResponse { } private: - grpc_byte_buffer **recv_message + grpc_byte_buffer **recv_message; }; +switch () { +case GRPC_RECV_CLIENT_STATUS: + op = new ClientStatusResponse; + break; +} + + class ClientStatusResponse : public OpResponse { public: - explicit ClientStatusResponse(grpc_metadata_array *metadata_array, - grpc_status_code *status, - char **status_details): - metadata_array(metadata_array), status(status), - status_details(status_details), OpResponse("status") { + explicit ClientStatusResponse(): + OpResponse("status") { + } + + bool ParseOp(Handle obj, grpc_op *out) { } Handle GetNodeValue() const { @@ -159,9 +167,9 @@ class ClientStatusResponse : public OpResponse { return NanEscapeScope(status_obj); } private: - grpc_metadata_array *metadata_array; - grpc_status_code *status; - char **status_details; + grpc_metadata_array metadata_array; + grpc_status_code status; + char *status_details; }; class ServerCloseResponse : public OpResponse { @@ -208,22 +216,35 @@ class NewCallResponse : public OpResponse { } struct tag { - tag(NanCallback *callback, std::vector *responses) : - callback(callback), repsonses(responses) { + tag(NanCallback *callback, std::vector *responses, + std::vector> *handles, + std::vector *strings) : + callback(callback), repsonses(responses), handles(handles), + strings(strings){ } ~tag() { for (std::vector::iterator it = responses->begin(); it != responses->end(); ++it) { delete *it; } + for (std::vector::iterator it = responses->begin(); + it != responses->end(); ++it) { + delete *it; + } delete callback; delete responses; + delete handles; + delete strings; } NanCallback *callback; std::vector *responses; + std::vector> *handles; + std::vector *strings; }; -void *CreateTag(Handle callback, grpc_op *ops, size_t nops) { +void *CreateTag(Handle callback, grpc_op *ops, size_t nops, + std::vector> *handles, + std::vector *strings) { NanScope(); NanCallback *cb = new NanCallback(callback); vector *responses = new vector(); @@ -264,7 +285,7 @@ void *CreateTag(Handle callback, grpc_op *ops, size_t nops) { } responses->push_back(resp); } - struct tag *tag_struct = new struct tag(cb, responses); + struct tag *tag_struct = new struct tag(cb, responses, handles, strings); return reinterpret_cast(tag_struct); } @@ -280,7 +301,7 @@ void *CreateTag(Handle callback, grpc_call **call, return reinterpret_cast(tag_struct); } -NanCallback GetCallback(void *tag) { +NanCallback GetTagCallback(void *tag) { NanEscapableScope(); struct tag *tag_struct = reinterpret_cast(tag); return NanEscapeScope(*tag_struct->callback); diff --git a/src/node/ext/tag.h b/src/node/ext/tag.h index 5c709743237..9ff8703b959 100644 --- a/src/node/ext/tag.h +++ b/src/node/ext/tag.h @@ -34,6 +34,9 @@ #ifndef NET_GRPC_NODE_TAG_H_ #define NET_GRPC_NODE_TAG_H_ +#include + + #include #include #include @@ -41,9 +44,11 @@ namespace grpc { namespace node { -/* Create a void* tag that can be passed to grpc_call_start_batch from a callback - function and an ops array */ -void *CreateTag(v8::Handle callback, grpc_op *ops, size_t nops); +/* Create a void* tag that can be passed to grpc_call_start_batch from a + callback function and an ops array */ +void *CreateTag(v8::Handle callback, grpc_op *ops, size_t nops, + std::vector > *handles, + std::vector *strings); /* Create a void* tag that can be passed to grpc_server_request_call from a callback and the various out parameters to that function */ @@ -55,7 +60,7 @@ void *CreateTag(v8::Handle callback, grpc_call **call, NanCallback GetCallback(void *tag); /* Get the combined output value from the tag */ -v8::Handle GetNodevalue(void *tag); +v8::Handle GetNodeValue(void *tag); /* Destroy the tag and all resources it is holding. It is illegal to call any of these other functions on a tag after it has been destroyed. */ From ff43c093b646cc3b9b4166a75decc0fa0e436ce9 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 9 Feb 2015 11:41:23 -0800 Subject: [PATCH 03/31] Fixed some compiler errors in call.cc --- src/node/binding.gyp | 7 ++--- src/node/ext/call.cc | 61 +++++++++++++++++++++++++++----------------- src/node/ext/call.h | 12 ++++----- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/node/binding.gyp b/src/node/binding.gyp index cf2a6acb04f..a289b9b9e8c 100644 --- a/src/node/binding.gyp +++ b/src/node/binding.gyp @@ -9,14 +9,15 @@ 'include_dirs': [ " #include +#include #include @@ -46,11 +47,12 @@ #include "completion_queue_async_worker.h" #include "timeval.h" +using std::unique_ptr; + namespace grpc { namespace node { using ::node::Buffer; -using std::unique_ptr; using v8::Arguments; using v8::Array; using v8::Exception; @@ -91,7 +93,7 @@ bool CreateMetadataArray( for (unsigned int i = 0; i < keys->Length(); i++) { Handle current_key(keys->Get(i)->ToString()); NanUtf8String *utf8_key = new NanUtf8String(current_key); - string_handles->push_back(unique_ptrpush_back(unique_ptr(utf8_key)); Handle values = Local::Cast(metadata->Get(current_key)); for (unsigned int j = 0; j < values->Length(); j++) { Handle value = values->Get(j); @@ -102,7 +104,8 @@ bool CreateMetadataArray( current->value_length = Buffer::Length(value); Persistent handle; NanAssignPersistent(handle, value); - handles->push_back(PersistentHolder(handle)); + handles->push_back(unique_ptr( + new PersistentHolder(handle))); } else if (value->IsString()) { Handle string_value = value->ToString(); NanUtf8String *utf8_value = new NanUtf8String(string_value); @@ -118,15 +121,15 @@ bool CreateMetadataArray( return true; } -Handle ParseMetadata(grpc_metadata_array *metadata_array) { +Handle ParseMetadata(const grpc_metadata_array *metadata_array) { NanEscapableScope(); grpc_metadata *metadata_elements = metadata_array->metadata; size_t length = metadata_array->count; - std::map size_map; - std::map index_map; + std::map size_map; + std::map index_map; for (unsigned int i = 0; i < length; i++) { - char *key = metadata_elements[i].key; + const char *key = metadata_elements[i].key; if (size_map.count(key)) { size_map[key] += 1; } @@ -151,13 +154,10 @@ Handle ParseMetadata(grpc_metadata_array *metadata_array) { return NanEscapeScope(metadata_object); } -class Op { - public: - Handle GetOpType() const { - NanEscapableScope(); - return NanEscapeScope(NanNew(GetTypeString())); - } -}; +Handle Op::GetOpType() const { + NanEscapableScope(); + return NanEscapeScope(NanNew(GetTypeString())); +} class SendMetadataOp : public Op { public: @@ -180,7 +180,7 @@ class SendMetadataOp : public Op { return true; } protected: - char *GetTypeString() { + std::string GetTypeString() { return "send metadata"; } }; @@ -197,12 +197,13 @@ class SendMessageOp : public Op { if (!Buffer::HasInstance(value)) { return false; } - out->.data.send_message = BufferToByteBuffer(obj->Get(type)); + out->data.send_message = BufferToByteBuffer(obj->Get(type)); NanAssignPersistent(handle, value); - handles->push_back(PersistentHolder(handle)); + handles->push_back(unique_ptr( + new PersistentHolder(handle))); } protected: - char *GetTypeString() { + std::string GetTypeString() { return "send message"; } }; @@ -219,7 +220,7 @@ class SendClientCloseOp : public Op { return true; } protected: - char *GetTypeString() { + std::string GetTypeString() { return "client close"; } }; @@ -264,7 +265,7 @@ class SendServerStatusOp : public Op { return true; } protected: - char *GetTypeString() { + std::string GetTypeString() { return "send status"; } } @@ -291,7 +292,7 @@ class GetMetadataOp : public Op { } protected: - char *GetTypeString() { + std::string GetTypeString() { return "metadata"; } @@ -311,17 +312,18 @@ class ReadMessageOp : public Op { } Handle GetNodeValue() const { NanEscapableScope(); - return NanEscapeScope(ByteBufferToBuffer(*recv_message)); + return NanEscapeScope(ByteBufferToBuffer(recv_message)); } bool ParseOp(Handle value, grpc_op *out, std::vector > *strings, std::vector > *handles) { out->data.recv_message = &recv_message; + return true; } protected: - char *GetTypeString() { + std::string GetTypeString() { return "read"; } @@ -348,6 +350,7 @@ class ClientStatusOp : public Op { out->data.recv_status_on_client.status = &status; out->data.recv_status_on_client.status_details = &status_details; out->data.recv_status_on_client.status_details_capacity = &details_capacity; + return true; } Handle GetNodeValue() const { @@ -360,6 +363,10 @@ class ClientStatusOp : public Op { status_obj->Set(NanNew("metadata"), ParseMetadata(&metadata_array)); return NanEscapeScope(status_obj); } + protected: + std::string GetTypeString() const { + return "status"; + } private: grpc_metadata_array metadata_array; grpc_status_code status; @@ -378,6 +385,12 @@ class ServerCloseResponseOp : public Op { std::vector > *strings, std::vector > *handles) { out->data.recv_close_on_server.cancelled = &cancelled; + return true; + } + + protected: + std::string GetTypeString() const { + return "cancelled"; } private: diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 6ae370d02f1..6c38877d3a8 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -49,27 +49,27 @@ using std::unique_ptr; class PersistentHolder { public: - explicit PersistentHolder(v8::Persistent persist) : persist(persist) { + explicit PersistentHolder(v8::Persistent persist) : persist(persist) { } ~PersistentHolder() { persist.Dispose(); - } +} private: - v8::Persistent persist; + v8::Persistent persist; }; class Op { public: - virtual Handle GetNodeValue() const = 0; + virtual v8::Handle GetNodeValue() const = 0; virtual bool ParseOp(v8::Handle value, grpc_op *out, std::vector > *strings, std::vector > *handles) = 0; - Handle GetOpType(); + v8::Handle GetOpType() const; protected: - virtual char *GetTypeString(); + virtual char *GetTypeString() const; }; struct tag { From 5efd50fd985cf90d8cd82c8537e26eafe7855200 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 9 Feb 2015 11:43:34 -0800 Subject: [PATCH 04/31] Fixed another compiler error --- src/node/ext/call.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 6c38877d3a8..880ce7c451e 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -69,7 +69,7 @@ class Op { v8::Handle GetOpType() const; protected: - virtual char *GetTypeString() const; + virtual std::string GetTypeString() const; }; struct tag { From 016bb50e763978b27ddf73612f65fdd84b89f478 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 9 Feb 2015 15:55:10 -0800 Subject: [PATCH 05/31] Extension module now compiles and some tests pass --- src/node/binding.gyp | 2 - src/node/ext/call.cc | 109 +++++++++------ src/node/ext/call.h | 14 +- src/node/ext/completion_queue_async_worker.cc | 4 +- src/node/ext/node_grpc.cc | 33 ----- src/node/ext/server.cc | 27 ++-- src/node/test/call_test.js | 128 +++++++----------- src/node/test/constant_test.js | 37 ----- src/node/test/end_to_end_test.js | 81 ++++++----- 9 files changed, 195 insertions(+), 240 deletions(-) diff --git a/src/node/binding.gyp b/src/node/binding.gyp index a289b9b9e8c..fb4c779f8eb 100644 --- a/src/node/binding.gyp +++ b/src/node/binding.gyp @@ -34,11 +34,9 @@ "ext/channel.cc", "ext/completion_queue_async_worker.cc", "ext/credentials.cc", - "ext/event.cc", "ext/node_grpc.cc", "ext/server.cc", "ext/server_credentials.cc", - "ext/tag.cc", "ext/timeval.cc" ], 'conditions' : [ diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 4751621c9f7..785cee8d3ef 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -55,6 +55,7 @@ namespace node { using ::node::Buffer; using v8::Arguments; using v8::Array; +using v8::Boolean; using v8::Exception; using v8::External; using v8::Function; @@ -80,6 +81,7 @@ bool CreateMetadataArray( std::vector > *string_handles, std::vector > *handles) { NanScope(); + grpc_metadata_array_init(array); Handle keys(metadata->GetOwnPropertyNames()); for (unsigned int i = 0; i < keys->Length(); i++) { Handle current_key(keys->Get(i)->ToString()); @@ -156,12 +158,12 @@ Handle ParseMetadata(const grpc_metadata_array *metadata_array) { Handle Op::GetOpType() const { NanEscapableScope(); - return NanEscapeScope(NanNew(GetTypeString())); + return NanEscapeScope(NanNew(GetTypeString())); } class SendMetadataOp : public Op { public: - Handle GetNodeValue() { + Handle GetNodeValue() const { NanEscapableScope(); return NanEscapeScope(NanTrue()); } @@ -180,14 +182,14 @@ class SendMetadataOp : public Op { return true; } protected: - std::string GetTypeString() { + std::string GetTypeString() const { return "send metadata"; } }; class SendMessageOp : public Op { public: - Handle GetNodeValue() { + Handle GetNodeValue() const { NanEscapableScope(); return NanEscapeScope(NanTrue()); } @@ -197,20 +199,22 @@ class SendMessageOp : public Op { if (!Buffer::HasInstance(value)) { return false; } - out->data.send_message = BufferToByteBuffer(obj->Get(type)); + out->data.send_message = BufferToByteBuffer(value); + Persistent handle; NanAssignPersistent(handle, value); handles->push_back(unique_ptr( new PersistentHolder(handle))); + return true; } protected: - std::string GetTypeString() { + std::string GetTypeString() const { return "send message"; } }; class SendClientCloseOp : public Op { public: - Handle GetNodeValue() { + Handle GetNodeValue() const { NanEscapableScope(); return NanEscapeScope(NanTrue()); } @@ -220,14 +224,14 @@ class SendClientCloseOp : public Op { return true; } protected: - std::string GetTypeString() { + std::string GetTypeString() const { return "client close"; } }; class SendServerStatusOp : public Op { public: - Handle GetNodeValue() { + Handle GetNodeValue() const { NanEscapableScope(); return NanEscapeScope(NanTrue()); } @@ -265,10 +269,10 @@ class SendServerStatusOp : public Op { return true; } protected: - std::string GetTypeString() { + std::string GetTypeString() const { return "send status"; } -} +}; class GetMetadataOp : public Op { public: @@ -289,10 +293,11 @@ class GetMetadataOp : public Op { std::vector > *strings, std::vector > *handles) { out->data.recv_initial_metadata = &recv_metadata; + return true; } protected: - std::string GetTypeString() { + std::string GetTypeString() const { return "metadata"; } @@ -323,7 +328,7 @@ class ReadMessageOp : public Op { } protected: - std::string GetTypeString() { + std::string GetTypeString() const { return "read"; } @@ -334,12 +339,13 @@ class ReadMessageOp : public Op { class ClientStatusOp : public Op { public: ClientStatusOp() { - grpc_metadata_array_init(&metadata); + grpc_metadata_array_init(&metadata_array); status_details = NULL; + details_capacity = 0; } ~ClientStatusOp() { - gprc_metadata_array_destroy(&metadata_array); + grpc_metadata_array_destroy(&metadata_array); gpr_free(status_details); } @@ -357,7 +363,7 @@ class ClientStatusOp : public Op { NanEscapableScope(); Handle status_obj = NanNew(); status_obj->Set(NanNew("code"), NanNew(status)); - if (event->data.finished.details != NULL) { + if (status_details != NULL) { status_obj->Set(NanNew("details"), String::New(status_details)); } status_obj->Set(NanNew("metadata"), ParseMetadata(&metadata_array)); @@ -378,7 +384,7 @@ class ServerCloseResponseOp : public Op { public: Handle GetNodeValue() const { NanEscapableScope(); - NanEscapeScope(NanNew(cancelled)); + return NanEscapeScope(NanNew(cancelled)); } bool ParseOp(Handle value, grpc_op *out, @@ -397,27 +403,43 @@ class ServerCloseResponseOp : public Op { int cancelled; }; -struct tag { - tag(NanCallback *callback, std::vector > *ops, - std::vector > *handles, - std::vector > *strings) : - callback(callback), ops(ops), handles(handles), strings(strings){ - } - ~tag() { - if (strings != null) { - for (std::vector::iterator it = strings.begin(); - it != strings.end(); ++it) { - delete *it; - } - delete strings; - } - delete callback; - delete ops; - if (handles != null) { - delete handles; - } +tag::tag(NanCallback *callback, std::vector > *ops, + std::vector > *handles, + std::vector > *strings) : + callback(callback), ops(ops), handles(handles), strings(strings){ +} +tag::~tag() { + delete callback; + delete ops; + if (handles != NULL) { + delete handles; } -}; + if (strings != NULL) { + delete strings; + } +} + +Handle GetTagNodeValue(void *tag) { + NanEscapableScope(); + struct tag *tag_struct = reinterpret_cast(tag); + Handle tag_obj = NanNew(); + for (std::vector >::iterator it = tag_struct->ops->begin(); + it != tag_struct->ops->end(); ++it) { + Op *op_ptr = it->get(); + tag_obj->Set(op_ptr->GetOpType(), op_ptr->GetNodeValue()); + } + return NanEscapeScope(tag_obj); +} + +NanCallback GetTagCallback(void *tag) { + struct tag *tag_struct = reinterpret_cast(tag); + return *tag_struct->callback; +} + +void DestroyTag(void *tag) { + struct tag *tag_struct = reinterpret_cast(tag); + delete tag_struct; +} Call::Call(grpc_call *call) : wrapped_call(call) {} @@ -559,13 +581,16 @@ NAN_METHOD(Call::StartBatch) { default: return NanThrowError("Argument object had an unrecognized key"); } - op.ParseOp(obj.get(type), &ops[i], strings, handles); - op_vector.push_back(unique_ptr(op)); + if (!op->ParseOp(obj->Get(type), &ops[i], strings, handles)) { + return NanThrowTypeError("Incorrectly typed arguments to startBatch"); + } + op_vector->push_back(unique_ptr(op)); } grpc_call_error error = grpc_call_start_batch( - call->wrapped_call, ops, nops, new struct tag(args[1].As(), - op_vector, nops, handles, - strings)); + call->wrapped_call, ops, nops, new struct tag( + new NanCallback(args[1].As()), + op_vector, handles, + strings)); if (error != GRPC_CALL_OK) { return NanThrowError("startBatch failed", error); } diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 880ce7c451e..434bcf8a635 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -35,6 +35,7 @@ #define NET_GRPC_NODE_CALL_H_ #include +#include #include #include @@ -47,9 +48,12 @@ namespace node { using std::unique_ptr; +v8::Handle ParseMetadata(const grpc_metadata_array *metadata_array); + class PersistentHolder { public: - explicit PersistentHolder(v8::Persistent persist) : persist(persist) { + explicit PersistentHolder(v8::Persistent persist) : + persist(persist) { } ~PersistentHolder() { @@ -69,7 +73,7 @@ class Op { v8::Handle GetOpType() const; protected: - virtual std::string GetTypeString() const; + virtual std::string GetTypeString() const = 0; }; struct tag { @@ -83,6 +87,12 @@ struct tag { std::vector > *strings; }; +v8::Handle GetTagNodeValue(void *tag); + +NanCallback GetTagCallback(void *tag); + +void DestroyTag(void *tag); + /* Wrapper class for grpc_call structs. */ class Call : public ::node::ObjectWrap { public: diff --git a/src/node/ext/completion_queue_async_worker.cc b/src/node/ext/completion_queue_async_worker.cc index bb0e39180e8..5c0e27e6a7f 100644 --- a/src/node/ext/completion_queue_async_worker.cc +++ b/src/node/ext/completion_queue_async_worker.cc @@ -37,7 +37,7 @@ #include "grpc/grpc.h" #include "grpc/support/time.h" #include "completion_queue_async_worker.h" -#include "tag.h" +#include "call.h" namespace grpc { namespace node { @@ -78,7 +78,7 @@ void CompletionQueueAsyncWorker::Init(Handle exports) { void CompletionQueueAsyncWorker::HandleOKCallback() { NanScope(); NanCallback callback = GetTagCallback(result->tag); - Handle argv[] = {NanNull(), GetNodeValue(result->tag)}; + Handle argv[] = {NanNull(), GetTagNodeValue(result->tag)}; DestroyTag(result->tag); grpc_event_finish(result); diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc index c9388940ad2..9b0fe82976e 100644 --- a/src/node/ext/node_grpc.cc +++ b/src/node/ext/node_grpc.cc @@ -130,37 +130,6 @@ void InitCallErrorConstants(Handle exports) { call_error->Set(NanNew("INVALID_FLAGS"), INVALID_FLAGS); } -void InitOpErrorConstants(Handle exports) { - NanScope(); - Handle op_error = Object::New(); - exports->Set(NanNew("opError"), op_error); - Handle OK(NanNew(GRPC_OP_OK)); - op_error->Set(NanNew("OK"), OK); - Handle ERROR(NanNew(GRPC_OP_ERROR)); - op_error->Set(NanNew("ERROR"), ERROR); -} - -void InitCompletionTypeConstants(Handle exports) { - NanScope(); - Handle completion_type = Object::New(); - exports->Set(NanNew("completionType"), completion_type); - Handle QUEUE_SHUTDOWN(NanNew(GRPC_QUEUE_SHUTDOWN)); - completion_type->Set(NanNew("QUEUE_SHUTDOWN"), QUEUE_SHUTDOWN); - Handle READ(NanNew(GRPC_READ)); - completion_type->Set(NanNew("READ"), READ); - Handle WRITE_ACCEPTED(NanNew(GRPC_WRITE_ACCEPTED)); - completion_type->Set(NanNew("WRITE_ACCEPTED"), WRITE_ACCEPTED); - Handle FINISH_ACCEPTED(NanNew(GRPC_FINISH_ACCEPTED)); - completion_type->Set(NanNew("FINISH_ACCEPTED"), FINISH_ACCEPTED); - Handle CLIENT_METADATA_READ( - NanNew(GRPC_CLIENT_METADATA_READ)); - completion_type->Set(NanNew("CLIENT_METADATA_READ"), CLIENT_METADATA_READ); - Handle FINISHED(NanNew(GRPC_FINISHED)); - completion_type->Set(NanNew("FINISHED"), FINISHED); - Handle SERVER_RPC_NEW(NanNew(GRPC_SERVER_RPC_NEW)); - completion_type->Set(NanNew("SERVER_RPC_NEW"), SERVER_RPC_NEW); -} - void InitOpTypeConstants(Handle exports) { NanScope(); Handle op_type = Object::New(); @@ -196,8 +165,6 @@ void init(Handle exports) { grpc_init(); InitStatusConstants(exports); InitCallErrorConstants(exports); - InitOpErrorConstants(exports); - InitCompletionTypeConstants(exports); InitOpTypeConstants(exports); grpc::node::Call::Init(exports); diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index c0ccf1f381c..75ea681fa72 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -45,8 +45,8 @@ #include "grpc/grpc_security.h" #include "call.h" #include "completion_queue_async_worker.h" -#include "tag.h" #include "server_credentials.h" +#include "timeval.h" namespace grpc { namespace node { @@ -55,6 +55,7 @@ using std::unique_ptr; using v8::Arguments; using v8::Array; using v8::Boolean; +using v8::Date; using v8::Exception; using v8::Function; using v8::FunctionTemplate; @@ -80,12 +81,12 @@ class NewCallOp : public Op { ~NewCallOp() { grpc_call_details_destroy(&details); - grpc_metadata_array_destroy(&details); + grpc_metadata_array_destroy(&request_metadata); } Handle GetNodeValue() const { NanEscapableScope(); - if (*call == NULL) { + if (call == NULL) { return NanEscapeScope(NanNull()); } Handle obj = NanNew(); @@ -99,15 +100,20 @@ class NewCallOp : public Op { } bool ParseOp(Handle value, grpc_op *out, - std::vector > strings, - std::vector > handles) { + std::vector > *strings, + std::vector > *handles) { return true; } grpc_call *call; grpc_call_details details; grpc_metadata_array request_metadata; -} + + protected: + std::string GetTypeString() const { + return "new call"; + } +}; Server::Server(grpc_server *server) : wrapped_server(server) {} @@ -217,12 +223,13 @@ NAN_METHOD(Server::RequestCall) { return NanThrowTypeError("requestCall can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(args.This()); - Op *op = new NewCallOp(); - std::vector > *ops = { unique_ptr(op) }; + NewCallOp *op = new NewCallOp(); + std::vector > *ops = new std::vector >(); + ops->push_back(unique_ptr(op)); grpc_call_error error = grpc_server_request_call( - server->wrapped_server, &op->call, &op->details, &op->metadata, + server->wrapped_server, &op->call, &op->details, &op->request_metadata, CompletionQueueAsyncWorker::GetQueue(), - new struct tag(args[0].As(), ops, NULL, NULL)); + new struct tag(new NanCallback(args[0].As()), ops, NULL, NULL)); if (error != GRPC_CALL_OK) { return NanThrowError("requestCall failed", error); } diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js index dfa9aaa1a78..e341092ff8e 100644 --- a/src/node/test/call_test.js +++ b/src/node/test/call_test.js @@ -98,104 +98,80 @@ describe('call', function() { }, TypeError); }); }); - describe('addMetadata', function() { - it('should succeed with a map from strings to string arrays', function() { + describe('startBatch', function() { + it('should fail without an object and a function', function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); - assert.doesNotThrow(function() { - call.addMetadata({'key': ['value']}); + assert.throws(function() { + call.startBatch(); }); - assert.doesNotThrow(function() { - call.addMetadata({'key1': ['value1'], 'key2': ['value2']}); + assert.throws(function() { + call.startBatch({}); + }); + assert.throws(function() { + call.startBatch(null, function(){}); }); }); - it('should succeed with a map from strings to buffer arrays', function() { + it.skip('should succeed with an empty object', function(done) { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.doesNotThrow(function() { - call.addMetadata({'key': [new Buffer('value')]}); - }); - assert.doesNotThrow(function() { - call.addMetadata({'key1': [new Buffer('value1')], - 'key2': [new Buffer('value2')]}); + call.startBatch({}, function(err) { + assert.ifError(err); + done(); + }); }); }); - it('should fail with other parameter types', function() { + }); + describe('startBatch with metadata', function() { + it('should succeed with a map of strings to string arrays', function(done) { var call = new grpc.Call(channel, 'method', getDeadline(1)); - assert.throws(function() { - call.addMetadata(); + assert.doesNotThrow(function() { + var batch = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = {'key1': ['value1'], + 'key2': ['value2']}; + call.startBatch(batch, function(err, resp) { + assert.ifError(err); + assert.deepEqual(resp, {'send metadata': true}); + done(); + }); }); - assert.throws(function() { - call.addMetadata(null); - }, TypeError); - assert.throws(function() { - call.addMetadata('value'); - }, TypeError); - assert.throws(function() { - call.addMetadata(5); - }, TypeError); }); - it('should fail if invoke was already called', function(done) { + it('should succeed with a map of strings to buffer arrays', function(done) { var call = new grpc.Call(channel, 'method', getDeadline(1)); - call.invoke(function() {}, - function() {done();}, - 0); - assert.throws(function() { - call.addMetadata({'key': ['value']}); - }, function(err) { - return err.code === grpc.callError.ALREADY_INVOKED; + assert.doesNotThrow(function() { + var batch = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = { + 'key1': [new Buffer('value1')], + 'key2': [new Buffer('value2')] + }; + call.startBatch(batch, function(err, resp) { + assert.ifError(err); + assert.deepEqual(resp, {'send metadata': true}); + done(); + }); }); - // Cancel to speed up the test - call.cancel(); }); - }); - describe('invoke', function() { - it('should fail with fewer than 3 arguments', function() { + it('should fail with other parameter types', function() { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.throws(function() { - call.invoke(); - }, TypeError); - assert.throws(function() { - call.invoke(function() {}); - }, TypeError); - assert.throws(function() { - call.invoke(function() {}, - function() {}); - }, TypeError); - }); - it('should work with 2 args and an int', function(done) { - assert.doesNotThrow(function() { - var call = new grpc.Call(channel, 'method', getDeadline(1)); - call.invoke(function() {}, - function() {done();}, - 0); - // Cancel to speed up the test - call.cancel(); + var batch = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = undefined; + call.startBatch(batch, function(){}); }); - }); - it('should reject incorrectly typed arguments', function() { - var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.throws(function() { - call.invoke(0, 0, 0); + var batch = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = null; + call.startBatch(batch, function(){}); }, TypeError); assert.throws(function() { - call.invoke(function() {}, - function() {}, 'test'); - }); - }); - }); - describe('serverAccept', function() { - it('should fail with fewer than 1 argument1', function() { - var call = new grpc.Call(channel, 'method', getDeadline(1)); - assert.throws(function() { - call.serverAccept(); + var batch = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = 'value'; + call.startBatch(batch, function(){}); }, TypeError); - }); - it('should return an error when called on a client Call', function() { - var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.throws(function() { - call.serverAccept(function() {}); - }, function(err) { - return err.code === grpc.callError.NOT_ON_CLIENT; - }); + var batch = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = 5; + call.startBatch(batch, function(){}); + }, TypeError); }); }); describe('cancel', function() { diff --git a/src/node/test/constant_test.js b/src/node/test/constant_test.js index 0138a552265..4d11e6f5272 100644 --- a/src/node/test/constant_test.js +++ b/src/node/test/constant_test.js @@ -76,31 +76,6 @@ var callErrorNames = [ 'INVALID_FLAGS' ]; -/** - * List of all op error names - * @const - * @type {Array.} - */ -var opErrorNames = [ - 'OK', - 'ERROR' -]; - -/** - * List of all completion type names - * @const - * @type {Array.} - */ -var completionTypeNames = [ - 'QUEUE_SHUTDOWN', - 'READ', - 'WRITE_ACCEPTED', - 'FINISH_ACCEPTED', - 'CLIENT_METADATA_READ', - 'FINISHED', - 'SERVER_RPC_NEW' -]; - describe('constants', function() { it('should have all of the status constants', function() { for (var i = 0; i < statusNames.length; i++) { @@ -114,16 +89,4 @@ describe('constants', function() { 'call error missing: ' + callErrorNames[i]); } }); - it('should have all of the op errors', function() { - for (var i = 0; i < opErrorNames.length; i++) { - assert(grpc.opError.hasOwnProperty(opErrorNames[i]), - 'op error missing: ' + opErrorNames[i]); - } - }); - it('should have all of the completion types', function() { - for (var i = 0; i < completionTypeNames.length; i++) { - assert(grpc.completionType.hasOwnProperty(completionTypeNames[i]), - 'completion type missing: ' + completionTypeNames[i]); - } - }); }); diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js index 1f53df23f3b..e0ad9a88749 100644 --- a/src/node/test/end_to_end_test.js +++ b/src/node/test/end_to_end_test.js @@ -110,52 +110,61 @@ describe('end-to-end', function() { assert.strictEqual(event.data, grpc.opError.OK); }); }); - it('should successfully send and receive metadata', function(complete) { - var done = multiDone(complete, 2); + it.only('should successfully send and receive metadata', function(done) { + debugger; var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 3); var status_text = 'xyz'; var call = new grpc.Call(channel, 'dummy_method', deadline); - call.addMetadata({'client_key': ['client_value']}); - call.invoke(function(event) { - assert.strictEqual(event.type, - grpc.completionType.CLIENT_METADATA_READ); - assert.strictEqual(event.data.server_key[0].toString(), 'server_value'); - },function(event) { - assert.strictEqual(event.type, grpc.completionType.FINISHED); - var status = event.data; - assert.strictEqual(status.code, grpc.status.OK); - assert.strictEqual(status.details, status_text); + var client_batch = {}; + client_batch[grpc.opType.SEND_INITIAL_METADATA] = { + 'client_key': ['client_value'] + }; + client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(client_batch, function(err, response) { + assert.ifError(err); + assert.deepEqual(response, { + 'send metadata': true, + 'client close': true, + 'metadata': {'server_key': [new Buffer('server_value')]}, + 'status': { + 'code': grpc.status.OK, + 'details': status_text + } + }); done(); - }, 0); + }); - server.requestCall(function(event) { - assert.strictEqual(event.type, grpc.completionType.SERVER_RPC_NEW); - assert.strictEqual(event.data.metadata.client_key[0].toString(), + server.requestCall(function(err, call_details) { + var new_call = call_details['new call']; + assert.notEqual(new_call, null); + assert.strictEqual(new_call.metadata.client_key[0].toString(), 'client_value'); - var server_call = event.call; + var server_call = new_call.call; assert.notEqual(server_call, null); - server_call.serverAccept(function(event) { - assert.strictEqual(event.type, grpc.completionType.FINISHED); - }, 0); - server_call.addMetadata({'server_key': ['server_value']}); - server_call.serverEndInitialMetadata(0); - server_call.startWriteStatus( - grpc.status.OK, - status_text, - function(event) { - assert.strictEqual(event.type, - grpc.completionType.FINISH_ACCEPTED); - assert.strictEqual(event.data, grpc.opError.OK); - done(); - }); - }); - call.writesDone(function(event) { - assert.strictEqual(event.type, - grpc.completionType.FINISH_ACCEPTED); - assert.strictEqual(event.data, grpc.opError.OK); + var server_batch = {}; + server_batch[grpc.opType.SEND_INITIAL_METADATA] = { + 'server_key': ['server_value'] + }; + server_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { + 'metadata': {}, + 'code': grpc.status.OK, + 'details': status_text + }; + server_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; + console.log(server_batch); + server_call.startBatch(server_batch, function(err, response) { + assert.ifError(err); + assert.deepEqual(response, { + 'send metadata': true, + 'send status': true, + 'cancelled': false + }); + }); }); }); it('should send and receive data without error', function(complete) { From cd0b90621dd2b404d93b169836f02b1694b1f45c Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 10 Feb 2015 09:16:49 -0800 Subject: [PATCH 06/31] Fixed end-to-end tests for new changes --- src/node/ext/call.cc | 2 +- src/node/test/end_to_end_test.js | 193 +++++++++++++++---------------- 2 files changed, 95 insertions(+), 100 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 785cee8d3ef..9a6359fe448 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -238,7 +238,7 @@ class SendServerStatusOp : public Op { bool ParseOp(Handle value, grpc_op *out, std::vector > *strings, std::vector > *handles) { - if (value->IsObject()) { + if (!value->IsObject()) { return false; } Handle server_status = value->ToObject(); diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js index e0ad9a88749..f1277ff207a 100644 --- a/src/node/test/end_to_end_test.js +++ b/src/node/test/end_to_end_test.js @@ -75,43 +75,51 @@ describe('end-to-end', function() { var call = new grpc.Call(channel, 'dummy_method', deadline); - call.invoke(function(event) { - assert.strictEqual(event.type, - grpc.completionType.CLIENT_METADATA_READ); - },function(event) { - assert.strictEqual(event.type, grpc.completionType.FINISHED); - var status = event.data; - assert.strictEqual(status.code, grpc.status.OK); - assert.strictEqual(status.details, status_text); + var client_batch = {}; + client_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(client_batch, function(err, response) { + assert.ifError(err); + assert.deepEqual(response, { + 'send metadata': true, + 'client close': true, + 'status': { + 'code': grpc.status.OK, + 'details': status_text, + 'metadata': {} + } + }); done(); - }, 0); + }); - server.requestCall(function(event) { - assert.strictEqual(event.type, grpc.completionType.SERVER_RPC_NEW); - var server_call = event.call; + server.requestCall(function(err, call_details) { + var new_call = call_details['new call']; + assert.notEqual(new_call, null); + var server_call = new_call.call; assert.notEqual(server_call, null); - server_call.serverAccept(function(event) { - assert.strictEqual(event.type, grpc.completionType.FINISHED); - }, 0); - server_call.serverEndInitialMetadata(0); - server_call.startWriteStatus( - grpc.status.OK, - status_text, - function(event) { - assert.strictEqual(event.type, - grpc.completionType.FINISH_ACCEPTED); - assert.strictEqual(event.data, grpc.opError.OK); - done(); - }); - }); - call.writesDone(function(event) { - assert.strictEqual(event.type, - grpc.completionType.FINISH_ACCEPTED); - assert.strictEqual(event.data, grpc.opError.OK); + var server_batch = {}; + server_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + server_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { + 'metadata': {}, + 'code': grpc.status.OK, + 'details': status_text + }; + server_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; + server_call.startBatch(server_batch, function(err, response) { + assert.ifError(err); + assert.deepEqual(response, { + 'send metadata': true, + 'send status': true, + 'cancelled': false + }); + done(); + }); }); }); - it.only('should successfully send and receive metadata', function(done) { - debugger; + it('should successfully send and receive metadata', function(complete) { + var done = multiDone(complete, 2); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 3); var status_text = 'xyz'; @@ -127,15 +135,14 @@ describe('end-to-end', function() { client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_batch, function(err, response) { assert.ifError(err); - assert.deepEqual(response, { - 'send metadata': true, - 'client close': true, - 'metadata': {'server_key': [new Buffer('server_value')]}, - 'status': { - 'code': grpc.status.OK, - 'details': status_text - } - }); + assert(response['send metadata']); + assert(response['client close']); + assert(response.hasOwnProperty('metadata')); + assert.strictEqual(response.metadata.server_key.toString(), + 'server_value'); + assert.deepEqual(response.status, {'code': grpc.status.OK, + 'details': status_text, + 'metadata': {}}); done(); }); @@ -156,7 +163,6 @@ describe('end-to-end', function() { 'details': status_text }; server_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; - console.log(server_batch); server_call.startBatch(server_batch, function(err, response) { assert.ifError(err); assert.deepEqual(response, { @@ -164,77 +170,66 @@ describe('end-to-end', function() { 'send status': true, 'cancelled': false }); + done(); }); }); }); - it('should send and receive data without error', function(complete) { + it.only('should send and receive data without error', function(complete) { var req_text = 'client_request'; var reply_text = 'server_response'; - var done = multiDone(complete, 6); + var done = multiDone(complete, 2); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 3); var status_text = 'success'; var call = new grpc.Call(channel, 'dummy_method', deadline); - call.invoke(function(event) { - assert.strictEqual(event.type, - grpc.completionType.CLIENT_METADATA_READ); - done(); - },function(event) { - assert.strictEqual(event.type, grpc.completionType.FINISHED); - var status = event.data; - assert.strictEqual(status.code, grpc.status.OK); - assert.strictEqual(status.details, status_text); - done(); - }, 0); - call.startWrite( - new Buffer(req_text), - function(event) { - assert.strictEqual(event.type, - grpc.completionType.WRITE_ACCEPTED); - assert.strictEqual(event.data, grpc.opError.OK); - call.writesDone(function(event) { - assert.strictEqual(event.type, - grpc.completionType.FINISH_ACCEPTED); - assert.strictEqual(event.data, grpc.opError.OK); - done(); - }); - }, 0); - call.startRead(function(event) { - assert.strictEqual(event.type, grpc.completionType.READ); - assert.strictEqual(event.data.toString(), reply_text); + var client_batch = {}; + client_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + client_batch[grpc.opType.SEND_MESSAGE] = new Buffer(req_text); + client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + client_batch[grpc.opType.RECV_MESSAGE] = true; + client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(client_batch, function(err, response) { + assert.ifError(err); + assert(response['send metadata']); + assert(response['client close']); + assert.deepEqual(response.metadata, {}); + assert(response['send message']); + assert.strictEqual(response.read.toString(), reply_text); + assert.deepEqual(response.status, {'code': grpc.status.OK, + 'details': status_text, + 'metadata': {}}); + console.log("OK status"); done(); }); - server.requestCall(function(event) { - assert.strictEqual(event.type, grpc.completionType.SERVER_RPC_NEW); - var server_call = event.call; + + server.requestCall(function(err, call_details) { + var new_call = call_details['new call']; + assert.notEqual(new_call, null); + var server_call = new_call.call; assert.notEqual(server_call, null); - server_call.serverAccept(function(event) { - assert.strictEqual(event.type, grpc.completionType.FINISHED); - done(); - }); - server_call.serverEndInitialMetadata(0); - server_call.startRead(function(event) { - assert.strictEqual(event.type, grpc.completionType.READ); - assert.strictEqual(event.data.toString(), req_text); - server_call.startWrite( - new Buffer(reply_text), - function(event) { - assert.strictEqual(event.type, - grpc.completionType.WRITE_ACCEPTED); - assert.strictEqual(event.data, - grpc.opError.OK); - server_call.startWriteStatus( - grpc.status.OK, - status_text, - function(event) { - assert.strictEqual(event.type, - grpc.completionType.FINISH_ACCEPTED); - assert.strictEqual(event.data, grpc.opError.OK); - done(); - }); - }, 0); + var server_batch = {}; + server_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + server_batch[grpc.opType.RECV_MESSAGE] = true; + server_call.startBatch(server_batch, function(err, response) { + assert.ifError(err); + assert(response['send metadata']); + assert.strictEqual(response.read.toString(), req_text); + var response_batch = {}; + response_batch[grpc.opType.SEND_MESSAGE] = new Buffer(reply_text); + response_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { + 'metadata': {}, + 'code': grpc.status.OK, + 'details': status_text + }; + response_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; + server_call.startBatch(response_batch, function(err, response) { + assert(response['send status']); + //assert(!response['cancelled']); + done(); + }); }); }); }); From 77659065216cb3756711dd6c490a202faa133c83 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 11 Feb 2015 09:26:25 -0800 Subject: [PATCH 07/31] More end to end test debugging --- src/node/ext/call.cc | 19 +++++++++++++------ src/node/ext/call.h | 4 ++-- src/node/ext/completion_queue_async_worker.cc | 11 +++++++---- src/node/ext/server.cc | 2 ++ src/node/test/end_to_end_test.js | 17 +++++++++-------- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 9a6359fe448..3452af943d2 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -201,6 +201,8 @@ class SendMessageOp : public Op { } out->data.send_message = BufferToByteBuffer(value); Persistent handle; + Handle temp = NanNew(); + NanAssignPersistent(handle, temp); NanAssignPersistent(handle, value); handles->push_back(unique_ptr( new PersistentHolder(handle))); @@ -441,9 +443,14 @@ void DestroyTag(void *tag) { delete tag_struct; } -Call::Call(grpc_call *call) : wrapped_call(call) {} +Call::Call(grpc_call *call) : wrapped_call(call) { + gpr_log(GPR_DEBUG, "Constructing call, this: %p, pointer: %p", this, call); +} -Call::~Call() { grpc_call_destroy(wrapped_call); } +Call::~Call() { + gpr_log(GPR_DEBUG, "Destructing call, this: %p, pointer: %p", this, wrapped_call); + grpc_call_destroy(wrapped_call); +} void Call::Init(Handle exports) { NanScope(); @@ -473,6 +480,7 @@ Handle Call::WrapStruct(grpc_call *call) { if (call == NULL) { return NanEscapeScope(NanNull()); } + gpr_log(GPR_DEBUG, "Wrapping call: %p", call); const int argc = 1; Handle argv[argc] = {External::New(reinterpret_cast(call))}; return NanEscapeScope(constructor->NewInstance(argc, argv)); @@ -534,12 +542,13 @@ NAN_METHOD(Call::StartBatch) { if (!args[1]->IsFunction()) { return NanThrowError("startBatch's second argument must be a callback"); } + Handle callback_func = args[1].As(); + NanCallback *callback = new NanCallback(callback_func); Call *call = ObjectWrap::Unwrap(args.This()); std::vector > *handles = new std::vector >(); std::vector > *strings = new std::vector >(); - Persistent handle; Handle obj = args[0]->ToObject(); Handle keys = obj->GetOwnPropertyNames(); size_t nops = keys->Length(); @@ -588,9 +597,7 @@ NAN_METHOD(Call::StartBatch) { } grpc_call_error error = grpc_call_start_batch( call->wrapped_call, ops, nops, new struct tag( - new NanCallback(args[1].As()), - op_vector, handles, - strings)); + callback, op_vector, handles, strings)); if (error != GRPC_CALL_OK) { return NanThrowError("startBatch failed", error); } diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 434bcf8a635..b8792713da8 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -57,8 +57,8 @@ class PersistentHolder { } ~PersistentHolder() { - persist.Dispose(); -} + NanDisposePersistent(persist); + } private: v8::Persistent persist; diff --git a/src/node/ext/completion_queue_async_worker.cc b/src/node/ext/completion_queue_async_worker.cc index 5c0e27e6a7f..dbacdf034ed 100644 --- a/src/node/ext/completion_queue_async_worker.cc +++ b/src/node/ext/completion_queue_async_worker.cc @@ -35,6 +35,7 @@ #include #include "grpc/grpc.h" +#include "grpc/support/log.h" #include "grpc/support/time.h" #include "completion_queue_async_worker.h" #include "call.h" @@ -57,6 +58,7 @@ CompletionQueueAsyncWorker::~CompletionQueueAsyncWorker() {} void CompletionQueueAsyncWorker::Execute() { result = grpc_completion_queue_next(queue, gpr_inf_future); + gpr_log(GPR_DEBUG, "Handling response on call %p", result->call); if (result->data.op_complete != GRPC_OP_OK) { SetErrorMessage("The batch encountered an error"); } @@ -77,14 +79,15 @@ void CompletionQueueAsyncWorker::Init(Handle exports) { void CompletionQueueAsyncWorker::HandleOKCallback() { NanScope(); + gpr_log(GPR_DEBUG, "Handling response on call %p", result->call); NanCallback callback = GetTagCallback(result->tag); Handle argv[] = {NanNull(), GetTagNodeValue(result->tag)}; + callback.Call(2, argv); + DestroyTag(result->tag); grpc_event_finish(result); result = NULL; - - callback.Call(2, argv); } void CompletionQueueAsyncWorker::HandleErrorCallback() { @@ -92,11 +95,11 @@ void CompletionQueueAsyncWorker::HandleErrorCallback() { NanCallback callback = GetTagCallback(result->tag); Handle argv[] = {NanError(ErrorMessage())}; + callback.Call(1, argv); + DestroyTag(result->tag); grpc_event_finish(result); result = NULL; - - callback.Call(1, argv); } } // namespace node diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index 75ea681fa72..93aa9ec44d4 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -43,6 +43,7 @@ #include #include "grpc/grpc.h" #include "grpc/grpc_security.h" +#include "grpc/support/log.h" #include "call.h" #include "completion_queue_async_worker.h" #include "server_credentials.h" @@ -90,6 +91,7 @@ class NewCallOp : public Op { return NanEscapeScope(NanNull()); } Handle obj = NanNew(); + gpr_log(GPR_DEBUG, "Wrapping server call: %p", call); obj->Set(NanNew("call"), Call::WrapStruct(call)); obj->Set(NanNew("method"), NanNew(details.method)); obj->Set(NanNew("host"), NanNew(details.host)); diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js index f1277ff207a..d43446084cc 100644 --- a/src/node/test/end_to_end_test.js +++ b/src/node/test/end_to_end_test.js @@ -67,14 +67,14 @@ describe('end-to-end', function() { after(function() { server.shutdown(); }); - it('should start and end a request without error', function(complete) { + it.skip('should start and end a request without error', function(complete) { var done = multiDone(complete, 2); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 3); var status_text = 'xyz'; var call = new grpc.Call(channel, 'dummy_method', - deadline); + Infinity); var client_batch = {}; client_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; @@ -85,6 +85,7 @@ describe('end-to-end', function() { assert.deepEqual(response, { 'send metadata': true, 'client close': true, + 'metadata': {}, 'status': { 'code': grpc.status.OK, 'details': status_text, @@ -125,7 +126,7 @@ describe('end-to-end', function() { var status_text = 'xyz'; var call = new grpc.Call(channel, 'dummy_method', - deadline); + Infinity); var client_batch = {}; client_batch[grpc.opType.SEND_INITIAL_METADATA] = { 'client_key': ['client_value'] @@ -138,7 +139,7 @@ describe('end-to-end', function() { assert(response['send metadata']); assert(response['client close']); assert(response.hasOwnProperty('metadata')); - assert.strictEqual(response.metadata.server_key.toString(), + assert.strictEqual(response.metadata.server_key[0].toString(), 'server_value'); assert.deepEqual(response.status, {'code': grpc.status.OK, 'details': status_text, @@ -147,6 +148,7 @@ describe('end-to-end', function() { }); server.requestCall(function(err, call_details) { + console.log("Server received new call"); var new_call = call_details['new call']; assert.notEqual(new_call, null); assert.strictEqual(new_call.metadata.client_key[0].toString(), @@ -174,7 +176,7 @@ describe('end-to-end', function() { }); }); }); - it.only('should send and receive data without error', function(complete) { + it('should send and receive data without error', function(complete) { var req_text = 'client_request'; var reply_text = 'server_response'; var done = multiDone(complete, 2); @@ -183,7 +185,7 @@ describe('end-to-end', function() { var status_text = 'success'; var call = new grpc.Call(channel, 'dummy_method', - deadline); + Infinity); var client_batch = {}; client_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; client_batch[grpc.opType.SEND_MESSAGE] = new Buffer(req_text); @@ -201,7 +203,6 @@ describe('end-to-end', function() { assert.deepEqual(response.status, {'code': grpc.status.OK, 'details': status_text, 'metadata': {}}); - console.log("OK status"); done(); }); @@ -227,7 +228,7 @@ describe('end-to-end', function() { response_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; server_call.startBatch(response_batch, function(err, response) { assert(response['send status']); - //assert(!response['cancelled']); + assert(!response['cancelled']); done(); }); }); From 1578c6a4ab91aed70b4c2c271249ec82e2f95d7f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 11 Feb 2015 16:19:55 -0800 Subject: [PATCH 08/31] Fixed end to end tests --- src/node/ext/call.cc | 8 ++++++-- src/node/ext/call.h | 2 +- src/node/ext/completion_queue_async_worker.cc | 8 ++++---- src/node/test/call_test.js | 2 +- src/node/test/end_to_end_test.js | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 3452af943d2..cdc34b52a74 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -98,6 +98,9 @@ bool CreateMetadataArray( string_handles->push_back(unique_ptr(utf8_key)); Handle values = Local::Cast(metadata->Get(current_key)); for (unsigned int j = 0; j < values->Length(); j++) { + if (array->count >= array->capacity) { + gpr_log(GPR_ERROR, "Metadata array grew past capacity"); + } Handle value = values->Get(j); grpc_metadata *current = &array->metadata[array->count]; current->key = **utf8_key; @@ -433,9 +436,9 @@ Handle GetTagNodeValue(void *tag) { return NanEscapeScope(tag_obj); } -NanCallback GetTagCallback(void *tag) { +NanCallback *GetTagCallback(void *tag) { struct tag *tag_struct = reinterpret_cast(tag); - return *tag_struct->callback; + return tag_struct->callback; } void DestroyTag(void *tag) { @@ -598,6 +601,7 @@ NAN_METHOD(Call::StartBatch) { grpc_call_error error = grpc_call_start_batch( call->wrapped_call, ops, nops, new struct tag( callback, op_vector, handles, strings)); + delete ops; if (error != GRPC_CALL_OK) { return NanThrowError("startBatch failed", error); } diff --git a/src/node/ext/call.h b/src/node/ext/call.h index b8792713da8..f443a04637f 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -89,7 +89,7 @@ struct tag { v8::Handle GetTagNodeValue(void *tag); -NanCallback GetTagCallback(void *tag); +NanCallback *GetTagCallback(void *tag); void DestroyTag(void *tag); diff --git a/src/node/ext/completion_queue_async_worker.cc b/src/node/ext/completion_queue_async_worker.cc index dbacdf034ed..3c32b07ca33 100644 --- a/src/node/ext/completion_queue_async_worker.cc +++ b/src/node/ext/completion_queue_async_worker.cc @@ -80,10 +80,10 @@ void CompletionQueueAsyncWorker::Init(Handle exports) { void CompletionQueueAsyncWorker::HandleOKCallback() { NanScope(); gpr_log(GPR_DEBUG, "Handling response on call %p", result->call); - NanCallback callback = GetTagCallback(result->tag); + NanCallback *callback = GetTagCallback(result->tag); Handle argv[] = {NanNull(), GetTagNodeValue(result->tag)}; - callback.Call(2, argv); + callback->Call(2, argv); DestroyTag(result->tag); grpc_event_finish(result); @@ -92,10 +92,10 @@ void CompletionQueueAsyncWorker::HandleOKCallback() { void CompletionQueueAsyncWorker::HandleErrorCallback() { NanScope(); - NanCallback callback = GetTagCallback(result->tag); + NanCallback *callback = GetTagCallback(result->tag); Handle argv[] = {NanError(ErrorMessage())}; - callback.Call(1, argv); + callback->Call(1, argv); DestroyTag(result->tag); grpc_event_finish(result); diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js index e341092ff8e..1cbfc2280ce 100644 --- a/src/node/test/call_test.js +++ b/src/node/test/call_test.js @@ -1,6 +1,6 @@ /* * - * Copyright 2014, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js index d43446084cc..34ce2500f6c 100644 --- a/src/node/test/end_to_end_test.js +++ b/src/node/test/end_to_end_test.js @@ -67,7 +67,7 @@ describe('end-to-end', function() { after(function() { server.shutdown(); }); - it.skip('should start and end a request without error', function(complete) { + it('should start and end a request without error', function(complete) { var done = multiDone(complete, 2); var deadline = new Date(); deadline.setSeconds(deadline.getSeconds() + 3); From 63056a694d154b9b19e25b8e4352e81eba2e30fb Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 11 Feb 2015 17:29:09 -0800 Subject: [PATCH 09/31] Removed extra extension files --- src/node/ext/event.cc | 173 ---------------------- src/node/ext/event.h | 48 ------- src/node/ext/tag.cc | 325 ------------------------------------------ src/node/ext/tag.h | 72 ---------- 4 files changed, 618 deletions(-) delete mode 100644 src/node/ext/event.cc delete mode 100644 src/node/ext/event.h delete mode 100644 src/node/ext/tag.cc delete mode 100644 src/node/ext/tag.h diff --git a/src/node/ext/event.cc b/src/node/ext/event.cc deleted file mode 100644 index d59b68fb404..00000000000 --- a/src/node/ext/event.cc +++ /dev/null @@ -1,173 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include - -#include -#include -#include "grpc/grpc.h" -#include "byte_buffer.h" -#include "call.h" -#include "event.h" -#include "tag.h" -#include "timeval.h" - -namespace grpc { -namespace node { - -using ::node::Buffer; -using v8::Array; -using v8::Date; -using v8::Handle; -using v8::HandleScope; -using v8::Number; -using v8::Object; -using v8::Persistent; -using v8::String; -using v8::Value; - -Handle ParseMetadata(grpc_metadata *metadata_elements, size_t length) { - NanEscapableScope(); - std::map size_map; - std::map index_map; - - for (unsigned int i = 0; i < length; i++) { - const char *key = metadata_elements[i].key; - if (size_map.count(key)) { - size_map[key] += 1; - } - index_map[key] = 0; - } - Handle metadata_object = NanNew(); - for (unsigned int i = 0; i < length; i++) { - grpc_metadata* elem = &metadata_elements[i]; - Handle key_string = String::New(elem->key); - Handle array; - if (metadata_object->Has(key_string)) { - array = Handle::Cast(metadata_object->Get(key_string)); - } else { - array = NanNew(size_map[elem->key]); - metadata_object->Set(key_string, array); - } - array->Set(index_map[elem->key], - MakeFastBuffer( - NanNewBufferHandle(elem->value, elem->value_length))); - index_map[elem->key] += 1; - } - return NanEscapeScope(metadata_object); -} - -Handle GetEventData(grpc_event *event) { - NanEscapableScope(); - size_t count; - grpc_metadata *items; - Handle metadata; - Handle status; - Handle rpc_new; - switch (event->type) { - case GRPC_READ: - return NanEscapeScope(ByteBufferToBuffer(event->data.read)); - case GRPC_WRITE_ACCEPTED: - return NanEscapeScope(NanNew(event->data.write_accepted)); - case GRPC_FINISH_ACCEPTED: - return NanEscapeScope(NanNew(event->data.finish_accepted)); - case GRPC_CLIENT_METADATA_READ: - count = event->data.client_metadata_read.count; - items = event->data.client_metadata_read.elements; - return NanEscapeScope(ParseMetadata(items, count)); - case GRPC_FINISHED: - status = NanNew(); - status->Set(NanNew("code"), NanNew(event->data.finished.status)); - if (event->data.finished.details != NULL) { - status->Set(NanNew("details"), - String::New(event->data.finished.details)); - } - count = event->data.finished.metadata_count; - items = event->data.finished.metadata_elements; - status->Set(NanNew("metadata"), ParseMetadata(items, count)); - return NanEscapeScope(status); - case GRPC_SERVER_RPC_NEW: - rpc_new = NanNew(); - if (event->data.server_rpc_new.method == NULL) { - return NanEscapeScope(NanNull()); - } - rpc_new->Set( - NanNew("method"), - NanNew(event->data.server_rpc_new.method)); - rpc_new->Set( - NanNew("host"), - NanNew(event->data.server_rpc_new.host)); - rpc_new->Set(NanNew("absolute_deadline"), - NanNew(TimespecToMilliseconds( - event->data.server_rpc_new.deadline))); - count = event->data.server_rpc_new.metadata_count; - items = event->data.server_rpc_new.metadata_elements; - metadata = NanNew(static_cast(count)); - for (unsigned int i = 0; i < count; i++) { - Handle item_obj = Object::New(); - item_obj->Set(NanNew("key"), - NanNew(items[i].key)); - item_obj->Set( - NanNew("value"), - NanNew(items[i].value, static_cast(items[i].value_length))); - metadata->Set(i, item_obj); - } - rpc_new->Set(NanNew("metadata"), ParseMetadata(items, count)); - return NanEscapeScope(rpc_new); - default: - return NanEscapeScope(NanNull()); - } -} - -Handle CreateEventObject(grpc_event *event) { - NanEscapableScope(); - if (event == NULL) { - return NanEscapeScope(NanNull()); - } - Handle event_obj = NanNew(); - Handle call; - if (TagHasCall(event->tag)) { - call = TagGetCall(event->tag); - } else { - call = Call::WrapStruct(event->call); - } - event_obj->Set(NanNew("call"), call); - event_obj->Set(NanNew("type"), - NanNew(event->type)); - event_obj->Set(NanNew("data"), GetEventData(event)); - - return NanEscapeScope(event_obj); -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/event.h b/src/node/ext/event.h deleted file mode 100644 index e06d8f0168d..00000000000 --- a/src/node/ext/event.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef NET_GRPC_NODE_EVENT_H_ -#define NET_GRPC_NODE_EVENT_H_ - -#include -#include "grpc/grpc.h" - -namespace grpc { -namespace node { - -v8::Handle CreateEventObject(grpc_event *event); - -} // namespace node -} // namespace grpc - -#endif // NET_GRPC_NODE_EVENT_H_ diff --git a/src/node/ext/tag.cc b/src/node/ext/tag.cc deleted file mode 100644 index 27baa94a8ea..00000000000 --- a/src/node/ext/tag.cc +++ /dev/null @@ -1,325 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -#include - -#include -#include -#include -#include -#include "tag.h" -#include "call.h" - -namespace grpc { -namespace node { - -using v8::Boolean; -using v8::Function; -using v8::Handle; -using v8::HandleScope; -using v8::Persistent; -using v8::Value; - -Handle ParseMetadata(grpc_metadata_array *metadata_array) { - NanEscapableScope(); - grpc_metadata *metadata_elements = metadata_array->metadata; - size_t length = metadata_array->count; - std::map size_map; - std::map index_map; - - for (unsigned int i = 0; i < length; i++) { - char *key = metadata_elements[i].key; - if (size_map.count(key)) { - size_map[key] += 1; - } - index_map[key] = 0; - } - Handle metadata_object = NanNew(); - for (unsigned int i = 0; i < length; i++) { - grpc_metadata* elem = &metadata_elements[i]; - Handle key_string = String::New(elem->key); - Handle array; - if (metadata_object->Has(key_string)) { - array = Handle::Cast(metadata_object->Get(key_string)); - } else { - array = NanNew(size_map[elem->key]); - metadata_object->Set(key_string, array); - } - array->Set(index_map[elem->key], - MakeFastBuffer( - NanNewBufferHandle(elem->value, elem->value_length))); - index_map[elem->key] += 1; - } - return NanEscapeScope(metadata_object); -} - -class OpResponse { - public: - explicit OpResponse(char *name): name(name) { - } - virtual Handle GetNodeValue() const = 0; - virtual bool ParseOp() = 0; - Handle GetOpType() const { - NanEscapableScope(); - return NanEscapeScope(NanNew(name)); - } - - private: - char *name; -}; - -class SendResponse : public OpResponse { - public: - explicit SendResponse(char *name): OpResponse(name) { - } - - Handle GetNodeValue() { - NanEscapableScope(); - return NanEscapeScope(NanTrue()); - } -} - -class MetadataResponse : public OpResponse { - public: - explicit MetadataResponse(grpc_metadata_array *recv_metadata): - recv_metadata(recv_metadata), OpResponse("metadata") { - } - - Handle GetNodeValue() const { - NanEscapableScope(); - return NanEscapeScope(ParseMetadata(recv_metadata)); - } - - private: - grpc_metadata_array *recv_metadata; -}; - -class MessageResponse : public OpResponse { - public: - explicit MessageResponse(grpc_byte_buffer **recv_message): - recv_message(recv_message), OpResponse("read") { - } - - Handle GetNodeValue() const { - NanEscapableScope(); - return NanEscapeScope(ByteBufferToBuffer(*recv_message)); - } - - private: - grpc_byte_buffer **recv_message; -}; - -switch () { -case GRPC_RECV_CLIENT_STATUS: - op = new ClientStatusResponse; - break; -} - - -class ClientStatusResponse : public OpResponse { - public: - explicit ClientStatusResponse(): - OpResponse("status") { - } - - bool ParseOp(Handle obj, grpc_op *out) { - } - - Handle GetNodeValue() const { - NanEscapableScope(); - Handle status_obj = NanNew(); - status_obj->Set(NanNew("code"), NanNew(*status)); - if (event->data.finished.details != NULL) { - status_obj->Set(NanNew("details"), String::New(*status_details)); - } - status_obj->Set(NanNew("metadata"), ParseMetadata(metadata_array)); - return NanEscapeScope(status_obj); - } - private: - grpc_metadata_array metadata_array; - grpc_status_code status; - char *status_details; -}; - -class ServerCloseResponse : public OpResponse { - public: - explicit ServerCloseResponse(int *cancelled): cancelled(cancelled), - OpResponse("cancelled") { - } - - Handle GetNodeValue() const { - NanEscapableScope(); - NanEscapeScope(NanNew(*cancelled)); - } - - private: - int *cancelled; -}; - -class NewCallResponse : public OpResponse { - public: - explicit NewCallResponse(grpc_call **call, grpc_call_details *details, - grpc_metadata_array *request_metadata) : - call(call), details(details), request_metadata(request_metadata), - OpResponse("call"){ - } - - Handle GetNodeValue() const { - NanEscapableScope(); - if (*call == NULL) { - return NanEscapeScope(NanNull()); - } - Handle obj = NanNew(); - obj->Set(NanNew("call"), Call::WrapStruct(*call)); - obj->Set(NanNew("method"), NanNew(details->method)); - obj->Set(NanNew("host"), NanNew(details->host)); - obj->Set(NanNew("deadline"), - NanNew(TimespecToMilliseconds(details->deadline))); - obj->Set(NanNew("metadata"), ParseMetadata(request_metadata)); - return NanEscapeScope(obj); - } - private: - grpc_call **call; - grpc_call_details *details; - grpc_metadata_array *request_metadata; -} - -struct tag { - tag(NanCallback *callback, std::vector *responses, - std::vector> *handles, - std::vector *strings) : - callback(callback), repsonses(responses), handles(handles), - strings(strings){ - } - ~tag() { - for (std::vector::iterator it = responses->begin(); - it != responses->end(); ++it) { - delete *it; - } - for (std::vector::iterator it = responses->begin(); - it != responses->end(); ++it) { - delete *it; - } - delete callback; - delete responses; - delete handles; - delete strings; - } - NanCallback *callback; - std::vector *responses; - std::vector> *handles; - std::vector *strings; -}; - -void *CreateTag(Handle callback, grpc_op *ops, size_t nops, - std::vector> *handles, - std::vector *strings) { - NanScope(); - NanCallback *cb = new NanCallback(callback); - vector *responses = new vector(); - for (size_t i = 0; i < nops; i++) { - grpc_op *op = &ops[i]; - OpResponse *resp; - // Switching on the TYPE of the op - switch (op->op) { - case GRPC_OP_SEND_INITIAL_METADATA: - resp = new SendResponse("send metadata"); - break; - case GRPC_OP_SEND_MESSAGE: - resp = new SendResponse("write"); - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - resp = new SendResponse("client close"); - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - resp = new SendResponse("server close"); - break; - case GRPC_OP_RECV_INITIAL_METADATA: - resp = new MetadataResponse(op->data.recv_initial_metadata); - break; - case GRPC_OP_RECV_MESSAGE: - resp = new MessageResponse(op->data.recv_message); - break; - case GRPC_OP_RECV_STATUS_ON_CLIENT: - resp = new ClientStatusResponse( - op->data.recv_status_on_client.trailing_metadata, - op->data.recv_status_on_client.status, - op->data.recv_status_on_client.status_details); - break; - case GRPC_RECV_CLOSE_ON_SERVER: - resp = new ServerCloseResponse(op->data.recv_close_on_server.cancelled); - break; - default: - continue; - } - responses->push_back(resp); - } - struct tag *tag_struct = new struct tag(cb, responses, handles, strings); - return reinterpret_cast(tag_struct); -} - -void *CreateTag(Handle callback, grpc_call **call, - grpc_call_details *details, - grpc_metadata_array *request_metadata) { - NanEscapableScope(); - NanCallback *cb = new NanCallback(callback); - vector *responses = new vector(); - OpResponse *resp = new NewCallResponse(call, details, request_metadata); - responses->push_back(resp); - struct tag *tag_struct = new struct tag(cb, responses); - return reinterpret_cast(tag_struct); -} - -NanCallback GetTagCallback(void *tag) { - NanEscapableScope(); - struct tag *tag_struct = reinterpret_cast(tag); - return NanEscapeScope(*tag_struct->callback); -} - -Handle GetNodeValue(void *tag) { - NanEscapableScope(); - struct tag *tag_struct = reinterpret_cast(tag); - Handle obj = NanNew(); - for (std::vector::iterator it = tag_struct->responses->begin(); - it != tag_struct->responses->end(); ++it) { - OpResponse *resp = *it; - obj->Set(resp->GetOpType(), resp->GetNodeValue()); - } - return NanEscapeScope(obj); -} - -void DestroyTag(void *tag) { delete reinterpret_cast(tag); } - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/tag.h b/src/node/ext/tag.h deleted file mode 100644 index 9ff8703b959..00000000000 --- a/src/node/ext/tag.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef NET_GRPC_NODE_TAG_H_ -#define NET_GRPC_NODE_TAG_H_ - -#include - - -#include -#include -#include - -namespace grpc { -namespace node { - -/* Create a void* tag that can be passed to grpc_call_start_batch from a - callback function and an ops array */ -void *CreateTag(v8::Handle callback, grpc_op *ops, size_t nops, - std::vector > *handles, - std::vector *strings); - -/* Create a void* tag that can be passed to grpc_server_request_call from a - callback and the various out parameters to that function */ -void *CreateTag(v8::Handle callback, grpc_call **call, - grpc_call_details *details, - grpc_metadata_array *request_metadata); - -/* Get the callback from the tag */ -NanCallback GetCallback(void *tag); - -/* Get the combined output value from the tag */ -v8::Handle GetNodeValue(void *tag); - -/* Destroy the tag and all resources it is holding. It is illegal to call any - of these other functions on a tag after it has been destroyed. */ -void DestroyTag(void *tag); - -} // namespace node -} // namespace grpc - -#endif // NET_GRPC_NODE_TAG_H_ From 1bc8df4cf57f1c3c1f0ca3dfc0e5a0ecb887a0cd Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 12 Feb 2015 12:20:46 -0800 Subject: [PATCH 10/31] Fix race in call.c --- src/core/surface/call.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 0af21548423..c0f5742c108 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -514,32 +514,32 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, } } -static void finish_send_op(grpc_call *call, grpc_ioreq_op op, +static void finish_send_op(grpc_call *call, grpc_ioreq_op op, write_state ws, grpc_op_error error) { lock(call); finish_ioreq_op(call, op, error); call->sending = 0; + call->write_state = ws; unlock(call); grpc_call_internal_unref(call, 0); } static void finish_write_step(void *pc, grpc_op_error error) { - finish_send_op(pc, GRPC_IOREQ_SEND_MESSAGE, error); + finish_send_op(pc, GRPC_IOREQ_SEND_MESSAGE, WRITE_STATE_STARTED, error); } static void finish_finish_step(void *pc, grpc_op_error error) { - finish_send_op(pc, GRPC_IOREQ_SEND_CLOSE, error); + finish_send_op(pc, GRPC_IOREQ_SEND_CLOSE, WRITE_STATE_WRITE_CLOSED, error); } static void finish_start_step(void *pc, grpc_op_error error) { - finish_send_op(pc, GRPC_IOREQ_SEND_INITIAL_METADATA, error); + finish_send_op(pc, GRPC_IOREQ_SEND_INITIAL_METADATA, WRITE_STATE_STARTED, error); } static send_action choose_send_action(grpc_call *call) { switch (call->write_state) { case WRITE_STATE_INITIAL: if (is_op_live(call, GRPC_IOREQ_SEND_INITIAL_METADATA)) { - call->write_state = WRITE_STATE_STARTED; if (is_op_live(call, GRPC_IOREQ_SEND_MESSAGE) || is_op_live(call, GRPC_IOREQ_SEND_CLOSE)) { return SEND_BUFFERED_INITIAL_METADATA; } else { @@ -555,7 +555,6 @@ static send_action choose_send_action(grpc_call *call) { return SEND_MESSAGE; } } else if (is_op_live(call, GRPC_IOREQ_SEND_CLOSE)) { - call->write_state = WRITE_STATE_WRITE_CLOSED; finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, GRPC_OP_OK); if (call->is_client) { From e7879557c624c0254e711d6e63c70533ebf39a5d Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 12 Feb 2015 12:21:15 -0800 Subject: [PATCH 11/31] Fixed most of surface tests --- src/node/examples/math_server.js | 1 + src/node/index.js | 10 +- src/node/src/client.js | 489 +++++++++++++++++++++-------- src/node/src/common.js | 25 ++ src/node/src/server.js | 506 +++++++++++++++++++++--------- src/node/test/math_client_test.js | 5 +- 6 files changed, 756 insertions(+), 280 deletions(-) diff --git a/src/node/examples/math_server.js b/src/node/examples/math_server.js index e1bd11b5a6d..e0104453898 100644 --- a/src/node/examples/math_server.js +++ b/src/node/examples/math_server.js @@ -69,6 +69,7 @@ function mathDiv(call, cb) { * @param {stream} stream The stream for sending responses. */ function mathFib(stream) { + console.log(stream); // Here, call is a standard writable Node object Stream var previous = 0, current = 1; for (var i = 0; i < stream.request.limit; i++) { diff --git a/src/node/index.js b/src/node/index.js index 0627e7f5576..baef4d03c68 100644 --- a/src/node/index.js +++ b/src/node/index.js @@ -35,9 +35,9 @@ var _ = require('underscore'); var ProtoBuf = require('protobufjs'); -var surface_client = require('./src/surface_client.js'); +var client = require('./src/client.js'); -var surface_server = require('./src/surface_server.js'); +var server = require('./src/server.js'); var grpc = require('bindings')('grpc'); @@ -54,7 +54,7 @@ function loadObject(value) { }); return result; } else if (value.className === 'Service') { - return surface_client.makeClientConstructor(value); + return client.makeClientConstructor(value); } else if (value.className === 'Message' || value.className === 'Enum') { return value.build(); } else { @@ -84,9 +84,9 @@ exports.loadObject = loadObject; exports.load = load; /** - * See docs for surface_server.makeServerConstructor + * See docs for server.makeServerConstructor */ -exports.buildServer = surface_server.makeServerConstructor; +exports.buildServer = server.makeServerConstructor; /** * Status name to code number mapping diff --git a/src/node/src/client.js b/src/node/src/client.js index 3a1c9eef846..88fa9dc2e25 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -1,6 +1,6 @@ /* * - * Copyright 2014, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,14 +31,104 @@ * */ +var _ = require('underscore'); + +var capitalize = require('underscore.string/capitalize'); +var decapitalize = require('underscore.string/decapitalize'); + var grpc = require('bindings')('grpc.node'); -var common = require('./common'); +var common = require('./common.js'); + +var EventEmitter = require('events').EventEmitter; + +var stream = require('stream'); -var Duplex = require('stream').Duplex; +var Readable = stream.Readable; +var Writable = stream.Writable; +var Duplex = stream.Duplex; var util = require('util'); -util.inherits(GrpcClientStream, Duplex); +util.inherits(ClientWritableStream, Writable); + +function ClientWritableStream(call, serialize) { + Writable.call(this, {objectMode: true}); + this.call = call; + this.serialize = common.wrapIgnoreNull(serialize); + this.on('finish', function() { + var batch = {}; + batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + call.startBatch(batch, function() {}); + }); +} + +/** + * Attempt to write the given chunk. Calls the callback when done. This is an + * implementation of a method needed for implementing stream.Writable. + * @param {Buffer} chunk The chunk to write + * @param {string} encoding Ignored + * @param {function(Error=)} callback Called when the write is complete + */ +function _write(chunk, encoding, callback) { + var batch = {}; + batch[grpc.opType.SEND_MESSAGE] = this.serialize(chunk); + console.log(batch); + this.call.startBatch(batch, function(err, event) { + if (err) { + throw err; + } + callback(); + }); +}; + +ClientWritableStream.prototype._write = _write; + +util.inherits(ClientReadableStream, Readable); + +function ClientReadableStream(call, deserialize) { + Readable.call(this, {objectMode: true}); + this.call = call; + this.finished = false; + this.reading = false; + this.serialize = common.wrapIgnoreNull(deserialize); +} + +function _read(size) { + var self = this; + /** + * Callback to be called when a READ event is received. Pushes the data onto + * the read queue and starts reading again if applicable + * @param {grpc.Event} event READ event object + */ + function readCallback(event) { + if (self.finished) { + self.push(null); + return; + } + var data = event.data; + if (self.push(self.deserialize(data)) && data != null) { + var read_batch = {}; + read_batch[grpc.opType.RECV_MESSAGE] = true; + self.call.startBatch(read_batch, readCallback); + } else { + self.reading = false; + } + } + if (self.finished) { + self.push(null); + } else { + if (!self.reading) { + self.reading = true; + var read_batch = {}; + read_batch[grpc.opType.RECV_MESSAGE] = true; + self.call.startBatch(read_batch, readCallback); + } + } +}; + +ClientReadableStream.prototype._read = _read; + +util.inherits(ClientDuplexStream, Duplex); /** * Class for representing a gRPC client side stream as a Node stream. Extends @@ -49,167 +139,310 @@ util.inherits(GrpcClientStream, Duplex); * @param {function(Buffer):*=} deserialize Deserialization function for * responses */ -function GrpcClientStream(call, serialize, deserialize) { +function ClientDuplexStream(call, serialize, deserialize) { Duplex.call(this, {objectMode: true}); - if (!serialize) { - serialize = function(value) { - return value; - }; - } - if (!deserialize) { - deserialize = function(value) { - return value; - }; - } + this.serialize = common.wrapIgnoreNull(serialize); + this.serialize = common.wrapIgnoreNull(deserialize); var self = this; var finished = false; // Indicates that a read is currently pending var reading = false; - // Indicates that a write is currently pending - var writing = false; - this._call = call; + this.call = call; +} - /** - * Serialize a request value to a buffer. Always maps null to null. Otherwise - * uses the provided serialize function - * @param {*} value The value to serialize - * @return {Buffer} The serialized value - */ - this.serialize = function(value) { - if (value === null || value === undefined) { - return null; - } - return serialize(value); - }; +ClientDuplexStream.prototype._read = _read; +ClientDuplexStream.prototype._write = _write; + +function cancel() { + this.call.cancel(); +} + +ClientReadableStream.prototype.cancel = cancel; +ClientWritableStream.prototype.cancel = cancel; +ClientDuplexStream.prototype.cancel = cancel; +/** + * Get a function that can make unary requests to the specified method. + * @param {string} method The name of the method to request + * @param {function(*):Buffer} serialize The serialization function for inputs + * @param {function(Buffer)} deserialize The deserialization function for + * outputs + * @return {Function} makeUnaryRequest + */ +function makeUnaryRequestFunction(method, serialize, deserialize) { /** - * Deserialize a response buffer to a value. Always maps null to null. - * Otherwise uses the provided deserialize function. - * @param {Buffer} buffer The buffer to deserialize - * @return {*} The deserialized value + * Make a unary request with this method on the given channel with the given + * argument, callback, etc. + * @this {Client} Client object. Must have a channel member. + * @param {*} argument The argument to the call. Should be serializable with + * serialize + * @param {function(?Error, value=)} callback The callback to for when the + * response is received + * @param {array=} metadata Array of metadata key/value pairs to add to the + * call + * @param {(number|Date)=} deadline The deadline for processing this request. + * Defaults to infinite future + * @return {EventEmitter} An event emitter for stream related events */ - this.deserialize = function(buffer) { - if (buffer === null) { - return null; + function makeUnaryRequest(argument, callback, metadata, deadline) { + if (deadline === undefined) { + deadline = Infinity; } - return deserialize(buffer); - }; + var emitter = new EventEmitter(); + var call = new grpc.Call(this.channel, method, deadline); + if (metadata === null || metadata === undefined) { + metadata = {}; + } + emitter.cancel = function cancel() { + call.cancel(); + }; + var client_batch = {}; + client_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + client_batch[grpc.opType.SEND_MESSAGE] = serialize(argument); + client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + client_batch[grpc.opType.RECV_MESSAGE] = true; + client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(client_batch, function(err, response) { + if (err) { + callback(err); + return; + } + emitter.emit('status', response.status); + emitter.emit('metadata', response.metadata); + callback(null, deserialize(response.read)); + }); + return emitter; + } + return makeUnaryRequest; +} + +/** + * Get a function that can make client stream requests to the specified method. + * @param {string} method The name of the method to request + * @param {function(*):Buffer} serialize The serialization function for inputs + * @param {function(Buffer)} deserialize The deserialization function for + * outputs + * @return {Function} makeClientStreamRequest + */ +function makeClientStreamRequestFunction(method, serialize, deserialize) { /** - * Callback to be called when a READ event is received. Pushes the data onto - * the read queue and starts reading again if applicable - * @param {grpc.Event} event READ event object + * Make a client stream request with this method on the given channel with the + * given callback, etc. + * @this {Client} Client object. Must have a channel member. + * @param {function(?Error, value=)} callback The callback to for when the + * response is received + * @param {array=} metadata Array of metadata key/value pairs to add to the + * call + * @param {(number|Date)=} deadline The deadline for processing this request. + * Defaults to infinite future + * @return {EventEmitter} An event emitter for stream related events */ - function readCallback(event) { - if (finished) { - self.push(null); - return; + function makeClientStreamRequest(callback, metadata, deadline) { + if (deadline === undefined) { + deadline = Infinity; } - var data = event.data; - if (self.push(self.deserialize(data)) && data != null) { - self._call.startRead(readCallback); - } else { - reading = false; + var call = new grpc.Call(this.channel, method, deadline); + if (metadata === null || metadata === undefined) { + metadata = {}; } + var stream = new ClientWritableStream(call, serialize); + var metadata_batch = {}; + metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + metadata_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + call.startBatch(metadata_batch, function(err, response) { + if (err) { + callback(err); + return; + } + stream.emit('metadata', response.metadata); + }); + var client_batch = {}; + client_batch[grpc.opType.RECV_MESSAGE] = true; + client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(client_batch, function(err, response) { + if (err) { + callback(err); + return; + } + stream.emit('status', response.status); + callback(null, deserialize(response.read)); + }); + return stream; } - call.invoke(function(event) { - self.emit('metadata', event.data); - }, function(event) { - finished = true; - self.emit('status', event.data); - }, 0); - this.on('finish', function() { - call.writesDone(function() {}); - }); + return makeClientStreamRequest; +} + +/** + * Get a function that can make server stream requests to the specified method. + * @param {string} method The name of the method to request + * @param {function(*):Buffer} serialize The serialization function for inputs + * @param {function(Buffer)} deserialize The deserialization function for + * outputs + * @return {Function} makeServerStreamRequest + */ +function makeServerStreamRequestFunction(method, serialize, deserialize) { /** - * Start reading if there is not already a pending read. Reading will - * continue until self.push returns false (indicating reads should slow - * down) or the read data is null (indicating that there is no more data). + * Make a server stream request with this method on the given channel with the + * given argument, etc. + * @this {SurfaceClient} Client object. Must have a channel member. + * @param {*} argument The argument to the call. Should be serializable with + * serialize + * @param {array=} metadata Array of metadata key/value pairs to add to the + * call + * @param {(number|Date)=} deadline The deadline for processing this request. + * Defaults to infinite future + * @return {EventEmitter} An event emitter for stream related events */ - this.startReading = function() { - if (finished) { - self.push(null); - } else { - if (!reading) { - reading = true; - self._call.startRead(readCallback); - } + function makeServerStreamRequest(argument, metadata, deadline) { + if (deadline === undefined) { + deadline = Infinity; + } + var call = new grpc.Call(this.channel, method, deadline); + if (metadata === null || metadata === undefined) { + metadata = {}; } - }; + var stream = new ClientReadableStream(call, deserialize); + var start_batch = {}; + console.log('Starting server streaming request on', method); + start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + start_batch[grpc.opType.SEND_MESSAGE] = serialize(argument); + start_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + call.startBatch(start_batch, function(err, response) { + if (err) { + throw err; + } + console.log(response); + stream.emit('metadata', response.metadata); + }); + var status_batch = {}; + status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(status_batch, function(err, response) { + if (err) { + throw err; + } + stream.emit('status', response.status); + }); + return stream; + } + return makeServerStreamRequest; } /** - * Start reading. This is an implementation of a method needed for implementing - * stream.Readable. - * @param {number} size Ignored + * Get a function that can make bidirectional stream requests to the specified + * method. + * @param {string} method The name of the method to request + * @param {function(*):Buffer} serialize The serialization function for inputs + * @param {function(Buffer)} deserialize The deserialization function for + * outputs + * @return {Function} makeBidiStreamRequest */ -GrpcClientStream.prototype._read = function(size) { - this.startReading(); -}; +function makeBidiStreamRequestFunction(method, serialize, deserialize) { + /** + * Make a bidirectional stream request with this method on the given channel. + * @this {SurfaceClient} Client object. Must have a channel member. + * @param {array=} metadata Array of metadata key/value pairs to add to the + * call + * @param {(number|Date)=} deadline The deadline for processing this request. + * Defaults to infinite future + * @return {EventEmitter} An event emitter for stream related events + */ + function makeBidiStreamRequest(metadata, deadline) { + if (deadline === undefined) { + deadline = Infinity; + } + var call = new grpc.Call(this.channel, method, deadline); + if (metadata === null || metadata === undefined) { + metadata = {}; + } + var stream = new ClientDuplexStream(call, serialize, deserialize); + var start_batch = {}; + start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + call.startBatch(start_batch, function(err, response) { + if (err) { + throw err; + } + stream.emit('metadata', response.metadata); + }); + var status_batch = {}; + status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(status_batch, function(err, response) { + if (err) { + throw err; + } + stream.emit('status', response.status); + }); + return stream; + } + return makeBidiStreamRequest; +} -/** - * Attempt to write the given chunk. Calls the callback when done. This is an - * implementation of a method needed for implementing stream.Writable. - * @param {Buffer} chunk The chunk to write - * @param {string} encoding Ignored - * @param {function(Error=)} callback Ignored - */ -GrpcClientStream.prototype._write = function(chunk, encoding, callback) { - var self = this; - self._call.startWrite(self.serialize(chunk), function(event) { - callback(); - }, 0); -}; /** - * Cancel the ongoing call. If the call has not already finished, it will finish - * with status CANCELLED. + * Map with short names for each of the requester maker functions. Used in + * makeClientConstructor */ -GrpcClientStream.prototype.cancel = function() { - this._call.cancel(); +var requester_makers = { + unary: makeUnaryRequestFunction, + server_stream: makeServerStreamRequestFunction, + client_stream: makeClientStreamRequestFunction, + bidi: makeBidiStreamRequestFunction }; /** - * Make a request on the channel to the given method with the given arguments - * @param {grpc.Channel} channel The channel on which to make the request - * @param {string} method The method to request - * @param {function(*):Buffer} serialize Serialization function for requests - * @param {function(Buffer):*} deserialize Deserialization function for - * responses - * @param {array=} metadata Array of metadata key/value pairs to add to the call - * @param {(number|Date)=} deadline The deadline for processing this request. - * Defaults to infinite future. - * @return {stream=} The stream of responses + * Creates a constructor for clients for the given service + * @param {ProtoBuf.Reflect.Service} service The service to generate a client + * for + * @return {function(string, Object)} New client constructor */ -function makeRequest(channel, - method, - serialize, - deserialize, - metadata, - deadline) { - if (deadline === undefined) { - deadline = Infinity; - } - var call = new grpc.Call(channel, method, deadline); - if (metadata) { - call.addMetadata(metadata); +function makeClientConstructor(service) { + var prefix = '/' + common.fullyQualifiedName(service) + '/'; + /** + * Create a client with the given methods + * @constructor + * @param {string} address The address of the server to connect to + * @param {Object} options Options to pass to the underlying channel + */ + function Client(address, options) { + this.channel = new grpc.Channel(address, options); } - return new GrpcClientStream(call, serialize, deserialize); + + _.each(service.children, function(method) { + var method_type; + if (method.requestStream) { + if (method.responseStream) { + method_type = 'bidi'; + } else { + method_type = 'client_stream'; + } + } else { + if (method.responseStream) { + method_type = 'server_stream'; + } else { + method_type = 'unary'; + } + } + Client.prototype[decapitalize(method.name)] = + requester_makers[method_type]( + prefix + capitalize(method.name), + common.serializeCls(method.resolvedRequestType.build()), + common.deserializeCls(method.resolvedResponseType.build())); + }); + + Client.service = service; + + return Client; } -/** - * See documentation for makeRequest above - */ -exports.makeRequest = makeRequest; +exports.makeClientConstructor = makeClientConstructor; /** - * Represents a client side gRPC channel associated with a single host. - */ -exports.Channel = grpc.Channel; -/** - * Status name to code number mapping + * See docs for client.status */ exports.status = grpc.status; /** - * Call error name to code number mapping + * See docs for client.callError */ exports.callError = grpc.callError; diff --git a/src/node/src/common.js b/src/node/src/common.js index 54247e3fa11..7560cf1bddf 100644 --- a/src/node/src/common.js +++ b/src/node/src/common.js @@ -31,6 +31,8 @@ * */ +var _ = require('underscore'); + var capitalize = require('underscore.string/capitalize'); /** @@ -87,6 +89,24 @@ function fullyQualifiedName(value) { return name; } +/** + * Wrap a function to pass null-like values through without calling it. If no + * function is given, just uses the identity; + * @param {?function} func The function to wrap + * @return {function} The wrapped function + */ +function wrapIgnoreNull(func) { + if (!func) { + return _.identity; + } + return function(arg) { + if (arg === null || arg === undefined) { + return null; + } + return func(arg); + }; +} + /** * See docs for deserializeCls */ @@ -101,3 +121,8 @@ exports.serializeCls = serializeCls; * See docs for fullyQualifiedName */ exports.fullyQualifiedName = fullyQualifiedName; + +/** + * See docs for wrapIgnoreNull + */ +exports.wrapIgnoreNull = wrapIgnoreNull; diff --git a/src/node/src/server.js b/src/node/src/server.js index e4f71ff05f7..2d5396e3b71 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -1,6 +1,6 @@ /* * - * Copyright 2014, Google Inc. + * Copyright 2015, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,80 +33,72 @@ var _ = require('underscore'); +var capitalize = require('underscore.string/capitalize'); +var decapitalize = require('underscore.string/decapitalize'); + var grpc = require('bindings')('grpc.node'); var common = require('./common'); -var Duplex = require('stream').Duplex; +var stream = require('stream'); + +var Readable = stream.Readable; +var Writable = stream.Writable; +var Duplex = stream.Duplex; var util = require('util'); -util.inherits(GrpcServerStream, Duplex); +var EventEmitter = require('events').EventEmitter; -/** - * Class for representing a gRPC server side stream as a Node stream. Extends - * from stream.Duplex. - * @constructor - * @param {grpc.Call} call Call object to proxy - * @param {function(*):Buffer=} serialize Serialization function for responses - * @param {function(Buffer):*=} deserialize Deserialization function for - * requests - */ -function GrpcServerStream(call, serialize, deserialize) { - Duplex.call(this, {objectMode: true}); - if (!serialize) { - serialize = function(value) { - return value; - }; - } - if (!deserialize) { - deserialize = function(value) { - return value; - }; - } - this._call = call; - // Indicate that a status has been sent - var finished = false; - var self = this; - var status = { - 'code' : grpc.status.OK, - 'details' : 'OK' - }; +var common = require('./common.js'); - /** - * Serialize a response value to a buffer. Always maps null to null. Otherwise - * uses the provided serialize function - * @param {*} value The value to serialize - * @return {Buffer} The serialized value - */ - this.serialize = function(value) { - if (value === null || value === undefined) { - return null; - } - return serialize(value); +function handleError(call, error) { + var error_batch = {}; + error_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { + code: grpc.status.INTERNAL, + details: 'Unknown Error', + metadata: {} }; + call.startBatch(error_batch, function(){}); +} - /** - * Deserialize a request buffer to a value. Always maps null to null. - * Otherwise uses the provided deserialize function. - * @param {Buffer} buffer The buffer to deserialize - * @return {*} The deserialized value - */ - this.deserialize = function(buffer) { - if (buffer === null) { - return null; +function waitForCancel(call, emitter) { + var cancel_batch = {}; + cancel_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; + call.startBatch(cancel_batch, function(err, result) { + if (err) { + emitter.emit('error', err); } - return deserialize(buffer); + if (result.cancelled) { + emitter.cancelled = true; + emitter.emit('cancelled'); + } + }); +} + +function sendUnaryResponse(call, value, serialize) { + var end_batch = {}; + end_batch[grpc.opType.SEND_MESSAGE] = serialize(value); + end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { + code: grpc.status.OK, + details: 'OK', + metadata: {} }; + call.startBatch(end_batch, function (){}); +} - /** - * Send the pending status - */ +function setUpWritable(stream, serialize) { + stream.finished = false; + stream.status = { + 'code' : grpc.status.OK, + 'details' : 'OK' + }; + stream.serialize = common.wrapIgnoreNull(serialize); function sendStatus() { - call.startWriteStatus(status.code, status.details, function() { - }); - finished = true; + var batch = {}; + batch[grpc.opType.SEND_STATUS_FROM_SERVER] = stream.status; + stream.call.startBatch(batch, function(){}); } - this.on('finish', sendStatus); + stream.on('finish', sendStatus); /** * Set the pending status to a given error status. If the error does not have * code or details properties, the code will be set to grpc.status.INTERNAL @@ -123,7 +115,7 @@ function GrpcServerStream(call, serialize, deserialize) { details = err.details; } } - status = {'code': code, 'details': details}; + stream.status = {'code': code, 'details': details}; } /** * Terminate the call. This includes indicating that reads are done, draining @@ -133,69 +125,196 @@ function GrpcServerStream(call, serialize, deserialize) { */ function terminateCall(err) { // Drain readable data - this.on('data', function() {}); setStatus(err); - this.end(); + stream.end(); } - this.on('error', terminateCall); - // Indicates that a read is pending - var reading = false; + stream.on('error', terminateCall); +} + +function setUpReadable(stream, deserialize) { + stream.deserialize = common.wrapIgnoreNull(deserialize); + stream.finished = false; + stream.reading = false; + + stream.terminate = function() { + stream.finished = true; + stream.on('data', function() {}); + }; + + stream.on('cancelled', function() { + stream.terminate(); + }); +} + +util.inherits(ServerWritableStream, Writable); + +function ServerWritableStream(call, serialize) { + Writable.call(this, {objectMode: true}); + this.call = call; + + this.finished = false; + setUpWritable(this, serialize); +} + +/** + * Start writing a chunk of data. This is an implementation of a method required + * for implementing stream.Writable. + * @param {Buffer} chunk The chunk of data to write + * @param {string} encoding Ignored + * @param {function(Error=)} callback Callback to indicate that the write is + * complete + */ +function _write(chunk, encoding, callback) { + var batch = {}; + batch[grpc.opType.SEND_MESSAGE] = this.serialize(chunk); + this.call.startBatch(batch, function(err, value) { + if (err) { + this.emit('error', err); + return; + } + callback(); + }); +} + +ServerWritableStream.prototype._write = _write; + +util.inherits(ServerReadableStream, Readable); + +function ServerReadableStream(call, deserialize) { + Readable.call(this, {objectMode: true}); + this.call = call; + setUpReadable(this, deserialize); +} + +/** + * Start reading from the gRPC data source. This is an implementation of a + * method required for implementing stream.Readable + * @param {number} size Ignored + */ +function _read(size) { + var self = this; /** * Callback to be called when a READ event is received. Pushes the data onto * the read queue and starts reading again if applicable * @param {grpc.Event} event READ event object */ - function readCallback(event) { - if (finished) { + function readCallback(err, event) { + if (err) { + self.terminate(); + return; + } + if (self.finished) { self.push(null); return; } - var data = event.data; + var data = event.read; if (self.push(self.deserialize(data)) && data != null) { - self._call.startRead(readCallback); + var read_batch = {}; + read_batch[grpc.opType.RECV_MESSAGE] = true; + self.call.startBatch(read_batch, readCallback); } else { - reading = false; + self.reading = false; } } - /** - * Start reading if there is not already a pending read. Reading will - * continue until self.push returns false (indicating reads should slow - * down) or the read data is null (indicating that there is no more data). - */ - this.startReading = function() { - if (finished) { - self.push(null); - } else { - if (!reading) { - reading = true; - self._call.startRead(readCallback); + if (self.finished) { + self.push(null); + } else { + if (!self.reading) { + self.reading = true; + var batch = {}; + batch[grpc.opType.RECV_MESSAGE] = true; + self.call.startBatch(batch, readCallback); + } + } +} + +ServerReadableStream.prototype._read = _read; + +util.inherits(ServerDuplexStream, Duplex); + +function ServerDuplexStream(call, serialize, deserialize) { + Duplex.call(this, {objectMode: true}); + setUpWritable(this, serialize); + setUpReadable(this, deserialize); +} + +ServerDuplexStream.prototype._read = _read; +ServerDuplexStream.prototype._write = _write; + +function handleUnary(call, handler, metadata) { + var emitter = new EventEmitter(); + emitter.on('error', function(error) { + handleError(call, error); + }); + waitForCancel(call, emitter); + var batch = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + batch[grpc.opType.RECV_MESSAGE] = true; + call.startBatch(batch, function(err, result) { + if (err) { + handleError(call, err); + return; + } + emitter.request = handler.deserialize(result.read); + if (emitter.cancelled) { + return; + } + handler.func(emitter, function sendUnaryData(err, value) { + if (err) { + handleError(call, err); } + sendUnaryResponse(call, value, handler.serialize); + }); + }); +} + +function handleServerStreaming(call, handler, metadata) { + console.log('Handling server streaming call'); + var stream = new ServerWritableStream(call, handler.serialize); + waitForCancel(call, stream); + var batch = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + batch[grpc.opType.RECV_MESSAGE] = true; + call.startBatch(batch, function(err, result) { + if (err) { + stream.emit('error', err); + return; } - }; + stream.request = result.read; + handler.func(stream); + }); } -/** - * Start reading from the gRPC data source. This is an implementation of a - * method required for implementing stream.Readable - * @param {number} size Ignored - */ -GrpcServerStream.prototype._read = function(size) { - this.startReading(); -}; +function handleClientStreaming(call, handler, metadata) { + var stream = new ServerReadableStream(call, handler.deserialize); + waitForCancel(call, stream); + var metadata_batch = {}; + metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + call.startBatch(metadata_batch, function() {}); + handler.func(stream, function(err, value) { + stream.terminate(); + if (err) { + handleError(call, err); + } + sendUnaryResponse(call, value, handler.serialize); + }); +} -/** - * Start writing a chunk of data. This is an implementation of a method required - * for implementing stream.Writable. - * @param {Buffer} chunk The chunk of data to write - * @param {string} encoding Ignored - * @param {function(Error=)} callback Callback to indicate that the write is - * complete - */ -GrpcServerStream.prototype._write = function(chunk, encoding, callback) { - var self = this; - self._call.startWrite(self.serialize(chunk), function(event) { - callback(); - }, 0); +function handleBidiStreaming(call, handler, metadata) { + var stream = new ServerDuplexStream(call, handler.serialize, + handler.deserialize); + waitForCancel(call, stream); + var metadata_batch = {}; + metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + call.startBatch(metadata_batch, function() {}); + handler.func(stream); +} + +var streamHandlers = { + unary: handleUnary, + server_stream: handleServerStreaming, + client_stream: handleClientStreaming, + bidi: handleBidiStreaming }; /** @@ -218,7 +337,7 @@ function Server(getMetadata, options) { * Start the server and begin handling requests * @this Server */ - this.start = function() { + this.listen = function() { console.log('Server starting'); _.each(handlers, function(handler, handler_name) { console.log('Serving', handler_name); @@ -233,48 +352,42 @@ function Server(getMetadata, options) { * wait for the next request * @param {grpc.Event} event The event to handle with tag SERVER_RPC_NEW */ - function handleNewCall(event) { - var call = event.call; - var data = event.data; - if (data === null) { + function handleNewCall(err, event) { + console.log('Handling new call'); + if (err) { + return; + } + var details = event['new call']; + var call = details.call; + var method = details.method; + var metadata = details.metadata; + if (method === null) { return; } server.requestCall(handleNewCall); var handler = undefined; - var deadline = data.absolute_deadline; - var cancelled = false; - call.serverAccept(function(event) { - if (event.data.code === grpc.status.CANCELLED) { - cancelled = true; - if (stream) { - stream.emit('cancelled'); - } - } - }, 0); - if (handlers.hasOwnProperty(data.method)) { - handler = handlers[data.method]; + var deadline = details.deadline; + if (handlers.hasOwnProperty(method)) { + handler = handlers[method]; + console.log(handler); } else { - call.serverEndInitialMetadata(0); - call.startWriteStatus( - grpc.status.UNIMPLEMENTED, - "This method is not available on this server.", - function() {}); + console.log(handlers); + var batch = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { + code: grpc.status.UNIMPLEMENTED, + details: "This method is not available on this server.", + metadata: {} + }; + batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; + call.startBatch(batch, function() {}); return; } + var response_metadata = {}; if (getMetadata) { - call.addMetadata(getMetadata(data.method, data.metadata)); - } - call.serverEndInitialMetadata(0); - var stream = new GrpcServerStream(call, handler.serialize, - handler.deserialize); - Object.defineProperty(stream, 'cancelled', { - get: function() { return cancelled;} - }); - try { - handler.func(stream, data.metadata); - } catch (e) { - stream.emit('error', e); + response_metadata = getMetadata(method, metadata); } + streamHandlers[handler.type](call, handler, response_metadata); } server.requestCall(handleNewCall); }; @@ -294,17 +407,20 @@ function Server(getMetadata, options) { * returns a stream of response values * @param {function(*):Buffer} serialize Serialization function for responses * @param {function(Buffer):*} deserialize Deserialization function for requests + * @param {string} type The streaming type of method that this handles * @return {boolean} True if the handler was set. False if a handler was already * set for that name. */ -Server.prototype.register = function(name, handler, serialize, deserialize) { +Server.prototype.register = function(name, handler, serialize, deserialize, + type) { if (this.handlers.hasOwnProperty(name)) { return false; } this.handlers[name] = { func: handler, serialize: serialize, - deserialize: deserialize + deserialize: deserialize, + type: type }; return true; }; @@ -324,6 +440,110 @@ Server.prototype.bind = function(port, secure) { }; /** - * See documentation for Server + * Creates a constructor for servers with a service defined by the methods + * object. The methods object has string keys and values of this form: + * {serialize: function, deserialize: function, client_stream: bool, + * server_stream: bool} + * @param {Object} methods Method descriptor for each method the server should + * expose + * @param {string} prefix The prefex to prepend to each method name + * @return {function(Object, Object)} New server constructor + */ +function makeServerConstructor(services) { + var qual_names = []; + _.each(services, function(service) { + _.each(service.children, function(method) { + var name = common.fullyQualifiedName(method); + if (_.indexOf(qual_names, name) !== -1) { + throw new Error('Method ' + name + ' exposed by more than one service'); + } + qual_names.push(name); + }); + }); + /** + * Create a server with the given handlers for all of the methods. + * @constructor + * @param {Object} service_handlers Map from service names to map from method + * names to handlers + * @param {function(string, Object>): + Object>=} getMetadata Callback that + * gets metatada for a given method + * @param {Object=} options Options to pass to the underlying server + */ + function SurfaceServer(service_handlers, getMetadata, options) { + var server = new Server(getMetadata, options); + this.inner_server = server; + _.each(services, function(service) { + var service_name = common.fullyQualifiedName(service); + if (service_handlers[service_name] === undefined) { + throw new Error('Handlers for service ' + + service_name + ' not provided.'); + } + var prefix = '/' + common.fullyQualifiedName(service) + '/'; + _.each(service.children, function(method) { + var method_type; + if (method.requestStream) { + if (method.responseStream) { + method_type = 'bidi'; + } else { + method_type = 'client_stream'; + } + } else { + if (method.responseStream) { + method_type = 'server_stream'; + } else { + method_type = 'unary'; + } + } + if (service_handlers[service_name][decapitalize(method.name)] === + undefined) { + throw new Error('Method handler for ' + + common.fullyQualifiedName(method) + ' not provided.'); + } + var serialize = common.serializeCls( + method.resolvedResponseType.build()); + var deserialize = common.deserializeCls( + method.resolvedRequestType.build()); + server.register( + prefix + capitalize(method.name), + service_handlers[service_name][decapitalize(method.name)], + serialize, deserialize, method_type); + }); + }, this); + } + + /** + * Binds the server to the given port, with SSL enabled if secure is specified + * @param {string} port The port that the server should bind on, in the format + * "address:port" + * @param {boolean=} secure Whether the server should open a secure port + * @return {SurfaceServer} this + */ + SurfaceServer.prototype.bind = function(port, secure) { + return this.inner_server.bind(port, secure); + }; + + /** + * Starts the server listening on any bound ports + * @return {SurfaceServer} this + */ + SurfaceServer.prototype.listen = function() { + this.inner_server.listen(); + return this; + }; + + /** + * Shuts the server down; tells it to stop listening for new requests and to + * kill old requests. + */ + SurfaceServer.prototype.shutdown = function() { + this.inner_server.shutdown(); + }; + + return SurfaceServer; +} + +/** + * See documentation for makeServerConstructor */ -module.exports = Server; +exports.makeServerConstructor = makeServerConstructor; diff --git a/src/node/test/math_client_test.js b/src/node/test/math_client_test.js index 0e365bf8706..f347b18ea0f 100644 --- a/src/node/test/math_client_test.js +++ b/src/node/test/math_client_test.js @@ -63,13 +63,10 @@ describe('Math client', function() { assert.ifError(err); assert.equal(value.quotient, 1); assert.equal(value.remainder, 3); - }); - call.on('status', function checkStatus(status) { - assert.strictEqual(status.code, grpc.status.OK); done(); }); }); - it('should handle a server streaming request', function(done) { + it.only('should handle a server streaming request', function(done) { var call = math_client.fib({limit: 7}); var expected_results = [1, 1, 2, 3, 5, 8, 13]; var next_expected = 0; From 10ac96cb8ff60637f2b46e7059b46d701c123dc0 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 12 Feb 2015 13:28:25 -0800 Subject: [PATCH 12/31] All tests but one now pass against new API --- src/node/interop/interop_client.js | 2 +- src/node/interop/interop_server.js | 1 + src/node/src/client.js | 27 +- src/node/src/server.js | 15 +- src/node/src/surface_client.js | 357 --------------------------- src/node/src/surface_server.js | 340 ------------------------- src/node/test/client_server_test.js | 255 ------------------- src/node/test/interop_sanity_test.js | 2 +- src/node/test/math_client_test.js | 2 +- src/node/test/server_test.js | 122 --------- src/node/test/surface_test.js | 4 +- 11 files changed, 40 insertions(+), 1087 deletions(-) delete mode 100644 src/node/src/surface_client.js delete mode 100644 src/node/src/surface_server.js delete mode 100644 src/node/test/client_server_test.js delete mode 100644 src/node/test/server_test.js diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js index ce18f77fe71..8737af6cde9 100644 --- a/src/node/interop/interop_client.js +++ b/src/node/interop/interop_client.js @@ -145,8 +145,8 @@ function serverStreaming(client, done) { resp_index += 1; }); call.on('status', function(status) { - assert.strictEqual(resp_index, 4); assert.strictEqual(status.code, grpc.status.OK); + assert.strictEqual(resp_index, 4); if (done) { done(); } diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js index 54e9715d1e3..271fe5962e3 100644 --- a/src/node/interop/interop_server.js +++ b/src/node/interop/interop_server.js @@ -106,6 +106,7 @@ function handleStreamingOutput(call) { testProto.PayloadType.COMPRESSABLE, testProto.PayloadType.UNCOMPRESSABLE][Math.random() < 0.5 ? 0 : 1]; } + console.log('req:', req); _.each(req.response_parameters, function(resp_param) { call.write({ payload: { diff --git a/src/node/src/client.js b/src/node/src/client.js index 88fa9dc2e25..36a6f41d7bb 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -56,6 +56,7 @@ function ClientWritableStream(call, serialize) { this.call = call; this.serialize = common.wrapIgnoreNull(serialize); this.on('finish', function() { + console.log('Send close from client'); var batch = {}; batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; call.startBatch(batch, function() {}); @@ -90,7 +91,7 @@ function ClientReadableStream(call, deserialize) { this.call = call; this.finished = false; this.reading = false; - this.serialize = common.wrapIgnoreNull(deserialize); + this.deserialize = common.wrapIgnoreNull(deserialize); } function _read(size) { @@ -100,12 +101,15 @@ function _read(size) { * the read queue and starts reading again if applicable * @param {grpc.Event} event READ event object */ - function readCallback(event) { + function readCallback(err, event) { + if (err) { + throw err; + } if (self.finished) { self.push(null); return; } - var data = event.data; + var data = event.read; if (self.push(self.deserialize(data)) && data != null) { var read_batch = {}; read_batch[grpc.opType.RECV_MESSAGE] = true; @@ -142,12 +146,18 @@ util.inherits(ClientDuplexStream, Duplex); function ClientDuplexStream(call, serialize, deserialize) { Duplex.call(this, {objectMode: true}); this.serialize = common.wrapIgnoreNull(serialize); - this.serialize = common.wrapIgnoreNull(deserialize); + this.deserialize = common.wrapIgnoreNull(deserialize); var self = this; var finished = false; // Indicates that a read is currently pending var reading = false; this.call = call; + this.on('finish', function() { + console.log('Send close from client'); + var batch = {}; + batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + call.startBatch(batch, function() {}); + }); } ClientDuplexStream.prototype._read = _read; @@ -208,6 +218,10 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { callback(err); return; } + if (response.status.code != grpc.status.OK) { + callback(response.status); + return; + } emitter.emit('status', response.status); emitter.emit('metadata', response.metadata); callback(null, deserialize(response.read)); @@ -265,6 +279,11 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { callback(err); return; } + console.log(response); + if (response.status.code != grpc.status.OK) { + callback(response.status); + return; + } stream.emit('status', response.status); callback(null, deserialize(response.read)); }); diff --git a/src/node/src/server.js b/src/node/src/server.js index 2d5396e3b71..3c214913195 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -89,11 +89,13 @@ function sendUnaryResponse(call, value, serialize) { function setUpWritable(stream, serialize) { stream.finished = false; stream.status = { - 'code' : grpc.status.OK, - 'details' : 'OK' + code : grpc.status.OK, + details : 'OK', + metadata : {} }; stream.serialize = common.wrapIgnoreNull(serialize); function sendStatus() { + console.log('Server sending status'); var batch = {}; batch[grpc.opType.SEND_STATUS_FROM_SERVER] = stream.status; stream.call.startBatch(batch, function(){}); @@ -115,7 +117,7 @@ function setUpWritable(stream, serialize) { details = err.details; } } - stream.status = {'code': code, 'details': details}; + stream.status = {code: code, details: details, metadata: {}}; } /** * Terminate the call. This includes indicating that reads are done, draining @@ -167,6 +169,7 @@ function ServerWritableStream(call, serialize) { function _write(chunk, encoding, callback) { var batch = {}; batch[grpc.opType.SEND_MESSAGE] = this.serialize(chunk); + console.log('Server writing', batch); this.call.startBatch(batch, function(err, value) { if (err) { this.emit('error', err); @@ -204,11 +207,14 @@ function _read(size) { return; } if (self.finished) { + console.log('Pushing null'); self.push(null); return; } var data = event.read; + console.log(data); if (self.push(self.deserialize(data)) && data != null) { + console.log('Reading again'); var read_batch = {}; read_batch[grpc.opType.RECV_MESSAGE] = true; self.call.startBatch(read_batch, readCallback); @@ -234,6 +240,7 @@ util.inherits(ServerDuplexStream, Duplex); function ServerDuplexStream(call, serialize, deserialize) { Duplex.call(this, {objectMode: true}); + this.call = call; setUpWritable(this, serialize); setUpReadable(this, deserialize); } @@ -280,7 +287,7 @@ function handleServerStreaming(call, handler, metadata) { stream.emit('error', err); return; } - stream.request = result.read; + stream.request = handler.deserialize(result.read); handler.func(stream); }); } diff --git a/src/node/src/surface_client.js b/src/node/src/surface_client.js deleted file mode 100644 index 16c31809f43..00000000000 --- a/src/node/src/surface_client.js +++ /dev/null @@ -1,357 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -var _ = require('underscore'); - -var capitalize = require('underscore.string/capitalize'); -var decapitalize = require('underscore.string/decapitalize'); - -var client = require('./client.js'); - -var common = require('./common.js'); - -var EventEmitter = require('events').EventEmitter; - -var stream = require('stream'); - -var Readable = stream.Readable; -var Writable = stream.Writable; -var Duplex = stream.Duplex; -var util = require('util'); - - -function forwardEvent(fromEmitter, toEmitter, event) { - fromEmitter.on(event, function forward() { - _.partial(toEmitter.emit, event).apply(toEmitter, arguments); - }); -} - -util.inherits(ClientReadableObjectStream, Readable); - -/** - * Class for representing a gRPC server streaming call as a Node stream on the - * client side. Extends from stream.Readable. - * @constructor - * @param {stream} stream Underlying binary Duplex stream for the call - */ -function ClientReadableObjectStream(stream) { - var options = {objectMode: true}; - Readable.call(this, options); - this._stream = stream; - var self = this; - forwardEvent(stream, this, 'status'); - forwardEvent(stream, this, 'metadata'); - this._stream.on('data', function forwardData(chunk) { - if (!self.push(chunk)) { - self._stream.pause(); - } - }); - this._stream.pause(); -} - -/** - * _read implementation for both types of streams that allow reading. - * @this {ClientReadableObjectStream} - * @param {number} size Ignored - */ -function _read(size) { - this._stream.resume(); -} - -/** - * See docs for _read - */ -ClientReadableObjectStream.prototype._read = _read; - -util.inherits(ClientWritableObjectStream, Writable); - -/** - * Class for representing a gRPC client streaming call as a Node stream on the - * client side. Extends from stream.Writable. - * @constructor - * @param {stream} stream Underlying binary Duplex stream for the call - */ -function ClientWritableObjectStream(stream) { - var options = {objectMode: true}; - Writable.call(this, options); - this._stream = stream; - forwardEvent(stream, this, 'status'); - forwardEvent(stream, this, 'metadata'); - this.on('finish', function() { - this._stream.end(); - }); -} - -/** - * _write implementation for both types of streams that allow writing - * @this {ClientWritableObjectStream} - * @param {*} chunk The value to write to the stream - * @param {string} encoding Ignored - * @param {function(Error)} callback Callback to call when finished writing - */ -function _write(chunk, encoding, callback) { - this._stream.write(chunk, encoding, callback); -} - -/** - * See docs for _write - */ -ClientWritableObjectStream.prototype._write = _write; - -/** - * Cancel the underlying call - */ -function cancel() { - this._stream.cancel(); -} - -ClientReadableObjectStream.prototype.cancel = cancel; -ClientWritableObjectStream.prototype.cancel = cancel; - -/** - * Get a function that can make unary requests to the specified method. - * @param {string} method The name of the method to request - * @param {function(*):Buffer} serialize The serialization function for inputs - * @param {function(Buffer)} deserialize The deserialization function for - * outputs - * @return {Function} makeUnaryRequest - */ -function makeUnaryRequestFunction(method, serialize, deserialize) { - /** - * Make a unary request with this method on the given channel with the given - * argument, callback, etc. - * @this {SurfaceClient} Client object. Must have a channel member. - * @param {*} argument The argument to the call. Should be serializable with - * serialize - * @param {function(?Error, value=)} callback The callback to for when the - * response is received - * @param {array=} metadata Array of metadata key/value pairs to add to the - * call - * @param {(number|Date)=} deadline The deadline for processing this request. - * Defaults to infinite future - * @return {EventEmitter} An event emitter for stream related events - */ - function makeUnaryRequest(argument, callback, metadata, deadline) { - var stream = client.makeRequest(this.channel, method, serialize, - deserialize, metadata, deadline); - var emitter = new EventEmitter(); - emitter.cancel = function cancel() { - stream.cancel(); - }; - forwardEvent(stream, emitter, 'status'); - forwardEvent(stream, emitter, 'metadata'); - stream.write(argument); - stream.end(); - stream.on('data', function forwardData(chunk) { - try { - callback(null, chunk); - } catch (e) { - callback(e); - } - }); - stream.on('status', function forwardStatus(status) { - if (status.code !== client.status.OK) { - callback(status); - } - }); - return emitter; - } - return makeUnaryRequest; -} - -/** - * Get a function that can make client stream requests to the specified method. - * @param {string} method The name of the method to request - * @param {function(*):Buffer} serialize The serialization function for inputs - * @param {function(Buffer)} deserialize The deserialization function for - * outputs - * @return {Function} makeClientStreamRequest - */ -function makeClientStreamRequestFunction(method, serialize, deserialize) { - /** - * Make a client stream request with this method on the given channel with the - * given callback, etc. - * @this {SurfaceClient} Client object. Must have a channel member. - * @param {function(?Error, value=)} callback The callback to for when the - * response is received - * @param {array=} metadata Array of metadata key/value pairs to add to the - * call - * @param {(number|Date)=} deadline The deadline for processing this request. - * Defaults to infinite future - * @return {EventEmitter} An event emitter for stream related events - */ - function makeClientStreamRequest(callback, metadata, deadline) { - var stream = client.makeRequest(this.channel, method, serialize, - deserialize, metadata, deadline); - var obj_stream = new ClientWritableObjectStream(stream); - stream.on('data', function forwardData(chunk) { - try { - callback(null, chunk); - } catch (e) { - callback(e); - } - }); - stream.on('status', function forwardStatus(status) { - if (status.code !== client.status.OK) { - callback(status); - } - }); - return obj_stream; - } - return makeClientStreamRequest; -} - -/** - * Get a function that can make server stream requests to the specified method. - * @param {string} method The name of the method to request - * @param {function(*):Buffer} serialize The serialization function for inputs - * @param {function(Buffer)} deserialize The deserialization function for - * outputs - * @return {Function} makeServerStreamRequest - */ -function makeServerStreamRequestFunction(method, serialize, deserialize) { - /** - * Make a server stream request with this method on the given channel with the - * given argument, etc. - * @this {SurfaceClient} Client object. Must have a channel member. - * @param {*} argument The argument to the call. Should be serializable with - * serialize - * @param {array=} metadata Array of metadata key/value pairs to add to the - * call - * @param {(number|Date)=} deadline The deadline for processing this request. - * Defaults to infinite future - * @return {EventEmitter} An event emitter for stream related events - */ - function makeServerStreamRequest(argument, metadata, deadline) { - var stream = client.makeRequest(this.channel, method, serialize, - deserialize, metadata, deadline); - var obj_stream = new ClientReadableObjectStream(stream); - stream.write(argument); - stream.end(); - return obj_stream; - } - return makeServerStreamRequest; -} - -/** - * Get a function that can make bidirectional stream requests to the specified - * method. - * @param {string} method The name of the method to request - * @param {function(*):Buffer} serialize The serialization function for inputs - * @param {function(Buffer)} deserialize The deserialization function for - * outputs - * @return {Function} makeBidiStreamRequest - */ -function makeBidiStreamRequestFunction(method, serialize, deserialize) { - /** - * Make a bidirectional stream request with this method on the given channel. - * @this {SurfaceClient} Client object. Must have a channel member. - * @param {array=} metadata Array of metadata key/value pairs to add to the - * call - * @param {(number|Date)=} deadline The deadline for processing this request. - * Defaults to infinite future - * @return {EventEmitter} An event emitter for stream related events - */ - function makeBidiStreamRequest(metadata, deadline) { - return client.makeRequest(this.channel, method, serialize, - deserialize, metadata, deadline); - } - return makeBidiStreamRequest; -} - -/** - * Map with short names for each of the requester maker functions. Used in - * makeClientConstructor - */ -var requester_makers = { - unary: makeUnaryRequestFunction, - server_stream: makeServerStreamRequestFunction, - client_stream: makeClientStreamRequestFunction, - bidi: makeBidiStreamRequestFunction -} - -/** - * Creates a constructor for clients for the given service - * @param {ProtoBuf.Reflect.Service} service The service to generate a client - * for - * @return {function(string, Object)} New client constructor - */ -function makeClientConstructor(service) { - var prefix = '/' + common.fullyQualifiedName(service) + '/'; - /** - * Create a client with the given methods - * @constructor - * @param {string} address The address of the server to connect to - * @param {Object} options Options to pass to the underlying channel - */ - function SurfaceClient(address, options) { - this.channel = new client.Channel(address, options); - } - - _.each(service.children, function(method) { - var method_type; - if (method.requestStream) { - if (method.responseStream) { - method_type = 'bidi'; - } else { - method_type = 'client_stream'; - } - } else { - if (method.responseStream) { - method_type = 'server_stream'; - } else { - method_type = 'unary'; - } - } - SurfaceClient.prototype[decapitalize(method.name)] = - requester_makers[method_type]( - prefix + capitalize(method.name), - common.serializeCls(method.resolvedRequestType.build()), - common.deserializeCls(method.resolvedResponseType.build())); - }); - - SurfaceClient.service = service; - - return SurfaceClient; -} - -exports.makeClientConstructor = makeClientConstructor; - -/** - * See docs for client.status - */ -exports.status = client.status; -/** - * See docs for client.callError - */ -exports.callError = client.callError; diff --git a/src/node/src/surface_server.js b/src/node/src/surface_server.js deleted file mode 100644 index a47d1fa23d5..00000000000 --- a/src/node/src/surface_server.js +++ /dev/null @@ -1,340 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -var _ = require('underscore'); - -var capitalize = require('underscore.string/capitalize'); -var decapitalize = require('underscore.string/decapitalize'); - -var Server = require('./server.js'); - -var stream = require('stream'); - -var Readable = stream.Readable; -var Writable = stream.Writable; -var Duplex = stream.Duplex; -var util = require('util'); - -var common = require('./common.js'); - -util.inherits(ServerReadableObjectStream, Readable); - -/** - * Class for representing a gRPC client streaming call as a Node stream on the - * server side. Extends from stream.Readable. - * @constructor - * @param {stream} stream Underlying binary Duplex stream for the call - */ -function ServerReadableObjectStream(stream) { - var options = {objectMode: true}; - Readable.call(this, options); - this._stream = stream; - Object.defineProperty(this, 'cancelled', { - get: function() { return stream.cancelled; } - }); - var self = this; - this._stream.on('cancelled', function() { - self.emit('cancelled'); - }); - this._stream.on('data', function forwardData(chunk) { - if (!self.push(chunk)) { - self._stream.pause(); - } - }); - this._stream.on('end', function forwardEnd() { - self.push(null); - }); - this._stream.pause(); -} - -/** - * _read implementation for both types of streams that allow reading. - * @this {ServerReadableObjectStream|ServerBidiObjectStream} - * @param {number} size Ignored - */ -function _read(size) { - this._stream.resume(); -} - -/** - * See docs for _read - */ -ServerReadableObjectStream.prototype._read = _read; - -util.inherits(ServerWritableObjectStream, Writable); - -/** - * Class for representing a gRPC server streaming call as a Node stream on the - * server side. Extends from stream.Writable. - * @constructor - * @param {stream} stream Underlying binary Duplex stream for the call - */ -function ServerWritableObjectStream(stream) { - var options = {objectMode: true}; - Writable.call(this, options); - this._stream = stream; - this._stream.on('cancelled', function() { - self.emit('cancelled'); - }); - this.on('finish', function() { - this._stream.end(); - }); -} - -/** - * _write implementation for both types of streams that allow writing - * @this {ServerWritableObjectStream} - * @param {*} chunk The value to write to the stream - * @param {string} encoding Ignored - * @param {function(Error)} callback Callback to call when finished writing - */ -function _write(chunk, encoding, callback) { - this._stream.write(chunk, encoding, callback); -} - -/** - * See docs for _write - */ -ServerWritableObjectStream.prototype._write = _write; - -/** - * Creates a binary stream handler function from a unary handler function - * @param {function(Object, function(Error, *), metadata=)} handler Unary call - * handler - * @return {function(stream, metadata=)} Binary stream handler - */ -function makeUnaryHandler(handler) { - /** - * Handles a stream by reading a single data value, passing it to the handler, - * and writing the response back to the stream. - * @param {stream} stream Binary data stream - * @param {metadata=} metadata Incoming metadata array - */ - return function handleUnaryCall(stream, metadata) { - stream.on('data', function handleUnaryData(value) { - var call = {request: value}; - Object.defineProperty(call, 'cancelled', { - get: function() { return stream.cancelled;} - }); - stream.on('cancelled', function() { - call.emit('cancelled'); - }); - handler(call, function sendUnaryData(err, value) { - if (err) { - stream.emit('error', err); - } else { - stream.write(value); - stream.end(); - } - }, metadata); - }); - }; -} - -/** - * Creates a binary stream handler function from a client stream handler - * function - * @param {function(Readable, function(Error, *), metadata=)} handler Client - * stream call handler - * @return {function(stream, metadata=)} Binary stream handler - */ -function makeClientStreamHandler(handler) { - /** - * Handles a stream by passing a deserializing stream to the handler and - * writing the response back to the stream. - * @param {stream} stream Binary data stream - * @param {metadata=} metadata Incoming metadata array - */ - return function handleClientStreamCall(stream, metadata) { - var object_stream = new ServerReadableObjectStream(stream); - handler(object_stream, function sendClientStreamData(err, value) { - if (err) { - stream.emit('error', err); - } else { - stream.write(value); - stream.end(); - } - }, metadata); - }; -} - -/** - * Creates a binary stream handler function from a server stream handler - * function - * @param {function(Writable, metadata=)} handler Server stream call handler - * @return {function(stream, metadata=)} Binary stream handler - */ -function makeServerStreamHandler(handler) { - /** - * Handles a stream by attaching it to a serializing stream, and passing it to - * the handler. - * @param {stream} stream Binary data stream - * @param {metadata=} metadata Incoming metadata array - */ - return function handleServerStreamCall(stream, metadata) { - stream.on('data', function handleClientData(value) { - var object_stream = new ServerWritableObjectStream(stream); - object_stream.request = value; - handler(object_stream, metadata); - }); - }; -} - -/** - * Creates a binary stream handler function from a bidi stream handler function - * @param {function(Duplex, metadata=)} handler Unary call handler - * @return {function(stream, metadata=)} Binary stream handler - */ -function makeBidiStreamHandler(handler) { - return handler; -} - -/** - * Map with short names for each of the handler maker functions. Used in - * makeServerConstructor - */ -var handler_makers = { - unary: makeUnaryHandler, - server_stream: makeServerStreamHandler, - client_stream: makeClientStreamHandler, - bidi: makeBidiStreamHandler -}; - -/** - * Creates a constructor for servers with a service defined by the methods - * object. The methods object has string keys and values of this form: - * {serialize: function, deserialize: function, client_stream: bool, - * server_stream: bool} - * @param {Object} methods Method descriptor for each method the server should - * expose - * @param {string} prefix The prefex to prepend to each method name - * @return {function(Object, Object)} New server constructor - */ -function makeServerConstructor(services) { - var qual_names = []; - _.each(services, function(service) { - _.each(service.children, function(method) { - var name = common.fullyQualifiedName(method); - if (_.indexOf(qual_names, name) !== -1) { - throw new Error('Method ' + name + ' exposed by more than one service'); - } - qual_names.push(name); - }); - }); - /** - * Create a server with the given handlers for all of the methods. - * @constructor - * @param {Object} service_handlers Map from service names to map from method - * names to handlers - * @param {function(string, Object>): - Object>=} getMetadata Callback that - * gets metatada for a given method - * @param {Object=} options Options to pass to the underlying server - */ - function SurfaceServer(service_handlers, getMetadata, options) { - var server = new Server(getMetadata, options); - this.inner_server = server; - _.each(services, function(service) { - var service_name = common.fullyQualifiedName(service); - if (service_handlers[service_name] === undefined) { - throw new Error('Handlers for service ' + - service_name + ' not provided.'); - } - var prefix = '/' + common.fullyQualifiedName(service) + '/'; - _.each(service.children, function(method) { - var method_type; - if (method.requestStream) { - if (method.responseStream) { - method_type = 'bidi'; - } else { - method_type = 'client_stream'; - } - } else { - if (method.responseStream) { - method_type = 'server_stream'; - } else { - method_type = 'unary'; - } - } - if (service_handlers[service_name][decapitalize(method.name)] === - undefined) { - throw new Error('Method handler for ' + - common.fullyQualifiedName(method) + ' not provided.'); - } - var binary_handler = handler_makers[method_type]( - service_handlers[service_name][decapitalize(method.name)]); - var serialize = common.serializeCls( - method.resolvedResponseType.build()); - var deserialize = common.deserializeCls( - method.resolvedRequestType.build()); - server.register(prefix + capitalize(method.name), binary_handler, - serialize, deserialize); - }); - }, this); - } - - /** - * Binds the server to the given port, with SSL enabled if secure is specified - * @param {string} port The port that the server should bind on, in the format - * "address:port" - * @param {boolean=} secure Whether the server should open a secure port - * @return {SurfaceServer} this - */ - SurfaceServer.prototype.bind = function(port, secure) { - return this.inner_server.bind(port, secure); - }; - - /** - * Starts the server listening on any bound ports - * @return {SurfaceServer} this - */ - SurfaceServer.prototype.listen = function() { - this.inner_server.start(); - return this; - }; - - /** - * Shuts the server down; tells it to stop listening for new requests and to - * kill old requests. - */ - SurfaceServer.prototype.shutdown = function() { - this.inner_server.shutdown(); - }; - - return SurfaceServer; -} - -/** - * See documentation for makeServerConstructor - */ -exports.makeServerConstructor = makeServerConstructor; diff --git a/src/node/test/client_server_test.js b/src/node/test/client_server_test.js deleted file mode 100644 index 1db9f694678..00000000000 --- a/src/node/test/client_server_test.js +++ /dev/null @@ -1,255 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -var assert = require('assert'); -var fs = require('fs'); -var path = require('path'); -var grpc = require('bindings')('grpc.node'); -var Server = require('../src/server'); -var client = require('../src/client'); -var common = require('../src/common'); - -var ca_path = path.join(__dirname, 'data/ca.pem'); - -var key_path = path.join(__dirname, 'data/server1.key'); - -var pem_path = path.join(__dirname, 'data/server1.pem'); - -/** - * Helper function to return an absolute deadline given a relative timeout in - * seconds. - * @param {number} timeout_secs The number of seconds to wait before timing out - * @return {Date} A date timeout_secs in the future - */ -function getDeadline(timeout_secs) { - var deadline = new Date(); - deadline.setSeconds(deadline.getSeconds() + timeout_secs); - return deadline; -} - -/** - * Responds to every request with the same data as a response - * @param {Stream} stream - */ -function echoHandler(stream) { - stream.pipe(stream); -} - -/** - * Responds to every request with an error status - * @param {Stream} stream - */ -function errorHandler(stream) { - throw { - 'code' : grpc.status.UNIMPLEMENTED, - 'details' : 'error details' - }; -} - -/** - * Wait for a cancellation instead of responding - * @param {Stream} stream - */ -function cancelHandler(stream) { - // do nothing -} - -function metadataHandler(stream, metadata) { - stream.end(); -} - -/** - * Serialize a string to a Buffer - * @param {string} value The string to serialize - * @return {Buffer} The serialized value - */ -function stringSerialize(value) { - return new Buffer(value); -} - -/** - * Deserialize a Buffer to a string - * @param {Buffer} buffer The buffer to deserialize - * @return {string} The string value of the buffer - */ -function stringDeserialize(buffer) { - return buffer.toString(); -} - -describe('echo client', function() { - var server; - var channel; - before(function() { - server = new Server(function getMetadata(method, metadata) { - return {method: [method]}; - }); - var port_num = server.bind('0.0.0.0:0'); - server.register('echo', echoHandler); - server.register('error', errorHandler); - server.register('cancellation', cancelHandler); - server.register('metadata', metadataHandler); - server.start(); - - channel = new grpc.Channel('localhost:' + port_num); - }); - after(function() { - server.shutdown(); - }); - it('should receive echo responses', function(done) { - var messages = ['echo1', 'echo2', 'echo3', 'echo4']; - var stream = client.makeRequest( - channel, - 'echo', - stringSerialize, - stringDeserialize); - for (var i = 0; i < messages.length; i++) { - stream.write(messages[i]); - } - stream.end(); - var index = 0; - stream.on('data', function(chunk) { - assert.equal(messages[index], chunk); - index += 1; - }); - stream.on('status', function(status) { - assert.equal(status.code, client.status.OK); - }); - stream.on('end', function() { - assert.equal(index, messages.length); - done(); - }); - }); - it('should recieve metadata set by the server', function(done) { - var stream = client.makeRequest(channel, 'metadata'); - stream.on('metadata', function(metadata) { - assert.strictEqual(metadata.method[0].toString(), 'metadata'); - }); - stream.on('status', function(status) { - assert.equal(status.code, client.status.OK); - done(); - }); - stream.end(); - }); - it('should get an error status that the server throws', function(done) { - var stream = client.makeRequest(channel, 'error'); - - stream.on('data', function() {}); - stream.write(new Buffer('test')); - stream.end(); - stream.on('status', function(status) { - assert.equal(status.code, grpc.status.UNIMPLEMENTED); - assert.equal(status.details, 'error details'); - done(); - }); - }); - it('should be able to cancel a call', function(done) { - var stream = client.makeRequest( - channel, - 'cancellation', - null, - getDeadline(1)); - - stream.cancel(); - stream.on('status', function(status) { - assert.equal(status.code, grpc.status.CANCELLED); - done(); - }); - }); - it('should get correct status for unimplemented method', function(done) { - var stream = client.makeRequest(channel, 'unimplemented_method'); - stream.end(); - stream.on('status', function(status) { - assert.equal(status.code, grpc.status.UNIMPLEMENTED); - done(); - }); - }); -}); -/* TODO(mlumish): explore options for reducing duplication between this test - * and the insecure echo client test */ -describe('secure echo client', function() { - var server; - var channel; - before(function(done) { - fs.readFile(ca_path, function(err, ca_data) { - assert.ifError(err); - fs.readFile(key_path, function(err, key_data) { - assert.ifError(err); - fs.readFile(pem_path, function(err, pem_data) { - assert.ifError(err); - var creds = grpc.Credentials.createSsl(ca_data); - var server_creds = grpc.ServerCredentials.createSsl(null, - key_data, - pem_data); - - server = new Server(null, {'credentials' : server_creds}); - var port_num = server.bind('0.0.0.0:0', true); - server.register('echo', echoHandler); - server.start(); - - channel = new grpc.Channel('localhost:' + port_num, { - 'grpc.ssl_target_name_override' : 'foo.test.google.com', - 'credentials' : creds - }); - done(); - }); - }); - }); - }); - after(function() { - server.shutdown(); - }); - it('should recieve echo responses', function(done) { - var messages = ['echo1', 'echo2', 'echo3', 'echo4']; - var stream = client.makeRequest( - channel, - 'echo', - stringSerialize, - stringDeserialize); - for (var i = 0; i < messages.length; i++) { - stream.write(messages[i]); - } - stream.end(); - var index = 0; - stream.on('data', function(chunk) { - assert.equal(messages[index], chunk); - index += 1; - }); - stream.on('status', function(status) { - assert.equal(status.code, client.status.OK); - }); - stream.on('end', function() { - assert.equal(index, messages.length); - done(); - }); - }); -}); diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js index 7ecaad833d4..81cd9fa5b95 100644 --- a/src/node/test/interop_sanity_test.js +++ b/src/node/test/interop_sanity_test.js @@ -56,7 +56,7 @@ describe('Interop tests', function() { interop_client.runTest(port, name_override, 'empty_unary', true, done); }); // This fails due to an unknown bug - it.skip('should pass large_unary', function(done) { + it('should pass large_unary', function(done) { interop_client.runTest(port, name_override, 'large_unary', true, done); }); it('should pass client_streaming', function(done) { diff --git a/src/node/test/math_client_test.js b/src/node/test/math_client_test.js index f347b18ea0f..61b4a2fa2fe 100644 --- a/src/node/test/math_client_test.js +++ b/src/node/test/math_client_test.js @@ -66,7 +66,7 @@ describe('Math client', function() { done(); }); }); - it.only('should handle a server streaming request', function(done) { + it('should handle a server streaming request', function(done) { var call = math_client.fib({limit: 7}); var expected_results = [1, 1, 2, 3, 5, 8, 13]; var next_expected = 0; diff --git a/src/node/test/server_test.js b/src/node/test/server_test.js deleted file mode 100644 index a3e1edf50f9..00000000000 --- a/src/node/test/server_test.js +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * Copyright 2014, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -var assert = require('assert'); -var grpc = require('bindings')('grpc.node'); -var Server = require('../src/server'); - -/** - * This is used for testing functions with multiple asynchronous calls that - * can happen in different orders. This should be passed the number of async - * function invocations that can occur last, and each of those should call this - * function's return value - * @param {function()} done The function that should be called when a test is - * complete. - * @param {number} count The number of calls to the resulting function if the - * test passes. - * @return {function()} The function that should be called at the end of each - * sequence of asynchronous functions. - */ -function multiDone(done, count) { - return function() { - count -= 1; - if (count <= 0) { - done(); - } - }; -} - -/** - * Responds to every request with the same data as a response - * @param {Stream} stream - */ -function echoHandler(stream) { - stream.pipe(stream); -} - -describe('echo server', function() { - var server; - var channel; - before(function() { - server = new Server(); - var port_num = server.bind('[::]:0'); - server.register('echo', echoHandler); - server.start(); - - channel = new grpc.Channel('localhost:' + port_num); - }); - after(function() { - server.shutdown(); - }); - it('should echo inputs as responses', function(done) { - done = multiDone(done, 4); - - var req_text = 'echo test string'; - var status_text = 'OK'; - - var deadline = new Date(); - deadline.setSeconds(deadline.getSeconds() + 3); - var call = new grpc.Call(channel, - 'echo', - deadline); - call.invoke(function(event) { - assert.strictEqual(event.type, - grpc.completionType.CLIENT_METADATA_READ); - done(); - },function(event) { - assert.strictEqual(event.type, grpc.completionType.FINISHED); - var status = event.data; - assert.strictEqual(status.code, grpc.status.OK); - assert.strictEqual(status.details, status_text); - done(); - }, 0); - call.startWrite( - new Buffer(req_text), - function(event) { - assert.strictEqual(event.type, - grpc.completionType.WRITE_ACCEPTED); - assert.strictEqual(event.data, grpc.opError.OK); - call.writesDone(function(event) { - assert.strictEqual(event.type, - grpc.completionType.FINISH_ACCEPTED); - assert.strictEqual(event.data, grpc.opError.OK); - done(); - }); - }, 0); - call.startRead(function(event) { - assert.strictEqual(event.type, grpc.completionType.READ); - assert.strictEqual(event.data.toString(), req_text); - done(); - }); - }); -}); diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index 1038f9ab337..34e4ab4013c 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -33,9 +33,9 @@ var assert = require('assert'); -var surface_server = require('../src/surface_server.js'); +var surface_server = require('../src/server.js'); -var surface_client = require('../src/surface_client.js'); +var surface_client = require('../src/client.js'); var ProtoBuf = require('protobufjs'); From d17d57aa39b6e20fac45b8b961f41eb979dc2d5d Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 12 Feb 2015 13:32:18 -0800 Subject: [PATCH 13/31] Removed extra log lines --- src/node/examples/math_server.js | 1 - src/node/interop/interop_server.js | 1 - src/node/src/client.js | 6 ------ src/node/src/server.js | 9 --------- src/node/test/end_to_end_test.js | 1 - 5 files changed, 18 deletions(-) diff --git a/src/node/examples/math_server.js b/src/node/examples/math_server.js index e0104453898..e1bd11b5a6d 100644 --- a/src/node/examples/math_server.js +++ b/src/node/examples/math_server.js @@ -69,7 +69,6 @@ function mathDiv(call, cb) { * @param {stream} stream The stream for sending responses. */ function mathFib(stream) { - console.log(stream); // Here, call is a standard writable Node object Stream var previous = 0, current = 1; for (var i = 0; i < stream.request.limit; i++) { diff --git a/src/node/interop/interop_server.js b/src/node/interop/interop_server.js index 271fe5962e3..54e9715d1e3 100644 --- a/src/node/interop/interop_server.js +++ b/src/node/interop/interop_server.js @@ -106,7 +106,6 @@ function handleStreamingOutput(call) { testProto.PayloadType.COMPRESSABLE, testProto.PayloadType.UNCOMPRESSABLE][Math.random() < 0.5 ? 0 : 1]; } - console.log('req:', req); _.each(req.response_parameters, function(resp_param) { call.write({ payload: { diff --git a/src/node/src/client.js b/src/node/src/client.js index 36a6f41d7bb..4b7eda324ee 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -56,7 +56,6 @@ function ClientWritableStream(call, serialize) { this.call = call; this.serialize = common.wrapIgnoreNull(serialize); this.on('finish', function() { - console.log('Send close from client'); var batch = {}; batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; call.startBatch(batch, function() {}); @@ -73,7 +72,6 @@ function ClientWritableStream(call, serialize) { function _write(chunk, encoding, callback) { var batch = {}; batch[grpc.opType.SEND_MESSAGE] = this.serialize(chunk); - console.log(batch); this.call.startBatch(batch, function(err, event) { if (err) { throw err; @@ -153,7 +151,6 @@ function ClientDuplexStream(call, serialize, deserialize) { var reading = false; this.call = call; this.on('finish', function() { - console.log('Send close from client'); var batch = {}; batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; call.startBatch(batch, function() {}); @@ -279,7 +276,6 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { callback(err); return; } - console.log(response); if (response.status.code != grpc.status.OK) { callback(response.status); return; @@ -323,7 +319,6 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { } var stream = new ClientReadableStream(call, deserialize); var start_batch = {}; - console.log('Starting server streaming request on', method); start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; start_batch[grpc.opType.SEND_MESSAGE] = serialize(argument); @@ -332,7 +327,6 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { if (err) { throw err; } - console.log(response); stream.emit('metadata', response.metadata); }); var status_batch = {}; diff --git a/src/node/src/server.js b/src/node/src/server.js index 3c214913195..82d521ddf12 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -95,7 +95,6 @@ function setUpWritable(stream, serialize) { }; stream.serialize = common.wrapIgnoreNull(serialize); function sendStatus() { - console.log('Server sending status'); var batch = {}; batch[grpc.opType.SEND_STATUS_FROM_SERVER] = stream.status; stream.call.startBatch(batch, function(){}); @@ -169,7 +168,6 @@ function ServerWritableStream(call, serialize) { function _write(chunk, encoding, callback) { var batch = {}; batch[grpc.opType.SEND_MESSAGE] = this.serialize(chunk); - console.log('Server writing', batch); this.call.startBatch(batch, function(err, value) { if (err) { this.emit('error', err); @@ -207,14 +205,11 @@ function _read(size) { return; } if (self.finished) { - console.log('Pushing null'); self.push(null); return; } var data = event.read; - console.log(data); if (self.push(self.deserialize(data)) && data != null) { - console.log('Reading again'); var read_batch = {}; read_batch[grpc.opType.RECV_MESSAGE] = true; self.call.startBatch(read_batch, readCallback); @@ -276,7 +271,6 @@ function handleUnary(call, handler, metadata) { } function handleServerStreaming(call, handler, metadata) { - console.log('Handling server streaming call'); var stream = new ServerWritableStream(call, handler.serialize); waitForCancel(call, stream); var batch = {}; @@ -360,7 +354,6 @@ function Server(getMetadata, options) { * @param {grpc.Event} event The event to handle with tag SERVER_RPC_NEW */ function handleNewCall(err, event) { - console.log('Handling new call'); if (err) { return; } @@ -376,9 +369,7 @@ function Server(getMetadata, options) { var deadline = details.deadline; if (handlers.hasOwnProperty(method)) { handler = handlers[method]; - console.log(handler); } else { - console.log(handlers); var batch = {}; batch[grpc.opType.SEND_INITIAL_METADATA] = {}; batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js index 34ce2500f6c..f8899beae82 100644 --- a/src/node/test/end_to_end_test.js +++ b/src/node/test/end_to_end_test.js @@ -148,7 +148,6 @@ describe('end-to-end', function() { }); server.requestCall(function(err, call_details) { - console.log("Server received new call"); var new_call = call_details['new call']; assert.notEqual(new_call, null); assert.strictEqual(new_call.metadata.client_key[0].toString(), From c55ee616b58ce06916661ddaf585711a987a2da2 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 12 Feb 2015 13:58:24 -0800 Subject: [PATCH 14/31] Last test now passes --- src/node/test/call_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js index 1cbfc2280ce..c1a7e95fa09 100644 --- a/src/node/test/call_test.js +++ b/src/node/test/call_test.js @@ -111,7 +111,7 @@ describe('call', function() { call.startBatch(null, function(){}); }); }); - it.skip('should succeed with an empty object', function(done) { + it('should succeed with an empty object', function(done) { var call = new grpc.Call(channel, 'method', getDeadline(1)); assert.doesNotThrow(function() { call.startBatch({}, function(err) { From 44dd2f33679e1b8a35d7c3f37a719279988419a7 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 12 Feb 2015 15:48:51 -0800 Subject: [PATCH 15/31] Removed extraneous log messages --- src/node/ext/call.cc | 6 ------ src/node/ext/completion_queue_async_worker.cc | 2 -- src/node/ext/credentials.cc | 1 - src/node/ext/server.cc | 1 - src/node/ext/server_credentials.cc | 1 - 5 files changed, 11 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index cdc34b52a74..4401698b1e5 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -98,9 +98,6 @@ bool CreateMetadataArray( string_handles->push_back(unique_ptr(utf8_key)); Handle values = Local::Cast(metadata->Get(current_key)); for (unsigned int j = 0; j < values->Length(); j++) { - if (array->count >= array->capacity) { - gpr_log(GPR_ERROR, "Metadata array grew past capacity"); - } Handle value = values->Get(j); grpc_metadata *current = &array->metadata[array->count]; current->key = **utf8_key; @@ -447,11 +444,9 @@ void DestroyTag(void *tag) { } Call::Call(grpc_call *call) : wrapped_call(call) { - gpr_log(GPR_DEBUG, "Constructing call, this: %p, pointer: %p", this, call); } Call::~Call() { - gpr_log(GPR_DEBUG, "Destructing call, this: %p, pointer: %p", this, wrapped_call); grpc_call_destroy(wrapped_call); } @@ -483,7 +478,6 @@ Handle Call::WrapStruct(grpc_call *call) { if (call == NULL) { return NanEscapeScope(NanNull()); } - gpr_log(GPR_DEBUG, "Wrapping call: %p", call); const int argc = 1; Handle argv[argc] = {External::New(reinterpret_cast(call))}; return NanEscapeScope(constructor->NewInstance(argc, argv)); diff --git a/src/node/ext/completion_queue_async_worker.cc b/src/node/ext/completion_queue_async_worker.cc index 3c32b07ca33..a1f390f64b6 100644 --- a/src/node/ext/completion_queue_async_worker.cc +++ b/src/node/ext/completion_queue_async_worker.cc @@ -58,7 +58,6 @@ CompletionQueueAsyncWorker::~CompletionQueueAsyncWorker() {} void CompletionQueueAsyncWorker::Execute() { result = grpc_completion_queue_next(queue, gpr_inf_future); - gpr_log(GPR_DEBUG, "Handling response on call %p", result->call); if (result->data.op_complete != GRPC_OP_OK) { SetErrorMessage("The batch encountered an error"); } @@ -79,7 +78,6 @@ void CompletionQueueAsyncWorker::Init(Handle exports) { void CompletionQueueAsyncWorker::HandleOKCallback() { NanScope(); - gpr_log(GPR_DEBUG, "Handling response on call %p", result->call); NanCallback *callback = GetTagCallback(result->tag); Handle argv[] = {NanNull(), GetTagNodeValue(result->tag)}; diff --git a/src/node/ext/credentials.cc b/src/node/ext/credentials.cc index c8859ed9410..b79c3e3019d 100644 --- a/src/node/ext/credentials.cc +++ b/src/node/ext/credentials.cc @@ -63,7 +63,6 @@ Credentials::Credentials(grpc_credentials *credentials) : wrapped_credentials(credentials) {} Credentials::~Credentials() { - gpr_log(GPR_DEBUG, "Destroying credentials object"); grpc_credentials_release(wrapped_credentials); } diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index 93aa9ec44d4..51904479a9a 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -91,7 +91,6 @@ class NewCallOp : public Op { return NanEscapeScope(NanNull()); } Handle obj = NanNew(); - gpr_log(GPR_DEBUG, "Wrapping server call: %p", call); obj->Set(NanNew("call"), Call::WrapStruct(call)); obj->Set(NanNew("method"), NanNew(details.method)); obj->Set(NanNew("host"), NanNew(details.host)); diff --git a/src/node/ext/server_credentials.cc b/src/node/ext/server_credentials.cc index 393f3a63052..3add43c48c9 100644 --- a/src/node/ext/server_credentials.cc +++ b/src/node/ext/server_credentials.cc @@ -63,7 +63,6 @@ ServerCredentials::ServerCredentials(grpc_server_credentials *credentials) : wrapped_credentials(credentials) {} ServerCredentials::~ServerCredentials() { - gpr_log(GPR_DEBUG, "Destroying server credentials object"); grpc_server_credentials_release(wrapped_credentials); } From 17be589de0c41807b14fe47165e165c7d64deb9c Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Feb 2015 10:19:10 -0800 Subject: [PATCH 16/31] Made changes based on comments --- src/node/ext/call.cc | 86 +++++++++++++++++------------------------- src/node/ext/call.h | 15 +++++--- src/node/ext/server.cc | 6 +-- 3 files changed, 46 insertions(+), 61 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 4401698b1e5..18f40f2488e 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -48,6 +48,7 @@ #include "timeval.h" using std::unique_ptr; +using std::shared_ptr; namespace grpc { namespace node { @@ -76,10 +77,8 @@ Persistent Call::constructor; Persistent Call::fun_tpl; -bool CreateMetadataArray( - Handle metadata, grpc_metadata_array *array, - std::vector > *string_handles, - std::vector > *handles) { +bool CreateMetadataArray(Handle metadata, grpc_metadata_array *array, + shared_ptr resources) { NanScope(); grpc_metadata_array_init(array); Handle keys(metadata->GetOwnPropertyNames()); @@ -95,7 +94,7 @@ bool CreateMetadataArray( for (unsigned int i = 0; i < keys->Length(); i++) { Handle current_key(keys->Get(i)->ToString()); NanUtf8String *utf8_key = new NanUtf8String(current_key); - string_handles->push_back(unique_ptr(utf8_key)); + resources->strings.push_back(unique_ptr(utf8_key)); Handle values = Local::Cast(metadata->Get(current_key)); for (unsigned int j = 0; j < values->Length(); j++) { Handle value = values->Get(j); @@ -106,12 +105,12 @@ bool CreateMetadataArray( current->value_length = Buffer::Length(value); Persistent handle; NanAssignPersistent(handle, value); - handles->push_back(unique_ptr( + resources->handles.push_back(unique_ptr( new PersistentHolder(handle))); } else if (value->IsString()) { Handle string_value = value->ToString(); NanUtf8String *utf8_value = new NanUtf8String(string_value); - string_handles->push_back(unique_ptr(utf8_value)); + resources->strings.push_back(unique_ptr(utf8_value)); current->value = **utf8_value; current->value_length = string_value->Length(); } else { @@ -168,13 +167,12 @@ class SendMetadataOp : public Op { return NanEscapeScope(NanTrue()); } bool ParseOp(Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) { + shared_ptr resources) { if (!value->IsObject()) { return false; } grpc_metadata_array array; - if (!CreateMetadataArray(value->ToObject(), &array, strings, handles)) { + if (!CreateMetadataArray(value->ToObject(), &array, resources)) { return false; } out->data.send_initial_metadata.count = array.count; @@ -194,8 +192,7 @@ class SendMessageOp : public Op { return NanEscapeScope(NanTrue()); } bool ParseOp(Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) { + shared_ptr resources) { if (!Buffer::HasInstance(value)) { return false; } @@ -204,7 +201,7 @@ class SendMessageOp : public Op { Handle temp = NanNew(); NanAssignPersistent(handle, temp); NanAssignPersistent(handle, value); - handles->push_back(unique_ptr( + resources->handles.push_back(unique_ptr( new PersistentHolder(handle))); return true; } @@ -221,8 +218,7 @@ class SendClientCloseOp : public Op { return NanEscapeScope(NanTrue()); } bool ParseOp(Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) { + shared_ptr resources) { return true; } protected: @@ -238,8 +234,7 @@ class SendServerStatusOp : public Op { return NanEscapeScope(NanTrue()); } bool ParseOp(Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) { + shared_ptr resources) { if (!value->IsObject()) { return false; } @@ -256,7 +251,7 @@ class SendServerStatusOp : public Op { grpc_metadata_array array; if (!CreateMetadataArray(server_status->Get(NanNew("metadata"))-> ToObject(), - &array, strings, handles)) { + &array, resources)) { return false; } out->data.send_status_from_server.trailing_metadata_count = array.count; @@ -266,7 +261,7 @@ class SendServerStatusOp : public Op { server_status->Get(NanNew("code"))->Uint32Value()); NanUtf8String *str = new NanUtf8String( server_status->Get(NanNew("details"))); - strings->push_back(unique_ptr(str)); + resources->strings.push_back(unique_ptr(str)); out->data.send_status_from_server.status_details = **str; return true; } @@ -292,8 +287,7 @@ class GetMetadataOp : public Op { } bool ParseOp(Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) { + shared_ptr resources) { out->data.recv_initial_metadata = &recv_metadata; return true; } @@ -323,8 +317,7 @@ class ReadMessageOp : public Op { } bool ParseOp(Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) { + shared_ptr resources) { out->data.recv_message = &recv_message; return true; } @@ -352,8 +345,7 @@ class ClientStatusOp : public Op { } bool ParseOp(Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) { + shared_ptr resources) { out->data.recv_status_on_client.trailing_metadata = &metadata_array; out->data.recv_status_on_client.status = &status; out->data.recv_status_on_client.status_details = &status_details; @@ -390,8 +382,7 @@ class ServerCloseResponseOp : public Op { } bool ParseOp(Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) { + shared_ptr resources) { out->data.recv_close_on_server.cancelled = &cancelled; return true; } @@ -406,19 +397,13 @@ class ServerCloseResponseOp : public Op { }; tag::tag(NanCallback *callback, std::vector > *ops, - std::vector > *handles, - std::vector > *strings) : - callback(callback), ops(ops), handles(handles), strings(strings){ + shared_ptr resources) : + callback(callback), ops(ops), resources(resources){ } + tag::~tag() { delete callback; delete ops; - if (handles != NULL) { - delete handles; - } - if (strings != NULL) { - delete strings; - } } Handle GetTagNodeValue(void *tag) { @@ -542,17 +527,14 @@ NAN_METHOD(Call::StartBatch) { Handle callback_func = args[1].As(); NanCallback *callback = new NanCallback(callback_func); Call *call = ObjectWrap::Unwrap(args.This()); - std::vector > *handles = - new std::vector >(); - std::vector > *strings = - new std::vector >(); + shared_ptr resources(new Resources); Handle obj = args[0]->ToObject(); Handle keys = obj->GetOwnPropertyNames(); size_t nops = keys->Length(); grpc_op *ops = new grpc_op[nops]; std::vector > *op_vector = new std::vector >(); for (unsigned int i = 0; i < nops; i++) { - Op *op; + unique_ptr op; if (!keys->Get(i)->IsUint32()) { return NanThrowError( "startBatch's first argument's keys must be integers"); @@ -561,40 +543,40 @@ NAN_METHOD(Call::StartBatch) { ops[i].op = static_cast(type); switch (type) { case GRPC_OP_SEND_INITIAL_METADATA: - op = new SendMetadataOp(); + op.reset(new SendMetadataOp()); break; case GRPC_OP_SEND_MESSAGE: - op = new SendMessageOp(); + op.reset(new SendMessageOp()); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - op = new SendClientCloseOp(); + op.reset(new SendClientCloseOp()); break; case GRPC_OP_SEND_STATUS_FROM_SERVER: - op = new SendServerStatusOp(); + op.reset(new SendServerStatusOp()); break; case GRPC_OP_RECV_INITIAL_METADATA: - op = new GetMetadataOp(); + op.reset(new GetMetadataOp()); break; case GRPC_OP_RECV_MESSAGE: - op = new ReadMessageOp(); + op.reset(new ReadMessageOp()); break; case GRPC_OP_RECV_STATUS_ON_CLIENT: - op = new ClientStatusOp(); + op.reset(new ClientStatusOp()); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: - op = new ServerCloseResponseOp(); + op.reset(new ServerCloseResponseOp()); break; default: return NanThrowError("Argument object had an unrecognized key"); } - if (!op->ParseOp(obj->Get(type), &ops[i], strings, handles)) { + if (!op->ParseOp(obj->Get(type), &ops[i], resources)) { return NanThrowTypeError("Incorrectly typed arguments to startBatch"); } - op_vector->push_back(unique_ptr(op)); + op_vector->push_back(std::move(op)); } grpc_call_error error = grpc_call_start_batch( call->wrapped_call, ops, nops, new struct tag( - callback, op_vector, handles, strings)); + callback, op_vector, resources)); delete ops; if (error != GRPC_CALL_OK) { return NanThrowError("startBatch failed", error); diff --git a/src/node/ext/call.h b/src/node/ext/call.h index f443a04637f..4074f1509bf 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -47,6 +47,7 @@ namespace grpc { namespace node { using std::unique_ptr; +using std::shared_ptr; v8::Handle ParseMetadata(const grpc_metadata_array *metadata_array); @@ -64,12 +65,16 @@ class PersistentHolder { v8::Persistent persist; }; +struct Resources { + std::vector > strings; + std::vector > handles; +}; + class Op { public: virtual v8::Handle GetNodeValue() const = 0; virtual bool ParseOp(v8::Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) = 0; + shared_ptr resources) = 0; v8::Handle GetOpType() const; protected: @@ -78,13 +83,11 @@ class Op { struct tag { tag(NanCallback *callback, std::vector > *ops, - std::vector > *handles, - std::vector > *strings); + shared_ptr resources); ~tag(); NanCallback *callback; std::vector > *ops; - std::vector > *handles; - std::vector > *strings; + shared_ptr resources; }; v8::Handle GetTagNodeValue(void *tag); diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index 51904479a9a..6a4a9511216 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -101,8 +101,7 @@ class NewCallOp : public Op { } bool ParseOp(Handle value, grpc_op *out, - std::vector > *strings, - std::vector > *handles) { + shared_ptr resources) { return true; } @@ -230,7 +229,8 @@ NAN_METHOD(Server::RequestCall) { grpc_call_error error = grpc_server_request_call( server->wrapped_server, &op->call, &op->details, &op->request_metadata, CompletionQueueAsyncWorker::GetQueue(), - new struct tag(new NanCallback(args[0].As()), ops, NULL, NULL)); + new struct tag(new NanCallback(args[0].As()), ops, + shared_ptr(nullptr))); if (error != GRPC_CALL_OK) { return NanThrowError("requestCall failed", error); } From d66408ba5a23bdaac9a9764cc28ffe13edbfafea Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Feb 2015 10:40:07 -0800 Subject: [PATCH 17/31] Improved memory management --- src/node/ext/call.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 18f40f2488e..4d719802fc7 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -531,7 +531,7 @@ NAN_METHOD(Call::StartBatch) { Handle obj = args[0]->ToObject(); Handle keys = obj->GetOwnPropertyNames(); size_t nops = keys->Length(); - grpc_op *ops = new grpc_op[nops]; + std::vector ops(nops); std::vector > *op_vector = new std::vector >(); for (unsigned int i = 0; i < nops; i++) { unique_ptr op; @@ -575,9 +575,8 @@ NAN_METHOD(Call::StartBatch) { op_vector->push_back(std::move(op)); } grpc_call_error error = grpc_call_start_batch( - call->wrapped_call, ops, nops, new struct tag( + call->wrapped_call, &ops[0], nops, new struct tag( callback, op_vector, resources)); - delete ops; if (error != GRPC_CALL_OK) { return NanThrowError("startBatch failed", error); } From 57dfd058510d1a3be0ce315ff51fb9f793befd64 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Feb 2015 10:41:25 -0800 Subject: [PATCH 18/31] Further improved memory management --- src/node/ext/call.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 4d719802fc7..e6701efbd4b 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -525,7 +525,6 @@ NAN_METHOD(Call::StartBatch) { return NanThrowError("startBatch's second argument must be a callback"); } Handle callback_func = args[1].As(); - NanCallback *callback = new NanCallback(callback_func); Call *call = ObjectWrap::Unwrap(args.This()); shared_ptr resources(new Resources); Handle obj = args[0]->ToObject(); @@ -574,6 +573,7 @@ NAN_METHOD(Call::StartBatch) { } op_vector->push_back(std::move(op)); } + NanCallback *callback = new NanCallback(callback_func); grpc_call_error error = grpc_call_start_batch( call->wrapped_call, &ops[0], nops, new struct tag( callback, op_vector, resources)); From e012366e25b0e73fdd9e071798e6e0036eadad5d Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Feb 2015 11:14:03 -0800 Subject: [PATCH 19/31] Improved op_vector memory management --- src/node/ext/call.cc | 11 ++++++----- src/node/ext/call.h | 7 +++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index e6701efbd4b..a2333fa4268 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -49,6 +49,7 @@ using std::unique_ptr; using std::shared_ptr; +using std::vector; namespace grpc { namespace node { @@ -396,7 +397,7 @@ class ServerCloseResponseOp : public Op { int cancelled; }; -tag::tag(NanCallback *callback, std::vector > *ops, +tag::tag(NanCallback *callback, OpVec *ops, shared_ptr resources) : callback(callback), ops(ops), resources(resources){ } @@ -410,7 +411,7 @@ Handle GetTagNodeValue(void *tag) { NanEscapableScope(); struct tag *tag_struct = reinterpret_cast(tag); Handle tag_obj = NanNew(); - for (std::vector >::iterator it = tag_struct->ops->begin(); + for (vector >::iterator it = tag_struct->ops->begin(); it != tag_struct->ops->end(); ++it) { Op *op_ptr = it->get(); tag_obj->Set(op_ptr->GetOpType(), op_ptr->GetNodeValue()); @@ -530,8 +531,8 @@ NAN_METHOD(Call::StartBatch) { Handle obj = args[0]->ToObject(); Handle keys = obj->GetOwnPropertyNames(); size_t nops = keys->Length(); - std::vector ops(nops); - std::vector > *op_vector = new std::vector >(); + vector ops(nops); + unique_ptr op_vector(new OpVec()); for (unsigned int i = 0; i < nops; i++) { unique_ptr op; if (!keys->Get(i)->IsUint32()) { @@ -576,7 +577,7 @@ NAN_METHOD(Call::StartBatch) { NanCallback *callback = new NanCallback(callback_func); grpc_call_error error = grpc_call_start_batch( call->wrapped_call, &ops[0], nops, new struct tag( - callback, op_vector, resources)); + callback, op_vector.release(), resources)); if (error != GRPC_CALL_OK) { return NanThrowError("startBatch failed", error); } diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 4074f1509bf..dbdb8e2ff65 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -43,6 +43,7 @@ #include "channel.h" + namespace grpc { namespace node { @@ -81,12 +82,14 @@ class Op { virtual std::string GetTypeString() const = 0; }; +typedef std::vector> OpVec; + struct tag { - tag(NanCallback *callback, std::vector > *ops, + tag(NanCallback *callback, OpVec *ops, shared_ptr resources); ~tag(); NanCallback *callback; - std::vector > *ops; + OpVec *ops; shared_ptr resources; }; From d3f9f9f5493710515d0a82b590261294bb966859 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Feb 2015 12:21:59 -0800 Subject: [PATCH 20/31] Updated server.cc to match call.cc changes --- src/node/ext/server.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index 6a4a9511216..ee3e1087ce7 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -224,12 +224,12 @@ NAN_METHOD(Server::RequestCall) { } Server *server = ObjectWrap::Unwrap(args.This()); NewCallOp *op = new NewCallOp(); - std::vector > *ops = new std::vector >(); + unique_ptr ops(new OpVec()); ops->push_back(unique_ptr(op)); grpc_call_error error = grpc_server_request_call( server->wrapped_server, &op->call, &op->details, &op->request_metadata, CompletionQueueAsyncWorker::GetQueue(), - new struct tag(new NanCallback(args[0].As()), ops, + new struct tag(new NanCallback(args[0].As()), ops.release(), shared_ptr(nullptr))); if (error != GRPC_CALL_OK) { return NanThrowError("requestCall failed", error); From 42683db2d89f30f2458b7689cd6b2be60b0a560b Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Feb 2015 13:02:47 -0800 Subject: [PATCH 21/31] Removed debugging code --- src/node/ext/call.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index a2333fa4268..9ed389f3bc5 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -199,8 +199,6 @@ class SendMessageOp : public Op { } out->data.send_message = BufferToByteBuffer(value); Persistent handle; - Handle temp = NanNew(); - NanAssignPersistent(handle, temp); NanAssignPersistent(handle, value); resources->handles.push_back(unique_ptr( new PersistentHolder(handle))); From b3a4e03b2df42d8480a215f0ea3165514f0ed4f4 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 13 Feb 2015 14:10:13 -0800 Subject: [PATCH 22/31] Version bump --- src/node/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node/package.json b/src/node/package.json index 028dc20555b..8f81014c1e8 100644 --- a/src/node/package.json +++ b/src/node/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "0.1.0", + "version": "0.2.0", "description": "gRPC Library for Node", "scripts": { "test": "./node_modules/mocha/bin/mocha" From 1fe7b9d66a34d774e8a26ff7409b8739c4c2db58 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 17 Feb 2015 11:57:02 -0800 Subject: [PATCH 23/31] Fix a race in transport. I removed the condition variable here a little while ago to remove a thundering herd. Unfortunately it introduces a race if we are calling back an application defined object whilst destroying. Reintroduce the cv, and guard it's usage closely to avoid the herd (additionally, it's not needed for stream deletion, so we keep it out of that). --- src/core/transport/chttp2_transport.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 8b1fb789172..5921c3806ec 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -184,11 +184,13 @@ struct transport { gpr_uint8 is_client; gpr_mu mu; + gpr_cv cv; /* basic state management - what are we doing at the moment? */ gpr_uint8 reading; gpr_uint8 writing; gpr_uint8 calling_back; + gpr_uint8 destroying; error_state error_state; /* stream indexing */ @@ -362,6 +364,7 @@ static void unref_transport(transport *t) { gpr_mu_unlock(&t->mu); gpr_mu_destroy(&t->mu); + gpr_cv_destroy(&t->cv); /* callback remaining pings: they're not allowed to call into the transpot, and maybe they hold resources that need to be freed */ @@ -397,6 +400,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup, /* one ref is for destroy, the other for when ep becomes NULL */ gpr_ref_init(&t->refs, 2); gpr_mu_init(&t->mu); + gpr_cv_init(&t->cv); t->metadata_context = mdctx; t->str_grpc_timeout = grpc_mdstr_from_string(t->metadata_context, "grpc-timeout"); @@ -405,6 +409,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup, t->error_state = ERROR_STATE_NONE; t->next_stream_id = is_client ? 1 : 2; t->last_incoming_stream_id = 0; + t->destroying = 0; t->is_client = is_client; t->outgoing_window = DEFAULT_WINDOW; t->incoming_window = DEFAULT_WINDOW; @@ -487,6 +492,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup, t->cb = sr.callbacks; t->cb_user_data = sr.user_data; t->calling_back = 0; + if (t->destroying) gpr_cv_signal(&t->cv); unlock(t); unref_transport(t); } @@ -495,6 +501,10 @@ static void destroy_transport(grpc_transport *gt) { transport *t = (transport *)gt; gpr_mu_lock(&t->mu); + t->destroying = 1; + while (t->calling_back) { + gpr_cv_wait(&t->cv, &t->mu, gpr_inf_future); + } t->cb = NULL; gpr_mu_unlock(&t->mu); @@ -754,6 +764,7 @@ static void unlock(transport *t) { if (perform_callbacks || call_closed || num_goaways) { lock(t); t->calling_back = 0; + if (t->destroying) gpr_cv_signal(&t->cv); unlock(t); unref_transport(t); } From 23139ae24e94b2d51505836f7746e8f122c96f45 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 17 Feb 2015 15:46:13 -0800 Subject: [PATCH 24/31] Add checking on fd_posix refcounts --- src/core/iomgr/fd_posix.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index 737ee016aab..cc578305513 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -104,14 +104,17 @@ static void destroy(grpc_fd *fd) { } static void ref_by(grpc_fd *fd, int n) { - gpr_atm_no_barrier_fetch_add(&fd->refst, n); + GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); } static void unref_by(grpc_fd *fd, int n) { - if (gpr_atm_full_fetch_add(&fd->refst, -n) == n) { + gpr_atm old = gpr_atm_full_fetch_add(&fd->refst, -n); + if (old == n) { grpc_iomgr_add_callback(fd->on_done, fd->on_done_user_data); freelist_fd(fd); grpc_iomgr_unref(); + } else { + GPR_ASSERT(old > n); } } From fc3aca2ea8602e9cfbd52a7c10b64b34c7aeac86 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 17 Feb 2015 15:46:33 -0800 Subject: [PATCH 25/31] Add missing ref This prevents a bug whereby not all fds were destroyed at application exit. --- src/core/iomgr/pollset_posix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 53c9806fb9b..1245d22ddee 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -214,6 +214,7 @@ static void unary_poll_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) { * unary poller */ grpc_fd_unref(fds[0]); pollset->data.ptr = fd; + grpc_fd_ref(fd); } } From 5882b53e9426fb9a55cfc2bf8f9ad09e1feb49df Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 17 Feb 2015 15:51:43 -0800 Subject: [PATCH 26/31] Fixing memleak. - Fixes #542 --- src/core/security/security_context.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index adb02697925..1909617614d 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -349,11 +349,13 @@ static grpc_security_status ssl_channel_check_peer(grpc_security_context *ctx, void *user_data) { grpc_ssl_channel_security_context *c = (grpc_ssl_channel_security_context *)ctx; - grpc_security_status status = ssl_check_peer(c->overridden_target_name != NULL - ? c->overridden_target_name - : c->target_name, - &peer); + grpc_security_status status; + tsi_peer_destruct(&c->peer); c->peer = peer; + status = ssl_check_peer(c->overridden_target_name != NULL + ? c->overridden_target_name + : c->target_name, + &peer); return status; } From ffbcaaf18ecc4aabdc3938c8ccaccc554c35da60 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 17 Feb 2015 16:23:06 -0800 Subject: [PATCH 27/31] Added missing documentation --- src/node/src/client.js | 25 ++++++++++- src/node/src/server.js | 97 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 117 insertions(+), 5 deletions(-) diff --git a/src/node/src/client.js b/src/node/src/client.js index 4b7eda324ee..81fa65eb263 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -51,6 +51,13 @@ var util = require('util'); util.inherits(ClientWritableStream, Writable); +/** + * A stream that the client can write to. Used for calls that are streaming from + * the client side. + * @constructor + * @param {grpc.Call} call The call object to send data with + * @param {function(*):Buffer=} serialize Serialization function for writes. + */ function ClientWritableStream(call, serialize) { Writable.call(this, {objectMode: true}); this.call = call; @@ -84,6 +91,13 @@ ClientWritableStream.prototype._write = _write; util.inherits(ClientReadableStream, Readable); +/** + * A stream that the client can read from. Used for calls that are streaming + * from the server side. + * @constructor + * @param {grpc.Call} call The call object to read data with + * @param {function(Buffer):*=} deserialize Deserialization function for reads + */ function ClientReadableStream(call, deserialize) { Readable.call(this, {objectMode: true}); this.call = call; @@ -92,6 +106,10 @@ function ClientReadableStream(call, deserialize) { this.deserialize = common.wrapIgnoreNull(deserialize); } +/** + * Read the next object from the stream. + * @param {*} size Ignored because we use objectMode=true + */ function _read(size) { var self = this; /** @@ -133,8 +151,8 @@ ClientReadableStream.prototype._read = _read; util.inherits(ClientDuplexStream, Duplex); /** - * Class for representing a gRPC client side stream as a Node stream. Extends - * from stream.Duplex. + * A stream that the client can read from or write to. Used for calls with + * duplex streaming. * @constructor * @param {grpc.Call} call Call object to proxy * @param {function(*):Buffer=} serialize Serialization function for requests @@ -160,6 +178,9 @@ function ClientDuplexStream(call, serialize, deserialize) { ClientDuplexStream.prototype._read = _read; ClientDuplexStream.prototype._write = _write; +/** + * Cancel the ongoing call + */ function cancel() { this.call.cancel(); } diff --git a/src/node/src/server.js b/src/node/src/server.js index 82d521ddf12..48c349ef99d 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -51,16 +51,38 @@ var EventEmitter = require('events').EventEmitter; var common = require('./common.js'); +/** + * Handle an error on a call by sending it as a status + * @param {grpc.Call} call The call to send the error on + * @param {Object} error The error object + */ function handleError(call, error) { - var error_batch = {}; - error_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { + var status = { code: grpc.status.INTERNAL, details: 'Unknown Error', metadata: {} }; + if (error.hasOwnProperty('message')) { + status.details = error.message; + } + if (error.hasOwnProperty('code')) { + status.code = error.code; + if (error.hasOwnProperty('details')) { + status.details = error.details; + } + } + var error_batch = {}; + error_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status; call.startBatch(error_batch, function(){}); } +/** + * Wait for the client to close, then emit a cancelled event if the client + * cancelled. + * @param {grpc.Call} call The call object to wait on + * @param {EventEmitter} emitter The event emitter to emit the cancelled event + * on + */ function waitForCancel(call, emitter) { var cancel_batch = {}; cancel_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; @@ -75,6 +97,13 @@ function waitForCancel(call, emitter) { }); } +/** + * Send a response to a unary or client streaming call. + * @param {grpc.Call} call The call to respond on + * @param {*} value The value to respond with + * @param {function(*):Buffer=} serialize Serialization function for the + * response + */ function sendUnaryResponse(call, value, serialize) { var end_batch = {}; end_batch[grpc.opType.SEND_MESSAGE] = serialize(value); @@ -86,6 +115,12 @@ function sendUnaryResponse(call, value, serialize) { call.startBatch(end_batch, function (){}); } +/** + * Initialize a writable stream. This is used for both the writable and duplex + * stream constructors. + * @param {Writable} stream The stream to set up + * @param {function(*):Buffer=} Serialization function for responses + */ function setUpWritable(stream, serialize) { stream.finished = false; stream.status = { @@ -109,7 +144,9 @@ function setUpWritable(stream, serialize) { function setStatus(err) { var code = grpc.status.INTERNAL; var details = 'Unknown Error'; - + if (err.hasOwnProperty('message')) { + details = err.message; + } if (err.hasOwnProperty('code')) { code = err.code; if (err.hasOwnProperty('details')) { @@ -132,6 +169,13 @@ function setUpWritable(stream, serialize) { stream.on('error', terminateCall); } +/** + * Initialize a readable stream. This is used for both the readable and duplex + * stream constructors. + * @param {Readable} stream The stream to initialize + * @param {function(Buffer):*=} deserialize Deserialization function for + * incoming data. + */ function setUpReadable(stream, deserialize) { stream.deserialize = common.wrapIgnoreNull(deserialize); stream.finished = false; @@ -149,6 +193,13 @@ function setUpReadable(stream, deserialize) { util.inherits(ServerWritableStream, Writable); +/** + * A stream that the server can write to. Used for calls that are streaming from + * the server side. + * @constructor + * @param {grpc.Call} call The call object to send data with + * @param {function(*):Buffer=} serialize Serialization function for writes + */ function ServerWritableStream(call, serialize) { Writable.call(this, {objectMode: true}); this.call = call; @@ -181,6 +232,13 @@ ServerWritableStream.prototype._write = _write; util.inherits(ServerReadableStream, Readable); +/** + * A stream that the server can read from. Used for calls that are streaming + * from the client side. + * @constructor + * @param {grpc.Call} call The call object to read data with + * @param {function(Buffer):*=} deserialize Deserialization function for reads + */ function ServerReadableStream(call, deserialize) { Readable.call(this, {objectMode: true}); this.call = call; @@ -233,6 +291,15 @@ ServerReadableStream.prototype._read = _read; util.inherits(ServerDuplexStream, Duplex); +/** + * A stream that the server can read from or write to. Used for calls with + * duplex streaming. + * @constructor + * @param {grpc.Call} call Call object to proxy + * @param {function(*):Buffer=} serialize Serialization function for requests + * @param {function(Buffer):*=} deserialize Deserialization function for + * responses + */ function ServerDuplexStream(call, serialize, deserialize) { Duplex.call(this, {objectMode: true}); this.call = call; @@ -243,6 +310,12 @@ function ServerDuplexStream(call, serialize, deserialize) { ServerDuplexStream.prototype._read = _read; ServerDuplexStream.prototype._write = _write; +/** + * Fully handle a unary call + * @param {grpc.Call} call The call to handle + * @param {Object} handler Request handler object for the method that was called + * @param {Object} metadata Metadata from the client + */ function handleUnary(call, handler, metadata) { var emitter = new EventEmitter(); emitter.on('error', function(error) { @@ -270,6 +343,12 @@ function handleUnary(call, handler, metadata) { }); } +/** + * Fully handle a server streaming call + * @param {grpc.Call} call The call to handle + * @param {Object} handler Request handler object for the method that was called + * @param {Object} metadata Metadata from the client + */ function handleServerStreaming(call, handler, metadata) { var stream = new ServerWritableStream(call, handler.serialize); waitForCancel(call, stream); @@ -286,6 +365,12 @@ function handleServerStreaming(call, handler, metadata) { }); } +/** + * Fully handle a client streaming call + * @param {grpc.Call} call The call to handle + * @param {Object} handler Request handler object for the method that was called + * @param {Object} metadata Metadata from the client + */ function handleClientStreaming(call, handler, metadata) { var stream = new ServerReadableStream(call, handler.deserialize); waitForCancel(call, stream); @@ -301,6 +386,12 @@ function handleClientStreaming(call, handler, metadata) { }); } +/** + * Fully handle a bidirectional streaming call + * @param {grpc.Call} call The call to handle + * @param {Object} handler Request handler object for the method that was called + * @param {Object} metadata Metadata from the client + */ function handleBidiStreaming(call, handler, metadata) { var stream = new ServerDuplexStream(call, handler.serialize, handler.deserialize); From aa31da4ffe0703292a9d76b0c543a0fb7e60f0a1 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 17 Feb 2015 16:33:35 -0800 Subject: [PATCH 28/31] UDS Fix Remove existing UDS listeners IFF they are a socket before trying to create a new socket. --- src/core/iomgr/tcp_server_posix.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/core/iomgr/tcp_server_posix.c b/src/core/iomgr/tcp_server_posix.c index 6a961637188..9e5076efc71 100644 --- a/src/core/iomgr/tcp_server_posix.c +++ b/src/core/iomgr/tcp_server_posix.c @@ -42,17 +42,18 @@ #include "src/core/iomgr/tcp_server.h" -#include +#include #include +#include #include #include #include +#include +#include +#include #include #include -#include #include -#include -#include #include "src/core/iomgr/pollset_posix.h" #include "src/core/iomgr/resolve_address.h" @@ -83,6 +84,14 @@ typedef struct { int addr_len; } server_port; +static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) { + struct stat st; + + if (stat(un->sun_path, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) { + unlink(un->sun_path); + } +} + /* the overall server */ struct grpc_tcp_server { grpc_tcp_server_cb cb; @@ -130,7 +139,7 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s) { for (i = 0; i < s->nports; i++) { server_port *sp = &s->ports[i]; if (sp->addr.sockaddr.sa_family == AF_UNIX) { - unlink(sp->addr.un.sun_path); + unlink_if_unix_domain_socket(&sp->addr.un); } grpc_fd_orphan(sp->emfd, NULL, NULL); } @@ -301,6 +310,10 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr, socklen_t sockname_len; int port; + if (((struct sockaddr *)addr)->sa_family == AF_UNIX) { + unlink_if_unix_domain_socket(addr); + } + /* Check if this is a wildcard port, and if so, try to keep the port the same as some previously created listener. */ if (grpc_sockaddr_get_port(addr) == 0) { From d251ab9e71dc58ae5675777190ad84ed1ff9de10 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 17 Feb 2015 17:22:14 -0800 Subject: [PATCH 29/31] Attempt to better explain secure server creation --- include/grpc/grpc.h | 7 +------ include/grpc/grpc_security.h | 7 +++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 9807de9f4bc..6e5f48d7efb 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -549,16 +549,11 @@ grpc_call_error grpc_server_request_call( grpc_server *grpc_server_create(grpc_completion_queue *cq, const grpc_channel_args *args); -/* Add a http2 over tcp listener. +/* Add a HTTP2 over plaintext over tcp listener. Returns bound port number on success, 0 on failure. REQUIRES: server not started */ int grpc_server_add_http2_port(grpc_server *server, const char *addr); -/* Add a secure port to server. - Returns bound port number on success, 0 on failure. - REQUIRES: server not started */ -int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr); - /* Start a server - tells all listeners to start listening */ void grpc_server_start(grpc_server *server); diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 731959069fc..a43d998d029 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -162,6 +162,13 @@ grpc_server *grpc_secure_server_create(grpc_server_credentials *creds, grpc_completion_queue *cq, const grpc_channel_args *args); +/* Add a HTTP2 over an encrypted link over tcp listener. + Server must have been created with grpc_secure_server_create. + Returns bound port number on success, 0 on failure. + REQUIRES: server not started */ +int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr); + + #ifdef __cplusplus } #endif From c25a3b35bd8e41c4ccf140930b4497ea707b0d6e Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Wed, 18 Feb 2015 02:46:17 +0000 Subject: [PATCH 30/31] Python source reorganization. A top-level "grpc" package is added and RPC Framework is made public. --- src/python/interop/interop/methods.py | 2 +- src/python/interop/interop/server.py | 2 +- src/python/src/{ => grpc}/__init__.py | 0 .../src/{ => grpc}/_adapter/__init__.py | 0 ...blocking_invocation_inline_service_test.py | 4 +- src/python/src/{ => grpc}/_adapter/_c.c | 10 ++-- src/python/src/{ => grpc}/_adapter/_c_test.py | 4 +- src/python/src/{ => grpc}/_adapter/_call.c | 8 ++-- src/python/src/{ => grpc}/_adapter/_call.h | 0 src/python/src/{ => grpc}/_adapter/_channel.c | 2 +- src/python/src/{ => grpc}/_adapter/_channel.h | 0 src/python/src/{ => grpc}/_adapter/_common.py | 0 .../{ => grpc}/_adapter/_completion_queue.c | 6 +-- .../{ => grpc}/_adapter/_completion_queue.h | 0 .../src/{ => grpc}/_adapter/_datatypes.py | 0 src/python/src/{ => grpc}/_adapter/_error.c | 2 +- src/python/src/{ => grpc}/_adapter/_error.h | 0 ...vocation_synchronous_event_service_test.py | 4 +- .../{ => grpc}/_adapter/_face_test_case.py | 18 ++++---- ...ocation_asynchronous_event_service_test.py | 4 +- .../src/{ => grpc}/_adapter/_links_test.py | 14 +++--- .../_adapter/_lonely_rear_link_test.py | 10 ++-- src/python/src/{ => grpc}/_adapter/_low.py | 4 +- .../src/{ => grpc}/_adapter/_low_test.py | 2 +- .../{ => grpc}/_adapter/_proto_scenarios.py | 2 +- src/python/src/{ => grpc}/_adapter/_server.c | 8 ++-- src/python/src/{ => grpc}/_adapter/_server.h | 0 .../{ => grpc}/_adapter/_server_credentials.c | 2 +- .../{ => grpc}/_adapter/_server_credentials.h | 0 .../src/{ => grpc}/_adapter/_test_links.py | 2 +- src/python/src/{ => grpc}/_adapter/fore.py | 12 ++--- src/python/src/{ => grpc}/_adapter/rear.py | 10 ++-- .../_junkdrawer}/__init__.py | 0 .../src/{ => grpc}/_junkdrawer/math_pb2.py | 0 .../src/{ => grpc}/_junkdrawer/stock_pb2.py | 0 .../base => grpc/early_adopter}/__init__.py | 0 .../early_adopter}/_face_utilities.py | 4 +- .../early_adopter}/implementations.py | 12 ++--- .../early_adopter}/interfaces.py | 0 .../early_adopter}/utilities.py | 2 +- .../packets => grpc/framework}/__init__.py | 0 .../framework/base}/__init__.py | 0 .../framework}/base/exceptions.py | 0 .../framework}/base/interfaces.py | 2 +- .../framework}/base/interfaces_test.py | 10 ++-- .../framework/base/packets}/__init__.py | 0 .../framework}/base/packets/_cancellation.py | 4 +- .../framework}/base/packets/_constants.py | 0 .../framework}/base/packets/_context.py | 6 +-- .../framework}/base/packets/_emission.py | 4 +- .../framework}/base/packets/_ends.py | 26 +++++------ .../framework}/base/packets/_expiration.py | 6 +-- .../framework}/base/packets/_ingestion.py | 16 +++---- .../framework}/base/packets/_interfaces.py | 6 +-- .../framework}/base/packets/_reception.py | 4 +- .../framework}/base/packets/_termination.py | 10 ++-- .../framework}/base/packets/_transmission.py | 10 ++-- .../base/packets/implementations.py | 4 +- .../base/packets/implementations_test.py | 8 ++-- .../framework}/base/packets/in_memory.py | 6 +-- .../framework}/base/packets/interfaces.py | 4 +- .../framework}/base/packets/null.py | 2 +- .../framework}/base/packets/packets.py | 2 +- .../framework}/base/util.py | 2 +- .../framework/common}/__init__.py | 0 .../framework}/common/cardinality.py | 0 .../framework/face}/__init__.py | 0 .../framework}/face/_calls.py | 12 ++--- .../framework}/face/_control.py | 10 ++-- .../framework}/face/_service.py | 16 +++---- .../framework}/face/_test_case.py | 8 ++-- ...blocking_invocation_inline_service_test.py | 4 +- .../framework}/face/demonstration.py | 8 ++-- ...vocation_synchronous_event_service_test.py | 4 +- .../framework}/face/exceptions.py | 0 ...ocation_asynchronous_event_service_test.py | 4 +- .../framework}/face/implementations.py | 12 ++--- .../framework}/face/interfaces.py | 6 +-- .../framework/face/testing}/__init__.py | 0 .../framework}/face/testing/base_util.py | 10 ++-- ...ing_invocation_inline_service_test_case.py | 12 ++--- .../framework}/face/testing/callback.py | 2 +- .../framework}/face/testing/control.py | 0 .../framework}/face/testing/coverage.py | 0 .../framework}/face/testing/digest.py | 14 +++--- ...ion_synchronous_event_service_test_case.py | 14 +++--- ...on_asynchronous_event_service_test_case.py | 16 +++---- .../framework}/face/testing/interfaces.py | 2 +- .../framework}/face/testing/serial.py | 0 .../framework}/face/testing/service.py | 4 +- .../framework}/face/testing/stock_service.py | 12 ++--- .../framework}/face/testing/test_case.py | 4 +- .../framework/foundation}/__init__.py | 0 .../framework}/foundation/_later_test.py | 2 +- .../foundation/_logging_pool_test.py | 2 +- .../framework}/foundation/_timer_future.py | 2 +- .../framework}/foundation/abandonment.py | 0 .../framework}/foundation/callable_util.py | 0 .../framework}/foundation/future.py | 0 .../framework}/foundation/later.py | 2 +- .../framework}/foundation/logging_pool.py | 0 .../framework}/foundation/stream.py | 0 .../framework}/foundation/stream_testing.py | 2 +- .../framework}/foundation/stream_util.py | 2 +- src/python/src/setup.py | 46 ++++++++++--------- tools/dockerfile/grpc_python/Dockerfile | 26 +++++------ tools/run_tests/run_python.sh | 26 +++++------ 107 files changed, 284 insertions(+), 282 deletions(-) rename src/python/src/{ => grpc}/__init__.py (100%) rename src/python/src/{ => grpc}/_adapter/__init__.py (100%) rename src/python/src/{ => grpc}/_adapter/_blocking_invocation_inline_service_test.py (67%) rename src/python/src/{ => grpc}/_adapter/_c.c (92%) rename src/python/src/{ => grpc}/_adapter/_c_test.py (98%) rename src/python/src/{ => grpc}/_adapter/_call.c (98%) rename src/python/src/{ => grpc}/_adapter/_call.h (100%) rename src/python/src/{ => grpc}/_adapter/_channel.c (99%) rename src/python/src/{ => grpc}/_adapter/_channel.h (100%) rename src/python/src/{ => grpc}/_adapter/_common.py (100%) rename src/python/src/{ => grpc}/_adapter/_completion_queue.c (99%) rename src/python/src/{ => grpc}/_adapter/_completion_queue.h (100%) rename src/python/src/{ => grpc}/_adapter/_datatypes.py (100%) rename src/python/src/{ => grpc}/_adapter/_error.c (98%) rename src/python/src/{ => grpc}/_adapter/_error.h (100%) rename src/python/src/{ => grpc}/_adapter/_event_invocation_synchronous_event_service_test.py (92%) rename src/python/src/{ => grpc}/_adapter/_face_test_case.py (91%) rename src/python/src/{ => grpc}/_adapter/_future_invocation_asynchronous_event_service_test.py (92%) rename src/python/src/{ => grpc}/_adapter/_links_test.py (97%) rename src/python/src/{ => grpc}/_adapter/_lonely_rear_link_test.py (94%) rename src/python/src/{ => grpc}/_adapter/_low.py (96%) rename src/python/src/{ => grpc}/_adapter/_low_test.py (99%) rename src/python/src/{ => grpc}/_adapter/_proto_scenarios.py (99%) rename src/python/src/{ => grpc}/_adapter/_server.c (97%) rename src/python/src/{ => grpc}/_adapter/_server.h (100%) rename src/python/src/{ => grpc}/_adapter/_server_credentials.c (99%) rename src/python/src/{ => grpc}/_adapter/_server_credentials.h (100%) rename src/python/src/{ => grpc}/_adapter/_test_links.py (98%) rename src/python/src/{ => grpc}/_adapter/fore.py (97%) rename src/python/src/{ => grpc}/_adapter/rear.py (98%) rename src/python/src/{_framework => grpc/_junkdrawer}/__init__.py (100%) rename src/python/src/{ => grpc}/_junkdrawer/math_pb2.py (100%) rename src/python/src/{ => grpc}/_junkdrawer/stock_pb2.py (100%) rename src/python/src/{_framework/base => grpc/early_adopter}/__init__.py (100%) rename src/python/src/{grpc_early_adopter => grpc/early_adopter}/_face_utilities.py (97%) rename src/python/src/{grpc_early_adopter => grpc/early_adopter}/implementations.py (93%) rename src/python/src/{grpc_early_adopter => grpc/early_adopter}/interfaces.py (100%) rename src/python/src/{grpc_early_adopter => grpc/early_adopter}/utilities.py (99%) rename src/python/src/{_framework/base/packets => grpc/framework}/__init__.py (100%) rename src/python/src/{_framework/common => grpc/framework/base}/__init__.py (100%) rename src/python/src/{_framework => grpc/framework}/base/exceptions.py (100%) rename src/python/src/{_framework => grpc/framework}/base/interfaces.py (98%) rename src/python/src/{_framework => grpc/framework}/base/interfaces_test.py (98%) rename src/python/src/{_framework/face => grpc/framework/base/packets}/__init__.py (100%) rename src/python/src/{_framework => grpc/framework}/base/packets/_cancellation.py (96%) rename src/python/src/{_framework => grpc/framework}/base/packets/_constants.py (100%) rename src/python/src/{_framework => grpc/framework}/base/packets/_context.py (94%) rename src/python/src/{_framework => grpc/framework}/base/packets/_emission.py (97%) rename src/python/src/{_framework => grpc/framework}/base/packets/_ends.py (95%) rename src/python/src/{_framework => grpc/framework}/base/packets/_expiration.py (97%) rename src/python/src/{_framework => grpc/framework}/base/packets/_ingestion.py (97%) rename src/python/src/{_framework => grpc/framework}/base/packets/_interfaces.py (97%) rename src/python/src/{_framework => grpc/framework}/base/packets/_reception.py (99%) rename src/python/src/{_framework => grpc/framework}/base/packets/_termination.py (97%) rename src/python/src/{_framework => grpc/framework}/base/packets/_transmission.py (98%) rename src/python/src/{_framework => grpc/framework}/base/packets/implementations.py (96%) rename src/python/src/{_framework => grpc/framework}/base/packets/implementations_test.py (94%) rename src/python/src/{_framework => grpc/framework}/base/packets/in_memory.py (96%) rename src/python/src/{_framework => grpc/framework}/base/packets/interfaces.py (96%) rename src/python/src/{_framework => grpc/framework}/base/packets/null.py (97%) rename src/python/src/{_framework => grpc/framework}/base/packets/packets.py (98%) rename src/python/src/{_framework => grpc/framework}/base/util.py (98%) rename src/python/src/{_framework/face/testing => grpc/framework/common}/__init__.py (100%) rename src/python/src/{_framework => grpc/framework}/common/cardinality.py (100%) rename src/python/src/{_framework/foundation => grpc/framework/face}/__init__.py (100%) rename src/python/src/{_framework => grpc/framework}/face/_calls.py (98%) rename src/python/src/{_framework => grpc/framework}/face/_control.py (96%) rename src/python/src/{_framework => grpc/framework}/face/_service.py (93%) rename src/python/src/{_framework => grpc/framework}/face/_test_case.py (94%) rename src/python/src/{_framework => grpc/framework}/face/blocking_invocation_inline_service_test.py (92%) rename src/python/src/{_framework => grpc/framework}/face/demonstration.py (95%) rename src/python/src/{_framework => grpc/framework}/face/event_invocation_synchronous_event_service_test.py (92%) rename src/python/src/{_framework => grpc/framework}/face/exceptions.py (100%) rename src/python/src/{_framework => grpc/framework}/face/future_invocation_asynchronous_event_service_test.py (92%) rename src/python/src/{_framework => grpc/framework}/face/implementations.py (96%) rename src/python/src/{_framework => grpc/framework}/face/interfaces.py (98%) rename src/python/src/{_junkdrawer => grpc/framework/face/testing}/__init__.py (100%) rename src/python/src/{_framework => grpc/framework}/face/testing/base_util.py (92%) rename src/python/src/{_framework => grpc/framework}/face/testing/blocking_invocation_inline_service_test_case.py (96%) rename src/python/src/{_framework => grpc/framework}/face/testing/callback.py (98%) rename src/python/src/{_framework => grpc/framework}/face/testing/control.py (100%) rename src/python/src/{_framework => grpc/framework}/face/testing/coverage.py (100%) rename src/python/src/{_framework => grpc/framework}/face/testing/digest.py (96%) rename src/python/src/{_framework => grpc/framework}/face/testing/event_invocation_synchronous_event_service_test_case.py (97%) rename src/python/src/{_framework => grpc/framework}/face/testing/future_invocation_asynchronous_event_service_test_case.py (97%) rename src/python/src/{_framework => grpc/framework}/face/testing/interfaces.py (97%) rename src/python/src/{_framework => grpc/framework}/face/testing/serial.py (100%) rename src/python/src/{_framework => grpc/framework}/face/testing/service.py (98%) rename src/python/src/{_framework => grpc/framework}/face/testing/stock_service.py (97%) rename src/python/src/{_framework => grpc/framework}/face/testing/test_case.py (96%) rename src/python/src/{grpc_early_adopter => grpc/framework/foundation}/__init__.py (100%) rename src/python/src/{_framework => grpc/framework}/foundation/_later_test.py (99%) rename src/python/src/{_framework => grpc/framework}/foundation/_logging_pool_test.py (97%) rename src/python/src/{_framework => grpc/framework}/foundation/_timer_future.py (99%) rename src/python/src/{_framework => grpc/framework}/foundation/abandonment.py (100%) rename src/python/src/{_framework => grpc/framework}/foundation/callable_util.py (100%) rename src/python/src/{_framework => grpc/framework}/foundation/future.py (100%) rename src/python/src/{_framework => grpc/framework}/foundation/later.py (97%) rename src/python/src/{_framework => grpc/framework}/foundation/logging_pool.py (100%) rename src/python/src/{_framework => grpc/framework}/foundation/stream.py (100%) rename src/python/src/{_framework => grpc/framework}/foundation/stream_testing.py (98%) rename src/python/src/{_framework => grpc/framework}/foundation/stream_util.py (99%) diff --git a/src/python/interop/interop/methods.py b/src/python/interop/interop/methods.py index e5ce5902ca7..854dbec8cc3 100644 --- a/src/python/interop/interop/methods.py +++ b/src/python/interop/interop/methods.py @@ -29,7 +29,7 @@ """Implementations of interoperability test methods.""" -from grpc_early_adopter import utilities +from grpc.early_adopter import utilities from interop import empty_pb2 from interop import messages_pb2 diff --git a/src/python/interop/interop/server.py b/src/python/interop/interop/server.py index 404c87dd0a9..0035e062a4e 100644 --- a/src/python/interop/interop/server.py +++ b/src/python/interop/interop/server.py @@ -34,7 +34,7 @@ import logging import pkg_resources import time -from grpc_early_adopter import implementations +from grpc.early_adopter import implementations from interop import methods diff --git a/src/python/src/__init__.py b/src/python/src/grpc/__init__.py similarity index 100% rename from src/python/src/__init__.py rename to src/python/src/grpc/__init__.py diff --git a/src/python/src/_adapter/__init__.py b/src/python/src/grpc/_adapter/__init__.py similarity index 100% rename from src/python/src/_adapter/__init__.py rename to src/python/src/grpc/_adapter/__init__.py diff --git a/src/python/src/_adapter/_blocking_invocation_inline_service_test.py b/src/python/src/grpc/_adapter/_blocking_invocation_inline_service_test.py similarity index 67% rename from src/python/src/_adapter/_blocking_invocation_inline_service_test.py rename to src/python/src/grpc/_adapter/_blocking_invocation_inline_service_test.py index 873ce9a5a46..761e5cf6839 100644 --- a/src/python/src/_adapter/_blocking_invocation_inline_service_test.py +++ b/src/python/src/grpc/_adapter/_blocking_invocation_inline_service_test.py @@ -2,8 +2,8 @@ import unittest -from _adapter import _face_test_case -from _framework.face.testing import blocking_invocation_inline_service_test_case as test_case +from grpc._adapter import _face_test_case +from grpc.framework.face.testing import blocking_invocation_inline_service_test_case as test_case class BlockingInvocationInlineServiceTest( diff --git a/src/python/src/_adapter/_c.c b/src/python/src/grpc/_adapter/_c.c similarity index 92% rename from src/python/src/_adapter/_c.c rename to src/python/src/grpc/_adapter/_c.c index 6fb7fa29faf..13eb93fe5ab 100644 --- a/src/python/src/_adapter/_c.c +++ b/src/python/src/grpc/_adapter/_c.c @@ -34,11 +34,11 @@ #include #include -#include "_adapter/_completion_queue.h" -#include "_adapter/_channel.h" -#include "_adapter/_call.h" -#include "_adapter/_server.h" -#include "_adapter/_server_credentials.h" +#include "grpc/_adapter/_completion_queue.h" +#include "grpc/_adapter/_channel.h" +#include "grpc/_adapter/_call.h" +#include "grpc/_adapter/_server.h" +#include "grpc/_adapter/_server_credentials.h" static PyObject *init(PyObject *self, PyObject *args) { grpc_init(); diff --git a/src/python/src/_adapter/_c_test.py b/src/python/src/grpc/_adapter/_c_test.py similarity index 98% rename from src/python/src/_adapter/_c_test.py rename to src/python/src/grpc/_adapter/_c_test.py index 210ac1fff78..d421692ec9c 100644 --- a/src/python/src/_adapter/_c_test.py +++ b/src/python/src/grpc/_adapter/_c_test.py @@ -33,8 +33,8 @@ import threading import time import unittest -from _adapter import _c -from _adapter import _datatypes +from grpc._adapter import _c +from grpc._adapter import _datatypes _TIMEOUT = 3 _FUTURE = time.time() + 60 * 60 * 24 diff --git a/src/python/src/_adapter/_call.c b/src/python/src/grpc/_adapter/_call.c similarity index 98% rename from src/python/src/_adapter/_call.c rename to src/python/src/grpc/_adapter/_call.c index 3bc35be0ef0..a2cc590d28b 100644 --- a/src/python/src/_adapter/_call.c +++ b/src/python/src/grpc/_adapter/_call.c @@ -31,15 +31,15 @@ * */ -#include "_adapter/_call.h" +#include "grpc/_adapter/_call.h" #include #include #include -#include "_adapter/_channel.h" -#include "_adapter/_completion_queue.h" -#include "_adapter/_error.h" +#include "grpc/_adapter/_channel.h" +#include "grpc/_adapter/_completion_queue.h" +#include "grpc/_adapter/_error.h" static int pygrpc_call_init(Call *self, PyObject *args, PyObject *kwds) { const PyObject *channel; diff --git a/src/python/src/_adapter/_call.h b/src/python/src/grpc/_adapter/_call.h similarity index 100% rename from src/python/src/_adapter/_call.h rename to src/python/src/grpc/_adapter/_call.h diff --git a/src/python/src/_adapter/_channel.c b/src/python/src/grpc/_adapter/_channel.c similarity index 99% rename from src/python/src/_adapter/_channel.c rename to src/python/src/grpc/_adapter/_channel.c index d41ebd4479e..6962722ed25 100644 --- a/src/python/src/_adapter/_channel.c +++ b/src/python/src/grpc/_adapter/_channel.c @@ -31,7 +31,7 @@ * */ -#include "_adapter/_channel.h" +#include "grpc/_adapter/_channel.h" #include #include diff --git a/src/python/src/_adapter/_channel.h b/src/python/src/grpc/_adapter/_channel.h similarity index 100% rename from src/python/src/_adapter/_channel.h rename to src/python/src/grpc/_adapter/_channel.h diff --git a/src/python/src/_adapter/_common.py b/src/python/src/grpc/_adapter/_common.py similarity index 100% rename from src/python/src/_adapter/_common.py rename to src/python/src/grpc/_adapter/_common.py diff --git a/src/python/src/_adapter/_completion_queue.c b/src/python/src/grpc/_adapter/_completion_queue.c similarity index 99% rename from src/python/src/_adapter/_completion_queue.c rename to src/python/src/grpc/_adapter/_completion_queue.c index 7c951d24a00..1d593d0d140 100644 --- a/src/python/src/_adapter/_completion_queue.c +++ b/src/python/src/grpc/_adapter/_completion_queue.c @@ -31,13 +31,13 @@ * */ -#include "_adapter/_completion_queue.h" +#include "grpc/_adapter/_completion_queue.h" #include #include #include -#include "_adapter/_call.h" +#include "grpc/_adapter/_call.h" static PyObject *status_class; static PyObject *service_acceptance_class; @@ -500,7 +500,7 @@ static int pygrpc_get_event_kinds(PyObject *event_class) { } int pygrpc_add_completion_queue(PyObject *module) { - char *datatypes_module_path = "_adapter._datatypes"; + char *datatypes_module_path = "grpc._adapter._datatypes"; PyObject *datatypes_module = PyImport_ImportModule(datatypes_module_path); if (datatypes_module == NULL) { PyErr_SetString(PyExc_ImportError, datatypes_module_path); diff --git a/src/python/src/_adapter/_completion_queue.h b/src/python/src/grpc/_adapter/_completion_queue.h similarity index 100% rename from src/python/src/_adapter/_completion_queue.h rename to src/python/src/grpc/_adapter/_completion_queue.h diff --git a/src/python/src/_adapter/_datatypes.py b/src/python/src/grpc/_adapter/_datatypes.py similarity index 100% rename from src/python/src/_adapter/_datatypes.py rename to src/python/src/grpc/_adapter/_datatypes.py diff --git a/src/python/src/_adapter/_error.c b/src/python/src/grpc/_adapter/_error.c similarity index 98% rename from src/python/src/_adapter/_error.c rename to src/python/src/grpc/_adapter/_error.c index 8c04f4bcea7..a8a1dbc1bbf 100644 --- a/src/python/src/_adapter/_error.c +++ b/src/python/src/grpc/_adapter/_error.c @@ -31,7 +31,7 @@ * */ -#include "_adapter/_error.h" +#include "grpc/_adapter/_error.h" #include #include diff --git a/src/python/src/_adapter/_error.h b/src/python/src/grpc/_adapter/_error.h similarity index 100% rename from src/python/src/_adapter/_error.h rename to src/python/src/grpc/_adapter/_error.h diff --git a/src/python/src/_adapter/_event_invocation_synchronous_event_service_test.py b/src/python/src/grpc/_adapter/_event_invocation_synchronous_event_service_test.py similarity index 92% rename from src/python/src/_adapter/_event_invocation_synchronous_event_service_test.py rename to src/python/src/grpc/_adapter/_event_invocation_synchronous_event_service_test.py index 69d91ec7da7..b9a13ce69fd 100644 --- a/src/python/src/_adapter/_event_invocation_synchronous_event_service_test.py +++ b/src/python/src/grpc/_adapter/_event_invocation_synchronous_event_service_test.py @@ -31,8 +31,8 @@ import unittest -from _adapter import _face_test_case -from _framework.face.testing import event_invocation_synchronous_event_service_test_case as test_case +from grpc._adapter import _face_test_case +from grpc.framework.face.testing import event_invocation_synchronous_event_service_test_case as test_case class EventInvocationSynchronousEventServiceTest( diff --git a/src/python/src/_adapter/_face_test_case.py b/src/python/src/grpc/_adapter/_face_test_case.py similarity index 91% rename from src/python/src/_adapter/_face_test_case.py rename to src/python/src/grpc/_adapter/_face_test_case.py index 2c6e6286b57..da73366f446 100644 --- a/src/python/src/_adapter/_face_test_case.py +++ b/src/python/src/grpc/_adapter/_face_test_case.py @@ -31,15 +31,15 @@ import unittest -from _adapter import fore -from _adapter import rear -from _framework.base import util -from _framework.base.packets import implementations as tickets_implementations -from _framework.face import implementations as face_implementations -from _framework.face.testing import coverage -from _framework.face.testing import serial -from _framework.face.testing import test_case -from _framework.foundation import logging_pool +from grpc._adapter import fore +from grpc._adapter import rear +from grpc.framework.base import util +from grpc.framework.base.packets import implementations as tickets_implementations +from grpc.framework.face import implementations as face_implementations +from grpc.framework.face.testing import coverage +from grpc.framework.face.testing import serial +from grpc.framework.face.testing import test_case +from grpc.framework.foundation import logging_pool _TIMEOUT = 3 _MAXIMUM_TIMEOUT = 90 diff --git a/src/python/src/_adapter/_future_invocation_asynchronous_event_service_test.py b/src/python/src/grpc/_adapter/_future_invocation_asynchronous_event_service_test.py similarity index 92% rename from src/python/src/_adapter/_future_invocation_asynchronous_event_service_test.py rename to src/python/src/grpc/_adapter/_future_invocation_asynchronous_event_service_test.py index 3db39dd1540..7d6a4ffc17a 100644 --- a/src/python/src/_adapter/_future_invocation_asynchronous_event_service_test.py +++ b/src/python/src/grpc/_adapter/_future_invocation_asynchronous_event_service_test.py @@ -31,8 +31,8 @@ import unittest -from _adapter import _face_test_case -from _framework.face.testing import future_invocation_asynchronous_event_service_test_case as test_case +from grpc._adapter import _face_test_case +from grpc.framework.face.testing import future_invocation_asynchronous_event_service_test_case as test_case class FutureInvocationAsynchronousEventServiceTest( diff --git a/src/python/src/_adapter/_links_test.py b/src/python/src/grpc/_adapter/_links_test.py similarity index 97% rename from src/python/src/_adapter/_links_test.py rename to src/python/src/grpc/_adapter/_links_test.py index d8bbb271270..ba7660bb920 100644 --- a/src/python/src/_adapter/_links_test.py +++ b/src/python/src/grpc/_adapter/_links_test.py @@ -32,13 +32,13 @@ import threading import unittest -from _adapter import _proto_scenarios -from _adapter import _test_links -from _adapter import fore -from _adapter import rear -from _framework.base import interfaces -from _framework.base.packets import packets as tickets -from _framework.foundation import logging_pool +from grpc._adapter import _proto_scenarios +from grpc._adapter import _test_links +from grpc._adapter import fore +from grpc._adapter import rear +from grpc.framework.base import interfaces +from grpc.framework.base.packets import packets as tickets +from grpc.framework.foundation import logging_pool _IDENTITY = lambda x: x _TIMEOUT = 2 diff --git a/src/python/src/_adapter/_lonely_rear_link_test.py b/src/python/src/grpc/_adapter/_lonely_rear_link_test.py similarity index 94% rename from src/python/src/_adapter/_lonely_rear_link_test.py rename to src/python/src/grpc/_adapter/_lonely_rear_link_test.py index 7ccdb0b5307..fd502a1c817 100644 --- a/src/python/src/_adapter/_lonely_rear_link_test.py +++ b/src/python/src/grpc/_adapter/_lonely_rear_link_test.py @@ -31,11 +31,11 @@ import unittest -from _adapter import _test_links -from _adapter import rear -from _framework.base import interfaces -from _framework.base.packets import packets -from _framework.foundation import logging_pool +from grpc._adapter import _test_links +from grpc._adapter import rear +from grpc.framework.base import interfaces +from grpc.framework.base.packets import packets +from grpc.framework.foundation import logging_pool _IDENTITY = lambda x: x _TIMEOUT = 2 diff --git a/src/python/src/_adapter/_low.py b/src/python/src/grpc/_adapter/_low.py similarity index 96% rename from src/python/src/_adapter/_low.py rename to src/python/src/grpc/_adapter/_low.py index 09105eafa0c..2ef2eb879c1 100644 --- a/src/python/src/_adapter/_low.py +++ b/src/python/src/grpc/_adapter/_low.py @@ -32,8 +32,8 @@ import atexit import gc -from _adapter import _c -from _adapter import _datatypes +from grpc._adapter import _c +from grpc._adapter import _datatypes def _shut_down(): # force garbage collection before shutting down grpc, to ensure all grpc diff --git a/src/python/src/_adapter/_low_test.py b/src/python/src/grpc/_adapter/_low_test.py similarity index 99% rename from src/python/src/_adapter/_low_test.py rename to src/python/src/grpc/_adapter/_low_test.py index 899ccf53c8a..898c62c0026 100644 --- a/src/python/src/_adapter/_low_test.py +++ b/src/python/src/grpc/_adapter/_low_test.py @@ -32,7 +32,7 @@ import time import unittest -from _adapter import _low +from grpc._adapter import _low _STREAM_LENGTH = 300 _TIMEOUT = 5 diff --git a/src/python/src/_adapter/_proto_scenarios.py b/src/python/src/grpc/_adapter/_proto_scenarios.py similarity index 99% rename from src/python/src/_adapter/_proto_scenarios.py rename to src/python/src/grpc/_adapter/_proto_scenarios.py index c452fb523ae..60a622ba8b8 100644 --- a/src/python/src/_adapter/_proto_scenarios.py +++ b/src/python/src/grpc/_adapter/_proto_scenarios.py @@ -32,7 +32,7 @@ import abc import threading -from _junkdrawer import math_pb2 +from grpc._junkdrawer import math_pb2 class ProtoScenario(object): diff --git a/src/python/src/_adapter/_server.c b/src/python/src/grpc/_adapter/_server.c similarity index 97% rename from src/python/src/_adapter/_server.c rename to src/python/src/grpc/_adapter/_server.c index 2f8cc99e44d..d4bf5fb8f64 100644 --- a/src/python/src/_adapter/_server.c +++ b/src/python/src/grpc/_adapter/_server.c @@ -31,14 +31,14 @@ * */ -#include "_adapter/_server.h" +#include "grpc/_adapter/_server.h" #include #include -#include "_adapter/_completion_queue.h" -#include "_adapter/_error.h" -#include "_adapter/_server_credentials.h" +#include "grpc/_adapter/_completion_queue.h" +#include "grpc/_adapter/_error.h" +#include "grpc/_adapter/_server_credentials.h" static int pygrpc_server_init(Server *self, PyObject *args, PyObject *kwds) { const PyObject *completion_queue; diff --git a/src/python/src/_adapter/_server.h b/src/python/src/grpc/_adapter/_server.h similarity index 100% rename from src/python/src/_adapter/_server.h rename to src/python/src/grpc/_adapter/_server.h diff --git a/src/python/src/_adapter/_server_credentials.c b/src/python/src/grpc/_adapter/_server_credentials.c similarity index 99% rename from src/python/src/_adapter/_server_credentials.c rename to src/python/src/grpc/_adapter/_server_credentials.c index 390266ae897..ae85fd3eb75 100644 --- a/src/python/src/_adapter/_server_credentials.c +++ b/src/python/src/grpc/_adapter/_server_credentials.c @@ -31,7 +31,7 @@ * */ -#include "_adapter/_server_credentials.h" +#include "grpc/_adapter/_server_credentials.h" #include #include diff --git a/src/python/src/_adapter/_server_credentials.h b/src/python/src/grpc/_adapter/_server_credentials.h similarity index 100% rename from src/python/src/_adapter/_server_credentials.h rename to src/python/src/grpc/_adapter/_server_credentials.h diff --git a/src/python/src/_adapter/_test_links.py b/src/python/src/grpc/_adapter/_test_links.py similarity index 98% rename from src/python/src/_adapter/_test_links.py rename to src/python/src/grpc/_adapter/_test_links.py index 77d1b00f366..ac0d6e20b69 100644 --- a/src/python/src/_adapter/_test_links.py +++ b/src/python/src/grpc/_adapter/_test_links.py @@ -31,7 +31,7 @@ import threading -from _framework.base.packets import interfaces +from grpc.framework.base.packets import interfaces class ForeLink(interfaces.ForeLink): diff --git a/src/python/src/_adapter/fore.py b/src/python/src/grpc/_adapter/fore.py similarity index 97% rename from src/python/src/_adapter/fore.py rename to src/python/src/grpc/_adapter/fore.py index 28aede1fd9d..f72b2fd5a5f 100644 --- a/src/python/src/_adapter/fore.py +++ b/src/python/src/grpc/_adapter/fore.py @@ -34,12 +34,12 @@ import logging import threading import time -from _adapter import _common -from _adapter import _low -from _framework.base import interfaces -from _framework.base.packets import interfaces as ticket_interfaces -from _framework.base.packets import null -from _framework.base.packets import packets as tickets +from grpc._adapter import _common +from grpc._adapter import _low +from grpc.framework.base import interfaces +from grpc.framework.base.packets import interfaces as ticket_interfaces +from grpc.framework.base.packets import null +from grpc.framework.base.packets import packets as tickets @enum.unique diff --git a/src/python/src/_adapter/rear.py b/src/python/src/grpc/_adapter/rear.py similarity index 98% rename from src/python/src/_adapter/rear.py rename to src/python/src/grpc/_adapter/rear.py index 5e0975ab4e3..c47c0aa0209 100644 --- a/src/python/src/_adapter/rear.py +++ b/src/python/src/grpc/_adapter/rear.py @@ -34,11 +34,11 @@ import logging import threading import time -from _adapter import _common -from _adapter import _low -from _framework.base.packets import interfaces as ticket_interfaces -from _framework.base.packets import null -from _framework.base.packets import packets as tickets +from grpc._adapter import _common +from grpc._adapter import _low +from grpc.framework.base.packets import interfaces as ticket_interfaces +from grpc.framework.base.packets import null +from grpc.framework.base.packets import packets as tickets _INVOCATION_EVENT_KINDS = ( _low.Event.Kind.METADATA_ACCEPTED, diff --git a/src/python/src/_framework/__init__.py b/src/python/src/grpc/_junkdrawer/__init__.py similarity index 100% rename from src/python/src/_framework/__init__.py rename to src/python/src/grpc/_junkdrawer/__init__.py diff --git a/src/python/src/_junkdrawer/math_pb2.py b/src/python/src/grpc/_junkdrawer/math_pb2.py similarity index 100% rename from src/python/src/_junkdrawer/math_pb2.py rename to src/python/src/grpc/_junkdrawer/math_pb2.py diff --git a/src/python/src/_junkdrawer/stock_pb2.py b/src/python/src/grpc/_junkdrawer/stock_pb2.py similarity index 100% rename from src/python/src/_junkdrawer/stock_pb2.py rename to src/python/src/grpc/_junkdrawer/stock_pb2.py diff --git a/src/python/src/_framework/base/__init__.py b/src/python/src/grpc/early_adopter/__init__.py similarity index 100% rename from src/python/src/_framework/base/__init__.py rename to src/python/src/grpc/early_adopter/__init__.py diff --git a/src/python/src/grpc_early_adopter/_face_utilities.py b/src/python/src/grpc/early_adopter/_face_utilities.py similarity index 97% rename from src/python/src/grpc_early_adopter/_face_utilities.py rename to src/python/src/grpc/early_adopter/_face_utilities.py index 8b10be729b2..714f2bb79cb 100644 --- a/src/python/src/grpc_early_adopter/_face_utilities.py +++ b/src/python/src/grpc/early_adopter/_face_utilities.py @@ -30,9 +30,9 @@ import abc import collections -from _framework.face import interfaces as face_interfaces +from grpc.framework.face import interfaces as face_interfaces -from grpc_early_adopter import interfaces +from grpc.early_adopter import interfaces class _InlineUnaryUnaryMethod(face_interfaces.InlineValueInValueOutMethod): diff --git a/src/python/src/grpc_early_adopter/implementations.py b/src/python/src/grpc/early_adopter/implementations.py similarity index 93% rename from src/python/src/grpc_early_adopter/implementations.py rename to src/python/src/grpc/early_adopter/implementations.py index 8a2f7fde616..cd9dd5a57d6 100644 --- a/src/python/src/grpc_early_adopter/implementations.py +++ b/src/python/src/grpc/early_adopter/implementations.py @@ -31,12 +31,12 @@ import threading -from _adapter import fore -from _framework.base.packets import implementations as _tickets_implementations -from _framework.face import implementations as _face_implementations -from _framework.foundation import logging_pool -from grpc_early_adopter import _face_utilities -from grpc_early_adopter import interfaces +from grpc._adapter import fore +from grpc.framework.base.packets import implementations as _tickets_implementations +from grpc.framework.face import implementations as _face_implementations +from grpc.framework.foundation import logging_pool +from grpc.early_adopter import _face_utilities +from grpc.early_adopter import interfaces _MEGA_TIMEOUT = 60 * 60 * 24 _THREAD_POOL_SIZE = 80 diff --git a/src/python/src/grpc_early_adopter/interfaces.py b/src/python/src/grpc/early_adopter/interfaces.py similarity index 100% rename from src/python/src/grpc_early_adopter/interfaces.py rename to src/python/src/grpc/early_adopter/interfaces.py diff --git a/src/python/src/grpc_early_adopter/utilities.py b/src/python/src/grpc/early_adopter/utilities.py similarity index 99% rename from src/python/src/grpc_early_adopter/utilities.py rename to src/python/src/grpc/early_adopter/utilities.py index 333ed3a9db4..a4ee253d830 100644 --- a/src/python/src/grpc_early_adopter/utilities.py +++ b/src/python/src/grpc/early_adopter/utilities.py @@ -29,7 +29,7 @@ """Utilities for use with GRPC.""" -from grpc_early_adopter import interfaces +from grpc.early_adopter import interfaces class _RpcMethod(interfaces.RpcMethod): diff --git a/src/python/src/_framework/base/packets/__init__.py b/src/python/src/grpc/framework/__init__.py similarity index 100% rename from src/python/src/_framework/base/packets/__init__.py rename to src/python/src/grpc/framework/__init__.py diff --git a/src/python/src/_framework/common/__init__.py b/src/python/src/grpc/framework/base/__init__.py similarity index 100% rename from src/python/src/_framework/common/__init__.py rename to src/python/src/grpc/framework/base/__init__.py diff --git a/src/python/src/_framework/base/exceptions.py b/src/python/src/grpc/framework/base/exceptions.py similarity index 100% rename from src/python/src/_framework/base/exceptions.py rename to src/python/src/grpc/framework/base/exceptions.py diff --git a/src/python/src/_framework/base/interfaces.py b/src/python/src/grpc/framework/base/interfaces.py similarity index 98% rename from src/python/src/_framework/base/interfaces.py rename to src/python/src/grpc/framework/base/interfaces.py index 70030e564d6..ed43b253fe5 100644 --- a/src/python/src/_framework/base/interfaces.py +++ b/src/python/src/grpc/framework/base/interfaces.py @@ -33,7 +33,7 @@ import abc import enum # stream is referenced from specification in this module. -from _framework.foundation import stream # pylint: disable=unused-import +from grpc.framework.foundation import stream # pylint: disable=unused-import @enum.unique diff --git a/src/python/src/_framework/base/interfaces_test.py b/src/python/src/grpc/framework/base/interfaces_test.py similarity index 98% rename from src/python/src/_framework/base/interfaces_test.py rename to src/python/src/grpc/framework/base/interfaces_test.py index 8e26d884ec4..b86011c449e 100644 --- a/src/python/src/_framework/base/interfaces_test.py +++ b/src/python/src/grpc/framework/base/interfaces_test.py @@ -32,11 +32,11 @@ import threading import time -from _framework.base import interfaces -from _framework.base import util -from _framework.foundation import stream -from _framework.foundation import stream_testing -from _framework.foundation import stream_util +from grpc.framework.base import interfaces +from grpc.framework.base import util +from grpc.framework.foundation import stream +from grpc.framework.foundation import stream_testing +from grpc.framework.foundation import stream_util TICK = 0.1 SMALL_TIMEOUT = TICK * 50 diff --git a/src/python/src/_framework/face/__init__.py b/src/python/src/grpc/framework/base/packets/__init__.py similarity index 100% rename from src/python/src/_framework/face/__init__.py rename to src/python/src/grpc/framework/base/packets/__init__.py diff --git a/src/python/src/_framework/base/packets/_cancellation.py b/src/python/src/grpc/framework/base/packets/_cancellation.py similarity index 96% rename from src/python/src/_framework/base/packets/_cancellation.py rename to src/python/src/grpc/framework/base/packets/_cancellation.py index 49172d1b974..2373c78842d 100644 --- a/src/python/src/_framework/base/packets/_cancellation.py +++ b/src/python/src/grpc/framework/base/packets/_cancellation.py @@ -29,8 +29,8 @@ """State and behavior for operation cancellation.""" -from _framework.base.packets import _interfaces -from _framework.base.packets import packets +from grpc.framework.base.packets import _interfaces +from grpc.framework.base.packets import packets class CancellationManager(_interfaces.CancellationManager): diff --git a/src/python/src/_framework/base/packets/_constants.py b/src/python/src/grpc/framework/base/packets/_constants.py similarity index 100% rename from src/python/src/_framework/base/packets/_constants.py rename to src/python/src/grpc/framework/base/packets/_constants.py diff --git a/src/python/src/_framework/base/packets/_context.py b/src/python/src/grpc/framework/base/packets/_context.py similarity index 94% rename from src/python/src/_framework/base/packets/_context.py rename to src/python/src/grpc/framework/base/packets/_context.py index be390364b0a..e09d4a60c91 100644 --- a/src/python/src/_framework/base/packets/_context.py +++ b/src/python/src/grpc/framework/base/packets/_context.py @@ -32,9 +32,9 @@ import time # _interfaces and packets are referenced from specification in this module. -from _framework.base import interfaces as base_interfaces -from _framework.base.packets import _interfaces # pylint: disable=unused-import -from _framework.base.packets import packets # pylint: disable=unused-import +from grpc.framework.base import interfaces as base_interfaces +from grpc.framework.base.packets import _interfaces # pylint: disable=unused-import +from grpc.framework.base.packets import packets # pylint: disable=unused-import class OperationContext(base_interfaces.OperationContext): diff --git a/src/python/src/_framework/base/packets/_emission.py b/src/python/src/grpc/framework/base/packets/_emission.py similarity index 97% rename from src/python/src/_framework/base/packets/_emission.py rename to src/python/src/grpc/framework/base/packets/_emission.py index b4be5eb0ff9..9446b8665db 100644 --- a/src/python/src/_framework/base/packets/_emission.py +++ b/src/python/src/grpc/framework/base/packets/_emission.py @@ -30,8 +30,8 @@ """State and behavior for handling emitted values.""" # packets is referenced from specifications in this module. -from _framework.base.packets import _interfaces -from _framework.base.packets import packets # pylint: disable=unused-import +from grpc.framework.base.packets import _interfaces +from grpc.framework.base.packets import packets # pylint: disable=unused-import class _EmissionManager(_interfaces.EmissionManager): diff --git a/src/python/src/_framework/base/packets/_ends.py b/src/python/src/grpc/framework/base/packets/_ends.py similarity index 95% rename from src/python/src/_framework/base/packets/_ends.py rename to src/python/src/grpc/framework/base/packets/_ends.py index b1d16451e2a..15bf3bf330b 100644 --- a/src/python/src/_framework/base/packets/_ends.py +++ b/src/python/src/grpc/framework/base/packets/_ends.py @@ -34,19 +34,19 @@ import threading import uuid # _interfaces and packets are referenced from specification in this module. -from _framework.base import interfaces as base_interfaces -from _framework.base.packets import _cancellation -from _framework.base.packets import _context -from _framework.base.packets import _emission -from _framework.base.packets import _expiration -from _framework.base.packets import _ingestion -from _framework.base.packets import _interfaces # pylint: disable=unused-import -from _framework.base.packets import _reception -from _framework.base.packets import _termination -from _framework.base.packets import _transmission -from _framework.base.packets import interfaces -from _framework.base.packets import packets # pylint: disable=unused-import -from _framework.foundation import callable_util +from grpc.framework.base import interfaces as base_interfaces +from grpc.framework.base.packets import _cancellation +from grpc.framework.base.packets import _context +from grpc.framework.base.packets import _emission +from grpc.framework.base.packets import _expiration +from grpc.framework.base.packets import _ingestion +from grpc.framework.base.packets import _interfaces # pylint: disable=unused-import +from grpc.framework.base.packets import _reception +from grpc.framework.base.packets import _termination +from grpc.framework.base.packets import _transmission +from grpc.framework.base.packets import interfaces +from grpc.framework.base.packets import packets # pylint: disable=unused-import +from grpc.framework.foundation import callable_util _IDLE_ACTION_EXCEPTION_LOG_MESSAGE = 'Exception calling idle action!' diff --git a/src/python/src/_framework/base/packets/_expiration.py b/src/python/src/grpc/framework/base/packets/_expiration.py similarity index 97% rename from src/python/src/_framework/base/packets/_expiration.py rename to src/python/src/grpc/framework/base/packets/_expiration.py index 772e15f08c8..f58db28aa25 100644 --- a/src/python/src/_framework/base/packets/_expiration.py +++ b/src/python/src/grpc/framework/base/packets/_expiration.py @@ -31,9 +31,9 @@ import time -from _framework.base.packets import _interfaces -from _framework.base.packets import packets -from _framework.foundation import later +from grpc.framework.base.packets import _interfaces +from grpc.framework.base.packets import packets +from grpc.framework.foundation import later class _ExpirationManager(_interfaces.ExpirationManager): diff --git a/src/python/src/_framework/base/packets/_ingestion.py b/src/python/src/grpc/framework/base/packets/_ingestion.py similarity index 97% rename from src/python/src/_framework/base/packets/_ingestion.py rename to src/python/src/grpc/framework/base/packets/_ingestion.py index 91f5a35359f..a750195ccba 100644 --- a/src/python/src/_framework/base/packets/_ingestion.py +++ b/src/python/src/grpc/framework/base/packets/_ingestion.py @@ -32,14 +32,14 @@ import abc import collections -from _framework.base import exceptions -from _framework.base import interfaces -from _framework.base.packets import _constants -from _framework.base.packets import _interfaces -from _framework.base.packets import packets -from _framework.foundation import abandonment -from _framework.foundation import callable_util -from _framework.foundation import stream +from grpc.framework.base import exceptions +from grpc.framework.base import interfaces +from grpc.framework.base.packets import _constants +from grpc.framework.base.packets import _interfaces +from grpc.framework.base.packets import packets +from grpc.framework.foundation import abandonment +from grpc.framework.foundation import callable_util +from grpc.framework.foundation import stream _CREATE_CONSUMER_EXCEPTION_LOG_MESSAGE = 'Exception initializing ingestion!' _CONSUME_EXCEPTION_LOG_MESSAGE = 'Exception during ingestion!' diff --git a/src/python/src/_framework/base/packets/_interfaces.py b/src/python/src/grpc/framework/base/packets/_interfaces.py similarity index 97% rename from src/python/src/_framework/base/packets/_interfaces.py rename to src/python/src/grpc/framework/base/packets/_interfaces.py index d1bda95bf74..70d95723910 100644 --- a/src/python/src/_framework/base/packets/_interfaces.py +++ b/src/python/src/grpc/framework/base/packets/_interfaces.py @@ -32,9 +32,9 @@ import abc # base_interfaces and packets are referenced from specification in this module. -from _framework.base import interfaces as base_interfaces # pylint: disable=unused-import -from _framework.base.packets import packets # pylint: disable=unused-import -from _framework.foundation import stream +from grpc.framework.base import interfaces as base_interfaces # pylint: disable=unused-import +from grpc.framework.base.packets import packets # pylint: disable=unused-import +from grpc.framework.foundation import stream class TerminationManager(object): diff --git a/src/python/src/_framework/base/packets/_reception.py b/src/python/src/grpc/framework/base/packets/_reception.py similarity index 99% rename from src/python/src/_framework/base/packets/_reception.py rename to src/python/src/grpc/framework/base/packets/_reception.py index a2a3823d28c..6e2c9c0a4e7 100644 --- a/src/python/src/_framework/base/packets/_reception.py +++ b/src/python/src/grpc/framework/base/packets/_reception.py @@ -31,8 +31,8 @@ import abc -from _framework.base.packets import _interfaces -from _framework.base.packets import packets +from grpc.framework.base.packets import _interfaces +from grpc.framework.base.packets import packets class _Receiver(object): diff --git a/src/python/src/_framework/base/packets/_termination.py b/src/python/src/grpc/framework/base/packets/_termination.py similarity index 97% rename from src/python/src/_framework/base/packets/_termination.py rename to src/python/src/grpc/framework/base/packets/_termination.py index ae3ba1c16f3..5c10da7aa8c 100644 --- a/src/python/src/_framework/base/packets/_termination.py +++ b/src/python/src/grpc/framework/base/packets/_termination.py @@ -31,11 +31,11 @@ import enum -from _framework.base import interfaces -from _framework.base.packets import _constants -from _framework.base.packets import _interfaces -from _framework.base.packets import packets -from _framework.foundation import callable_util +from grpc.framework.base import interfaces +from grpc.framework.base.packets import _constants +from grpc.framework.base.packets import _interfaces +from grpc.framework.base.packets import packets +from grpc.framework.foundation import callable_util _CALLBACK_EXCEPTION_LOG_MESSAGE = 'Exception calling termination callback!' diff --git a/src/python/src/_framework/base/packets/_transmission.py b/src/python/src/grpc/framework/base/packets/_transmission.py similarity index 98% rename from src/python/src/_framework/base/packets/_transmission.py rename to src/python/src/grpc/framework/base/packets/_transmission.py index 24fe6e6164f..ac7f4509db9 100644 --- a/src/python/src/_framework/base/packets/_transmission.py +++ b/src/python/src/grpc/framework/base/packets/_transmission.py @@ -31,11 +31,11 @@ import abc -from _framework.base import interfaces -from _framework.base.packets import _constants -from _framework.base.packets import _interfaces -from _framework.base.packets import packets -from _framework.foundation import callable_util +from grpc.framework.base import interfaces +from grpc.framework.base.packets import _constants +from grpc.framework.base.packets import _interfaces +from grpc.framework.base.packets import packets +from grpc.framework.foundation import callable_util _TRANSMISSION_EXCEPTION_LOG_MESSAGE = 'Exception during transmission!' diff --git a/src/python/src/_framework/base/packets/implementations.py b/src/python/src/grpc/framework/base/packets/implementations.py similarity index 96% rename from src/python/src/_framework/base/packets/implementations.py rename to src/python/src/grpc/framework/base/packets/implementations.py index 2f07054d4d2..28688bcc0f9 100644 --- a/src/python/src/_framework/base/packets/implementations.py +++ b/src/python/src/grpc/framework/base/packets/implementations.py @@ -30,8 +30,8 @@ """Entry points into the packet-exchange-based implementation the base layer.""" # interfaces is referenced from specification in this module. -from _framework.base.packets import _ends -from _framework.base.packets import interfaces # pylint: disable=unused-import +from grpc.framework.base.packets import _ends +from grpc.framework.base.packets import interfaces # pylint: disable=unused-import def front(work_pool, transmission_pool, utility_pool): diff --git a/src/python/src/_framework/base/packets/implementations_test.py b/src/python/src/grpc/framework/base/packets/implementations_test.py similarity index 94% rename from src/python/src/_framework/base/packets/implementations_test.py rename to src/python/src/grpc/framework/base/packets/implementations_test.py index 8bb53531760..628f4b39094 100644 --- a/src/python/src/_framework/base/packets/implementations_test.py +++ b/src/python/src/grpc/framework/base/packets/implementations_test.py @@ -31,10 +31,10 @@ import unittest -from _framework.base import interfaces_test -from _framework.base import util -from _framework.base.packets import implementations -from _framework.foundation import logging_pool +from grpc.framework.base import interfaces_test +from grpc.framework.base import util +from grpc.framework.base.packets import implementations +from grpc.framework.foundation import logging_pool POOL_MAX_WORKERS = 100 DEFAULT_TIMEOUT = 30 diff --git a/src/python/src/_framework/base/packets/in_memory.py b/src/python/src/grpc/framework/base/packets/in_memory.py similarity index 96% rename from src/python/src/_framework/base/packets/in_memory.py rename to src/python/src/grpc/framework/base/packets/in_memory.py index 17daf3acf7b..453fd3b38aa 100644 --- a/src/python/src/_framework/base/packets/in_memory.py +++ b/src/python/src/grpc/framework/base/packets/in_memory.py @@ -31,9 +31,9 @@ import threading -from _framework.base.packets import _constants -from _framework.base.packets import interfaces -from _framework.foundation import callable_util +from grpc.framework.base.packets import _constants +from grpc.framework.base.packets import interfaces +from grpc.framework.foundation import callable_util class _Serializer(object): diff --git a/src/python/src/_framework/base/packets/interfaces.py b/src/python/src/grpc/framework/base/packets/interfaces.py similarity index 96% rename from src/python/src/_framework/base/packets/interfaces.py rename to src/python/src/grpc/framework/base/packets/interfaces.py index 99f9e877726..7c48956ba59 100644 --- a/src/python/src/_framework/base/packets/interfaces.py +++ b/src/python/src/grpc/framework/base/packets/interfaces.py @@ -32,8 +32,8 @@ import abc # packets is referenced from specifications in this module. -from _framework.base import interfaces -from _framework.base.packets import packets # pylint: disable=unused-import +from grpc.framework.base import interfaces +from grpc.framework.base.packets import packets # pylint: disable=unused-import class ForeLink(object): diff --git a/src/python/src/_framework/base/packets/null.py b/src/python/src/grpc/framework/base/packets/null.py similarity index 97% rename from src/python/src/_framework/base/packets/null.py rename to src/python/src/grpc/framework/base/packets/null.py index 9b40a005052..5a2121243bf 100644 --- a/src/python/src/_framework/base/packets/null.py +++ b/src/python/src/grpc/framework/base/packets/null.py @@ -29,7 +29,7 @@ """Null links that ignore tickets passed to them.""" -from _framework.base.packets import interfaces +from grpc.framework.base.packets import interfaces class _NullForeLink(interfaces.ForeLink): diff --git a/src/python/src/_framework/base/packets/packets.py b/src/python/src/grpc/framework/base/packets/packets.py similarity index 98% rename from src/python/src/_framework/base/packets/packets.py rename to src/python/src/grpc/framework/base/packets/packets.py index f7503bdcd65..9e2d4080b8c 100644 --- a/src/python/src/_framework/base/packets/packets.py +++ b/src/python/src/grpc/framework/base/packets/packets.py @@ -33,7 +33,7 @@ import collections import enum # interfaces is referenced from specifications in this module. -from _framework.base import interfaces # pylint: disable=unused-import +from grpc.framework.base import interfaces # pylint: disable=unused-import @enum.unique diff --git a/src/python/src/_framework/base/util.py b/src/python/src/grpc/framework/base/util.py similarity index 98% rename from src/python/src/_framework/base/util.py rename to src/python/src/grpc/framework/base/util.py index 35ce0443fcb..c832c826cfd 100644 --- a/src/python/src/_framework/base/util.py +++ b/src/python/src/grpc/framework/base/util.py @@ -32,7 +32,7 @@ import collections import threading -from _framework.base import interfaces +from grpc.framework.base import interfaces class _ServicedSubscription( diff --git a/src/python/src/_framework/face/testing/__init__.py b/src/python/src/grpc/framework/common/__init__.py similarity index 100% rename from src/python/src/_framework/face/testing/__init__.py rename to src/python/src/grpc/framework/common/__init__.py diff --git a/src/python/src/_framework/common/cardinality.py b/src/python/src/grpc/framework/common/cardinality.py similarity index 100% rename from src/python/src/_framework/common/cardinality.py rename to src/python/src/grpc/framework/common/cardinality.py diff --git a/src/python/src/_framework/foundation/__init__.py b/src/python/src/grpc/framework/face/__init__.py similarity index 100% rename from src/python/src/_framework/foundation/__init__.py rename to src/python/src/grpc/framework/face/__init__.py diff --git a/src/python/src/_framework/face/_calls.py b/src/python/src/grpc/framework/face/_calls.py similarity index 98% rename from src/python/src/_framework/face/_calls.py rename to src/python/src/grpc/framework/face/_calls.py index a7d8be5e432..75a550e3c7d 100644 --- a/src/python/src/_framework/face/_calls.py +++ b/src/python/src/grpc/framework/face/_calls.py @@ -32,12 +32,12 @@ import sys import threading -from _framework.base import interfaces as base_interfaces -from _framework.base import util as base_util -from _framework.face import _control -from _framework.face import interfaces -from _framework.foundation import callable_util -from _framework.foundation import future +from grpc.framework.base import interfaces as base_interfaces +from grpc.framework.base import util as base_util +from grpc.framework.face import _control +from grpc.framework.face import interfaces +from grpc.framework.foundation import callable_util +from grpc.framework.foundation import future _ITERATOR_EXCEPTION_LOG_MESSAGE = 'Exception iterating over requests!' _DONE_CALLBACK_LOG_MESSAGE = 'Exception calling Future "done" callback!' diff --git a/src/python/src/_framework/face/_control.py b/src/python/src/grpc/framework/face/_control.py similarity index 96% rename from src/python/src/_framework/face/_control.py rename to src/python/src/grpc/framework/face/_control.py index 9f1bf6d5fdb..e918907b749 100644 --- a/src/python/src/_framework/face/_control.py +++ b/src/python/src/grpc/framework/face/_control.py @@ -31,11 +31,11 @@ import threading -from _framework.base import interfaces as base_interfaces -from _framework.face import exceptions -from _framework.face import interfaces -from _framework.foundation import abandonment -from _framework.foundation import stream +from grpc.framework.base import interfaces as base_interfaces +from grpc.framework.face import exceptions +from grpc.framework.face import interfaces +from grpc.framework.foundation import abandonment +from grpc.framework.foundation import stream INTERNAL_ERROR_LOG_MESSAGE = ':-( RPC Framework (Face) Internal Error! :-(' diff --git a/src/python/src/_framework/face/_service.py b/src/python/src/grpc/framework/face/_service.py similarity index 93% rename from src/python/src/_framework/face/_service.py rename to src/python/src/grpc/framework/face/_service.py index d758c2f1480..26bde129687 100644 --- a/src/python/src/_framework/face/_service.py +++ b/src/python/src/grpc/framework/face/_service.py @@ -31,14 +31,14 @@ # base_interfaces and interfaces are referenced from specification in this # module. -from _framework.base import interfaces as base_interfaces # pylint: disable=unused-import -from _framework.face import _control -from _framework.face import exceptions -from _framework.face import interfaces # pylint: disable=unused-import -from _framework.foundation import abandonment -from _framework.foundation import callable_util -from _framework.foundation import stream -from _framework.foundation import stream_util +from grpc.framework.base import interfaces as base_interfaces # pylint: disable=unused-import +from grpc.framework.face import _control +from grpc.framework.face import exceptions +from grpc.framework.face import interfaces # pylint: disable=unused-import +from grpc.framework.foundation import abandonment +from grpc.framework.foundation import callable_util +from grpc.framework.foundation import stream +from grpc.framework.foundation import stream_util class _ValueInStreamOutConsumer(stream.Consumer): diff --git a/src/python/src/_framework/face/_test_case.py b/src/python/src/grpc/framework/face/_test_case.py similarity index 94% rename from src/python/src/_framework/face/_test_case.py rename to src/python/src/grpc/framework/face/_test_case.py index 50b55c389f3..a4e17c464ce 100644 --- a/src/python/src/_framework/face/_test_case.py +++ b/src/python/src/grpc/framework/face/_test_case.py @@ -29,10 +29,10 @@ """Common lifecycle code for in-memory-ticket-exchange Face-layer tests.""" -from _framework.face import implementations -from _framework.face.testing import base_util -from _framework.face.testing import test_case -from _framework.foundation import logging_pool +from grpc.framework.face import implementations +from grpc.framework.face.testing import base_util +from grpc.framework.face.testing import test_case +from grpc.framework.foundation import logging_pool _TIMEOUT = 3 _MAXIMUM_POOL_SIZE = 100 diff --git a/src/python/src/_framework/face/blocking_invocation_inline_service_test.py b/src/python/src/grpc/framework/face/blocking_invocation_inline_service_test.py similarity index 92% rename from src/python/src/_framework/face/blocking_invocation_inline_service_test.py rename to src/python/src/grpc/framework/face/blocking_invocation_inline_service_test.py index 96563c94eeb..636cd701ff1 100644 --- a/src/python/src/_framework/face/blocking_invocation_inline_service_test.py +++ b/src/python/src/grpc/framework/face/blocking_invocation_inline_service_test.py @@ -31,8 +31,8 @@ import unittest -from _framework.face import _test_case -from _framework.face.testing import blocking_invocation_inline_service_test_case as test_case +from grpc.framework.face import _test_case +from grpc.framework.face.testing import blocking_invocation_inline_service_test_case as test_case class BlockingInvocationInlineServiceTest( diff --git a/src/python/src/_framework/face/demonstration.py b/src/python/src/grpc/framework/face/demonstration.py similarity index 95% rename from src/python/src/_framework/face/demonstration.py rename to src/python/src/grpc/framework/face/demonstration.py index 501ec6b3f83..d922f6e5ef0 100644 --- a/src/python/src/_framework/face/demonstration.py +++ b/src/python/src/grpc/framework/face/demonstration.py @@ -29,10 +29,10 @@ """Demonstration-suitable implementation of the face layer of RPC Framework.""" -from _framework.base import util as _base_util -from _framework.base.packets import implementations as _tickets_implementations -from _framework.face import implementations -from _framework.foundation import logging_pool +from grpc.framework.base import util as _base_util +from grpc.framework.base.packets import implementations as _tickets_implementations +from grpc.framework.face import implementations +from grpc.framework.foundation import logging_pool _POOL_SIZE_LIMIT = 20 diff --git a/src/python/src/_framework/face/event_invocation_synchronous_event_service_test.py b/src/python/src/grpc/framework/face/event_invocation_synchronous_event_service_test.py similarity index 92% rename from src/python/src/_framework/face/event_invocation_synchronous_event_service_test.py rename to src/python/src/grpc/framework/face/event_invocation_synchronous_event_service_test.py index 48e05b2478e..25f3e297b5c 100644 --- a/src/python/src/_framework/face/event_invocation_synchronous_event_service_test.py +++ b/src/python/src/grpc/framework/face/event_invocation_synchronous_event_service_test.py @@ -31,8 +31,8 @@ import unittest -from _framework.face import _test_case -from _framework.face.testing import event_invocation_synchronous_event_service_test_case as test_case +from grpc.framework.face import _test_case +from grpc.framework.face.testing import event_invocation_synchronous_event_service_test_case as test_case class EventInvocationSynchronousEventServiceTest( diff --git a/src/python/src/_framework/face/exceptions.py b/src/python/src/grpc/framework/face/exceptions.py similarity index 100% rename from src/python/src/_framework/face/exceptions.py rename to src/python/src/grpc/framework/face/exceptions.py diff --git a/src/python/src/_framework/face/future_invocation_asynchronous_event_service_test.py b/src/python/src/grpc/framework/face/future_invocation_asynchronous_event_service_test.py similarity index 92% rename from src/python/src/_framework/face/future_invocation_asynchronous_event_service_test.py rename to src/python/src/grpc/framework/face/future_invocation_asynchronous_event_service_test.py index 96f5fe85d3d..38229ea9f4a 100644 --- a/src/python/src/_framework/face/future_invocation_asynchronous_event_service_test.py +++ b/src/python/src/grpc/framework/face/future_invocation_asynchronous_event_service_test.py @@ -31,8 +31,8 @@ import unittest -from _framework.face import _test_case -from _framework.face.testing import future_invocation_asynchronous_event_service_test_case as test_case +from grpc.framework.face import _test_case +from grpc.framework.face.testing import future_invocation_asynchronous_event_service_test_case as test_case class FutureInvocationAsynchronousEventServiceTest( diff --git a/src/python/src/_framework/face/implementations.py b/src/python/src/grpc/framework/face/implementations.py similarity index 96% rename from src/python/src/_framework/face/implementations.py rename to src/python/src/grpc/framework/face/implementations.py index 94362e20071..c499b907207 100644 --- a/src/python/src/_framework/face/implementations.py +++ b/src/python/src/grpc/framework/face/implementations.py @@ -29,12 +29,12 @@ """Entry points into the Face layer of RPC Framework.""" -from _framework.base import exceptions as _base_exceptions -from _framework.base import interfaces as base_interfaces -from _framework.face import _calls -from _framework.face import _service -from _framework.face import exceptions -from _framework.face import interfaces +from grpc.framework.base import exceptions as _base_exceptions +from grpc.framework.base import interfaces as base_interfaces +from grpc.framework.face import _calls +from grpc.framework.face import _service +from grpc.framework.face import exceptions +from grpc.framework.face import interfaces class _BaseServicer(base_interfaces.Servicer): diff --git a/src/python/src/_framework/face/interfaces.py b/src/python/src/grpc/framework/face/interfaces.py similarity index 98% rename from src/python/src/_framework/face/interfaces.py rename to src/python/src/grpc/framework/face/interfaces.py index 24804543694..548e9ce4dbe 100644 --- a/src/python/src/_framework/face/interfaces.py +++ b/src/python/src/grpc/framework/face/interfaces.py @@ -34,9 +34,9 @@ import enum # exceptions, abandonment, and future are referenced from specification in this # module. -from _framework.face import exceptions # pylint: disable=unused-import -from _framework.foundation import abandonment # pylint: disable=unused-import -from _framework.foundation import future # pylint: disable=unused-import +from grpc.framework.face import exceptions # pylint: disable=unused-import +from grpc.framework.foundation import abandonment # pylint: disable=unused-import +from grpc.framework.foundation import future # pylint: disable=unused-import class CancellableIterator(object): diff --git a/src/python/src/_junkdrawer/__init__.py b/src/python/src/grpc/framework/face/testing/__init__.py similarity index 100% rename from src/python/src/_junkdrawer/__init__.py rename to src/python/src/grpc/framework/face/testing/__init__.py diff --git a/src/python/src/_framework/face/testing/base_util.py b/src/python/src/grpc/framework/face/testing/base_util.py similarity index 92% rename from src/python/src/_framework/face/testing/base_util.py rename to src/python/src/grpc/framework/face/testing/base_util.py index d9ccb3af8fc..7872a6b9e94 100644 --- a/src/python/src/_framework/face/testing/base_util.py +++ b/src/python/src/grpc/framework/face/testing/base_util.py @@ -32,11 +32,11 @@ import abc # interfaces is referenced from specification in this module. -from _framework.base import util as _base_util -from _framework.base.packets import implementations -from _framework.base.packets import in_memory -from _framework.base.packets import interfaces # pylint: disable=unused-import -from _framework.foundation import logging_pool +from grpc.framework.base import util as _base_util +from grpc.framework.base.packets import implementations +from grpc.framework.base.packets import in_memory +from grpc.framework.base.packets import interfaces # pylint: disable=unused-import +from grpc.framework.foundation import logging_pool _POOL_SIZE_LIMIT = 20 diff --git a/src/python/src/_framework/face/testing/blocking_invocation_inline_service_test_case.py b/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py similarity index 96% rename from src/python/src/_framework/face/testing/blocking_invocation_inline_service_test_case.py rename to src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py index 0b1a2f0bd21..993098f4ae5 100644 --- a/src/python/src/_framework/face/testing/blocking_invocation_inline_service_test_case.py +++ b/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py @@ -33,12 +33,12 @@ import abc import unittest # pylint: disable=unused-import -from _framework.face import exceptions -from _framework.face.testing import control -from _framework.face.testing import coverage -from _framework.face.testing import digest -from _framework.face.testing import stock_service -from _framework.face.testing import test_case +from grpc.framework.face import exceptions +from grpc.framework.face.testing import control +from grpc.framework.face.testing import coverage +from grpc.framework.face.testing import digest +from grpc.framework.face.testing import stock_service +from grpc.framework.face.testing import test_case _TIMEOUT = 3 diff --git a/src/python/src/_framework/face/testing/callback.py b/src/python/src/grpc/framework/face/testing/callback.py similarity index 98% rename from src/python/src/_framework/face/testing/callback.py rename to src/python/src/grpc/framework/face/testing/callback.py index 7a20869abe9..d0e63c8c562 100644 --- a/src/python/src/_framework/face/testing/callback.py +++ b/src/python/src/grpc/framework/face/testing/callback.py @@ -31,7 +31,7 @@ import threading -from _framework.foundation import stream +from grpc.framework.foundation import stream class Callback(stream.Consumer): diff --git a/src/python/src/_framework/face/testing/control.py b/src/python/src/grpc/framework/face/testing/control.py similarity index 100% rename from src/python/src/_framework/face/testing/control.py rename to src/python/src/grpc/framework/face/testing/control.py diff --git a/src/python/src/_framework/face/testing/coverage.py b/src/python/src/grpc/framework/face/testing/coverage.py similarity index 100% rename from src/python/src/_framework/face/testing/coverage.py rename to src/python/src/grpc/framework/face/testing/coverage.py diff --git a/src/python/src/_framework/face/testing/digest.py b/src/python/src/grpc/framework/face/testing/digest.py similarity index 96% rename from src/python/src/_framework/face/testing/digest.py rename to src/python/src/grpc/framework/face/testing/digest.py index 8d1291c9755..b8fb5733013 100644 --- a/src/python/src/_framework/face/testing/digest.py +++ b/src/python/src/grpc/framework/face/testing/digest.py @@ -34,13 +34,13 @@ import threading # testing_control, interfaces, and testing_service are referenced from # specification in this module. -from _framework.face import exceptions -from _framework.face import interfaces as face_interfaces -from _framework.face.testing import control as testing_control # pylint: disable=unused-import -from _framework.face.testing import interfaces # pylint: disable=unused-import -from _framework.face.testing import service as testing_service # pylint: disable=unused-import -from _framework.foundation import stream -from _framework.foundation import stream_util +from grpc.framework.face import exceptions +from grpc.framework.face import interfaces as face_interfaces +from grpc.framework.face.testing import control as testing_control # pylint: disable=unused-import +from grpc.framework.face.testing import interfaces # pylint: disable=unused-import +from grpc.framework.face.testing import service as testing_service # pylint: disable=unused-import +from grpc.framework.foundation import stream +from grpc.framework.foundation import stream_util _IDENTITY = lambda x: x diff --git a/src/python/src/_framework/face/testing/event_invocation_synchronous_event_service_test_case.py b/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py similarity index 97% rename from src/python/src/_framework/face/testing/event_invocation_synchronous_event_service_test_case.py rename to src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py index cb786f500c0..21e669b9080 100644 --- a/src/python/src/_framework/face/testing/event_invocation_synchronous_event_service_test_case.py +++ b/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py @@ -32,13 +32,13 @@ import abc import unittest -from _framework.face import interfaces -from _framework.face.testing import callback as testing_callback -from _framework.face.testing import control -from _framework.face.testing import coverage -from _framework.face.testing import digest -from _framework.face.testing import stock_service -from _framework.face.testing import test_case +from grpc.framework.face import interfaces +from grpc.framework.face.testing import callback as testing_callback +from grpc.framework.face.testing import control +from grpc.framework.face.testing import coverage +from grpc.framework.face.testing import digest +from grpc.framework.face.testing import stock_service +from grpc.framework.face.testing import test_case _TIMEOUT = 3 diff --git a/src/python/src/_framework/face/testing/future_invocation_asynchronous_event_service_test_case.py b/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py similarity index 97% rename from src/python/src/_framework/face/testing/future_invocation_asynchronous_event_service_test_case.py rename to src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py index 939b238b66e..42db3050e1f 100644 --- a/src/python/src/_framework/face/testing/future_invocation_asynchronous_event_service_test_case.py +++ b/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py @@ -34,14 +34,14 @@ import contextlib import threading import unittest -from _framework.face import exceptions -from _framework.face.testing import control -from _framework.face.testing import coverage -from _framework.face.testing import digest -from _framework.face.testing import stock_service -from _framework.face.testing import test_case -from _framework.foundation import future -from _framework.foundation import logging_pool +from grpc.framework.face import exceptions +from grpc.framework.face.testing import control +from grpc.framework.face.testing import coverage +from grpc.framework.face.testing import digest +from grpc.framework.face.testing import stock_service +from grpc.framework.face.testing import test_case +from grpc.framework.foundation import future +from grpc.framework.foundation import logging_pool _TIMEOUT = 3 _MAXIMUM_POOL_SIZE = 100 diff --git a/src/python/src/_framework/face/testing/interfaces.py b/src/python/src/grpc/framework/face/testing/interfaces.py similarity index 97% rename from src/python/src/_framework/face/testing/interfaces.py rename to src/python/src/grpc/framework/face/testing/interfaces.py index 253f6f118df..5932dabf1eb 100644 --- a/src/python/src/_framework/face/testing/interfaces.py +++ b/src/python/src/grpc/framework/face/testing/interfaces.py @@ -32,7 +32,7 @@ import abc # cardinality is referenced from specification in this module. -from _framework.common import cardinality # pylint: disable=unused-import +from grpc.framework.common import cardinality # pylint: disable=unused-import class Method(object): diff --git a/src/python/src/_framework/face/testing/serial.py b/src/python/src/grpc/framework/face/testing/serial.py similarity index 100% rename from src/python/src/_framework/face/testing/serial.py rename to src/python/src/grpc/framework/face/testing/serial.py diff --git a/src/python/src/_framework/face/testing/service.py b/src/python/src/grpc/framework/face/testing/service.py similarity index 98% rename from src/python/src/_framework/face/testing/service.py rename to src/python/src/grpc/framework/face/testing/service.py index 771346ec2e1..a58e2ee42e4 100644 --- a/src/python/src/_framework/face/testing/service.py +++ b/src/python/src/grpc/framework/face/testing/service.py @@ -32,8 +32,8 @@ import abc # interfaces is referenced from specification in this module. -from _framework.face import interfaces as face_interfaces # pylint: disable=unused-import -from _framework.face.testing import interfaces +from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import +from grpc.framework.face.testing import interfaces class UnaryUnaryTestMethod(interfaces.Method): diff --git a/src/python/src/_framework/face/testing/stock_service.py b/src/python/src/grpc/framework/face/testing/stock_service.py similarity index 97% rename from src/python/src/_framework/face/testing/stock_service.py rename to src/python/src/grpc/framework/face/testing/stock_service.py index bd82877e838..83c9418b074 100644 --- a/src/python/src/_framework/face/testing/stock_service.py +++ b/src/python/src/grpc/framework/face/testing/stock_service.py @@ -29,12 +29,12 @@ """Examples of Python implementations of the stock.proto Stock service.""" -from _framework.common import cardinality -from _framework.face.testing import service -from _framework.foundation import abandonment -from _framework.foundation import stream -from _framework.foundation import stream_util -from _junkdrawer import stock_pb2 +from grpc.framework.common import cardinality +from grpc.framework.face.testing import service +from grpc.framework.foundation import abandonment +from grpc.framework.foundation import stream +from grpc.framework.foundation import stream_util +from grpc._junkdrawer import stock_pb2 SYMBOL_FORMAT = 'test symbol:%03d' STREAM_LENGTH = 400 diff --git a/src/python/src/_framework/face/testing/test_case.py b/src/python/src/grpc/framework/face/testing/test_case.py similarity index 96% rename from src/python/src/_framework/face/testing/test_case.py rename to src/python/src/grpc/framework/face/testing/test_case.py index 09b5a67f5ad..218a2a8549b 100644 --- a/src/python/src/_framework/face/testing/test_case.py +++ b/src/python/src/grpc/framework/face/testing/test_case.py @@ -32,8 +32,8 @@ import abc # face_interfaces and interfaces are referenced in specification in this module. -from _framework.face import interfaces as face_interfaces # pylint: disable=unused-import -from _framework.face.testing import interfaces # pylint: disable=unused-import +from grpc.framework.face import interfaces as face_interfaces # pylint: disable=unused-import +from grpc.framework.face.testing import interfaces # pylint: disable=unused-import class FaceTestCase(object): diff --git a/src/python/src/grpc_early_adopter/__init__.py b/src/python/src/grpc/framework/foundation/__init__.py similarity index 100% rename from src/python/src/grpc_early_adopter/__init__.py rename to src/python/src/grpc/framework/foundation/__init__.py diff --git a/src/python/src/_framework/foundation/_later_test.py b/src/python/src/grpc/framework/foundation/_later_test.py similarity index 99% rename from src/python/src/_framework/foundation/_later_test.py rename to src/python/src/grpc/framework/foundation/_later_test.py index 50b67907db4..e83e7031289 100644 --- a/src/python/src/_framework/foundation/_later_test.py +++ b/src/python/src/grpc/framework/foundation/_later_test.py @@ -33,7 +33,7 @@ import threading import time import unittest -from _framework.foundation import later +from grpc.framework.foundation import later TICK = 0.1 diff --git a/src/python/src/_framework/foundation/_logging_pool_test.py b/src/python/src/grpc/framework/foundation/_logging_pool_test.py similarity index 97% rename from src/python/src/_framework/foundation/_logging_pool_test.py rename to src/python/src/grpc/framework/foundation/_logging_pool_test.py index f2224d80e5c..11463a8bece 100644 --- a/src/python/src/_framework/foundation/_logging_pool_test.py +++ b/src/python/src/grpc/framework/foundation/_logging_pool_test.py @@ -31,7 +31,7 @@ import unittest -from _framework.foundation import logging_pool +from grpc.framework.foundation import logging_pool _POOL_SIZE = 16 diff --git a/src/python/src/_framework/foundation/_timer_future.py b/src/python/src/grpc/framework/foundation/_timer_future.py similarity index 99% rename from src/python/src/_framework/foundation/_timer_future.py rename to src/python/src/grpc/framework/foundation/_timer_future.py index 4aa66991c5e..2c9996aa9db 100644 --- a/src/python/src/_framework/foundation/_timer_future.py +++ b/src/python/src/grpc/framework/foundation/_timer_future.py @@ -33,7 +33,7 @@ import sys import threading import time -from _framework.foundation import future +from grpc.framework.foundation import future class TimerFuture(future.Future): diff --git a/src/python/src/_framework/foundation/abandonment.py b/src/python/src/grpc/framework/foundation/abandonment.py similarity index 100% rename from src/python/src/_framework/foundation/abandonment.py rename to src/python/src/grpc/framework/foundation/abandonment.py diff --git a/src/python/src/_framework/foundation/callable_util.py b/src/python/src/grpc/framework/foundation/callable_util.py similarity index 100% rename from src/python/src/_framework/foundation/callable_util.py rename to src/python/src/grpc/framework/foundation/callable_util.py diff --git a/src/python/src/_framework/foundation/future.py b/src/python/src/grpc/framework/foundation/future.py similarity index 100% rename from src/python/src/_framework/foundation/future.py rename to src/python/src/grpc/framework/foundation/future.py diff --git a/src/python/src/_framework/foundation/later.py b/src/python/src/grpc/framework/foundation/later.py similarity index 97% rename from src/python/src/_framework/foundation/later.py rename to src/python/src/grpc/framework/foundation/later.py index fc2cf578d0b..1d1e0650413 100644 --- a/src/python/src/_framework/foundation/later.py +++ b/src/python/src/grpc/framework/foundation/later.py @@ -31,7 +31,7 @@ import time -from _framework.foundation import _timer_future +from grpc.framework.foundation import _timer_future def later(delay, computation): diff --git a/src/python/src/_framework/foundation/logging_pool.py b/src/python/src/grpc/framework/foundation/logging_pool.py similarity index 100% rename from src/python/src/_framework/foundation/logging_pool.py rename to src/python/src/grpc/framework/foundation/logging_pool.py diff --git a/src/python/src/_framework/foundation/stream.py b/src/python/src/grpc/framework/foundation/stream.py similarity index 100% rename from src/python/src/_framework/foundation/stream.py rename to src/python/src/grpc/framework/foundation/stream.py diff --git a/src/python/src/_framework/foundation/stream_testing.py b/src/python/src/grpc/framework/foundation/stream_testing.py similarity index 98% rename from src/python/src/_framework/foundation/stream_testing.py rename to src/python/src/grpc/framework/foundation/stream_testing.py index c1acedc5c6e..098a53d5e75 100644 --- a/src/python/src/_framework/foundation/stream_testing.py +++ b/src/python/src/grpc/framework/foundation/stream_testing.py @@ -29,7 +29,7 @@ """Utilities for testing stream-related code.""" -from _framework.foundation import stream +from grpc.framework.foundation import stream class TestConsumer(stream.Consumer): diff --git a/src/python/src/_framework/foundation/stream_util.py b/src/python/src/grpc/framework/foundation/stream_util.py similarity index 99% rename from src/python/src/_framework/foundation/stream_util.py rename to src/python/src/grpc/framework/foundation/stream_util.py index 3a9c0433169..2210e4efcf0 100644 --- a/src/python/src/_framework/foundation/stream_util.py +++ b/src/python/src/grpc/framework/foundation/stream_util.py @@ -32,7 +32,7 @@ import logging import threading -from _framework.foundation import stream +from grpc.framework.foundation import stream _NO_VALUE = object() diff --git a/src/python/src/setup.py b/src/python/src/setup.py index 93af4d68ca9..8e33ebb31c4 100644 --- a/src/python/src/setup.py +++ b/src/python/src/setup.py @@ -32,13 +32,13 @@ from distutils import core as _core _EXTENSION_SOURCES = ( - '_adapter/_c.c', - '_adapter/_call.c', - '_adapter/_channel.c', - '_adapter/_completion_queue.c', - '_adapter/_error.c', - '_adapter/_server.c', - '_adapter/_server_credentials.c', + 'grpc/_adapter/_c.c', + 'grpc/_adapter/_call.c', + 'grpc/_adapter/_channel.c', + 'grpc/_adapter/_completion_queue.c', + 'grpc/_adapter/_error.c', + 'grpc/_adapter/_server.c', + 'grpc/_adapter/_server_credentials.c', ) _EXTENSION_INCLUDE_DIRECTORIES = ( @@ -51,29 +51,31 @@ _EXTENSION_LIBRARIES = ( ) _EXTENSION_MODULE = _core.Extension( - '_adapter._c', sources=list(_EXTENSION_SOURCES), + 'grpc._adapter._c', sources=list(_EXTENSION_SOURCES), include_dirs=_EXTENSION_INCLUDE_DIRECTORIES, libraries=_EXTENSION_LIBRARIES, ) _PACKAGES=( - '_adapter', - '_framework', - '_framework.base', - '_framework.base.packets', - '_framework.common', - '_framework.face', - '_framework.face.testing', - '_framework.foundation', - '_junkdrawer', - 'grpc_early_adopter', + 'grpc', + 'grpc._adapter', + 'grpc._junkdrawer', + 'grpc.early_adopter', + 'grpc.framework', + 'grpc.framework.base', + 'grpc.framework.base.packets', + 'grpc.framework.common', + 'grpc.framework.face', + 'grpc.framework.face.testing', + 'grpc.framework.foundation', ) _PACKAGE_DIRECTORIES = { - '_adapter': '_adapter', - '_framework': '_framework', - '_junkdrawer': '_junkdrawer', - 'grpc_early_adopter': 'grpc_early_adopter', + 'grpc': 'grpc', + 'grpc._adapter': 'grpc/_adapter', + 'grpc._junkdrawer': 'grpc/_junkdrawer', + 'grpc.early_adopter': 'grpc/early_adopter', + 'grpc.framework': 'grpc/framework', } _core.setup( diff --git a/tools/dockerfile/grpc_python/Dockerfile b/tools/dockerfile/grpc_python/Dockerfile index 2390ed7bcfa..d434b473510 100644 --- a/tools/dockerfile/grpc_python/Dockerfile +++ b/tools/dockerfile/grpc_python/Dockerfile @@ -17,19 +17,19 @@ RUN cd /var/local/git/grpc \ # Run Python GRPC's tests RUN cd /var/local/git/grpc \ # TODO(nathaniel): It would be nice for these to be auto-discoverable? - && python2.7 -B -m _adapter._blocking_invocation_inline_service_test - && python2.7 -B -m _adapter._c_test - && python2.7 -B -m _adapter._event_invocation_synchronous_event_service_test - && python2.7 -B -m _adapter._future_invocation_asynchronous_event_service_test - && python2.7 -B -m _adapter._links_test - && python2.7 -B -m _adapter._lonely_rear_link_test - && python2.7 -B -m _adapter._low_test - && python2.7 -B -m _framework.base.packets.implementations_test - && python2.7 -B -m _framework.face.blocking_invocation_inline_service_test - && python2.7 -B -m _framework.face.event_invocation_synchronous_event_service_test - && python2.7 -B -m _framework.face.future_invocation_asynchronous_event_service_test - && python2.7 -B -m _framework.foundation._later_test - && python2.7 -B -m _framework.foundation._logging_pool_test + && python2.7 -B -m grpc._adapter._blocking_invocation_inline_service_test + && python2.7 -B -m grpc._adapter._c_test + && python2.7 -B -m grpc._adapter._event_invocation_synchronous_event_service_test + && python2.7 -B -m grpc._adapter._future_invocation_asynchronous_event_service_test + && python2.7 -B -m grpc._adapter._links_test + && python2.7 -B -m grpc._adapter._lonely_rear_link_test + && python2.7 -B -m grpc._adapter._low_test + && python2.7 -B -m grpc._framework.base.packets.implementations_test + && python2.7 -B -m grpc._framework.face.blocking_invocation_inline_service_test + && python2.7 -B -m grpc._framework.face.event_invocation_synchronous_event_service_test + && python2.7 -B -m grpc._framework.face.future_invocation_asynchronous_event_service_test + && python2.7 -B -m grpc._framework.foundation._later_test + && python2.7 -B -m grpc._framework.foundation._logging_pool_test # Add a cacerts directory containing the Google root pem file, allowing the interop client to access the production test instance ADD cacerts cacerts diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh index 7d3ee73a0e4..b79278857f3 100755 --- a/tools/run_tests/run_python.sh +++ b/tools/run_tests/run_python.sh @@ -9,18 +9,18 @@ root=`pwd` export LD_LIBRARY_PATH=$root/libs/opt source python2.7_virtual_environment/bin/activate # TODO(issue 215): Properly itemize these in run_tests.py so that they can be parallelized. -python2.7 -B -m _adapter._blocking_invocation_inline_service_test -python2.7 -B -m _adapter._c_test -python2.7 -B -m _adapter._event_invocation_synchronous_event_service_test -python2.7 -B -m _adapter._future_invocation_asynchronous_event_service_test -python2.7 -B -m _adapter._links_test -python2.7 -B -m _adapter._lonely_rear_link_test -python2.7 -B -m _adapter._low_test -python2.7 -B -m _framework.base.packets.implementations_test -python2.7 -B -m _framework.face.blocking_invocation_inline_service_test -python2.7 -B -m _framework.face.event_invocation_synchronous_event_service_test -python2.7 -B -m _framework.face.future_invocation_asynchronous_event_service_test -python2.7 -B -m _framework.foundation._later_test -python2.7 -B -m _framework.foundation._logging_pool_test +python2.7 -B -m grpc._adapter._blocking_invocation_inline_service_test +python2.7 -B -m grpc._adapter._c_test +python2.7 -B -m grpc._adapter._event_invocation_synchronous_event_service_test +python2.7 -B -m grpc._adapter._future_invocation_asynchronous_event_service_test +python2.7 -B -m grpc._adapter._links_test +python2.7 -B -m grpc._adapter._lonely_rear_link_test +python2.7 -B -m grpc._adapter._low_test +python2.7 -B -m grpc.framework.base.packets.implementations_test +python2.7 -B -m grpc.framework.face.blocking_invocation_inline_service_test +python2.7 -B -m grpc.framework.face.event_invocation_synchronous_event_service_test +python2.7 -B -m grpc.framework.face.future_invocation_asynchronous_event_service_test +python2.7 -B -m grpc.framework.foundation._later_test +python2.7 -B -m grpc.framework.foundation._logging_pool_test # TODO(nathaniel): Get tests working under 3.4 (requires 3.X-friendly protobuf) # python3.4 -B -m unittest discover -s src/python -p '*.py' From 16b8924068c52eb20e0cfd3b1416c6eb720992c3 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Wed, 18 Feb 2015 02:53:37 +0000 Subject: [PATCH 31/31] Drop an erroneous trailing backslash. --- tools/dockerfile/grpc_python_base/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dockerfile/grpc_python_base/Dockerfile b/tools/dockerfile/grpc_python_base/Dockerfile index 01292c2e121..98f695a8191 100644 --- a/tools/dockerfile/grpc_python_base/Dockerfile +++ b/tools/dockerfile/grpc_python_base/Dockerfile @@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y \ python-all-dev \ python3-all-dev \ python-pip \ - python-virtualenv \ + python-virtualenv # Install Python packages from PyPI RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.0.0-alpha-1