mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 05:21:29 +00:00
[Database] Database update improvements, content db and terminal checks (#3814)
* [Database] Database update improvements, content db and terminal checks * Update manifest entries with content flag * Update database_update_manifest.cpp
This commit is contained in:
parent
4c7016bd7b
commit
a0f2a8a743
@ -13,7 +13,6 @@ SET(common_sources
|
|||||||
crc32.cpp
|
crc32.cpp
|
||||||
database/database_dump_service.cpp
|
database/database_dump_service.cpp
|
||||||
database.cpp
|
database.cpp
|
||||||
database_conversions.cpp
|
|
||||||
database_instances.cpp
|
database_instances.cpp
|
||||||
database/database_update_manifest.cpp
|
database/database_update_manifest.cpp
|
||||||
database/database_update_manifest_bots.cpp
|
database/database_update_manifest_bots.cpp
|
||||||
|
|||||||
@ -226,11 +226,6 @@ public:
|
|||||||
|
|
||||||
void PurgeAllDeletedDataBuckets();
|
void PurgeAllDeletedDataBuckets();
|
||||||
|
|
||||||
/* Database Conversions 'database_conversions.cpp' */
|
|
||||||
|
|
||||||
bool CheckDatabaseConversions();
|
|
||||||
bool CheckDatabaseConvertCorpseDeblob();
|
|
||||||
bool CheckDatabaseConvertPPDeblob();
|
|
||||||
|
|
||||||
/* Database Variables */
|
/* Database Variables */
|
||||||
|
|
||||||
|
|||||||
@ -76,9 +76,9 @@ void DatabaseUpdate::CheckDbUpdates()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DatabaseUpdate::GetQueryResult(std::string query)
|
std::string DatabaseUpdate::GetQueryResult(const ManifestEntry& e)
|
||||||
{
|
{
|
||||||
auto results = m_database->QueryDatabase(query);
|
auto results = (e.content_schema_update ? m_content_database : m_database)->QueryDatabase(e.check);
|
||||||
|
|
||||||
std::vector<std::string> result_lines = {};
|
std::vector<std::string> result_lines = {};
|
||||||
|
|
||||||
@ -121,6 +121,16 @@ bool DatabaseUpdate::ShouldRunMigration(ManifestEntry &e, std::string query_resu
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if we are running in a terminal
|
||||||
|
bool is_atty()
|
||||||
|
{
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
return ::_isatty(_fileno(stdin));
|
||||||
|
#else
|
||||||
|
return isatty(fileno(stdin));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// return true if we ran updates
|
// return true if we ran updates
|
||||||
bool DatabaseUpdate::UpdateManifest(
|
bool DatabaseUpdate::UpdateManifest(
|
||||||
std::vector<ManifestEntry> entries,
|
std::vector<ManifestEntry> entries,
|
||||||
@ -136,7 +146,7 @@ bool DatabaseUpdate::UpdateManifest(
|
|||||||
for (auto &e: entries) {
|
for (auto &e: entries) {
|
||||||
if (e.version == version) {
|
if (e.version == version) {
|
||||||
bool has_migration = true;
|
bool has_migration = true;
|
||||||
std::string r = GetQueryResult(e.check);
|
std::string r = GetQueryResult(e);
|
||||||
if (ShouldRunMigration(e, r)) {
|
if (ShouldRunMigration(e, r)) {
|
||||||
has_migration = false;
|
has_migration = false;
|
||||||
missing_migrations.emplace_back(e.version);
|
missing_migrations.emplace_back(e.version);
|
||||||
@ -179,7 +189,7 @@ bool DatabaseUpdate::UpdateManifest(
|
|||||||
if (e.version == m) {
|
if (e.version == m) {
|
||||||
bool errored_migration = false;
|
bool errored_migration = false;
|
||||||
|
|
||||||
auto r = m_database->QueryDatabaseMulti(e.sql);
|
auto r = (e.content_schema_update ? m_content_database : m_database)->QueryDatabaseMulti(e.sql);
|
||||||
|
|
||||||
// ignore empty query result "errors"
|
// ignore empty query result "errors"
|
||||||
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
|
if (r.ErrorNumber() != 1065 && !r.ErrorMessage().empty()) {
|
||||||
@ -187,31 +197,38 @@ bool DatabaseUpdate::UpdateManifest(
|
|||||||
errored_migration = true;
|
errored_migration = true;
|
||||||
|
|
||||||
LogInfo("Required database update failed. This could be a problem");
|
LogInfo("Required database update failed. This could be a problem");
|
||||||
LogInfo("Would you like to skip this update? [y/n] (Timeout 60s)");
|
|
||||||
|
|
||||||
// user input
|
// if terminal attached then prompt for skip
|
||||||
std::string input;
|
if (is_atty()) {
|
||||||
bool gave_input = false;
|
LogInfo("Would you like to skip this update? [y/n] (Timeout 60s)");
|
||||||
time_t start_time = time(nullptr);
|
|
||||||
time_t wait_time_seconds = 60;
|
|
||||||
|
|
||||||
// spawn a concurrent thread that waits for input from std::cin
|
// user input
|
||||||
std::thread t1(
|
std::string input;
|
||||||
[&]() {
|
bool gave_input = false;
|
||||||
std::cin >> input;
|
time_t start_time = time(nullptr);
|
||||||
gave_input = true;
|
time_t wait_time_seconds = 60;
|
||||||
|
|
||||||
|
// spawn a concurrent thread that waits for input from std::cin
|
||||||
|
std::thread t1(
|
||||||
|
[&]() {
|
||||||
|
std::cin >> input;
|
||||||
|
gave_input = true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
t1.detach();
|
||||||
|
|
||||||
|
// check the inputReceived flag once every 50ms for 10 seconds
|
||||||
|
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||||
}
|
}
|
||||||
);
|
|
||||||
t1.detach();
|
|
||||||
|
|
||||||
// check the inputReceived flag once every 50ms for 10 seconds
|
// prompt for user skip
|
||||||
while (time(nullptr) < start_time + wait_time_seconds && !gave_input) {
|
if (Strings::Trim(input) == "y") {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
errored_migration = false;
|
||||||
}
|
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
|
||||||
|
}
|
||||||
// prompt for user skip
|
} else {
|
||||||
if (Strings::Trim(input) == "y") {
|
errored_migration = true;
|
||||||
errored_migration = false;
|
|
||||||
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
|
LogInfo("Skipping update [{}] [{}]", e.version, e.description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -247,6 +264,13 @@ DatabaseUpdate *DatabaseUpdate::SetDatabase(Database *db)
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DatabaseUpdate *DatabaseUpdate::SetContentDatabase(Database *db)
|
||||||
|
{
|
||||||
|
m_content_database = db;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
bool DatabaseUpdate::CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b)
|
||||||
{
|
{
|
||||||
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
LogInfo("{}", Strings::Repeat("-", BREAK_LENGTH));
|
||||||
|
|||||||
@ -10,6 +10,7 @@ struct ManifestEntry {
|
|||||||
std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
std::string condition{}; // condition or "match_type" - Possible values [contains|match|missing|empty|not_empty]
|
||||||
std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
std::string match{}; // match field that is not always used, but works in conjunction with "condition" values [missing|match|contains]
|
||||||
std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
std::string sql{}; // the SQL DDL that gets ran when the condition is true
|
||||||
|
bool content_schema_update{}; // if true, this migration is a content schema update and should be ran against the content database
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DatabaseVersion {
|
struct DatabaseVersion {
|
||||||
@ -22,14 +23,16 @@ public:
|
|||||||
DatabaseVersion GetDatabaseVersions();
|
DatabaseVersion GetDatabaseVersions();
|
||||||
DatabaseVersion GetBinaryDatabaseVersions();
|
DatabaseVersion GetBinaryDatabaseVersions();
|
||||||
void CheckDbUpdates();
|
void CheckDbUpdates();
|
||||||
std::string GetQueryResult(std::string query);
|
std::string GetQueryResult(const ManifestEntry& e);
|
||||||
static bool ShouldRunMigration(ManifestEntry &e, std::string query_result);
|
static bool ShouldRunMigration(ManifestEntry &e, std::string query_result);
|
||||||
bool UpdateManifest(std::vector<ManifestEntry> entries, int version_low, int version_high);
|
bool UpdateManifest(std::vector<ManifestEntry> entries, int version_low, int version_high);
|
||||||
|
|
||||||
DatabaseUpdate *SetDatabase(Database *db);
|
DatabaseUpdate *SetDatabase(Database *db);
|
||||||
|
DatabaseUpdate *SetContentDatabase(Database *db);
|
||||||
bool HasPendingUpdates();
|
bool HasPendingUpdates();
|
||||||
private:
|
private:
|
||||||
Database *m_database;
|
Database *m_database;
|
||||||
|
Database *m_content_database;
|
||||||
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
|
static bool CheckVersionsUpToDate(DatabaseVersion v, DatabaseVersion b);
|
||||||
void InjectBotsVersionColumn();
|
void InjectBotsVersionColumn();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5016,7 +5016,7 @@ CREATE TABLE `spawn2_disabled` (
|
|||||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
|
||||||
INSERT INTO spawn2_disabled (spawn2_id, disabled) SELECT id, 1 FROM spawn2 WHERE enabled = 0;
|
INSERT INTO spawn2_disabled (spawn2_id, disabled) SELECT id, 1 FROM spawn2 WHERE enabled = 0;
|
||||||
ALTER TABLE `spawn2` DROP COLUMN `enabled`;
|
ALTER TABLE `spawn2` DROP COLUMN `enabled`;
|
||||||
)"
|
)",
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9242,
|
.version = 9242,
|
||||||
@ -5028,7 +5028,8 @@ ALTER TABLE `spawn2` DROP COLUMN `enabled`;
|
|||||||
ALTER TABLE `spawnentry`
|
ALTER TABLE `spawnentry`
|
||||||
ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`,
|
ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`,
|
||||||
ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`;
|
ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9243,
|
.version = 9243,
|
||||||
@ -5082,7 +5083,8 @@ INSERT INTO
|
|||||||
|
|
||||||
DROP TABLE `starting_items`;
|
DROP TABLE `starting_items`;
|
||||||
RENAME TABLE `starting_items_new` TO `starting_items`;
|
RENAME TABLE `starting_items_new` TO `starting_items`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9244,
|
.version = 9244,
|
||||||
@ -5092,7 +5094,8 @@ RENAME TABLE `starting_items_new` TO `starting_items`;
|
|||||||
.match = "0000-00-00 00:00:00",
|
.match = "0000-00-00 00:00:00",
|
||||||
.sql = R"(
|
.sql = R"(
|
||||||
ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
|
ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9245,
|
.version = 9245,
|
||||||
@ -5104,7 +5107,8 @@ ALTER TABLE `items` MODIFY COLUMN `updated` datetime NULL DEFAULT NULL;
|
|||||||
ALTER TABLE `object` CHANGE COLUMN `unknown08` `size_percentage` float NOT NULL DEFAULT 0 AFTER `icon`;
|
ALTER TABLE `object` CHANGE COLUMN `unknown08` `size_percentage` float NOT NULL DEFAULT 0 AFTER `icon`;
|
||||||
ALTER TABLE `object` CHANGE COLUMN `unknown10` `solid_type` mediumint(5) NOT NULL DEFAULT 0 AFTER `size`;
|
ALTER TABLE `object` CHANGE COLUMN `unknown10` `solid_type` mediumint(5) NOT NULL DEFAULT 0 AFTER `size`;
|
||||||
ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAULT 0 AFTER `solid_type`;
|
ALTER TABLE `object` CHANGE COLUMN `unknown20` `incline` int(11) NOT NULL DEFAULT 0 AFTER `solid_type`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9246,
|
.version = 9246,
|
||||||
@ -5133,7 +5137,8 @@ CHANGE COLUMN `slot` `inventory_slot` mediumint(9) NOT NULL DEFAULT -1 AFTER `st
|
|||||||
|
|
||||||
ALTER TABLE `starting_items`
|
ALTER TABLE `starting_items`
|
||||||
CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`;
|
CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `id`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9248,
|
.version = 9248,
|
||||||
@ -5143,7 +5148,8 @@ CHANGE COLUMN `temporary` `class_list` text CHARACTER SET latin1 COLLATE latin1_
|
|||||||
.match = "",
|
.match = "",
|
||||||
.sql = R"(
|
.sql = R"(
|
||||||
ALTER TABLE `npc_emotes` DROP INDEX `emoteid`;
|
ALTER TABLE `npc_emotes` DROP INDEX `emoteid`;
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
},
|
},
|
||||||
ManifestEntry{
|
ManifestEntry{
|
||||||
.version = 9249,
|
.version = 9249,
|
||||||
@ -5154,7 +5160,8 @@ ALTER TABLE `npc_emotes` DROP INDEX `emoteid`;
|
|||||||
.sql = R"(
|
.sql = R"(
|
||||||
ALTER TABLE `tasks`
|
ALTER TABLE `tasks`
|
||||||
ADD COLUMN `enabled` smallint NULL DEFAULT 1 AFTER `faction_amount`
|
ADD COLUMN `enabled` smallint NULL DEFAULT 1 AFTER `faction_amount`
|
||||||
)"
|
)",
|
||||||
|
.content_schema_update = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- template; copy/paste this when you need to create a new entry
|
// -- template; copy/paste this when you need to create a new entry
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
#include "../common/global_define.h"
|
|
||||||
#include "../common/rulesys.h"
|
|
||||||
#include "../common/strings.h"
|
|
||||||
|
|
||||||
#include "database.h"
|
|
||||||
#include "database/database_update.h"
|
|
||||||
|
|
||||||
|
|
||||||
// Disgrace: for windows compile
|
|
||||||
#ifdef _WINDOWS
|
|
||||||
#include <windows.h>
|
|
||||||
#define snprintf _snprintf
|
|
||||||
#define strncasecmp _strnicmp
|
|
||||||
#define strcasecmp _stricmp
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "unix.h"
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#pragma pack(1)
|
|
||||||
|
|
||||||
DatabaseUpdate database_update;
|
|
||||||
|
|
||||||
bool Database::CheckDatabaseConversions()
|
|
||||||
{
|
|
||||||
auto *r = RuleManager::Instance();
|
|
||||||
r->LoadRules(this, "default", false);
|
|
||||||
if (!RuleB(Bots, Enabled) && DoesTableExist("bot_data")) {
|
|
||||||
LogInfo("Bot tables found but rule not enabled, enabling");
|
|
||||||
r->SetRule("Bots:Enabled", "true", this, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
database_update.SetDatabase(this)->CheckDbUpdates();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@ -9,5 +9,7 @@ void WorldserverCLI::DatabaseUpdates(int argc, char **argv, argh::parser &cmd, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
DatabaseUpdate update;
|
DatabaseUpdate update;
|
||||||
update.SetDatabase(&database)->CheckDbUpdates();
|
update.SetDatabase(&database)
|
||||||
|
->SetContentDatabase(&content_db)
|
||||||
|
->CheckDbUpdates();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
#include "../common/ip_util.h"
|
#include "../common/ip_util.h"
|
||||||
#include "../common/zone_store.h"
|
#include "../common/zone_store.h"
|
||||||
#include "../common/path_manager.h"
|
#include "../common/path_manager.h"
|
||||||
|
#include "../common/database/database_update.h"
|
||||||
|
|
||||||
extern ZSList zoneserver_list;
|
extern ZSList zoneserver_list;
|
||||||
extern WorldConfig Config;
|
extern WorldConfig Config;
|
||||||
@ -293,7 +294,18 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
|
|||||||
const auto c = EQEmuConfig::get();
|
const auto c = EQEmuConfig::get();
|
||||||
if (c->auto_database_updates) {
|
if (c->auto_database_updates) {
|
||||||
LogInfo("Checking Database Conversions");
|
LogInfo("Checking Database Conversions");
|
||||||
database.CheckDatabaseConversions();
|
|
||||||
|
auto *r = RuleManager::Instance();
|
||||||
|
r->LoadRules(&database, "default", false);
|
||||||
|
if (!RuleB(Bots, Enabled) && database.DoesTableExist("bot_data")) {
|
||||||
|
LogInfo("Bot tables found but rule not enabled, enabling");
|
||||||
|
r->SetRule("Bots:Enabled", "true", &database, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseUpdate update{};
|
||||||
|
update.SetDatabase(&database)
|
||||||
|
->SetContentDatabase(&content_db)
|
||||||
|
->CheckDbUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RuleB(Logging, WorldGMSayLogging)) {
|
if (RuleB(Logging, WorldGMSayLogging)) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user