]> git.proxmox.com Git - proxmox-backup.git/blame - src/api2/admin/datastore/backup/environment.rs
src/api2/types.rs: add schema/format for file names
[proxmox-backup.git] / src / api2 / admin / datastore / backup / environment.rs
CommitLineData
b4b63e52 1use failure::*;
f9578f3c 2use std::sync::{Arc, Mutex};
d95ced64
DM
3use std::collections::HashMap;
4
5use serde_json::Value;
6
7use crate::api_schema::router::{RpcEnvironment, RpcEnvironmentType};
8use crate::server::WorkerTask;
21ee7912 9use crate::backup::*;
b4b63e52
DM
10use crate::server::formatter::*;
11use hyper::{Body, Response};
d95ced64 12
f9578f3c
DM
13struct SharedBackupState {
14 uid_counter: usize,
15 dynamic_writers: HashMap<usize, (u64 /* offset */, DynamicIndexWriter)>,
16}
17
d95ced64
DM
18/// `RpcEnvironmet` implementation for backup service
19#[derive(Clone)]
20pub struct BackupEnvironment {
21 env_type: RpcEnvironmentType,
22 result_attributes: HashMap<String, Value>,
23 user: String,
b4b63e52 24 pub formatter: &'static OutputFormatter,
21ee7912
DM
25 pub worker: Arc<WorkerTask>,
26 pub datastore: Arc<DataStore>,
f9578f3c 27 pub backup_dir: BackupDir,
b02a52e3 28 pub last_backup: Option<BackupInfo>,
f9578f3c 29 state: Arc<Mutex<SharedBackupState>>
d95ced64
DM
30}
31
32impl BackupEnvironment {
f9578f3c
DM
33 pub fn new(
34 env_type: RpcEnvironmentType,
35 user: String,
36 worker: Arc<WorkerTask>,
37 datastore: Arc<DataStore>,
38 backup_dir: BackupDir,
f9578f3c
DM
39 ) -> Self {
40
41 let state = SharedBackupState {
42 uid_counter: 0,
43 dynamic_writers: HashMap::new(),
44 };
45
d95ced64
DM
46 Self {
47 result_attributes: HashMap::new(),
48 env_type,
49 user,
50 worker,
21ee7912 51 datastore,
b4b63e52 52 formatter: &JSON_FORMATTER,
f9578f3c 53 backup_dir,
b02a52e3 54 last_backup: None,
f9578f3c 55 state: Arc::new(Mutex::new(state)),
d95ced64
DM
56 }
57 }
58
f9578f3c
DM
59 /// Get an unique integer ID
60 pub fn next_uid(&self) -> usize {
61 let mut state = self.state.lock().unwrap();
62 state.uid_counter += 1;
63 state.uid_counter
64 }
65
66 /// Store the writer with an unique ID
67 pub fn register_dynamic_writer(&self, writer: DynamicIndexWriter) -> usize {
68 let mut state = self.state.lock().unwrap();
69 state.uid_counter += 1;
70 let uid = state.uid_counter;
71
72 state.dynamic_writers.insert(uid, (0, writer));
73 uid
74 }
75
76 /// Append chunk to dynamic writer
77 pub fn dynamic_writer_append_chunk(&self, wid: usize, size: u64, digest: &[u8; 32]) -> Result<(), Error> {
78 let mut state = self.state.lock().unwrap();
79
80 let mut data = match state.dynamic_writers.get_mut(&wid) {
81 Some(data) => data,
82 None => bail!("dynamic writer '{}' not registered", wid),
83 };
84
85 data.0 += size;
86
87 data.1.add_chunk(data.0, digest)?;
88
89 Ok(())
90 }
91
d95ced64
DM
92 pub fn log<S: AsRef<str>>(&self, msg: S) {
93 self.worker.log(msg);
94 }
b4b63e52
DM
95
96 pub fn format_response(&self, result: Result<Value, Error>) -> Response<Body> {
97 match result {
98 Ok(data) => (self.formatter.format_data)(data, self),
99 Err(err) => (self.formatter.format_error)(err),
100 }
101 }
d95ced64
DM
102}
103
104impl RpcEnvironment for BackupEnvironment {
105
106 fn set_result_attrib(&mut self, name: &str, value: Value) {
107 self.result_attributes.insert(name.into(), value);
108 }
109
110 fn get_result_attrib(&self, name: &str) -> Option<&Value> {
111 self.result_attributes.get(name)
112 }
113
114 fn env_type(&self) -> RpcEnvironmentType {
115 self.env_type
116 }
117
118 fn set_user(&mut self, _user: Option<String>) {
119 panic!("unable to change user");
120 }
121
122 fn get_user(&self) -> Option<String> {
123 Some(self.user.clone())
124 }
125}
21ee7912
DM
126
127impl AsRef<BackupEnvironment> for RpcEnvironment {
128 fn as_ref(&self) -> &BackupEnvironment {
129 self.as_any().downcast_ref::<BackupEnvironment>().unwrap()
130 }
131}
b4b63e52
DM
132impl AsRef<BackupEnvironment> for Box<RpcEnvironment> {
133 fn as_ref(&self) -> &BackupEnvironment {
134 self.as_any().downcast_ref::<BackupEnvironment>().unwrap()
135 }
136}