Merge branch 'master' of https://github.com/grpc/grpc
diff --git a/Makefile b/Makefile
index 26899c5..2e9a5c1 100644
--- a/Makefile
+++ b/Makefile
@@ -2518,6 +2518,21 @@
 endif
 
 ifeq ($(NO_PROTOC),true)
+$(GENDIR)/test/cpp/qps/perf_db.pb.cc: protoc_dep_error
+$(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc: protoc_dep_error
+else
+$(GENDIR)/test/cpp/qps/perf_db.pb.cc: test/cpp/qps/perf_db.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
+	$(E) "[PROTOC]  Generating protobuf CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
+
+$(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc: test/cpp/qps/perf_db.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
+	$(E) "[GRPC]    Generating gRPC's protobuf service CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
+endif
+
+ifeq ($(NO_PROTOC),true)
 $(GENDIR)/test/cpp/qps/qpstest.pb.cc: protoc_dep_error
 $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc: protoc_dep_error
 else
@@ -3535,6 +3550,8 @@
 
 LIBGRPC++_BENCHMARK_CONFIG_SRC = \
     $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc \
+    $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc \
+    test/cpp/qps/perf_db_client.cc \
     test/cpp/qps/report.cc \
     test/cpp/util/benchmark_config.cc \
 
@@ -3580,8 +3597,9 @@
 -include $(LIBGRPC++_BENCHMARK_CONFIG_OBJS:.o=.dep)
 endif
 endif
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/report.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/util/benchmark_config.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/perf_db_client.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/report.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/benchmark_config.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
 
 
 LIBGRPC++_TEST_CONFIG_SRC = \
@@ -4096,9 +4114,11 @@
 
 LIBQPS_SRC = \
     $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc \
+    $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc \
     test/cpp/qps/client_async.cc \
     test/cpp/qps/client_sync.cc \
     test/cpp/qps/driver.cc \
+    test/cpp/qps/perf_db_client.cc \
     test/cpp/qps/qps_worker.cc \
     test/cpp/qps/server_async.cc \
     test/cpp/qps/server_sync.cc \
@@ -4146,13 +4166,14 @@
 -include $(LIBQPS_OBJS:.o=.dep)
 endif
 endif
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_sync.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_worker.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_sync.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/timer.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_sync.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/perf_db_client.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_worker.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_sync.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/timer.o: $(GENDIR)/test/cpp/qps/qpstest.pb.cc $(GENDIR)/test/cpp/qps/qpstest.grpc.pb.cc $(GENDIR)/test/cpp/qps/perf_db.pb.cc $(GENDIR)/test/cpp/qps/perf_db.grpc.pb.cc
 
 
 LIBGRPC_CSHARP_EXT_SRC = \
diff --git a/build.json b/build.json
index e01a419..1abbc9a 100644
--- a/build.json
+++ b/build.json
@@ -543,6 +543,8 @@
       "language": "c++",
       "src": [
         "test/cpp/qps/qpstest.proto",
+        "test/cpp/qps/perf_db.proto",
+        "test/cpp/qps/perf_db_client.cc",
         "test/cpp/qps/report.cc",
         "test/cpp/util/benchmark_config.cc"
       ]
@@ -714,9 +716,11 @@
       ],
       "src": [
         "test/cpp/qps/qpstest.proto",
+        "test/cpp/qps/perf_db.proto",
         "test/cpp/qps/client_async.cc",
         "test/cpp/qps/client_sync.cc",
         "test/cpp/qps/driver.cc",
+        "test/cpp/qps/perf_db_client.cc",
         "test/cpp/qps/qps_worker.cc",
         "test/cpp/qps/server_async.cc",
         "test/cpp/qps/server_sync.cc",
diff --git a/test/cpp/qps/perf_db.proto b/test/cpp/qps/perf_db.proto
new file mode 100644
index 0000000..7f4a460
--- /dev/null
+++ b/test/cpp/qps/perf_db.proto
@@ -0,0 +1,124 @@
+// 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";
+
+import "test/cpp/qps/qpstest.proto";
+
+package grpc.testing;
+
+service PerfDbTransfer {
+  // Sends client info
+  rpc RecordSingleClientData (SingleUserRecordRequest) returns (SingleUserRecordReply) {}
+
+  rpc RetrieveSingleUserData (SingleUserRetrieveRequest) returns (SingleUserRetrieveReply) {}
+
+  rpc RetrieveAllUsersData (AllUsersRetrieveRequest) returns (AllUsersRetrieveReply) {}
+}
+
+//Metrics to be stored
+message Metrics {
+  double qps = 1;
+  double qps_per_core = 2;
+  double perc_lat_50 = 3;
+  double perc_lat_90 = 4;
+  double perc_lat_95 = 5;
+  double perc_lat_99 = 6;
+  double perc_lat_99_point_9 = 7;
+  double server_system_time = 8;
+  double server_user_time = 9;
+  double client_system_time = 10;
+  double client_user_time = 11;
+}
+
+//Timestamped details
+message DataDetails {
+  string timestamp = 1;
+  string test_name = 2;
+  string sys_info = 3;
+  string tag = 4;
+  Metrics metrics = 5;
+  ClientConfig client_config = 6;
+  ServerConfig server_config = 7;
+}
+
+//User details
+message UserDetails {
+  string id = 1;
+  string email = 2;
+  bool verified_email = 3;
+  string name = 4;
+  string given_name = 5;
+  string family_name = 6;
+  string link = 7;
+  string picture = 8;
+  string gender = 9;
+  string locale = 10;
+  string hd = 11;
+}
+
+//Stored to database
+message SingleUserDetails {
+  repeated DataDetails data_details = 1;
+  UserDetails user_details = 2;
+}
+
+//Request for storing a single user's data
+message SingleUserRecordRequest {
+  string access_token = 1;
+  string test_name = 2;
+  string sys_info = 3;
+  string tag = 4;
+  Metrics metrics = 5;
+  ClientConfig client_config = 6;
+  ServerConfig server_config = 7;
+}
+
+//Reply to request for storing single user's data
+message SingleUserRecordReply {
+}
+
+//Request for retrieving single user's data
+message SingleUserRetrieveRequest {
+  string user_id = 1;
+}
+
+//Reply for request to retrieve single user's data
+message SingleUserRetrieveReply {
+  SingleUserDetails details = 1;
+}
+
+//Request for retrieving all users' data
+message AllUsersRetrieveReply {
+  repeated SingleUserDetails user_data = 1;
+}
+
+//Reply to request for retrieving all users' data
+message AllUsersRetrieveRequest {
+}
diff --git a/test/cpp/qps/perf_db_client.cc b/test/cpp/qps/perf_db_client.cc
new file mode 100644
index 0000000..65569e5
--- /dev/null
+++ b/test/cpp/qps/perf_db_client.cc
@@ -0,0 +1,115 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "test/cpp/qps/perf_db_client.h"
+
+namespace grpc {
+namespace testing {
+
+//sets the client and server config information
+void PerfDbClient::setConfigs(const ClientConfig& clientConfig, const ServerConfig& serverConfig) {
+  this->clientConfig_ = clientConfig;
+  this->serverConfig_ = serverConfig;
+}
+
+//sets the QPS
+void PerfDbClient::setQPS(double QPS) {
+  this->QPS_ = QPS;
+}
+
+//sets the QPS per core
+void PerfDbClient::setQPSPerCore(double QPSPerCore) {
+  this->QPSPerCore_ = QPSPerCore;
+}
+
+//sets the 50th, 90th, 95th, 99th and 99.9th percentile latency
+void PerfDbClient::setLatencies(double percentileLatency50, double percentileLatency90,
+    double percentileLatency95, double percentileLatency99, double percentileLatency99Point9) {
+  this->percentileLatency50_ = percentileLatency50;
+  this->percentileLatency90_ = percentileLatency90;
+  this->percentileLatency95_ = percentileLatency95;
+  this->percentileLatency99_ = percentileLatency99;
+  this->percentileLatency99Point9_ = percentileLatency99Point9;
+}
+
+//sets the server and client, user and system times
+void PerfDbClient::setTimes(double serverSystemTime, double serverUserTime, 
+    double clientSystemTime, double clientUserTime) {
+  this->serverSystemTime_ = serverSystemTime;
+  this->serverUserTime_ = serverUserTime;
+  this->clientSystemTime_ = clientSystemTime;
+  this->clientUserTime_ = clientUserTime;
+}
+
+//sends the data to the performancew database server
+int PerfDbClient::sendData(std::string access_token, std::string test_name, std::string sys_info, std::string tag) {
+  //Data record request object
+  SingleUserRecordRequest singleUserRecordRequest;
+
+  //setting access token, name of the test and the system information
+  singleUserRecordRequest.set_access_token(access_token);
+  singleUserRecordRequest.set_test_name(test_name);
+  singleUserRecordRequest.set_sys_info(sys_info);
+  singleUserRecordRequest.set_tag(tag);
+
+  //setting configs
+  *(singleUserRecordRequest.mutable_client_config()) = this->clientConfig_;
+  *(singleUserRecordRequest.mutable_server_config()) = this->serverConfig_;
+  
+  Metrics* metrics = singleUserRecordRequest.mutable_metrics();
+
+  //setting metrcs in data record request
+  if(QPS_ != DBL_MIN) metrics->set_qps(this->QPS_);
+  if(QPSPerCore_ != DBL_MIN) metrics->set_qps_per_core(this->QPSPerCore_);
+  if(percentileLatency50_ != DBL_MIN) metrics->set_perc_lat_50(this->percentileLatency50_);
+  if(percentileLatency90_ != DBL_MIN) metrics->set_perc_lat_90(this->percentileLatency90_);
+  if(percentileLatency95_ != DBL_MIN) metrics->set_perc_lat_95(this->percentileLatency95_);
+  if(percentileLatency99_ != DBL_MIN) metrics->set_perc_lat_99(this->percentileLatency99_);
+  if(percentileLatency99Point9_ != DBL_MIN) metrics->set_perc_lat_99_point_9(this->percentileLatency99Point9_);
+  if(serverSystemTime_ != DBL_MIN) metrics->set_server_system_time(this->serverSystemTime_);
+  if(serverUserTime_ != DBL_MIN) metrics->set_server_user_time(this->serverUserTime_);
+  if(clientSystemTime_ != DBL_MIN) metrics->set_client_system_time(this->clientSystemTime_);
+  if(clientUserTime_ != DBL_MIN) metrics->set_client_user_time(this->clientUserTime_);
+
+  SingleUserRecordReply singleUserRecordReply;
+  ClientContext context;
+
+  Status status = stub_->RecordSingleClientData(&context, singleUserRecordRequest, &singleUserRecordReply);
+  if (status.ok()) {
+    return 1;  //data sent to database successfully
+  } else {
+    return -1;  //error in data sending
+  }
+}
+}  //testing
+}  //grpc
diff --git a/test/cpp/qps/perf_db_client.h b/test/cpp/qps/perf_db_client.h
new file mode 100644
index 0000000..be4766a
--- /dev/null
+++ b/test/cpp/qps/perf_db_client.h
@@ -0,0 +1,113 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <iostream>
+#include <memory>
+#include <string>
+#include <cfloat>
+
+#include <grpc/grpc.h>
+#include <grpc++/channel_arguments.h>
+#include <grpc++/channel_interface.h>
+#include <grpc++/client_context.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/credentials.h>
+#include <grpc++/status.h>
+#include "test/cpp/qps/perf_db.grpc.pb.h"
+
+
+namespace grpc{
+namespace testing {
+
+//Manages data sending to performance database server
+class PerfDbClient {
+public:
+  PerfDbClient() {
+    QPS_ = DBL_MIN;
+    QPSPerCore_ = DBL_MIN;
+    percentileLatency50_ = DBL_MIN;
+    percentileLatency90_ = DBL_MIN;
+    percentileLatency95_ = DBL_MIN;
+    percentileLatency99_ = DBL_MIN;
+    percentileLatency99Point9_ = DBL_MIN;
+    serverSystemTime_ = DBL_MIN;
+    serverUserTime_ = DBL_MIN;
+    clientSystemTime_ = DBL_MIN;
+    clientUserTime_ = DBL_MIN;
+  }
+  
+  void init(std::shared_ptr<ChannelInterface> channel) { stub_ = PerfDbTransfer::NewStub(channel); }
+
+  ~PerfDbClient() {}
+
+  //sets the client and server config information
+  void setConfigs(const ClientConfig& clientConfig, const ServerConfig& serverConfig);
+  
+  //sets the QPS
+  void setQPS(double QPS);
+
+  //sets the QPS per core
+  void setQPSPerCore(double QPSPerCore);
+
+  //sets the 50th, 90th, 95th, 99th and 99.9th percentile latency
+  void setLatencies(double percentileLatency50, double percentileLatency90,
+     double percentileLatency95, double percentileLatency99, double percentileLatency99Point9);
+
+  //sets the server and client, user and system times
+  void setTimes(double serverSystemTime, double serverUserTime, 
+    double clientSystemTime, double clientUserTime);
+
+  //sends the data to the performancew database server
+  int sendData(std::string access_token, std::string test_name, std::string sys_info, std::string tag);
+
+private:
+  std::unique_ptr<PerfDbTransfer::Stub> stub_;
+  ClientConfig clientConfig_;
+  ServerConfig serverConfig_;
+  double QPS_;
+  double QPSPerCore_;
+  double percentileLatency50_;
+  double percentileLatency90_;
+  double percentileLatency95_;
+  double percentileLatency99_;
+  double percentileLatency99Point9_;
+  double serverSystemTime_;
+  double serverUserTime_;
+  double clientSystemTime_;
+  double clientUserTime_;
+};
+
+} //namespace testing
+} //namespace grpc
+
+
diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc
index 94aacdb..7167d4e 100644
--- a/test/cpp/qps/report.cc
+++ b/test/cpp/qps/report.cc
@@ -118,5 +118,73 @@
                   [](ResourceUsage u) { return u.wall_time; }));
 }
 
