1use crate::storage::{ArtifactLoadOp, ArtifactStorage, HandleOp, IndirectIdentifier};
2use crate::ArtifactTypeId;
3use crossbeam_channel::{Receiver, Sender};
4use hydrate_base::handle::{
5 ArtifactRef, LoadState, LoadStateProvider, LoaderInfoProvider, ResolvedLoadHandle,
6};
7use hydrate_base::hashing::{HashMap, HashSet};
8use hydrate_base::ArtifactId;
9use hydrate_base::{ArtifactManifestData, LoadHandle, StringHash};
10use std::fmt::Formatter;
11use std::hash::Hash;
12use std::sync::atomic::Ordering;
13use std::sync::{Arc, Mutex};
14
15#[derive(Debug)]
31pub struct ArtifactMetadata {
32 pub dependencies: Vec<ArtifactId>,
33 pub artifact_type_id: ArtifactTypeId,
34 pub hash: u64,
35 }
37
38pub struct ArtifactData {
40 pub data: Vec<u8>,
41}
42
43impl std::fmt::Debug for ArtifactData {
44 fn fmt(
45 &self,
46 f: &mut std::fmt::Formatter<'_>,
47 ) -> std::fmt::Result {
48 f.debug_struct("ArtifactData")
49 .field("data_length", &self.data.len())
50 .finish()
51 }
52}
53
54#[derive(Debug)]
56pub struct RequestMetadataResult {
57 pub artifact_id: ArtifactId,
58 pub load_handle: LoadHandle,
59 pub result: std::io::Result<ArtifactMetadata>,
61}
62
63#[derive(Debug)]
65pub struct RequestDataResult {
66 pub artifact_id: ArtifactId,
67 pub load_handle: LoadHandle,
68 pub result: std::io::Result<ArtifactData>,
71}
72
73#[derive(Copy, Clone, PartialEq, Eq)]
77pub struct ManifestBuildHash(pub u64);
78
79impl std::fmt::Debug for ManifestBuildHash {
80 fn fmt(
81 &self,
82 f: &mut Formatter<'_>,
83 ) -> std::fmt::Result {
84 write!(f, "ManifestBuildHash({:0>16x})", self.0)
85 }
86}
87
88pub trait LoaderIO: Sync + Send {
90 fn update(&mut self);
91
92 fn current_build_hash(&self) -> ManifestBuildHash;
94
95 fn pending_build_hash(&self) -> Option<ManifestBuildHash>;
97
98 fn activate_pending_build_hash(
100 &mut self,
101 new_build_hash: ManifestBuildHash,
102 );
103
104 fn manifest_entry(
106 &self,
107 artifact_id: ArtifactId,
108 ) -> Option<&ArtifactManifestData>;
109
110 fn resolve_indirect(
113 &self,
114 indirect_identifier: &IndirectIdentifier,
115 ) -> Option<&ArtifactManifestData>;
116
117 fn request_metadata(
120 &self,
121 build_hash: ManifestBuildHash,
122 load_handle: LoadHandle,
123 artifact_id: ArtifactId,
124 );
125
126 fn request_data(
129 &self,
130 build_hash: ManifestBuildHash,
131 load_handle: LoadHandle,
132 artifact_id: ArtifactId,
133 hash: u64,
134 );
135}
136
137#[derive(Debug)]
141pub enum LoaderEvent {
142 TryLoad(LoadHandle),
144 TryUnload(LoadHandle),
146 MetadataRequestComplete(RequestMetadataResult),
148 DependenciesLoaded(LoadHandle),
150 DataRequestComplete(RequestDataResult),
152 LoadResult(HandleOp),
154 }
157
158#[derive(Debug)]
160struct IndirectLoad {
161 id: IndirectIdentifier,
163 resolved_id_and_hash: Option<ArtifactIdAndHash>,
166 external_ref_count_indirect: u32,
169}
170
171struct LoadHandleInfo {
175 artifact_id: ArtifactId,
176 artifact_type_id: ArtifactTypeId,
177
178 hash: u64,
180 load_state: LoadState,
182
183 external_ref_count_direct: u32,
193
194 internal_ref_count: u32,
198
199 blocking_dependency_count: u32,
201
202 blocked_loads: Vec<LoadHandle>,
204
205 dependencies: Vec<LoadHandle>,
208
209 symbol: Option<StringHash>,
211 debug_name: Option<Arc<String>>,
213}
214
215struct ReloadAction {
218 load_handles_to_reload: Vec<LoadHandle>,
223}
224
225#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
226struct ArtifactIdAndHash {
227 id: ArtifactId,
228 hash: u64,
229}
230
231struct LoaderInner {
232 next_handle_index: u64,
233
234 load_handle_infos: HashMap<LoadHandle, LoadHandleInfo>,
237 artifact_id_to_handle: HashMap<ArtifactIdAndHash, LoadHandle>,
241
242 loader_io: Box<dyn LoaderIO>,
244
245 events_tx: Sender<LoaderEvent>,
248 events_rx: Receiver<LoaderEvent>,
249
250 indirect_states: HashMap<LoadHandle, IndirectLoad>,
252 indirect_to_load: HashMap<IndirectIdentifier, Arc<ResolvedLoadHandle>>,
256
257 current_build_hash: ManifestBuildHash,
259 current_reload_action: Option<ReloadAction>,
260}
261
262impl LoaderInner {
263 pub fn log_load_state_recursive(
264 &self,
265 load_handle: LoadHandle,
266 indent: usize,
267 ) {
268 let load_handle_info = self.load_handle_infos.get(&load_handle).unwrap();
269 log::debug!(
270 "{:indent$}{:?} {:?} {:?}",
271 "",
272 load_handle_info.artifact_id,
273 load_handle_info.debug_name,
274 load_handle_info.load_state,
275 indent = indent
276 );
277 for dependency in &load_handle_info.dependencies {
278 self.log_load_state_recursive(*dependency, indent + 2);
279 }
280 }
281
282 #[profiling::function]
285 fn update(
286 &mut self,
287 artifact_storage: &mut dyn ArtifactStorage,
288 ) {
289 self.loader_io.update();
290
291 if let Some(current_reload_action) = &self.current_reload_action {
292 let mut reload_complete = true;
298 for &load_handle in ¤t_reload_action.load_handles_to_reload {
299 let load_handle_info = self.load_handle_infos.get(&load_handle).unwrap();
300 if load_handle_info.load_state != LoadState::Loaded {
301 reload_complete = false;
304 break;
305 }
306 }
307
308 if reload_complete {
309 log::info!("All artifacts we need to reload are ready, updating indirect handles to point at new data");
313
314 for (_, indirect_load) in &mut self.indirect_states {
316 let new_manifest_entry = self.loader_io.resolve_indirect(&indirect_load.id);
318 let new_id_and_hash = new_manifest_entry.map(|x| ArtifactIdAndHash {
319 id: x.artifact_id,
320 hash: x.combined_build_hash,
321 });
322 let old_id_and_hash = indirect_load.resolved_id_and_hash;
323
324 let artifact_changed = old_id_and_hash != new_id_and_hash;
327 if artifact_changed {
328 let new_load_handle_direct = if let Some(new_id_and_hash) = new_id_and_hash
330 {
331 let new_load_handle_direct =
332 *self.artifact_id_to_handle.get(&new_id_and_hash).unwrap();
333 let new_load_handle_info = self
334 .load_handle_infos
335 .get_mut(&new_load_handle_direct)
336 .unwrap();
337
338 new_load_handle_info.external_ref_count_direct +=
343 indirect_load.external_ref_count_indirect;
344 for _ in 0..indirect_load.external_ref_count_indirect {
345 Self::add_internal_ref(
346 &self.events_tx,
347 new_load_handle_direct,
348 new_load_handle_info,
349 );
350 }
351 new_load_handle_direct
352 } else {
353 LoadHandle(0)
355 };
356
357 indirect_load.resolved_id_and_hash = new_id_and_hash;
359 let old_load_handle_direct = self
360 .indirect_to_load
361 .get(&indirect_load.id)
362 .unwrap()
363 .direct_load_handle
364 .swap(new_load_handle_direct.0, Ordering::Relaxed);
365 log::info!(
366 "Update indirect handle {:?} => {:?} -> {:?}",
367 indirect_load.id,
368 LoadHandle(old_load_handle_direct),
369 new_load_handle_direct
370 );
371
372 if let Some(old_id_and_hash) = &old_id_and_hash {
374 let old_load_handle_direct =
375 *self.artifact_id_to_handle.get(&old_id_and_hash).unwrap();
376 let old_load_handle_info = self
377 .load_handle_infos
378 .get_mut(&old_load_handle_direct)
379 .unwrap();
380
381 old_load_handle_info.external_ref_count_direct -=
386 indirect_load.external_ref_count_indirect;
387 for _ in 0..indirect_load.external_ref_count_indirect {
388 Self::remove_internal_ref(
389 &self.events_tx,
390 old_load_handle_direct,
391 old_load_handle_info,
392 );
393 }
394 }
395 }
396 }
397
398 for &load_handle in ¤t_reload_action.load_handles_to_reload {
400 let load_handle_info = self.load_handle_infos.get_mut(&load_handle).unwrap();
401 log::info!("Remove temporary load handle ref for {:?}", load_handle);
402 Self::remove_internal_ref(&self.events_tx, load_handle, load_handle_info);
403 }
404
405 log::info!(
407 "Finished artifact reload, now on manifest build hash {:?}",
408 self.current_build_hash
409 );
410 self.current_reload_action = None;
411 }
412 } else if let Some(pending_build_hash) = self.loader_io.pending_build_hash() {
413 let old_build_hash = self.current_build_hash;
420 self.loader_io
421 .activate_pending_build_hash(pending_build_hash);
422 self.current_build_hash = self.loader_io.current_build_hash();
423
424 log::info!(
425 "Begin artifact reload {:?} -> {:?}",
426 old_build_hash,
427 self.current_build_hash
428 );
429
430 let mut artifacts_to_reload = HashSet::default();
432 for (_, indirect_load) in &self.indirect_states {
433 let new_manifest_entry = self.loader_io.resolve_indirect(&indirect_load.id);
435 let new_id_and_hash = new_manifest_entry.map(|x| ArtifactIdAndHash {
436 id: x.artifact_id,
437 hash: x.combined_build_hash,
438 });
439 let old_id_and_hash = indirect_load.resolved_id_and_hash;
440
441 let artifact_changed = old_id_and_hash != new_id_and_hash;
444 if artifact_changed {
445 log::info!("indirect load {:?} is in the new manifest but has changed, hash {:?} -> {:?}", indirect_load.id, old_id_and_hash, new_id_and_hash);
446 if let Some(new_manifest_entry) = &new_manifest_entry {
448 artifacts_to_reload.insert(ArtifactIdAndHash {
449 id: new_manifest_entry.artifact_id,
450 hash: new_manifest_entry.combined_build_hash,
451 });
452 }
453 }
454 }
455
456 let mut load_handles_to_reload = vec![];
458 for new_handle in artifacts_to_reload {
459 let new_load_handle = self.get_or_insert_direct(new_handle);
460 let new_load_handle_info =
461 self.load_handle_infos.get_mut(&new_load_handle).unwrap();
462
463 log::info!("Add temporary load handle ref for {:?}", new_load_handle);
465 Self::add_internal_ref(&self.events_tx, new_load_handle, new_load_handle_info);
466 load_handles_to_reload.push(new_load_handle);
467 }
468
469 self.current_reload_action = Some(ReloadAction {
470 load_handles_to_reload,
471 });
472 }
473
474 while let Ok(loader_event) = self.events_rx.try_recv() {
475 log::debug!("handle event {:?}", loader_event);
476 match loader_event {
477 LoaderEvent::TryLoad(load_handle) => {
478 self.handle_try_load(self.current_build_hash, load_handle)
479 }
480 LoaderEvent::TryUnload(load_handle) => {
481 self.handle_try_unload(load_handle, artifact_storage)
482 }
483 LoaderEvent::MetadataRequestComplete(result) => {
484 self.handle_request_metadata_result(self.current_build_hash, result)
485 }
486 LoaderEvent::DependenciesLoaded(load_handle) => {
487 self.handle_dependencies_loaded(self.current_build_hash, load_handle)
488 }
489 LoaderEvent::DataRequestComplete(result) => {
490 self.handle_request_data_result(result, artifact_storage)
491 }
492 LoaderEvent::LoadResult(load_result) => {
493 self.handle_load_result(load_result, artifact_storage)
494 }
495 }
496 }
497 }
498
499 fn handle_try_load(
500 &mut self,
501 build_hash: ManifestBuildHash,
502 load_handle: LoadHandle,
503 ) {
504 let load_state_info = self.load_handle_infos.get_mut(&load_handle).unwrap();
506
507 log::debug!(
508 "handle_try_load {:?} {:?} {:?} {:0>16x}",
509 load_handle,
510 load_state_info.debug_name,
511 load_state_info.artifact_id,
512 load_state_info.hash
513 );
514
515 let artifact_id = load_state_info.artifact_id;
518 if load_state_info.load_state == LoadState::Unloaded {
519 if load_state_info.internal_ref_count > 0 {
521 self.loader_io
523 .request_metadata(build_hash, load_handle, artifact_id);
524 load_state_info.load_state = LoadState::WaitingForMetadata;
525 } else {
526 }
529 } else {
530 }
533 }
534
535 fn handle_try_unload(
536 &mut self,
537 load_handle: LoadHandle,
538 artifact_storage: &mut dyn ArtifactStorage,
539 ) {
540 let load_state_info = self.load_handle_infos.get_mut(&load_handle).unwrap();
542
543 log::debug!(
544 "handle_try_unload {:?} {:?} {:?} {:0>16x}",
545 load_handle,
546 load_state_info.debug_name,
547 load_state_info.artifact_id,
548 load_state_info.hash
549 );
550
551 let mut dependencies = vec![];
552
553 if load_state_info.load_state != LoadState::Unloaded {
554 if load_state_info.internal_ref_count > 0 {
557 } else {
559 if load_state_info.load_state == LoadState::Loading
563 || load_state_info.load_state == LoadState::Loaded
564 {
565 artifact_storage.free_artifact(load_state_info.artifact_type_id, load_handle);
566 }
567
568 std::mem::swap(&mut dependencies, &mut load_state_info.dependencies);
569
570 load_state_info.load_state = LoadState::Unloaded;
571 }
572 } else {
573 }
575
576 for depenency_load_handle in dependencies {
579 let depenency_load_handle_info = self
580 .load_handle_infos
581 .get_mut(&depenency_load_handle)
582 .unwrap();
583 Self::remove_internal_ref(
584 &self.events_tx,
585 depenency_load_handle,
586 depenency_load_handle_info,
587 );
588 }
589 }
590
591 fn handle_request_metadata_result(
592 &mut self,
593 build_hash: ManifestBuildHash,
594 result: RequestMetadataResult,
595 ) {
596 if let Some(load_state_info) = self.load_handle_infos.get(&result.load_handle) {
597 log::debug!(
598 "handle_request_metadata_result {:?} {:?} {:?} {:0>16x}",
599 result.load_handle,
600 load_state_info.debug_name,
601 load_state_info.artifact_id,
602 load_state_info.hash
603 );
604 let load_state = load_state_info.load_state;
605 if load_state == LoadState::Unloaded {
607 return;
608 }
609
610 assert_eq!(load_state, LoadState::WaitingForMetadata);
611 } else {
612 unreachable!();
614 }
615
616 let metadata = result.result.unwrap();
618
619 let mut blocking_dependency_count = 0;
620
621 let mut dependency_load_handles = vec![];
622 for dependency in &metadata.dependencies {
623 let dependency_manifest_entry = self.loader_io.manifest_entry(*dependency).unwrap();
624
625 let dependency_load_handle = self.get_or_insert_direct(ArtifactIdAndHash {
626 id: *dependency,
627 hash: dependency_manifest_entry.combined_build_hash,
628 });
629 let dependency_load_handle_info = self
630 .load_handle_infos
631 .get_mut(&dependency_load_handle)
632 .unwrap();
633
634 dependency_load_handles.push(dependency_load_handle);
635
636 Self::add_internal_ref(
637 &self.events_tx,
638 dependency_load_handle,
639 dependency_load_handle_info,
640 );
641
642 let load_state = dependency_load_handle_info.load_state;
643 if load_state != LoadState::Loaded {
644 blocking_dependency_count += 1;
645
646 dependency_load_handle_info
647 .blocked_loads
648 .push(result.load_handle);
649 }
650 }
651
652 if let Some(load_state_info) = self.load_handle_infos.get_mut(&result.load_handle) {
653 let artifact_id = load_state_info.artifact_id;
654 load_state_info.artifact_type_id = metadata.artifact_type_id;
655 load_state_info.hash = metadata.hash;
656 load_state_info.dependencies = dependency_load_handles;
657
658 if blocking_dependency_count == 0 {
659 log::debug!("load handle {:?} has no dependencies", result.load_handle);
660 self.loader_io.request_data(
661 build_hash,
662 result.load_handle,
663 artifact_id,
664 metadata.hash,
665 );
667 assert_eq!(load_state_info.blocking_dependency_count, 0);
668 load_state_info.load_state = LoadState::WaitingForData;
669 } else {
670 log::debug!(
671 "load handle {:?} has {} dependencies",
672 result.load_handle,
673 blocking_dependency_count
674 );
675 load_state_info.blocking_dependency_count = blocking_dependency_count;
676 load_state_info.load_state = LoadState::WaitingForDependencies;
677 }
681 } else {
682 unreachable!();
684 }
685 }
686
687 fn handle_dependencies_loaded(
688 &mut self,
689 build_hash: ManifestBuildHash,
690 load_handle: LoadHandle,
691 ) {
692 let load_state_info = self.load_handle_infos.get_mut(&load_handle).unwrap();
694 log::debug!(
695 "handle_dependencies_loaded {:?} {:?} {:?} {:0>16x}",
696 load_handle,
697 load_state_info.debug_name,
698 load_state_info.artifact_id,
699 load_state_info.hash,
700 );
701 if load_state_info.load_state == LoadState::Unloaded {
702 return;
703 }
704
705 assert_eq!(
706 load_state_info.load_state,
707 LoadState::WaitingForDependencies
708 );
709
710 self.loader_io.request_data(
711 build_hash,
712 load_handle,
713 load_state_info.artifact_id,
714 load_state_info.hash,
715 );
717 load_state_info.load_state = LoadState::WaitingForData;
718 }
719
720 fn handle_request_data_result(
721 &mut self,
722 result: RequestDataResult,
723 artifact_storage: &mut dyn ArtifactStorage,
724 ) {
725 let (load_op, load_state_info, data) = {
735 let load_state_info = self.load_handle_infos.get(&result.load_handle).unwrap();
736 log::debug!(
737 "handle_request_data_result {:?} {:?} {:?} {:0>16x}",
738 result.load_handle,
739 load_state_info.debug_name,
740 load_state_info.artifact_id,
741 load_state_info.hash
742 );
743 if load_state_info.load_state == LoadState::Unloaded {
745 return;
746 }
747
748 assert_eq!(load_state_info.load_state, LoadState::WaitingForData);
749
750 let data = result.result.unwrap();
752
753 let load_op = ArtifactLoadOp::new(self.events_tx.clone(), result.load_handle);
754
755 (load_op, load_state_info, data)
756 };
757
758 let info_provider = LoadHandleInfoProviderImpl {
759 artifact_id_to_handle: &self.artifact_id_to_handle,
760 load_handle_infos: &self.load_handle_infos,
761 loader_io: &*self.loader_io,
762 };
763
764 artifact_storage
767 .load_artifact(
768 &info_provider,
769 &load_state_info.artifact_type_id,
770 load_state_info.artifact_id,
771 data.data,
772 result.load_handle,
773 load_op,
774 )
775 .unwrap();
776
777 let load_state_info = self.load_handle_infos.get_mut(&result.load_handle).unwrap();
779 load_state_info.load_state = LoadState::Loading;
780 }
781
782 fn handle_load_result(
783 &mut self,
784 load_result: HandleOp,
785 artifact_storage: &mut dyn ArtifactStorage,
786 ) {
787 match load_result {
790 HandleOp::Error(load_handle, error) => {
791 let load_handle_info = self.load_handle_infos.get(&load_handle).unwrap();
792 log::debug!(
793 "handle_load_result error {:?} {:?} {:?} {:0>16x}",
794 load_handle,
795 load_handle_info.debug_name,
796 load_handle_info.artifact_id,
797 load_handle_info.hash
798 );
799 log::error!("load error {}", error);
801 panic!("load error {}", error);
802 }
803 HandleOp::Complete(load_handle) => {
804 let mut blocked_loads = Vec::default();
809 let artifact_type_id = {
810 let load_handle_info = self.load_handle_infos.get_mut(&load_handle).unwrap();
811 log::debug!(
812 "handle_load_result complete {:?} {:?} {:?} {:0>16x}",
813 load_handle,
814 load_handle_info.debug_name,
815 load_handle_info.artifact_id,
816 load_handle_info.hash
817 );
818 std::mem::swap(&mut blocked_loads, &mut load_handle_info.blocked_loads);
819 load_handle_info.load_state = LoadState::Loaded;
820 load_handle_info.artifact_type_id
821 };
822
823 for blocked_load_handle in blocked_loads {
824 log::trace!("blocked load {:?}", blocked_load_handle);
825 let blocked_load = self
826 .load_handle_infos
827 .get_mut(&blocked_load_handle)
828 .unwrap();
829 blocked_load.blocking_dependency_count -= 1;
830 if blocked_load.blocking_dependency_count == 0 {
831 self.events_tx
833 .send(LoaderEvent::DependenciesLoaded(blocked_load_handle))
834 .unwrap();
835 }
836 }
837
838 artifact_storage.commit_artifact(artifact_type_id, load_handle);
839 }
840 HandleOp::Drop(load_handle) => {
841 log::debug!("handle_load_result drop {:?}", load_handle);
842 log::error!(
843 "load op dropped without calling complete/error, handle {:?}",
844 load_handle,
845 );
846 panic!(
847 "load op dropped without calling complete/error, handle {:?}",
848 load_handle
849 )
850 }
851 }
852 }
853
854 fn get_or_insert_indirect(
857 &mut self,
858 indirect_id: &IndirectIdentifier,
859 ) -> Arc<ResolvedLoadHandle> {
860 let next_handle_index = &mut self.next_handle_index;
861 let indirect_states = &mut self.indirect_states;
862 let loader_io = &mut self.loader_io;
863 self.indirect_to_load
864 .entry(indirect_id.clone())
865 .or_insert_with(|| {
866 let indirect_load_handle = LoadHandle::new(*next_handle_index, true);
867 *next_handle_index += 1;
868
869 let resolved = loader_io.resolve_indirect(indirect_id);
870 if resolved.is_none() {
871 panic!("Couldn't find artifact {:?}", indirect_id);
872 }
873
874 let manifest_entry = resolved.unwrap();
875 log::debug!(
876 "Allocate indirect load handle {:?} for indirect id {:?} -> {:?}",
877 indirect_load_handle,
878 &indirect_id,
879 manifest_entry.artifact_id
880 );
881
882 let resolved_load_handle =
883 ResolvedLoadHandle::new(indirect_load_handle, LoadHandle(0));
884
885 indirect_states.insert(
886 indirect_load_handle,
887 IndirectLoad {
888 id: indirect_id.clone(),
889 resolved_id_and_hash: Some(ArtifactIdAndHash {
890 id: manifest_entry.artifact_id,
891 hash: manifest_entry.combined_build_hash,
892 }),
893 external_ref_count_indirect: 0,
894 },
895 );
896 resolved_load_handle
897 })
898 .clone()
899 }
900
901 fn get_or_insert_direct(
902 &mut self,
903 artifact_id_and_hash: ArtifactIdAndHash,
904 ) -> LoadHandle {
905 let next_handle_index = &mut self.next_handle_index;
906 let load_handle_infos = &mut self.load_handle_infos;
907 let loader_io = &mut self.loader_io;
908 *self
909 .artifact_id_to_handle
910 .entry(artifact_id_and_hash)
911 .or_insert_with(|| {
912 let direct_load_handle = LoadHandle::new(*next_handle_index, false);
913 *next_handle_index += 1;
914 let manifest_entry = loader_io.manifest_entry(artifact_id_and_hash.id).unwrap();
915 assert_eq!(
916 manifest_entry.combined_build_hash,
917 artifact_id_and_hash.hash
918 );
919
920 log::debug!(
921 "Allocate load handle {:?} for artifact id {:?}",
922 direct_load_handle,
923 artifact_id_and_hash,
924 );
925
926 load_handle_infos.insert(
927 direct_load_handle,
928 LoadHandleInfo {
929 artifact_id: artifact_id_and_hash.id,
930 external_ref_count_direct: 0,
931 load_state: LoadState::Unloaded,
932 artifact_type_id: ArtifactTypeId::default(),
933 hash: artifact_id_and_hash.hash,
934 internal_ref_count: 0,
936 blocking_dependency_count: 0,
937 blocked_loads: vec![],
938 dependencies: vec![],
939 symbol: manifest_entry.symbol_hash.clone(),
940 debug_name: manifest_entry.debug_name.clone(),
941 },
942 );
943
944 direct_load_handle
945 })
946 }
947
948 fn add_engine_ref_indirect(
949 &mut self,
950 id: IndirectIdentifier,
951 ) -> Arc<ResolvedLoadHandle> {
952 let indirect_load_handle = self.get_or_insert_indirect(&id);
953
954 let direct_load_handle = self.add_engine_ref_by_handle_indirect(indirect_load_handle.id);
956
957 let direct_load_test = indirect_load_handle
961 .direct_load_handle
962 .swap(direct_load_handle.0, Ordering::Relaxed);
963 assert!(direct_load_test == 0 || direct_load_test == direct_load_handle.0);
964
965 indirect_load_handle
966 }
967
968 fn add_engine_ref_by_handle_indirect(
970 &mut self,
971 indirect_load_handle: LoadHandle,
972 ) -> LoadHandle {
973 assert!(indirect_load_handle.is_indirect());
974 let state = self.indirect_states.get_mut(&indirect_load_handle).unwrap();
975 state.external_ref_count_indirect += 1;
976
977 let resolved_id_and_hash = state.resolved_id_and_hash;
978 if let Some(resolved_id_and_hash) = resolved_id_and_hash {
979 let direct_load_handle = self.get_or_insert_direct(resolved_id_and_hash);
980 self.add_engine_ref_by_handle_direct(direct_load_handle);
981 direct_load_handle
982 } else {
983 LoadHandle(0)
984 }
985 }
986
987 fn add_engine_ref_by_handle_direct(
989 &mut self,
990 direct_load_handle: LoadHandle,
991 ) -> LoadHandle {
992 assert!(!direct_load_handle.is_indirect());
993 let load_handle_info = self.load_handle_infos.get_mut(&direct_load_handle).unwrap();
994 load_handle_info.external_ref_count_direct += 1;
995
996 Self::add_internal_ref(&self.events_tx, direct_load_handle, load_handle_info);
997
998 direct_load_handle
999 }
1000
1001 fn remove_engine_ref_indirect(
1002 &mut self,
1003 indirect_load_handle: LoadHandle,
1004 ) {
1005 assert!(indirect_load_handle.is_indirect());
1006 let state = self.indirect_states.get_mut(&indirect_load_handle).unwrap();
1007 state.external_ref_count_indirect -= 1;
1008 if let Some(resolved_id_and_hash) = &state.resolved_id_and_hash {
1009 let direct_load_handle = *self
1010 .artifact_id_to_handle
1011 .get(resolved_id_and_hash)
1012 .unwrap();
1013 self.remove_engine_ref_direct(direct_load_handle);
1014 }
1015 }
1016
1017 fn remove_engine_ref_direct(
1018 &mut self,
1019 direct_load_handle: LoadHandle,
1020 ) {
1021 assert!(!direct_load_handle.is_indirect());
1022 let load_handle_info = self.load_handle_infos.get_mut(&direct_load_handle).unwrap();
1023 load_handle_info.external_ref_count_direct -= 1;
1024
1025 Self::remove_internal_ref(&self.events_tx, direct_load_handle, load_handle_info);
1027 }
1028
1029 fn add_internal_ref(
1031 events_tx: &Sender<LoaderEvent>,
1032 direct_load_handle: LoadHandle,
1033 load_handle_info: &mut LoadHandleInfo,
1034 ) {
1035 assert!(!direct_load_handle.is_indirect());
1036 load_handle_info.internal_ref_count += 1;
1037
1038 if load_handle_info.internal_ref_count == 1 {
1040 events_tx
1041 .send(LoaderEvent::TryLoad(direct_load_handle))
1042 .unwrap();
1043 }
1044 }
1045
1046 fn remove_internal_ref(
1048 events_tx: &Sender<LoaderEvent>,
1049 direct_load_handle: LoadHandle,
1050 load_handle_info: &mut LoadHandleInfo,
1051 ) {
1052 assert!(!direct_load_handle.is_indirect());
1053 load_handle_info.internal_ref_count -= 1;
1054 if load_handle_info.internal_ref_count == 0 {
1056 events_tx
1057 .send(LoaderEvent::TryUnload(direct_load_handle))
1058 .unwrap();
1059 }
1060 }
1061
1062 pub fn get_load_info(
1063 &self,
1064 handle: LoadHandle,
1065 ) -> Option<LoadInfo> {
1066 let handle = if handle.is_indirect() {
1067 let indirect_id = self.indirect_states.get(&handle).unwrap().id.clone();
1068 self.indirect_to_load
1069 .get(&indirect_id)
1070 .unwrap()
1071 .direct_load_handle()
1072 } else {
1073 handle
1074 };
1075
1076 let load_info = self.load_handle_infos.get(&handle)?;
1077 Some(LoadInfo {
1078 artifact_id: load_info.artifact_id,
1079 refs: load_info.external_ref_count_direct,
1080 symbol: load_info.symbol.clone(),
1081 debug_name: load_info.debug_name.clone(),
1082 })
1084 }
1085}
1086
1087#[derive(Debug)]
1092pub struct LoadInfo {
1093 pub artifact_id: ArtifactId,
1095 pub refs: u32,
1097 pub symbol: Option<StringHash>,
1098 pub debug_name: Option<Arc<String>>,
1099 }
1106
1107#[derive(Clone)]
1111pub struct Loader {
1112 inner: Arc<Mutex<LoaderInner>>,
1113}
1114
1115impl Loader {
1116 pub(crate) fn new(
1117 loader_io: Box<dyn LoaderIO>,
1118 events_tx: Sender<LoaderEvent>,
1119 events_rx: Receiver<LoaderEvent>,
1120 ) -> Self {
1121 let build_hash = loader_io.current_build_hash();
1122
1123 let inner = LoaderInner {
1124 next_handle_index: 1,
1126 artifact_id_to_handle: Default::default(),
1127 load_handle_infos: Default::default(),
1128 loader_io,
1129 events_tx,
1130 events_rx,
1131 indirect_states: Default::default(),
1132 indirect_to_load: Default::default(),
1133 current_build_hash: build_hash,
1134 current_reload_action: None,
1135 };
1136
1137 Loader {
1138 inner: Arc::new(Mutex::new(inner)),
1139 }
1140 }
1141
1142 pub(crate) fn update(
1143 &self,
1144 artifact_storage: &mut dyn ArtifactStorage,
1145 ) {
1146 self.inner.lock().unwrap().update(artifact_storage);
1147 }
1148
1149 pub(crate) fn add_engine_ref_indirect(
1150 &self,
1151 id: IndirectIdentifier,
1152 ) -> Arc<ResolvedLoadHandle> {
1153 self.inner.lock().unwrap().add_engine_ref_indirect(id)
1154 }
1155
1156 pub(crate) fn add_engine_ref_by_handle(
1157 &self,
1158 load_handle: LoadHandle,
1159 ) -> LoadHandle {
1160 if load_handle.is_indirect() {
1161 self.inner
1162 .lock()
1163 .unwrap()
1164 .add_engine_ref_by_handle_indirect(load_handle)
1165 } else {
1166 self.inner
1167 .lock()
1168 .unwrap()
1169 .add_engine_ref_by_handle_direct(load_handle)
1170 }
1171 }
1172
1173 pub(crate) fn remove_engine_ref(
1175 &self,
1176 load_handle: LoadHandle,
1177 ) {
1178 if load_handle.is_indirect() {
1179 self.inner
1180 .lock()
1181 .unwrap()
1182 .remove_engine_ref_indirect(load_handle);
1183 } else {
1184 self.inner
1185 .lock()
1186 .unwrap()
1187 .remove_engine_ref_direct(load_handle);
1188 }
1189 }
1190
1191 pub fn get_active_loads(&self) -> Vec<LoadHandle> {
1193 let mut loading_handles = Vec::default();
1194 let inner = self.inner.lock().unwrap();
1195 for k in inner.load_handle_infos.keys() {
1196 loading_handles.push(k.clone());
1197 }
1198
1199 loading_handles
1200 }
1201
1202 pub fn get_load_info(
1203 &self,
1204 handle: LoadHandle,
1205 ) -> Option<LoadInfo> {
1206 self.inner.lock().unwrap().get_load_info(handle)
1207 }
1208
1209 pub fn log_load_state_recursive(
1210 &self,
1211 load_handle: LoadHandle,
1212 ) {
1213 self.inner
1214 .lock()
1215 .unwrap()
1216 .log_load_state_recursive(load_handle, 0);
1217 }
1218}
1219
1220impl LoadStateProvider for Loader {
1225 fn load_state(
1226 &self,
1227 load_handle: &Arc<ResolvedLoadHandle>,
1228 ) -> LoadState {
1229 self.inner
1230 .lock()
1231 .unwrap()
1232 .load_handle_infos
1233 .get(&load_handle.direct_load_handle())
1234 .unwrap()
1235 .load_state
1236 }
1237
1238 fn artifact_id(
1239 &self,
1240 load_handle: &Arc<ResolvedLoadHandle>,
1241 ) -> ArtifactId {
1242 self.inner
1243 .lock()
1244 .unwrap()
1245 .load_handle_infos
1246 .get(&load_handle.direct_load_handle())
1247 .unwrap()
1248 .artifact_id
1249 }
1250}
1251
1252#[derive(Copy, Clone)]
1259struct LoadHandleInfoProviderImpl<'a> {
1260 artifact_id_to_handle: &'a HashMap<ArtifactIdAndHash, LoadHandle>,
1261 load_handle_infos: &'a HashMap<LoadHandle, LoadHandleInfo>,
1262 loader_io: &'a dyn LoaderIO,
1263}
1264
1265impl<'a> LoaderInfoProvider for LoadHandleInfoProviderImpl<'a> {
1266 fn resolved_load_handle(
1269 &self,
1270 id: &ArtifactRef,
1271 ) -> Option<Arc<ResolvedLoadHandle>> {
1272 let artifact_id = ArtifactId::from_uuid(id.0.as_uuid());
1273 let build_hash = self
1274 .loader_io
1275 .manifest_entry(artifact_id)
1276 .unwrap()
1277 .combined_build_hash;
1278
1279 let load_handle = self
1280 .artifact_id_to_handle
1281 .get(&ArtifactIdAndHash {
1282 id: artifact_id,
1283 hash: build_hash,
1284 })
1285 .map(|l| *l)?;
1286 Some(ResolvedLoadHandle::new(load_handle, load_handle))
1287 }
1288
1289 fn artifact_id(
1291 &self,
1292 load: LoadHandle,
1293 ) -> Option<ArtifactId> {
1294 self.load_handle_infos.get(&load).map(|l| l.artifact_id)
1295 }
1296}