mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-23 14:03:34 +00:00
Address numerous bugs
DELETE CASCADE is not a valid SQL command so this was changed to a better delete statement. Added user confirmation before deleting a broken model. Address appending the string model appending bad data, causing excess deletion. Addressed memory leaks with sql::Blob
This commit is contained in:
parent
b434bf9e78
commit
c94909e4f5
@ -1,6 +1,7 @@
|
|||||||
#include "BrickByBrickFix.h"
|
#include "BrickByBrickFix.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "tinyxml2.h"
|
#include "tinyxml2.h"
|
||||||
@ -25,12 +26,14 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
|||||||
auto modelsToTruncate = GetModelsFromDatabase();
|
auto modelsToTruncate = GetModelsFromDatabase();
|
||||||
bool previousCommitValue = Database::GetAutoCommit();
|
bool previousCommitValue = Database::GetAutoCommit();
|
||||||
Database::SetAutoCommit(false);
|
Database::SetAutoCommit(false);
|
||||||
std::unique_ptr<sql::PreparedStatement> modelsToDelete(Database::CreatePreppedStmt("DELETE CASCADE FROM properties_contents WHERE ugc_id = ?;"));
|
std::unique_ptr<sql::PreparedStatement> modelsToDelete(
|
||||||
|
Database::CreatePreppedStmt(
|
||||||
|
"DELETE ugc, pc FROM ugc join properties_contents AS pc ON ugc.id = pc.ugc_id WHERE ugc.id = ?;"));
|
||||||
while (modelsToTruncate->next()) {
|
while (modelsToTruncate->next()) {
|
||||||
std::string completeUncompressedModel;
|
std::string completeUncompressedModel{};
|
||||||
uint32_t chunkCount{};
|
uint32_t chunkCount{};
|
||||||
uint64_t modelId = modelsToTruncate->getInt(1);
|
uint64_t modelId = modelsToTruncate->getInt(1);
|
||||||
auto modelAsSd0 = modelsToTruncate->getBlob(2);
|
std::unique_ptr<sql::Blob> modelAsSd0(modelsToTruncate->getBlob(2));
|
||||||
Game::logger->Log("BrickByBrickFix", "Checking brick-by-brick model %llu", modelId);
|
Game::logger->Log("BrickByBrickFix", "Checking brick-by-brick model %llu", modelId);
|
||||||
// Check that header is sd0 by checking for the sd0 magic.
|
// Check that header is sd0 by checking for the sd0 magic.
|
||||||
if (
|
if (
|
||||||
@ -49,6 +52,7 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
|||||||
compressedChunk[i] = modelAsSd0->get();
|
compressedChunk[i] = modelAsSd0->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ignore the valgrind warning about uninitialized values. These are discarded later when we know the actual uncompressed size.
|
||||||
std::unique_ptr<uint8_t[]> uncompressedChunk(new uint8_t[MAX_SD0_CHUNK_SIZE]);
|
std::unique_ptr<uint8_t[]> uncompressedChunk(new uint8_t[MAX_SD0_CHUNK_SIZE]);
|
||||||
int32_t err{};
|
int32_t err{};
|
||||||
int32_t actualUncompressedSize = ZCompression::Decompress(
|
int32_t actualUncompressedSize = ZCompression::Decompress(
|
||||||
@ -56,8 +60,9 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
|||||||
|
|
||||||
if (actualUncompressedSize != -1) {
|
if (actualUncompressedSize != -1) {
|
||||||
Game::logger->Log("BrickByBrickFix", "Chunk %i inflated successfully", chunkCount);
|
Game::logger->Log("BrickByBrickFix", "Chunk %i inflated successfully", chunkCount);
|
||||||
|
uint32_t previousSize = completeUncompressedModel.size();
|
||||||
completeUncompressedModel.append((char*)uncompressedChunk.get());
|
completeUncompressedModel.append((char*)uncompressedChunk.get());
|
||||||
completeUncompressedModel.shrink_to_fit();
|
completeUncompressedModel.resize(previousSize + actualUncompressedSize);
|
||||||
} else {
|
} else {
|
||||||
Game::logger->Log("BrickByBrickFix", "Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, modelId, err);
|
Game::logger->Log("BrickByBrickFix", "Failed to inflate chunk %i for model %llu. Error: %i", chunkCount, modelId, err);
|
||||||
break;
|
break;
|
||||||
@ -73,12 +78,20 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
|||||||
if (document->Parse(completeUncompressedModel.c_str(), completeUncompressedModel.size()) == tinyxml2::XML_SUCCESS) {
|
if (document->Parse(completeUncompressedModel.c_str(), completeUncompressedModel.size()) == tinyxml2::XML_SUCCESS) {
|
||||||
Game::logger->Log("BrickByBrickFix", "Model %llu is a valid brick-by-brick model!", modelId);
|
Game::logger->Log("BrickByBrickFix", "Model %llu is a valid brick-by-brick model!", modelId);
|
||||||
} else {
|
} else {
|
||||||
|
Game::logger->Log(
|
||||||
|
"BrickByBrickFix", "Potentially invalid lxfml found. Last 10 characters are ||%s||."
|
||||||
|
"If the string between the bars does not end in </LXFML> then press y and enter.",
|
||||||
|
completeUncompressedModel.substr(completeUncompressedModel.length() - 15).c_str());
|
||||||
|
std::string response;
|
||||||
|
std::cin >> response;
|
||||||
|
if (strcmp(response.c_str(), "y") == 0) {
|
||||||
Game::logger->Log("BrickByBrickFix",
|
Game::logger->Log("BrickByBrickFix",
|
||||||
"Model %llu is an invalid brick-by-brick model and will be deleted!", modelId);
|
"Brick-by-brick model %llu will be deleted!", modelId);
|
||||||
modelsToDelete->setInt64(1, modelsToTruncate->getInt64(1));
|
modelsToDelete->setInt64(1, modelsToTruncate->getInt64(1));
|
||||||
modelsToDelete->addBatch();
|
modelsToDelete->addBatch();
|
||||||
modelsTruncated++;
|
modelsTruncated++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Game::logger->Log("BrickByBrickFix",
|
Game::logger->Log("BrickByBrickFix",
|
||||||
"Aborting truncation. Update models to use sd0 through UpdateOldModels.");
|
"Aborting truncation. Update models to use sd0 through UpdateOldModels.");
|
||||||
@ -92,7 +105,7 @@ uint32_t BrickByBrickFix::TruncateBrokenBrickByBrickXml() {
|
|||||||
"encountered error truncating models. Not truncating models. Error is: %s", error.what());
|
"encountered error truncating models. Not truncating models. Error is: %s", error.what());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Game::logger->Log("BrickByBrickFix", "Successfully executed batch deletion. Commiting...");
|
Game::logger->Log("BrickByBrickFix", "Successfully executed batch deletion of %i models. Commiting to database...", modelsTruncated);
|
||||||
Database::Commit();
|
Database::Commit();
|
||||||
Database::SetAutoCommit(previousCommitValue);
|
Database::SetAutoCommit(previousCommitValue);
|
||||||
return modelsTruncated;
|
return modelsTruncated;
|
||||||
@ -111,8 +124,8 @@ uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
|
|||||||
Database::SetAutoCommit(false);
|
Database::SetAutoCommit(false);
|
||||||
std::unique_ptr<sql::PreparedStatement> insertionStatement(Database::CreatePreppedStmt("UPDATE ugc SET lxfml = ? WHERE id = ?;"));
|
std::unique_ptr<sql::PreparedStatement> insertionStatement(Database::CreatePreppedStmt("UPDATE ugc SET lxfml = ? WHERE id = ?;"));
|
||||||
while (modelsToUpdate->next()) {
|
while (modelsToUpdate->next()) {
|
||||||
uint32_t modelId = modelsToUpdate->getInt(1);
|
int64_t modelId = modelsToUpdate->getInt64(1);
|
||||||
auto oldLxfml = modelsToUpdate->getBlob(2);
|
std::unique_ptr<sql::Blob> oldLxfml(modelsToUpdate->getBlob(2));
|
||||||
// Check if the stored blob starts with zlib magic (0x78 0xDA - best compression of zlib)
|
// Check if the stored blob starts with zlib magic (0x78 0xDA - best compression of zlib)
|
||||||
// If it does, convert it to sd0.
|
// If it does, convert it to sd0.
|
||||||
if (oldLxfml->get() == 0x78 && oldLxfml->get() == 0xDA) {
|
if (oldLxfml->get() == 0x78 && oldLxfml->get() == 0xDA) {
|
||||||
@ -125,7 +138,7 @@ uint32_t BrickByBrickFix::UpdateBrickByBrickModelsToSd0() {
|
|||||||
|
|
||||||
// Allocate 9 extra bytes. 5 for sd0 magic, 4 for the only zlib compressed size.
|
// Allocate 9 extra bytes. 5 for sd0 magic, 4 for the only zlib compressed size.
|
||||||
uint32_t oldLxfmlSizeWithHeader = oldLxfmlSize + 9;
|
uint32_t oldLxfmlSizeWithHeader = oldLxfmlSize + 9;
|
||||||
std::unique_ptr<char> sd0ConvertedModel(new char[oldLxfmlSizeWithHeader]);
|
std::unique_ptr<char[]> sd0ConvertedModel(new char[oldLxfmlSizeWithHeader]);
|
||||||
|
|
||||||
WriteSd0Magic(sd0ConvertedModel.get(), oldLxfmlSize);
|
WriteSd0Magic(sd0ConvertedModel.get(), oldLxfmlSize);
|
||||||
for (uint32_t i = 9; i < oldLxfmlSizeWithHeader; i++) {
|
for (uint32_t i = 9; i < oldLxfmlSizeWithHeader; i++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user