+void PerfDbReporter::ReportQPS(const ScenarioResult& result) {
+  auto qps = result.latencies.Count() /
+              average(result.client_resources,
+                      [](ResourceUsage u) { return u.wall_time; });
+
+  perfDbClient_.setQPS(qps);
+  perfDbClient_.setConfigs(result.client_config, result.server_config);
+}
+
+void PerfDbReporter::ReportQPSPerCore(const ScenarioResult& result) {
+  auto qps = result.latencies.Count() /
+            average(result.client_resources,
+                    [](ResourceUsage u) { return u.wall_time; });
+
+  auto qpsPerCore = qps / result.server_config.threads();
+
+  perfDbClient_.setQPS(qps);
+  perfDbClient_.setQPSPerCore(qpsPerCore);
+  perfDbClient_.setConfigs(result.client_config, result.server_config);
+}
+
+void PerfDbReporter::ReportLatency(const ScenarioResult& result) {
+  perfDbClient_.setLatencies(result.latencies.Percentile(50) / 1000,
+                              result.latencies.Percentile(90) / 1000,
+                              result.latencies.Percentile(95) / 1000,
+                              result.latencies.Percentile(99) / 1000,
+                              result.latencies.Percentile(99.9) / 1000);
+  perfDbClient_.setConfigs(result.client_config, result.server_config);
+}
+
+void PerfDbReporter::ReportTimes(const ScenarioResult& result) {
+  double serverSystemTime = 100.0 * sum(result.server_resources,
+                  [](ResourceUsage u) { return u.system_time; }) /
+                    sum(result.server_resources,
+                  [](ResourceUsage u) { return u.wall_time; });
+  double serverUserTime = 100.0 * sum(result.server_resources,
+                  [](ResourceUsage u) { return u.user_time; }) /
+                    sum(result.server_resources,
+                  [](ResourceUsage u) { return u.wall_time; });
+  double clientSystemTime = 100.0 * sum(result.client_resources,
+                  [](ResourceUsage u) { return u.system_time; }) /
+                    sum(result.client_resources,
+                  [](ResourceUsage u) { return u.wall_time; });
+  double clientUserTime = 100.0 * sum(result.client_resources,
+                  [](ResourceUsage u) { return u.user_time; }) /
+                    sum(result.client_resources,
+                  [](ResourceUsage u) { return u.wall_time; });
+
+  perfDbClient_.setTimes(serverSystemTime, serverUserTime, 
+    clientSystemTime, clientUserTime);
+  perfDbClient_.setConfigs(result.client_config, result.server_config);
+}
+
+void PerfDbReporter::SendData() {
+  //send data to performance database
+  int dataState = perfDbClient_.sendData(access_token_, test_name_, sys_info_, tag_);
+
+  //check state of data sending
+  switch(dataState) {
+    case 1:
+      gpr_log(GPR_INFO, "Data sent to performance database successfully");
+      break;
+    case -1:
+      gpr_log(GPR_INFO, "Data could not be sent to performance database");
+      break;
+  }
+}
+
 }  // namespace testing
 }  // namespace grpc
diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h
index b1cf83f..5655906 100644
--- a/test/cpp/qps/report.h
+++ b/test/cpp/qps/report.h
@@ -41,6 +41,7 @@
 
 #include "test/cpp/qps/driver.h"
 #include "test/cpp/qps/qpstest.grpc.pb.h"
+#include "test/cpp/qps/perf_db_client.h"
 
 namespace grpc {
 namespace testing {
@@ -103,6 +104,29 @@
   void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE;
 };
 
+/** Reporter for performance database tool */
+class PerfDbReporter : public Reporter {
+ public:
+  PerfDbReporter(const string& name, const string& access_token, const string& test_name, 
+    const string& sys_info, const string& server_address, const string& tag)
+   : Reporter(name), access_token_(access_token), test_name_(test_name), sys_info_(sys_info), tag_(tag) {
+    perfDbClient_.init(grpc::CreateChannel(server_address, grpc::InsecureCredentials(), ChannelArguments()));
+  }
+  ~PerfDbReporter() { SendData(); };
+
+ private:
+  PerfDbClient perfDbClient_;
+  std::string access_token_;
+  std::string test_name_;
+  std::string sys_info_;
+  std::string tag_;
+  void ReportQPS(const ScenarioResult& result) GRPC_OVERRIDE;
+  void ReportQPSPerCore(const ScenarioResult& result) GRPC_OVERRIDE;
+  void ReportLatency(const ScenarioResult& result) GRPC_OVERRIDE;
+  void ReportTimes(const ScenarioResult& result) GRPC_OVERRIDE;
+  void SendData();
+};
+
 }  // namespace testing
 }  // namespace grpc
 
