@@ -58,6 +58,7 @@ enum class ActionType {
58
58
AggregateAsJSON,
59
59
ScanDeps,
60
60
ScanDepsByModuleName,
61
+ UploadCachedJob,
61
62
MaterializeCachedJob,
62
63
ReplayCachedJob,
63
64
PruneCAS,
@@ -85,6 +86,8 @@ Action(cl::desc("Action:"), cl::init(ActionType::None),
85
86
" Get file dependencies" ),
86
87
clEnumValN(ActionType::ScanDepsByModuleName, " scan-deps-by-mod-name" ,
87
88
" Get file dependencies by module name alone" ),
89
+ clEnumValN(ActionType::UploadCachedJob, " upload-cached-job" ,
90
+ " Upload cached compilation data to upstream CAS" ),
88
91
clEnumValN(ActionType::MaterializeCachedJob, " materialize-cached-job" ,
89
92
" Materialize cached compilation data from upstream CAS" ),
90
93
clEnumValN(ActionType::ReplayCachedJob, " replay-cached-job" ,
@@ -154,6 +157,10 @@ static cl::list<std::string> CASPluginOpts("fcas-plugin-option",
154
157
cl::desc (" Plugin CAS Options" ));
155
158
static llvm::cl::opt<std::string>
156
159
WorkingDir (" working-dir" , llvm::cl::desc(" Path for working directory" ));
160
+ static cl::opt<bool > TestCASCancellation (
161
+ " test-cas-cancellation" ,
162
+ cl::desc (
163
+ " perform extra CAS API invocation and cancel it for testing purposes" ));
157
164
}
158
165
} // anonymous namespace
159
166
@@ -865,41 +872,117 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
865
872
return 1 ;
866
873
}
867
874
868
- static int materializeCachedJob (std::string CacheKey, CXCASDatabases DBs) {
869
- struct CompResult {
870
- CXCASCachedCompilation Comp = nullptr ;
871
- CXError Err = nullptr ;
875
+ static int uploadCachedJob (std::string CacheKey, CXCASDatabases DBs) {
876
+ CXError Err = nullptr ;
877
+ CXCASCachedCompilation CComp = clang_experimental_cas_getCachedCompilation (
878
+ DBs, CacheKey.c_str (), /* Globally*/ false , &Err);
879
+ auto CleanupCachedComp = llvm::make_scope_exit (
880
+ [&] { clang_experimental_cas_CachedCompilation_dispose (CComp); });
881
+ if (!CComp) {
882
+ if (Err) {
883
+ llvm::errs () << clang_Error_getDescription (Err) << " \n " ;
884
+ clang_Error_dispose (Err);
885
+ } else {
886
+ llvm::errs () << " cache key was not found\n " ;
887
+ }
888
+ return 1 ;
889
+ }
890
+
891
+ // / \returns true of an error occurred.
892
+ auto invokeMakeGlobal = [&](bool Cancel) -> bool {
893
+ CXCASCancellationToken CancelToken = nullptr ;
894
+ auto CleanupCancelTok = llvm::make_scope_exit ([&] {
895
+ if (Cancel)
896
+ clang_experimental_cas_CancellationToken_dispose (CancelToken);
897
+ });
898
+
899
+ std::promise<CXError> CallPromise;
900
+ clang_experimental_cas_CachedCompilation_makeGlobal (
901
+ CComp, &CallPromise,
902
+ [](void *Ctx, CXError Err) {
903
+ static_cast <std::promise<CXError> *>(Ctx)->set_value (Err);
904
+ },
905
+ Cancel ? &CancelToken : nullptr );
906
+ if (Cancel) {
907
+ clang_experimental_cas_CancellationToken_cancel (CancelToken);
908
+ }
909
+ CXError CallRes = CallPromise.get_future ().get ();
910
+ if (CallRes) {
911
+ llvm::errs () << clang_Error_getDescription (CallRes) << " \n " ;
912
+ return true ;
913
+ }
914
+ return false ;
872
915
};
873
- std::promise<CompResult> CompPromise;
874
- auto CompFuture = CompPromise.get_future ();
875
- struct CompCall {
876
- std::promise<CompResult> Promise;
916
+
917
+ if (options::TestCASCancellation) {
918
+ // Cancel an invocation for testing purposes.
919
+ if (invokeMakeGlobal (/* Cancel=*/ true ))
920
+ return 1 ;
921
+ }
922
+ if (invokeMakeGlobal (/* Cancel=*/ false ))
923
+ return 1 ;
924
+
925
+ return 0 ;
926
+ }
927
+
928
+ static int materializeCachedJob (std::string CacheKey, CXCASDatabases DBs) {
929
+ // / \returns true of an error occurred.
930
+ auto invokeGetCachedCompilation =
931
+ [&](bool Cancel, CXCASCachedCompilation &OutComp) -> bool {
932
+ OutComp = nullptr ;
933
+ CXCASCancellationToken CancelToken = nullptr ;
934
+ auto CleanupCancelTok = llvm::make_scope_exit ([&] {
935
+ if (Cancel)
936
+ clang_experimental_cas_CancellationToken_dispose (CancelToken);
937
+ });
938
+
939
+ struct CompResult {
940
+ CXCASCachedCompilation Comp = nullptr ;
941
+ CXError Err = nullptr ;
942
+ };
943
+ std::promise<CompResult> CompPromise;
944
+ auto CompFuture = CompPromise.get_future ();
945
+ struct CompCall {
946
+ std::promise<CompResult> Promise;
947
+ };
948
+ CompCall *CallCtx = new CompCall{std::move (CompPromise)};
949
+ clang_experimental_cas_getCachedCompilation_async (
950
+ DBs, CacheKey.c_str (), /* Globally*/ true , CallCtx,
951
+ [](void *Ctx, CXCASCachedCompilation Comp, CXError Err) {
952
+ std::unique_ptr<CompCall> CallCtx (static_cast <CompCall *>(Ctx));
953
+ CallCtx->Promise .set_value (CompResult{Comp, Err});
954
+ },
955
+ Cancel ? &CancelToken : nullptr );
956
+ if (Cancel) {
957
+ clang_experimental_cas_CancellationToken_cancel (CancelToken);
958
+ }
959
+ CompResult Res = CompFuture.get ();
960
+ OutComp = Res.Comp ;
961
+ if (!OutComp && !Cancel) {
962
+ if (Res.Err ) {
963
+ llvm::errs () << clang_Error_getDescription (Res.Err ) << " \n " ;
964
+ clang_Error_dispose (Res.Err );
965
+ } else {
966
+ llvm::errs () << " cache key was not found\n " ;
967
+ }
968
+ return true ;
969
+ }
970
+ return false ;
877
971
};
878
- CompCall *CallCtx = new CompCall{std::move (CompPromise)};
879
- clang_experimental_cas_getCachedCompilation_async (
880
- DBs, CacheKey.c_str (), /* Globally*/ true , CallCtx,
881
- [](void *Ctx, CXCASCachedCompilation Comp, CXError Err) {
882
- std::unique_ptr<CompCall> CallCtx (static_cast <CompCall *>(Ctx));
883
- CallCtx->Promise .set_value (CompResult{Comp, Err});
884
- },
885
- /* cancelToken*/ nullptr );
886
- CompResult Res = CompFuture.get ();
887
- CXCASCachedCompilation CComp = Res.Comp ;
888
972
973
+ CXCASCachedCompilation CComp = nullptr ;
889
974
auto CleanupCachedComp = llvm::make_scope_exit ([&] {
890
975
if (CComp)
891
976
clang_experimental_cas_CachedCompilation_dispose (CComp);
892
- if (Res.Err )
893
- clang_Error_dispose (Res.Err );
894
977
});
895
- if (!CComp) {
896
- if (Res.Err ) {
897
- llvm::errs () << clang_Error_getDescription (Res.Err ) << " \n " ;
898
- } else {
899
- llvm::errs () << " cache key was not found\n " ;
900
- }
901
- return 1 ;
978
+
979
+ if (options::TestCASCancellation) {
980
+ // Cancel an invocation for testing purposes.
981
+ if (invokeGetCachedCompilation (/* Cancel=*/ true , CComp))
982
+ return 1 ;
902
983
}
984
+ if (invokeGetCachedCompilation (/* Cancel=*/ false , CComp))
985
+ return 1 ;
903
986
904
987
for (unsigned
905
988
I = 0 ,
@@ -912,42 +995,63 @@ static int materializeCachedJob(std::string CacheKey, CXCASDatabases DBs) {
912
995
auto CleanupOutputID =
913
996
llvm::make_scope_exit ([&] { clang_disposeString (OutputID); });
914
997
915
- struct LoadResult {
916
- CXCASObject Obj = nullptr ;
917
- CXError Err = nullptr ;
918
- };
919
- std::promise<LoadResult> LoadPromise;
920
- auto LoadFuture = LoadPromise.get_future ();
921
- struct LoadCall {
922
- std::promise<LoadResult> Promise;
923
- };
924
- LoadCall *CallCtx = new LoadCall{std::move (LoadPromise)};
925
- clang_experimental_cas_loadObjectByString_async (
926
- DBs, clang_getCString (OutputID), CallCtx,
927
- [](void *Ctx, CXCASObject Obj, CXError Err) {
928
- std::unique_ptr<LoadCall> CallCtx (static_cast <LoadCall *>(Ctx));
929
- CallCtx->Promise .set_value (LoadResult{Obj, Err});
930
- },
931
- /* cancelToken*/ nullptr );
998
+ // / \returns true of an error occurred.
999
+ auto invokeLoadObject = [&](bool Cancel, CXCASObject &OutObj) -> bool {
1000
+ OutObj = nullptr ;
1001
+ CXCASCancellationToken CancelToken = nullptr ;
1002
+ auto CleanupCancelTok = llvm::make_scope_exit ([&] {
1003
+ if (Cancel)
1004
+ clang_experimental_cas_CancellationToken_dispose (CancelToken);
1005
+ });
932
1006
933
- LoadResult Res = LoadFuture.get ();
934
- CXCASObject CASObj = Res.Obj ;
1007
+ struct LoadResult {
1008
+ CXCASObject Obj = nullptr ;
1009
+ CXError Err = nullptr ;
1010
+ };
1011
+ std::promise<LoadResult> LoadPromise;
1012
+ auto LoadFuture = LoadPromise.get_future ();
1013
+ struct LoadCall {
1014
+ std::promise<LoadResult> Promise;
1015
+ };
1016
+ LoadCall *CallCtx = new LoadCall{std::move (LoadPromise)};
1017
+ clang_experimental_cas_loadObjectByString_async (
1018
+ DBs, clang_getCString (OutputID), CallCtx,
1019
+ [](void *Ctx, CXCASObject Obj, CXError Err) {
1020
+ std::unique_ptr<LoadCall> CallCtx (static_cast <LoadCall *>(Ctx));
1021
+ CallCtx->Promise .set_value (LoadResult{Obj, Err});
1022
+ },
1023
+ Cancel ? &CancelToken : nullptr );
1024
+ if (Cancel) {
1025
+ clang_experimental_cas_CancellationToken_cancel (CancelToken);
1026
+ }
1027
+ LoadResult Res = LoadFuture.get ();
1028
+ OutObj = Res.Obj ;
1029
+ if (!OutObj && !Cancel) {
1030
+ if (Res.Err ) {
1031
+ llvm::errs () << clang_Error_getDescription (Res.Err ) << " \n " ;
1032
+ clang_Error_dispose (Res.Err );
1033
+ } else {
1034
+ llvm::errs () << " cache key was not found\n " ;
1035
+ }
1036
+ return true ;
1037
+ }
1038
+ return false ;
1039
+ };
935
1040
1041
+ CXCASObject CASObj = nullptr ;
936
1042
auto CleanupLoadObj = llvm::make_scope_exit ([&] {
937
1043
if (CASObj)
938
1044
clang_experimental_cas_CASObject_dispose (CASObj);
939
- if (Res.Err )
940
- clang_Error_dispose (Res.Err );
941
1045
});
942
1046
943
- if (!CASObj) {
944
- if (Res.Err ) {
945
- llvm::errs () << clang_Error_getDescription (Res.Err ) << " \n " ;
946
- } else {
947
- llvm::errs () << " compilation output ID was not found\n " ;
948
- }
949
- return 1 ;
1047
+ if (options::TestCASCancellation) {
1048
+ // Cancel an invocation for testing purposes.
1049
+ if (invokeLoadObject (/* Cancel=*/ true , CASObj))
1050
+ return 1 ;
950
1051
}
1052
+ if (invokeLoadObject (/* Cancel=*/ false , CASObj))
1053
+ return 1 ;
1054
+
951
1055
if (!clang_experimental_cas_CachedCompilation_isOutputMaterialized (CComp,
952
1056
I))
953
1057
report_fatal_error (" output was not materialized?" );
@@ -1393,6 +1497,18 @@ int indextest_core_main(int argc, const char **argv) {
1393
1497
options::OutputDir, DBs, options::ModuleName);
1394
1498
}
1395
1499
1500
+ if (options::Action == ActionType::UploadCachedJob) {
1501
+ if (options::InputFiles.empty ()) {
1502
+ errs () << " error: missing cache key\n " ;
1503
+ return 1 ;
1504
+ }
1505
+ if (!DBs) {
1506
+ errs () << " error: CAS was not configured\n " ;
1507
+ return 1 ;
1508
+ }
1509
+ return uploadCachedJob (options::InputFiles[0 ], DBs);
1510
+ }
1511
+
1396
1512
if (options::Action == ActionType::MaterializeCachedJob) {
1397
1513
if (options::InputFiles.empty ()) {
1398
1514
errs () << " error: missing cache key\n " ;
0 commit comments