1947fbce521d9e8377df03e3c1c31884ed5577f32yro/* 2947fbce521d9e8377df03e3c1c31884ed5577f32yro * Copyright (C) 2017 The Android Open Source Project 3947fbce521d9e8377df03e3c1c31884ed5577f32yro * 4947fbce521d9e8377df03e3c1c31884ed5577f32yro * Licensed under the Apache License, Version 2.0 (the "License"); 5947fbce521d9e8377df03e3c1c31884ed5577f32yro * you may not use this file except in compliance with the License. 6947fbce521d9e8377df03e3c1c31884ed5577f32yro * You may obtain a copy of the License at 7947fbce521d9e8377df03e3c1c31884ed5577f32yro * 8947fbce521d9e8377df03e3c1c31884ed5577f32yro * http://www.apache.org/licenses/LICENSE-2.0 9947fbce521d9e8377df03e3c1c31884ed5577f32yro * 10947fbce521d9e8377df03e3c1c31884ed5577f32yro * Unless required by applicable law or agreed to in writing, software 11947fbce521d9e8377df03e3c1c31884ed5577f32yro * distributed under the License is distributed on an "AS IS" BASIS, 12947fbce521d9e8377df03e3c1c31884ed5577f32yro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13947fbce521d9e8377df03e3c1c31884ed5577f32yro * See the License for the specific language governing permissions and 14947fbce521d9e8377df03e3c1c31884ed5577f32yro * limitations under the License. 15947fbce521d9e8377df03e3c1c31884ed5577f32yro */ 16947fbce521d9e8377df03e3c1c31884ed5577f32yro 17484524a246ffe453f8cd89b698a279c23b0bde1fTej Singh#define DEBUG false // STOPSHIP if true 18947fbce521d9e8377df03e3c1c31884ed5577f32yro#include "Log.h" 19947fbce521d9e8377df03e3c1c31884ed5577f32yro 20947fbce521d9e8377df03e3c1c31884ed5577f32yro#include "android-base/stringprintf.h" 2198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro#include "guardrail/StatsdStats.h" 2298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro#include "storage/StorageManager.h" 23330af58f2b8582b855085655fae553cdfaf44e6cYangster-mac#include "stats_log_util.h" 24947fbce521d9e8377df03e3c1c31884ed5577f32yro 25947fbce521d9e8377df03e3c1c31884ed5577f32yro#include <android-base/file.h> 26947fbce521d9e8377df03e3c1c31884ed5577f32yro#include <dirent.h> 2798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro#include <private/android_filesystem_config.h> 2898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro#include <fstream> 2998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro#include <iostream> 30947fbce521d9e8377df03e3c1c31884ed5577f32yro 31947fbce521d9e8377df03e3c1c31884ed5577f32yronamespace android { 32947fbce521d9e8377df03e3c1c31884ed5577f32yronamespace os { 33947fbce521d9e8377df03e3c1c31884ed5577f32yronamespace statsd { 34947fbce521d9e8377df03e3c1c31884ed5577f32yro 35f09569f848ca0b81a21a74e9f4dd8bd9a886151aYao Chenusing android::util::FIELD_COUNT_REPEATED; 36f09569f848ca0b81a21a74e9f4dd8bd9a886151aYao Chenusing android::util::FIELD_TYPE_MESSAGE; 37f09569f848ca0b81a21a74e9f4dd8bd9a886151aYao Chenusing std::map; 38f09569f848ca0b81a21a74e9f4dd8bd9a886151aYao Chen 3998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro#define STATS_DATA_DIR "/data/misc/stats-data" 4003faf093301847f0ac293ce8d6fcb0bce657a841yro#define STATS_SERVICE_DIR "/data/misc/stats-service" 41947fbce521d9e8377df03e3c1c31884ed5577f32yro 42947fbce521d9e8377df03e3c1c31884ed5577f32yro// for ConfigMetricsReportList 43947fbce521d9e8377df03e3c1c31884ed5577f32yroconst int FIELD_ID_REPORTS = 2; 44947fbce521d9e8377df03e3c1c31884ed5577f32yro 45947fbce521d9e8377df03e3c1c31884ed5577f32yrousing android::base::StringPrintf; 46947fbce521d9e8377df03e3c1c31884ed5577f32yrousing std::unique_ptr; 47947fbce521d9e8377df03e3c1c31884ed5577f32yro 4898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro// Returns array of int64_t which contains timestamp in seconds, uid, and 4998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro// configID. 5098a28501fe8ab53a490ec353c8a1f74f2e329cc5yrostatic void parseFileName(char* name, int64_t* result) { 5198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int index = 0; 5298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro char* substr = strtok(name, "_"); 5398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro while (substr != nullptr && index < 3) { 5498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro result[index] = StrToInt64(substr); 5598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro index++; 5698a28501fe8ab53a490ec353c8a1f74f2e329cc5yro substr = strtok(nullptr, "_"); 5798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 5898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro // When index ends before hitting 3, file name is corrupted. We 5998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro // intentionally put -1 at index 0 to indicate the error to caller. 6098a28501fe8ab53a490ec353c8a1f74f2e329cc5yro // TODO: consider removing files with unexpected name format. 6198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (index < 3) { 6298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro result[0] = -1; 6398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 6498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro} 6598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 6698a28501fe8ab53a490ec353c8a1f74f2e329cc5yrostatic string getFilePath(const char* path, int64_t timestamp, int64_t uid, int64_t configID) { 6750d23f1ed57003a389c010e3445bbc33b7c74a83yro return StringPrintf("%s/%lld_%d_%lld", path, (long long)timestamp, (int)uid, 6898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro (long long)configID); 6998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro} 7098a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 71947fbce521d9e8377df03e3c1c31884ed5577f32yrovoid StorageManager::writeFile(const char* file, const void* buffer, int numBytes) { 72947fbce521d9e8377df03e3c1c31884ed5577f32yro int fd = open(file, O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR); 73c7bdc6291df427f2de9ba191246065f5ff87e11fStefan Lafon if (fd == -1) { 74947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("Attempt to access %s but failed", file); 75947fbce521d9e8377df03e3c1c31884ed5577f32yro return; 76947fbce521d9e8377df03e3c1c31884ed5577f32yro } 7798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro trimToFit(STATS_SERVICE_DIR); 7898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro trimToFit(STATS_DATA_DIR); 79947fbce521d9e8377df03e3c1c31884ed5577f32yro 80947fbce521d9e8377df03e3c1c31884ed5577f32yro int result = write(fd, buffer, numBytes); 81947fbce521d9e8377df03e3c1c31884ed5577f32yro if (result == numBytes) { 82947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("Successfully wrote %s", file); 83947fbce521d9e8377df03e3c1c31884ed5577f32yro } else { 84947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("Failed to write %s", file); 85947fbce521d9e8377df03e3c1c31884ed5577f32yro } 8698a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 8798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro result = fchown(fd, AID_STATSD, AID_STATSD); 8898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (result) { 8998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro VLOG("Failed to chown %s to statsd", file); 9098a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 9198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 92947fbce521d9e8377df03e3c1c31884ed5577f32yro close(fd); 93947fbce521d9e8377df03e3c1c31884ed5577f32yro} 94947fbce521d9e8377df03e3c1c31884ed5577f32yro 95947fbce521d9e8377df03e3c1c31884ed5577f32yrovoid StorageManager::deleteFile(const char* file) { 96947fbce521d9e8377df03e3c1c31884ed5577f32yro if (remove(file) != 0) { 97947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("Attempt to delete %s but is not found", file); 98947fbce521d9e8377df03e3c1c31884ed5577f32yro } else { 99947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("Successfully deleted %s", file); 100947fbce521d9e8377df03e3c1c31884ed5577f32yro } 101947fbce521d9e8377df03e3c1c31884ed5577f32yro} 102947fbce521d9e8377df03e3c1c31884ed5577f32yro 103947fbce521d9e8377df03e3c1c31884ed5577f32yrovoid StorageManager::deleteAllFiles(const char* path) { 104947fbce521d9e8377df03e3c1c31884ed5577f32yro unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir); 105947fbce521d9e8377df03e3c1c31884ed5577f32yro if (dir == NULL) { 106947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("Directory does not exist: %s", path); 107947fbce521d9e8377df03e3c1c31884ed5577f32yro return; 108947fbce521d9e8377df03e3c1c31884ed5577f32yro } 109947fbce521d9e8377df03e3c1c31884ed5577f32yro 110947fbce521d9e8377df03e3c1c31884ed5577f32yro dirent* de; 111947fbce521d9e8377df03e3c1c31884ed5577f32yro while ((de = readdir(dir.get()))) { 112947fbce521d9e8377df03e3c1c31884ed5577f32yro char* name = de->d_name; 113947fbce521d9e8377df03e3c1c31884ed5577f32yro if (name[0] == '.') continue; 114947fbce521d9e8377df03e3c1c31884ed5577f32yro deleteFile(StringPrintf("%s/%s", path, name).c_str()); 115947fbce521d9e8377df03e3c1c31884ed5577f32yro } 116947fbce521d9e8377df03e3c1c31884ed5577f32yro} 117947fbce521d9e8377df03e3c1c31884ed5577f32yro 118e5f82927ae60fdff909e030434354a6ba164f333yrovoid StorageManager::deleteSuffixedFiles(const char* path, const char* suffix) { 119947fbce521d9e8377df03e3c1c31884ed5577f32yro unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir); 120947fbce521d9e8377df03e3c1c31884ed5577f32yro if (dir == NULL) { 121947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("Directory does not exist: %s", path); 122947fbce521d9e8377df03e3c1c31884ed5577f32yro return; 123947fbce521d9e8377df03e3c1c31884ed5577f32yro } 124947fbce521d9e8377df03e3c1c31884ed5577f32yro 125947fbce521d9e8377df03e3c1c31884ed5577f32yro dirent* de; 126947fbce521d9e8377df03e3c1c31884ed5577f32yro while ((de = readdir(dir.get()))) { 127947fbce521d9e8377df03e3c1c31884ed5577f32yro char* name = de->d_name; 128e5f82927ae60fdff909e030434354a6ba164f333yro if (name[0] == '.') { 129947fbce521d9e8377df03e3c1c31884ed5577f32yro continue; 130947fbce521d9e8377df03e3c1c31884ed5577f32yro } 131e5f82927ae60fdff909e030434354a6ba164f333yro size_t nameLen = strlen(name); 132e5f82927ae60fdff909e030434354a6ba164f333yro size_t suffixLen = strlen(suffix); 133e5f82927ae60fdff909e030434354a6ba164f333yro if (suffixLen <= nameLen && strncmp(name + nameLen - suffixLen, suffix, suffixLen) == 0) { 134e5f82927ae60fdff909e030434354a6ba164f333yro deleteFile(StringPrintf("%s/%s", path, name).c_str()); 135e5f82927ae60fdff909e030434354a6ba164f333yro } 136947fbce521d9e8377df03e3c1c31884ed5577f32yro } 137947fbce521d9e8377df03e3c1c31884ed5577f32yro} 138947fbce521d9e8377df03e3c1c31884ed5577f32yro 139947fbce521d9e8377df03e3c1c31884ed5577f32yrovoid StorageManager::sendBroadcast(const char* path, 140947fbce521d9e8377df03e3c1c31884ed5577f32yro const std::function<void(const ConfigKey&)>& sendBroadcast) { 141947fbce521d9e8377df03e3c1c31884ed5577f32yro unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir); 142947fbce521d9e8377df03e3c1c31884ed5577f32yro if (dir == NULL) { 143947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("no stats-data directory on disk"); 144947fbce521d9e8377df03e3c1c31884ed5577f32yro return; 145947fbce521d9e8377df03e3c1c31884ed5577f32yro } 146947fbce521d9e8377df03e3c1c31884ed5577f32yro 147947fbce521d9e8377df03e3c1c31884ed5577f32yro dirent* de; 148947fbce521d9e8377df03e3c1c31884ed5577f32yro while ((de = readdir(dir.get()))) { 149947fbce521d9e8377df03e3c1c31884ed5577f32yro char* name = de->d_name; 150947fbce521d9e8377df03e3c1c31884ed5577f32yro if (name[0] == '.') continue; 151947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("file %s", name); 152947fbce521d9e8377df03e3c1c31884ed5577f32yro 15398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t result[3]; 15498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro parseFileName(name, result); 15598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (result[0] == -1) continue; 15698a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t uid = result[1]; 15798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t configID = result[2]; 158947fbce521d9e8377df03e3c1c31884ed5577f32yro 15998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro sendBroadcast(ConfigKey((int)uid, configID)); 160947fbce521d9e8377df03e3c1c31884ed5577f32yro } 161947fbce521d9e8377df03e3c1c31884ed5577f32yro} 162947fbce521d9e8377df03e3c1c31884ed5577f32yro 16348944901f7e6334724efadda6c6b27d9e88fc9e2David Chenbool StorageManager::hasConfigMetricsReport(const ConfigKey& key) { 16448944901f7e6334724efadda6c6b27d9e88fc9e2David Chen unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_DATA_DIR), closedir); 16548944901f7e6334724efadda6c6b27d9e88fc9e2David Chen if (dir == NULL) { 16648944901f7e6334724efadda6c6b27d9e88fc9e2David Chen VLOG("Path %s does not exist", STATS_DATA_DIR); 16748944901f7e6334724efadda6c6b27d9e88fc9e2David Chen return false; 16848944901f7e6334724efadda6c6b27d9e88fc9e2David Chen } 16948944901f7e6334724efadda6c6b27d9e88fc9e2David Chen 17048944901f7e6334724efadda6c6b27d9e88fc9e2David Chen string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId()); 17148944901f7e6334724efadda6c6b27d9e88fc9e2David Chen 17248944901f7e6334724efadda6c6b27d9e88fc9e2David Chen dirent* de; 17348944901f7e6334724efadda6c6b27d9e88fc9e2David Chen while ((de = readdir(dir.get()))) { 17448944901f7e6334724efadda6c6b27d9e88fc9e2David Chen char* name = de->d_name; 17548944901f7e6334724efadda6c6b27d9e88fc9e2David Chen if (name[0] == '.') continue; 17648944901f7e6334724efadda6c6b27d9e88fc9e2David Chen 17748944901f7e6334724efadda6c6b27d9e88fc9e2David Chen size_t nameLen = strlen(name); 17848944901f7e6334724efadda6c6b27d9e88fc9e2David Chen size_t suffixLen = suffix.length(); 17948944901f7e6334724efadda6c6b27d9e88fc9e2David Chen if (suffixLen <= nameLen && 18048944901f7e6334724efadda6c6b27d9e88fc9e2David Chen strncmp(name + nameLen - suffixLen, suffix.c_str(), suffixLen) == 0) { 18148944901f7e6334724efadda6c6b27d9e88fc9e2David Chen // Check again that the file name is parseable. 18248944901f7e6334724efadda6c6b27d9e88fc9e2David Chen int64_t result[3]; 18348944901f7e6334724efadda6c6b27d9e88fc9e2David Chen parseFileName(name, result); 18448944901f7e6334724efadda6c6b27d9e88fc9e2David Chen if (result[0] == -1) continue; 18548944901f7e6334724efadda6c6b27d9e88fc9e2David Chen return true; 18648944901f7e6334724efadda6c6b27d9e88fc9e2David Chen } 18748944901f7e6334724efadda6c6b27d9e88fc9e2David Chen } 18848944901f7e6334724efadda6c6b27d9e88fc9e2David Chen return false; 18948944901f7e6334724efadda6c6b27d9e88fc9e2David Chen} 19048944901f7e6334724efadda6c6b27d9e88fc9e2David Chen 1914beccbe3de7537365856bbd2a34be8d6f226b8b8yrovoid StorageManager::appendConfigMetricsReport(const ConfigKey& key, ProtoOutputStream* proto) { 19298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_DATA_DIR), closedir); 1937250622b47397bd05983aa5655f18fb5cc757cb4Yao Chen if (dir == NULL) { 19498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro VLOG("Path %s does not exist", STATS_DATA_DIR); 195947fbce521d9e8377df03e3c1c31884ed5577f32yro return; 196947fbce521d9e8377df03e3c1c31884ed5577f32yro } 197947fbce521d9e8377df03e3c1c31884ed5577f32yro 198fef48cb64c505664b078818455baebbe3cc025cbYao Chen string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId()); 1994beccbe3de7537365856bbd2a34be8d6f226b8b8yro 200947fbce521d9e8377df03e3c1c31884ed5577f32yro dirent* de; 201947fbce521d9e8377df03e3c1c31884ed5577f32yro while ((de = readdir(dir.get()))) { 202947fbce521d9e8377df03e3c1c31884ed5577f32yro char* name = de->d_name; 203947fbce521d9e8377df03e3c1c31884ed5577f32yro if (name[0] == '.') continue; 204947fbce521d9e8377df03e3c1c31884ed5577f32yro 2054beccbe3de7537365856bbd2a34be8d6f226b8b8yro size_t nameLen = strlen(name); 206fef48cb64c505664b078818455baebbe3cc025cbYao Chen size_t suffixLen = suffix.length(); 2074beccbe3de7537365856bbd2a34be8d6f226b8b8yro if (suffixLen <= nameLen && 208fef48cb64c505664b078818455baebbe3cc025cbYao Chen strncmp(name + nameLen - suffixLen, suffix.c_str(), suffixLen) == 0) { 2094beccbe3de7537365856bbd2a34be8d6f226b8b8yro int64_t result[3]; 2104beccbe3de7537365856bbd2a34be8d6f226b8b8yro parseFileName(name, result); 2114beccbe3de7537365856bbd2a34be8d6f226b8b8yro if (result[0] == -1) continue; 2124beccbe3de7537365856bbd2a34be8d6f226b8b8yro int64_t timestamp = result[0]; 2134beccbe3de7537365856bbd2a34be8d6f226b8b8yro int64_t uid = result[1]; 2144beccbe3de7537365856bbd2a34be8d6f226b8b8yro int64_t configID = result[2]; 2154beccbe3de7537365856bbd2a34be8d6f226b8b8yro 2164beccbe3de7537365856bbd2a34be8d6f226b8b8yro string file_name = getFilePath(STATS_DATA_DIR, timestamp, uid, configID); 2174beccbe3de7537365856bbd2a34be8d6f226b8b8yro int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC); 2184beccbe3de7537365856bbd2a34be8d6f226b8b8yro if (fd != -1) { 2194beccbe3de7537365856bbd2a34be8d6f226b8b8yro string content; 2204beccbe3de7537365856bbd2a34be8d6f226b8b8yro if (android::base::ReadFdToString(fd, &content)) { 2214beccbe3de7537365856bbd2a34be8d6f226b8b8yro proto->write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS, 2224beccbe3de7537365856bbd2a34be8d6f226b8b8yro content.c_str(), content.size()); 2234beccbe3de7537365856bbd2a34be8d6f226b8b8yro } 2244beccbe3de7537365856bbd2a34be8d6f226b8b8yro close(fd); 225947fbce521d9e8377df03e3c1c31884ed5577f32yro } 226947fbce521d9e8377df03e3c1c31884ed5577f32yro 2274beccbe3de7537365856bbd2a34be8d6f226b8b8yro // Remove file from disk after reading. 2284beccbe3de7537365856bbd2a34be8d6f226b8b8yro remove(file_name.c_str()); 2294beccbe3de7537365856bbd2a34be8d6f226b8b8yro } 230947fbce521d9e8377df03e3c1c31884ed5577f32yro } 231947fbce521d9e8377df03e3c1c31884ed5577f32yro} 232947fbce521d9e8377df03e3c1c31884ed5577f32yro 233932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-macbool StorageManager::readFileToString(const char* file, string* content) { 234932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac int fd = open(file, O_RDONLY | O_CLOEXEC); 235932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac bool res = false; 236932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac if (fd != -1) { 237932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac if (android::base::ReadFdToString(fd, content)) { 238932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac res = true; 239932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac } else { 240932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac VLOG("Failed to read file %s\n", file); 241932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac } 242932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac close(fd); 243932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac } 244932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac return res; 245932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac} 246932ececa1674c59a8da9f3e32d2651e781b86fc4Yangster-mac 247f09569f848ca0b81a21a74e9f4dd8bd9a886151aYao Chenvoid StorageManager::readConfigFromDisk(map<ConfigKey, StatsdConfig>& configsMap) { 248947fbce521d9e8377df03e3c1c31884ed5577f32yro unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), closedir); 249947fbce521d9e8377df03e3c1c31884ed5577f32yro if (dir == NULL) { 250947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("no default config on disk"); 251947fbce521d9e8377df03e3c1c31884ed5577f32yro return; 252947fbce521d9e8377df03e3c1c31884ed5577f32yro } 25398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro trimToFit(STATS_SERVICE_DIR); 254947fbce521d9e8377df03e3c1c31884ed5577f32yro 255947fbce521d9e8377df03e3c1c31884ed5577f32yro dirent* de; 256947fbce521d9e8377df03e3c1c31884ed5577f32yro while ((de = readdir(dir.get()))) { 257947fbce521d9e8377df03e3c1c31884ed5577f32yro char* name = de->d_name; 258947fbce521d9e8377df03e3c1c31884ed5577f32yro if (name[0] == '.') continue; 259947fbce521d9e8377df03e3c1c31884ed5577f32yro VLOG("file %s", name); 260947fbce521d9e8377df03e3c1c31884ed5577f32yro 26198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t result[3]; 26298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro parseFileName(name, result); 26398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (result[0] == -1) continue; 26498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t timestamp = result[0]; 26598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t uid = result[1]; 26698a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t configID = result[2]; 26798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro string file_name = getFilePath(STATS_SERVICE_DIR, timestamp, uid, configID); 268947fbce521d9e8377df03e3c1c31884ed5577f32yro int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC); 269947fbce521d9e8377df03e3c1c31884ed5577f32yro if (fd != -1) { 270947fbce521d9e8377df03e3c1c31884ed5577f32yro string content; 271947fbce521d9e8377df03e3c1c31884ed5577f32yro if (android::base::ReadFdToString(fd, &content)) { 272947fbce521d9e8377df03e3c1c31884ed5577f32yro StatsdConfig config; 273947fbce521d9e8377df03e3c1c31884ed5577f32yro if (config.ParseFromString(content)) { 2746e304ec6901484157b9cae1cafc5713a825720bcyro configsMap[ConfigKey(uid, configID)] = config; 27598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro VLOG("map key uid=%lld|configID=%lld", (long long)uid, (long long)configID); 276947fbce521d9e8377df03e3c1c31884ed5577f32yro } 277947fbce521d9e8377df03e3c1c31884ed5577f32yro } 278947fbce521d9e8377df03e3c1c31884ed5577f32yro close(fd); 279947fbce521d9e8377df03e3c1c31884ed5577f32yro } 280947fbce521d9e8377df03e3c1c31884ed5577f32yro } 281947fbce521d9e8377df03e3c1c31884ed5577f32yro} 282947fbce521d9e8377df03e3c1c31884ed5577f32yro 283b142cc8add29c8c97f6134d35873d23db666027cYangster-macbool StorageManager::readConfigFromDisk(const ConfigKey& key, StatsdConfig* config) { 284b142cc8add29c8c97f6134d35873d23db666027cYangster-mac string content; 285b142cc8add29c8c97f6134d35873d23db666027cYangster-mac return config != nullptr && 286b142cc8add29c8c97f6134d35873d23db666027cYangster-mac StorageManager::readConfigFromDisk(key, &content) && config->ParseFromString(content); 287b142cc8add29c8c97f6134d35873d23db666027cYangster-mac} 288b142cc8add29c8c97f6134d35873d23db666027cYangster-mac 289b142cc8add29c8c97f6134d35873d23db666027cYangster-macbool StorageManager::readConfigFromDisk(const ConfigKey& key, string* content) { 2904490765d1552f1a2ae114f9c301386823b930828yro unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR), 2914490765d1552f1a2ae114f9c301386823b930828yro closedir); 2924490765d1552f1a2ae114f9c301386823b930828yro if (dir == NULL) { 2934490765d1552f1a2ae114f9c301386823b930828yro VLOG("Directory does not exist: %s", STATS_SERVICE_DIR); 2944490765d1552f1a2ae114f9c301386823b930828yro return false; 2954490765d1552f1a2ae114f9c301386823b930828yro } 2964490765d1552f1a2ae114f9c301386823b930828yro 297fef48cb64c505664b078818455baebbe3cc025cbYao Chen string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId()); 2984490765d1552f1a2ae114f9c301386823b930828yro dirent* de; 2994490765d1552f1a2ae114f9c301386823b930828yro while ((de = readdir(dir.get()))) { 3004490765d1552f1a2ae114f9c301386823b930828yro char* name = de->d_name; 3014490765d1552f1a2ae114f9c301386823b930828yro if (name[0] == '.') { 3024490765d1552f1a2ae114f9c301386823b930828yro continue; 3034490765d1552f1a2ae114f9c301386823b930828yro } 3044490765d1552f1a2ae114f9c301386823b930828yro size_t nameLen = strlen(name); 305fef48cb64c505664b078818455baebbe3cc025cbYao Chen size_t suffixLen = suffix.length(); 3064490765d1552f1a2ae114f9c301386823b930828yro // There can be at most one file that matches this suffix (config key). 3074490765d1552f1a2ae114f9c301386823b930828yro if (suffixLen <= nameLen && 308fef48cb64c505664b078818455baebbe3cc025cbYao Chen strncmp(name + nameLen - suffixLen, suffix.c_str(), suffixLen) == 0) { 3094490765d1552f1a2ae114f9c301386823b930828yro int fd = open(StringPrintf("%s/%s", STATS_SERVICE_DIR, name).c_str(), 3104490765d1552f1a2ae114f9c301386823b930828yro O_RDONLY | O_CLOEXEC); 3114490765d1552f1a2ae114f9c301386823b930828yro if (fd != -1) { 312b142cc8add29c8c97f6134d35873d23db666027cYangster-mac if (android::base::ReadFdToString(fd, content)) { 313b142cc8add29c8c97f6134d35873d23db666027cYangster-mac return true; 3144490765d1552f1a2ae114f9c301386823b930828yro } 3154beccbe3de7537365856bbd2a34be8d6f226b8b8yro close(fd); 3164490765d1552f1a2ae114f9c301386823b930828yro } 3174490765d1552f1a2ae114f9c301386823b930828yro } 3184490765d1552f1a2ae114f9c301386823b930828yro } 3194490765d1552f1a2ae114f9c301386823b930828yro return false; 3204490765d1552f1a2ae114f9c301386823b930828yro} 3214490765d1552f1a2ae114f9c301386823b930828yro 322b142cc8add29c8c97f6134d35873d23db666027cYangster-macbool StorageManager::hasIdenticalConfig(const ConfigKey& key, 323b142cc8add29c8c97f6134d35873d23db666027cYangster-mac const vector<uint8_t>& config) { 324b142cc8add29c8c97f6134d35873d23db666027cYangster-mac string content; 325b142cc8add29c8c97f6134d35873d23db666027cYangster-mac if (StorageManager::readConfigFromDisk(key, &content)) { 326b142cc8add29c8c97f6134d35873d23db666027cYangster-mac vector<uint8_t> vec(content.begin(), content.end()); 327b142cc8add29c8c97f6134d35873d23db666027cYangster-mac if (vec == config) { 328b142cc8add29c8c97f6134d35873d23db666027cYangster-mac return true; 329b142cc8add29c8c97f6134d35873d23db666027cYangster-mac } 330b142cc8add29c8c97f6134d35873d23db666027cYangster-mac } 331b142cc8add29c8c97f6134d35873d23db666027cYangster-mac return false; 332b142cc8add29c8c97f6134d35873d23db666027cYangster-mac} 333b142cc8add29c8c97f6134d35873d23db666027cYangster-mac 33498a28501fe8ab53a490ec353c8a1f74f2e329cc5yrovoid StorageManager::trimToFit(const char* path) { 33598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir); 33698a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (dir == NULL) { 33798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro VLOG("Path %s does not exist", path); 33898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro return; 33998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 34098a28501fe8ab53a490ec353c8a1f74f2e329cc5yro dirent* de; 34198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int totalFileSize = 0; 34298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro vector<string> fileNames; 34398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro while ((de = readdir(dir.get()))) { 34498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro char* name = de->d_name; 34598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (name[0] == '.') continue; 34698a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 34798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t result[3]; 34898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro parseFileName(name, result); 34998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (result[0] == -1) continue; 35098a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t timestamp = result[0]; 35198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t uid = result[1]; 35298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int64_t configID = result[2]; 35398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro string file_name = getFilePath(path, timestamp, uid, configID); 35498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 35598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro // Check for timestamp and delete if it's too old. 356330af58f2b8582b855085655fae553cdfaf44e6cYangster-mac long fileAge = getWallClockSec() - timestamp; 35798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (fileAge > StatsdStats::kMaxAgeSecond) { 35898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro deleteFile(file_name.c_str()); 35998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 36098a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 36198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro fileNames.push_back(file_name); 36298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro ifstream file(file_name.c_str(), ifstream::in | ifstream::binary); 36398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (file.is_open()) { 36498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro file.seekg(0, ios::end); 36598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int fileSize = file.tellg(); 36698a28501fe8ab53a490ec353c8a1f74f2e329cc5yro file.close(); 36798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro totalFileSize += fileSize; 36898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 36998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 37098a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 37198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (fileNames.size() > StatsdStats::kMaxFileNumber || 37298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro totalFileSize > StatsdStats::kMaxFileSize) { 37398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro // Reverse sort to effectively remove from the back (oldest entries). 37498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro // This will sort files in reverse-chronological order. 37598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro sort(fileNames.begin(), fileNames.end(), std::greater<std::string>()); 37698a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 37798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 37898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro // Start removing files from oldest to be under the limit. 37998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro while (fileNames.size() > 0 && (fileNames.size() > StatsdStats::kMaxFileNumber || 38098a28501fe8ab53a490ec353c8a1f74f2e329cc5yro totalFileSize > StatsdStats::kMaxFileSize)) { 38198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro string file_name = fileNames.at(fileNames.size() - 1); 38298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro ifstream file(file_name.c_str(), ifstream::in | ifstream::binary); 38398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro if (file.is_open()) { 38498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro file.seekg(0, ios::end); 38598a28501fe8ab53a490ec353c8a1f74f2e329cc5yro int fileSize = file.tellg(); 38698a28501fe8ab53a490ec353c8a1f74f2e329cc5yro file.close(); 38798a28501fe8ab53a490ec353c8a1f74f2e329cc5yro totalFileSize -= fileSize; 38898a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 38998a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 39098a28501fe8ab53a490ec353c8a1f74f2e329cc5yro deleteFile(file_name.c_str()); 39198a28501fe8ab53a490ec353c8a1f74f2e329cc5yro fileNames.pop_back(); 39298a28501fe8ab53a490ec353c8a1f74f2e329cc5yro } 39398a28501fe8ab53a490ec353c8a1f74f2e329cc5yro} 39498a28501fe8ab53a490ec353c8a1f74f2e329cc5yro 395665208d74345d779bed8724862e8d0d1c46a7a76yrovoid StorageManager::printStats(FILE* out) { 396665208d74345d779bed8724862e8d0d1c46a7a76yro printDirStats(out, STATS_SERVICE_DIR); 397665208d74345d779bed8724862e8d0d1c46a7a76yro printDirStats(out, STATS_DATA_DIR); 398665208d74345d779bed8724862e8d0d1c46a7a76yro} 399665208d74345d779bed8724862e8d0d1c46a7a76yro 400665208d74345d779bed8724862e8d0d1c46a7a76yrovoid StorageManager::printDirStats(FILE* out, const char* path) { 401665208d74345d779bed8724862e8d0d1c46a7a76yro fprintf(out, "Printing stats of %s\n", path); 402665208d74345d779bed8724862e8d0d1c46a7a76yro unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir); 403665208d74345d779bed8724862e8d0d1c46a7a76yro if (dir == NULL) { 404665208d74345d779bed8724862e8d0d1c46a7a76yro VLOG("Path %s does not exist", path); 405665208d74345d779bed8724862e8d0d1c46a7a76yro return; 406665208d74345d779bed8724862e8d0d1c46a7a76yro } 407665208d74345d779bed8724862e8d0d1c46a7a76yro dirent* de; 408665208d74345d779bed8724862e8d0d1c46a7a76yro int fileCount = 0; 409665208d74345d779bed8724862e8d0d1c46a7a76yro int totalFileSize = 0; 410665208d74345d779bed8724862e8d0d1c46a7a76yro while ((de = readdir(dir.get()))) { 411665208d74345d779bed8724862e8d0d1c46a7a76yro char* name = de->d_name; 412665208d74345d779bed8724862e8d0d1c46a7a76yro if (name[0] == '.') { 413665208d74345d779bed8724862e8d0d1c46a7a76yro continue; 414665208d74345d779bed8724862e8d0d1c46a7a76yro } 415665208d74345d779bed8724862e8d0d1c46a7a76yro int64_t result[3]; 416665208d74345d779bed8724862e8d0d1c46a7a76yro parseFileName(name, result); 417665208d74345d779bed8724862e8d0d1c46a7a76yro if (result[0] == -1) continue; 418665208d74345d779bed8724862e8d0d1c46a7a76yro int64_t timestamp = result[0]; 419665208d74345d779bed8724862e8d0d1c46a7a76yro int64_t uid = result[1]; 420665208d74345d779bed8724862e8d0d1c46a7a76yro int64_t configID = result[2]; 421665208d74345d779bed8724862e8d0d1c46a7a76yro fprintf(out, "\t #%d, Last updated: %lld, UID: %d, Config ID: %lld", 422665208d74345d779bed8724862e8d0d1c46a7a76yro fileCount + 1, 423665208d74345d779bed8724862e8d0d1c46a7a76yro (long long)timestamp, 424665208d74345d779bed8724862e8d0d1c46a7a76yro (int)uid, 425665208d74345d779bed8724862e8d0d1c46a7a76yro (long long)configID); 426665208d74345d779bed8724862e8d0d1c46a7a76yro string file_name = getFilePath(path, timestamp, uid, configID); 427665208d74345d779bed8724862e8d0d1c46a7a76yro ifstream file(file_name.c_str(), ifstream::in | ifstream::binary); 428665208d74345d779bed8724862e8d0d1c46a7a76yro if (file.is_open()) { 429665208d74345d779bed8724862e8d0d1c46a7a76yro file.seekg(0, ios::end); 430665208d74345d779bed8724862e8d0d1c46a7a76yro int fileSize = file.tellg(); 431665208d74345d779bed8724862e8d0d1c46a7a76yro file.close(); 432665208d74345d779bed8724862e8d0d1c46a7a76yro fprintf(out, ", File Size: %d bytes", fileSize); 433665208d74345d779bed8724862e8d0d1c46a7a76yro totalFileSize += fileSize; 434665208d74345d779bed8724862e8d0d1c46a7a76yro } 435665208d74345d779bed8724862e8d0d1c46a7a76yro fprintf(out, "\n"); 436665208d74345d779bed8724862e8d0d1c46a7a76yro fileCount++; 437665208d74345d779bed8724862e8d0d1c46a7a76yro } 438665208d74345d779bed8724862e8d0d1c46a7a76yro fprintf(out, "\tTotal number of files: %d, Total size of files: %d bytes.\n", 439665208d74345d779bed8724862e8d0d1c46a7a76yro fileCount, totalFileSize); 440665208d74345d779bed8724862e8d0d1c46a7a76yro} 441665208d74345d779bed8724862e8d0d1c46a7a76yro 442947fbce521d9e8377df03e3c1c31884ed5577f32yro} // namespace statsd 443947fbce521d9e8377df03e3c1c31884ed5577f32yro} // namespace os 444947fbce521d9e8377df03e3c1c31884ed5577f32yro} // namespace android 445