Line data Source code
1 : use std::sync::Arc;
2 : use std::thread;
3 :
4 : use compute_api::responses::ComputeStatus;
5 : use tracing::{error, info, instrument};
6 :
7 : use crate::compute::ComputeNode;
8 :
9 : #[instrument(skip_all)]
10 : fn configurator_main_loop(compute: &Arc<ComputeNode>) {
11 : info!("waiting for reconfiguration requests");
12 : loop {
13 : let mut state = compute.state.lock().unwrap();
14 :
15 : // We have to re-check the status after re-acquiring the lock because it could be that
16 : // the status has changed while we were waiting for the lock, and we might not need to
17 : // wait on the condition variable. Otherwise, we might end up in some soft-/deadlock, i.e.
18 : // we are waiting for a condition variable that will never be signaled.
19 : if state.status != ComputeStatus::ConfigurationPending {
20 : state = compute.state_changed.wait(state).unwrap();
21 : }
22 :
23 : // Re-check the status after waking up
24 : if state.status == ComputeStatus::ConfigurationPending {
25 : info!("got configuration request");
26 : state.set_status(ComputeStatus::Configuration, &compute.state_changed);
27 : drop(state);
28 :
29 : let mut new_status = ComputeStatus::Failed;
30 : if let Err(e) = compute.reconfigure() {
31 : error!("could not configure compute node: {}", e);
32 : } else {
33 : new_status = ComputeStatus::Running;
34 : info!("compute node configured");
35 : }
36 :
37 : // XXX: used to test that API is blocking
38 : // std::thread::sleep(std::time::Duration::from_millis(10000));
39 :
40 : compute.set_status(new_status);
41 : } else if state.status == ComputeStatus::Failed {
42 : info!("compute node is now in Failed state, exiting");
43 : break;
44 : } else {
45 : info!("woken up for compute status: {:?}, sleeping", state.status);
46 : }
47 : }
48 : }
49 :
50 0 : pub fn launch_configurator(compute: &Arc<ComputeNode>) -> thread::JoinHandle<()> {
51 0 : let compute = Arc::clone(compute);
52 0 :
53 0 : let runtime = tokio::runtime::Handle::current();
54 0 :
55 0 : thread::Builder::new()
56 0 : .name("compute-configurator".into())
57 0 : .spawn(move || {
58 0 : let _rt_guard = runtime.enter();
59 0 : configurator_main_loop(&compute);
60 0 : info!("configurator thread is exited");
61 0 : })
62 0 : .expect("cannot launch configurator thread")
63 0 : }
|