Merge branch 'master' into loaded

pull/5240/head
Vijay Pai 9 years ago
commit ee53dc5e08
  1. 1
      .yardopts
  2. 6
      BUILD
  3. 38
      Makefile
  4. 1
      PYTHON-MANIFEST.in
  5. 1
      binding.gyp
  6. 12
      build.yaml
  7. 12
      examples/node/README.md
  8. 2
      examples/node/greeter_client.js
  9. 2
      examples/node/greeter_server.js
  10. 50
      examples/node/helloworld.proto
  11. 2
      examples/node/package.json
  12. 120
      examples/node/route_guide/route_guide.proto
  13. 6
      examples/node/route_guide/route_guide_client.js
  14. 4
      examples/node/route_guide/route_guide_server.js
  15. 3
      gRPC.podspec
  16. 6
      grpc.gemspec
  17. 2
      include/grpc++/create_channel.h
  18. 5
      package.json
  19. 1
      requirements.txt
  20. 43
      setup.py
  21. 600
      src/core/census/log.c
  22. 93
      src/core/census/log.h
  23. 6
      src/php/ext/grpc/call.c
  24. 56
      src/php/ext/grpc/channel.c
  25. 45
      src/php/tests/generated_code/AbstractGeneratedCodeTest.php
  26. 135
      src/php/tests/unit_tests/CallCredentials2Test.php
  27. 136
      src/php/tests/unit_tests/CallCredentials3Test.php
  28. 51
      src/php/tests/unit_tests/CallCredentialsTest.php
  29. 28
      src/php/tests/unit_tests/CallTest.php
  30. 73
      src/php/tests/unit_tests/ChannelCredentialsTest.php
  31. 82
      src/php/tests/unit_tests/ChannelTest.php
  32. 344
      src/php/tests/unit_tests/EndToEndTest.php
  33. 71
      src/php/tests/unit_tests/ServerTest.php
  34. 65
      src/php/tests/unit_tests/TimevalTest.php
  35. 38
      src/python/grpcio/README.rst
  36. 133
      src/python/grpcio/commands.py
  37. 1
      src/python/grpcio/grpc_core_dependencies.py
  38. 102
      src/python/grpcio/precompiled.py
  39. 4
      templates/grpc.gemspec.template
  40. 3
      templates/package.json.template
  41. 589
      test/core/census/log_test.c
  42. 4
      test/cpp/qps/driver.cc
  43. 3
      test/cpp/qps/server_async.cc
  44. 3
      test/distrib/node/run_distrib_test.sh
  45. 5
      tools/dockerfile/distribtest/python_fedora21_x64/Dockerfile
  46. 5
      tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
  47. 2
      tools/doxygen/Doxyfile.core.internal
  48. 4
      tools/run_tests/build_artifact_node.sh
  49. 12
      tools/run_tests/build_artifact_python.sh
  50. 1
      tools/run_tests/build_package_node.sh
  51. 10
      tools/run_tests/distribtest_targets.py
  52. 20
      tools/run_tests/sources_and_headers.json
  53. 20
      tools/run_tests/tests.json
  54. 27
      vsprojects/buildtests_c.sln
  55. 3
      vsprojects/vcxproj/grpc/grpc.vcxproj
  56. 6
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  57. 3
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  58. 6
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
  59. 199
      vsprojects/vcxproj/test/census_log_test/census_log_test.vcxproj
  60. 21
      vsprojects/vcxproj/test/census_log_test/census_log_test.vcxproj.filters

@ -0,0 +1 @@
src/ruby/**/*.rb

