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

Context api content: Linked list implementation #14

Open
wants to merge 105 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
7867296
demo context header
satac2 Jun 8, 2020
d5a360a
demo context header
satac2 Jun 8, 2020
5d3b713
added file threadlocal_context.h
satac2 Jun 8, 2020
d047ff7
added fixes
satac2 Jun 8, 2020
f283cc6
Fixed syntatical errors, moved token class definition to context.h an…
satac2 Jun 8, 2020
e1de13f
Update api/include/opentelemetry/context/context.h
satac2 Jun 8, 2020
d5b155d
changed define guards and minor syntactical changes
satac2 Jun 8, 2020
80b2332
removing context vars class
satac2 Jun 8, 2020
64cd1c2
Merge branch 'context_api' of github.com:satac2/opentelemetry-cpp int…
satac2 Jun 8, 2020
4d24115
removed threadlocal context and made the runtime context methods static
satac2 Jun 8, 2020
a17c028
removed threadlocal context and made the runtime context methods static
satac2 Jun 8, 2020
d2df2ac
added a constructor
satac2 Jun 8, 2020
c316636
fixed convention issue and removed unnecessary code
satac2 Jun 8, 2020
7b36945
Update context.h
satac2 Jun 8, 2020
8e02c07
Update context.h
satac2 Jun 8, 2020
115cd68
context implementation
satac2 Jun 10, 2020
0d9fea1
Adding tests
satac2 Jun 10, 2020
565c40e
Adding tests
satac2 Jun 10, 2020
2d4a411
renamed some variables, added tests
satac2 Jun 10, 2020
9874c4c
renamed some variables, added tests
satac2 Jun 10, 2020
7bceaab
Merge branch 'context_api' into context_api_content
satac2 Jun 10, 2020
061e564
reversed public/private order
satac2 Jun 10, 2020
b5c81ad
Merge branch 'context_api_content' of github.com:satac2/opentelemetry…
satac2 Jun 10, 2020
b2717b3
Added detach test
satac2 Jun 10, 2020
b7259cd
avoiding standard datastructures
satac2 Jun 11, 2020
34eacf2
replaced std::map and created a thread_local context
satac2 Jun 17, 2020
a086993
replaced std::map and created a thread_local context
satac2 Jun 17, 2020
e44e926
cleaned up
satac2 Jun 17, 2020
6edce29
cleaned up
satac2 Jun 17, 2020
dff6f8f
fixed undefined behavior in context.h
satac2 Jun 20, 2020
e660ab7
minor style
satac2 Jun 21, 2020
aec8ca8
style
satac2 Jun 21, 2020
605cb75
added tests and comparison operator to the context api
satac2 Jun 22, 2020
e4d3069
auto formatted
satac2 Jun 22, 2020
786f8a6
style changes
satac2 Jun 24, 2020
62b0c88
added nostd::list and nostd::pair
satac2 Jun 24, 2020
9c39536
ran auto formatter
satac2 Jun 24, 2020
92f8bb7
Merge pull request #9 from satac2/list_and_pair
satac2 Jun 24, 2020
4f39935
Merge branch 'context_api_content' of github.com:satac2/opentelemetry…
satac2 Jun 24, 2020
821bfb4
added tests to build file
satac2 Jun 24, 2020
25813c8
Added tests, removed unnecessary code and simplified things
satac2 Jun 25, 2020
ec12e39
added assignment tests for pair and comparison test for pair
satac2 Jun 25, 2020
7ac58e2
moved some delete statements
satac2 Jun 25, 2020
cf403b7
fixed memory leak in list and pair
satac2 Jun 26, 2020
09b0d50
fixed list comparison error
satac2 Jun 26, 2020
6979e81
minor test
satac2 Jun 28, 2020
6b75dec
Merge pull request #10 from satac2/list_and_pair
satac2 Jun 28, 2020
e91e0fe
Merge branch 'context_api_content' of github.com:satac2/opentelemetry…
satac2 Jun 28, 2020
0f870e0
added CMakeLists.txt to context folder
satac2 Jun 28, 2020
3593653
added linked list implementation
satac2 Jul 7, 2020
67a7978
fixed cmake file
satac2 Jul 7, 2020
cab9bc9
removed files
satac2 Jul 7, 2020
6bf0821
Added internal constructors and functions to context.h, and well as m…
satac2 Jul 15, 2020
ada7c68
Added context_value.h
satac2 Jul 15, 2020
134d6b4
Temp removing files.
satac2 Jul 15, 2020
00aee4c
temp removed more files to pare down PR
satac2 Jul 15, 2020
9a42949
re-adding CMakeLists.txt
satac2 Jul 15, 2020
d8432dd
removed old includes
satac2 Jul 15, 2020
00ed02a
fixed destruction, disallowed copying and add DataList constructors
satac2 Jul 15, 2020
d3d6b30
Stylistic changes
satac2 Jul 15, 2020
5c59f5c
Stylistic changes
satac2 Jul 15, 2020
ac8503f
added copy and assignment constructors
satac2 Jul 15, 2020
9125477
adding tests
satac2 Jul 16, 2020
80bf695
style change
satac2 Jul 16, 2020
9d3d643
Update api/include/opentelemetry/context/context.h
satac2 Jul 16, 2020
4781d74
added context CMakeLists.txt
satac2 Jul 17, 2020
7d0a145
fixed minor context.h error, updated tests CMakeLists.txt to contain …
satac2 Jul 17, 2020
a4d9b73
Merge branch 'context_api_content' of github.com:satac2/opentelemetry…
satac2 Jul 17, 2020
ea288a5
eliminated memory leaks and added abstraction for stability, also mod…
satac2 Jul 20, 2020
0f1d485
auto formatted
satac2 Jul 20, 2020
3b922a5
fixed pull request error
satac2 Jul 20, 2020
39941d3
SpanContext should be found now
satac2 Jul 20, 2020
e1f2cfa
fixed Cmake test failure
satac2 Jul 20, 2020
f4e2718
should fix the cmake error
satac2 Jul 20, 2020
f1f2480
removing warnings
satac2 Jul 20, 2020
ce6d9fa
avoiding strncpy
satac2 Jul 20, 2020
c7cbb21
initialized shared_ptr
satac2 Jul 20, 2020
f2542fd
removed getValue to try and pass tests
satac2 Jul 20, 2020
ba9da8e
restricted GetValue
satac2 Jul 20, 2020
a9c4eea
now deferencing shared_ptr
satac2 Jul 20, 2020
a7fbbd0
formatted
satac2 Jul 20, 2020
dd3f297
shared Datalist instead of context list
satac2 Jul 20, 2020
8292012
one long list
satac2 Jul 20, 2020
7534cbc
updated some comments
satac2 Jul 20, 2020
c925962
removed unnecessary complexity from SetValue
satac2 Jul 20, 2020
b2e53b2
auto formatted
satac2 Jul 20, 2020
067e7dd
stylistic changes updated ContextValue, add HasKey method
satac2 Jul 21, 2020
8396792
removed reference to span_context.h
satac2 Jul 21, 2020
86b032c
explicit conversion to contextValue in tests
satac2 Jul 21, 2020
f78ab74
explicit type case in tests
satac2 Jul 21, 2020
77c4c9a
added nostd::shared_ptr<SpanContext> to ContextValue
satac2 Jul 21, 2020
f63d595
removed span_context.h include, so tests would pass, not sure why
satac2 Jul 21, 2020
5f25cf1
readded span_context.h
satac2 Jul 21, 2020
86eacca
re-added span_context include
satac2 Jul 21, 2020
7a2ea4c
testing for the include failure
satac2 Jul 21, 2020
961f7ed
removed key_value_iterable_include
satac2 Jul 21, 2020
4358d35
removed unncessary shared_ptr during iteration
satac2 Jul 21, 2020
c5f6c08
Merge branch 'master' into context_api_content
satac2 Jul 21, 2020
80cbb96
added shared_ptr<trace::SpanContext> to context_value
satac2 Jul 21, 2020
896bc45
Merge remote-tracking branch 'origin/master' into context_api_content
satac2 Jul 21, 2020
feb3f17
added shared_ptr<SpanContext> and include
satac2 Jul 21, 2020
acffb61
Merge branch 'context_api_content' of github.com:satac2/opentelemetry…
satac2 Jul 21, 2020
bf94af8
simplifications
satac2 Jul 21, 2020
5eddd2f
removed unecessary includes
satac2 Jul 21, 2020
78bd8a6
Merge branch 'master' into context_api_content
reyang Jul 21, 2020
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
Empty file.
166 changes: 166 additions & 0 deletions api/include/opentelemetry/context/context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#pragma once

