3030#include " schema/custom_generator_serialization.h"
3131#include " schema/path.h"
3232
33+ #include " custom_generator/custom_blob_handler.h"
34+ #include " custom_generator/custom_generator_context.h"
35+
3336#include " target/common/target_env.h"
3437
3538namespace buildcc {
3639
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+ }
7252 };
7353
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>;
9655 std::unordered_map<IdKey, UserIdInfo> ids;
9756
9857void ConvertToInternal () {
@@ -110,7 +69,8 @@ class CustomGenerator : public internal::BuilderInterface {
11069CustomGenerator (const std::string &name,const TargetEnv &env)
11170 : name_(name),
11271env_ (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_) {
11474Initialize ();
11575 }
11676virtual ~CustomGenerator () =default ;
@@ -137,33 +97,12 @@ class CustomGenerator : public internal::BuilderInterface {
13797 * @param generate_cb User-defined generate callback to build outputs from the
13898 * provided inputs
13999*/
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 );
167106
168107void Build ()override ;
169108
@@ -176,19 +115,100 @@ class CustomGenerator : public internal::BuilderInterface {
176115const fs::path &GetBuildDir ()const {return env_.GetTargetBuildDir (); }
177116const std::string &Get (const std::string &file_identifier)const ;
178117
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+
179204private:
180205void Initialize ();
181206
182- void TaskRunner (bool run,const std::string &id);
183- tf::TaskCreateTaskRunner (tf::Subflow &subflow,bool build,
184- const std::string &id);
207+ tf::TaskCreateTaskRunner (tf::Subflow &subflow,const std::string &id);
208+ void TaskRunner (const std::string &id);
185209
186210void 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 ();
192212
193213// Recheck states
194214void IdRemoved ();
@@ -199,47 +219,23 @@ class CustomGenerator : public internal::BuilderInterface {
199219const env::Command &ConstCommand ()const {return command_; }
200220 env::Command &RefCommand () {return command_; }
201221
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-
225222private:
226223 std::string name_;
227224 TargetEnv env_;
228225 internal::CustomGeneratorSerialization serialization_;
229226
230227// Serialization
231228 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_;
234232
235233 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_;
237236
238237// Internal
239238 env::Command command_;
240-
241- // Callbacks
242- DependencyCb dependency_cb_;
243239};
244240
245241}// namespace buildcc