You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2023/05/01 17:59:13 UTC
[celix] 06/06: Add initial implementation for celix_err
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch feature/celix_err
in repository https://gitbox.apache.org/repos/asf/celix.git
commit c4b9d723a54762908396123ab879d19e028a9ced
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon May 1 19:58:59 2023 +0200
Add initial implementation for celix_err
---
libs/utils/CMakeLists.txt | 1 +
libs/utils/gtest/CMakeLists.txt | 1 +
libs/utils/gtest/src/ErrTestSuite.cc | 56 ++++++++++++++++
libs/utils/include/celix_err.h | 71 ++++++++++++++++++++
libs/utils/src/celix_err.c | 124 +++++++++++++++++++++++++++++++++++
5 files changed, 253 insertions(+)
diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt
index db500513..d57c0c7c 100644
--- a/libs/utils/CMakeLists.txt
+++ b/libs/utils/CMakeLists.txt
@@ -44,6 +44,7 @@ add_library(utils_obj OBJECT
src/celix_hash_map.c
src/celix_file_utils.c
src/celix_convert_utils.c
+ src/celix_err.c
${MEMSTREAM_SOURCES}
)
diff --git a/libs/utils/gtest/CMakeLists.txt b/libs/utils/gtest/CMakeLists.txt
index 2d8a47f5..47e92d96 100644
--- a/libs/utils/gtest/CMakeLists.txt
+++ b/libs/utils/gtest/CMakeLists.txt
@@ -33,6 +33,7 @@ add_executable(test_utils
src/FilterTestSuite.cc
src/CelixUtilsTestSuite.cc
src/ConvertUtilsTestSuite.cc
+ src/ErrTestSuite.cc
${CELIX_UTIL_TEST_SOURCES_FOR_CXX_HEADERS}
)
diff --git a/libs/utils/gtest/src/ErrTestSuite.cc b/libs/utils/gtest/src/ErrTestSuite.cc
new file mode 100644
index 00000000..abb15cb6
--- /dev/null
+++ b/libs/utils/gtest/src/ErrTestSuite.cc
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "celix_err.h"
+
+class ErrTestSuite : public ::testing::Test {
+public:
+ ErrTestSuite() = default;
+ ~ErrTestSuite() noexcept override = default;
+};
+
+TEST_F(ErrTestSuite, AddAndPopErrorTest) {
+ EXPECT_EQ(0, celix_err_getErrorCount());
+ celix_err_push("error message");
+ celix_err_pushf("error message from %s", "test");
+ EXPECT_EQ(2, celix_err_getErrorCount());
+
+ auto* m = celix_err_popLastError();
+ EXPECT_STREQ("error message from test", m);
+ free(m);
+ EXPECT_EQ(1, celix_err_getErrorCount());
+
+ m = celix_err_popLastError();
+ EXPECT_STREQ("error message", m);
+ free(m);
+ EXPECT_EQ(0, celix_err_getErrorCount());
+}
+
+TEST_F(ErrTestSuite, ResetErrorTest) {
+ EXPECT_EQ(0, celix_err_getErrorCount());
+ celix_err_push("error message");
+ celix_err_push("error message");
+ EXPECT_EQ(2, celix_err_getErrorCount());
+
+ celix_err_resetErrors();
+ EXPECT_EQ(0, celix_err_getErrorCount());
+ EXPECT_EQ(nullptr, celix_err_popLastError());
+}
diff --git a/libs/utils/include/celix_err.h b/libs/utils/include/celix_err.h
new file mode 100644
index 00000000..16bd2d31
--- /dev/null
+++ b/libs/utils/include/celix_err.h
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef CELIX_CELIX_ERR_H
+#define CELIX_CELIX_ERR_H
+
+#include "celix_utils_export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @file celix_err.h
+* @brief The celix error handling functions.
+* @thread_safety Thread safe.
+*/
+
+/**
+ * @brief Returns the last error message from the current thread.
+ * The error message must be freed by the caller.
+ * @returnval NULL if no error message is available.
+ */
+CELIX_UTILS_EXPORT
+char* celix_err_popLastError(); //TODO update to return const char* and remove free
+
+/**
+ * @brief Push an formatted error message to the thread specific storage rcm errors.
+ */
+CELIX_UTILS_EXPORT
+void celix_err_pushf(const char* format, ...) __attribute__((format(printf, 1, 2)));
+
+/**
+ * @brief Push an error message to the thread specific storage rcm errors.
+ */
+CELIX_UTILS_EXPORT
+void celix_err_push(const char* msg);
+
+/**
+ * @brief Returns the number of error messages from the current thread.
+ */
+CELIX_UTILS_EXPORT
+int celix_err_getErrorCount();
+
+/**
+ * @brief Resets the error message for the current thread.
+ */
+CELIX_UTILS_EXPORT
+void celix_err_resetErrors();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //CELIX_CELIX_ERR_H
diff --git a/libs/utils/src/celix_err.c b/libs/utils/src/celix_err.c
new file mode 100644
index 00000000..939c7078
--- /dev/null
+++ b/libs/utils/src/celix_err.c
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "celix_err.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#include "celix_array_list.h"
+#include "celix_utils.h"
+
+pthread_key_t celix_rcm_tssErrorsKey; //TODO replace with celix_tss_key and celix_tss_* functions
+
+static void celix_err_destroyTssErrors(void* data) {
+ //TODO replace array list with some thread specific storage char buffer
+ celix_array_list_t* errors = data;
+ if (errors != NULL) {
+ for (int i = 0; i < celix_arrayList_size(errors); ++i) {
+ char* msg = celix_arrayList_get(errors, i);
+ free(msg);
+ }
+ }
+ celix_arrayList_destroy(errors);
+}
+
+__attribute__((constructor)) void celix_err_initThreadSpecificStorageKey() {
+ int rc = pthread_key_create(&celix_rcm_tssErrorsKey, celix_err_destroyTssErrors);
+ if (rc != 0) {
+ fprintf(stderr,"Failed to create thread specific storage key for celix_err\n");
+ }
+}
+
+__attribute__((destructor)) void celix_err_deinitThreadSpecificStorageKey() {
+ int rc = pthread_key_delete(celix_rcm_tssErrorsKey);
+ if (rc != 0) {
+ fprintf(stderr,"Failed to delete thread specific storage key for celix_err\n");
+ }
+}
+
+char* celix_err_popLastError() {
+ char* result = NULL;
+ celix_array_list_t* errors = pthread_getspecific(celix_rcm_tssErrorsKey);
+ if (errors != NULL && celix_arrayList_size(errors) > 0) {
+ int last = celix_arrayList_size(errors) - 1;
+ result = celix_arrayList_get(errors, last);
+ celix_arrayList_removeAt(errors, last);
+ }
+ return result;
+}
+
+int celix_err_getErrorCount() {
+ int result = 0;
+ celix_array_list_t* errors = pthread_getspecific(celix_rcm_tssErrorsKey);
+ if (errors != NULL) {
+ result = celix_arrayList_size(errors);
+ }
+ return result;
+}
+
+void celix_err_resetErrors() {
+ celix_array_list_t* errors = pthread_getspecific(celix_rcm_tssErrorsKey);
+ celix_err_destroyTssErrors(errors);
+ pthread_setspecific(celix_rcm_tssErrorsKey, NULL);
+}
+
+static void celix_err_pushMsg(char* msg) {
+ celix_array_list_t* errors = pthread_getspecific(celix_rcm_tssErrorsKey);
+ if (errors == NULL) {
+ errors = celix_arrayList_create();
+ if (errors == NULL) {
+ fprintf(stderr, "Failed to create error list for Apache Celix rcm lib\n");
+ free(msg);
+ return;
+ }
+ pthread_setspecific(celix_rcm_tssErrorsKey, errors);
+ }
+ if (errors != NULL) {
+ celix_status_t rc = celix_arrayList_add(errors, msg);
+ if (rc != CELIX_SUCCESS) {
+ fprintf(stderr, "Failed to add error to error list for Apache Celix rcm lib\n");
+ free(msg);
+ }
+ }
+}
+
+void celix_err_push(const char* msg) {
+ char* msgCpy = celix_utils_strdup(msg);
+ if (msgCpy == NULL) {
+ fprintf(stderr, "Failed to copy error message for Apache Celix rcm lib\n");
+ return;
+ }
+ celix_err_pushMsg(msgCpy);
+}
+
+void celix_err_pushf(const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ char* msg = NULL;
+ int rc = vasprintf(&msg, format, args);
+ if (rc >= 0) {
+ celix_err_pushMsg(msg);
+ } else {
+ fprintf(stderr, "Failed to copy error message for Apache Celix rcm lib\n");
+ }
+ va_end(args);
+}