maintenance: Add --purge-package to delete rows/files by package name.

Used by the performance tests (AppLaunch.apk) to purge files for
iorap-trial runs.

Test: iorap.cmd.maintenance --package-name com.whatever.name /data/misc/iorapd/sqlite.db
Bug: 150880186
Change-Id: Ifdb0db2b0fcd66eba9e65e94b856929a882e8a75
diff --git a/src/db/clean_up.cc b/src/db/clean_up.cc
index b3eba46..49f1657 100644
--- a/src/db/clean_up.cc
+++ b/src/db/clean_up.cc
@@ -40,6 +40,7 @@
     std::string file_path = raw_trace.file_path;
     LOG(DEBUG) << "Remove file: " << file_path;
     std::filesystem::remove(file_path.c_str());
+    raw_trace.Delete();
   }
 
   // Remove compiled traces.
@@ -50,6 +51,7 @@
     std::string file_path = prefetch_file->file_path;
     LOG(DEBUG) << "Remove file: " << file_path;
     std::filesystem::remove(file_path.c_str());
+    prefetch_file->Delete();
   }
 }
 
@@ -75,4 +77,25 @@
   }
 }
 
+void CleanUpFilesForPackage(const std::string& db_path,
+                            const std::string& package_name) {
+  iorap::db::SchemaModel db_schema = db::SchemaModel::GetOrCreate(db_path);
+  db::DbHandle db{db_schema.db()};
+  CleanUpFilesForPackage(db, package_name);
+}
+
+
+void CleanUpFilesForPackage(const db::DbHandle& db,
+                            const std::string& package_name) {
+  std::vector<PackageModel> packages = PackageModel::SelectByName(db, package_name.c_str());;
+
+  for (PackageModel& package : packages) {
+    CleanUpFilesForPackage(db, package.id, package.name, package.version);
+  }
+
+  if (packages.empty()) {
+    LOG(DEBUG) << "No package rows to clean up " << package_name;
+  }
+}
+
 }  // namespace iorap::db
diff --git a/src/db/clean_up.h b/src/db/clean_up.h
index 82a26fd..93ef9c4 100644
--- a/src/db/clean_up.h
+++ b/src/db/clean_up.h
@@ -32,6 +32,14 @@
                             int package_id,
                             const std::string& package_name,
                             int64_t version);
+
+// Clean up all package rows (and files) associated with a package by name.
+void CleanUpFilesForPackage(const std::string& db_path,
+                            const std::string& package_name);
+
+// Clean up all package rows (and files) associated with a package by name.
+void CleanUpFilesForPackage(const db::DbHandle& db,
+                            const std::string& package_name);
 }  // namespace iorap::db
 
 #endif  // IORAP_SRC_DB_CLEANER_H_
diff --git a/src/db/models.h b/src/db/models.h
index 1feac47..df6beb6 100644
--- a/src/db/models.h
+++ b/src/db/models.h
@@ -585,18 +585,20 @@
     return p;
   }
 
-  static std::optional<PackageModel> SelectByName(DbHandle db, const char* name) {
+  static std::vector<PackageModel> SelectByName(DbHandle db, const char* name) {
     ScopedLockDb lock{db};
 
-    std::string query = "SELECT * FROM packages WHERE name = ?1 LIMIT 1;";
+    std::string query = "SELECT * FROM packages WHERE name = ?1;";
     DbStatement stmt = DbStatement::Prepare(db, query, name);
 
+    std::vector<PackageModel> packages;
+
     PackageModel p{db};
-    if (!DbQueryBuilder::SelectOnce(stmt, p.id, p.name, p.version)) {
-      return std::nullopt;
+    while (DbQueryBuilder::SelectOnce(stmt, p.id, p.name, p.version)) {
+      packages.push_back(p);
     }
 
-    return p;
+    return packages;
   }
 
   static std::optional<PackageModel> SelectByNameAndVersion(DbHandle db,
diff --git a/src/maintenance/main.cc b/src/maintenance/main.cc
index 18a0f1e..16b2a35 100644
--- a/src/maintenance/main.cc
+++ b/src/maintenance/main.cc
@@ -15,6 +15,7 @@
 #include "common/debug.h"
 #include "compiler/compiler.h"
 #include "maintenance/controller.h"
+#include "db/clean_up.h"
 
 #include <android-base/parseint.h>
 #include <android-base/properties.h>
@@ -39,8 +40,8 @@
   std::cerr << "    --activity $,-a $          Activity name." << std::endl;
   std::cerr << "    --inode-textcache $,-it $  Resolve inode->filename from textcache." << std::endl;
   std::cerr << "    --help,-h                  Print this Usage." << std::endl;
-  std::cerr << "    --recompile,-r             Force re-compilation, which replace the existing compiled trace ."
-            << std::endl;
+  std::cerr << "    --recompile,-r             Force re-compilation, which replace the existing compiled trace ." << std::endl;
+  std::cerr << "    --purge-package,-pp        Purge all files associated with a package." << std::endl;
   std::cerr << "    --verbose,-v               Set verbosity (default off)." << std::endl;
   std::cerr << "    --output-text,-ot          Output ascii text instead of protobuf (default off)." << std::endl;
   std::cerr << "    --min_traces,-mt           The min number of perfetto traces needed for compilation (default 1)."
@@ -60,6 +61,7 @@
 
   std::vector<std::string> arg_input_filenames;
   std::optional<std::string> arg_package;
+  std::optional<std::string> arg_purge_package;
   int arg_version = -1;
   std::optional<std::string> arg_activity;
   std::optional<std::string> arg_inode_textcache;
@@ -108,7 +110,15 @@
       }
       arg_inode_textcache = arg_next;
       ++arg;
-    } else if (argstr == "--verbose" || argstr == "-v") {
+    } else if (argstr == "--purge-package" || argstr == "-pp") {
+      if (!has_arg_next) {
+        std::cerr << "Missing --purge-package <value>" << std::endl;
+        return 1;
+      }
+      arg_purge_package = arg_next;
+      ++arg;
+    }
+    else if (argstr == "--verbose" || argstr == "-v") {
       enable_verbose = true;
     } else if (argstr == "--recompile" || argstr == "-r") {
       recompile = true;
@@ -134,7 +144,7 @@
     Usage(argv);
   }
 
-  std::string db = arg_input_filenames[0];
+  std::string db_path = arg_input_filenames[0];
 
   if (enable_verbose) {
     android::base::SetMinimumLogSeverity(android::base::VERBOSE);
@@ -145,6 +155,12 @@
     android::base::SetMinimumLogSeverity(android::base::DEBUG);
   }
 
+  if (arg_purge_package) {
+    db::CleanUpFilesForPackage(db_path, *arg_purge_package);
+    return 0;
+    // Don't do any more work because SchemaModel can only be created once.
+  }
+
   maintenance::ControllerParameters params{
     arg_output_text,
     arg_inode_textcache,
@@ -155,15 +171,15 @@
 
   int ret_code = 0;
   if (arg_package && arg_activity) {
-    ret_code = !Compile(std::move(db),
+    ret_code = !Compile(std::move(db_path),
                         std::move(*arg_package),
                         std::move(*arg_activity),
                         arg_version,
                         params);
   } else if (arg_package) {
-    ret_code = !Compile(std::move(db), std::move(*arg_package), arg_version, params);
+    ret_code = !Compile(std::move(db_path), std::move(*arg_package), arg_version, params);
   } else {
-    ret_code = !Compile(std::move(db), params);
+    ret_code = !Compile(std::move(db_path), params);
   }
   return ret_code;
 }