@ -282,6 +282,7 @@ cc_library(
"src/core/transport/transport.h",
"src/core/transport/transport_impl.h",
"src/core/census/aggregation.h",
"src/core/census/log.h",
"src/core/census/rpc_metric_id.h",
"src/core/httpcli/httpcli_security_connector.c",
"src/core/security/base64.c",
@ -433,6 +434,7 @@ cc_library(
"src/core/transport/transport_op_string.c",
"src/core/census/context.c",
"src/core/census/initialize.c",
"src/core/census/log.c",
"src/core/census/operation.c",
"src/core/census/placeholders.c",
"src/core/census/tracing.c",
@ -584,6 +586,7 @@ cc_library(
"src/core/transport/transport.h",
"src/core/transport/transport_impl.h",
"src/core/census/aggregation.h",
"src/core/census/log.h",
"src/core/census/rpc_metric_id.h",
"src/core/surface/init_unsecure.c",
"src/core/census/grpc_context.c",
@ -715,6 +718,7 @@ cc_library(
"src/core/transport/transport_op_string.c",
"src/core/census/context.c",
"src/core/census/initialize.c",
"src/core/census/log.c",
"src/core/census/operation.c",
"src/core/census/placeholders.c",
"src/core/census/tracing.c",
@ -1395,6 +1399,7 @@ objc_library(
"src/core/transport/transport_op_string.c",
"src/core/census/context.c",
"src/core/census/initialize.c",
"src/core/census/log.c",
"src/core/census/operation.c",
"src/core/census/placeholders.c",
"src/core/census/tracing.c",
@ -1541,6 +1546,7 @@ objc_library(
"src/core/transport/transport.h",
"src/core/transport/transport_impl.h",
"src/core/census/aggregation.h",
"src/core/census/log.h",
"src/core/census/rpc_metric_id.h",
],
includes = [

@ -826,6 +826,7 @@ alloc_test: $(BINDIR)/$(CONFIG)/alloc_test
alpn_test: $(BINDIR)/$(CONFIG)/alpn_test
bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
census_log_test: $(BINDIR)/$(CONFIG)/census_log_test
channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test
chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
@ -1134,6 +1135,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/alpn_test \
$(BINDIR)/$(CONFIG)/bin_encoder_test \
$(BINDIR)/$(CONFIG)/census_context_test \
$(BINDIR)/$(CONFIG)/census_log_test \
$(BINDIR)/$(CONFIG)/channel_create_test \
$(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \
$(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \
@ -1369,6 +1371,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/bin_encoder_test || ( echo test bin_encoder_test failed ; exit 1 )
$(E) "[RUN] Testing census_context_test"
$(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 )
$(E) "[RUN] Testing census_log_test"
$(Q) $(BINDIR)/$(CONFIG)/census_log_test || ( echo test census_log_test failed ; exit 1 )
$(E) "[RUN] Testing channel_create_test"
$(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 )
$(E) "[RUN] Testing chttp2_hpack_encoder_test"
@ -2464,6 +2468,7 @@ LIBGRPC_SRC = \
src/core/transport/transport_op_string.c \
src/core/census/context.c \
src/core/census/initialize.c \
src/core/census/log.c \
src/core/census/operation.c \
src/core/census/placeholders.c \
src/core/census/tracing.c \
@ -2748,6 +2753,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/transport/transport_op_string.c \
src/core/census/context.c \
src/core/census/initialize.c \
src/core/census/log.c \
src/core/census/operation.c \
src/core/census/placeholders.c \
src/core/census/tracing.c \
@ -5831,6 +5837,38 @@ endif
endif
CENSUS_LOG_TEST_SRC = \
test/core/census/log_test.c \
CENSUS_LOG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_LOG_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/census_log_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/census_log_test: $(CENSUS_LOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(CENSUS_LOG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_log_test
endif
$(OBJDIR)/$(CONFIG)/test/core/census/log_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_census_log_test: $(CENSUS_LOG_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(CENSUS_LOG_TEST_OBJS:.o=.dep)
endif
endif
CHANNEL_CREATE_TEST_SRC = \
test/core/surface/channel_create_test.c \

@ -7,6 +7,7 @@ graft third_party/zlib
include src/python/grpcio/commands.py
include src/python/grpcio/grpc_version.py
include src/python/grpcio/grpc_core_dependencies.py
include src/python/grpcio/precompiled.py
include src/python/grpcio/support.py
include src/python/grpcio/README.rst
include requirements.txt

@ -707,6 +707,7 @@
'src/core/transport/transport_op_string.c',
'src/core/census/context.c',
'src/core/census/initialize.c',
'src/core/census/log.c',
'src/core/census/operation.c',
'src/core/census/placeholders.c',
'src/core/census/tracing.c',

@ -14,10 +14,12 @@ filegroups:
- include/grpc/census.h
headers:
- src/core/census/aggregation.h
- src/core/census/log.h
- src/core/census/rpc_metric_id.h
src:
- src/core/census/context.c
- src/core/census/initialize.c
- src/core/census/log.c
- src/core/census/operation.c
- src/core/census/placeholders.c
- src/core/census/tracing.c
@ -953,6 +955,16 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: census_log_test
build: test
language: c
src:
- test/core/census/log_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: channel_create_test
build: test
language: c

@ -4,14 +4,10 @@ gRPC in 3 minutes (Node.js)
PREREQUISITES
-------------
- `node`: This requires Node 0.10.x or greater.
- [homebrew][] on Mac OS X. This simplifies the installation of the gRPC C core.
- `node`: This requires Node 0.12.x or greater.
INSTALL
-------
- [Install gRPC Node][]
- Install this package's dependencies
```sh
$ cd examples/node
@ -35,15 +31,9 @@ TRY IT!
$ node ./greeter_client.js
```
NOTE
----
This directory has a copy of `helloworld.proto` because it currently depends on
some Protocol Buffer 2.0 syntax that is deprecated in Protocol Buffer 3.0.
TUTORIAL
--------
You can find a more detailed tutorial in [gRPC Basics: Node.js][]
[homebrew]:http://brew.sh
[Install gRPC Node]:../../src/node
[gRPC Basics: Node.js]:http://www.grpc.io/docs/tutorials/basic/node.html

@ -31,7 +31,7 @@
*
*/
var PROTO_PATH = __dirname + '/helloworld.proto';
var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;

@ -31,7 +31,7 @@
*
*/
var PROTO_PATH = __dirname + '/helloworld.proto';
var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;

@ -1,50 +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.
syntax = "proto3";
option java_package = "ex.grpc";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
optional string name = 1;
}
// The response message containing the greetings
message HelloReply {
optional string message = 1;
}

@ -2,6 +2,6 @@
"name": "grpc-examples",
"version": "0.1.0",
"dependencies": {
"grpc": "0.12.0"
"grpc": "0.13.0"
}
}

@ -1,120 +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.
syntax = "proto3";
option java_package = "io.grpc.routeguide";
package routeguide;
// Interface exported by the server.
service RouteGuide {
// A simple RPC.
//
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
optional int32 latitude = 1;
optional int32 longitude = 2;
}
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
optional Point lo = 1;
// The other corner of the rectangle.
optional Point hi = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
optional string name = 1;
// The point where the feature is detected.
optional Point location = 2;
}
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
optional Point location = 1;
// The message to be sent.
optional string message = 2;
}
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
optional int32 point_count = 1;
// The number of known features passed while traversing the route.
optional int32 feature_count = 2;
// The distance covered in metres.
optional int32 distance = 3;
// The duration of the traversal in seconds.
optional int32 elapsed_time = 4;
}

@ -31,15 +31,17 @@
*
*/
var PROTO_PATH = __dirname + '/../../protos/route_guide.proto';
var async = require('async');
var fs = require('fs');
var parseArgs = require('minimist');
var path = require('path');
var _ = require('lodash');
var grpc = require('grpc');
var routeguide = grpc.load(__dirname + '/route_guide.proto').routeguide;
var routeguide = grpc.load(PROTO_PATH).routeguide;
var client = new routeguide.RouteGuide('localhost:50051',
grpc.Credentials.createInsecure());
grpc.credentials.createInsecure());
var COORD_FACTOR = 1e7;

@ -31,12 +31,14 @@
*
*/
var PROTO_PATH = __dirname + '/../../protos/route_guide.proto';
var fs = require('fs');
var parseArgs = require('minimist');
var path = require('path');
var _ = require('lodash');
var grpc = require('grpc');
var routeguide = grpc.load(__dirname + '/route_guide.proto').routeguide;
var routeguide = grpc.load(PROTO_PATH).routeguide;
var COORD_FACTOR = 1e7;

@ -286,6 +286,7 @@ Pod::Spec.new do |s|
'src/core/transport/transport.h',
'src/core/transport/transport_impl.h',
'src/core/census/aggregation.h',
'src/core/census/log.h',
'src/core/census/rpc_metric_id.h',
'include/grpc/grpc_security.h',
'include/grpc/impl/codegen/byte_buffer.h',
@ -450,6 +451,7 @@ Pod::Spec.new do |s|
'src/core/transport/transport_op_string.c',
'src/core/census/context.c',
'src/core/census/initialize.c',
'src/core/census/log.c',
'src/core/census/operation.c',
'src/core/census/placeholders.c',
'src/core/census/tracing.c'
@ -592,6 +594,7 @@ Pod::Spec.new do |s|
'src/core/transport/transport.h',
'src/core/transport/transport_impl.h',
'src/core/census/aggregation.h',
'src/core/census/log.h',
'src/core/census/rpc_metric_id.h'
ss.header_mappings_dir = '.'

@ -15,7 +15,7 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 2.0.0'
s.files = %w( Makefile )
s.files = %w( Makefile .yardopts )
s.files += %w( etc/roots.pem )
s.files += Dir.glob('src/ruby/bin/**/*')
s.files += Dir.glob('src/ruby/ext/**/*')
@ -31,7 +31,7 @@ Gem::Specification.new do |s|
s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.0.0.alpha.5.0.2'
s.add_dependency 'google-protobuf', '~> 3.0.0.alpha.5.0.3'
s.add_dependency 'googleauth', '~> 0.5.1'
s.add_development_dependency 'bundler', '~> 1.9'
@ -282,6 +282,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/transport/transport.h )
s.files += %w( src/core/transport/transport_impl.h )
s.files += %w( src/core/census/aggregation.h )
s.files += %w( src/core/census/log.h )
s.files += %w( src/core/census/rpc_metric_id.h )
s.files += %w( src/core/httpcli/httpcli_security_connector.c )
s.files += %w( src/core/security/base64.c )
@ -433,6 +434,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/transport/transport_op_string.c )
s.files += %w( src/core/census/context.c )
s.files += %w( src/core/census/initialize.c )
s.files += %w( src/core/census/log.c )
s.files += %w( src/core/census/operation.c )
s.files += %w( src/core/census/placeholders.c )
s.files += %w( src/core/census/tracing.c )

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -23,13 +23,12 @@
"test": "./node_modules/.bin/mocha src/node/test && npm run-script lint",
"gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json",
"coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test",
"preinstall": "npm install node-pre-gyp",
"install": "./node_modules/.bin/node-pre-gyp install --fallback-to-build"
},
"bundledDependencies": ["node-pre-gyp"],
"dependencies": {
"lodash": "^3.9.3",
"nan": "^2.0.0",
"node-pre-gyp": "^0.6.19",
"protobufjs": "^4.0.0"
},
"devDependencies": {
@ -228,6 +227,7 @@
"src/core/transport/transport.h",
"src/core/transport/transport_impl.h",
"src/core/census/aggregation.h",
"src/core/census/log.h",
"src/core/census/rpc_metric_id.h",
"src/core/httpcli/httpcli_security_connector.c",
"src/core/security/base64.c",
@ -379,6 +379,7 @@
"src/core/transport/transport_op_string.c",
"src/core/census/context.c",
"src/core/census/initialize.c",
"src/core/census/log.c",
"src/core/census/operation.c",
"src/core/census/placeholders.c",
"src/core/census/tracing.c",

@ -4,3 +4,4 @@ futures>=2.2.0
cython>=0.23
coverage>=4.0
six>=1.10
wheel>=0.29

@ -53,6 +53,7 @@ sys.path.insert(0, os.path.abspath(PYTHON_STEM))
# Break import-style to ensure we can actually find our in-repo dependencies.
import commands
import precompiled
import grpc_core_dependencies
import grpc_version
@ -156,15 +157,14 @@ SETUP_REQUIRES = (
) + INSTALL_REQUIRES
COMMAND_CLASS = {
'install': commands.Install,
'doc': commands.SphinxDocumentation,
'build_proto_modules': commands.BuildProtoModules,
'build_project_metadata': commands.BuildProjectMetadata,
'build_py': commands.BuildPy,
'build_ext': commands.BuildExt,
'build_tagged_ext': precompiled.BuildTaggedExt,
'gather': commands.Gather,
'run_interop': commands.RunInterop,
'bdist_egg_grpc_custom': commands.BdistEggCustomName,
}
# Ensure that package data is copied over before any commands have been run:
@ -202,10 +202,13 @@ TEST_LOADER = 'tests:Loader'
TEST_RUNNER = 'tests:Runner'
PACKAGE_DATA = {
# Binaries that may or may not be present in the final installation, but are
# mentioned here for completeness.
'grpc._cython': [
'_credentials/roots.pem',
'_windows/grpc_c.32.python',
'_windows/grpc_c.64.python',
'cygrpc.so',
],
}
if INSTALL_TESTS:
@ -215,19 +218,23 @@ else:
PACKAGES = setuptools.find_packages(
PYTHON_STEM, exclude=['tests', 'tests.*'])
setuptools.setup(
name='grpcio',
version=grpc_version.VERSION,
license=LICENSE,
ext_modules=CYTHON_EXTENSION_MODULES,
packages=list(PACKAGES),
package_dir=PACKAGE_DIRECTORIES,
package_data=PACKAGE_DATA,
install_requires=INSTALL_REQUIRES,
setup_requires=SETUP_REQUIRES,
cmdclass=COMMAND_CLASS,
tests_require=TESTS_REQUIRE,
test_suite=TEST_SUITE,
test_loader=TEST_LOADER,
test_runner=TEST_RUNNER,
)
setup_arguments = {
'name': 'grpcio',
'version': grpc_version.VERSION,
'license': LICENSE,
'ext_modules': CYTHON_EXTENSION_MODULES,
'packages': list(PACKAGES),
'package_dir': PACKAGE_DIRECTORIES,
'package_data': PACKAGE_DATA,
'install_requires': INSTALL_REQUIRES,
'setup_requires': SETUP_REQUIRES,
'cmdclass': COMMAND_CLASS,
'tests_require': TESTS_REQUIRE,
'test_suite': TEST_SUITE,
'test_loader': TEST_LOADER,
'test_runner': TEST_RUNNER,
}
precompiled.update_setup_arguments(setup_arguments)
setuptools.setup(**setup_arguments)

@ -0,0 +1,600 @@
/*
*
* Copyright 2015-2016, 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.
*
*/
// Implements an efficient in-memory log, optimized for multiple writers and
// a single reader. Available log space is divided up in blocks of
// CENSUS_LOG_2_MAX_RECORD_SIZE bytes. A block can be in one of the following
// three data structures:
// - Free blocks (free_block_list)
// - Blocks with unread data (dirty_block_list)
// - Blocks currently attached to cores (core_local_blocks[])
//
// census_log_start_write() moves a block from core_local_blocks[] to the end of
// dirty_block_list when block:
// - is out-of-space OR
// - has an incomplete record (an incomplete record occurs when a thread calls
// census_log_start_write() and is context-switched before calling
// census_log_end_write()
// So, blocks in dirty_block_list are ordered, from oldest to newest, by the
// time when block is detached from the core.
//
// census_log_read_next() first iterates over dirty_block_list and then
// core_local_blocks[]. It moves completely read blocks from dirty_block_list
// to free_block_list. Blocks in core_local_blocks[] are not freed, even when
// completely read.
//
// If the log is configured to discard old records and free_block_list is empty,
// census_log_start_write() iterates over dirty_block_list to allocate a
// new block. It moves the oldest available block (no pending read/write) to
// core_local_blocks[].
//
// core_local_block_struct is used to implement a map from core id to the block
// associated with that core. This mapping is advisory. It is possible that the
// block returned by this mapping is no longer associated with that core. This
// mapping is updated, lazily, by census_log_start_write().
//
// Locking in block struct:
//
// Exclusive g_log.lock must be held before calling any functions operating on
// block structs except census_log_start_write() and census_log_end_write().
//
// Writes to a block are serialized via writer_lock. census_log_start_write()
// acquires this lock and census_log_end_write() releases it. On failure to
// acquire the lock, writer allocates a new block for the current core and
// updates core_local_block accordingly.
//
// Simultaneous read and write access is allowed. Readers can safely read up to
// committed bytes (bytes_committed).
//
// reader_lock protects the block, currently being read, from getting recycled.
// start_read() acquires reader_lock and end_read() releases the lock.
//
// Read/write access to a block is disabled via try_disable_access(). It returns
// with both writer_lock and reader_lock held. These locks are subsequently
// released by enable_access() to enable access to the block.
//
// A note on naming: Most function/struct names are prepended by cl_
// (shorthand for census_log). Further, functions that manipulate structures
// include the name of the structure, which will be passed as the first
// argument. E.g. cl_block_initialize() will initialize a cl_block.
#include "src/core/census/log.h"
#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/useful.h>
#include <stdbool.h>
#include <string.h>
// End of platform specific code
typedef struct census_log_block_list_struct {
struct census_log_block_list_struct* next;
struct census_log_block_list_struct* prev;
struct census_log_block* block;
} cl_block_list_struct;
typedef struct census_log_block {
// Pointer to underlying buffer.
char* buffer;
gpr_atm writer_lock;
gpr_atm reader_lock;
// Keeps completely written bytes. Declared atomic because accessed
// simultaneously by reader and writer.
gpr_atm bytes_committed;
// Bytes already read.
size_t bytes_read;
// Links for list.
cl_block_list_struct link;
// We want this structure to be cacheline aligned. We assume the following
// sizes for the various parts on 32/64bit systems:
// type 32b size 64b size
// char* 4 8
// 3x gpr_atm 12 24
// size_t 4 8
// cl_block_list_struct 12 24
// TOTAL 32 64
//
// Depending on the size of our cacheline and the architecture, we
// selectively add char buffering to this structure. The size is checked
// via assert in census_log_initialize().
#if defined(GPR_ARCH_64)
#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 64)
#else
#if defined(GPR_ARCH_32)
#define CL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 32)
#else
#error "Unknown architecture"
#endif
#endif
#if CL_BLOCK_PAD_SIZE > 0
char padding[CL_BLOCK_PAD_SIZE];
#endif
} cl_block;
// A list of cl_blocks, doubly-linked through cl_block::link.
typedef struct census_log_block_list {
int32_t count; // Number of items in list.
cl_block_list_struct ht; // head/tail of linked list.
} cl_block_list;
// Cacheline aligned block pointers to avoid false sharing. Block pointer must
// be initialized via set_block(), before calling other functions
typedef struct census_log_core_local_block {
gpr_atm block;
// Ensure cachline alignment: we assume sizeof(gpr_atm) == 4 or 8
#if defined(GPR_ARCH_64)
#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 8)
#else
#if defined(GPR_ARCH_32)
#define CL_CORE_LOCAL_BLOCK_PAD_SIZE (GPR_CACHELINE_SIZE - 4)
#else
#error "Unknown architecture"
#endif
#endif
#if CL_CORE_LOCAL_BLOCK_PAD_SIZE > 0
char padding[CL_CORE_LOCAL_BLOCK_PAD_SIZE];
#endif
} cl_core_local_block;
struct census_log {
int discard_old_records;
// Number of cores (aka hardware-contexts)
unsigned num_cores;
// number of CENSUS_LOG_2_MAX_RECORD_SIZE blocks in log
uint32_t num_blocks;
cl_block* blocks; // Block metadata.
cl_core_local_block* core_local_blocks; // Keeps core to block mappings.
gpr_mu lock;
int initialized; // has log been initialized?
// Keeps the state of the reader iterator. A value of 0 indicates that
// iterator has reached the end. census_log_init_reader() resets the value
// to num_core to restart iteration.
uint32_t read_iterator_state;
// Points to the block being read. If non-NULL, the block is locked for
// reading(block_being_read_->reader_lock is held).
cl_block* block_being_read;
char* buffer;
cl_block_list free_block_list;
cl_block_list dirty_block_list;
gpr_atm out_of_space_count;
};
// Single internal log.
static struct census_log g_log;
// Functions that operate on an atomic memory location used as a lock.
// Returns non-zero if lock is acquired.
static int cl_try_lock(gpr_atm* lock) { return gpr_atm_acq_cas(lock, 0, 1); }
static void cl_unlock(gpr_atm* lock) { gpr_atm_rel_store(lock, 0); }
// Functions that operate on cl_core_local_block's.
static void cl_core_local_block_set_block(cl_core_local_block* clb,
cl_block* block) {
gpr_atm_rel_store(&clb->block, (gpr_atm)block);
}
static cl_block* cl_core_local_block_get_block(cl_core_local_block* clb) {
return (cl_block*)gpr_atm_acq_load(&clb->block);
}
// Functions that operate on cl_block_list_struct's.
static void cl_block_list_struct_initialize(cl_block_list_struct* bls,
cl_block* block) {
bls->next = bls->prev = bls;
bls->block = block;
}
// Functions that operate on cl_block_list's.
static void cl_block_list_initialize(cl_block_list* list) {
list->count = 0;
cl_block_list_struct_initialize(&list->ht, NULL);
}
// Returns head of *this, or NULL if empty.
static cl_block* cl_block_list_head(cl_block_list* list) {
return list->ht.next->block;
}
// Insert element *e after *pos.
static void cl_block_list_insert(cl_block_list* list, cl_block_list_struct* pos,
cl_block_list_struct* e) {
list->count++;
e->next = pos->next;
e->prev = pos;
e->next->prev = e;
e->prev->next = e;
}
// Insert block at the head of the list
static void cl_block_list_insert_at_head(cl_block_list* list, cl_block* block) {
cl_block_list_insert(list, &list->ht, &block->link);
}
// Insert block at the tail of the list.
static void cl_block_list_insert_at_tail(cl_block_list* list, cl_block* block) {
cl_block_list_insert(list, list->ht.prev, &block->link);
}
// Removes block *b. Requires *b be in the list.
static void cl_block_list_remove(cl_block_list* list, cl_block* b) {
list->count--;
b->link.next->prev = b->link.prev;
b->link.prev->next = b->link.next;
}
// Functions that operate on cl_block's
static void cl_block_initialize(cl_block* block, char* buffer) {
block->buffer = buffer;
gpr_atm_rel_store(&block->writer_lock, 0);
gpr_atm_rel_store(&block->reader_lock, 0);
gpr_atm_rel_store(&block->bytes_committed, 0);
block->bytes_read = 0;
cl_block_list_struct_initialize(&block->link, block);
}
// Guards against exposing partially written buffer to the reader.
static void cl_block_set_bytes_committed(cl_block* block,
size_t bytes_committed) {
gpr_atm_rel_store(&block->bytes_committed, (gpr_atm)bytes_committed);
}
static size_t cl_block_get_bytes_committed(cl_block* block) {
return (size_t)gpr_atm_acq_load(&block->bytes_committed);
}
// Tries to disable future read/write access to this block. Succeeds if:
// - no in-progress write AND
// - no in-progress read AND
// - 'discard_data' set to true OR no unread data
// On success, clears the block state and returns with writer_lock_ and
// reader_lock_ held. These locks are released by a subsequent
// cl_block_access_enable() call.
static bool cl_block_try_disable_access(cl_block* block, int discard_data) {
if (!cl_try_lock(&block->writer_lock)) {
return false;
}
if (!cl_try_lock(&block->reader_lock)) {
cl_unlock(&block->writer_lock);
return false;
}
if (!discard_data &&
(block->bytes_read != cl_block_get_bytes_committed(block))) {
cl_unlock(&block->reader_lock);
cl_unlock(&block->writer_lock);
return false;
}
cl_block_set_bytes_committed(block, 0);
block->bytes_read = 0;
return true;
}
static void cl_block_enable_access(cl_block* block) {
cl_unlock(&block->reader_lock);
cl_unlock(&block->writer_lock);
}
// Returns with writer_lock held.
static void* cl_block_start_write(cl_block* block, size_t size) {
if (!cl_try_lock(&block->writer_lock)) {
return NULL;
}
size_t bytes_committed = cl_block_get_bytes_committed(block);
if (bytes_committed + size > CENSUS_LOG_MAX_RECORD_SIZE) {
cl_unlock(&block->writer_lock);
return NULL;
}
return block->buffer + bytes_committed;
}
// Releases writer_lock and increments committed bytes by 'bytes_written'.
// 'bytes_written' must be <= 'size' specified in the corresponding
// StartWrite() call. This function is thread-safe.
static void cl_block_end_write(cl_block* block, size_t bytes_written) {
cl_block_set_bytes_committed(
block, cl_block_get_bytes_committed(block) + bytes_written);
cl_unlock(&block->writer_lock);
}
// Returns a pointer to the first unread byte in buffer. The number of bytes
// available are returned in 'bytes_available'. Acquires reader lock that is
// released by a subsequent cl_block_end_read() call. Returns NULL if:
// - read in progress
// - no data available
static void* cl_block_start_read(cl_block* block, size_t* bytes_available) {
if (!cl_try_lock(&block->reader_lock)) {
return NULL;
}
// bytes_committed may change from under us. Use bytes_available to update
// bytes_read below.
size_t bytes_committed = cl_block_get_bytes_committed(block);
GPR_ASSERT(bytes_committed >= block->bytes_read);
*bytes_available = bytes_committed - block->bytes_read;
if (*bytes_available == 0) {
cl_unlock(&block->reader_lock);
return NULL;
}
void* record = block->buffer + block->bytes_read;
block->bytes_read += *bytes_available;
return record;
}
static void cl_block_end_read(cl_block* block) {
cl_unlock(&block->reader_lock);
}
// Internal functions operating on g_log
// Allocates a new free block (or recycles an available dirty block if log is
// configured to discard old records). Returns NULL if out-of-space.
static cl_block* cl_allocate_block(void) {
cl_block* block = cl_block_list_head(&g_log.free_block_list);
if (block != NULL) {
cl_block_list_remove(&g_log.free_block_list, block);
return block;
}
if (!g_log.discard_old_records) {
// No free block and log is configured to keep old records.
return NULL;
}
// Recycle dirty block. Start from the oldest.
for (block = cl_block_list_head(&g_log.dirty_block_list); block != NULL;
block = block->link.next->block) {
if (cl_block_try_disable_access(block, 1 /* discard data */)) {
cl_block_list_remove(&g_log.dirty_block_list, block);
return block;
}
}
return NULL;
}
// Allocates a new block and updates core id => block mapping. 'old_block'
// points to the block that the caller thinks is attached to
// 'core_id'. 'old_block' may be NULL. Returns true if:
// - allocated a new block OR
// - 'core_id' => 'old_block' mapping changed (another thread allocated a
// block before lock was acquired).
static bool cl_allocate_core_local_block(uint32_t core_id,
cl_block* old_block) {
// Now that we have the lock, check if core-local mapping has changed.
cl_core_local_block* core_local_block = &g_log.core_local_blocks[core_id];
cl_block* block = cl_core_local_block_get_block(core_local_block);
if ((block != NULL) && (block != old_block)) {
return true;
}
if (block != NULL) {
cl_core_local_block_set_block(core_local_block, NULL);
cl_block_list_insert_at_tail(&g_log.dirty_block_list, block);
}
block = cl_allocate_block();
if (block == NULL) {
return false;
}
cl_core_local_block_set_block(core_local_block, block);
cl_block_enable_access(block);
return true;
}
static cl_block* cl_get_block(void* record) {
uintptr_t p = (uintptr_t)((char*)record - g_log.buffer);
uintptr_t index = p >> CENSUS_LOG_2_MAX_RECORD_SIZE;
return &g_log.blocks[index];
}
// Gets the next block to read and tries to free 'prev' block (if not NULL).
// Returns NULL if reached the end.
static cl_block* cl_next_block_to_read(cl_block* prev) {
cl_block* block = NULL;
if (g_log.read_iterator_state == g_log.num_cores) {
// We are traversing dirty list; find the next dirty block.
if (prev != NULL) {
// Try to free the previous block if there is no unread data. This
// block
// may have unread data if previously incomplete record completed
// between
// read_next() calls.
block = prev->link.next->block;
if (cl_block_try_disable_access(prev, 0 /* do not discard data */)) {
cl_block_list_remove(&g_log.dirty_block_list, prev);
cl_block_list_insert_at_head(&g_log.free_block_list, prev);
}
} else {
block = cl_block_list_head(&g_log.dirty_block_list);
}
if (block != NULL) {
return block;
}
// We are done with the dirty list; moving on to core-local blocks.
}
while (g_log.read_iterator_state > 0) {
g_log.read_iterator_state--;
block = cl_core_local_block_get_block(
&g_log.core_local_blocks[g_log.read_iterator_state]);
if (block != NULL) {
return block;
}
}
return NULL;
}
#define CL_LOG_2_MB 20 // 2^20 = 1MB
// External functions: primary stats_log interface
void census_log_initialize(size_t size_in_mb, int discard_old_records) {
// Check cacheline alignment.
GPR_ASSERT(sizeof(cl_block) % GPR_CACHELINE_SIZE == 0);
GPR_ASSERT(sizeof(cl_core_local_block) % GPR_CACHELINE_SIZE == 0);
GPR_ASSERT(!g_log.initialized);
g_log.discard_old_records = discard_old_records;
g_log.num_cores = gpr_cpu_num_cores();
// Ensure that we will not get any overflow in calaculating num_blocks
GPR_ASSERT(CL_LOG_2_MB >= CENSUS_LOG_2_MAX_RECORD_SIZE);
GPR_ASSERT(size_in_mb < 1000);
// Ensure at least 2x as many blocks as there are cores.
g_log.num_blocks =
(uint32_t)GPR_MAX(2 * g_log.num_cores, (size_in_mb << CL_LOG_2_MB) >>
CENSUS_LOG_2_MAX_RECORD_SIZE);
gpr_mu_init(&g_log.lock);
g_log.read_iterator_state = 0;
g_log.block_being_read = NULL;
g_log.core_local_blocks = (cl_core_local_block*)gpr_malloc_aligned(
g_log.num_cores * sizeof(cl_core_local_block), GPR_CACHELINE_SIZE_LOG);
memset(g_log.core_local_blocks, 0,
g_log.num_cores * sizeof(cl_core_local_block));
g_log.blocks = (cl_block*)gpr_malloc_aligned(
g_log.num_blocks * sizeof(cl_block), GPR_CACHELINE_SIZE_LOG);
memset(g_log.blocks, 0, g_log.num_blocks * sizeof(cl_block));
g_log.buffer = gpr_malloc(g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
memset(g_log.buffer, 0, g_log.num_blocks * CENSUS_LOG_MAX_RECORD_SIZE);
cl_block_list_initialize(&g_log.free_block_list);
cl_block_list_initialize(&g_log.dirty_block_list);
for (uint32_t i = 0; i < g_log.num_blocks; ++i) {
cl_block* block = g_log.blocks + i;
cl_block_initialize(block, g_log.buffer + (CENSUS_LOG_MAX_RECORD_SIZE * i));
cl_block_try_disable_access(block, 1 /* discard data */);
cl_block_list_insert_at_tail(&g_log.free_block_list, block);
}
gpr_atm_rel_store(&g_log.out_of_space_count, 0);
g_log.initialized = 1;
}
void census_log_shutdown(void) {
GPR_ASSERT(g_log.initialized);
gpr_mu_destroy(&g_log.lock);
gpr_free_aligned(g_log.core_local_blocks);
g_log.core_local_blocks = NULL;
gpr_free_aligned(g_log.blocks);
g_log.blocks = NULL;
gpr_free(g_log.buffer);
g_log.buffer = NULL;
g_log.initialized = 0;
}
void* census_log_start_write(size_t size) {
// Used to bound number of times block allocation is attempted.
GPR_ASSERT(size > 0);
GPR_ASSERT(g_log.initialized);
if (size > CENSUS_LOG_MAX_RECORD_SIZE) {
return NULL;
}
uint32_t attempts_remaining = g_log.num_blocks;
uint32_t core_id = gpr_cpu_current_cpu();
do {
void* record = NULL;
cl_block* block =
cl_core_local_block_get_block(&g_log.core_local_blocks[core_id]);
if (block && (record = cl_block_start_write(block, size))) {
return record;
}
// Need to allocate a new block. We are here if:
// - No block associated with the core OR
// - Write in-progress on the block OR
// - block is out of space
gpr_mu_lock(&g_log.lock);
bool allocated = cl_allocate_core_local_block(core_id, block);
gpr_mu_unlock(&g_log.lock);
if (!allocated) {
gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
return NULL;
}
} while (attempts_remaining--);
// Give up.
gpr_atm_no_barrier_fetch_add(&g_log.out_of_space_count, 1);
return NULL;
}
void census_log_end_write(void* record, size_t bytes_written) {
GPR_ASSERT(g_log.initialized);
cl_block_end_write(cl_get_block(record), bytes_written);
}
void census_log_init_reader(void) {
GPR_ASSERT(g_log.initialized);
gpr_mu_lock(&g_log.lock);
// If a block is locked for reading unlock it.
if (g_log.block_being_read != NULL) {
cl_block_end_read(g_log.block_being_read);
g_log.block_being_read = NULL;
}
g_log.read_iterator_state = g_log.num_cores;
gpr_mu_unlock(&g_log.lock);
}
const void* census_log_read_next(size_t* bytes_available) {
GPR_ASSERT(g_log.initialized);
gpr_mu_lock(&g_log.lock);
if (g_log.block_being_read != NULL) {
cl_block_end_read(g_log.block_being_read);
}
do {
g_log.block_being_read = cl_next_block_to_read(g_log.block_being_read);
if (g_log.block_being_read != NULL) {
void* record =
cl_block_start_read(g_log.block_being_read, bytes_available);
if (record != NULL) {
gpr_mu_unlock(&g_log.lock);
return record;
}
}
} while (g_log.block_being_read != NULL);
gpr_mu_unlock(&g_log.lock);
return NULL;
}
size_t census_log_remaining_space(void) {
GPR_ASSERT(g_log.initialized);
size_t space = 0;
gpr_mu_lock(&g_log.lock);
if (g_log.discard_old_records) {
// Remaining space is not meaningful; just return the entire log space.
space = g_log.num_blocks << CENSUS_LOG_2_MAX_RECORD_SIZE;
} else {
GPR_ASSERT(g_log.free_block_list.count >= 0);
space = (size_t)g_log.free_block_list.count * CENSUS_LOG_MAX_RECORD_SIZE;
}
gpr_mu_unlock(&g_log.lock);
return space;
}
int64_t census_log_out_of_space_count(void) {
GPR_ASSERT(g_log.initialized);
return gpr_atm_acq_load(&g_log.out_of_space_count);
}

@ -0,0 +1,93 @@
/*
*
* Copyright 2015-2016, 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 GRPC_INTERNAL_CORE_CENSUS_LOG_H
#define GRPC_INTERNAL_CORE_CENSUS_LOG_H
#include <grpc/support/port_platform.h>
#include <stddef.h>
/* Maximum record size, in bytes. */
#define CENSUS_LOG_2_MAX_RECORD_SIZE 14 /* 2^14 = 16KB */
#define CENSUS_LOG_MAX_RECORD_SIZE (1 << CENSUS_LOG_2_MAX_RECORD_SIZE)
/* Initialize the statistics logging subsystem with the given log size. A log
size of 0 will result in the smallest possible log for the platform
(approximately CENSUS_LOG_MAX_RECORD_SIZE * gpr_cpu_num_cores()). If
discard_old_records is non-zero, then new records will displace older ones
when the log is full. This function must be called before any other
census_log functions.
*/
void census_log_initialize(size_t size_in_mb, int discard_old_records);
/* Shutdown the logging subsystem. Caller must ensure that:
- no in progress or future call to any census_log functions
- no incomplete records
*/
void census_log_shutdown(void);
/* Allocates and returns a 'size' bytes record and marks it in use. A
subsequent census_log_end_write() marks the record complete. The
'bytes_written' census_log_end_write() argument must be <=
'size'. Returns NULL if out-of-space AND:
- log is configured to keep old records OR
- all blocks are pinned by incomplete records.
*/
void* census_log_start_write(size_t size);
void census_log_end_write(void* record, size_t bytes_written);
void census_log_init_reader(void);
/* census_log_read_next() iterates over blocks with data and for each block
returns a pointer to the first unread byte. The number of bytes that can be
read are returned in 'bytes_available'. Reader is expected to read all
available data. Reading the data consumes it i.e. it cannot be read again.
census_log_read_next() returns NULL if the end is reached i.e last block
is read. census_log_init_reader() starts the iteration or aborts the
current iteration.
*/
const void* census_log_read_next(size_t* bytes_available);
/* Returns estimated remaining space across all blocks, in bytes. If log is
configured to discard old records, returns total log space. Otherwise,
returns space available in empty blocks (partially filled blocks are
treated as full).
*/
size_t census_log_remaining_space(void);
/* Returns the number of times gprc_stats_log_start_write() failed due to
out-of-space. */
int64_t census_log_out_of_space_count(void);
#endif /* GRPC_INTERNAL_CORE_CENSUS_LOG_H */

@ -129,9 +129,9 @@ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array) {
zend_throw_exception(zend_exception_get_default(),
"Metadata hash somehow contains wrong types.",
1 TSRMLS_CC);
efree(str_key);
efree(str_val);
return NULL;
efree(str_key);
efree(str_val);
return NULL;
}
add_next_index_stringl(*data, str_val, elem->value_length, false);
} else {

@ -141,44 +141,40 @@ PHP_METHOD(Channel, __construct) {
HashTable *array_hash;
zval **creds_obj = NULL;
wrapped_grpc_channel_credentials *creds = NULL;
/* "s|a" == 1 string, 1 optional array */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a", &target,
/* "sa" == 1 string, 1 array */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &target,
&target_length, &args_array) == FAILURE) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"Channel expects a string and an array", 1 TSRMLS_CC);
return;
}
if (args_array == NULL) {
channel->wrapped = grpc_insecure_channel_create(target, NULL, NULL);
} else {
array_hash = Z_ARRVAL_P(args_array);
if (zend_hash_find(array_hash, "credentials", sizeof("credentials"),
(void **)&creds_obj) == SUCCESS) {
if (Z_TYPE_P(*creds_obj) == IS_NULL) {
creds = NULL;
zend_hash_del(array_hash, "credentials", 12);
} else if (zend_get_class_entry(*creds_obj TSRMLS_CC) !=
grpc_ce_channel_credentials) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"credentials must be a ChannelCredentials object",
1 TSRMLS_CC);
return;
} else {
creds = (wrapped_grpc_channel_credentials *)zend_object_store_get_object(
*creds_obj TSRMLS_CC);
zend_hash_del(array_hash, "credentials", 12);
}
}
php_grpc_read_args_array(args_array, &args);
if (creds == NULL) {
channel->wrapped = grpc_insecure_channel_create(target, &args, NULL);
array_hash = Z_ARRVAL_P(args_array);
if (zend_hash_find(array_hash, "credentials", sizeof("credentials"),
(void **)&creds_obj) == SUCCESS) {
if (Z_TYPE_P(*creds_obj) == IS_NULL) {
creds = NULL;
zend_hash_del(array_hash, "credentials", 12);
} else if (zend_get_class_entry(*creds_obj TSRMLS_CC) !=
grpc_ce_channel_credentials) {
zend_throw_exception(spl_ce_InvalidArgumentException,
"credentials must be a ChannelCredentials object",
1 TSRMLS_CC);
return;
} else {
gpr_log(GPR_DEBUG, "Initialized secure channel");
channel->wrapped =
grpc_secure_channel_create(creds->wrapped, target, &args, NULL);
creds = (wrapped_grpc_channel_credentials *)zend_object_store_get_object(
*creds_obj TSRMLS_CC);
zend_hash_del(array_hash, "credentials", 12);
}
efree(args.args);
}
php_grpc_read_args_array(args_array, &args);
if (creds == NULL) {
channel->wrapped = grpc_insecure_channel_create(target, &args, NULL);
} else {
gpr_log(GPR_DEBUG, "Initialized secure channel");
channel->wrapped =
grpc_secure_channel_create(creds->wrapped, target, &args, NULL);
}
efree(args.args);
}
/**

@ -106,6 +106,34 @@ abstract class AbstractGeneratedCodeTest extends PHPUnit_Framework_TestCase
$this->assertSame(\Grpc\STATUS_CANCELLED, $status->code);
}
public function testCallCredentialsCallback()
{
$div_arg = new math\DivArgs();
$call = self::$client->Div($div_arg, array(), array(
'call_credentials_callback' => function ($context) {
return array();
},
));
$call->cancel();
list($response, $status) = $call->wait();
$this->assertSame(\Grpc\STATUS_CANCELLED, $status->code);
}
public function testCallCredentialsCallback2()
{
$div_arg = new math\DivArgs();
$call = self::$client->Div($div_arg);
$call_credentials = Grpc\CallCredentials::createFromPlugin(
function ($context) {
return array();
}
);
$call->setCallCredentials($call_credentials);
$call->cancel();
list($response, $status) = $call->wait();
$this->assertSame(\Grpc\STATUS_CANCELLED, $status->code);
}
/**
* @expectedException InvalidArgumentException
*/
@ -118,6 +146,23 @@ abstract class AbstractGeneratedCodeTest extends PHPUnit_Framework_TestCase
$invalid_client->InvalidUnaryCall($div_arg);
}
/**
* @expectedException Exception
*/
public function testMissingCredentials()
{
$invalid_client = new DummyInvalidClient('host', [
]);
}
public function testPrimaryUserAgentString()
{
$invalid_client = new DummyInvalidClient('host', [
'credentials' => Grpc\ChannelCredentials::createInsecure(),
'grpc.primary_user_agent' => 'testUserAgent',
]);
}
public function testWriteFlags()
{
$div_arg = new math\DivArgs();

@ -0,0 +1,135 @@
<?php
/*
*
* 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.
*
*/
class CallCredentials2Test extends PHPUnit_Framework_TestCase
{
public function setUp()
{
$credentials = Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
$server_credentials = Grpc\ServerCredentials::createSsl(
null,
file_get_contents(dirname(__FILE__).'/../data/server1.key'),
file_get_contents(dirname(__FILE__).'/../data/server1.pem'));
$this->server = new Grpc\Server();
$this->port = $this->server->addSecureHttp2Port('0.0.0.0:0',
$server_credentials);
$this->server->start();
$this->host_override = 'foo.test.google.fr';
$this->channel = new Grpc\Channel(
'localhost:'.$this->port,
[
'grpc.ssl_target_name_override' => $this->host_override,
'grpc.default_authority' => $this->host_override,
'credentials' => $credentials,
]
);
}
public function tearDown()
{
unset($this->channel);
unset($this->server);
}
public function callbackFunc($context)
{
$this->assertTrue(is_string($context->service_url));
$this->assertTrue(is_string($context->method_name));
return ['k1' => ['v1'], 'k2' => ['v2']];
}
public function testCreateFromPlugin()
{
$deadline = Grpc\Timeval::infFuture();
$status_text = 'xyz';
$call = new Grpc\Call($this->channel,
'/abc/dummy_method',
$deadline,
$this->host_override);
$call_credentials = Grpc\CallCredentials::createFromPlugin(
array($this, 'callbackFunc'));
$call->setCredentials($call_credentials);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
]);
$this->assertTrue($event->send_metadata);
$this->assertTrue($event->send_close);
$event = $this->server->requestCall();
$this->assertTrue(is_array($event->metadata));
$metadata = $event->metadata;
$this->assertTrue(array_key_exists('k1', $metadata));
$this->assertTrue(array_key_exists('k2', $metadata));
$this->assertSame($metadata['k1'], ['v1']);
$this->assertSame($metadata['k2'], ['v2']);
$this->assertSame('/abc/dummy_method', $event->method);
$server_call = $event->call;
$event = $server_call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_STATUS_FROM_SERVER => [
'metadata' => [],
'code' => Grpc\STATUS_OK,
'details' => $status_text,
],
Grpc\OP_RECV_CLOSE_ON_SERVER => true,
]);
$this->assertTrue($event->send_metadata);
$this->assertTrue($event->send_status);
$this->assertFalse($event->cancelled);
$event = $call->startBatch([
Grpc\OP_RECV_INITIAL_METADATA => true,
Grpc\OP_RECV_STATUS_ON_CLIENT => true,
]);
$this->assertSame([], $event->metadata);
$status = $event->status;
$this->assertSame([], $status->metadata);
$this->assertSame(Grpc\STATUS_OK, $status->code);
$this->assertSame($status_text, $status->details);
unset($call);
unset($server_call);
}
}

