Skip to content

Commit

Permalink
cc: extend c++ api for hash table
Browse files Browse the repository at this point in the history
This commit extends the api for hash tables allowing to get, update and
delete elements

Signed-off-by: Mauricio Vasquez B <[email protected]>
  • Loading branch information
mauriciovasquezbernal committed Apr 4, 2017
1 parent b255a0a commit 089ad4c
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 7 deletions.
36 changes: 29 additions & 7 deletions src/cc/BPFTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#pragma once

#include <cstring>
#include <sys/epoll.h>
#include <exception>
#include <map>
Expand Down Expand Up @@ -70,16 +71,37 @@ template <class KeyType, class ValueType>
class BPFHashTable : protected BPFTableBase<KeyType, ValueType> {
public:
explicit BPFHashTable(const TableDesc& desc)
: BPFTableBase<KeyType, ValueType>(desc) {}
: BPFTableBase<KeyType, ValueType>(desc) {
if (desc.type != BPF_MAP_TYPE_HASH &&
desc.type != BPF_MAP_TYPE_PERCPU_HASH &&
desc.type != BPF_MAP_TYPE_LRU_HASH &&
desc.type != BPF_MAP_TYPE_LRU_PERCPU_HASH)
throw std::invalid_argument("Table '" + desc.name + "' is not a hash table");
}

ValueType get_value(const KeyType& key) {
ValueType res;
if (!this->lookup(const_cast<KeyType*>(&key), &res))
throw std::invalid_argument("Key does not exist in the table");
return res;
StatusTuple get_value(const KeyType& key, ValueType& value) {
if (!this->lookup(const_cast<KeyType*>(&key), &value))
return StatusTuple(-1, "Error getting value: %s", std::strerror(errno));
return StatusTuple(0);
}

StatusTuple update_value(const KeyType& key, const ValueType& value) {
if (!this->update(const_cast<KeyType*>(&key), const_cast<ValueType*>(&value)))
return StatusTuple(-1, "Error updating value: %s", std::strerror(errno));
return StatusTuple(0);
}

ValueType operator[](const KeyType& key) { return get_value(key); }
StatusTuple remove_value(const KeyType& key) {
if (!this->remove(const_cast<KeyType*>(&key)))
return StatusTuple(-1, "Error removing value: %s", std::strerror(errno));
return StatusTuple(0);
}

ValueType operator[](const KeyType& key) {
ValueType value;
get_value(key, value);
return value;
}

std::vector<std::pair<KeyType, ValueType>> get_table_offline() {
std::vector<std::pair<KeyType, ValueType>> res;
Expand Down
1 change: 1 addition & 0 deletions tests/cc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_test(NAME c_test_static COMMAND ${TEST_WRAPPER} c_test_static sudo ${CMAKE_C
add_executable(test_libbcc
test_libbcc.cc
test_c_api.cc
test_hash_table.cc
test_usdt_args.cc
test_usdt_probes.cc)

Expand Down
74 changes: 74 additions & 0 deletions tests/cc/test_hash_table.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2017 Politecnico di Torino
*
* 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:https://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 "BPF.h"

#include "catch.hpp"

TEST_CASE("test hash table", "[hash_table]") {
const std::string BPF_PROGRAM = R"(
BPF_TABLE("hash", int, int, myhash, 1024);
BPF_TABLE("array", int, int, myarray, 1024);
)";

ebpf::BPF bpf;
ebpf::StatusTuple res(0);
res = bpf.init(BPF_PROGRAM);
REQUIRE(res.code() == 0);

ebpf::BPFHashTable<int, int> t = bpf.get_hash_table<int, int>("myhash");

SECTION("bad table type") {
// try to get table of wrong type
auto f1 = [&](){
bpf.get_hash_table<int, int>("myarray");
};

REQUIRE_THROWS(f1());
}

SECTION("standard methods") {
int k, v1, v2;
k = 1;
v1 = 42;
// create new element
res = t.update_value(k, v1);
REQUIRE(res.code() == 0);
res = t.get_value(k, v2);
REQUIRE(res.code() == 0);
REQUIRE(v2 == 42);

// update existing element
v1 = 69;
res = t.update_value(k, v1);
REQUIRE(res.code() == 0);
res = t.get_value(k, v2);
REQUIRE(res.code() == 0);
REQUIRE(v2 == 69);

// remove existing element
res = t.remove_value(k);
REQUIRE(res.code() == 0);

// remove non existing element
res = t.remove_value(k);
REQUIRE(res.code() != 0);

// get non existing element
res = t.get_value(k, v2);
REQUIRE(res.code() != 0);
}
}

0 comments on commit 089ad4c

Please sign in to comment.