ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
state.c File Reference

Ring consensus state machine implementation. More...

Go to the source code of this file.

Data Structures

struct  election_result_t
 Election result storage. More...
 
struct  consensus_state
 State machine instance. More...
 

Typedefs

typedef struct consensus_state consensus_state_t
 State machine instance.
 

Functions

asciichat_error_t consensus_state_create (const uint8_t my_id[16], const consensus_topology_t *topology, consensus_state_t **out_state)
 
void consensus_state_destroy (consensus_state_t *state)
 
asciichat_error_t consensus_state_start_collection (consensus_state_t *state)
 
asciichat_error_t consensus_state_add_metrics (consensus_state_t *state, const participant_metrics_t *metrics)
 
asciichat_error_t consensus_state_collection_complete (consensus_state_t *state)
 
asciichat_error_t consensus_state_compute_election (consensus_state_t *state)
 
asciichat_error_t consensus_state_reset_to_idle (consensus_state_t *state)
 
consensus_state_machine_t consensus_state_get_current_state (const consensus_state_t *state)
 
asciichat_error_t consensus_state_get_elected_host (const consensus_state_t *state, uint8_t out_host_id[16])
 
asciichat_error_t consensus_state_get_elected_backup (const consensus_state_t *state, uint8_t out_backup_id[16])
 
bool consensus_state_is_leader (const consensus_state_t *state)
 
int consensus_state_get_metrics_count (const consensus_state_t *state)
 
asciichat_error_t consensus_state_get_metric_at (const consensus_state_t *state, int index, participant_metrics_t *out_metrics)
 

Detailed Description

Ring consensus state machine implementation.

Definition in file state.c.

Typedef Documentation

◆ consensus_state_t

State machine instance.

Function Documentation

◆ consensus_state_add_metrics()

asciichat_error_t consensus_state_add_metrics ( consensus_state_t state,
const participant_metrics_t *  metrics 
)

Definition at line 100 of file state.c.

100 {
101 if (!state || !metrics) {
102 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
103 }
104
105 if (state->current_state != CONSENSUS_STATE_COLLECTING) {
106 return SET_ERRNO(ERROR_INVALID_STATE, "Invalid state for adding metrics: %d", state->current_state);
107 }
108
109 /* Grow array if needed */
110 if (state->metrics_count >= state->metrics_capacity) {
111 int new_capacity = state->metrics_capacity * 2;
112 participant_metrics_t *new_metrics =
113 SAFE_REALLOC(state->metrics, new_capacity * sizeof(participant_metrics_t), participant_metrics_t *);
114 state->metrics = new_metrics;
115 state->metrics_capacity = new_capacity;
116 }
117
118 /* Copy metrics into array */
119 memcpy(&state->metrics[state->metrics_count], metrics, sizeof(participant_metrics_t));
120 state->metrics_count++;
121
122 return ASCIICHAT_OK;
123}
int metrics_capacity
Definition state.c:32
int metrics_count
Definition state.c:31
participant_metrics_t * metrics
Definition state.c:30
consensus_state_machine_t current_state
Definition state.c:25

References consensus_state::current_state, consensus_state::metrics, consensus_state::metrics_capacity, and consensus_state::metrics_count.

Referenced by consensus_coordinator_on_stats_update().

◆ consensus_state_collection_complete()

asciichat_error_t consensus_state_collection_complete ( consensus_state_t state)

Definition at line 125 of file state.c.

125 {
126 if (!state) {
127 return SET_ERRNO(ERROR_INVALID_PARAM, "State is NULL");
128 }
129
130 if (state->current_state != CONSENSUS_STATE_COLLECTING) {
131 return SET_ERRNO(ERROR_INVALID_STATE, "Invalid transition from state %d", state->current_state);
132 }
133
134 /* Transition: if we're leader, go to ELECTION_START; otherwise go to IDLE */
136 state->current_state = CONSENSUS_STATE_ELECTION_START;
137 } else {
138 state->current_state = CONSENSUS_STATE_IDLE;
139 }
140
141 return ASCIICHAT_OK;
142}
consensus_topology_t * topology
Definition state.c:26
bool consensus_topology_am_leader(const consensus_topology_t *topology)
Definition topology.c:76

References consensus_topology_am_leader(), consensus_state::current_state, and consensus_state::topology.

◆ consensus_state_compute_election()

asciichat_error_t consensus_state_compute_election ( consensus_state_t state)

Definition at line 144 of file state.c.

