Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…wss-common into zmq_new
  • Loading branch information
divyagayathri-hcl committed Jan 16, 2025
2 parents 510132f + b58a501 commit 5a1f050
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 14 deletions.
1 change: 1 addition & 0 deletions common/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ common_libswsscommon_la_SOURCES = \
common/c-api/zmqserver.cpp \
common/c-api/zmqconsumerstatetable.cpp \
common/c-api/zmqproducerstatetable.cpp \
common/c-api/table.cpp \
common/performancetimer.cpp

common_libswsscommon_la_CXXFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(LIBNL_CFLAGS) $(CODE_COVERAGE_CXXFLAGS)
Expand Down
71 changes: 71 additions & 0 deletions common/c-api/table.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <string>
#include <vector>

#include "../dbconnector.h"
#include "../table.h"
#include "table.h"
#include "util.h"

using namespace swss;
using namespace std;

SWSSTable SWSSTable_new(SWSSDBConnector db, const char *tableName) {
SWSSTry(return (SWSSTable) new Table((DBConnector *)db, string(tableName)));
}

void SWSSTable_free(SWSSTable tbl) {
SWSSTry(delete (Table *)tbl);
}

int8_t SWSSTable_get(SWSSTable tbl, const char *key, SWSSFieldValueArray *outValues) {
SWSSTry({
vector<FieldValueTuple> fvs;
bool exists = ((Table *)tbl)->get(string(key), fvs);
if (exists) {
*outValues = makeFieldValueArray(fvs);
return 1;
} else {
return 0;
}
});
}

int8_t SWSSTable_hget(SWSSTable tbl, const char *key, const char *field, SWSSString *outValue) {
SWSSTry({
string s;
bool exists = ((Table *)tbl)->hget(string(key), string(field), s);
if (exists) {
*outValue = makeString(move(s));
return 1;
} else {
return 0;
}
});
}

void SWSSTable_set(SWSSTable tbl, const char *key, SWSSFieldValueArray values) {
SWSSTry({
vector<FieldValueTuple> fvs = takeFieldValueArray(values);
((Table *)tbl)->set(string(key), fvs);
});
}

void SWSSTable_hset(SWSSTable tbl, const char *key, const char *field, SWSSStrRef value) {
SWSSTry({ ((Table *)tbl)->hset(string(key), string(field), takeStrRef(value)); });
}

void SWSSTable_del(SWSSTable tbl, const char *key) {
SWSSTry({ ((Table *)tbl)->del(string(key)); });
}

void SWSSTable_hdel(SWSSTable tbl, const char *key, const char *field) {
SWSSTry({ ((Table *)tbl)->hdel(string(key), string(field)); });
}

SWSSStringArray SWSSTable_getKeys(SWSSTable tbl) {
SWSSTry({
vector<string> keys;
((Table *)tbl)->getKeys(keys);
return makeStringArray(move(keys));
})
}
41 changes: 41 additions & 0 deletions common/c-api/table.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#ifndef SWSS_COMMON_C_API_TABLE_H
#define SWSS_COMMON_C_API_TABLE_H

#include "dbconnector.h"
#include "util.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

typedef struct SWSSTableOpaque *SWSSTable;

SWSSTable SWSSTable_new(SWSSDBConnector db, const char *tableName);

void SWSSTable_free(SWSSTable tbl);

// If the key exists, populates outValues with the table's values and returns 1.
// If the key doesn't exist, returns 0.
int8_t SWSSTable_get(SWSSTable tbl, const char *key, SWSSFieldValueArray *outValues);

// If the key and field exist, populates outValue with the field's value and returns 1.
// If the key doesn't exist, returns 0.
int8_t SWSSTable_hget(SWSSTable tbl, const char *key, const char *field, SWSSString *outValue);

void SWSSTable_set(SWSSTable tbl, const char *key, SWSSFieldValueArray values);

void SWSSTable_hset(SWSSTable tbl, const char *key, const char *field, SWSSStrRef value);

void SWSSTable_del(SWSSTable tbl, const char *key);

void SWSSTable_hdel(SWSSTable tbl, const char *key, const char *field);

SWSSStringArray SWSSTable_getKeys(SWSSTable tbl);

#ifdef __cplusplus
}
#endif

