GH-1927 Add more specific task status logging
* Tasks are now described by class name and object name (or memory address). * Tasks starts are logged. * Aborted tasks are now treated just as the other cases.
This commit is contained in:
		| @@ -9,9 +9,9 @@ | ||||
|  | ||||
| typedef std::shared_ptr<class SkinUpload> SkinUploadPtr; | ||||
|  | ||||
| class MULTIMC_LOGIC_EXPORT SkinUpload : public Task\ | ||||
| class MULTIMC_LOGIC_EXPORT SkinUpload : public Task | ||||
| { | ||||
| Q_OBJECT | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	enum Model | ||||
| 	{ | ||||
|   | ||||
| @@ -95,85 +95,87 @@ shared_qobject_ptr<Task> LegacyInstance::createUpdateTask() | ||||
| 	return shared_qobject_ptr<Task>(new LegacyUpdate(this, this)); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<Task> LegacyInstance::createJarModdingTask() | ||||
| class LegacyJarModTask : public Task | ||||
| { | ||||
| 	class JarModTask : public Task | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	explicit LegacyJarModTask(std::shared_ptr<LegacyInstance> inst) : Task(nullptr), m_inst(inst) | ||||
| 	{ | ||||
| 	public: | ||||
| 		explicit JarModTask(std::shared_ptr<LegacyInstance> inst) : Task(nullptr), m_inst(inst) | ||||
| 	} | ||||
| 	virtual void executeTask() | ||||
| 	{ | ||||
| 		if (!m_inst->shouldRebuild()) | ||||
| 		{ | ||||
| 			emitSucceeded(); | ||||
| 			return; | ||||
| 		} | ||||
| 		virtual void executeTask() | ||||
|  | ||||
| 		// Get the mod list | ||||
| 		auto modList = m_inst->getJarMods(); | ||||
|  | ||||
| 		QFileInfo runnableJar(m_inst->runnableJar()); | ||||
| 		QFileInfo baseJar(m_inst->baseJar()); | ||||
| 		bool base_is_custom = m_inst->shouldUseCustomBaseJar(); | ||||
|  | ||||
| 		// Nothing to do if there are no jar mods to install, no backup and just the mc jar | ||||
| 		if (base_is_custom) | ||||
| 		{ | ||||
| 			if (!m_inst->shouldRebuild()) | ||||
| 			// yes, this can happen if the instance only has the runnable jar and not the base jar | ||||
| 			// it *could* be assumed that such an instance is vanilla, but that wouldn't be safe | ||||
| 			// because that's not something mmc4 guarantees | ||||
| 			if (runnableJar.isFile() && !baseJar.exists() && modList.empty()) | ||||
| 			{ | ||||
| 				m_inst->setShouldRebuild(false); | ||||
| 				emitSucceeded(); | ||||
| 				return; | ||||
| 			} | ||||
|  | ||||
| 			// Get the mod list | ||||
| 			auto modList = m_inst->getJarMods(); | ||||
|  | ||||
| 			QFileInfo runnableJar(m_inst->runnableJar()); | ||||
| 			QFileInfo baseJar(m_inst->baseJar()); | ||||
| 			bool base_is_custom = m_inst->shouldUseCustomBaseJar(); | ||||
|  | ||||
| 			// Nothing to do if there are no jar mods to install, no backup and just the mc jar | ||||
| 			if (base_is_custom) | ||||
| 			setStatus(tr("Installing mods: Backing up minecraft.jar ...")); | ||||
| 			if (!baseJar.exists() && !QFile::copy(runnableJar.filePath(), baseJar.filePath())) | ||||
| 			{ | ||||
| 				// yes, this can happen if the instance only has the runnable jar and not the base jar | ||||
| 				// it *could* be assumed that such an instance is vanilla, but that wouldn't be safe | ||||
| 				// because that's not something mmc4 guarantees | ||||
| 				if (runnableJar.isFile() && !baseJar.exists() && modList.empty()) | ||||
| 				{ | ||||
| 					m_inst->setShouldRebuild(false); | ||||
| 					emitSucceeded(); | ||||
| 					return; | ||||
| 				} | ||||
|  | ||||
| 				setStatus(tr("Installing mods: Backing up minecraft.jar ...")); | ||||
| 				if (!baseJar.exists() && !QFile::copy(runnableJar.filePath(), baseJar.filePath())) | ||||
| 				{ | ||||
| 					emitFailed("It seems both the active and base jar are gone. A fresh base jar will " | ||||
| 							"be used on next run."); | ||||
| 					m_inst->setShouldRebuild(true); | ||||
| 					m_inst->setShouldUpdate(true); | ||||
| 					m_inst->setShouldUseCustomBaseJar(false); | ||||
| 					return; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (!baseJar.exists()) | ||||
| 			{ | ||||
| 				emitFailed("The base jar " + baseJar.filePath() + " does not exist"); | ||||
| 				emitFailed("It seems both the active and base jar are gone. A fresh base jar will " | ||||
| 						"be used on next run."); | ||||
| 				m_inst->setShouldRebuild(true); | ||||
| 				m_inst->setShouldUpdate(true); | ||||
| 				m_inst->setShouldUseCustomBaseJar(false); | ||||
| 				return; | ||||
| 			} | ||||
|  | ||||
| 			if (runnableJar.exists() && !QFile::remove(runnableJar.filePath())) | ||||
| 			{ | ||||
| 				emitFailed("Failed to delete old minecraft.jar"); | ||||
| 				return; | ||||
| 			} | ||||
|  | ||||
| 			setStatus(tr("Installing mods: Opening minecraft.jar ...")); | ||||
|  | ||||
| 			QString outputJarPath = runnableJar.filePath(); | ||||
| 			QString inputJarPath = baseJar.filePath(); | ||||
|  | ||||
| 			if(!MMCZip::createModdedJar(inputJarPath, outputJarPath, modList)) | ||||
| 			{ | ||||
| 				emitFailed(tr("Failed to create the custom Minecraft jar file.")); | ||||
| 				return; | ||||
| 			} | ||||
| 			m_inst->setShouldRebuild(false); | ||||
| 			// inst->UpdateVersion(true); | ||||
| 			emitSucceeded(); | ||||
| 			return; | ||||
|  | ||||
| 		} | ||||
| 		std::shared_ptr<LegacyInstance> m_inst; | ||||
| 	}; | ||||
| 	return std::make_shared<JarModTask>(std::dynamic_pointer_cast<LegacyInstance>(shared_from_this())); | ||||
|  | ||||
| 		if (!baseJar.exists()) | ||||
| 		{ | ||||
| 			emitFailed("The base jar " + baseJar.filePath() + " does not exist"); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		if (runnableJar.exists() && !QFile::remove(runnableJar.filePath())) | ||||
| 		{ | ||||
| 			emitFailed("Failed to delete old minecraft.jar"); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		setStatus(tr("Installing mods: Opening minecraft.jar ...")); | ||||
|  | ||||
| 		QString outputJarPath = runnableJar.filePath(); | ||||
| 		QString inputJarPath = baseJar.filePath(); | ||||
|  | ||||
| 		if(!MMCZip::createModdedJar(inputJarPath, outputJarPath, modList)) | ||||
| 		{ | ||||
| 			emitFailed(tr("Failed to create the custom Minecraft jar file.")); | ||||
| 			return; | ||||
| 		} | ||||
| 		m_inst->setShouldRebuild(false); | ||||
| 		// inst->UpdateVersion(true); | ||||
| 		emitSucceeded(); | ||||
| 		return; | ||||
|  | ||||
| 	} | ||||
| 	std::shared_ptr<LegacyInstance> m_inst; | ||||
| }; | ||||
|  | ||||
| std::shared_ptr<Task> LegacyInstance::createJarModdingTask() | ||||
| { | ||||
| 	return std::make_shared<LegacyJarModTask>(std::dynamic_pointer_cast<LegacyInstance>(shared_from_this())); | ||||
| } | ||||
|  | ||||
| QString LegacyInstance::createLaunchScript(AuthSessionPtr session) | ||||
| @@ -515,3 +517,5 @@ QStringList LegacyInstance::processMinecraftArgs(AuthSessionPtr account) const | ||||
| 	out.append(account->session); | ||||
| 	return out; | ||||
| } | ||||
|  | ||||
| #include "LegacyInstance.moc" | ||||
|   | ||||
| @@ -368,53 +368,54 @@ std::shared_ptr<LaunchStep> OneSixInstance::createMainLaunchStep(LaunchTask * pa | ||||
| 	return nullptr; | ||||
| } | ||||
|  | ||||
| class JarModTask : public Task | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	explicit JarModTask(std::shared_ptr<OneSixInstance> inst) : Task(nullptr), m_inst(inst) | ||||
| 	{ | ||||
| 	} | ||||
| 	virtual void executeTask() | ||||
| 	{ | ||||
| 		auto profile = m_inst->getMinecraftProfile(); | ||||
| 		// nuke obsolete stripped jar(s) if needed | ||||
| 		QString version_id = profile->getMinecraftVersion(); | ||||
| 		if(!FS::ensureFolderPathExists(m_inst->binRoot())) | ||||
| 		{ | ||||
| 			emitFailed(tr("Couldn't create the bin folder for Minecraft.jar")); | ||||
| 		} | ||||
| 		auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar"); | ||||
| 		QFile finalJar(finalJarPath); | ||||
| 		if(finalJar.exists()) | ||||
| 		{ | ||||
| 			if(!finalJar.remove()) | ||||
| 			{ | ||||
| 				emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath)); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// create temporary modded jar, if needed | ||||
| 		auto jarMods = m_inst->getJarMods(); | ||||
| 		if(jarMods.size()) | ||||
| 		{ | ||||
| 			auto mainJar = profile->getMainJar(); | ||||
| 			QStringList jars, temp1, temp2, temp3, temp4; | ||||
| 			mainJar->getApplicableFiles(currentSystem, jars, temp1, temp2, temp3, m_inst->getLocalLibraryPath()); | ||||
| 			auto sourceJarPath = jars[0]; | ||||
| 			if(!MMCZip::createModdedJar(sourceJarPath, finalJarPath, jarMods)) | ||||
| 			{ | ||||
| 				emitFailed(tr("Failed to create the custom Minecraft jar file.")); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 		emitSucceeded(); | ||||
| 	} | ||||
| 	std::shared_ptr<OneSixInstance> m_inst; | ||||
| }; | ||||
|  | ||||
| std::shared_ptr<Task> OneSixInstance::createJarModdingTask() | ||||
| { | ||||
| 	class JarModTask : public Task | ||||
| 	{ | ||||
| 	public: | ||||
| 		explicit JarModTask(std::shared_ptr<OneSixInstance> inst) : Task(nullptr), m_inst(inst) | ||||
| 		{ | ||||
| 		} | ||||
| 		virtual void executeTask() | ||||
| 		{ | ||||
| 			auto profile = m_inst->getMinecraftProfile(); | ||||
| 			// nuke obsolete stripped jar(s) if needed | ||||
| 			QString version_id = profile->getMinecraftVersion(); | ||||
| 			if(!FS::ensureFolderPathExists(m_inst->binRoot())) | ||||
| 			{ | ||||
| 				emitFailed(tr("Couldn't create the bin folder for Minecraft.jar")); | ||||
| 			} | ||||
| 			auto finalJarPath = QDir(m_inst->binRoot()).absoluteFilePath("minecraft.jar"); | ||||
| 			QFile finalJar(finalJarPath); | ||||
| 			if(finalJar.exists()) | ||||
| 			{ | ||||
| 				if(!finalJar.remove()) | ||||
| 				{ | ||||
| 					emitFailed(tr("Couldn't remove stale jar file: %1").arg(finalJarPath)); | ||||
| 					return; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// create temporary modded jar, if needed | ||||
| 			auto jarMods = m_inst->getJarMods(); | ||||
| 			if(jarMods.size()) | ||||
| 			{ | ||||
| 				auto mainJar = profile->getMainJar(); | ||||
| 				QStringList jars, temp1, temp2, temp3, temp4; | ||||
| 				mainJar->getApplicableFiles(currentSystem, jars, temp1, temp2, temp3, m_inst->getLocalLibraryPath()); | ||||
| 				auto sourceJarPath = jars[0]; | ||||
| 				if(!MMCZip::createModdedJar(sourceJarPath, finalJarPath, jarMods)) | ||||
| 				{ | ||||
| 					emitFailed(tr("Failed to create the custom Minecraft jar file.")); | ||||
| 					return; | ||||
| 				} | ||||
| 			} | ||||
| 			emitSucceeded(); | ||||
| 		} | ||||
| 		std::shared_ptr<OneSixInstance> m_inst; | ||||
| 	}; | ||||
| 	return std::make_shared<JarModTask>(std::dynamic_pointer_cast<OneSixInstance>(shared_from_this())); | ||||
| } | ||||
|  | ||||
| @@ -696,3 +697,5 @@ QStringList OneSixInstance::getNativeJars() const | ||||
| 	m_profile->getLibraryFiles(javaArchitecture, jars, nativeJars, getLocalLibraryPath(), binRoot()); | ||||
| 	return nativeJars; | ||||
| } | ||||
|  | ||||
| #include "OneSixInstance.moc" | ||||
|   | ||||
| @@ -142,11 +142,21 @@ void OneSixUpdate::next() | ||||
|  | ||||
| void OneSixUpdate::subtaskSucceeded() | ||||
| { | ||||
| 	if(isFinished()) | ||||
| 	{ | ||||
| 		qCritical() << "OneSixUpdate: Subtask" << sender() << "succeeded, but work was already done!"; | ||||
| 		return; | ||||
| 	} | ||||
| 	next(); | ||||
| } | ||||
|  | ||||
| void OneSixUpdate::subtaskFailed(QString error) | ||||
| { | ||||
| 	if(isFinished()) | ||||
| 	{ | ||||
| 		qCritical() << "OneSixUpdate: Subtask" << sender() << "failed, but work was already done!"; | ||||
| 		return; | ||||
| 	} | ||||
| 	emitFailed(error); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ class OneSixInstance; | ||||
|  | ||||
| class AssetUpdateTask : public Task | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	AssetUpdateTask(OneSixInstance * inst); | ||||
| 	void executeTask() override; | ||||
|   | ||||
| @@ -5,6 +5,7 @@ class OneSixInstance; | ||||
|  | ||||
| class FMLLibrariesTask : public Task | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	FMLLibrariesTask(OneSixInstance * inst); | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include <QDir> | ||||
|  | ||||
| FoldersTask::FoldersTask(OneSixInstance * inst) | ||||
| 	:Task() | ||||
| { | ||||
| 	m_inst = inst; | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| class OneSixInstance; | ||||
| class FoldersTask : public Task | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	FoldersTask(OneSixInstance * inst); | ||||
| 	void executeTask() override; | ||||
|   | ||||
| @@ -5,6 +5,7 @@ class OneSixInstance; | ||||
|  | ||||
| class LibrariesTask : public Task | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	LibrariesTask(OneSixInstance * inst); | ||||
|  | ||||
|   | ||||
| @@ -94,7 +94,6 @@ void NetJob::partProgress(int index, qint64 bytesReceived, qint64 bytesTotal) | ||||
|  | ||||
| void NetJob::executeTask() | ||||
| { | ||||
| 	qDebug() << m_job_name.toLocal8Bit() << " started."; | ||||
| 	// hack that delays early failures so they can be caught easier | ||||
| 	QMetaObject::invokeMethod(this, "startMoreParts", Qt::QueuedConnection); | ||||
| } | ||||
| @@ -114,18 +113,15 @@ void NetJob::startMoreParts() | ||||
| 		{ | ||||
| 			if(!m_failed.size()) | ||||
| 			{ | ||||
| 				qDebug() << m_job_name << "succeeded."; | ||||
| 				emitSucceeded(); | ||||
| 			} | ||||
| 			else if(m_aborted) | ||||
| 			{ | ||||
| 				qDebug() << m_job_name << "aborted."; | ||||
| 				emitFailed(tr("Job '%1' aborted.").arg(m_job_name)); | ||||
| 				emitAborted(); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				qCritical() << m_job_name << "failed."; | ||||
| 				emitFailed(tr("Job '%1' failed to process:\n%2").arg(m_job_name).arg(getFailedFiles().join("\n"))); | ||||
| 				emitFailed(tr("Job '%1' failed to process:\n%2").arg(objectName()).arg(getFailedFiles().join("\n"))); | ||||
| 			} | ||||
| 		} | ||||
| 		return; | ||||
|   | ||||
| @@ -30,7 +30,10 @@ class MULTIMC_LOGIC_EXPORT NetJob : public Task | ||||
| { | ||||
| 	Q_OBJECT | ||||
| public: | ||||
| 	explicit NetJob(QString job_name) : Task(), m_job_name(job_name) {} | ||||
| 	explicit NetJob(QString job_name) : Task() | ||||
| 	{ | ||||
| 		setObjectName(job_name); | ||||
| 	} | ||||
| 	virtual ~NetJob() {} | ||||
|  | ||||
| 	bool addNetAction(NetActionPtr action); | ||||
| @@ -77,7 +80,6 @@ private: | ||||
| 		qint64 total_progress = 1; | ||||
| 		int failures = 0; | ||||
| 	}; | ||||
| 	QString m_job_name; | ||||
| 	QList<NetActionPtr> downloads; | ||||
| 	QList<part_info> parts_progress; | ||||
| 	QQueue<int> m_todo; | ||||
|   | ||||
| @@ -41,31 +41,79 @@ void Task::start() | ||||
| { | ||||
| 	m_running = true; | ||||
| 	emit started(); | ||||
| 	qDebug() << "Task" << describe() << "started"; | ||||
| 	executeTask(); | ||||
| } | ||||
|  | ||||
| void Task::emitFailed(QString reason) | ||||
| { | ||||
| 	// Don't fail twice. | ||||
| 	if (!m_running) | ||||
| 	{ | ||||
| 		qCritical() << "Task" << describe() << "failed while not running!!!!: " << reason; | ||||
| 		return; | ||||
| 	} | ||||
| 	m_running = false; | ||||
| 	m_finished = true; | ||||
| 	m_succeeded = false; | ||||
| 	m_failReason = reason; | ||||
| 	qCritical() << "Task failed: " << reason; | ||||
| 	qCritical() << "Task" << describe() << "failed: " << reason; | ||||
| 	emit failed(reason); | ||||
| 	emit finished(); | ||||
| } | ||||
|  | ||||
| void Task::emitAborted() | ||||
| { | ||||
| 	// Don't abort twice. | ||||
| 	if (!m_running) | ||||
| 	{ | ||||
| 		qCritical() << "Task" << describe() << "aborted while not running!!!!"; | ||||
| 		return; | ||||
| 	} | ||||
| 	m_running = false; | ||||
| 	m_finished = true; | ||||
| 	m_succeeded = false; | ||||
| 	m_failReason = "Aborted."; | ||||
| 	qDebug() << "Task" << describe() << "aborted."; | ||||
| 	emit failed(m_failReason); | ||||
| 	emit finished(); | ||||
| } | ||||
|  | ||||
| void Task::emitSucceeded() | ||||
| { | ||||
| 	if (!m_running) { return; } // Don't succeed twice. | ||||
| 	// Don't succeed twice. | ||||
| 	if (!m_running) | ||||
| 	{ | ||||
| 		qCritical() << "Task" << describe() << "succeeded while not running!!!!"; | ||||
| 		return; | ||||
| 	} | ||||
| 	m_running = false; | ||||
| 	m_finished = true; | ||||
| 	m_succeeded = true; | ||||
| 	qDebug() << "Task succeeded"; | ||||
| 	qDebug() << "Task" << describe() << "succeeded"; | ||||
| 	emit succeeded(); | ||||
| 	emit finished(); | ||||
| } | ||||
|  | ||||
| QString Task::describe() | ||||
| { | ||||
| 	QString outStr; | ||||
| 	QTextStream out(&outStr); | ||||
| 	out << metaObject()->className() << QChar('('); | ||||
| 	auto name = objectName(); | ||||
| 	if(name.isEmpty()) | ||||
| 	{ | ||||
| 		out << QString("0x%1").arg((quintptr)this, 0, 16); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		out << name; | ||||
| 	} | ||||
| 	out << QChar(')'); | ||||
| 	out.flush(); | ||||
| 	return outStr; | ||||
| } | ||||
|  | ||||
| bool Task::isRunning() const | ||||
| { | ||||
| 	return m_running; | ||||
|   | ||||
| @@ -54,6 +54,9 @@ public: | ||||
| 		return m_progressTotal; | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	QString describe(); | ||||
|  | ||||
| signals: | ||||
| 	void started(); | ||||
| 	void progress(qint64 current, qint64 total); | ||||
| @@ -71,6 +74,7 @@ protected: | ||||
|  | ||||
| protected slots: | ||||
| 	virtual void emitSucceeded(); | ||||
| 	virtual void emitAborted(); | ||||
| 	virtual void emitFailed(QString reason); | ||||
|  | ||||
| public slots: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user