Skip to content

Commit

Permalink
C API Exceptions (#967)
Browse files Browse the repository at this point in the history
* c-api exceptions on dbconnector

* Remaining c api exceptions

* Improve coverage of exception surface

* Add comments explaining how structs should be freed
  • Loading branch information
erer1243 authored Jan 16, 2025
1 parent b58a501 commit 5a4b4a5
Show file tree
Hide file tree
Showing 23 changed files with 500 additions and 358 deletions.
36 changes: 20 additions & 16 deletions common/c-api/consumerstatetable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,37 @@ using namespace swss;
using namespace std;
using boost::numeric_cast;

SWSSConsumerStateTable SWSSConsumerStateTable_new(SWSSDBConnector db, const char *tableName,
const int32_t *p_popBatchSize,
const int32_t *p_pri) {
int popBatchSize = p_popBatchSize ? numeric_cast<int>(*p_popBatchSize)
: TableConsumable::DEFAULT_POP_BATCH_SIZE;
int pri = p_pri ? numeric_cast<int>(*p_pri) : 0;
SWSSTry(return (SWSSConsumerStateTable) new ConsumerStateTable(
(DBConnector *)db, string(tableName), popBatchSize, pri));
SWSSResult SWSSConsumerStateTable_new(SWSSDBConnector db, const char *tableName,
const int32_t *p_popBatchSize, const int32_t *p_pri,
SWSSConsumerStateTable *outTbl) {
SWSSTry({
int popBatchSize = p_popBatchSize ? numeric_cast<int>(*p_popBatchSize)
: TableConsumable::DEFAULT_POP_BATCH_SIZE;
int pri = p_pri ? numeric_cast<int>(*p_pri) : 0;
*outTbl = (SWSSConsumerStateTable) new ConsumerStateTable(
(DBConnector *)db, string(tableName), popBatchSize, pri);
});
}

void SWSSConsumerStateTable_free(SWSSConsumerStateTable tbl) {
SWSSResult SWSSConsumerStateTable_free(SWSSConsumerStateTable tbl) {
SWSSTry(delete (ConsumerStateTable *)tbl);
}

SWSSKeyOpFieldValuesArray SWSSConsumerStateTable_pops(SWSSConsumerStateTable tbl) {
SWSSResult SWSSConsumerStateTable_pops(SWSSConsumerStateTable tbl,
SWSSKeyOpFieldValuesArray *outArr) {
SWSSTry({
deque<KeyOpFieldsValuesTuple> vkco;
((ConsumerStateTable *)tbl)->pops(vkco);
return makeKeyOpFieldValuesArray(vkco);
*outArr = makeKeyOpFieldValuesArray(vkco);
});
}

uint32_t SWSSConsumerStateTable_getFd(SWSSConsumerStateTable tbl) {
SWSSTry(return numeric_cast<uint32_t>(((ConsumerStateTable *)tbl)->getFd()));
SWSSResult SWSSConsumerStateTable_getFd(SWSSConsumerStateTable tbl, uint32_t *outFd) {
SWSSTry(*outFd = numeric_cast<uint32_t>(((ConsumerStateTable *)tbl)->getFd()));
}

SWSSSelectResult SWSSConsumerStateTable_readData(SWSSConsumerStateTable tbl, uint32_t timeout_ms,
uint8_t interrupt_on_signal) {
SWSSTry(return selectOne((ConsumerStateTable *)tbl, timeout_ms, interrupt_on_signal));
SWSSResult SWSSConsumerStateTable_readData(SWSSConsumerStateTable tbl, uint32_t timeout_ms,
uint8_t interrupt_on_signal,
SWSSSelectResult *outResult) {
SWSSTry(*outResult = selectOne((ConsumerStateTable *)tbl, timeout_ms, interrupt_on_signal));
}
21 changes: 11 additions & 10 deletions common/c-api/consumerstatetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define SWSS_COMMON_C_API_CONSUMERSTATETABLE_H

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

#ifdef __cplusplus
Expand All @@ -12,25 +13,25 @@ extern "C" {

typedef struct SWSSConsumerStateTableOpaque *SWSSConsumerStateTable;

// Pass NULL for popBatchSize and/or pri to use the default values
SWSSConsumerStateTable SWSSConsumerStateTable_new(SWSSDBConnector db, const char *tableName,
const int32_t *popBatchSize, const int32_t *pri);
SWSSResult SWSSConsumerStateTable_new(SWSSDBConnector db, const char *tableName,
const int32_t *popBatchSize, const int32_t *pri,
SWSSConsumerStateTable *outTbl);

void SWSSConsumerStateTable_free(SWSSConsumerStateTable tbl);
SWSSResult SWSSConsumerStateTable_free(SWSSConsumerStateTable tbl);

// Result array and all of its members must be freed using free()
SWSSKeyOpFieldValuesArray SWSSConsumerStateTable_pops(SWSSConsumerStateTable tbl);
SWSSResult SWSSConsumerStateTable_pops(SWSSConsumerStateTable tbl, SWSSKeyOpFieldValuesArray *outArr);

// Return the underlying fd for polling/selecting on.
// Callers must NOT read/write on fd, it may only be used for epoll or similar.
// Outputs the underlying fd for polling/selecting on.
// Callers must NOT read/write on the fd, it may only be used for epoll or similar.
// After the fd becomes readable, SWSSConsumerStateTable_readData must be used to
// reset the fd and read data into internal data structures.
uint32_t SWSSConsumerStateTable_getFd(SWSSConsumerStateTable tbl);
SWSSResult SWSSConsumerStateTable_getFd(SWSSConsumerStateTable tbl, uint32_t *outFd);

// Block until data is available to read or until a timeout elapses.
// A timeout of 0 means the call will return immediately.
SWSSSelectResult SWSSConsumerStateTable_readData(SWSSConsumerStateTable tbl, uint32_t timeout_ms,
uint8_t interrupt_on_signal);
SWSSResult SWSSConsumerStateTable_readData(SWSSConsumerStateTable tbl, uint32_t timeout_ms,
uint8_t interrupt_on_signal, SWSSSelectResult *outResult);

#ifdef __cplusplus
}
Expand Down
59 changes: 29 additions & 30 deletions common/c-api/dbconnector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,66 @@
using namespace swss;
using namespace std;

void SWSSSonicDBConfig_initialize(const char *path) {
SWSSResult SWSSSonicDBConfig_initialize(const char *path) {
SWSSTry(SonicDBConfig::initialize(path));
}

void SWSSSonicDBConfig_initializeGlobalConfig(const char *path) {
SWSSResult SWSSSonicDBConfig_initializeGlobalConfig(const char *path) {
SWSSTry(SonicDBConfig::initializeGlobalConfig(path));
}

SWSSDBConnector SWSSDBConnector_new_tcp(int32_t dbId, const char *hostname, uint16_t port,
uint32_t timeout) {
SWSSTry(return (SWSSDBConnector) new DBConnector(dbId, string(hostname), port, timeout));
SWSSResult SWSSDBConnector_new_tcp(int32_t dbId, const char *hostname, uint16_t port,
uint32_t timeout, SWSSDBConnector *outDb) {
SWSSTry(*outDb = (SWSSDBConnector) new DBConnector(dbId, string(hostname), port, timeout));
}

SWSSDBConnector SWSSDBConnector_new_unix(int32_t dbId, const char *sock_path, uint32_t timeout) {
SWSSTry(return (SWSSDBConnector) new DBConnector(dbId, string(sock_path), timeout));
SWSSResult SWSSDBConnector_new_unix(int32_t dbId, const char *sock_path, uint32_t timeout, SWSSDBConnector *outDb) {
SWSSTry(*outDb = (SWSSDBConnector) new DBConnector(dbId, string(sock_path), timeout));
}

SWSSDBConnector SWSSDBConnector_new_named(const char *dbName, uint32_t timeout_ms, uint8_t isTcpConn) {
SWSSTry(return (SWSSDBConnector) new DBConnector(string(dbName), timeout_ms, isTcpConn));
SWSSResult SWSSDBConnector_new_named(const char *dbName, uint32_t timeout_ms, uint8_t isTcpConn, SWSSDBConnector *outDb) {
SWSSTry(*outDb = (SWSSDBConnector) new DBConnector(string(dbName), timeout_ms, isTcpConn));
}

void SWSSDBConnector_free(SWSSDBConnector db) {
delete (DBConnector *)db;
SWSSResult SWSSDBConnector_free(SWSSDBConnector db) {
SWSSTry(delete (DBConnector *)db);
}

int8_t SWSSDBConnector_del(SWSSDBConnector db, const char *key) {
SWSSTry(return ((DBConnector *)db)->del(string(key)) ? 1 : 0);
SWSSResult SWSSDBConnector_del(SWSSDBConnector db, const char *key, int8_t *outStatus) {
SWSSTry(*outStatus = ((DBConnector *)db)->del(string(key)) ? 1 : 0);
}

void SWSSDBConnector_set(SWSSDBConnector db, const char *key, SWSSStrRef value) {
SWSSResult SWSSDBConnector_set(SWSSDBConnector db, const char *key, SWSSStrRef value) {
SWSSTry(((DBConnector *)db)->set(string(key), takeStrRef(value)));
}

SWSSString SWSSDBConnector_get(SWSSDBConnector db, const char *key) {
SWSSResult SWSSDBConnector_get(SWSSDBConnector db, const char *key, SWSSString *outValue) {
SWSSTry({
shared_ptr<string> s = ((DBConnector *)db)->get(string(key));
return s ? makeString(move(*s)) : nullptr;
*outValue = s ? makeString(move(*s)) : nullptr;
});
}

int8_t SWSSDBConnector_exists(SWSSDBConnector db, const char *key) {
SWSSTry(return ((DBConnector *)db)->exists(string(key)) ? 1 : 0);
SWSSResult SWSSDBConnector_exists(SWSSDBConnector db, const char *key, int8_t *outExists) {
SWSSTry(*outExists = ((DBConnector *)db)->exists(string(key)) ? 1 : 0);
}

int8_t SWSSDBConnector_hdel(SWSSDBConnector db, const char *key, const char *field) {
SWSSTry(return ((DBConnector *)db)->hdel(string(key), string(field)) ? 1 : 0);
SWSSResult SWSSDBConnector_hdel(SWSSDBConnector db, const char *key, const char *field, int8_t *outResult) {
SWSSTry(*outResult = ((DBConnector *)db)->hdel(string(key), string(field)) ? 1 : 0);
}

void SWSSDBConnector_hset(SWSSDBConnector db, const char *key, const char *field,
SWSSStrRef value) {
SWSSResult SWSSDBConnector_hset(SWSSDBConnector db, const char *key, const char *field, SWSSStrRef value) {
SWSSTry(((DBConnector *)db)->hset(string(key), string(field), takeStrRef(value)));
}

SWSSString SWSSDBConnector_hget(SWSSDBConnector db, const char *key, const char *field) {
SWSSResult SWSSDBConnector_hget(SWSSDBConnector db, const char *key, const char *field, SWSSString *outValue) {
SWSSTry({
shared_ptr<string> s = ((DBConnector *)db)->hget(string(key), string(field));
return s ? makeString(move(*s)) : nullptr;
*outValue = s ? makeString(move(*s)) : nullptr;
});
}

SWSSFieldValueArray SWSSDBConnector_hgetall(SWSSDBConnector db, const char *key) {
SWSSResult SWSSDBConnector_hgetall(SWSSDBConnector db, const char *key, SWSSFieldValueArray *outArr) {
SWSSTry({
auto map = ((DBConnector *)db)->hgetall(string(key));

Expand All @@ -80,14 +79,14 @@ SWSSFieldValueArray SWSSDBConnector_hgetall(SWSSDBConnector db, const char *key)
for (auto &pair : map)
pairs.push_back(make_pair(pair.first, move(pair.second)));

return makeFieldValueArray(std::move(pairs));
*outArr = makeFieldValueArray(std::move(pairs));
});
}

int8_t SWSSDBConnector_hexists(SWSSDBConnector db, const char *key, const char *field) {
SWSSTry(return ((DBConnector *)db)->hexists(string(key), string(field)) ? 1 : 0);
SWSSResult SWSSDBConnector_hexists(SWSSDBConnector db, const char *key, const char *field, int8_t *outExists) {
SWSSTry(*outExists = ((DBConnector *)db)->hexists(string(key), string(field)) ? 1 : 0);
}

int8_t SWSSDBConnector_flushdb(SWSSDBConnector db) {
SWSSTry(return ((DBConnector *)db)->flushdb() ? 1 : 0);
SWSSResult SWSSDBConnector_flushdb(SWSSDBConnector db, int8_t *outStatus) {
SWSSTry(*outStatus = ((DBConnector *)db)->flushdb() ? 1 : 0);
}
56 changes: 29 additions & 27 deletions common/c-api/dbconnector.h
Original file line number Diff line number Diff line change
@@ -1,61 +1,63 @@
#ifndef SWSS_COMMON_C_API_DBCONNECTOR_H
#define SWSS_COMMON_C_API_DBCONNECTOR_H

#include "result.h"
#include "util.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

void SWSSSonicDBConfig_initialize(const char *path);
SWSSResult SWSSSonicDBConfig_initialize(const char *path);

void SWSSSonicDBConfig_initializeGlobalConfig(const char *path);
SWSSResult SWSSSonicDBConfig_initializeGlobalConfig(const char *path);

typedef struct SWSSDBConnectorOpaque *SWSSDBConnector;

// Pass 0 to timeout for infinity
SWSSDBConnector SWSSDBConnector_new_tcp(int32_t dbId, const char *hostname, uint16_t port,
uint32_t timeout_ms);
SWSSResult SWSSDBConnector_new_tcp(int32_t dbId, const char *hostname, uint16_t port,
uint32_t timeout, SWSSDBConnector *outDb);

// Pass 0 to timeout for infinity
SWSSDBConnector SWSSDBConnector_new_unix(int32_t dbId, const char *sock_path, uint32_t timeout_ms);
SWSSResult SWSSDBConnector_new_unix(int32_t dbId, const char *sock_path, uint32_t timeout, SWSSDBConnector *outDb);

// Pass 0 to timeout for infinity
SWSSDBConnector SWSSDBConnector_new_named(const char *dbName, uint32_t timeout_ms, uint8_t isTcpConn);
SWSSResult SWSSDBConnector_new_named(const char *dbName, uint32_t timeout_ms, uint8_t isTcpConn, SWSSDBConnector *outDb);

void SWSSDBConnector_free(SWSSDBConnector db);
SWSSResult SWSSDBConnector_free(SWSSDBConnector db);

// Returns 0 when key doesn't exist, 1 when key was deleted
int8_t SWSSDBConnector_del(SWSSDBConnector db, const char *key);
// Outputs 0 when key doesn't exist, 1 when key was deleted
SWSSResult SWSSDBConnector_del(SWSSDBConnector db, const char *key, int8_t *outStatus);

void SWSSDBConnector_set(SWSSDBConnector db, const char *key, SWSSStrRef value);
SWSSResult SWSSDBConnector_set(SWSSDBConnector db, const char *key, SWSSStrRef value);

// Returns NULL if key doesn't exist
// Result must be freed using SWSSString_free()
SWSSString SWSSDBConnector_get(SWSSDBConnector db, const char *key);
// Outputs NULL if key doesn't exist
// Value must be freed using SWSSString_free()
SWSSResult SWSSDBConnector_get(SWSSDBConnector db, const char *key, SWSSString *outValue);

// Returns 0 for false, 1 for true
int8_t SWSSDBConnector_exists(SWSSDBConnector db, const char *key);
// Outputs 0 for false, 1 for true
SWSSResult SWSSDBConnector_exists(SWSSDBConnector db, const char *key, int8_t *outExists);

// Returns 0 when key or field doesn't exist, 1 when field was deleted
int8_t SWSSDBConnector_hdel(SWSSDBConnector db, const char *key, const char *field);
// Outputs 0 when key or field doesn't exist, 1 when field was deleted
SWSSResult SWSSDBConnector_hdel(SWSSDBConnector db, const char *key, const char *field, int8_t *outResult);

void SWSSDBConnector_hset(SWSSDBConnector db, const char *key, const char *field, SWSSStrRef value);
SWSSResult SWSSDBConnector_hset(SWSSDBConnector db, const char *key, const char *field, SWSSStrRef value);

// Returns NULL if key or field doesn't exist
// Result must be freed using SWSSString_free()
SWSSString SWSSDBConnector_hget(SWSSDBConnector db, const char *key, const char *field);
// Outputs NULL if key or field doesn't exist
// Value must be freed using SWSSString_free()
SWSSResult SWSSDBConnector_hget(SWSSDBConnector db, const char *key, const char *field, SWSSString *outValue);

// Returns an empty map when the key doesn't exist
// Outputs an empty map when the key doesn't exist
// Result array and all of its elements must be freed using appropriate free functions
SWSSFieldValueArray SWSSDBConnector_hgetall(SWSSDBConnector db, const char *key);
SWSSResult SWSSDBConnector_hgetall(SWSSDBConnector db, const char *key, SWSSFieldValueArray *outArr);

// Returns 0 when key or field doesn't exist, 1 when field exists
int8_t SWSSDBConnector_hexists(SWSSDBConnector db, const char *key, const char *field);
// Outputs 0 when key or field doesn't exist, 1 when field exists
SWSSResult SWSSDBConnector_hexists(SWSSDBConnector db, const char *key, const char *field, int8_t *outExists);

// Returns 1 on success, 0 on failure
int8_t SWSSDBConnector_flushdb(SWSSDBConnector db);
// Outputs 1 on success, 0 on failure
SWSSResult SWSSDBConnector_flushdb(SWSSDBConnector db, int8_t *outStatus);

#ifdef __cplusplus
}
Expand Down
31 changes: 16 additions & 15 deletions common/c-api/producerstatetable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,45 @@
using namespace swss;
using namespace std;

SWSSProducerStateTable SWSSProducerStateTable_new(SWSSDBConnector db, const char *tableName) {
SWSSTry(return (SWSSProducerStateTable) new ProducerStateTable((DBConnector *)db,
string(tableName)));
SWSSResult SWSSProducerStateTable_new(SWSSDBConnector db, const char *tableName,
SWSSProducerStateTable *outTbl) {
SWSSTry(*outTbl = (SWSSProducerStateTable) new ProducerStateTable((DBConnector *)db,
string(tableName)));
}

void SWSSProducerStateTable_free(SWSSProducerStateTable tbl) {
SWSSResult SWSSProducerStateTable_free(SWSSProducerStateTable tbl) {
SWSSTry(delete ((ProducerStateTable *)tbl));
}

void SWSSProducerStateTable_setBuffered(SWSSProducerStateTable tbl, uint8_t buffered) {
SWSSTry(((ProducerStateTable *)tbl)->setBuffered((bool)buffered))
SWSSResult SWSSProducerStateTable_setBuffered(SWSSProducerStateTable tbl, uint8_t buffered) {
SWSSTry(((ProducerStateTable *)tbl)->setBuffered((bool)buffered));
}

void SWSSProducerStateTable_set(SWSSProducerStateTable tbl, const char *key,
SWSSFieldValueArray values) {
SWSSResult SWSSProducerStateTable_set(SWSSProducerStateTable tbl, const char *key,
SWSSFieldValueArray values) {
SWSSTry(((ProducerStateTable *)tbl)->set(string(key), takeFieldValueArray(std::move(values))));
}

void SWSSProducerStateTable_del(SWSSProducerStateTable tbl, const char *key) {
SWSSResult SWSSProducerStateTable_del(SWSSProducerStateTable tbl, const char *key) {
SWSSTry(((ProducerStateTable *)tbl)->del(string(key)));
}

void SWSSProducerStateTable_flush(SWSSProducerStateTable tbl) {
SWSSResult SWSSProducerStateTable_flush(SWSSProducerStateTable tbl) {
SWSSTry(((ProducerStateTable *)tbl)->flush());
}

int64_t SWSSProducerStateTable_count(SWSSProducerStateTable tbl) {
SWSSTry(return ((ProducerStateTable *)tbl)->count());
SWSSResult SWSSProducerStateTable_count(SWSSProducerStateTable tbl, int64_t *outCount) {
SWSSTry(*outCount = ((ProducerStateTable *)tbl)->count());
}

void SWSSProducerStateTable_clear(SWSSProducerStateTable tbl) {
SWSSResult SWSSProducerStateTable_clear(SWSSProducerStateTable tbl) {
SWSSTry(((ProducerStateTable *)tbl)->clear());
}

void SWSSProducerStateTable_create_temp_view(SWSSProducerStateTable tbl) {
SWSSResult SWSSProducerStateTable_create_temp_view(SWSSProducerStateTable tbl) {
SWSSTry(((ProducerStateTable *)tbl)->create_temp_view());
}

void SWSSProducerStateTable_apply_temp_view(SWSSProducerStateTable tbl) {
SWSSResult SWSSProducerStateTable_apply_temp_view(SWSSProducerStateTable tbl) {
SWSSTry(((ProducerStateTable *)tbl)->apply_temp_view());
}
Loading

0 comments on commit 5a4b4a5

Please sign in to comment.