Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added absl::optional dependency to replace current optional implementation of envoy #2688

Merged
merged 13 commits into from
Mar 13, 2018
Merged

Conversation

srikailash
Copy link
Contributor

Signed-off-by: sri kailash [email protected]
Description:
This is a work in progress pull request to replace our current optional.h with absl::optional.
refers to #2651.
Risk Level: Low
Testing: Added unit test until current implementation.

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for getting this started.

#include "gtest/gtest.h"

namespace Envoy {
TEST(abseil_optional , basic_operations) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can skip this I think, Abseil should have its own set of tests (plus, most of this is a pretty big violation of Envoy C++ style ;) )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, added this for my own checks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For your reference, here are the absl::optional<> tests: https://github.com/abseil/abseil-cpp/blob/master/absl/types/optional_test.cc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ccaraman, Thanks!

@@ -1,6 +1,7 @@
#pragma once

#include "envoy/common/exception.h"
#include "absl/types/optional.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rather folks just consume this directly across the tree, rather than having indirection here via our own wrapper header/build target.

Copy link
Contributor Author

@srikailash srikailash Mar 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack, I see less code changes as a benefit of wrapping with some extra maintenance cost. Would like to know other reasons if any from you. Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally I think it's just clearer to use the actual direct includes. I think we'll eventually go with the C++17 std::optional, which absl::optional is supposed to be compatible with, so we'll just do a giant sed at that point.

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed you haven't replaced the actual uses of Optional yet; I would go ahead and do them all in this PR. It shouldn't be that much work, it's just a bit tedious.

@@ -13,6 +13,7 @@
#include "envoy/api/v2/rds.pb.h"
#include "envoy/api/v2/route/route.pb.h"
#include "envoy/common/optional.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to remove the old one in the same sweep?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's still a work in progress PR. I don't mind doing that either. Let me know if you want me to do that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, let's just do one giant PR, it should be fairly easy to review, as the transforms should all be mechanical. Thanks.

@srikailash
Copy link
Contributor Author

srikailash commented Mar 3, 2018

Let me help you with this giant review process:
Bulk changes:
1. Optional -> abs::optional
2. Call to .valid() function need not be done as abs::optional variables itself evaluates to true/false
3. var.value(new_value) -> var = new_value
4. Removed all the includes of envoy/common/optional.h
5. Added “absl/types/optional.h”
Trivial changes (non-bulk):
1 . Removed tests to optional.h
2. Removed code of optional.h
Non trivial changes
1. Added conditional return to bool functions which return .valid() call for old optional
2. Included exception.h directly in shared_memory_hashset.h
3. Since cluster_impl_test expects an exception for noSdsConfig test, throwing exception code is added to cds_json.cc

@htuch
Copy link
Member

htuch commented Mar 5, 2018

@srikailash Thanks! This is a really nice cleanup. Can you get this to pass the failing CI checks? E.g. fix format, DCO, etc?

absl/types/optional.h
Signed-off-by: sri kailash <[email protected]>
@srikailash
Copy link
Contributor Author

@htuch, fixed all ci tests except format. Tried to fix it using "tools/check_format.py fix" but turns out it still fails format tests. Any other way to fix format? Thanks!

@htuch
Copy link
Member

htuch commented Mar 6, 2018

@srikailash did you run check_format under the Docker image? If not, I recommend you do, as you might have a different version of clang-format installed locally.

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, some changes to make..

