void stop_state_manager(void) { struct list_element* current; struct client_state* state; current = list_head(expiring_states); while (current) { state = container_of(current, struct client_state, expire); bst_remove_node(&states_tree, &state->node); release_state(state, 1); current = list_next(&state->expire); free(state); } current = list_head(renewed_states); while (current) { state = container_of(current, struct client_state, expire); bst_remove_node(&states_tree, &state->node); release_state(state, 1); current = list_next(&state->expire); free(state); } free(renewed_states); free(expiring_states); }
rcl_status quit_state(state_t state_id, uint32_t sequence) { struct bst_node* node; struct client_state* state; rcl_status error = RCL_OK; log_print(log_notice, "Quitting state: %#" PRIx64 " %" PRIu32, state_id, sequence); pthread_mutex_lock(&states_lock); node = bst_get_node(&states_tree, state_id); if (!node) { log_print(log_error, "State %#" PRIx64 " not found", state_id); error = RCL_BAD_STATE; goto out_tree_lock; } state = container_of(node, struct client_state, node); pthread_mutex_lock(&state->lock); switch (check_sequence(state, sequence)) { case sequence_retry: log_print(log_warning, "State %#" PRIx64 " still exists during" \ " QUIT retry", state_id); case sequence_invalid: error = RCL_BAD_SEQUENCE; pthread_mutex_unlock(&state->lock); goto out_tree_lock; default: break; } if (current_epoch == state->expire_epoch) list_remove(renewed_states, &state->expire); else list_remove(expiring_states, &state->expire); pthread_mutex_unlock(&state->lock); bst_remove_node(&states_tree, node); out_tree_lock: pthread_mutex_unlock(&states_lock); if (error) return error; release_state(state, 0); free(state); return error; }
static void* state_releaser(void* ptr) { struct list_element* current; struct client_state* state; struct list* expired_states; (void)ptr; log_print(log_notice, "Expire epoch %d -> %d", current_epoch, !current_epoch); pthread_mutex_lock(&states_lock); expired_states = expiring_states; expiring_states = renewed_states; renewed_states = malloc(sizeof(struct list)); if (renewed_states) list_init(renewed_states); current_epoch = !current_epoch; current = list_head(expired_states); while (current) { state = container_of(current, struct client_state, expire); bst_remove_node(&states_tree, &state->node); release_state(state, 1); current = list_next(&state->expire); free(state); } pthread_mutex_unlock(&states_lock); free(expired_states); enqueue_delayed_task(state_releaser, NULL, time(NULL) + STATE_EXPIRE); return NULL; }
bst_node_t *bst_remove(bst_t *bst, int key) { bst_node_t *node = bst_search(bst, key); if (NULL_NODE == node) return node; return bst_remove_node(bst, node); }