30
30
#include " schema/custom_generator_serialization.h"
31
31
#include " schema/path.h"
32
32
33
+ #include " custom_generator/custom_blob_handler.h"
34
+ #include " custom_generator/custom_generator_context.h"
35
+
33
36
#include " target/common/target_env.h"
34
37
35
38
namespace buildcc {
36
39
37
- // TODO, Shift to a different file
38
- // TODO, Check if we need the "id" here as well
39
- class CustomGeneratorContext {
40
- public:
41
- CustomGeneratorContext (const env::Command &c, const fs_unordered_set &i,
42
- const fs_unordered_set &o,
43
- const std::vector<uint8_t > &ub)
44
- : command(c), inputs(i), outputs(o), userblob(ub) {}
45
-
46
- const env::Command &command;
47
- const fs_unordered_set &inputs;
48
- const fs_unordered_set &outputs;
49
- const std::vector<uint8_t > &userblob;
50
- };
51
-
52
- // clang-format off
53
- using GenerateCb = std::function<bool (CustomGeneratorContext &)>;
54
-
55
- using DependencyCb = std::function<void (std::unordered_map<std::string, tf::Task> &&)>;
56
- // clang-format on
57
-
58
- class CustomBlobHandler {
59
- public:
60
- CustomBlobHandler () = default ;
61
- virtual ~CustomBlobHandler () = default ;
62
-
63
- bool CheckChanged (const std::vector<uint8_t > &previous,
64
- const std::vector<uint8_t > ¤t) const {
65
- env::assert_fatal (
66
- Verify (previous),
67
- " Stored blob is corrupted or User verification is incorrect" );
68
- env::assert_fatal (
69
- Verify (current),
70
- " Current blob is corrupted or User verification is incorrect" );
71
- return !IsEqual (previous, current);
40
+ struct UserCustomGeneratorSchema : public internal ::CustomGeneratorSchema {
41
+ struct UserIdInfo : internal::CustomGeneratorSchema::IdInfo {
42
+ fs_unordered_set inputs; // TODO, Remove
43
+ GenerateCb generate_cb;
44
+ std::shared_ptr<CustomBlobHandler> blob_handler{nullptr };
45
+
46
+ void ConvertToInternal () {
47
+ internal_inputs = internal::path_schema_convert (
48
+ inputs, internal::Path::CreateExistingPath);
49
+ userblob = blob_handler != nullptr ? blob_handler->GetSerializedData ()
50
+ : std::vector<uint8_t >();
51
+ }
72
52
};
73
53
74
- std::vector<uint8_t > GetSerializedData () const {
75
- auto serialized_data = Serialize ();
76
- env::assert_fatal (
77
- Verify (serialized_data),
78
- " Serialized data is corrupted or Serialize function is incorrect" );
79
- return serialized_data;
80
- }
81
-
82
- private:
83
- virtual bool Verify (const std::vector<uint8_t > &serialized_data) const = 0;
84
- virtual bool IsEqual (const std::vector<uint8_t > &previous,
85
- const std::vector<uint8_t > ¤t) const = 0;
86
- virtual std::vector<uint8_t > Serialize () const = 0;
87
- };
88
-
89
- struct UserIdInfo : internal::CustomGeneratorSchema::IdInfo {
90
- fs_unordered_set inputs;
91
- GenerateCb generate_cb;
92
- std::shared_ptr<CustomBlobHandler> blob_handler{nullptr };
93
- };
94
-
95
- struct UserCustomGeneratorSchema : public internal ::CustomGeneratorSchema {
54
+ using UserIdPair = std::pair<const IdKey, UserIdInfo>;
96
55
std::unordered_map<IdKey, UserIdInfo> ids;
97
56
98
57
void ConvertToInternal () {
@@ -110,7 +69,8 @@ class CustomGenerator : public internal::BuilderInterface {
110
69
CustomGenerator (const std::string &name, const TargetEnv &env)
111
70
: name_(name),
112
71
env_ (env.GetTargetRootDir(), env.GetTargetBuildDir() / name),
113
- serialization_(env_.GetTargetBuildDir() / fmt::format(" {}.bin" , name)) {
72
+ serialization_(env_.GetTargetBuildDir() / fmt::format(" {}.json" , name)),
73
+ comparator_(serialization_.GetLoad(), user_) {
114
74
Initialize ();
115
75
}
116
76
virtual ~CustomGenerator () = default ;
@@ -137,33 +97,12 @@ class CustomGenerator : public internal::BuilderInterface {
137
97
* @param generate_cb User-defined generate callback to build outputs from the
138
98
* provided inputs
139
99
*/
140
- void AddIdInfo (const std::string &id,
141
- const std::unordered_set<std::string> &inputs,
142
- const std::unordered_set<std::string> &outputs,
143
- const GenerateCb &generate_cb,
144
- std::shared_ptr<CustomBlobHandler> blob_handler = nullptr );
145
-
146
- // TODO, Doc
147
- void AddGroupInfo (const std::string &group_id,
148
- std::initializer_list<std::string> ids,
149
- const DependencyCb &dependency_cb = DependencyCb());
150
-
151
- // Callbacks
152
- /* *
153
- * @brief Setup dependencies between Tasks using their `id`
154
- * For example: `task_map["id1"].precede(task_map["id2"])`
155
- *
156
- * IMPORTANT: Successor tasks will not automatically run if dependent task is
157
- * run.
158
- * The Dependency callback only sets precedence (order in which your tasks
159
- * should run)
160
- * Default behaviour when dependency callback is not supplied: All task `id`s
161
- * run in parallel.
162
- *
163
- * @param dependency_cb Unordered map of `id` and `task`
164
- * The map can be safely mutated.
165
- */
166
- void AddDependencyCb (const DependencyCb &dependency_cb);
100
+ void
101
+ AddIdInfo (const std::string &id,
102
+ const std::unordered_set<std::string> &inputs,
103
+ const std::unordered_set<std::string> &outputs,
104
+ const GenerateCb &generate_cb,
105
+ const std::shared_ptr<CustomBlobHandler> &blob_handler = nullptr );
167
106
168
107
void Build () override ;
169
108
@@ -176,19 +115,100 @@ class CustomGenerator : public internal::BuilderInterface {
176
115
const fs::path &GetBuildDir () const { return env_.GetTargetBuildDir (); }
177
116
const std::string &Get (const std::string &file_identifier) const ;
178
117
118
+ private:
119
+ struct Comparator {
120
+ Comparator (const internal::CustomGeneratorSchema &loaded,
121
+ const UserCustomGeneratorSchema &us)
122
+ : loaded_schema_(loaded), current_schema_(us) {}
123
+
124
+ enum class State {
125
+ kRemoved ,
126
+ kAdded ,
127
+ kCheckLater ,
128
+ };
129
+
130
+ void AddAllIds () {
131
+ const auto &curr_ids = current_schema_.ids ;
132
+ for (const auto &[id, _] : curr_ids) {
133
+ id_state_info_.at (State::kAdded ).insert (id);
134
+ }
135
+ }
136
+
137
+ void CompareIds () {
138
+ const auto &prev_ids = loaded_schema_.internal_ids ;
139
+ const auto &curr_ids = current_schema_.ids ;
140
+
141
+ for (const auto &[prev_id, _] : prev_ids) {
142
+ if (curr_ids.find (prev_id) == curr_ids.end ()) {
143
+ // Id Removed condition, previous id is not present in the current run
144
+ id_state_info_.at (State::kRemoved ).insert (prev_id);
145
+ }
146
+ }
147
+
148
+ for (const auto &[curr_id, _] : curr_ids) {
149
+ if (prev_ids.find (curr_id) == prev_ids.end ()) {
150
+ // Id Added condition
151
+ id_state_info_.at (State::kAdded ).insert (curr_id);
152
+ } else {
153
+ // Id Check Later condition
154
+ id_state_info_.at (State::kCheckLater ).insert (curr_id);
155
+ }
156
+ }
157
+ }
158
+
159
+ bool IsChanged (const std::string &id) const {
160
+ const auto &previous_id_info = loaded_schema_.internal_ids .at (id);
161
+ const auto ¤t_id_info = current_schema_.ids .at (id);
162
+
163
+ bool changed = internal::CheckPaths (previous_id_info.internal_inputs ,
164
+ current_id_info.internal_inputs ) !=
165
+ internal::PathState::kNoChange ;
166
+ changed = changed || internal::CheckChanged (previous_id_info.outputs ,
167
+ current_id_info.outputs );
168
+ if (!changed && current_id_info.blob_handler != nullptr ) {
169
+ // We only check blob handler if not changed by inputs/outputs
170
+ // Checking blob_handler could be expensive so this optimization is made
171
+ // to run only when changed == false
172
+ changed = current_id_info.blob_handler ->CheckChanged (
173
+ previous_id_info.userblob , current_id_info.userblob );
174
+ }
175
+ return changed;
176
+ }
177
+
178
+ const std::unordered_set<std::string> &GetRemovedIds () const {
179
+ return id_state_info_.at (State::kRemoved );
180
+ }
181
+
182
+ const std::unordered_set<std::string> &GetAddedIds () const {
183
+ return id_state_info_.at (State::kAdded );
184
+ }
185
+
186
+ const std::unordered_set<std::string> &GetCheckLaterIds () const {
187
+ return id_state_info_.at (State::kCheckLater );
188
+ }
189
+
190
+ bool IsIdAdded (const std::string &id) const {
191
+ return id_state_info_.at (State::kAdded ).count (id) == 1 ;
192
+ }
193
+
194
+ private:
195
+ const internal::CustomGeneratorSchema &loaded_schema_;
196
+ const UserCustomGeneratorSchema ¤t_schema_;
197
+ std::unordered_map<State, std::unordered_set<std::string>> id_state_info_{
198
+ {State::kRemoved , std::unordered_set<std::string>()},
199
+ {State::kAdded , std::unordered_set<std::string>()},
200
+ {State::kCheckLater , std::unordered_set<std::string>()},
201
+ };
202
+ };
203
+
179
204
private:
180
205
void Initialize ();
181
206
182
- void TaskRunner (bool run, const std::string &id);
183
- tf::Task CreateTaskRunner (tf::Subflow &subflow, bool build,
184
- const std::string &id);
207
+ tf::Task CreateTaskRunner (tf::Subflow &subflow, const std::string &id);
208
+ void TaskRunner (const std::string &id);
185
209
186
210
void GenerateTask ();
187
- void BuildGenerate (std::unordered_set<std::string> &gen_selected_ids,
188
- std::unordered_set<std::string> &dummy_gen_selected_ids);
189
-
190
- void InvokeDependencyCb (std::unordered_map<std::string, tf::Task>
191
- &®istered_tasks) const noexcept ;
211
+ void BuildGenerate ();
192
212
193
213
// Recheck states
194
214
void IdRemoved ();
@@ -199,47 +219,23 @@ class CustomGenerator : public internal::BuilderInterface {
199
219
const env::Command &ConstCommand () const { return command_; }
200
220
env::Command &RefCommand () { return command_; }
201
221
202
- private:
203
- struct GroupMetadata {
204
- std::vector<std::string> ids;
205
- DependencyCb dependency_cb;
206
-
207
- void InvokeDependencyCb (const std::string &group_id,
208
- std::unordered_map<std::string, tf::Task>
209
- &®istered_tasks) const noexcept {
210
- if (!dependency_cb) {
211
- return ;
212
- }
213
- try {
214
- dependency_cb (std::move (registered_tasks));
215
- } catch (...) {
216
- env::log_critical (
217
- __FUNCTION__,
218
- fmt::format (" Dependency callback failed for group id {}" ,
219
- group_id));
220
- env::set_task_state (env::TaskState::FAILURE);
221
- }
222
- }
223
- };
224
-
225
222
private:
226
223
std::string name_;
227
224
TargetEnv env_;
228
225
internal::CustomGeneratorSerialization serialization_;
229
226
230
227
// Serialization
231
228
UserCustomGeneratorSchema user_;
232
- std::unordered_map<std::string, GroupMetadata> grouped_ids_;
233
- std::unordered_set<std::string> ungrouped_ids_;
229
+
230
+ // Comparator
231
+ Comparator comparator_;
234
232
235
233
std::mutex success_schema_mutex_;
236
- std::unordered_map<std::string, UserIdInfo> success_schema_;
234
+ std::unordered_map<std::string, UserCustomGeneratorSchema::UserIdInfo>
235
+ success_schema_;
237
236
238
237
// Internal
239
238
env::Command command_;
240
-
241
- // Callbacks
242
- DependencyCb dependency_cb_;
243
239
};
244
240
245
241
} // namespace buildcc
0 commit comments