Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a95f443
Add "life span" concept to FilterState and use it for sharing
penguingao Dec 3, 2019
6323439
Add test for FilterState::CopyInto
penguingao Dec 3, 2019
33bc63d
Fix format and comment.
penguingao Dec 3, 2019
4999df4
Fix comment and format.
penguingao Dec 3, 2019
125cc54
Add default life_span value to FilterStateImpl as well since tests use
penguingao Dec 3, 2019
4683ed5
Kick CI
penguingao Dec 3, 2019
ce7306c
data_ is a shared_ptr.
penguingao Dec 4, 2019
f76d532
Remove default parameter for life_span in FilterState::setData to let
penguingao Dec 4, 2019
84ea166
Fix more test.
penguingao Dec 4, 2019
08f1ed0
Revert to use default parameters
penguingao Dec 5, 2019
793d942
Add LifeSpan::DownstreamConnection to StreamInfo::FilterState.
penguingao Dec 5, 2019
7f2ee27
Merge remote-tracking branch 'upstream/master' into filter-state
penguingao Dec 5, 2019
30ec74b
Merge branch 'filter-state' of github.com:penguingao/envoy into
penguingao Dec 5, 2019
72ed2b9
Add default parameter back to FilterStateImpl::setData
penguingao Dec 5, 2019
82931b4
Fix tests.
penguingao Dec 5, 2019
f83f449
Fix tests.
penguingao Dec 5, 2019
10b6560
More test...
penguingao Dec 5, 2019
80f45cb
filter_state_ needs to be always initialized in StreamInfoImpl.
penguingao Dec 5, 2019
666e852
Resolve comments:
penguingao Dec 6, 2019
72a5f8a
Resolve comment:
penguingao Dec 6, 2019
4531b69
Resolve comment:
penguingao Dec 6, 2019
022aa74
Fix format.
penguingao Dec 6, 2019
ed32ced
Fix build.
penguingao Dec 6, 2019
25a79a2
Merge remote-tracking branch 'upstream/master' into filter-state
penguingao Dec 6, 2019
afcbaa7
Fix format.
penguingao Dec 6, 2019
4c10770
Fix some comment and make filter_state_ in conn_manager_impl not created
penguingao Dec 9, 2019
9282aea
Address comments:
penguingao Dec 9, 2019
3a590a1
Kick CI
penguingao Dec 9, 2019
dd7cde5
Address comments:
penguingao Dec 10, 2019
868ea9e
Merge remote-tracking branch 'upstream/master' into filter-state
penguingao Dec 10, 2019
1987d25
Address comments:
penguingao Dec 11, 2019
3f85eb7
Make tests also call FilterState::setData with correct LifeSpan for n…
penguingao Dec 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions include/envoy/stream_info/filter_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ namespace StreamInfo {
class FilterState {
public:
enum class StateType { ReadOnly, Mutable };
// When internal redirect is enabled, one downstream request may create multiple filter chains.
Comment thread
penguingao marked this conversation as resolved.
Outdated
// DownstreamRequest allows an object to survived across filter chain for book keeping.
// Note that order matters in this enum because it's assumed that life span grows as enum number
// grows.
enum class LifeSpan { FilterChain, DownstreamRequest };

class Object {
public:
Expand All @@ -41,6 +46,8 @@ class FilterState {
* @param data_name the name of the data being set.
* @param data an owning pointer to the data to be stored.
* @param state_type indicates whether the object is mutable or not.
* @param life_span indicates the life span of the object: bound to the filter chain or a
* downstream request.
*
* Note that it is an error to call setData() twice with the same
* data_name, if the existing object is immutable. Similarly, it is an
Expand All @@ -49,8 +56,21 @@ class FilterState {
* single authoritative source for each piece of immutable data stored in
* FilterState.
*/
virtual void setData(absl::string_view data_name, std::unique_ptr<Object>&& data,
StateType state_type) PURE;
virtual void setData(absl::string_view data_name, std::shared_ptr<Object> data,
StateType state_type, LifeSpan life_span = LifeSpan::FilterChain) PURE;
Comment thread
penguingao marked this conversation as resolved.

/**
* @param other the FilterState we want to copy current data into.
* @param life_span the object life span above or equal to which will be copied.
*
* This is useful for sharing filter state within bigger life span than a filter chain. For
* example, we are going to use it to share router filter state across filter chains created on
* the same downstream request for internal redirect handling.
*
* This can be extended to support connection level sharing fairly easily, but there is not a need
* yet.
*/
virtual void copyInto(FilterState& other, LifeSpan life_span) PURE;

/**
* @param data_name the name of the data being looked up (mutable/readonly).
Expand Down
5 changes: 5 additions & 0 deletions source/common/http/conn_manager_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "envoy/router/router.h"
#include "envoy/ssl/connection.h"
#include "envoy/stats/scope.h"
#include "envoy/stream_info/filter_state.h"
#include "envoy/tracing/http_tracer.h"

#include "common/buffer/buffer_impl.h"
Expand Down Expand Up @@ -2220,6 +2221,10 @@ bool ConnectionManagerImpl::ActiveStreamDecoderFilter::recreateStream() {
parent_.connection_manager_.doEndStream(this->parent_);

StreamDecoder& new_stream = parent_.connection_manager_.newStream(*response_encoder, true);
parent_.stream_info_.filterState().copyInto(
(*parent_.connection_manager_.streams_.begin())->stream_info_.filterState(),
StreamInfo::FilterState::LifeSpan::DownstreamRequest);

new_stream.decodeHeaders(std::move(request_headers), true);
return true;
}
Expand Down
14 changes: 12 additions & 2 deletions source/common/stream_info/filter_state_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
namespace Envoy {
namespace StreamInfo {

void FilterStateImpl::setData(absl::string_view data_name, std::unique_ptr<Object>&& data,
FilterState::StateType state_type) {
void FilterStateImpl::setData(absl::string_view data_name, std::shared_ptr<Object> data,
Comment thread
penguingao marked this conversation as resolved.
FilterState::StateType state_type, FilterState::LifeSpan life_span) {
const auto& it = data_storage_.find(data_name);
if (it != data_storage_.end()) {
// We have another object with same data_name. Check for mutability
Expand All @@ -25,9 +25,19 @@ void FilterStateImpl::setData(absl::string_view data_name, std::unique_ptr<Objec
std::unique_ptr<FilterStateImpl::FilterObject> filter_object(new FilterStateImpl::FilterObject());
filter_object->data_ = std::move(data);
filter_object->state_type_ = state_type;
filter_object->life_span_ = life_span;
Comment thread
penguingao marked this conversation as resolved.
Outdated
data_storage_[data_name] = std::move(filter_object);
}

void FilterStateImpl::copyInto(FilterState& other, LifeSpan life_span) {
for (const auto& filter_object : data_storage_) {
if (filter_object.second->life_span_ >= life_span) {
other.setData(filter_object.first, filter_object.second->data_,
filter_object.second->state_type_, filter_object.second->life_span_);
}
}
}

bool FilterStateImpl::hasDataWithName(absl::string_view data_name) const {
return data_storage_.count(data_name) > 0;
}
Expand Down
9 changes: 6 additions & 3 deletions source/common/stream_info/filter_state_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ namespace StreamInfo {
class FilterStateImpl : public FilterState {
public:
// FilterState
void setData(absl::string_view data_name, std::unique_ptr<Object>&& data,
FilterState::StateType state_type) override;
void setData(absl::string_view data_name, std::shared_ptr<Object> data,
FilterState::StateType state_type,
FilterState::LifeSpan life_span = FilterState::LifeSpan::FilterChain) override;
void copyInto(FilterState& other, FilterState::LifeSpan life_span) override;
bool hasDataWithName(absl::string_view) const override;
const Object* getDataReadOnlyGeneric(absl::string_view data_name) const override;
Object* getDataMutableGeneric(absl::string_view data_name) override;

private:
struct FilterObject {
std::unique_ptr<Object> data_;
std::shared_ptr<Object> data_;
FilterState::StateType state_type_;
FilterState::LifeSpan life_span_;
};

absl::flat_hash_map<std::string, std::unique_ptr<FilterObject>> data_storage_;
Expand Down
40 changes: 40 additions & 0 deletions test/common/stream_info/filter_state_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -239,5 +239,45 @@ TEST_F(FilterStateImplTest, HasData) {
EXPECT_FALSE(filter_state().hasDataWithName("test_2"));
}

TEST_F(FilterStateImplTest, LifeSpan) {
filter_state().setData("test_1", std::make_unique<SimpleType>(1),
FilterState::StateType::ReadOnly);
filter_state().setData("test_2", std::make_unique<SimpleType>(2),
FilterState::StateType::Mutable);
filter_state().setData("test_3", std::make_unique<SimpleType>(3),
FilterState::StateType::ReadOnly,
FilterState::LifeSpan::DownstreamRequest);
filter_state().setData("test_4", std::make_unique<SimpleType>(4), FilterState::StateType::Mutable,
FilterState::LifeSpan::DownstreamRequest);
{
FilterStateImpl new_filter_state;
filter_state().copyInto(new_filter_state, FilterState::LifeSpan::DownstreamRequest);
EXPECT_FALSE(new_filter_state.hasDataWithName("test_1"));
EXPECT_FALSE(new_filter_state.hasDataWithName("test_2"));
EXPECT_TRUE(new_filter_state.hasDataWithName("test_3"));
EXPECT_TRUE(new_filter_state.hasDataWithName("test_4"));
EXPECT_THROW_WITH_MESSAGE(
new_filter_state.getDataMutable<SimpleType>("test_3"), EnvoyException,
"FilterState::getDataMutable<T> tried to access immutable data as mutable.");
EXPECT_EQ(4, new_filter_state.getDataMutable<SimpleType>("test_4").access());
}
{
FilterStateImpl new_filter_state;
filter_state().copyInto(new_filter_state, FilterState::LifeSpan::FilterChain);
EXPECT_TRUE(new_filter_state.hasDataWithName("test_1"));
EXPECT_TRUE(new_filter_state.hasDataWithName("test_2"));
EXPECT_TRUE(new_filter_state.hasDataWithName("test_3"));
EXPECT_TRUE(new_filter_state.hasDataWithName("test_4"));
EXPECT_THROW_WITH_MESSAGE(
new_filter_state.getDataMutable<SimpleType>("test_1"), EnvoyException,
"FilterState::getDataMutable<T> tried to access immutable data as mutable.");
EXPECT_EQ(2, new_filter_state.getDataMutable<SimpleType>("test_2").access());
EXPECT_THROW_WITH_MESSAGE(
new_filter_state.getDataMutable<SimpleType>("test_3"), EnvoyException,
"FilterState::getDataMutable<T> tried to access immutable data as mutable.");
EXPECT_EQ(4, new_filter_state.getDataMutable<SimpleType>("test_4").access());
}
}

} // namespace StreamInfo
} // namespace Envoy