#include "opentelemetry/context/context_value.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace context
{

// The context class provides a context identifier. Is built as a linked list
// of DataList nodes and each context holds a shared_ptr to a place within
// the list that determines which keys and values it has access to. All that
// come before and none that come after.
class Context
{

public:
// Creates a context object from a map of keys and identifiers, this will
// hold a shared_ptr to the head of the DataList linked list
template <class T>
Context(const T &keys_and_values)
{
head_ = nostd::shared_ptr<DataList>{new DataList(keys_and_values)};
}

// Creates a context object from a key and value, this will
// hold a shared_ptr to the head of the DataList linked list
Context(nostd::string_view key, ContextValue value)
{
head_ = nostd::shared_ptr<DataList>{new DataList(key, value)};
}

// Accepts a new iterable and then returns a new context that
// contains the new key and value data. It attaches the
// exisiting list to the end of the new list.
template <class T>
Context SetValues(T &values) noexcept
{
Context context = Context(values);
nostd::shared_ptr<DataList> &last = context.head_;
while (last->next_ != nullptr)
{
last = last->next_;
}
last->next_ = head_;
return context;
}

// Accepts a new iterable and then returns a new context that
// contains the new key and value data. It attaches the
// exisiting list to the end of the new list.
Context SetValue(nostd::string_view key, ContextValue value) noexcept
{
Context context = Context(key, value);
context.head_->next_ = head_;
return context;
}

// Returns the value associated with the passed in key.
context::ContextValue GetValue(const nostd::string_view key) noexcept
{
for (DataList *data = head_.get(); data != nullptr; data = data->next_.get())
{
if (key.size() == data->key_length_)
{
if (memcmp(key.data(), data->key_, data->key_length_) == 0)
{
return data->value_;
}
}
}
return (int64_t)0;
}

// Checks for key and returns true if found
bool HasKey(const nostd::string_view key) noexcept
{
for (DataList *data = head_.get(); data != nullptr; data = data->next_.get())
{
if (key.size() == data->key_length_)
{
if (memcmp(key.data(), data->key_, data->key_length_) == 0)
{
return true;
}
}
}
return false;
}

private:
Context() = default;

// A linked list to contain the keys and values of this context node
class DataList
{
public:
nostd::shared_ptr<DataList> next_;

char *key_;

size_t key_length_;

ContextValue value_;

DataList() { next_ = nullptr; }

// Builds a data list off of a key and value iterable and returns the head
template <class T>
DataList(const T &keys_and_vals) : key_{nullptr}
{
bool first = true;
auto *node = this;
for (auto &iter : keys_and_vals)
{
if (first)
{
*node = std::move(DataList(iter.first, iter.second));
first = false;
}
else
{
node->next_ = nostd::shared_ptr<DataList>(new DataList(iter.first, iter.second));
node = node->next_.get();
}
}
}

// Builds a data list with just a key and value, so it will just be the head
// and returns that head.
DataList(nostd::string_view key, ContextValue value)
{
key_ = new char[key.size()];
key_length_ = key.size();
memcpy(key_, key.data(), key.size() * sizeof(char));
value_ = value;
next_ = nostd::shared_ptr<DataList>{nullptr};
}

DataList &operator=(DataList &&other)
{
key_length_ = other.key_length_;
value_ = std::move(other.value_);
next_ = std::move(other.next_);

key_ = other.key_;
other.key_ = nullptr;

return *this;
}

~DataList()
{
if (key_ != nullptr)
{
delete[] key_;
}
}
};

// Head of the list which holds the keys and values of this context
nostd::shared_ptr<DataList> head_;
};
} // namespace context
OPENTELEMETRY_END_NAMESPACE
18 changes: 18 additions & 0 deletions api/include/opentelemetry/context/context_value.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include <cstdint>

