1 /*
2 * Copyright (C) 2022 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/selector/instance_group_record.h"
18
19 #include "host/commands/cvd/selector/instance_database_utils.h"
20 #include "host/commands/cvd/selector/selector_constants.h"
21
22 namespace cuttlefish {
23 namespace selector {
24
LocalInstanceGroup(const InstanceGroupParam & param)25 LocalInstanceGroup::LocalInstanceGroup(const InstanceGroupParam& param)
26 : home_dir_{param.home_dir},
27 host_artifacts_path_{param.host_artifacts_path},
28 product_out_path_{param.product_out_path},
29 internal_group_name_(GenInternalGroupName()),
30 group_name_(param.group_name) {}
31
LocalInstanceGroup(const LocalInstanceGroup & src)32 LocalInstanceGroup::LocalInstanceGroup(const LocalInstanceGroup& src)
33 : home_dir_{src.home_dir_},
34 host_artifacts_path_{src.host_artifacts_path_},
35 product_out_path_{src.product_out_path_},
36 internal_group_name_{src.internal_group_name_},
37 group_name_{src.group_name_},
38 build_id_{src.build_id_},
39 instances_{CopyInstances(src.instances_)} {}
40
operator =(const LocalInstanceGroup & src)41 LocalInstanceGroup& LocalInstanceGroup::operator=(
42 const LocalInstanceGroup& src) {
43 if (this == std::addressof(src)) {
44 return *this;
45 }
46 home_dir_ = src.home_dir_;
47 host_artifacts_path_ = src.host_artifacts_path_;
48 product_out_path_ = src.product_out_path_;
49 internal_group_name_ = src.internal_group_name_;
50 group_name_ = src.group_name_;
51 build_id_ = src.build_id_;
52 instances_ = CopyInstances(src.instances_);
53 return *this;
54 }
55
CopyInstances(const Set<std::unique_ptr<LocalInstance>> & src_instances)56 Set<std::unique_ptr<LocalInstance>> LocalInstanceGroup::CopyInstances(
57 const Set<std::unique_ptr<LocalInstance>>& src_instances) {
58 Set<std::unique_ptr<LocalInstance>> copied;
59 // Due to the const reference to the parent, LocalInstanceGroup,
60 // the LocalInstance class does not have a copy constructor
61 for (const auto& src_instance : src_instances) {
62 LocalInstance* new_instance = new LocalInstance(
63 *this, src_instance->InstanceId(), src_instance->PerInstanceName());
64 copied.emplace(new_instance);
65 }
66 return copied;
67 }
68
GetCuttlefishConfigPath() const69 Result<std::string> LocalInstanceGroup::GetCuttlefishConfigPath() const {
70 return ::cuttlefish::selector::GetCuttlefishConfigPath(HomeDir());
71 }
72
AddInstance(const unsigned instance_id,const std::string & instance_name)73 Result<void> LocalInstanceGroup::AddInstance(const unsigned instance_id,
74 const std::string& instance_name) {
75 if (HasInstance(instance_id)) {
76 return CF_ERR("Instance Id " << instance_id << " is taken");
77 }
78 LocalInstance* instance =
79 new LocalInstance(*this, instance_id, instance_name);
80 instances_.emplace(std::unique_ptr<LocalInstance>(instance));
81 return {};
82 }
83
FindById(const unsigned id) const84 Result<Set<ConstRef<LocalInstance>>> LocalInstanceGroup::FindById(
85 const unsigned id) const {
86 auto subset = CollectToSet<LocalInstance>(
87 instances_, [&id](const std::unique_ptr<LocalInstance>& instance) {
88 return instance && (instance->InstanceId() == id);
89 });
90 return AtMostOne(subset,
91 GenerateTooManyInstancesErrorMsg(1, kInstanceIdField));
92 }
93
FindByInstanceName(const std::string & instance_name) const94 Result<Set<ConstRef<LocalInstance>>> LocalInstanceGroup::FindByInstanceName(
95 const std::string& instance_name) const {
96 auto subset = CollectToSet<LocalInstance>(
97 instances_,
98 [&instance_name](const std::unique_ptr<LocalInstance>& instance) {
99 return instance && (instance->PerInstanceName() == instance_name);
100 });
101
102 // note that inside a group, the instance name is unique. However,
103 // across groups, they can be multiple
104 return AtMostOne(subset,
105 GenerateTooManyInstancesErrorMsg(1, kInstanceNameField));
106 }
107
FindAllInstances() const108 Result<Set<ConstRef<LocalInstance>>> LocalInstanceGroup::FindAllInstances()
109 const {
110 auto subset = CollectToSet<LocalInstance>(
111 instances_, [](const std::unique_ptr<LocalInstance>& instance) {
112 if (instance) {
113 return true;
114 }
115 return false;
116 });
117 return subset;
118 }
119
HasInstance(const unsigned instance_id) const120 bool LocalInstanceGroup::HasInstance(const unsigned instance_id) const {
121 for (const auto& instance : instances_) {
122 if (!instance) {
123 continue;
124 }
125 if (instance_id == instance->InstanceId()) {
126 return true;
127 }
128 }
129 return false;
130 }
131
SetBuildId(const std::string & build_id)132 void LocalInstanceGroup::SetBuildId(const std::string& build_id) {
133 build_id_ = build_id;
134 }
135
Serialize() const136 Json::Value LocalInstanceGroup::Serialize() const {
137 Json::Value group_json;
138 group_json[kJsonGroupName] = group_name_;
139 group_json[kJsonHomeDir] = home_dir_;
140 group_json[kJsonHostArtifactPath] = host_artifacts_path_;
141 group_json[kJsonProductOutPath] = product_out_path_;
142 auto build_id_opt = BuildId();
143 group_json[kJsonBuildId] = build_id_opt ? *build_id_opt : kJsonUnknownBuildId;
144 int i = 0;
145 Json::Value instances_array_json;
146 for (const auto& instance : instances_) {
147 Json::Value instance_json = Serialize(instance);
148 instance_json[kJsonParent] = group_name_;
149 instances_array_json[i] = instance_json;
150 i++;
151 }
152 group_json[kJsonInstances] = instances_array_json;
153 return group_json;
154 }
155
Serialize(const std::unique_ptr<LocalInstance> & instance) const156 Json::Value LocalInstanceGroup::Serialize(
157 const std::unique_ptr<LocalInstance>& instance) const {
158 Json::Value instance_json;
159 if (!instance) {
160 return instance_json;
161 }
162 instance_json[LocalInstance::kJsonInstanceName] = instance->PerInstanceName();
163 instance_json[LocalInstance::kJsonInstanceId] =
164 std::to_string(instance->InstanceId());
165 return instance_json;
166 }
167
168 } // namespace selector
169 } // namespace cuttlefish
170