| // Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/developer/memory/monitor/high_water.h" | |
| #include <lib/async/dispatcher.h> | |
| #include <lib/syslog/cpp/macros.h> | |
| #include <zircon/status.h> | |
| #include <fstream> | |
| #include <src/lib/files/file.h> | |
| #include <src/lib/files/path.h> | |
| #include "src/developer/memory/metrics/digest.h" | |
| #include "src/developer/memory/metrics/printer.h" | |
| namespace monitor { | |
| using namespace memory; | |
| static const char kLatest[] = "latest.txt"; | |
| static const char kPrevious[] = "previous.txt"; | |
| static const char kLatestDigest[] = "latest_digest.txt"; | |
| static const char kPreviousDigest[] = "previous_digest.txt"; | |
| HighWater::HighWater(const std::string& dir, zx::duration poll_frequency, | |
| uint64_t high_water_threshold, async_dispatcher_t* dispatcher, | |
| CaptureFn capture_cb) | |
| : dir_(dir), | |
| watcher_(poll_frequency, high_water_threshold, dispatcher, std::move(capture_cb), | |
| [this](const Capture& c) { | |
| RecordHighWater(c); | |
| RecordHighWaterDigest(c); | |
| }), | |
| namer_(Summary::kNameMatches) { | |
| // Ok to ignore result. last might not exist. | |
| remove(files::JoinPath(dir_, kPrevious).c_str()); | |
| remove(files::JoinPath(dir_, kPreviousDigest).c_str()); | |
| // Ok to ignore this too. Latest might not exist. | |
| rename(files::JoinPath(dir_, kLatest).c_str(), files::JoinPath(dir_, kPrevious).c_str()); | |
| rename(files::JoinPath(dir_, kLatestDigest).c_str(), | |
| files::JoinPath(dir_, kPreviousDigest).c_str()); | |
| } | |
| void HighWater::RecordHighWater(const Capture& capture) { | |
| Summary s(capture, &namer_); | |
| std::ofstream out; | |
| out.open(files::JoinPath(dir_, kLatest)); | |
| Printer p(out); | |
| p.PrintSummary(s, VMO, memory::SORTED); | |
| out.close(); | |
| } | |
| void HighWater::RecordHighWaterDigest(const Capture& capture) { | |
| Digest d(capture, &digester_); | |
| std::ofstream out; | |
| out.open(files::JoinPath(dir_, kLatestDigest)); | |
| Printer p(out); | |
| p.PrintDigest(d); | |
| out.close(); | |
| } | |
| std::string HighWater::GetHighWater() const { return GetFile(kLatest); } | |
| std::string HighWater::GetPreviousHighWater() const { return GetFile(kPrevious); } | |
| std::string HighWater::GetHighWaterDigest() const { return GetFile(kLatestDigest); } | |
| std::string HighWater::GetPreviousHighWaterDigest() const { return GetFile(kPreviousDigest); } | |
| std::string HighWater::GetFile(const char* filename) const { | |
| std::string file; | |
| if (files::ReadFileToString(files::JoinPath(dir_, filename), &file)) { | |
| return file; | |
| } | |
| return ""; | |
| } | |
| } // namespace monitor |