#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/trace/span_context.h"
#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace context
{
using ContextValue =
nostd::variant<bool, int64_t, uint64_t, double, nostd::shared_ptr<trace::SpanContext>>;
} // namespace context
OPENTELEMETRY_END_NAMESPACE
1 change: 1 addition & 0 deletions api/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_subdirectory(core)
add_subdirectory(context)
add_subdirectory(plugin)
add_subdirectory(nostd)
add_subdirectory(trace)
Expand Down
12 changes: 12 additions & 0 deletions api/test/context/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark")

cc_test(
name = "context_test",
srcs = [
"context_test.cc",
],
deps = [
"//api",
"@com_google_googletest//:gtest_main",
],
)
8 changes: 8 additions & 0 deletions api/test/context/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
include(GoogleTest)

foreach(testname context_test)
add_executable(${testname} "${testname}.cc")
target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} opentelemetry_api)
gtest_add_tests(TARGET ${testname} TEST_PREFIX context. TEST_LIST ${testname})
endforeach()
120 changes: 120 additions & 0 deletions api/test/context/context_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include "opentelemetry/context/context.h"

#include <map>

#include <gtest/gtest.h>

using namespace opentelemetry;

// Tests that the context constructor accepts an std::map.
TEST(ContextTest, ContextIterableAcceptsMap)
{
std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
context::Context test_context = context::Context(map_test);
}

