diff options
Diffstat (limited to 'vespalib')
8 files changed, 314 insertions, 1 deletions
diff --git a/vespalib/src/tests/trace/.gitignore b/vespalib/src/tests/trace/.gitignore index 51b4ee1aef8..420e2121bba 100644 --- a/vespalib/src/tests/trace/.gitignore +++ b/vespalib/src/tests/trace/.gitignore @@ -1,4 +1,4 @@ .depend Makefile -trace_test vespalib_trace_test_app +vespalib_trace_serialization_test_app diff --git a/vespalib/src/tests/trace/CMakeLists.txt b/vespalib/src/tests/trace/CMakeLists.txt index c87c3f1b3a8..f719222835e 100644 --- a/vespalib/src/tests/trace/CMakeLists.txt +++ b/vespalib/src/tests/trace/CMakeLists.txt @@ -6,3 +6,11 @@ vespa_add_executable(vespalib_trace_test_app TEST vespalib ) vespa_add_test(NAME vespalib_trace_test_app COMMAND vespalib_trace_test_app) + +vespa_add_executable(staging_vespalib_trace_serialization_test_app TEST + SOURCES + trace_serialization.cpp + DEPENDS + vespalib +) +vespa_add_test(NAME staging_vespalib_trace_serialization_test_app COMMAND staging_vespalib_trace_serialization_test_app) diff --git a/vespalib/src/tests/trace/trace_serialization.cpp b/vespalib/src/tests/trace/trace_serialization.cpp new file mode 100644 index 00000000000..a7896d43338 --- /dev/null +++ b/vespalib/src/tests/trace/trace_serialization.cpp @@ -0,0 +1,110 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/fastos/fastos.h> +#include <vespa/log/log.h> +LOG_SETUP("trace_test"); +#include <vespa/vespalib/testkit/test_kit.h> +#include <vespa/vespalib/trace/tracenode.h> +#include <vespa/vespalib/trace/slime_trace_serializer.h> +#include <vespa/vespalib/trace/slime_trace_deserializer.h> + +using namespace vespalib; +using namespace vespalib::slime; + +TEST("that a single trace node is serialized") { + TraceNode node; + Slime slime; + SlimeTraceSerializer serializer(slime.setObject()); + node.accept(serializer); + Inspector & i(slime.get()); + EXPECT_TRUE(i["timestamp"].valid()); + EXPECT_EQUAL(0l, i["timestamp"].asLong()); + EXPECT_FALSE(i["payload"].valid()); +} + +TEST("that a trace node with children is serialized") { + TraceNode node; + node.addChild("foo", 1234); + node.addChild("bar", 1235); + Slime slime; + SlimeTraceSerializer serializer(slime.setObject()); + node.accept(serializer); + Inspector & i(slime.get()); + EXPECT_TRUE(i["timestamp"].valid()); + EXPECT_EQUAL(0l, i["timestamp"].asLong()); + EXPECT_TRUE(i["children"].valid()); + Inspector & iBar(i["children"][0]); + Inspector & iFoo(i["children"][1]); + EXPECT_TRUE(iFoo.valid()); + EXPECT_TRUE(iBar.valid()); + EXPECT_EQUAL(1234, iFoo["timestamp"].asLong()); + EXPECT_EQUAL("foo", iFoo["payload"].asString().make_string()); + EXPECT_EQUAL(1235, iBar["timestamp"].asLong()); + EXPECT_EQUAL("bar", iBar["payload"].asString().make_string()); +} + +TEST("that an empty root trace node can be deserialized") { + Slime slime; + Cursor & root(slime.setObject()); + SlimeTraceDeserializer deserializer(root); + TraceNode node(deserializer.deserialize()); + EXPECT_FALSE(node.hasNote()); + EXPECT_EQUAL(0, node.getTimestamp()); +} + + +TEST("that a single trace node can be deserialized") { + Slime slime; + Cursor & root(slime.setObject()); + root.setLong("timestamp", 1234); + root.setString("payload", "hello"); + SlimeTraceDeserializer deserializer(root); + TraceNode node(deserializer.deserialize()); + EXPECT_EQUAL(1234, node.getTimestamp()); + EXPECT_TRUE(node.hasNote()); + EXPECT_EQUAL("hello", node.getNote()); +} + +TEST("that a trace node with children can be deserialized") { + Slime slime; + Cursor & root(slime.setObject()); + Cursor & rootChildren(root.setArray("children")); + Cursor & foo(rootChildren.addObject()); + foo.setLong("timestamp", 123); + Cursor &fooArray(foo.setArray("children")); + Cursor &foobar(fooArray.addObject()); + foobar.setLong("timestamp", 45); + foobar.setString("payload", "world"); + Cursor & bar(rootChildren.addObject()); + bar.setLong("timestamp", 67); + bar.setString("payload", "!"); + + vespalib::slime::SimpleBuffer buf; + vespalib::slime::JsonFormat::encode(slime, buf, false); + + SlimeTraceDeserializer deserializer(root); + TraceNode node(deserializer.deserialize()); + EXPECT_FALSE(node.hasNote()); + ASSERT_EQUAL(2u, node.getNumChildren()); + TraceNode fooNode(node.getChild(0)); + ASSERT_EQUAL(1u, fooNode.getNumChildren()); + TraceNode fooBarNode(fooNode.getChild(0)); + EXPECT_EQUAL("world", fooBarNode.getNote()); + TraceNode barNode(node.getChild(1)); + EXPECT_EQUAL("!", barNode.getNote()); + ASSERT_EQUAL(0u, barNode.getNumChildren()); +} + +TEST("test serialization and deserialization") { + TraceNode root; + root.addChild("foo", 45); + root.addChild("bar"); + root.addChild(TraceNode()); + Slime slime; + SlimeTraceSerializer s(slime.setObject()); + root.accept(s); + SlimeTraceDeserializer d(slime.get()); + TraceNode root2(d.deserialize()); + ASSERT_EQUAL(3u, root2.getNumChildren()); +} + +TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespalib/src/vespa/vespalib/trace/CMakeLists.txt b/vespalib/src/vespa/vespalib/trace/CMakeLists.txt index d114ed4d953..87cd9428494 100644 --- a/vespalib/src/vespa/vespalib/trace/CMakeLists.txt +++ b/vespalib/src/vespa/vespalib/trace/CMakeLists.txt @@ -3,5 +3,7 @@ vespa_add_library(vespalib_vespalib_trace OBJECT SOURCES trace.cpp tracenode.cpp + slime_trace_serializer.cpp + slime_trace_deserializer.cpp DEPENDS ) diff --git a/vespalib/src/vespa/vespalib/trace/slime_trace_deserializer.cpp b/vespalib/src/vespa/vespalib/trace/slime_trace_deserializer.cpp new file mode 100644 index 00000000000..fc28dfbb40b --- /dev/null +++ b/vespalib/src/vespa/vespalib/trace/slime_trace_deserializer.cpp @@ -0,0 +1,68 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/vespalib/trace/slime_trace_deserializer.h> +#include <vespa/vespalib/trace/slime_trace_serializer.h> +#include <vespa/vespalib/trace/tracenode.h> + +using namespace vespalib::slime; + +namespace vespalib { + +SlimeTraceDeserializer::SlimeTraceDeserializer(const Inspector & inspector) + : _inspector(inspector) +{ +} + +TraceNode +SlimeTraceDeserializer::deserialize() const +{ + return deserialize(_inspector); +} + +TraceNode +SlimeTraceDeserializer::deserialize(const Inspector & inspector) +{ + TraceNode node(deserializeTraceNode(inspector)); + deserializeChildren(inspector[SlimeTraceSerializer::CHILDREN], node); + return node; +} + +TraceNode +SlimeTraceDeserializer::deserializeTraceNode(const Inspector & inspector) +{ + int64_t timestamp(decodeTimestamp(inspector)); + if (hasPayload(inspector)) { + std::string note(decodePayload(inspector)); + return TraceNode(note, timestamp); + } + return TraceNode(timestamp); +} + +bool +SlimeTraceDeserializer::hasPayload(const Inspector & inspector) +{ + return inspector[SlimeTraceSerializer::PAYLOAD].valid(); +} + +vespalib::string +SlimeTraceDeserializer::decodePayload(const Inspector & inspector) +{ + return inspector[SlimeTraceSerializer::PAYLOAD].asString().make_string(); +} + +int64_t +SlimeTraceDeserializer::decodeTimestamp(const Inspector & inspector) +{ + return inspector[SlimeTraceSerializer::TIMESTAMP].asLong(); +} + +void +SlimeTraceDeserializer::deserializeChildren(const Inspector & inspector, TraceNode & node) +{ + for (size_t i(0); i < inspector.children(); i++) { + Inspector & child(inspector[i]); + TraceNode childNode(deserialize(child)); + node.addChild(childNode); + } +} + +} diff --git a/vespalib/src/vespa/vespalib/trace/slime_trace_deserializer.h b/vespalib/src/vespa/vespalib/trace/slime_trace_deserializer.h new file mode 100644 index 00000000000..dc8c6dc5cff --- /dev/null +++ b/vespalib/src/vespa/vespalib/trace/slime_trace_deserializer.h @@ -0,0 +1,31 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include <vespa/vespalib/data/slime/slime.h> +#include <vespa/vespalib/stllike/string.h> +#include <stack> + +namespace vespalib { + +class TraceNode; + +/** + * For deserializing a TraceNode and its children. Note that the ordering of nodes + * are NOT guaranteed. + */ +class SlimeTraceDeserializer +{ +public: + SlimeTraceDeserializer(const slime::Inspector & inspector); + TraceNode deserialize() const; +private: + static TraceNode deserialize(const slime::Inspector & inspector); + static TraceNode deserializeTraceNode(const slime::Inspector & inspector); + static void deserializeChildren(const slime::Inspector & inspector, TraceNode & node); + static bool hasPayload(const slime::Inspector & inspector); + static int64_t decodeTimestamp(const slime::Inspector & inspector); + static vespalib::string decodePayload(const slime::Inspector & inspector); + const slime::Inspector & _inspector; +}; + +} diff --git a/vespalib/src/vespa/vespalib/trace/slime_trace_serializer.cpp b/vespalib/src/vespa/vespalib/trace/slime_trace_serializer.cpp new file mode 100644 index 00000000000..4332d6bf045 --- /dev/null +++ b/vespalib/src/vespa/vespalib/trace/slime_trace_serializer.cpp @@ -0,0 +1,62 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/vespalib/trace/slime_trace_serializer.h> +#include <vespa/vespalib/trace/trace.h> + +using namespace vespalib::slime; + +namespace vespalib { + +const Memory SlimeTraceSerializer::TIMESTAMP("timestamp"); +const Memory SlimeTraceSerializer::PAYLOAD("payload"); +const Memory SlimeTraceSerializer::CHILDREN("children"); + +SlimeTraceSerializer::SlimeTraceSerializer(Cursor & cursor) + : _cursors() +{ + _cursors.push(&cursor); +} + +void +SlimeTraceSerializer::visit(const TraceNode & node) +{ + assert(!_cursors.empty()); + Cursor * current(_cursors.top()); + assert(current != NULL); + _cursors.pop(); + addTimestamp(*current, node); + addPayload(*current, node); + addChildrenCursors(*current, node); +} + +void +SlimeTraceSerializer::addTimestamp(Cursor & current, const TraceNode & node) +{ + current.setLong(TIMESTAMP, node.getTimestamp()); +} + +void +SlimeTraceSerializer::addPayload(Cursor & current, const TraceNode & node) +{ + if (node.hasNote()) { + current.setString(PAYLOAD, Memory(node.getNote())); + } +} + +void +SlimeTraceSerializer::addChildrenCursors(Cursor & current, const TraceNode & node) +{ + if (node.getNumChildren() > 0) { + addChildrenCursorsToStack(current.setArray(CHILDREN), node); + } +} + +void +SlimeTraceSerializer::addChildrenCursorsToStack(Cursor & childrenArray, const TraceNode & node) +{ + for (uint32_t childIndex(0); childIndex < node.getNumChildren(); childIndex++) { + Cursor & child(childrenArray.addObject()); + _cursors.push(&child); + } +} + +} diff --git a/vespalib/src/vespa/vespalib/trace/slime_trace_serializer.h b/vespalib/src/vespa/vespalib/trace/slime_trace_serializer.h new file mode 100644 index 00000000000..3b50f0878bf --- /dev/null +++ b/vespalib/src/vespa/vespalib/trace/slime_trace_serializer.h @@ -0,0 +1,32 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include <vespa/vespalib/trace/tracevisitor.h> +#include <vespa/vespalib/data/slime/slime.h> +#include <stack> + +namespace vespalib { + +class TraceNode; + +/** + * A serializer of TraceNodes using the TraceVisitor API. The serialized order of the nodes are NOT + * guaranteed to be in the same order as the original. + */ +class SlimeTraceSerializer : public TraceVisitor +{ +public: + SlimeTraceSerializer(slime::Cursor & cursor); + void visit(const TraceNode & node); + static const slime::Memory TIMESTAMP; + static const slime::Memory PAYLOAD; + static const slime::Memory CHILDREN; +private: + void addTimestamp(slime::Cursor & current, const TraceNode & node); + void addPayload(slime::Cursor & current, const TraceNode & node); + void addChildrenCursors(slime::Cursor & current, const TraceNode & node); + void addChildrenCursorsToStack(slime::Cursor & childrenArray, const TraceNode & node); + std::stack<slime::Cursor *> _cursors; +}; + +} |