@ -0,0 +1,136 @@
<?php
/*
*
* 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.
*
*/
class CallCredentials3Test extends PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->credentials = Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
$server_credentials = Grpc\ServerCredentials::createSsl(
null,
file_get_contents(dirname(__FILE__).'/../data/server1.key'),
file_get_contents(dirname(__FILE__).'/../data/server1.pem'));
$this->server = new Grpc\Server();
$this->port = $this->server->addSecureHttp2Port('0.0.0.0:0',
$server_credentials);
$this->server->start();
$this->host_override = 'foo.test.google.fr';
$this->channel = new Grpc\Channel(
'localhost:'.$this->port,
[
'grpc.ssl_target_name_override' => $this->host_override,
'grpc.default_authority' => $this->host_override,
'credentials' => $this->credentials,
]
);
}
public function tearDown()
{
unset($this->channel);
unset($this->server);
}
public function callbackFunc($context)
{
$this->assertTrue(is_string($context->service_url));
$this->assertTrue(is_string($context->method_name));
return ['k1' => ['v1'], 'k2' => ['v2']];
}
public function testCreateFromPlugin()
{
$deadline = Grpc\Timeval::infFuture();
$status_text = 'xyz';
$call = new Grpc\Call($this->channel,
'/abc/dummy_method',
$deadline,
$this->host_override);
$call_credentials = Grpc\CallCredentials::createFromPlugin(
[$this, 'callbackFunc']);
$call->setCredentials($call_credentials);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
]);
$this->assertTrue($event->send_metadata);
$this->assertTrue($event->send_close);
$event = $this->server->requestCall();
$this->assertTrue(is_array($event->metadata));
$metadata = $event->metadata;
$this->assertTrue(array_key_exists('k1', $metadata));
$this->assertTrue(array_key_exists('k2', $metadata));
$this->assertSame($metadata['k1'], ['v1']);
$this->assertSame($metadata['k2'], ['v2']);
$this->assertSame('/abc/dummy_method', $event->method);
$server_call = $event->call;
$event = $server_call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_STATUS_FROM_SERVER => [
'metadata' => [],
'code' => Grpc\STATUS_OK,
'details' => $status_text,
],
Grpc\OP_RECV_CLOSE_ON_SERVER => true,
]);
$this->assertTrue($event->send_metadata);
$this->assertTrue($event->send_status);
$this->assertFalse($event->cancelled);
$event = $call->startBatch([
Grpc\OP_RECV_INITIAL_METADATA => true,
Grpc\OP_RECV_STATUS_ON_CLIENT => true,
]);
$this->assertSame([], $event->metadata);
$status = $event->status;
$this->assertSame([], $status->metadata);
$this->assertSame(Grpc\STATUS_OK, $status->code);
$this->assertSame($status_text, $status->details);
unset($call);
unset($server_call);
}
}