#endif
4 changes: 4 additions & 0 deletions common/c-api/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,7 @@ void SWSSFieldValueArray_free(SWSSFieldValueArray arr) {
void SWSSKeyOpFieldValuesArray_free(SWSSKeyOpFieldValuesArray kfvs) {
SWSSTry(delete[] kfvs.data);
}

void SWSSStringArray_free(SWSSStringArray arr) {
SWSSTry(delete[] arr.data);
}
25 changes: 25 additions & 0 deletions common/c-api/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ typedef struct SWSSStringOpaque *SWSSString;
typedef struct SWSSStrRefOpaque *SWSSStrRef;

// FFI version of swss::FieldValueTuple
// field should be freed with libc's free()
typedef struct {
const char *field;
SWSSString value;
Expand Down Expand Up @@ -59,6 +60,13 @@ typedef enum {
SWSSSelectResult_SIGNAL = 2,
} SWSSSelectResult;

// FFI version of std::vector<std::string>
// data strings should be freed with libc's free()
typedef struct {
uint64_t len;
const char **data;
} SWSSStringArray;

// data should not include a null terminator
SWSSString SWSSString_new(const char *data, uint64_t length);

Expand All @@ -85,6 +93,10 @@ void SWSSFieldValueArray_free(SWSSFieldValueArray arr);
// grained control of ownership).
void SWSSKeyOpFieldValuesArray_free(SWSSKeyOpFieldValuesArray kfvs);

// arr.data may be null. This is not recursive - elements must be freed separately (for finer
// grained control of ownership).
void SWSSStringArray_free(SWSSStringArray arr);

#ifdef __cplusplus
}
#endif
Expand Down Expand Up @@ -214,6 +226,19 @@ template <class T> static inline SWSSKeyOpFieldValuesArray makeKeyOpFieldValuesA
return out;
}

static inline SWSSStringArray makeStringArray(std::vector<std::string> &&in) {
const char **data = new const char*[in.size()];

size_t i = 0;
for (std::string &s : in)
data[i++] = strdup(s.c_str());

SWSSStringArray out;
out.len = (uint64_t)in.size();
out.data = data;
return out;
}

