@@ -467,6 +467,98 @@ bool swiftscan_cached_output_load(swiftscan_cached_output_t output,
467
467
return success ();
468
468
}
469
469
470
+ namespace {
471
+ // / Asynchronously visits the graph of the object node to ensure it's fully
472
+ // / materialized.
473
+ class AsyncObjectLoader
474
+ : public std::enable_shared_from_this<AsyncObjectLoader> {
475
+ void *Ctx;
476
+ void (*Callback)(void *Ctx, bool , swiftscan_string_ref_t );
477
+ llvm::cas::ObjectStore &CAS;
478
+
479
+ // The output handle to update after load if set.
480
+ SwiftCachedOutputHandle *OutputHandle;
481
+
482
+ llvm::SmallDenseSet<llvm::cas::ObjectRef> ObjectsSeen;
483
+ unsigned NumPending = 0 ;
484
+ std::optional<llvm::cas::ObjectProxy> RootObj;
485
+ std::atomic<bool > MissingNode{false };
486
+ // / The first error that occurred.
487
+ std::optional<llvm::Error> ErrOccurred;
488
+ std::mutex Mutex;
489
+
490
+ public:
491
+ AsyncObjectLoader (void *Ctx,
492
+ void (*Callback)(void *Ctx, bool , swiftscan_string_ref_t ),
493
+ llvm::cas::ObjectStore &CAS,
494
+ SwiftCachedOutputHandle *Handle = nullptr)
495
+ : Ctx(Ctx), Callback(Callback), CAS(CAS), OutputHandle(Handle) {}
496
+
497
+ void visit (llvm::cas::ObjectRef Ref, bool IsRootNode) {
498
+ {
499
+ std::lock_guard<std::mutex> Guard (Mutex);
500
+ if (!ObjectsSeen.insert (Ref).second )
501
+ return ;
502
+ ++NumPending;
503
+ }
504
+ auto This = shared_from_this ();
505
+ CAS.getProxyAsync (
506
+ Ref, [This, IsRootNode](
507
+ llvm::Expected<std::optional<llvm::cas::ObjectProxy>> Obj) {
508
+ SWIFT_DEFER { This->finishedNode (); };
509
+ if (!Obj) {
510
+ This->encounteredError (Obj.takeError ());
511
+ return ;
512
+ }
513
+ if (!*Obj) {
514
+ This->MissingNode = true ;
515
+ return ;
516
+ }
517
+ if (IsRootNode)
518
+ This->RootObj = *Obj;
519
+ if (auto Err = (*Obj)->forEachReference (
520
+ [&This](llvm::cas::ObjectRef Sub) -> llvm::Error {
521
+ This->visit (Sub, /* IsRootNode*/ false );
522
+ return llvm::Error::success ();
523
+ })) {
524
+ This->encounteredError (std::move (Err));
525
+ return ;
526
+ }
527
+ });
528
+ }
529
+
530
+ void finishedNode () {
531
+ {
532
+ std::lock_guard<std::mutex> Guard (Mutex);
533
+ assert (NumPending);
534
+ --NumPending;
535
+ if (NumPending != 0 )
536
+ return ;
537
+ }
538
+ if (ErrOccurred) {
539
+ std::string ErrMsg = toString (std::move (*ErrOccurred));
540
+ return Callback (Ctx, false , createNonOwningString (ErrMsg));
541
+ }
542
+ if (MissingNode)
543
+ return Callback (Ctx, false , swift::c_string_utils::create_null ());
544
+
545
+ if (OutputHandle)
546
+ OutputHandle->LoadedProxy = RootObj;
547
+ return Callback (Ctx, true , swift::c_string_utils::create_null ());
548
+ }
549
+
550
+ // / Only keeps the first error that occurred.
551
+ void encounteredError (llvm::Error &&E) {
552
+ std::lock_guard<std::mutex> Guard (Mutex);
553
+ if (ErrOccurred) {
554
+ llvm::consumeError (std::move (E));
555
+ return ;
556
+ }
557
+ ErrOccurred = std::move (E);
558
+ }
559
+ };
560
+ } // namespace
561
+
470
562
void swiftscan_cached_output_load_async (
471
563
swiftscan_cached_output_t output, void *ctx,
472
564
void (*callback)(void *ctx, bool success, swiftscan_string_ref_t error),
@@ -478,93 +570,35 @@ void swiftscan_cached_output_load_async(
478
570
if (Out->LoadedProxy )
479
571
return callback (ctx, true , swift::c_string_utils::create_null ());
480
572
481
- // / Asynchronously visits the graph of the object node to ensure it's fully
482
- // / materialized.
483
- class AsyncObjectLoader
484
- : public std::enable_shared_from_this<AsyncObjectLoader> {
485
- void *Ctx;
486
- void (*Callback)(void *Ctx, bool , swiftscan_string_ref_t );
487
- SwiftCachedOutputHandle &Handle;
488
-
489
- llvm::SmallDenseSet<llvm::cas::ObjectRef> ObjectsSeen;
490
- unsigned NumPending = 0 ;
491
- std::optional<llvm::cas::ObjectProxy> RootObj;
492
- std::atomic<bool > MissingNode{false };
493
- // / The first error that occurred.
494
- std::optional<llvm::Error> ErrOccurred;
495
- std::mutex Mutex;
496
-
497
- public:
498
- AsyncObjectLoader (void *Ctx,
499
- void (*Callback)(void *Ctx, bool , swiftscan_string_ref_t ),
500
- SwiftCachedOutputHandle &Handle)
501
- : Ctx(Ctx), Callback(Callback), Handle(Handle) {}
502
-
503
- void visit (llvm::cas::ObjectRef Ref, bool IsRootNode) {
504
- {
505
- std::lock_guard<std::mutex> Guard (Mutex);
506
- if (!ObjectsSeen.insert (Ref).second )
507
- return ;
508
- ++NumPending;
509
- }
510
- auto This = shared_from_this ();
511
- Handle.CAS .getProxyAsync (
512
- Ref, [This, IsRootNode](
513
- llvm::Expected<std::optional<llvm::cas::ObjectProxy>> Obj) {
514
- SWIFT_DEFER { This->finishedNode (); };
515
- if (!Obj) {
516
- This->encounteredError (Obj.takeError ());
517
- return ;
518
- }
519
- if (!*Obj) {
520
- This->MissingNode = true ;
521
- return ;
522
- }
523
- if (IsRootNode)
524
- This->RootObj = *Obj;
525
- if (auto Err = (*Obj)->forEachReference (
526
- [&This](llvm::cas::ObjectRef Sub) -> llvm::Error {
527
- This->visit (Sub, /* IsRootNode*/ false );
528
- return llvm::Error::success ();
529
- })) {
530
- This->encounteredError (std::move (Err));
531
- return ;
532
- }
533
- });
534
- }
573
+ auto Loader =
574
+ std::make_shared<AsyncObjectLoader>(ctx, callback, Out->CAS , Out);
575
+ Loader->visit (Out->Ref , /* IsRootNode*/ true );
576
+ }
535
577
536
- void finishedNode () {
537
- {
538
- std::lock_guard<std::mutex> Guard (Mutex);
539
- assert (NumPending);
540
- --NumPending;
541
- if (NumPending != 0 )
542
- return ;
543
- }
544
- if (ErrOccurred) {
545
- std::string ErrMsg = toString (std::move (*ErrOccurred));
546
- return Callback (Ctx, false , createNonOwningString (ErrMsg));
547
- }
548
- if (MissingNode)
549
- return Callback (Ctx, false , swift::c_string_utils::create_null ());
550
-
551
- Handle.LoadedProxy = RootObj;
552
- return Callback (Ctx, true , swift::c_string_utils::create_null ());
553
- }
578
+ void swiftscan_cache_download_cas_object_async (
579
+ swiftscan_cas_t cas, const char *id, void *ctx,
580
+ void (*callback)(void *ctx, bool success, swiftscan_string_ref_t error),
581
+ swiftscan_cache_cancellation_token_t *token) {
582
+ if (token)
583
+ *token = nullptr ;
554
584
555
- // / Only keeps the first error that occurred.
556
- void encounteredError (llvm::Error &&E) {
557
- std::lock_guard<std::mutex> Guard (Mutex);
558
- if (ErrOccurred) {
559
- llvm::consumeError (std::move (E));
560
- return ;
561
- }
562
- ErrOccurred = std::move (E);
563
- }
585
+ auto failure = [ctx, callback](llvm::Error E) {
586
+ std::string ErrMsg = toString (std::move (E));
587
+ return callback (ctx, false , createNonOwningString (ErrMsg));
564
588
};
565
589
566
- auto Loader = std::make_shared<AsyncObjectLoader>(ctx, callback, *Out);
567
- Loader->visit (Out->Ref, /* IsRootNode*/ true );
590
+ auto &CAS = unwrap (cas)->getCAS ();
591
+ auto ID = CAS.parseID (id);
592
+ if (!ID)
593
+ return failure (ID.takeError ());
594
+
595
+ auto Ref = CAS.getReference (*ID);
596
+ if (!Ref)
597
+ return callback (ctx, false , swift::c_string_utils::create_null ());
598
+
599
+ auto Loader =
600
+ std::make_shared<AsyncObjectLoader>(ctx, callback, CAS);
601
+ Loader->visit (*Ref, /* IsRootNode*/ true );
568
602
}
569
603
570
604
bool swiftscan_cached_output_is_materialized (swiftscan_cached_output_t output) {
0 commit comments