144 {
145 if (!state) {
146 return SET_ERRNO(ERROR_INVALID_PARAM, "State is NULL");
147 }
148
149 if (state->current_state != CONSENSUS_STATE_ELECTION_START) {
150 return SET_ERRNO(ERROR_INVALID_STATE, "Invalid transition from state %d", state->current_state);
151 }
152
153 if (state->metrics_count < 2) {
154 return SET_ERRNO(ERROR_INVALID_PARAM, "Need at least 2 metrics for election, have %d", state->metrics_count);
155 }
156
157 /* Find best and second-best metrics */
158 int best_idx = 0;
159 int backup_idx = 1;
160
161 double best_score = compute_metric_score(&state->metrics[0]);
162 double backup_score = compute_metric_score(&state->metrics[1]);
163
164 /* Ensure best_idx has lower score */
165 if (best_score > backup_score) {
166 int tmp = best_idx;
167 best_idx = backup_idx;
168 backup_idx = tmp;
169 double tmp_score = best_score;
170 best_score = backup_score;
171 backup_score = tmp_score;
172 }
173
174 /* Find best and second-best */
175 for (int i = 2; i < state->metrics_count; i++) {
176 double score = compute_metric_score(&state->metrics[i]);
177 if (score < best_score) {
178 backup_idx = best_idx;
179 backup_score = best_score;
180 best_idx = i;
181 best_score = score;
182 } else if (score < backup_score) {
183 backup_idx = i;
184 backup_score = score;
185 }
186 }
187
188 /* Store election result */
189 memcpy(state->election_result.host_id, state->metrics[best_idx].participant_id, 16);
190 memcpy(state->election_result.backup_id, state->metrics[backup_idx].participant_id, 16);
192
193 state->current_state = CONSENSUS_STATE_ELECTION_COMPLETE;
194 return ASCIICHAT_OK;
195}
election_result_t election_result
Definition state.c:35
uint8_t backup_id[16]
Definition state.c:17
uint8_t host_id[16]
Definition state.c:16
uint64_t timestamp_ns
Definition state.c:18
uint64_t time_get_realtime_ns(void)
Definition util/time.c:59

References election_result_t::backup_id, consensus_state::current_state, consensus_state::election_result, election_result_t::host_id, consensus_state::metrics, consensus_state::metrics_count, time_get_realtime_ns(), and election_result_t::timestamp_ns.

◆ consensus_state_create()

asciichat_error_t consensus_state_create ( const uint8_t  my_id[16],
const consensus_topology_t topology,
consensus_state_t **  out_state 
)

Definition at line 50 of file state.c.

51 {
52 if (!my_id || !topology || !out_state) {
53 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid state creation parameters");
54 }
55
56 consensus_state_t *state = SAFE_MALLOC(sizeof(*state), consensus_state_t *);
57 memset(state, 0, sizeof(*state));
58
59 state->current_state = CONSENSUS_STATE_IDLE;
60 state->topology = (consensus_topology_t *)topology; /* Cast away const for storage */
61 memcpy(state->my_id, my_id, 16);
62
63 /* Initialize metrics array with initial capacity of 10 */
64 state->metrics_capacity = 10;
65 state->metrics_count = 0;
66 state->metrics = SAFE_MALLOC(state->metrics_capacity * sizeof(participant_metrics_t), participant_metrics_t *);
67
68 memset(&state->election_result, 0, sizeof(election_result_t));
69
70 *out_state = state;
71 return ASCIICHAT_OK;
72}
State machine instance.
Definition state.c:24
uint8_t my_id[16]
Definition state.c:27
Ring topology for consensus participants.
Definition topology.c:17
Election result storage.
Definition state.c:15

References consensus_state::current_state, consensus_state::election_result, consensus_state::metrics, consensus_state::metrics_capacity, consensus_state::metrics_count, consensus_state::my_id, and consensus_state::topology.

Referenced by consensus_coordinator_create(), and consensus_coordinator_on_ring_members().

◆ consensus_state_destroy()

void consensus_state_destroy ( consensus_state_t state)

Definition at line 74 of file state.c.

74 {
75 if (state) {
76 if (state->metrics) {
77 SAFE_FREE(state->metrics);
78 }
79 SAFE_FREE(state);
80 }
81}

References consensus_state::metrics.

Referenced by consensus_coordinator_destroy(), and consensus_coordinator_on_ring_members().

◆ consensus_state_get_current_state()

consensus_state_machine_t consensus_state_get_current_state ( const consensus_state_t state)

◆ consensus_state_get_elected_backup()

asciichat_error_t consensus_state_get_elected_backup ( const consensus_state_t state,
uint8_t  out_backup_id[16] 
)

Definition at line 230 of file state.c.

230 {
231 if (!state || !out_backup_id) {
232 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
233 }
234
235 if (state->current_state != CONSENSUS_STATE_ELECTION_COMPLETE) {
236 return SET_ERRNO(ERROR_INVALID_STATE, "Election not complete, current state: %d", state->current_state);
237 }
238
239 memcpy(out_backup_id, state->election_result.backup_id, 16);
240 return ASCIICHAT_OK;
241}