// Tests that the GetValue method returns the expected value.
TEST(ContextTest, ContextGetValueReturnsExpectedValue)
{
std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123},
{"foo_key", (int64_t)456}};
context::Context test_context = context::Context(map_test);
EXPECT_EQ(nostd::get<int64_t>(test_context.GetValue("test_key")), 123);
EXPECT_EQ(nostd::get<int64_t>(test_context.GetValue("foo_key")), 456);
}

// Tests that the SetValues method accepts an std::map.
TEST(ContextTest, ContextSetValuesAcceptsMap)
{
std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
std::map<std::string, context::ContextValue> map_test_write = {{"foo_key", (int64_t)456}};

context::Context test_context = context::Context(map_test);
context::Context foo_context = test_context.SetValues(map_test_write);

EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("test_key")), 123);
EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("foo_key")), 456);
}

// Tests that the SetValues method accepts a nostd::string_view and
// context::ContextValue.
TEST(ContextTest, ContextSetValuesAcceptsStringViewContextValue)
{
nostd::string_view string_view_test = "string_view";
context::ContextValue context_value_test = (int64_t)123;

context::Context test_context = context::Context(string_view_test, context_value_test);
context::Context foo_context = test_context.SetValue(string_view_test, context_value_test);

EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue(string_view_test)), 123);
}

// Tests that the original context does not change when a value is
// written to it.
TEST(ContextTest, ContextImmutability)
{
std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};

context::Context context_test = context::Context(map_test);
context::Context context_foo = context_test.SetValue("foo_key", (int64_t)456);

EXPECT_NE(nostd::get<int64_t>(context_test.GetValue("foo_key")), 456);
}

// Tests that writing the same to a context overwrites the original value.
TEST(ContextTest, ContextKeyOverwrite)
{
std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};

context::Context context_test = context::Context(map_test);
context::Context context_foo = context_test.SetValue("test_key", (int64_t)456);

EXPECT_EQ(nostd::get<int64_t>(context_foo.GetValue("test_key")), 456);
}

// Tests that the new Context Objects inherits the keys and values
// of the original context object.
TEST(ContextTest, ContextInheritance)
{
using M = std::map<std::string, context::ContextValue>;

M m1 = {{"test_key", (int64_t)123}, {"foo_key", (int64_t)456}};
M m2 = {{"other_key", (int64_t)789}};

context::Context test_context = context::Context(m1);
context::Context foo_context = test_context.SetValues(m2);

EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("test_key")), 123);
EXPECT_EQ(nostd::get<int64_t>(foo_context.GetValue("foo_key")), 456);
}

// Tests that copying a context copies the key value pairs as expected.
TEST(ContextTest, ContextCopyOperator)
{
std::map<std::string, context::ContextValue> test_map = {
{"test_key", (int64_t)123}, {"foo_key", (int64_t)456}, {"other_key", (int64_t)789}};

context::Context test_context = context::Context(test_map);
context::Context copied_context = test_context;

EXPECT_EQ(nostd::get<int64_t>(copied_context.GetValue("test_key")), 123);
EXPECT_EQ(nostd::get<int64_t>(copied_context.GetValue("foo_key")), 456);
EXPECT_EQ(nostd::get<int64_t>(copied_context.GetValue("other_key")), 789);
}

// Tests that the Context accepts an empty map.
TEST(ContextTest, ContextEmptyMap)
{
std::map<std::string, context::ContextValue> map_test = {};
context::Context test_context = context::Context(map_test);
}

// Tests that if a key exists within a context has key will return true
// false if not.
TEST(ContextTest, ContextHasKey)
{
std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
context::Context context_test = context::Context(map_test);
EXPECT_TRUE(context_test.HasKey("test_key"));
EXPECT_FALSE(context_test.HasKey("foo_key"));
}