trace_processor: introduce status class to hold errors

This class allows us to fold all our inconsistencies of returning bool,
int and optional<string> into a single class.

base::Optional<string> is really counter intutive because nullopt indicates
success which is opposite to every other use of Optional. By wrapping
this class, it makes it a lot more intuitive.

This change also changes the API of trace processor to use this new API.

Change-Id: Idc882b9f89aad6c04991e6e032b89a8f1d5b5abc
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 91b132d..c71bd3b 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -182,8 +182,9 @@
     fprintf(stderr, "\n");
   }
 
-  if (base::Optional<std::string> opt_error = it.GetLastError()) {
-    PERFETTO_ELOG("Error while iterating stats %s", opt_error->c_str());
+  util::Status status = it.Status();
+  if (!status.ok()) {
+    PERFETTO_ELOG("Error while iterating stats %s", status.c_message());
     return false;
   }
   return true;
@@ -206,8 +207,10 @@
   auto attach_it = g_tp->ExecuteQuery(attach_sql);
   bool attach_has_more = attach_it.Next();
   PERFETTO_DCHECK(!attach_has_more);
-  if (base::Optional<std::string> opt_error = attach_it.GetLastError()) {
-    PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
+
+  util::Status status = attach_it.Status();
+  if (!status.ok()) {
+    PERFETTO_ELOG("SQLite error: %s", status.c_message());
     return 1;
   }
 
@@ -223,21 +226,25 @@
     auto export_it = g_tp->ExecuteQuery(export_sql);
     bool export_has_more = export_it.Next();
     PERFETTO_DCHECK(!export_has_more);
-    if (base::Optional<std::string> opt_error = export_it.GetLastError()) {
-      PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
+
+    status = export_it.Status();
+    if (!status.ok()) {
+      PERFETTO_ELOG("SQLite error: %s", status.c_message());
       return 1;
     }
   }
-  if (base::Optional<std::string> opt_error = tables_it.GetLastError()) {
-    PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
+  status = tables_it.Status();
+  if (!status.ok()) {
+    PERFETTO_ELOG("SQLite error: %s", status.c_message());
     return 1;
   }
 
   auto detach_it = g_tp->ExecuteQuery("DETACH DATABASE perfetto_export");
   bool detach_has_more = attach_it.Next();
   PERFETTO_DCHECK(!detach_has_more);
-  if (base::Optional<std::string> opt_error = detach_it.GetLastError()) {
-    PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
+  status = detach_it.Status();
+  if (!status.ok()) {
+    PERFETTO_ELOG("SQLite error: %s", status.c_message());
     return 1;
   }
   return 0;
@@ -300,8 +307,9 @@
     printf("\n");
   }
 
-  if (base::Optional<std::string> opt_error = it->GetLastError()) {
-    PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
+  util::Status status = it->Status();
+  if (!status.ok()) {
+    PERFETTO_ELOG("SQLite error: %s", status.c_message());
   }
   printf("\nQuery executed in %.3f ms\n\n", (t_end - t_start).count() / 1E6);
 }
@@ -423,8 +431,9 @@
     PERFETTO_ILOG("Executing query: %s", sql_query.c_str());
 
     auto it = g_tp->ExecuteQuery(sql_query);
-    if (base::Optional<std::string> opt_error = it.GetLastError()) {
-      PERFETTO_ELOG("SQLite error: %s", opt_error->c_str());
+    util::Status status = it.Status();
+    if (!status.ok()) {
+      PERFETTO_ELOG("SQLite error: %s", status.c_message());
       is_query_error = true;
       break;
     }
@@ -617,9 +626,11 @@
     PERFETTO_CHECK(aio_read(&cb) == 0);
 
     // Parse the completed buffer while the async read is in-flight.
-    bool success = tp->Parse(std::move(buf), static_cast<size_t>(rsize));
-    if (PERFETTO_UNLIKELY(!success))
+    util::Status status = tp->Parse(std::move(buf), static_cast<size_t>(rsize));
+    if (PERFETTO_UNLIKELY(!status.ok())) {
+      PERFETTO_ELOG("Fatal error while parsing trace: %s", status.c_message());
       return 1;
+    }
   }
   tp->NotifyEndOfFile();