]>
git.proxmox.com Git - proxmox-backup.git/blob - proxmox-rest-server/src/state.rs
468ef0aa2297a55c4bdc3b8f52a3b031443a972c
2 use lazy_static
::lazy_static
;
7 use tokio
::signal
::unix
::{signal, SignalKind}
;
9 use pbs_tools
::broadcast_future
::BroadcastData
;
11 #[derive(PartialEq, Copy, Clone, Debug)]
17 pub struct ServerState
{
19 pub shutdown_listeners
: BroadcastData
<()>,
20 pub last_worker_listeners
: BroadcastData
<()>,
21 pub worker_count
: usize,
22 pub internal_task_count
: usize,
23 pub reload_request
: bool
,
27 static ref SERVER_STATE
: Mutex
<ServerState
> = Mutex
::new(ServerState
{
28 mode
: ServerMode
::Normal
,
29 shutdown_listeners
: BroadcastData
::new(),
30 last_worker_listeners
: BroadcastData
::new(),
32 internal_task_count
: 0,
33 reload_request
: false,
37 pub fn server_state_init() -> Result
<(), Error
> {
39 let mut stream
= signal(SignalKind
::interrupt())?
;
41 let future
= async
move {
42 while stream
.recv().await
.is_some() {
43 println
!("got shutdown request (SIGINT)");
44 SERVER_STATE
.lock().unwrap().reload_request
= false;
45 crate::request_shutdown();
49 let abort_future
= last_worker_future().map_err(|_
| {}
);
50 let task
= futures
::future
::select(future
, abort_future
);
52 tokio
::spawn(task
.map(|_
| ()));
54 let mut stream
= signal(SignalKind
::hangup())?
;
56 let future
= async
move {
57 while stream
.recv().await
.is_some() {
58 println
!("got reload request (SIGHUP)");
59 SERVER_STATE
.lock().unwrap().reload_request
= true;
60 crate::request_shutdown();
64 let abort_future
= last_worker_future().map_err(|_
| {}
);
65 let task
= futures
::future
::select(future
, abort_future
);
67 tokio
::spawn(task
.map(|_
| ()));
72 pub fn is_reload_request() -> bool
{
73 let data
= SERVER_STATE
.lock().unwrap();
75 data
.mode
== ServerMode
::Shutdown
&& data
.reload_request
78 pub fn server_shutdown() {
79 let mut data
= SERVER_STATE
.lock().unwrap();
81 println
!("SET SHUTDOWN MODE");
83 data
.mode
= ServerMode
::Shutdown
;
85 data
.shutdown_listeners
.notify_listeners(Ok(()));
92 pub fn shutdown_future() -> impl Future
<Output
= ()> {
93 let mut data
= SERVER_STATE
.lock().unwrap();
100 pub fn last_worker_future() -> impl Future
<Output
= Result
<(), Error
>> {
101 let mut data
= SERVER_STATE
.lock().unwrap();
102 data
.last_worker_listeners
.listen()
105 pub fn set_worker_count(count
: usize) {
106 SERVER_STATE
.lock().unwrap().worker_count
= count
;
111 pub fn check_last_worker() {
112 let mut data
= SERVER_STATE
.lock().unwrap();
114 if !(data
.mode
== ServerMode
::Shutdown
&& data
.worker_count
== 0 && data
.internal_task_count
== 0) { return; }
116 data
.last_worker_listeners
.notify_listeners(Ok(()));
119 /// Spawns a tokio task that will be tracked for reload
120 /// and if it is finished, notify the last_worker_listener if we
121 /// are in shutdown mode
122 pub fn spawn_internal_task
<T
>(task
: T
)
124 T
: Future
+ Send
+ '
static,
125 T
::Output
: Send
+ '
static,
127 let mut data
= SERVER_STATE
.lock().unwrap();
128 data
.internal_task_count
+= 1;
130 tokio
::spawn(async
move {
131 let _
= tokio
::spawn(task
).await
; // ignore errors
134 let mut data
= SERVER_STATE
.lock().unwrap();
135 if data
.internal_task_count
> 0 {
136 data
.internal_task_count
-= 1;