@ -36,13 +36,13 @@ class CallCredentialsTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
$credentials = Grpc\ChannelCredentials::createSsl(
$this->credentials = Grpc\ChannelCredentials::createSsl(
file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
$call_credentials = Grpc\CallCredentials::createFromPlugin(
array($this, 'callbackFunc'));
$credentials = Grpc\ChannelCredentials::createComposite(
$credentials,
$call_credentials
$this->call_credentials = Grpc\CallCredentials::createFromPlugin(
[$this, 'callbackFunc']);
$this->credentials = Grpc\ChannelCredentials::createComposite(
$this->credentials,
$this->call_credentials
);
$server_credentials = Grpc\ServerCredentials::createSsl(
null,
@ -58,7 +58,7 @@ class CallCredentialsTest extends PHPUnit_Framework_TestCase
[
'grpc.ssl_target_name_override' => $this->host_override,
'grpc.default_authority' => $this->host_override,
'credentials' => $credentials,
'credentials' => $this->credentials,
]
);
}
@ -134,4 +134,41 @@ class CallCredentialsTest extends PHPUnit_Framework_TestCase
unset($call);
unset($server_call);
}
public function callbackFunc2($context)
{
return [];
}
public function testCreateComposite()
{
$call_credentials2 = Grpc\CallCredentials::createFromPlugin(
[$this, 'callbackFunc2']);
$call_credentials3 = Grpc\CallCredentials::createComposite(
$this->call_credentials,
$call_credentials2
);
$this->assertSame('Grpc\CallCredentials', get_class($call_credentials3));
}
/**
* @expectedException InvalidArgumentException
*/
public function testCreateFromPluginInvalidParam()
{
$call_credentials = Grpc\CallCredentials::createFromPlugin(
'callbackFunc'
);
}
/**
* @expectedException InvalidArgumentException
*/
public function testCreateCompositeInvalidParam()
{
$call_credentials3 = Grpc\CallCredentials::createComposite(
$this->call_credentials,
$this->credentials
);
}
}

