exocore_core/cell/
cell_apps.rs1use std::{
2 collections::HashMap,
3 path::PathBuf,
4 sync::{Arc, RwLock},
5};
6
7use exocore_protos::{generated::exocore_core::CellApplicationConfig, registry::Registry};
8
9use super::{Application, ApplicationId, CellId, Error};
10use crate::{dir::DynDirectory, sec::keys::PublicKey};
11
12#[derive(Clone)]
14pub struct CellApplications {
15 applications: Arc<RwLock<HashMap<ApplicationId, CellApplication>>>,
16 schemas: Arc<Registry>,
17}
18
19impl CellApplications {
20 pub(crate) fn new(schemas: Arc<Registry>) -> CellApplications {
21 CellApplications {
22 applications: Arc::new(RwLock::new(HashMap::new())),
23 schemas,
24 }
25 }
26
27 pub(crate) fn load_from_configurations<'c, I>(
28 &self,
29 cell_id: &CellId,
30 apps_dir: &DynDirectory,
31 iter: I,
32 ) -> Result<(), Error>
33 where
34 I: Iterator<Item = &'c CellApplicationConfig> + 'c,
35 {
36 for cell_app in iter {
37 let app_id = ApplicationId::from_base58_public_key(&cell_app.public_key)?;
38 let app_dir = cell_app_directory(apps_dir, &app_id, &cell_app.version);
39 let app_pk = PublicKey::decode_base58_string(&cell_app.public_key)?;
40
41 if Application::manifest_exists(app_dir.clone()) {
42 info!(
43 "{}: Adding loaded application '{}' (id='{}')",
44 cell_id, cell_app.name, app_id
45 );
46 let app = Application::from_directory(app_dir).map_err(|err| {
47 Error::Application(
48 cell_app.name.clone(),
49 anyhow!("failed to load from directory: {}", err),
50 )
51 })?;
52 self.add_loaded_application(cell_app.clone(), app)?;
53 } else {
54 info!(
55 "{}: Adding unloaded application '{}' (id='{}')",
56 cell_id, cell_app.name, app_id
57 );
58 self.add_unloaded_application(app_id, app_pk, cell_app.clone())?;
59 }
60 }
61
62 Ok(())
63 }
64
65 fn add_loaded_application(
66 &self,
67 cell_app_config: CellApplicationConfig,
68 application: Application,
69 ) -> Result<(), Error> {
70 let mut apps = self.applications.write().unwrap();
71
72 for fd_set in application.schemas() {
73 self.schemas.register_file_descriptor_set(fd_set);
74 }
75
76 apps.insert(
77 application.id().clone(),
78 CellApplication {
79 id: application.id().clone(),
80 name: application.name().to_string(),
81 version: application.version().to_string(),
82 public_key: application.public_key().clone(),
83 application: Some(application),
84 package_url: cell_app_config.package_url,
85 },
86 );
87 Ok(())
88 }
89
90 fn add_unloaded_application(
91 &self,
92 id: ApplicationId,
93 public_key: PublicKey,
94 cell_app: CellApplicationConfig,
95 ) -> Result<(), Error> {
96 let mut apps = self.applications.write().unwrap();
97
98 apps.insert(
99 id.clone(),
100 CellApplication {
101 id,
102 name: cell_app.name,
103 version: cell_app.version,
104 public_key,
105 application: None,
106 package_url: cell_app.package_url,
107 },
108 );
109 Ok(())
110 }
111
112 pub fn get(&self) -> Vec<CellApplication> {
113 let apps = self.applications.read().expect("couldn't lock inner");
114 apps.values().cloned().collect()
115 }
116}
117
118#[derive(Clone)]
119pub struct CellApplication {
120 id: ApplicationId,
121 name: String,
122 version: String,
123 public_key: PublicKey,
124 application: Option<Application>,
125 package_url: String,
126}
127
128impl CellApplication {
129 pub fn id(&self) -> &ApplicationId {
130 &self.id
131 }
132
133 pub fn name(&self) -> &str {
134 &self.name
135 }
136
137 pub fn version(&self) -> &str {
138 &self.version
139 }
140
141 pub fn public_key(&self) -> &PublicKey {
142 &self.public_key
143 }
144
145 pub fn package_url(&self) -> &str {
146 self.package_url.as_str()
147 }
148
149 pub fn is_loaded(&self) -> bool {
150 self.application.is_some()
151 }
152
153 pub fn get(&self) -> Option<&Application> {
154 self.application.as_ref()
155 }
156}
157
158pub fn cell_app_directory(
159 apps_dir: &DynDirectory,
160 app_id: &ApplicationId,
161 app_version: &str,
162) -> DynDirectory {
163 apps_dir.scope(PathBuf::from(format!("{}_{}", app_id, app_version)))
164}