---
CMakeLists.txt | 2 ++
election.c | 3 ++-
error.c | 16 ++++++++++++++++
internal.h | 7 +++++++
libfloat.h | 11 +++++++++++
log.c | 7 +++++++
raft.c | 3 +++
7 files changed, 48 insertions(+), 1 deletion(-)
create mode 100644 error.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b53806a..e976f8f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,7 @@ if (LIBFLOAT_BUILD_SHARED)
log.c
periodic.c
snapshot.c
+ error.c
externals/list.c
)
@@ -36,6 +37,7 @@ add_library(float-static STATIC
log.c
periodic.c
snapshot.c
+ error.c
externals/list.c
)
diff --git a/election.c b/election.c
index 95dd09b..e648421 100644
--- a/election.c
+++ b/election.c
@@ -189,6 +189,7 @@ void libfloat_request_vote_response(libfloat_ctx_t *ctx, libfloat_rpc_response_v
{
DEBUG(ctx, "I have a majority of votes! Assuming leadership");
libfloat_become_leader(ctx);
+ ctx->stat.leader_election++;
}
}
}
@@ -221,4 +222,4 @@ void libfloat_election_resign_receive(libfloat_ctx_t *ctx)
{
ERROR(ctx, "Restart election");
libfloat_election_start(ctx);
-}
\ No newline at end of file
+}
diff --git a/error.c b/error.c
new file mode 100644
index 0000000..0eed0fb
--- /dev/null
+++ b/error.c
@@ -0,0 +1,16 @@
+#include "internal.h"
+
+static char *__error = NULL;
+
+const char *libfloat_get_error_str(void)
+{
+ const char *ret = __error;
+
+ __error = NULL;
+ return ret;
+}
+
+void libfloat_set_error_str(const char *str)
+{
+ __error = (char *)str;
+}
diff --git a/internal.h b/internal.h
index 3e1dff1..ad41067 100644
--- a/internal.h
+++ b/internal.h
@@ -80,4 +80,11 @@ void libfloat_debug(libfloat_ctx_t *ctx, const char *fmt, ...) __attribute__((fo
} while (0)
void libfloat_error(libfloat_ctx_t *ctx, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
+/*!
+ * \brief Set a error to be retrieved by the caller
+ *
+ * \param[in] str String to set (Constants only)
+ */
+void libfloat_set_error_str(const char *str);
+
#endif /* LIBFLOAT_INTERNAL_H */
diff --git a/libfloat.h b/libfloat.h
index 1717ef8..dcce50f 100644
--- a/libfloat.h
+++ b/libfloat.h
@@ -43,6 +43,10 @@ struct libfloat_ctx_s {
} snapshot;
} persistent;
+ struct {
+ uint64_t leader_election; /*!< Count of leader elections for this cluster */
+ } stat;
+
struct {
uint32_t election_timeout; /*!< Timeout for RAFT election (ms) */
uint32_t log_commit_timeout; /*!< Timeout for log application (s) */
@@ -474,4 +478,11 @@ void libfloat_election_resign(libfloat_ctx_t *ctx);
*/
void libfloat_election_resign_receive(libfloat_ctx_t *ctx);
+/*!
+ * \brief Get a string explaining an error that has happened
+ *
+ * \note This is only useful for libfloat_add_log for now
+ */
+const char *libfloat_get_error_str(void);
+
#endif /* LIBFLOAT_H */
diff --git a/log.c b/log.c
index 7676da1..ad95bc7 100644
--- a/log.c
+++ b/log.c
@@ -11,12 +11,14 @@ bool libfloat_add_log(libfloat_ctx_t *ctx, libfloat_commit_type_t commit_type, l
if (ctx->state != RAFT_STATE_LEADER)
{
ERROR(ctx ,"libfloat_add_log: Refusing write, not leader");
+ libfloat_set_error_str("Refusing write, not leader");
return false;
}
entry = ctx->calloc(1, sizeof(*entry));
if (entry == NULL)
{
+ libfloat_set_error_str("Memory error");
return false;
}
@@ -24,6 +26,7 @@ bool libfloat_add_log(libfloat_ctx_t *ctx, libfloat_commit_type_t commit_type, l
if (entry->data == NULL)
{
ctx->free(entry);
+ libfloat_set_error_str("Memory error");
return false;
}
@@ -74,6 +77,7 @@ bool libfloat_add_log(libfloat_ctx_t *ctx, libfloat_commit_type_t commit_type, l
ctx->free(entry->data);
ctx->free(entry);
ERROR(ctx, "libfloat_add_log: Refusing write, callback returned false");
+ libfloat_set_error_str("User defined callback returned false");
return false;
}
@@ -445,6 +449,9 @@ response:
if (node == NULL)
node = libfloat_get_node(ctx, req->leader_id);
+ if (ctx->leader != node)
+ ctx->stat.leader_election++;
+
ctx->leader = node;
ctx->stepping_down = false;
diff --git a/raft.c b/raft.c
index 1515c5b..9070b2f 100644
--- a/raft.c
+++ b/raft.c
@@ -44,6 +44,9 @@ void libfloat_step_down(libfloat_ctx_t *ctx)
{
DEBUG(ctx, "Force stepping down");
ctx->stepping_down = true;
+ if (ctx->state == RAFT_STATE_LEADER)
+ ctx->leader = NULL;
+
ctx->state = RAFT_STATE_NONE;
}
--
2.32.0