@ -91,4 +91,32 @@ class CallTest extends PHPUnit_Framework_TestCase
{
$this->assertTrue(is_string($this->call->getPeer()));
}
public function testCancel()
{
$this->assertNull($this->call->cancel());
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidMetadataKey()
{
$batch = [
'invalid' => ['key1' => 'value1'],
];
$result = $this->call->startBatch($batch);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidMetadataInnerValue()
{
$batch = [
Grpc\OP_SEND_INITIAL_METADATA => ['key1' => 'value1'],
];
$result = $this->call->startBatch($batch);
}
}

@ -0,0 +1,73 @@
<?php
/*
*
* 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.
*
*/
class ChanellCredentialsTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
}
public function tearDown()
{
}
public function testCreateDefault()
{
$channel_credentials = Grpc\ChannelCredentials::createDefault();
$this->assertSame('Grpc\ChannelCredentials', get_class($channel_credentials));
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidCreateSsl()
{
$channel_credentials = Grpc\ChannelCredentials::createSsl([]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidCreateComposite()
{
$channel_credentials = Grpc\ChannelCredentials::createComposite(
'something', 'something');
}
public function testCreateInsecure()
{
$channel_credentials = Grpc\ChannelCredentials::createInsecure();
$this->assertNull($channel_credentials);
}
}

@ -0,0 +1,82 @@
<?php
/*
*
* 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.
*
*/
class ChannelTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
}
public function tearDown()
{
}
public function testInsecureCredentials()
{
$this->channel = new Grpc\Channel(
'localhost:0',
[
'credentials' => Grpc\ChannelCredentials::createInsecure(),
]
);
$this->assertSame('Grpc\Channel', get_class($this->channel));
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidCredentials()
{
$this->channel = new Grpc\Channel(
'localhost:0',
[
'credentials' => new Grpc\Timeval(100),
]
);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidOptionsArray()
{
$this->channel = new Grpc\Channel(
'localhost:0',
[
'abc' => [],
]
);
}
}

@ -201,6 +201,318 @@ class EndToEndTest extends PHPUnit_Framework_TestCase
unset($server_call);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidClientMessageArray()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
Grpc\OP_SEND_MESSAGE => 'invalid',
]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidClientMessageString()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
Grpc\OP_SEND_MESSAGE => ['message' => 0],
]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidClientMessageFlags()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
Grpc\OP_SEND_MESSAGE => ['message' => 'abc',
'flags' => 'invalid'],
]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidServerStatusMetadata()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
]);
$this->assertTrue($event->send_metadata);
$this->assertTrue($event->send_close);
$this->assertTrue($event->send_message);
$event = $this->server->requestCall();
$this->assertSame('dummy_method', $event->method);
$server_call = $event->call;
$event = $server_call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
Grpc\OP_SEND_STATUS_FROM_SERVER => [
'metadata' => 'invalid',
'code' => Grpc\STATUS_OK,
'details' => $status_text,
],
Grpc\OP_RECV_MESSAGE => true,
Grpc\OP_RECV_CLOSE_ON_SERVER => true,
]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidServerStatusCode()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
]);
$this->assertTrue($event->send_metadata);
$this->assertTrue($event->send_close);
$this->assertTrue($event->send_message);
$event = $this->server->requestCall();
$this->assertSame('dummy_method', $event->method);
$server_call = $event->call;
$event = $server_call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
Grpc\OP_SEND_STATUS_FROM_SERVER => [
'metadata' => [],
'code' => 'invalid',
'details' => $status_text,
],
Grpc\OP_RECV_MESSAGE => true,
Grpc\OP_RECV_CLOSE_ON_SERVER => true,
]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testMissingServerStatusCode()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
]);
$this->assertTrue($event->send_metadata);
$this->assertTrue($event->send_close);
$this->assertTrue($event->send_message);
$event = $this->server->requestCall();
$this->assertSame('dummy_method', $event->method);
$server_call = $event->call;
$event = $server_call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
Grpc\OP_SEND_STATUS_FROM_SERVER => [
'metadata' => [],
'details' => $status_text,
],
Grpc\OP_RECV_MESSAGE => true,
Grpc\OP_RECV_CLOSE_ON_SERVER => true,
]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidServerStatusDetails()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
]);
$this->assertTrue($event->send_metadata);
$this->assertTrue($event->send_close);
$this->assertTrue($event->send_message);
$event = $this->server->requestCall();
$this->assertSame('dummy_method', $event->method);
$server_call = $event->call;
$event = $server_call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
Grpc\OP_SEND_STATUS_FROM_SERVER => [
'metadata' => [],
'code' => Grpc\STATUS_OK,
'details' => 0,
],
Grpc\OP_RECV_MESSAGE => true,
Grpc\OP_RECV_CLOSE_ON_SERVER => true,
]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testMissingServerStatusDetails()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
]);
$this->assertTrue($event->send_metadata);
$this->assertTrue($event->send_close);
$this->assertTrue($event->send_message);
$event = $this->server->requestCall();
$this->assertSame('dummy_method', $event->method);
$server_call = $event->call;
$event = $server_call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_MESSAGE => ['message' => $reply_text],
Grpc\OP_SEND_STATUS_FROM_SERVER => [
'metadata' => [],
'code' => Grpc\STATUS_OK,
],
Grpc\OP_RECV_MESSAGE => true,
Grpc\OP_RECV_CLOSE_ON_SERVER => true,
]);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidStartBatchKey()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
9999999 => [],
]);
}
/**
* @expectedException LogicException
*/
public function testInvalidStartBatch()
{
$deadline = Grpc\Timeval::infFuture();
$req_text = 'client_server_full_request_response';
$reply_text = 'reply:client_server_full_request_response';
$status_text = 'status:client_server_full_response_text';
$call = new Grpc\Call($this->channel,
'dummy_method',
$deadline);
$event = $call->startBatch([
Grpc\OP_SEND_INITIAL_METADATA => [],
Grpc\OP_SEND_CLOSE_FROM_CLIENT => true,
Grpc\OP_SEND_MESSAGE => ['message' => $req_text],
Grpc\OP_SEND_STATUS_FROM_SERVER => [
'metadata' => [],
'code' => Grpc\STATUS_OK,
'details' => 'abc',
],
]);
}
public function testGetTarget()
{
$this->assertTrue(is_string($this->channel->getTarget()));
@ -255,4 +567,36 @@ class EndToEndTest extends PHPUnit_Framework_TestCase
$new_state = $this->channel->getConnectivityState();
$this->assertTrue($new_state == Grpc\CHANNEL_IDLE);
}
/**
* @expectedException InvalidArgumentException
*/
public function testGetConnectivityStateInvalidParam()
{
$this->assertTrue($this->channel->getConnectivityState(
new Grpc\Timeval));
}
/**
* @expectedException InvalidArgumentException
*/
public function testWatchConnectivityStateInvalidParam()
{
$this->assertTrue($this->channel->watchConnectivityState(
0, 1000));
}
/**
* @expectedException InvalidArgumentException
*/
public function testChannelConstructorInvalidParam()
{
$this->channel = new Grpc\Channel('localhost:'.$this->port, NULL);
}
public function testClose()
{
$this->assertNull($this->channel->close());
}
}

@ -0,0 +1,71 @@
<?php
/*
*
* 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.
*
*/
class ServerTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
}
public function tearDown()
{
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidConstructor()
{
$server = new Grpc\Server('invalid_host');
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidAddHttp2Port()
{
$this->server = new Grpc\Server([]);
$this->port = $this->server->addHttp2Port(['0.0.0.0:0']);
}
/**
* @expectedException InvalidArgumentException
*/
public function testInvalidAddSecureHttp2Port()
{
$this->server = new Grpc\Server([]);
$this->port = $this->server->addSecureHttp2Port(['0.0.0.0:0']);
}
}

@ -91,4 +91,69 @@ class TimevalTest extends PHPUnit_Framework_TestCase
$back_to_now = $deadline->subtract($delta);
$this->assertSame(0, Grpc\Timeval::compare($back_to_now, $now));
}
public function testSimilar()
{
$a = Grpc\Timeval::now();
$delta = new Grpc\Timeval(1000);
$b = $a->add($delta);
$thresh = new Grpc\Timeval(1100);
$this->assertTrue(Grpc\Timeval::similar($a, $b, $thresh));
$thresh = new Grpc\Timeval(900);
$this->assertFalse(Grpc\Timeval::similar($a, $b, $thresh));
}
public function testSleepUntil()
{
$curr_microtime = microtime(true);
$now = Grpc\Timeval::now();
$delta = new Grpc\Timeval(1000);
$deadline = $now->add($delta);
$deadline->sleepUntil();
$done_microtime = microtime(true);
$this->assertTrue(($done_microtime - $curr_microtime) > 0.0009);
}
/**
* @expectedException InvalidArgumentException
*/
public function testConstructorInvalidParam()
{
$delta = new Grpc\Timeval('abc');
}
/**
* @expectedException InvalidArgumentException
*/
public function testAddInvalidParam()
{
$a = Grpc\Timeval::now();
$a->add(1000);
}
/**
* @expectedException InvalidArgumentException
*/
public function testSubtractInvalidParam()
{
$a = Grpc\Timeval::now();
$a->subtract(1000);
}
/**
* @expectedException InvalidArgumentException
*/
public function testCompareInvalidParam()
{
$a = Grpc\Timeval::compare(1000, 1100);
}
/**
* @expectedException InvalidArgumentException
*/
public function testSimilarInvalidParam()
{
$a = Grpc\Timeval::similar(1000, 1100, 1200);
}
}

@ -1,22 +1,40 @@
gRPC Python
===========
Package for GRPC Python.
Package for gRPC Python.
Dependencies
Installation
------------
Ensure you have installed the gRPC core. On Mac OS X, install homebrew_.
Run the following command to install gRPC Python.
gRPC Python is available for Linux and Mac OS X running Python 2.7.
From PyPI
~~~~~~~~~
If you are installing locally...
::
$ curl -fsSL https://goo.gl/getgrpc | bash -s python
$ pip install grpcio
Else system wide (on Ubuntu)...
::
This will download and run the [gRPC install script][] to install grpc core. The script then uses pip to install this package. It also installs the Protocol Buffers compiler (_protoc_) and the gRPC _protoc_ plugin for python.
$ sudo pip install grpcio
From Source
~~~~~~~~~~~
Building from source requires that you have the Python headers (usually a
package named `python-dev`).
::
Otherwise, `install from source`_
$ export REPO_ROOT=grpc
$ git clone https://github.com/grpc/grpc.git $REPO_ROOT
$ cd $REPO_ROOT
$ pip install .
.. _`install from source`: https://github.com/grpc/grpc/blob/master/src/python/README.md#building-from-source
.. _homebrew: http://brew.sh
.. _`gRPC install script`: https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
Note that `$REPO_ROOT` can be assigned to whatever directory name floats your
fancy.