@@ -789,7 +789,7 @@ void ConnectionManagerImpl::startDrainSequence() {
void ConnectionManagerImpl::ActiveStream::refreshCachedRoute() {
Router::RouteConstSharedPtr route = snapped_route_config_->route(*request_headers_, stream_id_);
request_info_.route_entry_ = route ? route->routeEntry() : nullptr;
cached_route_.value(std::move(route));
cached_route_ = (std::move(route));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get rid of the extra parens at sites like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw this coming ;). will update these things as well.

@@ -140,6 +140,9 @@ void CdsJson::translateCluster(const Json::Object& json_cluster,
cluster.set_type(envoy::api::v2::Cluster::ORIGINAL_DST);
} else {
ASSERT(string_type == "sds");
if(!eds_config.has_value()){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing spaces here...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

@@ -140,6 +140,9 @@ void CdsJson::translateCluster(const Json::Object& json_cluster,
cluster.set_type(envoy::api::v2::Cluster::ORIGINAL_DST);
} else {
ASSERT(string_type == "sds");
if(!eds_config.has_value()){
throw EnvoyException("fetching invalid Optional value");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the description you mention an new exception in retry_state_impl.cc; I don't see that, but I see this.. is this what you meant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, updated the description. Sorry about that.

@@ -171,7 +171,7 @@ class Annotation : public ZipkinBase {
/**
* @return true if the endpoint attribute is set, or false otherwise.
*/
bool isSetEndpoint() const { return endpoint_.valid(); }
bool isSetEndpoint() const { if(endpoint_){return true;} return false; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be return endpoint_.has_value();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

@htuch
Copy link
Member

htuch commented Mar 6, 2018

@jmarantz can you take a pass on this when the next patches arrive?

sri kailash added 4 commits March 6, 2018 14:09
Accoding to htuch, the local ones doesn't work because of compatability issues
between clang versions.
Signed-off-by: sri kailash <[email protected]>
Signed-off-by: sri kailash <[email protected]>
@srikailash
Copy link
Contributor Author

srikailash commented Mar 6, 2018

@htuch , @jmarantz fixed all changes requested in previous review. Apparently has_value() call timeouts for //test/integration:http2_integration_test on ci/circleci mac tests (https://circleci.com/gh/envoyproxy/envoy/30033?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link or please check last two commits). Thanks!

@htuch
Copy link
Member

htuch commented Mar 7, 2018

@srikailash the OS X timeout is a known flake, please ignore. You're going to have to merge master to resolve the conflicts, unfortunately due to the size of this PR it's going to have to be done on an ongoing basis until we merge.

Config::Utility::translateEdsConfig(
*json_sds,
*bootstrap.mutable_dynamic_resources()->mutable_deprecated_v1()->mutable_sds_config());
eds_config.value(bootstrap.dynamic_resources().deprecated_v1().sds_config());
eds_config = (bootstrap.dynamic_resources().deprecated_v1().sds_config());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still some more surplus parens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do a second pass over the changes to fix these. Thanks for the review.


/**
* @return true of the endpoint attribute has been set, or false otherwise.
*/
bool isSetEndpoint() const { return endpoint_.valid(); }
bool isSetEndpoint() const {
if (endpoint_) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume you'll replace with has_value given the comment re: OS X flake? Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, will just have to revert the last commit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one still needs fixing.

@srikailash
Copy link
Contributor Author

@htuch, i probably need some help to resolve conflicts for some files. Do you think copying file from upstream and then re-applying replacement changes would be a good idea?(I am new to big code bases). Thanks!

@jmarantz
Copy link
Contributor

jmarantz commented Mar 8, 2018

I have some general suggestions about how to make large scale refactors easier to push through.

  1. Automate the changes if you can, via clang or sed or whatever, and review -- or at least describe it in the PR description, which might be easier to review than the results of the automation.
  2. Try to make the changes incremental with every step obviously &/or proveably correct
  3. Break down the changes into a few reviewable chunks at a time, which makes it easier to push through review/merge without conflicts.

For this case, I'm not sure about suggestion 1 above. Suggestion 2 might be a lot of work if you don't do suggestion 1, but a thought here is to:

  • start by adding absl::optional's interface into Envoy's Optional class, and converting call-sites over in reviewable swaths
  • When done, remove the class and replace it with a 'using' to alias it to absl::optional (which should be a tiny change)
  • Then do one another sweep through the codebase and change all the references, so you can finally remove the alias.

Each of these changes should be much easier to review and merge without conflicts.

But at a minimum, it doesn't seem like it's necessary for you to remove the existing Optional class all at once, so you could just revert the conflicting files and do more passes later to clean them up.

@htuch
Copy link
Member

htuch commented Mar 8, 2018

@jmarantz I asked for the all-in-one PR here, as it's fairly mechanical IMHO.

@htuch
Copy link
Member

htuch commented Mar 8, 2018

Ideally you have a script to automate the sed(or the like as suggested by @jmarantz), so you should be able to either resolve conflicts or start in a new client and do this. If not, you might want to do what you suggest.

sri kailash and others added 5 commits March 10, 2018 01:42
fixed conflicts and reapplied changes on conflicting files.
Signed-off-by: sri kailash <[email protected]>
Signed-off-by: sri kailash <[email protected]>
Signed-off-by: sri kailash <[email protected]>
@@ -10,13 +10,6 @@ load(

envoy_package()

envoy_cc_fuzz_test(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @htuch, fixed merge conflicts and made sure there are no extra braces.
Adding this test gives me this error " //test/common/common:base64_fuzz_test_lib: invalid label 'base64_corpus/.!31337!favicon.ico' in element 0 of attribute 'data' in 'cc_library' rule: invalid target name 'base64_corpus/.!31337!favicon.ico': target names may not contain '!'
". Any idea how to fix this? Thanks in advance!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at your diff below, it looks like you're trying to check-in some weird stuff like test/common/common/base64_corpus/.!31337!favicon.ico. Can you git rm these from your repo and try again? We do need to preserve this target :)

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, this is a really nice cleanup. Can you look into the base64_fuzz_test isue and the remaining small comments? Hopefully can merge soon to avoid another significant set of conflict resolution at your end.

@@ -10,13 +10,6 @@ load(

envoy_package()

envoy_cc_fuzz_test(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look at your diff below, it looks like you're trying to check-in some weird stuff like test/common/common/base64_corpus/.!31337!favicon.ico. Can you git rm these from your repo and try again? We do need to preserve this target :)

@@ -140,6 +140,9 @@ void CdsJson::translateCluster(const Json::Object& json_cluster,
cluster.set_type(envoy::api::v2::Cluster::ORIGINAL_DST);
} else {
ASSERT(string_type == "sds");
if (!eds_config.has_value()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically this can be if (!eds_config) I think.

const uint64_t old_value = hash.valid() ? ((hash.value() << 1) | (hash.value() >> 63)) : 0;
hash.value(old_value ^ new_hash.value());
const uint64_t old_value = hash ? ((hash.value() << 1) | (hash.value() >> 63)) : 0;
hash = (old_value ^ new_hash.value());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: can remove parens here.

* or the HTTP status code from the route's redirect if specified,
* or an empty Option otherwise.
* @return absl::optional<Http::Code> the HTTP status from the route's direct_response if
* specified, or the HTTP status code from the route's redirect if specified, or an empty Option
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: vestigial reference to Option.


/**
* @return true of the endpoint attribute has been set, or false otherwise.
*/
bool isSetEndpoint() const { return endpoint_.valid(); }
bool isSetEndpoint() const {
if (endpoint_) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one still needs fixing.

@srikailash
Copy link
Contributor Author

@htuch , Thanks for the review. Fixed things mentioned by you.

Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this. This is really awesome. One small question from a quick skim.

@@ -140,6 +140,9 @@ void CdsJson::translateCluster(const Json::Object& json_cluster,
cluster.set_type(envoy::api::v2::Cluster::ORIGINAL_DST);
} else {
ASSERT(string_type == "sds");
if (!eds_config) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When does this happen? It seems like this should not happen due to schema checks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattklein123 , copying from what i mentioned earlier about this change.
"Since cluster_impl_test expects an exception for noSdsConfig test, throwing exception code is added to cds_json.cc." (our previous optional.h throws exception when trying to retrieve value from empty optional.)
Thanks for the review!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I guess that was a bad error message before. Since you are already in here, can you potentially change the error message to be more useful and change the test to use EXPECT_THROW_WITH_MESSAGE to check it? Thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mattklein123, fixed. please take a look. Thanks!

Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! @htuch anything else?

Copy link
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome cleanup, thanks muchly!

@htuch htuch merged commit 725a6a4 into envoyproxy:master Mar 13, 2018
@srikailash
Copy link
Contributor Author

Thanks for merging :) will pick up something else from issues now.

htuch added a commit to htuch/envoy that referenced this pull request Mar 14, 2018
Some absl::optional changes missed due to not being merged with envoyproxy#2688.

Signed-off-by: Harvey Tuch <[email protected]>
htuch added a commit that referenced this pull request Mar 14, 2018
Some absl::optional changes missed due to not being merged with #2688.

Signed-off-by: Harvey Tuch <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants