1use std::fmt::{self, Debug, Formatter};
4use std::sync::atomic::{AtomicI32, Ordering};
5use std::sync::Mutex;
6use std::task::{Context, Poll, Waker};
7
8use crate::max_runtime::{
9 AccessAdmissionLaw, EmptyData, Exited, Initialized, InitializedData, Initializing,
10 InitializingData, Machine, ShutDown, Uninitialized,
11};
12
13#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
15#[repr(u8)]
16pub enum State {
17 Uninitialized = 0,
19 Initializing = 1,
21 Initialized = 2,
23 ShutDown = 3,
25 Exited = 4,
27}
28
29#[derive(Debug)]
31pub enum StateMachine {
32 Uninitialized(Machine<AccessAdmissionLaw, Uninitialized, EmptyData>),
34 Initializing(Machine<AccessAdmissionLaw, Initializing, InitializingData>),
36 Initialized(Machine<AccessAdmissionLaw, Initialized, InitializedData>),
38 ShutDown(Machine<AccessAdmissionLaw, ShutDown, EmptyData>),
40 #[allow(dead_code)]
42 Exited(Machine<AccessAdmissionLaw, Exited, EmptyData>),
43}
44
45impl StateMachine {
46 pub fn get_state(&self) -> State {
48 match self {
49 StateMachine::Uninitialized(_) => State::Uninitialized,
50 StateMachine::Initializing(_) => State::Initializing,
51 StateMachine::Initialized(_) => State::Initialized,
52 StateMachine::ShutDown(_) => State::ShutDown,
53 StateMachine::Exited(_) => State::Exited,
54 }
55 }
56}
57
58pub struct ServerState {
60 machine: Mutex<StateMachine>,
61 wakers: Mutex<Vec<Waker>>,
62 exit_code: AtomicI32,
63 pub mesh: Mutex<crate::max_runtime::AutonomicMesh>,
65 parent_pid: Mutex<Option<u32>>,
66}
67
68impl Default for ServerState {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74impl ServerState {
75 pub fn new() -> Self {
77 let mut mesh = crate::max_runtime::AutonomicMesh::new();
78 let mut instance = crate::max_runtime::LspInstance::new("LSP_1");
79 instance.phase = crate::max_runtime::LspPhase::Uninitialized;
80 let r0 = crate::max_protocol::Receipt {
81 receipt_id: "rcpt-uninitialized".to_string(),
82 hash: crate::max_runtime::sha256(b"rcpt-uninitialized"),
83 prev_receipt_hash: None,
84 };
85 instance.receipts.push(r0.clone());
86 mesh.add_instance(instance);
87
88 if let Ok(mut reg) = crate::get_registry().lock() {
89 reg.receipts.insert(r0.receipt_id.clone(), r0);
90 }
91
92 ServerState {
93 machine: Mutex::new(StateMachine::Uninitialized(Machine {
94 _law: std::marker::PhantomData,
95 phase: Uninitialized,
96 data: EmptyData {
97 client_capabilities: None,
98 server_capabilities: None,
99 },
100 })),
101 wakers: Mutex::new(Vec::new()),
102 exit_code: AtomicI32::new(1),
103 mesh: Mutex::new(mesh),
104 parent_pid: Mutex::new(None),
105 }
106 }
107
108 #[allow(dead_code)]
111 pub fn set(&self, state: State) {
112 let mut lock = self.machine.lock().unwrap();
113 let next_machine = match state {
114 State::Uninitialized => {
115 StateMachine::Uninitialized(Machine::new(Uninitialized, EmptyData::default()))
116 }
117 State::Initializing => StateMachine::Initializing(Machine::new(
118 Initializing,
119 InitializingData {
120 client_capabilities: serde_json::Value::Null,
121 },
122 )),
123 State::Initialized => StateMachine::Initialized(Machine::new(
124 Initialized,
125 InitializedData {
126 client_capabilities: serde_json::Value::Null,
127 server_capabilities: serde_json::Value::Null,
128 },
129 )),
130 State::ShutDown => StateMachine::ShutDown(Machine::new(ShutDown, EmptyData::default())),
131 State::Exited => StateMachine::Exited(Machine::new(Exited, EmptyData::default())),
132 };
133 *lock = next_machine;
134 if let Ok(mut reg) = crate::get_registry().lock() {
135 reg.current_state = state;
136 }
137 if let Some(instance) = self.mesh.lock().unwrap().instances.get_mut("LSP_1") {
138 instance.phase = match state {
139 crate::service::state::State::Uninitialized => {
140 crate::max_runtime::LspPhase::Uninitialized
141 }
142 crate::service::state::State::Initializing => {
143 crate::max_runtime::LspPhase::Initializing
144 }
145 crate::service::state::State::Initialized => {
146 crate::max_runtime::LspPhase::Initialized
147 }
148 crate::service::state::State::ShutDown => crate::max_runtime::LspPhase::ShutDown,
149 crate::service::state::State::Exited => crate::max_runtime::LspPhase::Exited,
150 };
151 }
152
153 if state != State::Initializing {
154 let mut wakers = self.wakers.lock().unwrap();
155 let wakers_to_wake = std::mem::take(&mut *wakers);
156 for waker in wakers_to_wake {
157 waker.wake();
158 }
159 }
160 }
161
162 pub fn get(&self) -> State {
164 self.machine.lock().unwrap().get_state()
165 }
166
167 #[allow(dead_code)]
169 pub fn set_exit_code(&self, code: i32) {
170 self.exit_code.store(code, Ordering::SeqCst);
171 }
172
173 pub fn get_exit_code(&self) -> i32 {
175 self.exit_code.load(Ordering::SeqCst)
176 }
177
178 pub fn set_parent_pid(&self, pid: u32) {
180 *self.parent_pid.lock().unwrap() = Some(pid);
181 }
182
183 pub fn get_parent_pid(&self) -> Option<u32> {
185 *self.parent_pid.lock().unwrap()
186 }
187
188 pub fn try_initialize(&self, client_caps: serde_json::Value) -> bool {
190 let mut lock = self.machine.lock().unwrap();
191 match &*lock {
192 StateMachine::Uninitialized(_) => {
193 let old = std::mem::replace(
194 &mut *lock,
195 StateMachine::Exited(Machine::new(Exited, EmptyData::default())),
196 );
197 if let StateMachine::Uninitialized(m) = old {
198 let next = m.admit_initialize(client_caps);
199 let receipt = crate::max_runtime::TypestateKernel::receipt(&next);
200 *lock = StateMachine::Initializing(next);
201 if let Ok(mut reg) = crate::get_registry().lock() {
202 reg.current_state = State::Initializing;
203 reg.receipts
204 .insert(receipt.receipt_id.clone(), receipt.clone());
205 }
206 if let Some(instance) = self.mesh.lock().unwrap().instances.get_mut("LSP_1") {
207 instance.phase = crate::max_runtime::LspPhase::Initializing;
208 instance.receipts.push(receipt.clone());
209 }
210
211 let mut mesh = self.mesh.lock().unwrap();
212 mesh.dispatch_event(crate::max_protocol::HookEvent::StateTransition {
213 instance_id: crate::runtime::InstanceId::from("LSP_1"),
214 from_phase: "Uninitialized".to_string(),
215 to_phase: "Initializing".to_string(),
216 });
217 mesh.dispatch_event(crate::max_protocol::HookEvent::ReceiptEmitted {
218 instance_id: crate::runtime::InstanceId::from("LSP_1"),
219 receipt,
220 });
221 let _ = mesh.verify_instance_ledger("LSP_1");
222 true
223 } else {
224 unreachable!()
225 }
226 }
227 _ => false,
228 }
229 }
230
231 pub fn transition_to_initialized(&self, server_caps: serde_json::Value) -> bool {
233 tracing::trace!("--- transition_to_initialized entered");
234 let mut lock = self.machine.lock().unwrap();
235 tracing::trace!(
236 "--- transition_to_initialized state machine before: {:?}",
237 lock.get_state()
238 );
239 let (success, receipt) = match &*lock {
240 StateMachine::Initializing(_) => {
241 let old = std::mem::replace(
242 &mut *lock,
243 StateMachine::Exited(Machine::new(Exited, EmptyData::default())),
244 );
245 if let StateMachine::Initializing(m) = old {
246 let next = m.admit_initialized(server_caps);
247 let receipt = crate::max_runtime::TypestateKernel::receipt(&next);
248 *lock = StateMachine::Initialized(next);
249 if let Some(instance) = self.mesh.lock().unwrap().instances.get_mut("LSP_1") {
250 instance.phase = crate::max_runtime::LspPhase::Initialized;
251 instance.receipts.push(receipt.clone());
252 }
253 (true, Some(receipt))
254 } else {
255 unreachable!()
256 }
257 }
258 _ => (false, None),
259 };
260 tracing::trace!("--- transition_to_initialized success: {}", success);
261 if success {
262 if let Ok(mut reg) = crate::get_registry().lock() {
263 reg.current_state = State::Initialized;
264 if let Some(ref r) = receipt {
265 reg.receipts.insert(r.receipt_id.clone(), r.clone());
266 }
267 }
268 if let Some(ref r) = receipt {
269 let mut mesh = self.mesh.lock().unwrap();
270 mesh.dispatch_event(crate::max_protocol::HookEvent::StateTransition {
271 instance_id: crate::runtime::InstanceId::from("LSP_1"),
272 from_phase: "Initializing".to_string(),
273 to_phase: "Initialized".to_string(),
274 });
275 mesh.dispatch_event(crate::max_protocol::HookEvent::ReceiptEmitted {
276 instance_id: crate::runtime::InstanceId::from("LSP_1"),
277 receipt: r.clone(),
278 });
279 let _ = mesh.verify_instance_ledger("LSP_1");
280 }
281 let mut wakers = self.wakers.lock().unwrap();
282 let wakers_to_wake = std::mem::take(&mut *wakers);
283 for waker in wakers_to_wake {
284 waker.wake();
285 }
286 }
287 success
288 }
289
290 pub fn transition_to_uninitialized(&self) -> bool {
292 let mut lock = self.machine.lock().unwrap();
293 let success = match &*lock {
294 StateMachine::Initializing(_) => {
295 *lock =
296 StateMachine::Uninitialized(Machine::new(Uninitialized, EmptyData::default()));
297 if let Some(instance) = self.mesh.lock().unwrap().instances.get_mut("LSP_1") {
298 instance.phase = crate::max_runtime::LspPhase::Uninitialized;
299 instance.receipts.truncate(1);
300 }
301 true
302 }
303 _ => false,
304 };
305 if success {
306 if let Ok(mut reg) = crate::get_registry().lock() {
307 reg.current_state = State::Uninitialized;
308 reg.receipts.retain(|k, _| k == "rcpt-uninitialized");
309 }
310 let mut wakers = self.wakers.lock().unwrap();
311 let wakers_to_wake = std::mem::take(&mut *wakers);
312 for waker in wakers_to_wake {
313 waker.wake();
314 }
315 }
316 success
317 }
318
319 pub fn transition_to_shutdown(&self) -> bool {
321 let mut lock = self.machine.lock().unwrap();
322 let (success, receipt) = match &*lock {
323 StateMachine::Initialized(_) => {
324 let old = std::mem::replace(
325 &mut *lock,
326 StateMachine::Exited(Machine::new(Exited, EmptyData::default())),
327 );
328 if let StateMachine::Initialized(m) = old {
329 let next = m.admit_shutdown();
330 let receipt = crate::max_runtime::TypestateKernel::receipt(&next);
331 *lock = StateMachine::ShutDown(next);
332 if let Some(instance) = self.mesh.lock().unwrap().instances.get_mut("LSP_1") {
333 instance.phase = crate::max_runtime::LspPhase::ShutDown;
334 instance.receipts.push(receipt.clone());
335 }
336 (true, Some(receipt))
337 } else {
338 unreachable!()
339 }
340 }
341 _ => (false, None),
342 };
343 if success {
344 if let Ok(mut reg) = crate::get_registry().lock() {
345 reg.current_state = State::ShutDown;
346 if let Some(ref r) = receipt {
347 reg.receipts.insert(r.receipt_id.clone(), r.clone());
348 }
349 }
350 if let Some(ref r) = receipt {
351 let mut mesh = self.mesh.lock().unwrap();
352 mesh.dispatch_event(crate::max_protocol::HookEvent::StateTransition {
353 instance_id: crate::runtime::InstanceId::from("LSP_1"),
354 from_phase: "Initialized".to_string(),
355 to_phase: "ShutDown".to_string(),
356 });
357 mesh.dispatch_event(crate::max_protocol::HookEvent::ReceiptEmitted {
358 instance_id: crate::runtime::InstanceId::from("LSP_1"),
359 receipt: r.clone(),
360 });
361 let _ = mesh.verify_instance_ledger("LSP_1");
362 }
363 }
364 success
365 }
366
367 pub fn transition_to_exited(&self) -> bool {
369 let mut lock = self.machine.lock().unwrap();
370 let (res, receipt) = match &*lock {
371 StateMachine::ShutDown(_m) => {
372 let old = std::mem::replace(
373 &mut *lock,
374 StateMachine::Exited(Machine::new(Exited, EmptyData::default())),
375 );
376 if let StateMachine::ShutDown(m) = old {
377 let next = m.admit_exit();
378 let receipt = crate::max_runtime::TypestateKernel::receipt(&next);
379 *lock = StateMachine::Exited(next);
380 self.set_exit_code(0);
381 if let Some(instance) = self.mesh.lock().unwrap().instances.get_mut("LSP_1") {
382 instance.phase = crate::max_runtime::LspPhase::Exited;
383 instance.receipts.push(receipt.clone());
384 }
385 (true, Some(receipt))
386 } else {
387 unreachable!()
388 }
389 }
390 _ => {
391 *lock = StateMachine::Exited(Machine::new(Exited, EmptyData::default()));
392 self.set_exit_code(1);
393 if let Some(instance) = self.mesh.lock().unwrap().instances.get_mut("LSP_1") {
394 instance.phase = crate::max_runtime::LspPhase::Exited;
395 }
396 (true, None)
397 }
398 };
399 if let Ok(mut reg) = crate::get_registry().lock() {
400 reg.current_state = State::Exited;
401 if let Some(ref r) = receipt {
402 reg.receipts.insert(r.receipt_id.clone(), r.clone());
403 }
404 }
405 if let Some(ref r) = receipt {
406 let mut mesh = self.mesh.lock().unwrap();
407 mesh.dispatch_event(crate::max_protocol::HookEvent::StateTransition {
408 instance_id: crate::runtime::InstanceId::from("LSP_1"),
409 from_phase: "ShutDown".to_string(),
410 to_phase: "Exited".to_string(),
411 });
412 mesh.dispatch_event(crate::max_protocol::HookEvent::ReceiptEmitted {
413 instance_id: crate::runtime::InstanceId::from("LSP_1"),
414 receipt: r.clone(),
415 });
416 let _ = mesh.verify_instance_ledger("LSP_1");
417 }
418 res
419 }
420
421 #[allow(dead_code)]
424 pub fn poll_initializing(&self, cx: &mut Context<'_>) -> Poll<()> {
425 let lock = self.machine.lock().unwrap();
426 match lock.get_state() {
427 State::Initializing => {
428 self.wakers.lock().unwrap().push(cx.waker().clone());
429 Poll::Pending
430 }
431 _ => Poll::Ready(()),
432 }
433 }
434}
435
436impl Debug for ServerState {
437 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
438 self.get().fmt(f)
439 }
440}