@ -41,7 +41,6 @@ import sys
import traceback
import setuptools
from setuptools.command import bdist_egg
from setuptools.command import build_ext
from setuptools.command import build_py
from setuptools.command import easy_install
@ -52,13 +51,6 @@ import support
PYTHON_STEM = os.path.dirname(os.path.abspath(__file__))
BINARIES_REPOSITORY = os.environ.get(
'GRPC_PYTHON_BINARIES_REPOSITORY',
'https://storage.googleapis.com/grpc-precompiled-binaries/python')
USE_GRPC_CUSTOM_BDIST = bool(int(os.environ.get(
'GRPC_PYTHON_USE_CUSTOM_BDIST', '1')))
CONF_PY_ADDENDUM = """
extensions.append('sphinx.ext.napoleon')
napoleon_google_docstring = True
@ -74,126 +66,39 @@ class CommandError(Exception):
# TODO(atash): Remove this once PyPI has better Linux bdist support. See
# https://bitbucket.org/pypa/pypi/issues/120/binary-wheels-for-linux-are-not-supported
def _get_grpc_custom_bdist_egg(decorated_basename, target_egg_basename):
"""Returns a string path to a .egg file for Linux to install.
def _get_grpc_custom_bdist(decorated_basename, target_bdist_basename):
"""Returns a string path to a bdist file for Linux to install.
If we can retrieve a pre-compiled egg from online, uses it. Else, emits a
If we can retrieve a pre-compiled bdist from online, uses it. Else, emits a
warning and builds from source.
"""
# TODO(atash): somehow the name that's returned from `wheel` is different
# between different versions of 'wheel' (but from a compatibility standpoint,
# the names are compatible); we should have some way of determining name
# compatibility in the same way `wheel` does to avoid having to rename all of
# the custom wheels that we build/upload to GCS.
# Break import style to ensure that setup.py has had a chance to install the
# relevant package eggs.
# relevant package.
from six.moves.urllib import request
decorated_path = decorated_basename + '.egg'
decorated_path = decorated_basename + GRPC_CUSTOM_BDIST_EXT
try:
url = BINARIES_REPOSITORY + '/{target}'.format(target=decorated_path)
egg_data = request.urlopen(url).read()
bdist_data = request.urlopen(url).read()
except IOError as error:
raise CommandError(
'{}\n\nCould not find the bdist egg {}: {}'
'{}\n\nCould not find the bdist {}: {}'
.format(traceback.format_exc(), decorated_path, error.message))
# Our chosen local egg path.
egg_path = target_egg_basename + '.egg'
# Our chosen local bdist path.
bdist_path = target_bdist_basename + GRPC_CUSTOM_BDIST_EXT
try:
with open(egg_path, 'w') as egg_file:
egg_file.write(egg_data)
with open(bdist_path, 'w') as bdist_file:
bdist_file.write(bdist_data)
except IOError as error:
raise CommandError(
'{}\n\nCould not write grpcio egg: {}'
'{}\n\nCould not write grpcio bdist: {}'
.format(traceback.format_exc(), error.message))
return egg_path
class EggNameMixin(object):
"""Mixin for setuptools.Command classes to enable acquiring the egg name."""
def egg_name(self, with_custom):
"""
Args:
with_custom: Boolean describing whether or not to decorate the egg name
with custom gRPC-specific target information.
"""
egg_command = self.get_finalized_command('bdist_egg')
base = os.path.splitext(os.path.basename(egg_command.egg_output))[0]
if with_custom:
flavor = 'ucs2' if sys.maxunicode == 65535 else 'ucs4'
return '{base}-{flavor}'.format(base=base, flavor=flavor)
else:
return base
class Install(install.install, EggNameMixin):
"""Custom Install command for gRPC Python.
This is for bdist shims and whatever else we might need a custom install
command for.
"""
user_options = install.install.user_options + [
# TODO(atash): remove this once PyPI has better Linux bdist support. See
# https://bitbucket.org/pypa/pypi/issues/120/binary-wheels-for-linux-are-not-supported
('use-grpc-custom-bdist', None,
'Whether to retrieve a binary from the gRPC binary repository instead '
'of building from source.'),
]
def initialize_options(self):
install.install.initialize_options(self)
self.use_grpc_custom_bdist = USE_GRPC_CUSTOM_BDIST
def finalize_options(self):
install.install.finalize_options(self)
def run(self):
if self.use_grpc_custom_bdist:
try:
try:
egg_path = _get_grpc_custom_bdist_egg(self.egg_name(True),
self.egg_name(False))
except CommandError as error:
sys.stderr.write(
'\nWARNING: Failed to acquire grpcio prebuilt binary:\n'
'{}.\n\n'.format(error.message))
raise
try:
self._run_bdist_retrieval_install(egg_path)
except Exception as error:
# if anything else happens (and given how there's no way to really know
# what's happening in setuptools here, I mean *anything*), warn the user
# and fall back to building from source.
sys.stderr.write(
'{}\nWARNING: Failed to install grpcio prebuilt binary.\n\n'
.format(traceback.format_exc()))
raise
except Exception:
install.install.run(self)
else:
install.install.run(self)
# TODO(atash): Remove this once PyPI has better Linux bdist support. See
# https://bitbucket.org/pypa/pypi/issues/120/binary-wheels-for-linux-are-not-supported
def _run_bdist_retrieval_install(self, bdist_egg):
easy_install = self.distribution.get_command_class('easy_install')
easy_install_command = easy_install(
self.distribution, args='x', root=self.root, record=self.record,
)
easy_install_command.ensure_finalized()
easy_install_command.always_copy_from = '.'
easy_install_command.package_index.scan(glob.glob('*.egg'))
arguments = [bdist_egg]
if setuptools.bootstrap_install_from:
args.insert(0, setuptools.bootstrap_install_from)
easy_install_command.args = arguments
easy_install_command.run()
setuptools.bootstrap_install_from = None
class BdistEggCustomName(bdist_egg.bdist_egg, EggNameMixin):
"""Thin wrapper around the bdist_egg command to build with our custom name."""
def run(self):
bdist_egg.bdist_egg.run(self)
target = os.path.join(self.dist_dir, '{}.egg'.format(self.egg_name(True)))
shutil.move(self.get_outputs()[0], target)
return bdist_path
class SphinxDocumentation(setuptools.Command):

