1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "host/commands/cvd/server_command/host_tool_target_manager.h"
18
19 #include "common/libs/utils/contains.h"
20 #include "common/libs/utils/files.h"
21 #include "host/commands/cvd/common_utils.h"
22
23 namespace cuttlefish {
24
25 class HostToolTargetManagerImpl : public HostToolTargetManager {
26 public:
27 INJECT(HostToolTargetManagerImpl(const OperationToBinsMap&));
28
29 Result<FlagInfo> ReadFlag(const HostToolFlagRequestForm& request) override;
30 Result<std::string> ExecBaseName(
31 const HostToolExecNameRequestForm& request) override;
32
33 private:
34 Result<void> EnsureExistence(const std::string& artifacts_path);
35 Result<void> UpdateOutdated(const std::string& artifacts_path);
36
37 using HostToolTargetMap = std::unordered_map<std::string, HostToolTarget>;
38
39 // map from artifact dir to host tool target information object
40 HostToolTargetMap host_target_table_;
41 // predefined mapping from an operation to potential executable binary names
42 // e.g. "start" -> {"cvd_internal_start", "launch_cvd"}
43 const OperationToBinsMap& op_to_possible_bins_map_;
44 std::mutex table_mutex_;
45 };
46
HostToolTargetManagerImpl(const OperationToBinsMap & op_to_bins_map)47 HostToolTargetManagerImpl::HostToolTargetManagerImpl(
48 const OperationToBinsMap& op_to_bins_map)
49 : op_to_possible_bins_map_{op_to_bins_map} {}
50
51 // use this only after acquiring the table_mutex_
EnsureExistence(const std::string & artifacts_path)52 Result<void> HostToolTargetManagerImpl::EnsureExistence(
53 const std::string& artifacts_path) {
54 if (!Contains(host_target_table_, artifacts_path)) {
55 HostToolTarget new_host_tool_target = CF_EXPECT(
56 HostToolTarget::Create(artifacts_path, op_to_possible_bins_map_));
57 host_target_table_.emplace(artifacts_path, std::move(new_host_tool_target));
58 }
59 return {};
60 }
61
UpdateOutdated(const std::string & artifacts_path)62 Result<void> HostToolTargetManagerImpl::UpdateOutdated(
63 const std::string& artifacts_path) {
64 CF_EXPECT(Contains(host_target_table_, artifacts_path));
65 auto& host_target = host_target_table_.at(artifacts_path);
66 if (!host_target.IsDirty()) {
67 return {};
68 }
69 LOG(ERROR) << artifacts_path << " is new, so updating HostToolTarget";
70 HostToolTarget new_host_tool_target = CF_EXPECT(
71 HostToolTarget::Create(artifacts_path, op_to_possible_bins_map_));
72 host_target_table_.emplace(artifacts_path, std::move(new_host_tool_target));
73 return {};
74 }
75
ReadFlag(const HostToolFlagRequestForm & request)76 Result<FlagInfo> HostToolTargetManagerImpl::ReadFlag(
77 const HostToolFlagRequestForm& request) {
78 std::lock_guard<std::mutex> lock(table_mutex_);
79 CF_EXPECT(
80 EnsureExistence(request.artifacts_path),
81 "Could not create HostToolTarget object for " << request.artifacts_path);
82 CF_EXPECT(UpdateOutdated(request.artifacts_path));
83 auto& host_target = host_target_table_.at(request.artifacts_path);
84 auto flag_info =
85 CF_EXPECT(host_target.GetFlagInfo(HostToolTarget::FlagInfoRequest{
86 .operation_ = request.op,
87 .flag_name_ = request.flag_name,
88 }));
89 return flag_info;
90 }
91
ExecBaseName(const HostToolExecNameRequestForm & request)92 Result<std::string> HostToolTargetManagerImpl::ExecBaseName(
93 const HostToolExecNameRequestForm& request) {
94 std::lock_guard<std::mutex> lock(table_mutex_);
95 CF_EXPECT(
96 EnsureExistence(request.artifacts_path),
97 "Could not create HostToolTarget object for " << request.artifacts_path);
98 auto& host_target = host_target_table_.at(request.artifacts_path);
99 auto base_name = CF_EXPECT(host_target.GetBinName(request.op));
100 return base_name;
101 }
102
103 fruit::Component<fruit::Required<OperationToBinsMap>, HostToolTargetManager>
HostToolTargetManagerComponent()104 HostToolTargetManagerComponent() {
105 return fruit::createComponent()
106 .bind<HostToolTargetManager, HostToolTargetManagerImpl>();
107 }
108
109 } // namespace cuttlefish
110