diff --git a/test/cpp/util/benchmark_config.cc b/test/cpp/util/benchmark_config.cc
index 5b3c1da..030cb28 100644
--- a/test/cpp/util/benchmark_config.cc
+++ b/test/cpp/util/benchmark_config.cc
@@ -37,6 +37,18 @@
 DEFINE_bool(enable_log_reporter, true,
             "Enable reporting of benchmark results through GprLog");
 
+DEFINE_bool(report_metrics_db, false, "True if metrics to be reported to performance database");
+
+DEFINE_string(access_token, "", "Authorizing JSON string for leaderboard");
+
+DEFINE_string(test_name, "", "Name of the test being executed");
+
+DEFINE_string(sys_info, "", "System information");
+
+DEFINE_string(server_address, "localhost:50052", "Address of the performance database server");
+
+DEFINE_string(tag, "", "Optional tag for the test");
+
 // In some distros, gflags is in the namespace google, and in some others,
 // in gflags. This hack is enabling us to find both.
 namespace google {}
@@ -57,6 +69,12 @@
     composite_reporter->add(
         std::unique_ptr<Reporter>(new GprLogReporter("LogReporter")));
   }
+  if(FLAGS_report_metrics_db) {
+    composite_reporter->add(
+      std::unique_ptr<Reporter>(new PerfDbReporter("PerfDbReporter", FLAGS_access_token, FLAGS_test_name, 
+        FLAGS_sys_info, FLAGS_server_address, FLAGS_tag)));
+  }
+
   return std::shared_ptr<Reporter>(composite_reporter);
 }