• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "common/cmd_utils.h"
16 #include "db/file_models.h"
17 #include "db/models.h"
18 
19 #include <android-base/file.h>
20 #include <android-base/properties.h>
21 
22 #include <algorithm>
23 #include <sstream>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <time.h>
27 #include <unistd.h>
28 
29 namespace iorap::db {
30 
31 static constexpr const char* kRootPathProp = "iorapd.root.dir";
32 static const unsigned int kPerfettoMaxTraces =
33     ::android::base::GetUintProperty("iorapd.perfetto.max_traces", /*default*/10u);
34 
GetTimeNanoseconds()35 static uint64_t GetTimeNanoseconds() {
36   struct timespec now;
37   clock_gettime(CLOCK_REALTIME, &now);
38 
39   uint64_t now_ns = (now.tv_sec * 1000000000LL + now.tv_nsec);
40   return now_ns;
41 }
42 
IsDir(const std::string & dirpath)43 static bool IsDir(const std::string& dirpath) {
44   struct stat st;
45   if (stat(dirpath.c_str(), &st) == 0) {
46     if (S_ISDIR(st.st_mode)) {
47       return true;
48     }
49   }
50   return false;
51 }
52 
53 // Given some path /a/b/c create all of /a, /a/b, /a/b/c/ recursively.
MkdirWithParents(const std::string & path)54 static bool MkdirWithParents(const std::string& path) {
55   size_t prev_end = 0;
56   while (prev_end < path.size()) {
57     size_t next_end = path.find('/', prev_end + 1);
58 
59     std::string dir_path = path.substr(0, next_end);
60     if (!IsDir(dir_path)) {
61 #if defined(_WIN32)
62       int ret = mkdir(dir_path.c_str());
63 #else
64       mode_t old_mask = umask(0);
65       // The user permission is 5 to allow system server to
66       // read the files. No other users could do that because
67       // the upper directory only allows system server and iorapd
68       // to access. Also selinux rules prevent other users to
69       // read files here.
70       int ret = mkdir(dir_path.c_str(), 0755);
71       umask(old_mask);
72 #endif
73       if (ret != 0) {
74         PLOG(ERROR) << "failed to create dir " << dir_path;
75         return false;
76       }
77     }
78     prev_end = next_end;
79 
80     if (next_end == std::string::npos) {
81       break;
82     }
83   }
84   return true;
85 }
86 
FileModelBase(VersionedComponentName vcn)87 FileModelBase::FileModelBase(VersionedComponentName vcn)
88   : vcn_{std::move(vcn)} {
89     root_path_ = common::GetEnvOrProperty(kRootPathProp,
90                                           /*default*/"/data/misc/iorapd");
91 }
92 
BaseDir() const93 std::string FileModelBase::BaseDir() const {
94   std::stringstream ss;
95 
96   ss << root_path_ << "/" << vcn_.GetPackage() << "/";
97   ss << vcn_.GetVersion();
98   ss << "/";
99   ss << vcn_.GetActivity() << "/";
100   ss << SubDir();
101 
102   return ss.str();
103 }
104 
FilePath() const105 std::string FileModelBase::FilePath() const {
106   std::stringstream ss;
107   ss << BaseDir();
108   ss << "/";
109   ss << BaseFile();
110 
111   return ss.str();
112 }
113 
MkdirWithParents()114 bool FileModelBase::MkdirWithParents() {
115   LOG(VERBOSE) << "MkdirWithParents: " << BaseDir();
116   return ::iorap::db::MkdirWithParents(BaseDir());
117 }
118 
PerfettoTraceFileModel(VersionedComponentName vcn,uint64_t timestamp)119 PerfettoTraceFileModel::PerfettoTraceFileModel(VersionedComponentName vcn,
120                                                uint64_t timestamp)
121   : FileModelBase{std::move(vcn)}, timestamp_{timestamp} {
122 }
123 
CalculateNewestFilePath(VersionedComponentName vcn)124 PerfettoTraceFileModel PerfettoTraceFileModel::CalculateNewestFilePath(VersionedComponentName vcn) {
125   uint64_t timestamp = GetTimeNanoseconds();
126   return PerfettoTraceFileModel{vcn, timestamp};
127 }
128 
BaseFile() const129 std::string PerfettoTraceFileModel::BaseFile() const {
130   std::stringstream ss;
131   ss << timestamp_ << ".perfetto_trace.pb";
132   return ss.str();
133 }
134 
DeleteOlderFiles(DbHandle & db,VersionedComponentName vcn)135 void PerfettoTraceFileModel::DeleteOlderFiles(DbHandle& db, VersionedComponentName vcn) {
136   std::vector<RawTraceModel> raw_traces =
137       RawTraceModel::SelectByVersionedComponentName(db, vcn);
138 
139   if (WOULD_LOG(VERBOSE)) {
140     size_t raw_traces_size = raw_traces.size();
141     for (size_t i = 0; i < raw_traces_size; ++i) {
142       LOG(VERBOSE) << "DeleteOlderFiles - selected " << raw_traces[i];
143     }
144     LOG(VERBOSE) << "DeleteOlderFiles - queried total " << raw_traces_size << " records";
145   }
146 
147   size_t items_to_delete = 0;
148   if (raw_traces.size() > kPerfettoMaxTraces) {
149     items_to_delete = raw_traces.size() - kPerfettoMaxTraces;
150   } else {
151     LOG(VERBOSE) << "DeleteOlderFiles - don't delete older raw traces, too few files: "
152                  << " wanted at least " << kPerfettoMaxTraces << ", but got " << raw_traces.size();
153   }
154 
155   for (size_t i = 0; i < items_to_delete; ++i) {
156     RawTraceModel& raw_trace = raw_traces[i];  // sorted ascending -> items to delete are first.
157     std::string err_msg;
158 
159     if (!::android::base::RemoveFileIfExists(raw_trace.file_path, /*out*/&err_msg)) {
160       LOG(ERROR) << "Failed to remove raw trace file: " << raw_trace.file_path
161                  << ", reason: " << err_msg;
162     } else {
163       raw_trace.Delete();
164       LOG(DEBUG) << "Deleted raw trace for " << vcn << " at " << raw_trace.file_path;
165     }
166   }
167 }
168 
CompiledTraceFileModel(VersionedComponentName vcn)169 CompiledTraceFileModel::CompiledTraceFileModel(VersionedComponentName vcn)
170   : FileModelBase{std::move(vcn)} {
171 }
172 
CalculateNewestFilePath(VersionedComponentName vcn)173 CompiledTraceFileModel CompiledTraceFileModel::CalculateNewestFilePath(VersionedComponentName vcn) {
174   return CompiledTraceFileModel{vcn};
175 }
176 
BaseFile() const177 std::string CompiledTraceFileModel::BaseFile() const {
178   return "compiled_trace.pb";
179 }
180 
181 }  // namespace iorap::db
182