Skip to content

Commit

Permalink
add delta update class. (envoyproxy#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
qiwzhang authored Jun 6, 2017
1 parent 8100db5 commit 5e669ac
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 0 deletions.
13 changes: 13 additions & 0 deletions mixerclient/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ cc_library(
"src/cache_key_set.h",
"src/client_impl.cc",
"src/client_impl.h",
"src/delta_update.cc",
"src/delta_update.h",
"src/signature.cc",
"src/signature.h",
"src/quota_cache.cc",
Expand Down Expand Up @@ -122,6 +124,17 @@ cc_test(
],
)

cc_test(
name = "delta_update_test",
size = "small",
srcs = ["src/delta_update_test.cc"],
linkstatic = 1,
deps = [
":mixer_client_lib",
"//external:googletest_main",
],
)

cc_test(
name = "quota_cache_test",
size = "small",
Expand Down
81 changes: 81 additions & 0 deletions mixerclient/src/delta_update.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* Copyright 2017 Istio Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "src/delta_update.h"

#include <set>

namespace istio {
namespace mixer_client {
namespace {

class DeltaUpdateImpl : public DeltaUpdate {
public:
// Start a update for a request.
void Start() override {
prev_set_.clear();
for (const auto& it : prev_map_) {
prev_set_.insert(it.first);
}
}

bool Check(int index, const Attributes::Value& value) override {
bool same = false;
const auto& it = prev_map_.find(index);
if (it != prev_map_.end()) {
if (it->second.type == value.type && it->second == value) {
same = true;
}
}
if (!same) {
prev_map_[index] = value;
}
prev_set_.erase(index);
return same;
}

// "deleted" is not supported for now. If some attributes are missing,
// return false to indicate delta update is not supported.
bool Finish() override { return prev_set_.empty(); }

private:
// The remaining attributes from previous.
std::set<int> prev_set_;

// The attribute map from previous.
std::map<int, Attributes::Value> prev_map_;
};

// An optimization for non-delta update case.
class DeltaUpdateNoOpImpl : public DeltaUpdate {
public:
void Start() override {}
bool Check(int index, const Attributes::Value& value) override {
return false;
}
bool Finish() override { return true; }
};

} // namespace

std::unique_ptr<DeltaUpdate> DeltaUpdate::Create() {
return std::unique_ptr<DeltaUpdate>(new DeltaUpdateImpl);
}

std::unique_ptr<DeltaUpdate> DeltaUpdate::CreateNoOp() {
return std::unique_ptr<DeltaUpdate>(new DeltaUpdateNoOpImpl);
}

} // namespace mixer_client
} // namespace istio
57 changes: 57 additions & 0 deletions mixerclient/src/delta_update.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* Copyright 2017 Istio Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef MIXERCLIENT_DELTA_UPDATE_H
#define MIXERCLIENT_DELTA_UPDATE_H

#include "include/attribute.h"

#include <memory>

namespace istio {
namespace mixer_client {

// A class to support attribute delta update.
// It has previous attribute values and check
// for the current one.
class DeltaUpdate {
public:
virtual ~DeltaUpdate() {}

// Start a new delta update
virtual void Start() = 0;

// Check an attribute, return true if it is in the previous
// set with same value, so no need to send it again.
// Each attribute in the current set needs to call this method.
virtual bool Check(int index, const Attributes::Value& value) = 0;

// Finish a delta update.
// Return false if delta update is not supported.
// For example, "deleted" is not supported, if some attributes are
// missing, delta update will not be supported.
virtual bool Finish() = 0;

// Create an instance.
static std::unique_ptr<DeltaUpdate> Create();

// Create an no-op instance; an optimization for no delta update cases.
static std::unique_ptr<DeltaUpdate> CreateNoOp();
};

} // namespace mixer_client
} // namespace istio

#endif // MIXERCLIENT_DELTA_UPDATE_H
77 changes: 77 additions & 0 deletions mixerclient/src/delta_update_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* Copyright 2017 Istio Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "src/delta_update.h"
#include "gtest/gtest.h"

namespace istio {
namespace mixer_client {

class DeltaUpdateTest : public ::testing::Test {
public:
void SetUp() {
string_map_value_ = Attributes::StringMapValue({{"foo", "bar"}});
update_ = DeltaUpdate::Create();

update_->Start();
EXPECT_FALSE(update_->Check(1, Attributes::Int64Value(1)));
EXPECT_FALSE(update_->Check(2, Attributes::Int64Value(2)));
EXPECT_FALSE(update_->Check(3, string_map_value_));
EXPECT_TRUE(update_->Finish());
}

std::unique_ptr<DeltaUpdate> update_;
Attributes::Value string_map_value_;
};

TEST_F(DeltaUpdateTest, TestUpdateNoDelete) {
update_->Start();
// 1: value is the same.
EXPECT_TRUE(update_->Check(1, Attributes::Int64Value(1)));
// 2: value is different.
EXPECT_FALSE(update_->Check(2, Attributes::Int64Value(3)));
// 3: compare string map.
EXPECT_TRUE(update_->Check(3, string_map_value_));
// 4: an new attribute.
EXPECT_FALSE(update_->Check(4, Attributes::Int64Value(4)));
// No missing item
EXPECT_TRUE(update_->Finish());
}

TEST_F(DeltaUpdateTest, TestUpdateWithDelete) {
update_->Start();
// 1: value is the same.
EXPECT_TRUE(update_->Check(1, Attributes::Int64Value(1)));

// 2: is missing

// 3: compare string map
EXPECT_FALSE(update_->Check(3, Attributes::StringMapValue({})));

// 4: an new attribute.
EXPECT_FALSE(update_->Check(4, Attributes::Int64Value(4)));

// There is a missing item
EXPECT_FALSE(update_->Finish());
}

TEST_F(DeltaUpdateTest, TestDifferentType) {
update_->Start();
// 1 is differnt type.
EXPECT_FALSE(update_->Check(1, Attributes::StringValue("")));
}

} // namespace mixer_client
} // namespace istio

0 comments on commit 5e669ac

Please sign in to comment.