Campaignd: use chrono::system_clock instead of std::time_t
Includes adjustments to client code to likewise use chrono types. I decided to keep using time_t (which is just an alias for long_long) for serializing time points. This avoids compatibility issues, since we keep the same resolution (seconds since Unix epoch), and unless we're going to "properly" store time points in config, the time_t's unitless value is a good a representation as any.
This commit is contained in:
parent
b859060627
commit
6dc65f6483
6 changed files with 87 additions and 49 deletions
|
@ -20,6 +20,7 @@
|
|||
#include "gettext.hpp"
|
||||
#include "picture.hpp"
|
||||
#include "log.hpp"
|
||||
#include "serialization/chrono.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
|
||||
static lg::log_domain log_addons_client("addons-client");
|
||||
|
@ -102,8 +103,8 @@ void addon_info::read(const config& cfg)
|
|||
tags = utils::split(cfg["tags"].str());
|
||||
feedback_url = cfg["feedback_url"].str();
|
||||
|
||||
updated = cfg["timestamp"].to_time_t();
|
||||
created = cfg["original_timestamp"].to_time_t();
|
||||
updated = chrono::parse_timestamp(cfg["timestamp"]);
|
||||
created = chrono::parse_timestamp(cfg["original_timestamp"]);
|
||||
|
||||
local_only = cfg["local_only"].to_bool();
|
||||
}
|
||||
|
@ -137,8 +138,8 @@ void addon_info::write(config& cfg) const
|
|||
cfg["tags"] = utils::join(tags);
|
||||
cfg["feedback_url"] = feedback_url;
|
||||
|
||||
cfg["timestamp"] = updated;
|
||||
cfg["original_timestamp"] = created;
|
||||
cfg["timestamp"] = chrono::serialize_timestamp(updated);
|
||||
cfg["original_timestamp"] = chrono::serialize_timestamp(created);
|
||||
}
|
||||
|
||||
void addon_info::write_minimal(config& cfg) const
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "addon/validation.hpp"
|
||||
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
|
@ -99,8 +99,8 @@ struct addon_info
|
|||
|
||||
std::string feedback_url;
|
||||
|
||||
std::time_t updated;
|
||||
std::time_t created;
|
||||
std::chrono::system_clock::time_point updated;
|
||||
std::chrono::system_clock::time_point created;
|
||||
|
||||
// Flag to indicate whether this object was generaled from pbl info for an addon
|
||||
// not previously published.
|
||||
|
|
|
@ -1022,25 +1022,22 @@ void addon_manager::show_help()
|
|||
help::show_help("installing_addons");
|
||||
}
|
||||
|
||||
static std::string format_addon_time(std::time_t time)
|
||||
static std::string format_addon_time(const std::chrono::system_clock::time_point& time)
|
||||
{
|
||||
if(time) {
|
||||
std::ostringstream ss;
|
||||
|
||||
const std::string format = prefs::get().use_twelve_hour_clock_format()
|
||||
// TRANSLATORS: Month + day of month + year + 12-hour time, eg 'November 02 2021, 1:59 PM'. Format for your locale.
|
||||
// Format reference: https://www.boost.org/doc/libs/1_85_0/doc/html/date_time/date_time_io.html#date_time.format_flags
|
||||
? _("%B %d %Y, %I:%M %p")
|
||||
// TRANSLATORS: Month + day of month + year + 24-hour time, eg 'November 02 2021, 13:59'. Format for your locale.
|
||||
// Format reference: https://www.boost.org/doc/libs/1_85_0/doc/html/date_time/date_time_io.html#date_time.format_flags
|
||||
: _("%B %d %Y, %H:%M");
|
||||
|
||||
ss << translation::strftime(format, std::localtime(&time));
|
||||
|
||||
return ss.str();
|
||||
if(time == std::chrono::system_clock::time_point{}) {
|
||||
return font::unicode_em_dash;
|
||||
}
|
||||
|
||||
return font::unicode_em_dash;
|
||||
const std::string format = prefs::get().use_twelve_hour_clock_format()
|
||||
// TRANSLATORS: Month + day of month + year + 12-hour time, eg 'November 02 2021, 1:59 PM'. Format for your locale.
|
||||
// Format reference: https://www.boost.org/doc/libs/1_85_0/doc/html/date_time/date_time_io.html#date_time.format_flags
|
||||
? _("%B %d %Y, %I:%M %p")
|
||||
// TRANSLATORS: Month + day of month + year + 24-hour time, eg 'November 02 2021, 13:59'. Format for your locale.
|
||||
// Format reference: https://www.boost.org/doc/libs/1_85_0/doc/html/date_time/date_time_io.html#date_time.format_flags
|
||||
: _("%B %d %Y, %H:%M");
|
||||
|
||||
auto as_time_t = std::chrono::system_clock::to_time_t(time);
|
||||
return translation::strftime(format, std::localtime(&as_time_t));
|
||||
}
|
||||
|
||||
void addon_manager::on_addon_select()
|
||||
|
|
32
src/serialization/chrono.hpp
Normal file
32
src/serialization/chrono.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright (C) 2024
|
||||
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config_attribute_value.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace chrono
|
||||
{
|
||||
inline auto parse_timestamp(const config_attribute_value& val)
|
||||
{
|
||||
return std::chrono::system_clock::from_time_t(val.to_long_long());
|
||||
}
|
||||
|
||||
inline auto serialize_timestamp(const std::chrono::system_clock::time_point& time)
|
||||
{
|
||||
return std::chrono::system_clock::to_time_t(time);
|
||||
}
|
||||
} // namespace chrono
|
|
@ -28,6 +28,7 @@
|
|||
#include "log.hpp"
|
||||
#include "serialization/base64.hpp"
|
||||
#include "serialization/binary_or_text.hpp"
|
||||
#include "serialization/chrono.hpp"
|
||||
#include "serialization/parser.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
#include "serialization/unicode.hpp"
|
||||
|
@ -344,7 +345,8 @@ void server::load_config()
|
|||
// Seems like compression level above 6 is a waste of CPU cycles.
|
||||
compress_level_ = cfg_["compress_level"].to_int(6);
|
||||
// One month probably will be fine (#TODO: testing needed)
|
||||
update_pack_lifespan_ = cfg_["update_pack_lifespan"].to_time_t(30 * 24 * 60 * 60);
|
||||
constexpr std::chrono::seconds seconds_in_a_month{30 * 24 * 60 * 60};
|
||||
update_pack_lifespan_ = cfg_["update_pack_lifespan"].to_duration(seconds_in_a_month);
|
||||
|
||||
const auto& svinfo_cfg = server_info();
|
||||
|
||||
|
@ -967,26 +969,32 @@ void server::handle_request_campaign_list(const server::request& req)
|
|||
{
|
||||
LOG_CS << req << "Sending add-ons list";
|
||||
|
||||
std::time_t epoch = std::time(nullptr);
|
||||
auto now = std::chrono::system_clock::now();
|
||||
const bool relative_to_now = req.cfg["times_relative_to"] == "now";
|
||||
|
||||
config addons_list;
|
||||
addons_list["timestamp"] = chrono::serialize_timestamp(now);
|
||||
|
||||
addons_list["timestamp"] = epoch;
|
||||
if(req.cfg["times_relative_to"] != "now") {
|
||||
epoch = 0;
|
||||
bool before_flag = !req.cfg["before"].empty();
|
||||
std::chrono::system_clock::time_point before;
|
||||
if(before_flag) {
|
||||
if(relative_to_now) {
|
||||
auto time_delta = req.cfg["before"].to_duration<std::chrono::seconds>();
|
||||
before = now + time_delta; // delta may be negative
|
||||
} else {
|
||||
before = chrono::parse_timestamp(req.cfg["before"]);
|
||||
}
|
||||
}
|
||||
|
||||
bool before_flag = false;
|
||||
std::time_t before = epoch;
|
||||
if(!req.cfg["before"].empty()) {
|
||||
before += req.cfg["before"].to_time_t();
|
||||
before_flag = true;
|
||||
}
|
||||
|
||||
bool after_flag = false;
|
||||
std::time_t after = epoch;
|
||||
if(!req.cfg["after"].empty()) {
|
||||
after += req.cfg["after"].to_time_t();
|
||||
after_flag = true;
|
||||
bool after_flag = !req.cfg["after"].empty();
|
||||
std::chrono::system_clock::time_point after;
|
||||
if(after_flag) {
|
||||
if(relative_to_now) {
|
||||
auto time_delta = req.cfg["after"].to_duration<std::chrono::seconds>();
|
||||
after = now + time_delta; // delta may be negative
|
||||
} else {
|
||||
after = chrono::parse_timestamp(req.cfg["after"]);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& name = req.cfg["name"];
|
||||
|
@ -1006,10 +1014,10 @@ void server::handle_request_campaign_list(const server::request& req)
|
|||
|
||||
const auto& tm = i["timestamp"];
|
||||
|
||||
if(before_flag && (tm.empty() || tm.to_time_t(0) >= before)) {
|
||||
if(before_flag && (tm.empty() || chrono::parse_timestamp(tm) >= before)) {
|
||||
continue;
|
||||
}
|
||||
if(after_flag && (tm.empty() || tm.to_time_t(0) <= after)) {
|
||||
if(after_flag && (tm.empty() || chrono::parse_timestamp(tm) <= after)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1473,7 +1481,7 @@ ADDON_CHECK_STATUS server::validate_addon(const server::request& req, config*& e
|
|||
|
||||
void server::handle_upload(const server::request& req)
|
||||
{
|
||||
const std::time_t upload_ts = std::time(nullptr);
|
||||
const auto upload_ts = std::chrono::system_clock::now();
|
||||
const config& upload = req.cfg;
|
||||
const auto& name = upload["name"].str();
|
||||
|
||||
|
@ -1501,7 +1509,7 @@ void server::handle_upload(const server::request& req)
|
|||
|
||||
if(!is_existing_upload) {
|
||||
// Create a new add-ons list entry and work with that from now on
|
||||
auto entry = addons_.emplace(name, config("original_timestamp", upload_ts));
|
||||
auto entry = addons_.emplace(name, config("original_timestamp", chrono::serialize_timestamp(upload_ts)));
|
||||
addon_ptr = &(*entry.first).second;
|
||||
}
|
||||
|
||||
|
@ -1530,7 +1538,7 @@ void server::handle_upload(const server::request& req)
|
|||
addon["downloads"] = 0;
|
||||
}
|
||||
|
||||
addon["timestamp"] = upload_ts;
|
||||
addon["timestamp"] = chrono::serialize_timestamp(upload_ts);
|
||||
addon["uploads"] = 1 + addon["uploads"].to_int();
|
||||
|
||||
addon.clear_children("feedback");
|
||||
|
@ -1651,7 +1659,7 @@ void server::handle_upload(const server::request& req)
|
|||
|
||||
pack_info["from"] = prev_version;
|
||||
pack_info["to"] = new_version;
|
||||
pack_info["expire"] = upload_ts + update_pack_lifespan_;
|
||||
pack_info["expire"] = chrono::serialize_timestamp(upload_ts + update_pack_lifespan_);
|
||||
pack_info["filename"] = update_pack_fn;
|
||||
|
||||
// Write the update pack to disk
|
||||
|
@ -1753,7 +1761,7 @@ void server::handle_upload(const server::request& req)
|
|||
std::set<std::string> expire_packs;
|
||||
|
||||
for(const config& pack : addon.child_range("update_pack")) {
|
||||
if(upload_ts > pack["expire"].to_time_t() || pack["from"].str() == new_version || (!is_delta_upload && pack["to"].str() == new_version)) {
|
||||
if(upload_ts > chrono::parse_timestamp(pack["expire"]) || pack["from"].str() == new_version || (!is_delta_upload && pack["to"].str() == new_version)) {
|
||||
LOG_CS << "Expiring upate pack for " << pack["from"].str() << " -> " << pack["to"].str();
|
||||
const auto& pack_filename = pack["filename"].str();
|
||||
filesystem::delete_file(pathstem + '/' + pack_filename);
|
||||
|
@ -1808,7 +1816,7 @@ void server::handle_upload(const server::request& req)
|
|||
config& pack_info = addon.add_child("update_pack");
|
||||
pack_info["from"] = prev_version_name;
|
||||
pack_info["to"] = next_version_name;
|
||||
pack_info["expire"] = upload_ts + update_pack_lifespan_;
|
||||
pack_info["expire"] = chrono::serialize_timestamp(upload_ts + update_pack_lifespan_);
|
||||
pack_info["filename"] = update_pack_fn;
|
||||
|
||||
// Generate the update pack from both full packs
|
||||
|
|
|
@ -115,7 +115,7 @@ private:
|
|||
|
||||
bool read_only_;
|
||||
int compress_level_; /**< Used for add-on archives. */
|
||||
time_t update_pack_lifespan_;
|
||||
std::chrono::seconds update_pack_lifespan_;
|
||||
|
||||
bool strict_versions_;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue