mpd/src/Stats.cxx

123 lines
2.5 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright The Music Player Daemon Project
#include "config.h"
#include "Stats.hxx"
#include "player/Control.hxx"
#include "client/Response.hxx"
#include "Partition.hxx"
#include "Instance.hxx"
#include "db/Selection.hxx"
#include "db/Interface.hxx"
#include "db/Stats.hxx"
#include "Log.hxx"
#include "time/ChronoUtil.hxx"
#include "util/Math.hxx"
#ifdef _WIN32
#include "system/Clock.hxx"
#endif
#include <fmt/format.h>
#include <chrono>
#ifndef _WIN32
/**
* The monotonic time stamp when MPD was started. It is used to
* calculate the uptime.
*/
static const std::chrono::steady_clock::time_point start_time =
std::chrono::steady_clock::now();
#endif
#ifdef ENABLE_DATABASE
static DatabaseStats stats;
enum class StatsValidity : uint8_t {
INVALID, VALID, FAILED,
};
static StatsValidity stats_validity = StatsValidity::INVALID;
void
stats_invalidate()
{
stats_validity = StatsValidity::INVALID;
}
static bool
stats_update(const Database &db)
{
switch (stats_validity) {
case StatsValidity::INVALID:
break;
case StatsValidity::VALID:
return true;
case StatsValidity::FAILED:
return false;
}
const DatabaseSelection selection("", true);
try {
stats = db.GetStats(selection);
stats_validity = StatsValidity::VALID;
return true;
} catch (...) {
LogError(std::current_exception());
stats_validity = StatsValidity::FAILED;
return false;
}
}
static void
db_stats_print(Response &r, const Database &db)
{
if (!stats_update(db))
return;
unsigned total_duration_s =
std::chrono::duration_cast<std::chrono::seconds>(stats.total_duration).count();
r.Fmt(FMT_STRING("artists: {}\n"
"albums: {}\n"
"songs: {}\n"
"db_playtime: {}\n"),
stats.artist_count,
stats.album_count,
stats.song_count,
total_duration_s);
const auto update_stamp = db.GetUpdateStamp();
if (!IsNegative(update_stamp))
r.Fmt(FMT_STRING("db_update: {}\n"),
std::chrono::system_clock::to_time_t(update_stamp));
}
#endif
void
stats_print(Response &r, const Partition &partition)
{
#ifdef _WIN32
const auto uptime = GetProcessUptimeS();
#else
const auto uptime = std::chrono::steady_clock::now() - start_time;
#endif
r.Fmt(FMT_STRING("uptime: {}\n"
"playtime: {}\n"),
std::chrono::duration_cast<std::chrono::seconds>(uptime).count(),
lround(partition.pc.GetTotalPlayTime().count()));
#ifdef ENABLE_DATABASE
const Database *db = partition.instance.GetDatabase();
if (db != nullptr)
db_stats_print(r, *db);
#endif
}