References election_result_t::backup_id, consensus_state::current_state, and consensus_state::election_result.

Referenced by consensus_coordinator_get_current_host().

◆ consensus_state_get_elected_host()

asciichat_error_t consensus_state_get_elected_host ( const consensus_state_t state,
uint8_t  out_host_id[16] 
)

Definition at line 217 of file state.c.

217 {
218 if (!state || !out_host_id) {
219 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
220 }
221
222 if (state->current_state != CONSENSUS_STATE_ELECTION_COMPLETE) {
223 return SET_ERRNO(ERROR_INVALID_STATE, "Election not complete, current state: %d", state->current_state);
224 }
225
226 memcpy(out_host_id, state->election_result.host_id, 16);
227 return ASCIICHAT_OK;
228}

References consensus_state::current_state, consensus_state::election_result, and election_result_t::host_id.

Referenced by consensus_coordinator_get_current_host().

◆ consensus_state_get_metric_at()

asciichat_error_t consensus_state_get_metric_at ( const consensus_state_t state,
int  index,
participant_metrics_t *  out_metrics 
)

Definition at line 257 of file state.c.

258 {
259 if (!state || !out_metrics || index < 0) {
260 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
261 }
262
263 if (index >= state->metrics_count) {
264 return SET_ERRNO(ERROR_INVALID_PARAM, "Index %d out of bounds (count: %d)", index, state->metrics_count);
265 }
266
267 /* Valid to retrieve metrics in COLLECTING, COLLECTION_COMPLETE, or ELECTION states */
268 if (state->current_state != CONSENSUS_STATE_COLLECTING &&
269 state->current_state != CONSENSUS_STATE_COLLECTION_COMPLETE &&
270 state->current_state != CONSENSUS_STATE_ELECTION_START && state->current_state != CONSENSUS_STATE_ELECTING &&
271 state->current_state != CONSENSUS_STATE_ELECTION_COMPLETE) {
272 return SET_ERRNO(ERROR_INVALID_STATE, "Cannot retrieve metrics in state %d", state->current_state);
273 }
274
275 memcpy(out_metrics, &state->metrics[index], sizeof(participant_metrics_t));
276 return ASCIICHAT_OK;
277}

References consensus_state::current_state, consensus_state::metrics, and consensus_state::metrics_count.

◆ consensus_state_get_metrics_count()

int consensus_state_get_metrics_count ( const consensus_state_t state)

Definition at line 250 of file state.c.

250 {
251 if (!state) {
252 return -1;
253 }
254 return state->metrics_count;
255}

References consensus_state::metrics_count.

Referenced by consensus_coordinator_get_metrics_count().

◆ consensus_state_is_leader()

bool consensus_state_is_leader ( const consensus_state_t state)

Definition at line 243 of file state.c.

243 {
244 if (!state) {
245 return false;
246 }
248}

References consensus_topology_am_leader(), and consensus_state::topology.

◆ consensus_state_reset_to_idle()

asciichat_error_t consensus_state_reset_to_idle ( consensus_state_t state)

Definition at line 197 of file state.c.

197 {
198 if (!state) {
199 return SET_ERRNO(ERROR_INVALID_PARAM, "State is NULL");
200 }
201
202 if (state->current_state != CONSENSUS_STATE_ELECTION_COMPLETE) {
203 return SET_ERRNO(ERROR_INVALID_STATE, "Invalid transition from state %d", state->current_state);
204 }
205
206 state->current_state = CONSENSUS_STATE_IDLE;
207 return ASCIICHAT_OK;
208}

References consensus_state::current_state.

Referenced by consensus_coordinator_on_election_result().

◆ consensus_state_start_collection()

asciichat_error_t consensus_state_start_collection ( consensus_state_t state)

Definition at line 83 of file state.c.

83 {
84 if (!state) {
85 return SET_ERRNO(ERROR_INVALID_PARAM, "State is NULL");
86 }
87
88 if (state->current_state != CONSENSUS_STATE_IDLE) {
89 return SET_ERRNO(ERROR_INVALID_STATE, "Invalid transition from state %d", state->current_state);
90 }
91
92 /* Reset metrics from previous round */
93 state->metrics_count = 0;
94 memset(&state->election_result, 0, sizeof(election_result_t));
95
96 state->current_state = CONSENSUS_STATE_COLLECTING;
97 return ASCIICHAT_OK;
98}

References consensus_state::current_state, consensus_state::election_result, and consensus_state::metrics_count.

Referenced by consensus_coordinator_on_collection_start().