diff --git a/common/c-api/consumerstatetable.cpp b/common/c-api/consumerstatetable.cpp index 9765ceec3..426055da1 100644 --- a/common/c-api/consumerstatetable.cpp +++ b/common/c-api/consumerstatetable.cpp @@ -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(*p_popBatchSize) - : TableConsumable::DEFAULT_POP_BATCH_SIZE; - int pri = p_pri ? numeric_cast(*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(*p_popBatchSize) + : TableConsumable::DEFAULT_POP_BATCH_SIZE; + int pri = p_pri ? numeric_cast(*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 vkco; ((ConsumerStateTable *)tbl)->pops(vkco); - return makeKeyOpFieldValuesArray(vkco); + *outArr = makeKeyOpFieldValuesArray(vkco); }); } -uint32_t SWSSConsumerStateTable_getFd(SWSSConsumerStateTable tbl) { - SWSSTry(return numeric_cast(((ConsumerStateTable *)tbl)->getFd())); +SWSSResult SWSSConsumerStateTable_getFd(SWSSConsumerStateTable tbl, uint32_t *outFd) { + SWSSTry(*outFd = numeric_cast(((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)); } diff --git a/common/c-api/consumerstatetable.h b/common/c-api/consumerstatetable.h index 468fb644b..43ed4cde4 100644 --- a/common/c-api/consumerstatetable.h +++ b/common/c-api/consumerstatetable.h @@ -2,6 +2,7 @@ #define SWSS_COMMON_C_API_CONSUMERSTATETABLE_H #include "dbconnector.h" +#include "result.h" #include "util.h" #ifdef __cplusplus @@ -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 } diff --git a/common/c-api/dbconnector.cpp b/common/c-api/dbconnector.cpp index 83f237cc0..2a8871481 100644 --- a/common/c-api/dbconnector.cpp +++ b/common/c-api/dbconnector.cpp @@ -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 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 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)); @@ -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); } diff --git a/common/c-api/dbconnector.h b/common/c-api/dbconnector.h index fe4acdf4d..f60026e71 100644 --- a/common/c-api/dbconnector.h +++ b/common/c-api/dbconnector.h @@ -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 -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 } diff --git a/common/c-api/producerstatetable.cpp b/common/c-api/producerstatetable.cpp index 276d7c680..c9cc34463 100644 --- a/common/c-api/producerstatetable.cpp +++ b/common/c-api/producerstatetable.cpp @@ -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()); } diff --git a/common/c-api/producerstatetable.h b/common/c-api/producerstatetable.h index 1acb9af37..463aeaaec 100644 --- a/common/c-api/producerstatetable.h +++ b/common/c-api/producerstatetable.h @@ -2,6 +2,7 @@ #define SWSS_COMMON_C_API_PRODUCERSTATETABLE_H #include "dbconnector.h" +#include "result.h" #include "util.h" #ifdef __cplusplus @@ -11,26 +12,27 @@ extern "C" { #include typedef struct SWSSProducerStateTableOpaque *SWSSProducerStateTable; +SWSSResult SWSSProducerStateTable_new(SWSSDBConnector db, const char *tableName, + SWSSProducerStateTable *outTbl); -SWSSProducerStateTable SWSSProducerStateTable_new(SWSSDBConnector db, const char *tableName); +SWSSResult SWSSProducerStateTable_free(SWSSProducerStateTable tbl); -void SWSSProducerStateTable_free(SWSSProducerStateTable tbl); +SWSSResult SWSSProducerStateTable_setBuffered(SWSSProducerStateTable tbl, uint8_t buffered); -void SWSSProducerStateTable_setBuffered(SWSSProducerStateTable tbl, uint8_t buffered); +SWSSResult SWSSProducerStateTable_set(SWSSProducerStateTable tbl, const char *key, + SWSSFieldValueArray values); -void SWSSProducerStateTable_set(SWSSProducerStateTable tbl, const char *key, SWSSFieldValueArray values); +SWSSResult SWSSProducerStateTable_del(SWSSProducerStateTable tbl, const char *key); -void SWSSProducerStateTable_del(SWSSProducerStateTable tbl, const char *key); +SWSSResult SWSSProducerStateTable_flush(SWSSProducerStateTable tbl); -void SWSSProducerStateTable_flush(SWSSProducerStateTable tbl); +SWSSResult SWSSProducerStateTable_count(SWSSProducerStateTable tbl, int64_t *outCount); -int64_t SWSSProducerStateTable_count(SWSSProducerStateTable tbl); +SWSSResult SWSSProducerStateTable_clear(SWSSProducerStateTable tbl); -void SWSSProducerStateTable_clear(SWSSProducerStateTable tbl); +SWSSResult SWSSProducerStateTable_create_temp_view(SWSSProducerStateTable tbl); -void SWSSProducerStateTable_create_temp_view(SWSSProducerStateTable tbl); - -void SWSSProducerStateTable_apply_temp_view(SWSSProducerStateTable tbl); +SWSSResult SWSSProducerStateTable_apply_temp_view(SWSSProducerStateTable tbl); #ifdef __cplusplus } diff --git a/common/c-api/result.h b/common/c-api/result.h new file mode 100644 index 000000000..9c29d0eea --- /dev/null +++ b/common/c-api/result.h @@ -0,0 +1,45 @@ +#ifndef SWSS_COMMON_C_API_RESULT_H +#define SWSS_COMMON_C_API_RESULT_H + +#include "util.h" + +typedef enum { + // No exception occurred + SWSSException_None, + + // std::exception was thrown + SWSSException_Exception, +} SWSSException; + +// If exception is SWSSException_None, message and location will be null. +// If message and location are non-null, they must be freed using SWSSString_free. +typedef struct { + SWSSException exception; + SWSSString message; + SWSSString location; +} SWSSResult; + +#ifdef __cplusplus +#include +#include +#include + +using namespace swss; + +#define SWSSTry(...) return SWSSTry_([=] { __VA_ARGS__; }, BOOST_CURRENT_FUNCTION) + +template static inline SWSSResult SWSSTry_(Func &&f, const char *funcName) { + SWSSResult result = {SWSSException_None, nullptr, nullptr}; + try { + f(); + } catch (std::exception &e) { + result.exception = SWSSException_Exception; + result.message = makeString(e.what()); + } + if (result.exception != SWSSException_None) + result.location = makeString(funcName); + return result; +} +#endif + +#endif diff --git a/common/c-api/subscriberstatetable.cpp b/common/c-api/subscriberstatetable.cpp index 4d3a04953..3e1deb8ec 100644 --- a/common/c-api/subscriberstatetable.cpp +++ b/common/c-api/subscriberstatetable.cpp @@ -14,34 +14,37 @@ using namespace swss; using namespace std; using boost::numeric_cast; -SWSSSubscriberStateTable SWSSSubscriberStateTable_new(SWSSDBConnector db, const char *tableName, - const int32_t *p_popBatchSize, - const int32_t *p_pri) { - int popBatchSize = p_popBatchSize ? numeric_cast(*p_popBatchSize) - : TableConsumable::DEFAULT_POP_BATCH_SIZE; - int pri = p_pri ? numeric_cast(*p_pri) : 0; - SWSSTry(return (SWSSSubscriberStateTable) new SubscriberStateTable( - (DBConnector *)db, string(tableName), popBatchSize, pri)); +SWSSResult SWSSSubscriberStateTable_new(SWSSDBConnector db, const char *tableName, + const int32_t *p_popBatchSize, const int32_t *p_pri, + SWSSSubscriberStateTable *outTbl) { + SWSSTry({ + int popBatchSize = p_popBatchSize ? numeric_cast(*p_popBatchSize) + : TableConsumable::DEFAULT_POP_BATCH_SIZE; + int pri = p_pri ? numeric_cast(*p_pri) : 0; + *outTbl = (SWSSSubscriberStateTable) new SubscriberStateTable( + (DBConnector *)db, string(tableName), popBatchSize, pri); + }); } -void SWSSSubscriberStateTable_free(SWSSSubscriberStateTable tbl) { - delete (SubscriberStateTable *)tbl; +SWSSResult SWSSSubscriberStateTable_free(SWSSSubscriberStateTable tbl) { + SWSSTry(delete (SubscriberStateTable *)tbl); } -SWSSKeyOpFieldValuesArray SWSSSubscriberStateTable_pops(SWSSSubscriberStateTable tbl) { +SWSSResult SWSSSubscriberStateTable_pops(SWSSSubscriberStateTable tbl, + SWSSKeyOpFieldValuesArray *outArr) { SWSSTry({ deque vkco; ((SubscriberStateTable *)tbl)->pops(vkco); - return makeKeyOpFieldValuesArray(vkco); + *outArr = makeKeyOpFieldValuesArray(vkco); }); } -uint32_t SWSSSubscriberStateTable_getFd(SWSSSubscriberStateTable tbl) { - SWSSTry(return numeric_cast(((SubscriberStateTable *)tbl)->getFd())); +SWSSResult SWSSSubscriberStateTable_getFd(SWSSSubscriberStateTable tbl, uint32_t *outFd) { + SWSSTry(*outFd = numeric_cast(((SubscriberStateTable *)tbl)->getFd())); } -SWSSSelectResult SWSSSubscriberStateTable_readData(SWSSSubscriberStateTable tbl, - uint32_t timeout_ms, - uint8_t interrupt_on_signal) { - SWSSTry(return selectOne((SubscriberStateTable *)tbl, timeout_ms, interrupt_on_signal)); +SWSSResult SWSSSubscriberStateTable_readData(SWSSSubscriberStateTable tbl, uint32_t timeout_ms, + uint8_t interrupt_on_signal, + SWSSSelectResult *outResult) { + SWSSTry(*outResult = selectOne((SubscriberStateTable *)tbl, timeout_ms, interrupt_on_signal)); } diff --git a/common/c-api/subscriberstatetable.h b/common/c-api/subscriberstatetable.h index ed0924c81..5f7444063 100644 --- a/common/c-api/subscriberstatetable.h +++ b/common/c-api/subscriberstatetable.h @@ -2,6 +2,7 @@ #define SWSS_COMMON_C_API_SUBSCRIBERSTATETABLE_H #include "dbconnector.h" +#include "result.h" #include "util.h" #ifdef __cplusplus @@ -12,27 +13,28 @@ extern "C" { typedef struct SWSSSubscriberStateTableOpaque *SWSSSubscriberStateTable; -// Pass NULL for popBatchSize and/or pri to use the default values -SWSSSubscriberStateTable SWSSSubscriberStateTable_new(SWSSDBConnector db, const char *tableName, - const int32_t *popBatchSize, - const int32_t *pri); +SWSSResult SWSSSubscriberStateTable_new(SWSSDBConnector db, const char *tableName, + const int32_t *popBatchSize, const int32_t *pri, + SWSSSubscriberStateTable *outTbl); -void SWSSSubscriberStateTable_free(SWSSSubscriberStateTable tbl); +// Frees the SubscriberStateTable +SWSSResult SWSSSubscriberStateTable_free(SWSSSubscriberStateTable tbl); // Result array and all of its members must be freed using free() -SWSSKeyOpFieldValuesArray SWSSSubscriberStateTable_pops(SWSSSubscriberStateTable tbl); +SWSSResult SWSSSubscriberStateTable_pops(SWSSSubscriberStateTable 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, SWSSSubscriberStateTable_readData must be used to // reset the fd and read data into internal data structures. -uint32_t SWSSSubscriberStateTable_getFd(SWSSSubscriberStateTable tbl); +SWSSResult SWSSSubscriberStateTable_getFd(SWSSSubscriberStateTable 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 SWSSSubscriberStateTable_readData(SWSSSubscriberStateTable tbl, - uint32_t timeout_ms, - uint8_t interrupt_on_sugnal); +SWSSResult SWSSSubscriberStateTable_readData(SWSSSubscriberStateTable tbl, uint32_t timeout_ms, + uint8_t interrupt_on_signal, + SWSSSelectResult *outResult); #ifdef __cplusplus } diff --git a/common/c-api/table.cpp b/common/c-api/table.cpp index af08cbaa8..d3e88c9cb 100644 --- a/common/c-api/table.cpp +++ b/common/c-api/table.cpp @@ -9,63 +9,65 @@ using namespace swss; using namespace std; -SWSSTable SWSSTable_new(SWSSDBConnector db, const char *tableName) { - SWSSTry(return (SWSSTable) new Table((DBConnector *)db, string(tableName))); +SWSSResult SWSSTable_new(SWSSDBConnector db, const char *tableName, SWSSTable *outTbl) { + SWSSTry(*outTbl = (SWSSTable) new Table((DBConnector *)db, string(tableName))); } -void SWSSTable_free(SWSSTable tbl) { +SWSSResult SWSSTable_free(SWSSTable tbl) { SWSSTry(delete (Table *)tbl); } -int8_t SWSSTable_get(SWSSTable tbl, const char *key, SWSSFieldValueArray *outValues) { +SWSSResult SWSSTable_get(SWSSTable tbl, const char *key, SWSSFieldValueArray *outValues, + int8_t *outExists) { SWSSTry({ vector fvs; bool exists = ((Table *)tbl)->get(string(key), fvs); if (exists) { *outValues = makeFieldValueArray(fvs); - return 1; + *outExists = 1; } else { - return 0; + *outExists = 0; } }); } -int8_t SWSSTable_hget(SWSSTable tbl, const char *key, const char *field, SWSSString *outValue) { +SWSSResult SWSSTable_hget(SWSSTable tbl, const char *key, const char *field, SWSSString *outValue, + int8_t *outExists) { SWSSTry({ string s; bool exists = ((Table *)tbl)->hget(string(key), string(field), s); if (exists) { *outValue = makeString(move(s)); - return 1; + *outExists = 1; } else { - return 0; + *outExists = 0; } }); } -void SWSSTable_set(SWSSTable tbl, const char *key, SWSSFieldValueArray values) { +SWSSResult SWSSTable_set(SWSSTable tbl, const char *key, SWSSFieldValueArray values) { SWSSTry({ vector 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)); }); +SWSSResult 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)); }); +SWSSResult 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)); }); +SWSSResult SWSSTable_hdel(SWSSTable tbl, const char *key, const char *field) { + SWSSTry(((Table *)tbl)->hdel(string(key), string(field))); } -SWSSStringArray SWSSTable_getKeys(SWSSTable tbl) { +SWSSResult SWSSTable_getKeys(SWSSTable tbl, SWSSStringArray *outKeys) { SWSSTry({ vector keys; ((Table *)tbl)->getKeys(keys); - return makeStringArray(move(keys)); - }) + *outKeys = makeStringArray(move(keys)); + }); } diff --git a/common/c-api/table.h b/common/c-api/table.h index 0d06e1e7d..087bec815 100644 --- a/common/c-api/table.h +++ b/common/c-api/table.h @@ -2,6 +2,7 @@ #define SWSS_COMMON_C_API_TABLE_H #include "dbconnector.h" +#include "result.h" #include "util.h" #ifdef __cplusplus @@ -12,27 +13,29 @@ extern "C" { typedef struct SWSSTableOpaque *SWSSTable; -SWSSTable SWSSTable_new(SWSSDBConnector db, const char *tableName); +SWSSResult SWSSTable_new(SWSSDBConnector db, const char *tableName, SWSSTable *outTbl); -void SWSSTable_free(SWSSTable tbl); +SWSSResult 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 exists, populates outValues with the table's values and outputs 1. +// If the key doesn't exist, outputs 0 and does not touch outValues. +SWSSResult SWSSTable_get(SWSSTable tbl, const char *key, SWSSFieldValueArray *outValues, + int8_t *outExists); -// 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); +// If the key and field exist, populates outValue with the field's value and outputs 1. +// If the key doesn't exist, outputs 0 and does not touch outValue. +SWSSResult SWSSTable_hget(SWSSTable tbl, const char *key, const char *field, SWSSString *outValue, + int8_t *outExists); -void SWSSTable_set(SWSSTable tbl, const char *key, SWSSFieldValueArray values); +SWSSResult SWSSTable_set(SWSSTable tbl, const char *key, SWSSFieldValueArray values); -void SWSSTable_hset(SWSSTable tbl, const char *key, const char *field, SWSSStrRef value); +SWSSResult SWSSTable_hset(SWSSTable tbl, const char *key, const char *field, SWSSStrRef value); -void SWSSTable_del(SWSSTable tbl, const char *key); +SWSSResult SWSSTable_del(SWSSTable tbl, const char *key); -void SWSSTable_hdel(SWSSTable tbl, const char *key, const char *field); +SWSSResult SWSSTable_hdel(SWSSTable tbl, const char *key, const char *field); -SWSSStringArray SWSSTable_getKeys(SWSSTable tbl); +SWSSResult SWSSTable_getKeys(SWSSTable tbl, SWSSStringArray *outKeys); #ifdef __cplusplus } diff --git a/common/c-api/util.cpp b/common/c-api/util.cpp index 26cc1b0f4..bc173420c 100644 --- a/common/c-api/util.cpp +++ b/common/c-api/util.cpp @@ -2,36 +2,34 @@ using namespace swss; -bool swss::cApiTestingDisableAbort = false; - SWSSString SWSSString_new(const char *data, uint64_t length) { - SWSSTry(return makeString(std::string(data, numeric_cast(length)))); + return makeString(std::string(data, numeric_cast(length))); } SWSSString SWSSString_new_c_str(const char *c_str) { - SWSSTry(return makeString(std::string(c_str))); + return makeString(std::string(c_str)); } const char *SWSSStrRef_c_str(SWSSStrRef s) { - SWSSTry(return ((std::string *)s)->c_str()); + return ((std::string *)s)->c_str(); } uint64_t SWSSStrRef_length(SWSSStrRef s) { - SWSSTry(return ((std::string *)s)->length()); + return ((std::string *)s)->length(); } void SWSSString_free(SWSSString s) { - SWSSTry(delete (std::string *)s); + delete (std::string *)s; } void SWSSFieldValueArray_free(SWSSFieldValueArray arr) { - SWSSTry(delete[] arr.data); + delete[] arr.data; } void SWSSKeyOpFieldValuesArray_free(SWSSKeyOpFieldValuesArray kfvs) { - SWSSTry(delete[] kfvs.data); + delete[] kfvs.data; } void SWSSStringArray_free(SWSSStringArray arr) { - SWSSTry(delete[] arr.data); + delete[] arr.data; } diff --git a/common/c-api/util.h b/common/c-api/util.h index aa0d66fbe..42785edcf 100644 --- a/common/c-api/util.h +++ b/common/c-api/util.h @@ -20,12 +20,14 @@ typedef struct SWSSStrRefOpaque *SWSSStrRef; // FFI version of swss::FieldValueTuple // field should be freed with libc's free() +// value should be freed with SWSSString_free() typedef struct { const char *field; SWSSString value; } SWSSFieldValueTuple; // FFI version of std::vector +// data should be freed with SWSSFieldValueArray_free() typedef struct { uint64_t len; SWSSFieldValueTuple *data; @@ -37,6 +39,8 @@ typedef enum { } SWSSKeyOperation; // FFI version of swss::KeyOpFieldValuesTuple +// key should be freed with libc's free() +// fieldValues should be freed with SWSSFieldValueArray_free() typedef struct { const char *key; SWSSKeyOperation operation; @@ -44,6 +48,7 @@ typedef struct { } SWSSKeyOpFieldValues; // FFI version of std::vector +// data should be freed with SWSSKeyOpFieldValuesArray_free() typedef struct { uint64_t len; SWSSKeyOpFieldValues *data; @@ -61,7 +66,8 @@ typedef enum { } SWSSSelectResult; // FFI version of std::vector -// data strings should be freed with libc's free() +// strings in data should be freed with libc's free() +// data should be freed with SWSSStringArray_free() typedef struct { uint64_t len; const char **data; @@ -121,40 +127,20 @@ void SWSSStringArray_free(SWSSStringArray arr); using boost::numeric_cast; -namespace swss { - -extern bool cApiTestingDisableAbort; - -// In the catch block, we must abort because passing an exception across an ffi boundary is -// undefined behavior. It was also decided that no exceptions in swss-common are recoverable, so -// there is no reason to convert exceptions into a returnable type. -#define SWSSTry(...) \ - if (swss::cApiTestingDisableAbort) { \ - { __VA_ARGS__; } \ - } else { \ - try { \ - { __VA_ARGS__; } \ - } catch (std::exception & e) { \ - std::cerr << "Aborting due to exception: " << e.what() << std::endl; \ - SWSS_LOG_ERROR("Aborting due to exception: %s", e.what()); \ - std::abort(); \ - } \ - } - static inline SWSSSelectResult selectOne(swss::Selectable *s, uint32_t timeout_ms, uint8_t interrupt_on_signal) { - Select select; - Selectable *sOut; + swss::Select select; + swss::Selectable *sOut; select.addSelectable(s); int ret = select.select(&sOut, numeric_cast(timeout_ms), interrupt_on_signal); switch (ret) { - case Select::OBJECT: + case swss::Select::OBJECT: return SWSSSelectResult_DATA; - case Select::ERROR: + case swss::Select::ERROR: throw std::system_error(errno, std::generic_category()); - case Select::TIMEOUT: + case swss::Select::TIMEOUT: return SWSSSelectResult_TIMEOUT; - case Select::SIGNALINT: + case swss::Select::SIGNALINT: return SWSSSelectResult_SIGNAL; default: SWSS_LOG_THROW("impossible: unhandled Select::select() return value: %d", ret); @@ -286,7 +272,5 @@ takeKeyOpFieldValuesArray(SWSSKeyOpFieldValuesArray in) { return out; } -} // namespace swss - #endif #endif diff --git a/common/c-api/zmqclient.cpp b/common/c-api/zmqclient.cpp index fa1d59ca2..9b0ef971a 100644 --- a/common/c-api/zmqclient.cpp +++ b/common/c-api/zmqclient.cpp @@ -6,25 +6,24 @@ using namespace swss; using namespace std; -SWSSZmqClient SWSSZmqClient_new(const char *endpoint) { - SWSSTry(return (SWSSZmqClient) new ZmqClient(endpoint)); +SWSSResult SWSSZmqClient_new(const char *endpoint, SWSSZmqClient *outClient) { + SWSSTry(*outClient = (SWSSZmqClient) new ZmqClient(endpoint)); } -void SWSSZmqClient_free(SWSSZmqClient zmqc) { +SWSSResult SWSSZmqClient_free(SWSSZmqClient zmqc) { SWSSTry(delete (ZmqClient *)zmqc); } -// Returns 0 for false, 1 for true -int8_t SWSSZmqClient_isConnected(SWSSZmqClient zmqc) { - SWSSTry(return ((ZmqClient *)zmqc)->isConnected() ? 1 : 0); +SWSSResult SWSSZmqClient_isConnected(SWSSZmqClient zmqc, int8_t *outIsConnected) { + SWSSTry(*outIsConnected = ((ZmqClient *)zmqc)->isConnected() ? 1 : 0); } -void SWSSZmqClient_connect(SWSSZmqClient zmqc) { +SWSSResult SWSSZmqClient_connect(SWSSZmqClient zmqc) { SWSSTry(((ZmqClient *)zmqc)->connect()); } -void SWSSZmqClient_sendMsg(SWSSZmqClient zmqc, const char *dbName, const char *tableName, - SWSSKeyOpFieldValuesArray arr) { +SWSSResult SWSSZmqClient_sendMsg(SWSSZmqClient zmqc, const char *dbName, const char *tableName, + SWSSKeyOpFieldValuesArray arr) { SWSSTry({ vector kcos = takeKeyOpFieldValuesArray(arr); ((ZmqClient *)zmqc) diff --git a/common/c-api/zmqclient.h b/common/c-api/zmqclient.h index da832ab30..d846f598d 100644 --- a/common/c-api/zmqclient.h +++ b/common/c-api/zmqclient.h @@ -1,6 +1,7 @@ #ifndef SWSS_COMMON_C_API_ZMQCLIENT_H #define SWSS_COMMON_C_API_ZMQCLIENT_H +#include "result.h" #include "util.h" #ifdef __cplusplus @@ -11,17 +12,17 @@ extern "C" { typedef struct SWSSZmqClientOpaque *SWSSZmqClient; -SWSSZmqClient SWSSZmqClient_new(const char *endpoint); +SWSSResult SWSSZmqClient_new(const char *endpoint, SWSSZmqClient *outZmqc); -void SWSSZmqClient_free(SWSSZmqClient zmqc); +SWSSResult SWSSZmqClient_free(SWSSZmqClient zmqc); -// Returns 0 for false, 1 for true -int8_t SWSSZmqClient_isConnected(SWSSZmqClient zmqc); +// Outputs 0 for false, 1 for true +SWSSResult SWSSZmqClient_isConnected(SWSSZmqClient zmqc, int8_t *outIsConnected); -void SWSSZmqClient_connect(SWSSZmqClient zmqc); +SWSSResult SWSSZmqClient_connect(SWSSZmqClient zmqc); -void SWSSZmqClient_sendMsg(SWSSZmqClient zmqc, const char *dbName, const char *tableName, - SWSSKeyOpFieldValuesArray kcos); +SWSSResult SWSSZmqClient_sendMsg(SWSSZmqClient zmqc, const char *dbName, const char *tableName, + SWSSKeyOpFieldValuesArray kcos); #ifdef __cplusplus } diff --git a/common/c-api/zmqconsumerstatetable.cpp b/common/c-api/zmqconsumerstatetable.cpp index ed416488e..59ed7dde4 100644 --- a/common/c-api/zmqconsumerstatetable.cpp +++ b/common/c-api/zmqconsumerstatetable.cpp @@ -1,4 +1,3 @@ -#include #include "../zmqconsumerstatetable.h" #include "../table.h" #include "util.h" @@ -11,41 +10,43 @@ using namespace std; using boost::numeric_cast; // Pass NULL for popBatchSize and/or pri to use the default values -SWSSZmqConsumerStateTable SWSSZmqConsumerStateTable_new(SWSSDBConnector db, const char *tableName, - SWSSZmqServer zmqs, - const int32_t *p_popBatchSize, - const int32_t *p_pri) { - - int popBatchSize = p_popBatchSize ? numeric_cast(*p_popBatchSize) - : TableConsumable::DEFAULT_POP_BATCH_SIZE; - int pri = p_pri ? numeric_cast(*p_pri) : 0; - SWSSTry(return (SWSSZmqConsumerStateTable) new ZmqConsumerStateTable( - (DBConnector *)db, string(tableName), *(ZmqServer *)zmqs, popBatchSize, pri)); +SWSSResult SWSSZmqConsumerStateTable_new(SWSSDBConnector db, const char *tableName, + SWSSZmqServer zmqs, const int32_t *p_popBatchSize, + const int32_t *p_pri, SWSSZmqConsumerStateTable *outTbl) { + SWSSTry({ + int popBatchSize = p_popBatchSize ? numeric_cast(*p_popBatchSize) + : TableConsumable::DEFAULT_POP_BATCH_SIZE; + int pri = p_pri ? numeric_cast(*p_pri) : 0; + *outTbl = (SWSSZmqConsumerStateTable) new ZmqConsumerStateTable( + (DBConnector *)db, string(tableName), *(ZmqServer *)zmqs, popBatchSize, pri); + }); } -void SWSSZmqConsumerStateTable_free(SWSSZmqConsumerStateTable tbl) { +SWSSResult SWSSZmqConsumerStateTable_free(SWSSZmqConsumerStateTable tbl) { SWSSTry(delete (ZmqConsumerStateTable *)tbl); } -SWSSKeyOpFieldValuesArray SWSSZmqConsumerStateTable_pops(SWSSZmqConsumerStateTable tbl) { +SWSSResult SWSSZmqConsumerStateTable_pops(SWSSZmqConsumerStateTable tbl, + SWSSKeyOpFieldValuesArray *outArr) { SWSSTry({ deque vkco; ((ZmqConsumerStateTable *)tbl)->pops(vkco); - return makeKeyOpFieldValuesArray(vkco); + *outArr = makeKeyOpFieldValuesArray(vkco); }); } -uint32_t SWSSZmqConsumerStateTable_getFd(SWSSZmqConsumerStateTable tbl) { - SWSSTry(return numeric_cast(((ZmqConsumerStateTable *)tbl)->getFd())); +SWSSResult SWSSZmqConsumerStateTable_getFd(SWSSZmqConsumerStateTable tbl, uint32_t *outFd) { + SWSSTry(*outFd = numeric_cast(((ZmqConsumerStateTable *)tbl)->getFd())); } -SWSSSelectResult SWSSZmqConsumerStateTable_readData(SWSSZmqConsumerStateTable tbl, - uint32_t timeout_ms, - uint8_t interrupt_on_signal) { - SWSSTry(return selectOne((ZmqConsumerStateTable *)tbl, timeout_ms, interrupt_on_signal)); +SWSSResult SWSSZmqConsumerStateTable_readData(SWSSZmqConsumerStateTable tbl, uint32_t timeout_ms, + uint8_t interrupt_on_signal, + SWSSSelectResult *outResult) { + SWSSTry(*outResult = selectOne((ZmqConsumerStateTable *)tbl, timeout_ms, interrupt_on_signal)); } -const struct SWSSDBConnectorOpaque * -SWSSZmqConsumerStateTable_getDbConnector(SWSSZmqConsumerStateTable tbl) { - SWSSTry(return (const SWSSDBConnectorOpaque *)((ZmqConsumerStateTable *)tbl)->getDbConnector()); +SWSSResult SWSSZmqConsumerStateTable_getDbConnector(SWSSZmqConsumerStateTable tbl, + const struct SWSSDBConnectorOpaque **outDb) { + SWSSTry(*outDb = + (const SWSSDBConnectorOpaque *)((ZmqConsumerStateTable *)tbl)->getDbConnector()); } diff --git a/common/c-api/zmqconsumerstatetable.h b/common/c-api/zmqconsumerstatetable.h index f5b934258..f781f6bc8 100644 --- a/common/c-api/zmqconsumerstatetable.h +++ b/common/c-api/zmqconsumerstatetable.h @@ -2,6 +2,7 @@ #define SWSS_COMMON_C_API_ZMQCONSUMERSTATETABLE_H #include "dbconnector.h" +#include "result.h" #include "util.h" #include "zmqserver.h" @@ -13,31 +14,32 @@ extern "C" { typedef struct SWSSZmqConsumerStateTableOpaque *SWSSZmqConsumerStateTable; -// Pass NULL for popBatchSize and/or pri to use the default values -SWSSZmqConsumerStateTable SWSSZmqConsumerStateTable_new(SWSSDBConnector db, const char *tableName, - SWSSZmqServer zmqs, - const int32_t *popBatchSize, - const int32_t *pri); +SWSSResult SWSSZmqConsumerStateTable_new(SWSSDBConnector db, const char *tableName, + SWSSZmqServer zmqs, const int32_t *popBatchSize, + const int32_t *pri, SWSSZmqConsumerStateTable *outTbl); -void SWSSZmqConsumerStateTable_free(SWSSZmqConsumerStateTable tbl); +// Outputs NULL for popBatchSize and/or pri to use the default values +SWSSResult SWSSZmqConsumerStateTable_free(SWSSZmqConsumerStateTable tbl); // Result array and all of its members must be freed using free() -SWSSKeyOpFieldValuesArray SWSSZmqConsumerStateTable_pops(SWSSZmqConsumerStateTable tbl); +SWSSResult SWSSZmqConsumerStateTable_pops(SWSSZmqConsumerStateTable tbl, + SWSSKeyOpFieldValuesArray *outArr); -// Return the underlying fd for polling/selecting on. +// Outputs the underlying fd for polling/selecting on. // Callers must NOT read/write on fd, it may only be used for epoll or similar. // After the fd becomes readable, SWSSZmqConsumerStateTable_readData must be used to // reset the fd and read data into internal data structures. -uint32_t SWSSZmqConsumerStateTable_getFd(SWSSZmqConsumerStateTable tbl); +SWSSResult SWSSZmqConsumerStateTable_getFd(SWSSZmqConsumerStateTable 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 SWSSZmqConsumerStateTable_readData(SWSSZmqConsumerStateTable tbl, - uint32_t timeout_ms, - uint8_t interrupt_on_signal); +SWSSResult SWSSZmqConsumerStateTable_readData(SWSSZmqConsumerStateTable tbl, uint32_t timeout_ms, + uint8_t interrupt_on_signal, + SWSSSelectResult *outResult); -const struct SWSSDBConnectorOpaque * -SWSSZmqConsumerStateTable_getDbConnector(SWSSZmqConsumerStateTable tbl); +SWSSResult +SWSSZmqConsumerStateTable_getDbConnector(SWSSZmqConsumerStateTable tbl, + const struct SWSSDBConnectorOpaque **outDbConnector); #ifdef __cplusplus } diff --git a/common/c-api/zmqproducerstatetable.cpp b/common/c-api/zmqproducerstatetable.cpp index e1c186806..b9192ee39 100644 --- a/common/c-api/zmqproducerstatetable.cpp +++ b/common/c-api/zmqproducerstatetable.cpp @@ -1,32 +1,34 @@ #include -#include "zmqproducerstatetable.h" #include "../zmqproducerstatetable.h" +#include "zmqproducerstatetable.h" using namespace std; using namespace swss; using boost::numeric_cast; -SWSSZmqProducerStateTable SWSSZmqProducerStateTable_new(SWSSDBConnector db, const char *tableName, - SWSSZmqClient zmqc, uint8_t dbPersistence) { - - SWSSTry(return (SWSSZmqProducerStateTable) new ZmqProducerStateTable( - (DBConnector *)db, string(tableName), *(ZmqClient *)zmqc, dbPersistence)); +SWSSResult SWSSZmqProducerStateTable_new(SWSSDBConnector db, const char *tableName, + SWSSZmqClient zmqc, uint8_t dbPersistence, + SWSSZmqProducerStateTable *outTbl) { + SWSSTry(*outTbl = (SWSSZmqProducerStateTable) new ZmqProducerStateTable( + (DBConnector *)db, string(tableName), *(ZmqClient *)zmqc, dbPersistence)); } -void SWSSZmqProducerStateTable_free(SWSSZmqProducerStateTable tbl) { +SWSSResult SWSSZmqProducerStateTable_free(SWSSZmqProducerStateTable tbl) { SWSSTry(delete (ZmqProducerStateTable *)tbl); } -void SWSSZmqProducerStateTable_set(SWSSZmqProducerStateTable tbl, const char *key, - SWSSFieldValueArray values) { +SWSSResult SWSSZmqProducerStateTable_set(SWSSZmqProducerStateTable tbl, const char *key, + SWSSFieldValueArray values) { SWSSTry(((ZmqProducerStateTable *)tbl)->set(string(key), takeFieldValueArray(values))); } -void SWSSZmqProducerStateTable_del(SWSSZmqProducerStateTable tbl, const char *key) { +SWSSResult SWSSZmqProducerStateTable_del(SWSSZmqProducerStateTable tbl, const char *key) { SWSSTry(((ZmqProducerStateTable *)tbl)->del(string(key))); } -uint64_t SWSSZmqProducerStateTable_dbUpdaterQueueSize(SWSSZmqProducerStateTable tbl) { - SWSSTry(return numeric_cast(((ZmqProducerStateTable *)tbl)->dbUpdaterQueueSize())); +SWSSResult SWSSZmqProducerStateTable_dbUpdaterQueueSize(SWSSZmqProducerStateTable tbl, + uint64_t *outSize) { + SWSSTry(*outSize = + numeric_cast(((ZmqProducerStateTable *)tbl)->dbUpdaterQueueSize())); } diff --git a/common/c-api/zmqproducerstatetable.h b/common/c-api/zmqproducerstatetable.h index 08d059186..f308fbb02 100644 --- a/common/c-api/zmqproducerstatetable.h +++ b/common/c-api/zmqproducerstatetable.h @@ -2,6 +2,7 @@ #define SWSS_COMMON_C_API_ZMQPRODUCERSTATETABLE_H #include "dbconnector.h" +#include "result.h" #include "util.h" #include "zmqclient.h" @@ -13,17 +14,18 @@ extern "C" { typedef struct SWSSZmqProducerStateTableOpaque *SWSSZmqProducerStateTable; -SWSSZmqProducerStateTable SWSSZmqProducerStateTable_new(SWSSDBConnector db, const char *tableName, - SWSSZmqClient zmqc, uint8_t dbPersistence); +SWSSResult SWSSZmqProducerStateTable_new(SWSSDBConnector db, const char *tableName, + SWSSZmqClient zmqc, uint8_t dbPersistence, + SWSSZmqProducerStateTable *outTbl); -void SWSSZmqProducerStateTable_free(SWSSZmqProducerStateTable tbl); +SWSSResult SWSSZmqProducerStateTable_free(SWSSZmqProducerStateTable tbl); -void SWSSZmqProducerStateTable_set(SWSSZmqProducerStateTable tbl, const char *key, - SWSSFieldValueArray values); +SWSSResult SWSSZmqProducerStateTable_set(SWSSZmqProducerStateTable tbl, const char *key, + SWSSFieldValueArray values); -void SWSSZmqProducerStateTable_del(SWSSZmqProducerStateTable tbl, const char *key); +SWSSResult SWSSZmqProducerStateTable_del(SWSSZmqProducerStateTable tbl, const char *key); -uint64_t SWSSZmqProducerStateTable_dbUpdaterQueueSize(SWSSZmqProducerStateTable tbl); +SWSSResult SWSSZmqProducerStateTable_dbUpdaterQueueSize(SWSSZmqProducerStateTable tbl, uint64_t *outSize); #ifdef __cplusplus } diff --git a/common/c-api/zmqserver.cpp b/common/c-api/zmqserver.cpp index 50452e22d..b2937ae38 100644 --- a/common/c-api/zmqserver.cpp +++ b/common/c-api/zmqserver.cpp @@ -5,10 +5,10 @@ using namespace swss; using namespace std; -SWSSZmqServer SWSSZmqServer_new(const char *endpoint) { - SWSSTry(return (SWSSZmqServer) new ZmqServer(string(endpoint))); +SWSSResult SWSSZmqServer_new(const char *endpoint, SWSSZmqServer *outZmqServer) { + SWSSTry(*outZmqServer = (SWSSZmqServer) new ZmqServer(string(endpoint))); } -void SWSSZmqServer_free(SWSSZmqServer zmqs) { +SWSSResult SWSSZmqServer_free(SWSSZmqServer zmqs) { SWSSTry(delete (ZmqServer *)zmqs); } diff --git a/common/c-api/zmqserver.h b/common/c-api/zmqserver.h index decd0e0dc..ee76af420 100644 --- a/common/c-api/zmqserver.h +++ b/common/c-api/zmqserver.h @@ -1,6 +1,7 @@ #ifndef SWSS_COMMON_C_API_ZMQSERVER_H #define SWSS_COMMON_C_API_ZMQSERVER_H +#include "result.h" #include "util.h" #ifdef __cplusplus @@ -9,9 +10,9 @@ extern "C" { typedef struct SWSSZmqServerOpaque *SWSSZmqServer; -SWSSZmqServer SWSSZmqServer_new(const char *endpoint); +SWSSResult SWSSZmqServer_new(const char *endpoint, SWSSZmqServer *outZmqServer); -void SWSSZmqServer_free(SWSSZmqServer zmqs); +SWSSResult SWSSZmqServer_free(SWSSZmqServer zmqs); #ifdef __cplusplus } diff --git a/tests/c_api_ut.cpp b/tests/c_api_ut.cpp index 90fffdaa2..3bee372c1 100644 --- a/tests/c_api_ut.cpp +++ b/tests/c_api_ut.cpp @@ -1,9 +1,12 @@ +#include +#include #include #include #include "common/c-api/consumerstatetable.h" #include "common/c-api/dbconnector.h" #include "common/c-api/producerstatetable.h" +#include "common/c-api/result.h" #include "common/c-api/subscriberstatetable.h" #include "common/c-api/table.h" #include "common/c-api/util.h" @@ -59,9 +62,17 @@ static void freeKeyOpFieldValuesArray(SWSSKeyOpFieldValuesArray arr) { struct SWSSStringManager { vector m_strings; + bool use_c_str = false; SWSSString makeString(const char *c_str) { - SWSSString s = SWSSString_new_c_str(c_str); + use_c_str = !use_c_str; + + SWSSString s; + if (use_c_str) { + s = SWSSString_new_c_str(c_str); + } else { + s = SWSSString_new(c_str, strlen(c_str)); + } m_strings.push_back(s); return s; } @@ -80,33 +91,61 @@ TEST(c_api, DBConnector) { clearDB(); SWSSStringManager sm; - EXPECT_THROW(SWSSDBConnector_new_named("does not exist", 0, true), out_of_range); - SWSSDBConnector db = SWSSDBConnector_new_named("TEST_DB", 1000, true); - EXPECT_EQ(SWSSDBConnector_get(db, "mykey"), nullptr); - EXPECT_FALSE(SWSSDBConnector_exists(db, "mykey")); + SWSSDBConnector db; + SWSSDBConnector_new_named("TEST_DB", 1000, true, &db); + + SWSSString val; + SWSSDBConnector_get(db, "mykey", &val); + EXPECT_EQ(val, nullptr); + + int8_t exists; + SWSSDBConnector_exists(db, "mykey", &exists); + EXPECT_FALSE(exists); SWSSDBConnector_set(db, "mykey", sm.makeStrRef("myval")); - SWSSString val = SWSSDBConnector_get(db, "mykey"); + SWSSDBConnector_get(db, "mykey", &val); EXPECT_STREQ(SWSSStrRef_c_str((SWSSStrRef)val), "myval"); SWSSString_free(val); - EXPECT_TRUE(SWSSDBConnector_exists(db, "mykey")); - EXPECT_TRUE(SWSSDBConnector_del(db, "mykey")); - EXPECT_FALSE(SWSSDBConnector_del(db, "mykey")); - EXPECT_FALSE(SWSSDBConnector_hget(db, "mykey", "myfield")); - EXPECT_FALSE(SWSSDBConnector_hexists(db, "mykey", "myfield")); + SWSSDBConnector_exists(db, "mykey", &exists); + EXPECT_TRUE(exists); + + int8_t status; + SWSSDBConnector_del(db, "mykey", &status); + EXPECT_TRUE(status); + + SWSSDBConnector_del(db, "mykey", &status); + EXPECT_FALSE(status); + + SWSSDBConnector_hget(db, "mykey", "myfield", &val); + EXPECT_EQ(val, nullptr); + + SWSSDBConnector_hexists(db, "mykey", "myfield", &exists); + EXPECT_FALSE(exists); + SWSSDBConnector_hset(db, "mykey", "myfield", sm.makeStrRef("myval")); - val = SWSSDBConnector_hget(db, "mykey", "myfield"); + SWSSDBConnector_hget(db, "mykey", "myfield", &val); EXPECT_STREQ(SWSSStrRef_c_str((SWSSStrRef)val), "myval"); SWSSString_free(val); - EXPECT_TRUE(SWSSDBConnector_hexists(db, "mykey", "myfield")); - EXPECT_FALSE(SWSSDBConnector_hget(db, "mykey", "notmyfield")); - EXPECT_FALSE(SWSSDBConnector_hexists(db, "mykey", "notmyfield")); - EXPECT_TRUE(SWSSDBConnector_hdel(db, "mykey", "myfield")); - EXPECT_FALSE(SWSSDBConnector_hdel(db, "mykey", "myfield")); + SWSSDBConnector_hexists(db, "mykey", "myfield", &exists); + EXPECT_TRUE(exists); + + SWSSDBConnector_hget(db, "mykey", "notmyfield", &val); + EXPECT_EQ(val, nullptr); + + SWSSDBConnector_hexists(db, "mykey", "notmyfield", &exists); + EXPECT_FALSE(exists); + + SWSSDBConnector_hdel(db, "mykey", "myfield", &status); + EXPECT_TRUE(status); + + SWSSDBConnector_hdel(db, "mykey", "myfield", &status); + EXPECT_FALSE(status); + + SWSSDBConnector_flushdb(db, &status); + EXPECT_TRUE(status); - EXPECT_TRUE(SWSSDBConnector_flushdb(db)); SWSSDBConnector_free(db); } @@ -114,31 +153,39 @@ TEST(c_api, Table) { clearDB(); SWSSStringManager sm; - SWSSDBConnector db = SWSSDBConnector_new_named("TEST_DB", 1000, true); - SWSSTable tbl = SWSSTable_new(db, "mytable"); + SWSSDBConnector db; + SWSSDBConnector_new_named("TEST_DB", 1000, true, &db); + SWSSTable tbl; + SWSSTable_new(db, "mytable", &tbl); SWSSFieldValueArray fvs; SWSSString ss; - EXPECT_FALSE(SWSSTable_get(tbl, "mykey", &fvs)); - EXPECT_FALSE(SWSSTable_hget(tbl, "mykey", "myfield", &ss)); - - SWSSStringArray keys = SWSSTable_getKeys(tbl); + int8_t exists; + SWSSTable_get(tbl, "mykey", &fvs, &exists); + EXPECT_FALSE(exists); + SWSSTable_hget(tbl, "mykey", "myfield", &ss, &exists); + EXPECT_FALSE(exists); + + SWSSStringArray keys; + SWSSTable_getKeys(tbl, &keys); EXPECT_EQ(keys.len, 0); SWSSStringArray_free(keys); SWSSTable_hset(tbl, "mykey", "myfield", sm.makeStrRef("myvalue")); - keys = SWSSTable_getKeys(tbl); + SWSSTable_getKeys(tbl, &keys); 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)); + SWSSTable_hget(tbl, "mykey", "myfield", &ss, &exists); + ASSERT_TRUE(exists); EXPECT_STREQ(SWSSStrRef_c_str((SWSSStrRef)ss), "myvalue"); SWSSString_free(ss); SWSSTable_hdel(tbl, "mykey", "myfield"); - EXPECT_FALSE(SWSSTable_hget(tbl, "mykey", "myfield", &ss)); + SWSSTable_hget(tbl, "mykey", "myfield", &ss, &exists); + EXPECT_FALSE(exists); SWSSFieldValueTuple data[2] = {{.field = "myfield1", .value = sm.makeString("myvalue1")}, {.field = "myfield2", .value = sm.makeString("myvalue2")}}; @@ -146,14 +193,15 @@ TEST(c_api, Table) { fvs.data = data; SWSSTable_set(tbl, "mykey", fvs); - ASSERT_TRUE(SWSSTable_get(tbl, "mykey", &fvs)); - EXPECT_EQ(fvs.len, 2); + SWSSTable_get(tbl, "mykey", &fvs, &exists); + ASSERT_TRUE(exists); + ASSERT_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); + SWSSTable_getKeys(tbl, &keys); EXPECT_EQ(keys.len, 0); SWSSStringArray_free(keys); @@ -165,13 +213,18 @@ TEST(c_api, ConsumerProducerStateTables) { clearDB(); SWSSStringManager sm; - SWSSDBConnector db = SWSSDBConnector_new_named("TEST_DB", 1000, true); - SWSSProducerStateTable pst = SWSSProducerStateTable_new(db, "mytable"); - SWSSConsumerStateTable cst = SWSSConsumerStateTable_new(db, "mytable", nullptr, nullptr); + SWSSDBConnector db; + SWSSDBConnector_new_named("TEST_DB", 1000, true, &db); + SWSSProducerStateTable pst; + SWSSProducerStateTable_new(db, "mytable", &pst); + SWSSConsumerStateTable cst; + SWSSConsumerStateTable_new(db, "mytable", nullptr, nullptr, &cst); - SWSSConsumerStateTable_getFd(cst); + uint32_t fd; + SWSSConsumerStateTable_getFd(cst, &fd); - SWSSKeyOpFieldValuesArray arr = SWSSConsumerStateTable_pops(cst); + SWSSKeyOpFieldValuesArray arr; + SWSSConsumerStateTable_pops(cst, &arr); ASSERT_EQ(arr.len, 0); freeKeyOpFieldValuesArray(arr); @@ -187,8 +240,9 @@ TEST(c_api, ConsumerProducerStateTables) { values.len = 1; SWSSProducerStateTable_set(pst, "mykey2", values); - ASSERT_EQ(SWSSConsumerStateTable_readData(cst, 300, true), SWSSSelectResult_DATA); - arr = SWSSConsumerStateTable_pops(cst); + SWSSSelectResult result; + SWSSConsumerStateTable_readData(cst, 300, true, &result); + SWSSConsumerStateTable_pops(cst, &arr); vector kfvs = takeKeyOpFieldValuesArray(arr); sortKfvs(kfvs); freeKeyOpFieldValuesArray(arr); @@ -210,7 +264,7 @@ TEST(c_api, ConsumerProducerStateTables) { EXPECT_EQ(fieldValues1[0].first, "myfield3"); EXPECT_EQ(fieldValues1[0].second, "myvalue3"); - arr = SWSSConsumerStateTable_pops(cst); + SWSSConsumerStateTable_pops(cst, &arr); EXPECT_EQ(arr.len, 0); freeKeyOpFieldValuesArray(arr); @@ -218,7 +272,7 @@ TEST(c_api, ConsumerProducerStateTables) { SWSSProducerStateTable_del(pst, "mykey4"); SWSSProducerStateTable_del(pst, "mykey5"); - arr = SWSSConsumerStateTable_pops(cst); + SWSSConsumerStateTable_pops(cst, &arr); kfvs = takeKeyOpFieldValuesArray(arr); sortKfvs(kfvs); freeKeyOpFieldValuesArray(arr); @@ -236,7 +290,8 @@ TEST(c_api, ConsumerProducerStateTables) { SWSSProducerStateTable_free(pst); SWSSConsumerStateTable_free(cst); - SWSSDBConnector_flushdb(db); + int8_t flushStatus; + SWSSDBConnector_flushdb(db, &flushStatus); SWSSDBConnector_free(db); } @@ -244,19 +299,26 @@ TEST(c_api, SubscriberStateTable) { clearDB(); SWSSStringManager sm; - SWSSDBConnector db = SWSSDBConnector_new_named("TEST_DB", 1000, true); - SWSSSubscriberStateTable sst = SWSSSubscriberStateTable_new(db, "mytable", nullptr, nullptr); + SWSSDBConnector db; + SWSSDBConnector_new_named("TEST_DB", 1000, true, &db); + SWSSSubscriberStateTable sst; + SWSSSubscriberStateTable_new(db, "mytable", nullptr, nullptr, &sst); - SWSSSubscriberStateTable_getFd(sst); + uint32_t fd; + SWSSSubscriberStateTable_getFd(sst, &fd); - EXPECT_EQ(SWSSSubscriberStateTable_readData(sst, 300, true), SWSSSelectResult_TIMEOUT); - SWSSKeyOpFieldValuesArray arr = SWSSSubscriberStateTable_pops(sst); + SWSSSelectResult result; + SWSSSubscriberStateTable_readData(sst, 300, true, &result); + EXPECT_EQ(result, SWSSSelectResult_TIMEOUT); + SWSSKeyOpFieldValuesArray arr; + SWSSSubscriberStateTable_pops(sst, &arr); EXPECT_EQ(arr.len, 0); freeKeyOpFieldValuesArray(arr); SWSSDBConnector_hset(db, "mytable:mykey", "myfield", sm.makeStrRef("myvalue")); - EXPECT_EQ(SWSSSubscriberStateTable_readData(sst, 300, true), SWSSSelectResult_DATA); - arr = SWSSSubscriberStateTable_pops(sst); + SWSSSubscriberStateTable_readData(sst, 300, true, &result); + EXPECT_EQ(result, SWSSSelectResult_DATA); + SWSSSubscriberStateTable_pops(sst, &arr); vector kfvs = takeKeyOpFieldValuesArray(arr); sortKfvs(kfvs); freeKeyOpFieldValuesArray(arr); @@ -269,7 +331,8 @@ TEST(c_api, SubscriberStateTable) { EXPECT_EQ(kfvFieldsValues(kfvs[0])[0].second, "myvalue"); SWSSSubscriberStateTable_free(sst); - SWSSDBConnector_flushdb(db); + int8_t flushStatus; + SWSSDBConnector_flushdb(db, &flushStatus); SWSSDBConnector_free(db); } @@ -277,27 +340,35 @@ TEST(c_api, ZmqConsumerProducerStateTable) { clearDB(); SWSSStringManager sm; - SWSSDBConnector db = SWSSDBConnector_new_named("TEST_DB", 1000, true); + SWSSDBConnector db; + SWSSDBConnector_new_named("TEST_DB", 1000, true, &db); - SWSSZmqServer srv = SWSSZmqServer_new("tcp://127.0.0.1:42312"); - SWSSZmqClient cli = SWSSZmqClient_new("tcp://127.0.0.1:42312"); - EXPECT_TRUE(SWSSZmqClient_isConnected(cli)); - SWSSZmqClient_connect(cli); // This should be idempotent/not throw + SWSSZmqServer srv; + SWSSZmqServer_new("tcp://127.0.0.1:42312", &srv); + SWSSZmqClient cli; + SWSSZmqClient_new("tcp://127.0.0.1:42312", &cli); + int8_t isConnected; + SWSSZmqClient_isConnected(cli, &isConnected); + ASSERT_TRUE(isConnected); + SWSSZmqClient_connect(cli); - SWSSZmqProducerStateTable pst = SWSSZmqProducerStateTable_new(db, "mytable", cli, false); - SWSSZmqConsumerStateTable cst = - SWSSZmqConsumerStateTable_new(db, "mytable", srv, nullptr, nullptr); + SWSSZmqProducerStateTable pst; + SWSSZmqProducerStateTable_new(db, "mytable", cli, false, &pst); + SWSSZmqConsumerStateTable cst; + SWSSZmqConsumerStateTable_new(db, "mytable", srv, nullptr, nullptr, &cst); - SWSSZmqConsumerStateTable_getFd(cst); + uint32_t fd; + SWSSZmqConsumerStateTable_getFd(cst, &fd); - ASSERT_EQ(SWSSZmqConsumerStateTable_getDbConnector(cst), db); + const SWSSDBConnectorOpaque *dbConnector; + SWSSZmqConsumerStateTable_getDbConnector(cst, &dbConnector); + ASSERT_EQ(dbConnector, db); - SWSSKeyOpFieldValuesArray arr = SWSSZmqConsumerStateTable_pops(cst); + SWSSKeyOpFieldValuesArray arr; + SWSSZmqConsumerStateTable_pops(cst, &arr); ASSERT_EQ(arr.len, 0); freeKeyOpFieldValuesArray(arr); - // 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")}, @@ -325,8 +396,9 @@ TEST(c_api, ZmqConsumerProducerStateTable) { else SWSSZmqClient_sendMsg(cli, "TEST_DB", "mytable", arr); - ASSERT_EQ(SWSSZmqConsumerStateTable_readData(cst, 1500, true), SWSSSelectResult_DATA); - arr = SWSSZmqConsumerStateTable_pops(cst); + SWSSSelectResult result; + SWSSZmqConsumerStateTable_readData(cst, 1500, true, &result); + SWSSZmqConsumerStateTable_pops(cst, &arr); vector kfvs = takeKeyOpFieldValuesArray(arr); sortKfvs(kfvs); @@ -349,7 +421,7 @@ TEST(c_api, ZmqConsumerProducerStateTable) { EXPECT_EQ(fieldValues1[0].first, "myfield3"); EXPECT_EQ(fieldValues1[0].second, "myvalue3"); - arr = SWSSZmqConsumerStateTable_pops(cst); + SWSSZmqConsumerStateTable_pops(cst, &arr); ASSERT_EQ(arr.len, 0); freeKeyOpFieldValuesArray(arr); @@ -363,8 +435,8 @@ TEST(c_api, ZmqConsumerProducerStateTable) { else SWSSZmqClient_sendMsg(cli, "TEST_DB", "mytable", arr); - ASSERT_EQ(SWSSZmqConsumerStateTable_readData(cst, 500, true), SWSSSelectResult_DATA); - arr = SWSSZmqConsumerStateTable_pops(cst); + SWSSZmqConsumerStateTable_readData(cst, 500, true, &result); + SWSSZmqConsumerStateTable_pops(cst, &arr); kfvs = takeKeyOpFieldValuesArray(arr); sortKfvs(kfvs); @@ -379,7 +451,6 @@ TEST(c_api, ZmqConsumerProducerStateTable) { EXPECT_EQ(kfvFieldsValues(kfvs[1]).size(), 0); } - // Server must be freed first to safely release message handlers (ZmqConsumerStateTable) SWSSZmqServer_free(srv); SWSSZmqProducerStateTable_free(pst); @@ -387,6 +458,26 @@ TEST(c_api, ZmqConsumerProducerStateTable) { SWSSZmqClient_free(cli); - SWSSDBConnector_flushdb(db); + int8_t flushStatus; + SWSSDBConnector_flushdb(db, &flushStatus); SWSSDBConnector_free(db); } + +TEST(c_api, exceptions) { + SWSSDBConnector db = nullptr; + SWSSResult result = SWSSDBConnector_new_tcp(0, "127.0.0.1", 1, 1000, &db); + ASSERT_EQ(db, nullptr); + ASSERT_NE(result.exception, SWSSException_None); + ASSERT_NE(result.location, nullptr); + ASSERT_NE(result.message, nullptr); + + const char *cstr = SWSSStrRef_c_str((SWSSStrRef)result.location); + EXPECT_EQ(SWSSStrRef_length((SWSSStrRef)result.location), strlen(cstr)); + printf("Exception location: %s\n", cstr); + cstr = SWSSStrRef_c_str((SWSSStrRef)result.message); + EXPECT_EQ(SWSSStrRef_length((SWSSStrRef)result.message), strlen(cstr)); + printf("Exception message: %s\n", cstr); + + SWSSString_free(result.location); + SWSSString_free(result.message); +} diff --git a/tests/main.cpp b/tests/main.cpp index 440978a46..bfdd9fcdb 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -85,9 +85,6 @@ class SwsscommonEnvironment : public ::testing::Environment { SonicDBConfig::initializeGlobalConfig(global_existing_file); cout<<"INIT: load global db config file, isInit = "<