mirror of
https://github.com/CHN-beta/hpcstat.git
synced 2026-01-11 02:09:24 +08:00
完善校验功能
This commit is contained in:
@@ -17,7 +17,7 @@ namespace hpcstat::lfs
|
||||
else
|
||||
{
|
||||
std::set<std::string> valid_args = { "J", "q", "n", "R", "o" };
|
||||
for (auto it = args.begin(); it != args.end(); it++)
|
||||
for (auto it = args.begin(); it != args.end(); ++it)
|
||||
{
|
||||
if (it->length() > 0 && (*it)[0] == '-')
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace hpcstat::lfs
|
||||
"please submit issue on [github](https://github.com/CHN-beta/hpcstat) or contact chn@chn.moe.\n";
|
||||
return std::nullopt;
|
||||
}
|
||||
else if (it + 1 != args.end() && ((it + 1)->length() == 0 || (*(it + 1))[0] != '-')) it++;
|
||||
else if (it + 1 != args.end() && ((it + 1)->length() == 0 || (*(it + 1))[0] != '-')) ++it;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
17
src/main.cpp
17
src/main.cpp
@@ -1,3 +1,4 @@
|
||||
# include <thread>
|
||||
# include <hpcstat/sql.hpp>
|
||||
# include <hpcstat/ssh.hpp>
|
||||
# include <hpcstat/env.hpp>
|
||||
@@ -10,6 +11,7 @@
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
using namespace hpcstat;
|
||||
using namespace std::literals;
|
||||
std::vector<std::string> args(argv, argv + argc);
|
||||
|
||||
if (args.size() == 1) { std::cout << "Usage: hpcstat initdb|login|logout|submitjob|finishjob\n"; return 1; }
|
||||
@@ -20,6 +22,7 @@ int main(int argc, const char** argv)
|
||||
else if (args[1] == "login")
|
||||
{
|
||||
if (env::interactive()) std::cout << "Communicating with the agent..." << std::flush;
|
||||
std::this_thread::sleep_for(1s); // might silly but it tells everyone that we are doing something
|
||||
if (auto fp = ssh::fingerprint(); !fp) return 1;
|
||||
else if (auto session = env::env("XDG_SESSION_ID", true); !session)
|
||||
return 1;
|
||||
@@ -34,7 +37,8 @@ int main(int argc, const char** argv)
|
||||
if (!signature) return 1;
|
||||
data.Signature = *signature;
|
||||
sql::writedb(data);
|
||||
if (env::interactive()) std::cout << fmt::format("\33[2K\rLogged in as {}.\n", Keys[*fp].Username);
|
||||
if (env::interactive())
|
||||
std::cout << fmt::format("\33[2K\rLogged in as {} (fingerprint: SHA256:{}).\n", Keys[*fp].Username, *fp);
|
||||
}
|
||||
}
|
||||
else if (args[1] == "logout")
|
||||
@@ -94,7 +98,7 @@ int main(int argc, const char** argv)
|
||||
sql::FinishJobData data
|
||||
{
|
||||
.Time = now(), .JobId = jobid, .JobResult = std::get<1>(all_jobs->at(jobid)),
|
||||
.SubmitTime = std::get<0>(all_jobs->at(jobid)), .JobDetail = *detail,
|
||||
.SubmitTime = std::get<0>(all_jobs->at(jobid)), .JobDetail = *detail, .Key = *fp,
|
||||
.CpuTime = std::get<2>(all_jobs->at(jobid)),
|
||||
};
|
||||
if
|
||||
@@ -107,7 +111,14 @@ int main(int argc, const char** argv)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (args[1] == "verify")
|
||||
{
|
||||
if (args.size() < 4) { std::cerr << "Usage: hpcstat verify <old.db> <new.db>\n"; return 1; }
|
||||
if (auto db_verify_result = sql::verify(args[2], args[3]); !db_verify_result) return 1;
|
||||
else for (auto& data : *db_verify_result)
|
||||
if (!std::apply(ssh::verify, data))
|
||||
{ std::cerr << fmt::format("Failed to verify data: {}\n", std::get<0>(data)); return 1; }
|
||||
}
|
||||
else { std::cerr << "Unknown command.\n"; return 1; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
59
src/sql.cpp
59
src/sql.cpp
@@ -4,6 +4,8 @@
|
||||
# include <hpcstat/env.hpp>
|
||||
# include <range/v3/range.hpp>
|
||||
# include <range/v3/view.hpp>
|
||||
# include <nameof.hpp>
|
||||
# include <fmt/format.h>
|
||||
|
||||
namespace hpcstat::sql
|
||||
{
|
||||
@@ -17,9 +19,12 @@ namespace hpcstat::sql
|
||||
template std::string serialize(LoginData);
|
||||
template std::string serialize(SubmitJobData);
|
||||
template std::string serialize(FinishJobData);
|
||||
std::optional<zxorm::Connection<LoginTable, LogoutTable, SubmitJobTable, FinishJobTable>> connect()
|
||||
std::optional<zxorm::Connection<LoginTable, LogoutTable, SubmitJobTable, FinishJobTable>> connect
|
||||
(std::optional<std::string> dbfile = std::nullopt)
|
||||
{
|
||||
if (auto datadir = env::env("HPCSTAT_DATADIR", true); !datadir)
|
||||
if (dbfile) return std::make_optional<zxorm::Connection<LoginTable, LogoutTable, SubmitJobTable, FinishJobTable>>
|
||||
(dbfile->c_str());
|
||||
else if (auto datadir = env::env("HPCSTAT_DATADIR", true); !datadir)
|
||||
return std::nullopt;
|
||||
else
|
||||
{
|
||||
@@ -52,4 +57,54 @@ namespace hpcstat::sql
|
||||
return not_logged_job;
|
||||
}
|
||||
}
|
||||
std::optional<std::vector<std::tuple<std::string, std::string, std::string>>>
|
||||
verify(std::string old_db, std::string new_db)
|
||||
{
|
||||
auto old_conn = connect(old_db), new_conn = connect(new_db);
|
||||
if (!old_conn || !new_conn) { std::cerr << "Failed to connect to database.\n"; return std::nullopt; }
|
||||
else
|
||||
{
|
||||
auto check_one = [&]<typename T>()
|
||||
-> std::optional<std::vector<std::tuple<std::string, std::string, std::string>>>
|
||||
{
|
||||
auto old_query = old_conn->select_query<T>().many().exec(),
|
||||
new_query = new_conn->select_query<T>().many().exec();
|
||||
auto old_data_it = old_query.begin(), new_data_it = new_query.begin();
|
||||
for (; old_data_it != old_query.end() && new_data_it != new_query.end(); ++old_data_it, ++new_data_it)
|
||||
if (*old_data_it != *new_data_it)
|
||||
{
|
||||
std::cerr << fmt::format
|
||||
("Data mismatch: {} {} != {}.\n", nameof::nameof_type<T>(), (*old_data_it).Id, (*new_data_it).Id);
|
||||
return std::nullopt;
|
||||
}
|
||||
if (old_data_it != old_query.end() && new_data_it == new_query.end())
|
||||
{
|
||||
std::cerr << fmt::format("Data mismatch in {}.\n", nameof::nameof_type<T>());
|
||||
return std::nullopt;
|
||||
}
|
||||
else if constexpr (requires(T data) { data.Signature; })
|
||||
{
|
||||
std::vector<std::tuple<std::string, std::string, std::string>> diff;
|
||||
for (; old_data_it != old_query.end(); ++old_data_it)
|
||||
{
|
||||
auto data = *old_data_it;
|
||||
data.Signature = "";
|
||||
data.Id = 0;
|
||||
diff.push_back({ serialize(data), (*old_data_it).Signature, (*old_data_it).Key });
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
else return std::vector<std::tuple<std::string, std::string, std::string>>{};
|
||||
};
|
||||
auto check_many = [&]<typename T, typename... Ts>(auto&& self)
|
||||
-> std::optional<std::vector<std::tuple<std::string, std::string, std::string>>>
|
||||
{
|
||||
if (auto diff = check_one.operator()<T>(); !diff) return std::nullopt;
|
||||
else if constexpr (sizeof...(Ts) == 0) return diff;
|
||||
else if (auto diff2 = self.template operator()<Ts...>(self); !diff2) return std::nullopt;
|
||||
else { diff->insert(diff->end(), diff2->begin(), diff2->end()); return diff; }
|
||||
};
|
||||
return check_many.operator()<LoginData, LogoutData, SubmitJobData, FinishJobData>(check_many);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace hpcstat::ssh
|
||||
for
|
||||
(
|
||||
auto i = std::sregex_iterator(output->begin(), output->end(), pattern);
|
||||
i != std::sregex_iterator(); i++
|
||||
i != std::sregex_iterator(); ++i
|
||||
)
|
||||
if (Keys.contains(i->str(1))) return i->str(1);
|
||||
std::cerr << fmt::format("No valid fingerprint found in:\n{}\n", *output);
|
||||
|
||||
Reference in New Issue
Block a user