@ -223,6 +223,7 @@ CORE_SOURCE_FILES = [
'src/core/transport/transport_op_string.c',
'src/core/census/context.c',
'src/core/census/initialize.c',
'src/core/census/log.c',
'src/core/census/operation.c',
'src/core/census/placeholders.c',
'src/core/census/tracing.c',

@ -0,0 +1,102 @@
# Copyright 2015-2016, 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.
import os
import platform
import shutil
import sys
import setuptools
import commands
import grpc_version
try:
from urllib2 import urlopen
except ImportError:
from urllib.request import urlopen
PYTHON_STEM = os.path.dirname(os.path.abspath(__file__))
BINARIES_REPOSITORY = os.environ.get(
'GRPC_PYTHON_BINARIES_REPOSITORY',
'https://storage.googleapis.com/grpc-precompiled-binaries/python')
USE_PRECOMPILED_BINARIES = bool(int(os.environ.get(
'GRPC_PYTHON_USE_PRECOMPILED_BINARIES', '1')))
def _tagged_ext_name(base):
uname = platform.uname()
tags = '-'.join((grpc_version.VERSION, uname[0], uname[4]))
flavor = 'ucs2' if sys.maxunicode == 65535 else 'ucs4'
return '{base}-{tags}-{flavor}'.format(base=base, tags=tags, flavor=flavor)
class BuildTaggedExt(setuptools.Command):
description = 'build the gRPC tagged extensions'
user_options = []
def initialize_options(self):
# distutils requires this override.
pass
def finalize_options(self):
# distutils requires this override.
pass
def run(self):
if 'linux' in sys.platform:
self.run_command('build_ext')
try:
os.makedirs('dist/')
except OSError:
pass
shutil.copyfile(
os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so'),
'dist/{}.so'.format(_tagged_ext_name('cygrpc')))
else:
sys.stderr.write('nothing to do for build_tagged_ext\n')
def update_setup_arguments(setup_arguments):
url = '{}/{}.so'.format(BINARIES_REPOSITORY, _tagged_ext_name('cygrpc'))
target_path = os.path.join(PYTHON_STEM, 'grpc/_cython/cygrpc.so')
try:
extension = urlopen(url).read()
except:
sys.stderr.write(
'could not download precompiled extension: {}\n'.format(url))
return
try:
with open(target_path, 'w') as target:
target.write(extension)
setup_arguments['ext_modules'] = []
except:
sys.stderr.write(
'could not write precompiled extension to directory: {} -> {}\n'
.format(url, target_path))

@ -17,7 +17,7 @@
s.required_ruby_version = '>= 2.0.0'
s.files = %w( Makefile )
s.files = %w( Makefile .yardopts )
s.files += %w( etc/roots.pem )
s.files += Dir.glob('src/ruby/bin/**/*')
s.files += Dir.glob('src/ruby/ext/**/*')
@ -33,7 +33,7 @@
s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.0.0.alpha.5.0.2'
s.add_dependency 'google-protobuf', '~> 3.0.0.alpha.5.0.3'
s.add_dependency 'googleauth', '~> 0.5.1'
s.add_development_dependency 'bundler', '~> 1.9'

@ -25,13 +25,12 @@
"test": "./node_modules/.bin/mocha src/node/test && npm run-script lint",
"gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json",
"coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test",
"preinstall": "npm install node-pre-gyp",
"install": "./node_modules/.bin/node-pre-gyp install --fallback-to-build"
},
"bundledDependencies": ["node-pre-gyp"],
"dependencies": {
"lodash": "^3.9.3",
"nan": "^2.0.0",
"node-pre-gyp": "^0.6.19",
"protobufjs": "^4.0.0"
},
"devDependencies": {

@ -0,0 +1,589 @@
/*
*
* Copyright 2015-2016, 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 "src/core/census/log.h"
#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test/core/util/test_config.h"
// Change this to non-zero if you want more output.
#define VERBOSE 0
// Log size to use for all tests.
#define LOG_SIZE_IN_MB 1
#define LOG_SIZE_IN_BYTES (LOG_SIZE_IN_MB << 20)
// Fills in 'record' of size 'size'. Each byte in record is filled in with the
// same value. The value is extracted from 'record' pointer.
static void write_record(char* record, size_t size) {
char data = (char)((uintptr_t)record % 255);
memset(record, data, size);
}
// Reads fixed size records. Returns the number of records read in
// 'num_records'.
static void read_records(size_t record_size, const char* buffer,
size_t buffer_size, int* num_records) {
GPR_ASSERT(buffer_size >= record_size);
GPR_ASSERT(buffer_size % record_size == 0);
*num_records = (int)(buffer_size / record_size);
for (int i = 0; i < *num_records; ++i) {
const char* record = buffer + (record_size * (size_t)i);
char data = (char)((uintptr_t)record % 255);
for (size_t j = 0; j < record_size; ++j) {
GPR_ASSERT(data == record[j]);
}
}
}
// Tries to write the specified number of records. Stops when the log gets
// full. Returns the number of records written. Spins for random
// number of times, up to 'max_spin_count', between writes.
static int write_records_to_log(int writer_id, size_t record_size,
int num_records, int max_spin_count) {
int counter = 0;
for (int i = 0; i < num_records; ++i) {
int spin_count = max_spin_count ? rand() % max_spin_count : 0;
if (VERBOSE && (counter++ == num_records / 10)) {
printf(" Writer %d: %d out of %d written\n", writer_id, i, num_records);
counter = 0;
}
char* record = (char*)(census_log_start_write(record_size));
if (record == NULL) {
return i;
}
write_record(record, record_size);
census_log_end_write(record, record_size);
for (int j = 0; j < spin_count; ++j) {
GPR_ASSERT(j >= 0);
}
}
return num_records;
}
// Performs a single read iteration. Returns the number of records read.
static int perform_read_iteration(size_t record_size) {
const void* read_buffer = NULL;
size_t bytes_available;
int records_read = 0;
census_log_init_reader();
while ((read_buffer = census_log_read_next(&bytes_available))) {
int num_records = 0;
read_records(record_size, (const char*)read_buffer, bytes_available,
&num_records);
records_read += num_records;
}
return records_read;
}
// Asserts that the log is empty.
static void assert_log_empty(void) {
census_log_init_reader();
size_t bytes_available;
GPR_ASSERT(census_log_read_next(&bytes_available) == NULL);
}
// Fills the log and verifies data. If 'no fragmentation' is true, records
// are sized such that CENSUS_LOG_2_MAX_RECORD_SIZE is a multiple of record
// size. If not a circular log, verifies that the number of records written
// match the number of records read.
static void fill_log(size_t log_size, int no_fragmentation, int circular_log) {
size_t size;
if (no_fragmentation) {
int log2size = rand() % (CENSUS_LOG_2_MAX_RECORD_SIZE + 1);
size = ((size_t)1 << log2size);
} else {
while (1) {
size = 1 + ((size_t)rand() % CENSUS_LOG_MAX_RECORD_SIZE);
if (CENSUS_LOG_MAX_RECORD_SIZE % size) {
break;
}
}
}
int records_written =
write_records_to_log(0 /* writer id */, size,
(int)((log_size / size) * 2), 0 /* spin count */);
int records_read = perform_read_iteration(size);
if (!circular_log) {
GPR_ASSERT(records_written == records_read);
}
assert_log_empty();
}
// Structure to pass args to writer_thread
typedef struct writer_thread_args {
// Index of this thread in the writers vector.
int index;
// Record size.
size_t record_size;
// Number of records to write.
int num_records;
// Used to signal when writer is complete
gpr_cv* done;
gpr_mu* mu;
int* count;
} writer_thread_args;
// Writes the given number of records of random size (up to kMaxRecordSize) and
// random data to the specified log.
static void writer_thread(void* arg) {
writer_thread_args* args = (writer_thread_args*)arg;
// Maximum number of times to spin between writes.
static const int MAX_SPIN_COUNT = 50;
int records_written = 0;
if (VERBOSE) {
printf(" Writer %d starting\n", args->index);
}
while (records_written < args->num_records) {
records_written += write_records_to_log(args->index, args->record_size,
args->num_records - records_written,
MAX_SPIN_COUNT);
if (records_written < args->num_records) {
// Ran out of log space. Sleep for a bit and let the reader catch up.
// This should never happen for circular logs.
if (VERBOSE) {
printf(
" Writer %d stalled due to out-of-space: %d out of %d "
"written\n",
args->index, records_written, args->num_records);
}
gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(10));
}
}
// Done. Decrement count and signal.
gpr_mu_lock(args->mu);
(*args->count)--;
gpr_cv_signal(args->done);
if (VERBOSE) {
printf(" Writer %d done\n", args->index);
}
gpr_mu_unlock(args->mu);
}
// struct to pass args to reader_thread
typedef struct reader_thread_args {
// Record size.
size_t record_size;
// Interval between read iterations.
int read_iteration_interval_in_msec;
// Total number of records.
int total_records;
// Signalled when reader should stop.
gpr_cv stop;
int stop_flag;
// Used to signal when reader has finished
gpr_cv* done;
gpr_mu* mu;
int running;
} reader_thread_args;
// Reads and verifies the specified number of records. Reader can also be
// stopped via gpr_cv_signal(&args->stop). Sleeps for 'read_interval_in_msec'
// between read iterations.
static void reader_thread(void* arg) {
reader_thread_args* args = (reader_thread_args*)arg;
if (VERBOSE) {
printf(" Reader starting\n");
}
gpr_timespec interval = gpr_time_from_micros(
args->read_iteration_interval_in_msec * 1000, GPR_TIMESPAN);
gpr_mu_lock(args->mu);
int records_read = 0;
int num_iterations = 0;
int counter = 0;
while (!args->stop_flag && records_read < args->total_records) {
gpr_cv_wait(&args->stop, args->mu, interval);
if (!args->stop_flag) {
records_read += perform_read_iteration(args->record_size);
GPR_ASSERT(records_read <= args->total_records);
if (VERBOSE && (counter++ == 100000)) {
printf(" Reader: %d out of %d read\n", records_read,
args->total_records);
counter = 0;
}
++num_iterations;
}
}
// Done
args->running = 0;
gpr_cv_signal(args->done);
if (VERBOSE) {
printf(" Reader: records: %d, iterations: %d\n", records_read,
num_iterations);
}
gpr_mu_unlock(args->mu);
}
// Creates NUM_WRITERS writers where each writer writes NUM_RECORDS_PER_WRITER
// records. Also, starts a reader that iterates over and reads blocks every
// READ_ITERATION_INTERVAL_IN_MSEC.
// Number of writers.
#define NUM_WRITERS 5
static void multiple_writers_single_reader(int circular_log) {
// Sleep interval between read iterations.
static const int READ_ITERATION_INTERVAL_IN_MSEC = 10;
// Maximum record size.
static const size_t MAX_RECORD_SIZE = 20;
// Number of records written by each writer. This is sized such that we
// will write through the entire log ~10 times.
const int NUM_RECORDS_PER_WRITER =
(int)((10 * census_log_remaining_space()) / (MAX_RECORD_SIZE / 2)) /
NUM_WRITERS;
size_t record_size = ((size_t)rand() % MAX_RECORD_SIZE) + 1;
// Create and start writers.
writer_thread_args writers[NUM_WRITERS];
int writers_count = NUM_WRITERS;
gpr_cv writers_done;
gpr_mu writers_mu; // protects writers_done and writers_count
gpr_cv_init(&writers_done);
gpr_mu_init(&writers_mu);
gpr_thd_id id;
for (int i = 0; i < NUM_WRITERS; ++i) {
writers[i].index = i;
writers[i].record_size = record_size;
writers[i].num_records = NUM_RECORDS_PER_WRITER;
writers[i].done = &writers_done;
writers[i].count = &writers_count;
writers[i].mu = &writers_mu;
gpr_thd_new(&id, &writer_thread, &writers[i], NULL);
}
// Start reader.
gpr_cv reader_done;
gpr_mu reader_mu; // protects reader_done and reader.running
reader_thread_args reader;
reader.record_size = record_size;
reader.read_iteration_interval_in_msec = READ_ITERATION_INTERVAL_IN_MSEC;
reader.total_records = NUM_WRITERS * NUM_RECORDS_PER_WRITER;
reader.stop_flag = 0;
gpr_cv_init(&reader.stop);
gpr_cv_init(&reader_done);
reader.done = &reader_done;
gpr_mu_init(&reader_mu);
reader.mu = &reader_mu;
reader.running = 1;
gpr_thd_new(&id, &reader_thread, &reader, NULL);
// Wait for writers to finish.
gpr_mu_lock(&writers_mu);
while (writers_count != 0) {
gpr_cv_wait(&writers_done, &writers_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
}
gpr_mu_unlock(&writers_mu);
gpr_mu_destroy(&writers_mu);
gpr_cv_destroy(&writers_done);
gpr_mu_lock(&reader_mu);
if (circular_log) {
// Stop reader.
reader.stop_flag = 1;
gpr_cv_signal(&reader.stop);
}
// wait for reader to finish
while (reader.running) {
gpr_cv_wait(&reader_done, &reader_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
}
if (circular_log) {
// Assert that there were no out-of-space errors.
GPR_ASSERT(0 == census_log_out_of_space_count());
}
gpr_mu_unlock(&reader_mu);
gpr_mu_destroy(&reader_mu);
gpr_cv_destroy(&reader_done);
if (VERBOSE) {
printf(" Reader: finished\n");
}
}
static void setup_test(int circular_log) {
census_log_initialize(LOG_SIZE_IN_MB, circular_log);
GPR_ASSERT(census_log_remaining_space() == LOG_SIZE_IN_BYTES);
}
// Attempts to create a record of invalid size (size >
// CENSUS_LOG_MAX_RECORD_SIZE).
void test_invalid_record_size(void) {
static const size_t INVALID_SIZE = CENSUS_LOG_MAX_RECORD_SIZE + 1;
static const size_t VALID_SIZE = 1;
printf("Starting test: invalid record size\n");
setup_test(0);
void* record = census_log_start_write(INVALID_SIZE);
GPR_ASSERT(record == NULL);
// Now try writing a valid record.
record = census_log_start_write(VALID_SIZE);
GPR_ASSERT(record != NULL);
census_log_end_write(record, VALID_SIZE);
// Verifies that available space went down by one block. In theory, this
// check can fail if the thread is context switched to a new CPU during the
// start_write execution (multiple blocks get allocated), but this has not
// been observed in practice.
GPR_ASSERT(LOG_SIZE_IN_BYTES - CENSUS_LOG_MAX_RECORD_SIZE ==
census_log_remaining_space());
census_log_shutdown();
}
// Tests end_write() with a different size than what was specified in
// start_write().
void test_end_write_with_different_size(void) {
static const size_t START_WRITE_SIZE = 10;
static const size_t END_WRITE_SIZE = 7;
printf("Starting test: end write with different size\n");
setup_test(0);
void* record_written = census_log_start_write(START_WRITE_SIZE);
GPR_ASSERT(record_written != NULL);
census_log_end_write(record_written, END_WRITE_SIZE);
census_log_init_reader();
size_t bytes_available;
const void* record_read = census_log_read_next(&bytes_available);
GPR_ASSERT(record_written == record_read);
GPR_ASSERT(END_WRITE_SIZE == bytes_available);
assert_log_empty();
census_log_shutdown();
}
// Verifies that pending records are not available via read_next().
void test_read_pending_record(void) {
static const size_t PR_RECORD_SIZE = 1024;
printf("Starting test: read pending record\n");
setup_test(0);
// Start a write.
void* record_written = census_log_start_write(PR_RECORD_SIZE);
GPR_ASSERT(record_written != NULL);
// As write is pending, read should fail.
census_log_init_reader();
size_t bytes_available;
const void* record_read = census_log_read_next(&bytes_available);
GPR_ASSERT(record_read == NULL);
// A read followed by end_write() should succeed.
census_log_end_write(record_written, PR_RECORD_SIZE);
census_log_init_reader();
record_read = census_log_read_next(&bytes_available);
GPR_ASSERT(record_written == record_read);
GPR_ASSERT(PR_RECORD_SIZE == bytes_available);
assert_log_empty();
census_log_shutdown();
}
// Tries reading beyond pending write.
void test_read_beyond_pending_record(void) {
printf("Starting test: read beyond pending record\n");
setup_test(0);
// Start a write.
const size_t incomplete_record_size = 10;
void* incomplete_record = census_log_start_write(incomplete_record_size);
GPR_ASSERT(incomplete_record != NULL);
const size_t complete_record_size = 20;
void* complete_record = census_log_start_write(complete_record_size);
GPR_ASSERT(complete_record != NULL);
GPR_ASSERT(complete_record != incomplete_record);
census_log_end_write(complete_record, complete_record_size);
// Now iterate over blocks to read completed records.
census_log_init_reader();
size_t bytes_available;
const void* record_read = census_log_read_next(&bytes_available);
GPR_ASSERT(complete_record == record_read);
GPR_ASSERT(complete_record_size == bytes_available);
// Complete first record.
census_log_end_write(incomplete_record, incomplete_record_size);
// Have read past the incomplete record, so read_next() should return NULL.
// NB: this test also assumes our thread did not get switched to a different
// CPU between the two start_write calls
record_read = census_log_read_next(&bytes_available);
GPR_ASSERT(record_read == NULL);
// Reset reader to get the newly completed record.
census_log_init_reader();
record_read = census_log_read_next(&bytes_available);
GPR_ASSERT(incomplete_record == record_read);
GPR_ASSERT(incomplete_record_size == bytes_available);
assert_log_empty();
census_log_shutdown();
}
// Tests scenario where block being read is detached from a core and put on the
// dirty list.
void test_detached_while_reading(void) {
printf("Starting test: detached while reading\n");
setup_test(0);
// Start a write.
static const size_t DWR_RECORD_SIZE = 10;
void* record_written = census_log_start_write(DWR_RECORD_SIZE);
GPR_ASSERT(record_written != NULL);
census_log_end_write(record_written, DWR_RECORD_SIZE);
// Read this record.
census_log_init_reader();
size_t bytes_available;
const void* record_read = census_log_read_next(&bytes_available);
GPR_ASSERT(record_read != NULL);
GPR_ASSERT(DWR_RECORD_SIZE == bytes_available);
// Now fill the log. This will move the block being read from core-local
// array to the dirty list.
while ((record_written = census_log_start_write(DWR_RECORD_SIZE))) {
census_log_end_write(record_written, DWR_RECORD_SIZE);
}
// In this iteration, read_next() should only traverse blocks in the
// core-local array. Therefore, we expect at most gpr_cpu_num_cores() more
// blocks. As log is full, if read_next() is traversing the dirty list, we
// will get more than gpr_cpu_num_cores() blocks.
int block_read = 0;
while ((record_read = census_log_read_next(&bytes_available))) {
++block_read;
GPR_ASSERT(block_read <= (int)gpr_cpu_num_cores());
}
census_log_shutdown();
}
// Fills non-circular log with records sized such that size is a multiple of
// CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation).
void test_fill_log_no_fragmentation(void) {
printf("Starting test: fill log no fragmentation\n");
const int circular = 0;
setup_test(circular);
fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular);
census_log_shutdown();
}
// Fills circular log with records sized such that size is a multiple of
// CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation).
void test_fill_circular_log_no_fragmentation(void) {
printf("Starting test: fill circular log no fragmentation\n");
const int circular = 1;
setup_test(circular);
fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular);
census_log_shutdown();
}
// Fills non-circular log with records that may straddle end of a block.
void test_fill_log_with_straddling_records(void) {
printf("Starting test: fill log with straddling records\n");
const int circular = 0;
setup_test(circular);
fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular);
census_log_shutdown();
}
// Fills circular log with records that may straddle end of a block.
void test_fill_circular_log_with_straddling_records(void) {
printf("Starting test: fill circular log with straddling records\n");
const int circular = 1;
setup_test(circular);
fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular);
census_log_shutdown();
}
// Tests scenario where multiple writers and a single reader are using a log
// that is configured to discard old records.
void test_multiple_writers_circular_log(void) {
printf("Starting test: multiple writers circular log\n");
const int circular = 1;
setup_test(circular);
multiple_writers_single_reader(circular);
census_log_shutdown();
}
// Tests scenario where multiple writers and a single reader are using a log
// that is configured to discard old records.
void test_multiple_writers(void) {
printf("Starting test: multiple writers\n");
const int circular = 0;
setup_test(circular);
multiple_writers_single_reader(circular);
census_log_shutdown();
}
// Repeat the straddling records and multiple writers tests with a small log.
void test_small_log(void) {
printf("Starting test: small log\n");
const int circular = 0;
census_log_initialize(0, circular);
size_t log_size = census_log_remaining_space();
GPR_ASSERT(log_size > 0);
fill_log(log_size, 0, circular);
census_log_shutdown();
census_log_initialize(0, circular);
multiple_writers_single_reader(circular);
census_log_shutdown();
}
void test_performance(void) {
for (size_t write_size = 1; write_size < CENSUS_LOG_MAX_RECORD_SIZE;
write_size *= 2) {
setup_test(0);
gpr_timespec start_time = gpr_now(GPR_CLOCK_REALTIME);
int nrecords = 0;
while (1) {
void* record = census_log_start_write(write_size);
if (record == NULL) {
break;
}
census_log_end_write(record, write_size);
nrecords++;
}
gpr_timespec write_time =
gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start_time);
double write_time_micro =
(double)write_time.tv_sec * 1000000 + (double)write_time.tv_nsec / 1000;
census_log_shutdown();
printf(
"Wrote %d %d byte records in %.3g microseconds: %g records/us "
"(%g ns/record), %g gigabytes/s\n",
nrecords, (int)write_size, write_time_micro,
nrecords / write_time_micro, 1000 * write_time_micro / nrecords,
(double)((int)write_size * nrecords) / write_time_micro / 1000);
}
}
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
gpr_time_init();
srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_invalid_record_size();
test_end_write_with_different_size();
test_read_pending_record();
test_read_beyond_pending_record();
test_detached_while_reading();
test_fill_log_no_fragmentation();
test_fill_circular_log_no_fragmentation();
test_fill_log_with_straddling_records();
test_fill_circular_log_with_straddling_records();
test_small_log();
test_multiple_writers();
test_multiple_writers_circular_log();
test_performance();
return 0;
}

@ -197,9 +197,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
workers.resize(num_clients + num_servers);
gpr_timespec deadline =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
gpr_time_from_seconds(
warmup_seconds + benchmark_seconds + 20, GPR_TIMESPAN));
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(warmup_seconds + benchmark_seconds + 20);
// Start servers
using runsc::ServerData;

@ -51,6 +51,7 @@
#include <gtest/gtest.h>
#include "src/proto/grpc/testing/services.grpc.pb.h"
#include "test/core/util/test_config.h"
#include "test/cpp/qps/server.h"
namespace grpc {
@ -129,7 +130,7 @@ class AsyncQpsServerTest : public Server {
}
}
~AsyncQpsServerTest() {
auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(10);
auto deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
server_->Shutdown(deadline);
for (auto ss = shutdown_state_.begin(); ss != shutdown_state_.end(); ++ss) {
(*ss)->set_shutdown();

@ -38,6 +38,9 @@ nvm install $NODE_VERSION
npm install -g node-static
# Kill off existing static servers
kill -9 $(ps aux | grep '[n]ode .*static' | awk '{print $2}') || true
STATIC_SERVER=127.0.0.1
STATIC_PORT=8080

@ -29,4 +29,9 @@
FROM fedora:21
# Make yum work properly under docker when using overlay storage driver.
# https://bugzilla.redhat.com/show_bug.cgi?id=1213602#c9
# https://github.com/docker/docker/issues/10180
RUN yum install -y yum-plugin-ovl
RUN yum clean all && yum update -y && yum install -y python python-pip

@ -29,6 +29,11 @@
FROM fedora:21
# Make yum work properly under docker when using overlay storage driver.
# https://bugzilla.redhat.com/show_bug.cgi?id=1213602#c9
# https://github.com/docker/docker/issues/10180
RUN yum install -y yum-plugin-ovl
RUN yum clean all && yum update -y && yum install -y ruby
RUN gem install bundler

@ -901,6 +901,7 @@ src/core/transport/static_metadata.h \
src/core/transport/transport.h \
src/core/transport/transport_impl.h \
src/core/census/aggregation.h \
src/core/census/log.h \
src/core/census/rpc_metric_id.h \
src/core/httpcli/httpcli_security_connector.c \
src/core/security/base64.c \
@ -1052,6 +1053,7 @@ src/core/transport/transport.c \
src/core/transport/transport_op_string.c \
src/core/census/context.c \
src/core/census/initialize.c \
src/core/census/log.c \
src/core/census/operation.c \
src/core/census/placeholders.c \
src/core/census/tracing.c \

@ -36,7 +36,7 @@ nvm use 4
cd $(dirname $0)/../..
rm -rf build
rm -rf build || true
mkdir -p artifacts
@ -46,6 +46,6 @@ node_versions=( 0.12.0 1.0.0 1.1.0 2.0.0 3.0.0 4.0.0 5.0.0 )
for version in ${node_versions[@]}
do
node-pre-gyp configure rebuild package testpackage --target=$version --target_arch=$NODE_TARGET_ARCH
./node_modules/.bin/node-pre-gyp configure rebuild package testpackage --target=$version --target_arch=$NODE_TARGET_ARCH
cp -r build/stage/* artifacts/
done

@ -39,12 +39,20 @@ then
pip install -rrequirements.txt
fi
# The bdist_wheel_grpc_custom command is finicky about command output ordering
# and thus ought to be run in a shell command separate of others. Further, it
# trashes the actual bdist_wheel output, so it should be run first so that
# bdist_wheel may be run unmolested.
GRPC_PYTHON_USE_CUSTOM_BDIST=0 \
GRPC_PYTHON_BUILD_WITH_CYTHON=1 \
${SETARCH_CMD} python setup.py \
build_tagged_ext
GRPC_PYTHON_USE_CUSTOM_BDIST=0 \
GRPC_PYTHON_BUILD_WITH_CYTHON=1 \
${SETARCH_CMD} python setup.py \
bdist_wheel \
sdist \
bdist_egg_grpc_custom
sdist
mkdir -p artifacts

@ -38,6 +38,7 @@ cd $(dirname $0)/../..
mkdir -p artifacts/
cp -r $EXTERNAL_GIT_ROOT/architecture={x86,x64},language=node,platform={windows,linux,macos}/artifacts/* artifacts/ || true
npm update
npm pack
cp grpc-*.tgz artifacts/grpc.tgz

@ -122,11 +122,15 @@ class NodeDistribTest(object):
def build_jobspec(self):
if self.platform == 'linux':
linux32 = ''
if self.arch == 'x86':
linux32 = 'linux32'
return create_docker_jobspec(self.name,
'tools/dockerfile/distribtest/node_%s_%s' % (
self.docker_suffix,
self.arch),
'test/distrib/node/run_distrib_test.sh %s' % (
'%s test/distrib/node/run_distrib_test.sh %s' % (
linux32,
self.node_version))
elif self.platform == 'macos':
return create_jobspec(self.name,
@ -236,11 +240,7 @@ def targets():
RubyDistribTest('linux', 'x64', 'ubuntu1504'),
RubyDistribTest('linux', 'x64', 'ubuntu1510'),
RubyDistribTest('linux', 'x64', 'ubuntu1604'),
NodeDistribTest('macos', 'x64', None, '0.10'),
NodeDistribTest('macos', 'x64', None, '0.12'),
NodeDistribTest('macos', 'x64', None, '3'),
NodeDistribTest('macos', 'x64', None, '4'),
NodeDistribTest('macos', 'x64', None, '5'),
NodeDistribTest('linux', 'x86', 'jessie', '4')
] + [
NodeDistribTest('linux', 'x64', os, version)

@ -81,6 +81,20 @@
"test/core/census/context_test.c"
]
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"language": "c",
"name": "census_log_test",
"src": [
"test/core/census/log_test.c"
]
},
{
"deps": [
"gpr",
@ -2969,6 +2983,7 @@
"include/grpc/status.h",
"src/core/census/aggregation.h",
"src/core/census/grpc_filter.h",
"src/core/census/log.h",
"src/core/census/rpc_metric_id.h",
"src/core/channel/channel_args.h",
"src/core/channel/channel_stack.h",
@ -3119,6 +3134,8 @@
"src/core/census/grpc_filter.c",
"src/core/census/grpc_filter.h",
"src/core/census/initialize.c",
"src/core/census/log.c",
"src/core/census/log.h",
"src/core/census/operation.c",
"src/core/census/placeholders.c",
"src/core/census/rpc_metric_id.h",
@ -3494,6 +3511,7 @@
"include/grpc/status.h",
"src/core/census/aggregation.h",
"src/core/census/grpc_filter.h",
"src/core/census/log.h",
"src/core/census/rpc_metric_id.h",
"src/core/channel/channel_args.h",
"src/core/channel/channel_stack.h",
@ -3629,6 +3647,8 @@
"src/core/census/grpc_filter.c",
"src/core/census/grpc_filter.h",
"src/core/census/initialize.c",
"src/core/census/log.c",
"src/core/census/log.h",
"src/core/census/operation.c",
"src/core/census/placeholders.c",
"src/core/census/rpc_metric_id.h",

@ -121,6 +121,26 @@
"windows"
]
},
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"flaky": false,
"language": "c",
"name": "census_log_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{
"args": [],
"ci_platforms": [

@ -176,6 +176,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_context_test", "vcxp
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_log_test", "vcxproj\test\census_log_test\census_log_test.vcxproj", "{C27CEE16-2BEC-5572-3956-677E9F6F8BED}"
ProjectSection(myProperties) = preProject
lib = "False"
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "channel_create_test", "vcxproj\test\channel_create_test\channel_create_test.vcxproj", "{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}"
ProjectSection(myProperties) = preProject
lib = "False"
@ -1604,6 +1615,22 @@ Global
{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|Win32.Build.0 = Release|Win32
{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.ActiveCfg = Release|x64
{5C1CFC2D-AF3C-D7CB-BA74-D267E91CBC73}.Release-DLL|x64.Build.0 = Release|x64
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug|Win32.ActiveCfg = Debug|Win32
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug|x64.ActiveCfg = Debug|x64
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release|Win32.ActiveCfg = Release|Win32
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release|x64.ActiveCfg = Release|x64
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug|Win32.Build.0 = Debug|Win32
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug|x64.Build.0 = Debug|x64
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release|Win32.Build.0 = Release|Win32
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release|x64.Build.0 = Release|x64
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug-DLL|Win32.Build.0 = Debug|Win32
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug-DLL|x64.ActiveCfg = Debug|x64
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Debug-DLL|x64.Build.0 = Debug|x64
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release-DLL|Win32.ActiveCfg = Release|Win32
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release-DLL|Win32.Build.0 = Release|Win32
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release-DLL|x64.ActiveCfg = Release|x64
{C27CEE16-2BEC-5572-3956-677E9F6F8BED}.Release-DLL|x64.Build.0 = Release|x64
{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|Win32.ActiveCfg = Debug|Win32
{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|x64.ActiveCfg = Debug|x64
{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Release|Win32.ActiveCfg = Release|Win32

@ -410,6 +410,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\transport\transport.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\transport\transport_impl.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\census\log.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h" />
</ItemGroup>
<ItemGroup>
@ -713,6 +714,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\initialize.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\log.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\operation.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\placeholders.c">

@ -451,6 +451,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\census\initialize.c">
<Filter>src\core\census</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\log.c">
<Filter>src\core\census</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\operation.c">
<Filter>src\core\census</Filter>
</ClCompile>
@ -887,6 +890,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h">
<Filter>src\core\census</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\census\log.h">
<Filter>src\core\census</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h">
<Filter>src\core\census</Filter>
</ClInclude>

@ -386,6 +386,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\transport\transport.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\transport\transport_impl.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\census\log.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h" />
</ItemGroup>
<ItemGroup>
@ -649,6 +650,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\initialize.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\log.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\operation.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\placeholders.c">

@ -391,6 +391,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\census\initialize.c">
<Filter>src\core\census</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\log.c">
<Filter>src\core\census</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\census\operation.c">
<Filter>src\core\census</Filter>
</ClCompile>
@ -782,6 +785,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\census\aggregation.h">
<Filter>src\core\census</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\census\log.h">
<Filter>src\core\census</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\census\rpc_metric_id.h">
<Filter>src\core\census</Filter>
</ClInclude>

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C27CEE16-2BEC-5572-3956-677E9F6F8BED}</ProjectGuid>
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\..\vsprojects\global.props" />
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<TargetName>census_log_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<TargetName>census_log_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\census\log_test.c">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
<Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
<Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
</Target>
</Project>

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\census\log_test.c">
<Filter>test\core\census</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="test">
<UniqueIdentifier>{4d0aae38-6975-cafb-30a6-a7c2c87d22ff}</UniqueIdentifier>
</Filter>
<Filter Include="test\core">
<UniqueIdentifier>{fb85321f-d3b5-ef2f-c5aa-34660a5e0c7b}</UniqueIdentifier>
</Filter>
<Filter Include="test\core\census">
<UniqueIdentifier>{f23141da-cbe2-70fa-8207-858af868eb18}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
Loading…
Cancel
Save