@@ -51,6 +51,10 @@ DEFINE_string(
5151 dump,
5252 " " ,
5353 " PATH where generated facts will be dumped instead of sending them to the Glean write server. You MUST specify --dump." );
54+ DEFINE_int32 (
55+ dump_every,
56+ 0 ,
57+ " If set, the facts will be dumped to <dump>.i after indexing N files" );
5458DEFINE_string (
5559 ownership_dump,
5660 " " ,
@@ -262,7 +266,10 @@ struct Config {
262266 if (!FLAGS_dump.empty ()) {
263267 // logging is historical, we always dump to a file now
264268 should_log = false ;
265- sender = fileWriter (FLAGS_dump);
269+ sender = fileWriter (
270+ FLAGS_dump_every != 0
271+ ? fmt::format (" {}.0" , FLAGS_dump)
272+ : FLAGS_dump);
266273 } else if (!FLAGS_print_sources_count) {
267274 fail (" missing --dump" );
268275 }
@@ -386,11 +393,13 @@ class CDB {
386393
387394struct SourceIndexer {
388395 const Config& config;
389- Batch<SCHEMA > batch;
396+ std::unique_ptr< Batch<SCHEMA > > batch;
390397 CDB cdb;
391398
392399 explicit SourceIndexer (Config& cfg)
393- : config(cfg), batch(cfg.schema.get(), FLAGS_fact_cache) {
400+ : config(cfg),
401+ batch(std::make_unique<Batch<SCHEMA >>(
402+ cfg.schema.get(), FLAGS_fact_cache)) {
394403 blank_cell_name = (!FLAGS_blank_cell_name.empty ())
395404 ? folly::Optional<std::string>(FLAGS_blank_cell_name)
396405 : folly::none;
@@ -400,7 +409,7 @@ struct SourceIndexer {
400409 if (FLAGS_ownership) {
401410 // source file paths will be absolute (see loadCompilationDatabase()) but
402411 // we need the unit path to be relative.
403- batch. beginUnit (
412+ batch-> beginUnit (
404413 std::filesystem::path (source.file )
405414 .lexically_relative (config.root )
406415 .string ());
@@ -415,7 +424,7 @@ struct SourceIndexer {
415424 config.root ,
416425 config.target_subdir ,
417426 config.path_prefix ,
418- batch,
427+ * batch,
419428 },
420429 config.diagnostics .get ()};
421430 FrontendActionFactory factory (&cfg);
@@ -465,11 +474,17 @@ struct SourceIndexer {
465474 });
466475 auto ok = tool.run (&factory) == 0 ;
467476 if (FLAGS_ownership) {
468- batch. endUnit ();
477+ batch-> endUnit ();
469478 }
470479 return ok;
471480 }
472481
482+ void flush () {
483+ config.sender ->flush (batch->base ());
484+ batch = std::make_unique<Batch<SCHEMA >>(
485+ config.schema .get (), FLAGS_fact_cache);
486+ }
487+
473488 private:
474489 folly::Optional<std::string> blank_cell_name;
475490
@@ -510,15 +525,15 @@ struct SourceIndexer {
510525
511526 return {
512527 repo_cell,
513- batch. fact <Buck::Locator>(
528+ batch-> fact <Buck::Locator>(
514529 maybe (cell),
515530 source.target .substr (path_start, path_len),
516531 source.target .substr (name_start))};
517532 }
518533
519534 folly::Optional<Fact<Buck::Platform>> platformOf (const SourceFile& file) {
520535 if (file.platform ) {
521- return batch. fact <Buck::Platform>(file.platform .value ());
536+ return batch-> fact <Buck::Platform>(file.platform .value ());
522537 } else {
523538 return folly::none;
524539 }
@@ -690,15 +705,15 @@ int main(int argc, char** argv) {
690705 << " ] " << config.sources [i].file ;
691706 if (FLAGS_fact_stats) {
692707 LOG_CFG (INFO , config)
693- << " fact buffer: " << showStats (indexer.batch . bufferStats ())
694- << " cache: " << showStats (indexer.batch . cacheStats ().facts )
708+ << " fact buffer: " << showStats (indexer.batch -> bufferStats ())
709+ << " cache: " << showStats (indexer.batch -> cacheStats ().facts )
695710 << " lifetime: " << showStats (lifetime_stats);
696711 }
697712 }
698713
699714 const auto & source = config.sources [i];
700- const auto buf_stats = indexer.batch . bufferStats ();
701- const auto cache_stats = indexer.batch . cacheStats ();
715+ const auto buf_stats = indexer.batch -> bufferStats ();
716+ const auto cache_stats = indexer.batch -> cacheStats ();
702717 try {
703718 bool ok = config.logger (" clang/index" )
704719 .log_index (source, buf_stats, cache_stats, [&]() {
@@ -732,7 +747,7 @@ int main(int argc, char** argv) {
732747 << " fact buffer size " << buf_stats.memory << " , waiting" ;
733748 }
734749 config.logger (wait ? " clang/wait" : " clang/send" ).log ([&]() {
735- config.sender ->rebaseAndSend (indexer.batch . base (), wait);
750+ config.sender ->rebaseAndSend (indexer.batch -> base (), wait);
736751 });
737752 if (wait) {
738753 const auto wait_time = std::chrono::steady_clock::now () - start;
@@ -742,7 +757,7 @@ int main(int argc, char** argv) {
742757 .count ();
743758 }
744759 }
745- prev_stats = indexer.batch . bufferStats ();
760+ prev_stats = indexer.batch -> bufferStats ();
746761 ++lifetime_files;
747762
748763 memory_exit = FLAGS_max_rss != 0 && (rss = getSelfRSS ()) > FLAGS_max_rss;
@@ -758,24 +773,30 @@ int main(int argc, char** argv) {
758773 // because that will skip the next target for no good reason
759774 break ;
760775 }
776+
777+ if (FLAGS_dump_every != 0 && lifetime_files % FLAGS_dump_every == 0 ) {
778+ indexer.flush ();
779+ config.sender = fileWriter (
780+ fmt::format (" {}.{}" , FLAGS_dump, lifetime_files / FLAGS_dump_every));
781+ }
761782 }
762783
763784 if (!FLAGS_dry_run) {
764785 LOG_CFG (INFO , config) << " flushing" ;
765786 config.logger (" clang/flush" ).log ([&]() {
766- config. sender -> flush (indexer. batch . base () );
787+ indexer. flush ();
767788 });
768789 }
769790
770- indexer.batch . logEnd ();
791+ indexer.batch -> logEnd ();
771792
772793 // Write ownership data to JSON file if dump path is specified
773794 // This honors the output_ownership_files flag which controls whether
774795 // the --ownership_dump parameter is passed to the indexer
775796 if (!FLAGS_ownership_dump.empty ()) {
776797 LOG_CFG (INFO , config) << " Writing ownership data to "
777798 << FLAGS_ownership_dump;
778- auto ownership_data = indexer.batch . base ().serializeOwnership ();
799+ auto ownership_data = indexer.batch -> base ().serializeOwnership ();
779800
780801 folly::dynamic ownership_json = folly::dynamic::object;
781802 for (const auto & [unit_name, fact_id_ranges] : ownership_data) {
0 commit comments