static inline std::string takeString(SWSSString s) {
return std::string(std::move(*((std::string *)s)));
}
Expand Down
3 changes: 3 additions & 0 deletions common/schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,9 @@ namespace swss {
#define CFG_PAC_GLOBAL_CONFIG_TABLE "PAC_GLOBAL_CONFIG_TABLE"
#define CFG_PAC_HOSTAPD_GLOBAL_CONFIG_TABLE "HOSTAPD_GLOBAL_CONFIG_TABLE"

#define CFG_SRV6_MY_SID_TABLE_NAME "SRV6_MY_SIDS"
#define CFG_SRV6_MY_LOCATOR_TABLE_NAME "SRV6_MY_LOCATORS"

/***** STATE DATABASE *****/

#define STATE_SWITCH_CAPABILITY_TABLE_NAME "SWITCH_CAPABILITY"
Expand Down
81 changes: 69 additions & 12 deletions tests/c_api_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "common/c-api/dbconnector.h"
#include "common/c-api/producerstatetable.h"
#include "common/c-api/subscriberstatetable.h"
#include "common/c-api/table.h"
#include "common/c-api/util.h"
#include "common/c-api/zmqclient.h"
#include "common/c-api/zmqconsumerstatetable.h"
Expand Down Expand Up @@ -40,14 +41,18 @@ static void sortKfvs(vector<KeyOpFieldsValuesTuple> &kfvs) {

#define free(x) std::free(const_cast<void *>(reinterpret_cast<const void *>(x)));

static void freeFieldValuesArray(SWSSFieldValueArray arr) {
for (uint64_t i = 0; i < arr.len; i++) {
free(arr.data[i].field);
SWSSString_free(arr.data[i].value);
}
SWSSFieldValueArray_free(arr);
}

static void freeKeyOpFieldValuesArray(SWSSKeyOpFieldValuesArray arr) {
for (uint64_t i = 0; i < arr.len; i++) {
free(arr.data[i].key);
for (uint64_t j = 0; j < arr.data[i].fieldValues.len; j++) {
free(arr.data[i].fieldValues.data[j].field);
SWSSString_free(arr.data[i].fieldValues.data[j].value);
}
SWSSFieldValueArray_free(arr.data[i].fieldValues);
freeFieldValuesArray(arr.data[i].fieldValues);
}
SWSSKeyOpFieldValuesArray_free(arr);
}
Expand Down Expand Up @@ -105,6 +110,57 @@ TEST(c_api, DBConnector) {
SWSSDBConnector_free(db);
}

TEST(c_api, Table) {
clearDB();
SWSSStringManager sm;

SWSSDBConnector db = SWSSDBConnector_new_named("TEST_DB", 1000, true);
SWSSTable tbl = SWSSTable_new(db, "mytable");

SWSSFieldValueArray fvs;
SWSSString ss;
EXPECT_FALSE(SWSSTable_get(tbl, "mykey", &fvs));
EXPECT_FALSE(SWSSTable_hget(tbl, "mykey", "myfield", &ss));

SWSSStringArray keys = SWSSTable_getKeys(tbl);
EXPECT_EQ(keys.len, 0);
SWSSStringArray_free(keys);

SWSSTable_hset(tbl, "mykey", "myfield", sm.makeStrRef("myvalue"));
keys = SWSSTable_getKeys(tbl);
ASSERT_EQ(keys.len, 1);
EXPECT_STREQ(keys.data[0], "mykey");
free(keys.data[0]);
SWSSStringArray_free(keys);

ASSERT_TRUE(SWSSTable_hget(tbl, "mykey", "myfield", &ss));
EXPECT_STREQ(SWSSStrRef_c_str((SWSSStrRef)ss), "myvalue");
SWSSString_free(ss);

SWSSTable_hdel(tbl, "mykey", "myfield");
EXPECT_FALSE(SWSSTable_hget(tbl, "mykey", "myfield", &ss));

SWSSFieldValueTuple data[2] = {{.field = "myfield1", .value = sm.makeString("myvalue1")},
{.field = "myfield2", .value = sm.makeString("myvalue2")}};
fvs.len = 2;
fvs.data = data;
SWSSTable_set(tbl, "mykey", fvs);

ASSERT_TRUE(SWSSTable_get(tbl, "mykey", &fvs));
EXPECT_EQ(fvs.len, 2);
EXPECT_STREQ(data[0].field, fvs.data[0].field);
EXPECT_STREQ(data[1].field, fvs.data[1].field);
freeFieldValuesArray(fvs);

SWSSTable_del(tbl, "mykey");
keys = SWSSTable_getKeys(tbl);
EXPECT_EQ(keys.len, 0);
SWSSStringArray_free(keys);

SWSSTable_free(tbl);
SWSSDBConnector_free(db);
}

TEST(c_api, ConsumerProducerStateTables) {
clearDB();
SWSSStringManager sm;
Expand All @@ -119,9 +175,8 @@ TEST(c_api, ConsumerProducerStateTables) {
ASSERT_EQ(arr.len, 0);
freeKeyOpFieldValuesArray(arr);

SWSSFieldValueTuple data[2] = {
{.field = "myfield1", .value = sm.makeString("myvalue1")},
{.field = "myfield2", .value = sm.makeString("myvalue2")}};
SWSSFieldValueTuple data[2] = {{.field = "myfield1", .value = sm.makeString("myvalue1")},
{.field = "myfield2", .value = sm.makeString("myvalue2")}};
SWSSFieldValueArray values = {
.len = 2,
.data = data,
Expand Down Expand Up @@ -154,7 +209,7 @@ TEST(c_api, ConsumerProducerStateTables) {
ASSERT_EQ(fieldValues1.size(), 1);
EXPECT_EQ(fieldValues1[0].first, "myfield3");
EXPECT_EQ(fieldValues1[0].second, "myvalue3");

arr = SWSSConsumerStateTable_pops(cst);
EXPECT_EQ(arr.len, 0);
freeKeyOpFieldValuesArray(arr);
Expand Down Expand Up @@ -244,14 +299,16 @@ TEST(c_api, ZmqConsumerProducerStateTable) {
// On flag = 0, we use the ZmqProducerStateTable
// On flag = 1, we use the ZmqClient directly
for (int flag = 0; flag < 2; flag++) {
SWSSFieldValueTuple values_key1_data[2] = {{.field = "myfield1", .value = sm.makeString("myvalue1")},
{.field = "myfield2", .value = sm.makeString("myvalue2")}};
SWSSFieldValueTuple values_key1_data[2] = {
{.field = "myfield1", .value = sm.makeString("myvalue1")},
{.field = "myfield2", .value = sm.makeString("myvalue2")}};
SWSSFieldValueArray values_key1 = {
.len = 2,
.data = values_key1_data,
};

SWSSFieldValueTuple values_key2_data[1] = {{.field = "myfield3", .value = sm.makeString("myvalue3")}};
SWSSFieldValueTuple values_key2_data[1] = {
{.field = "myfield3", .value = sm.makeString("myvalue3")}};
SWSSFieldValueArray values_key2 = {
.len = 1,
.data = values_key2_data,
Expand Down
3 changes: 1 addition & 2 deletions tests/zmq_state_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ static void zmqConsumerWorker(string tableName, string endpoint,
std::vector<FieldValueTuple>{FieldValueTuple{"f", "v"}}});

while (!zmq_done) {
sleep(10);
sleep(2);
std::string recDbName, recTableName;
std::vector<std::shared_ptr<KeyOpFieldsValuesTuple>> recKcos;
std::vector<KeyOpFieldsValuesTuple> deserializedKcos;
Expand Down Expand Up @@ -544,7 +544,6 @@ static void ZmqWithResponse(bool producerPersistence)
}

zmq_done = true;
sleep(10);
consumerThread->join();
delete consumerThread;
}
Expand Down

0 comments on commit 5a1f050

Please sign in to comment.