Files
o3de/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.h
T
Chris Burel ce0bb1ca2b [AssetProcessor] Refactor the FileWatcher to use only one watch thread
This change reworks the AssetProcessor's FileWatcher so that it only uses
one thread. This is motivated by getting better support for inotify on
Linux. The previous architecture required calling `inotify_init` once for
each directory that was being watched, and using separate inotify instances
for each watched tree. In addition, having separate threads per watched
tree is not necessary, and just consumes system resources. Each platform
supports watching multiple directories with the same platform-specific
watcher API, so each platform has been updated accordingly.

The interface to the FileWatcher class is greatly simplified. Previously,
it supported client-supplied filtering of the paths that would generate
notifications. This was done by subclassing `FolderWatchBase` and
implementing `OnFileChange`. However, only one filter was ever used, so
that filter is now hard-coded in the FileWatcher class, and the classes
driving the old filtering mechanism are removed. Users of the interface
now have a much easier time, they just call `AddFolderWatch` with the path
to watch, and only have to connect to one set of signals, instead of
separate signals per watched directory.

Signed-off-by: Chris Burel <burelc@amazon.com>
2022-01-04 16:12:17 -08:00

249 lines
9.8 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/std/string/string.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/Debug/TraceMessageBus.h>
#include <AzToolsFramework/API/AssetDatabaseBus.h>
#include <native/FileWatcher/FileWatcher.h>
#include <native/utilities/ApplicationManager.h>
#include <native/utilities/AssetBuilderInfo.h>
#include <native/utilities/BuilderManager.h>
#endif
namespace AzToolsFramework
{
class ProcessWatcher;
class Ticker;
}
namespace AssetProcessor
{
class AssetCatalog;
class AssetProcessorManager;
class AssetRequestHandler;
class AssetScanner;
class AssetServerHandler;
class BuilderConfigurationManager;
class BuilderManager;
class ExternalModuleAssetBuilderInfo;
class FileProcessor;
class FileStateBase;
class FileStateCache;
class InternalAssetBuilderInfo;
class PlatformConfiguration;
class RCController;
class SettingsRegistryBuilder;
}
class ApplicationServer;
class ConnectionManager;
class ControlRequestHandler;
class ApplicationManagerBase
: public ApplicationManager
, public AssetBuilderSDK::AssetBuilderBus::Handler
, public AssetProcessor::AssetBuilderInfoBus::Handler
, public AssetProcessor::AssetBuilderRegistrationBus::Handler
, public AZ::Debug::TraceMessageBus::Handler
, protected AzToolsFramework::AssetDatabase::AssetDatabaseRequests::Bus::Handler
, public AssetProcessor::DiskSpaceInfoBus::Handler
, protected AzToolsFramework::SourceControlNotificationBus::Handler
{
Q_OBJECT
public:
explicit ApplicationManagerBase(int* argc, char*** argv, QObject* parent = 0);
virtual ~ApplicationManagerBase();
ApplicationManager::BeforeRunStatus BeforeRun() override;
void Destroy() override;
bool Run() override;
void HandleFileRelocation() const;
bool Activate() override;
bool PostActivate() override;
AssetProcessor::PlatformConfiguration* GetPlatformConfiguration() const;
AssetProcessor::AssetProcessorManager* GetAssetProcessorManager() const;
AssetProcessor::AssetScanner* GetAssetScanner() const;
AssetProcessor::RCController* GetRCController() const;
ConnectionManager* GetConnectionManager() const;
ApplicationServer* GetApplicationServer() const;
int ProcessedAssetCount() const;
int FailedAssetsCount() const;
void ResetProcessedAssetCount();
void ResetFailedAssetCount();
//! AssetBuilderSDK::AssetBuilderBus Interface
void RegisterBuilderInformation(const AssetBuilderSDK::AssetBuilderDesc& builderDesc) override;
void RegisterComponentDescriptor(AZ::ComponentDescriptor* descriptor) override;
void BuilderLog(const AZ::Uuid& builderId, const char* message, ...) override;
void BuilderLogV(const AZ::Uuid& builderId, const char* message, va_list list) override;
bool FindBuilderInformation(const AZ::Uuid& builderGuid, AssetBuilderSDK::AssetBuilderDesc& descriptionOut) override;
//! AssetBuilderSDK::InternalAssetBuilderBus Interface
void UnRegisterBuilderDescriptor(const AZ::Uuid& builderId) override;
//! AssetProcessor::AssetBuilderInfoBus Interface
void GetMatchingBuildersInfo(const AZStd::string& assetPath, AssetProcessor::BuilderInfoList& builderInfoList) override;
void GetAllBuildersInfo(AssetProcessor::BuilderInfoList& builderInfoList) override;
//! TraceMessageBus Interface
bool OnError(const char* window, const char* message) override;
//! DiskSpaceInfoBus::Handler
bool CheckSufficientDiskSpace(const QString& savePath, qint64 requiredSpace, bool shutdownIfInsufficient) override;
//! AzFramework::SourceControlNotificationBus::Handler
void ConnectivityStateChanged(const AzToolsFramework::SourceControlState newState) override;
void RemoveOldTempFolders();
void Rescan();
bool IsAssetProcessorManagerIdle() const override;
bool CheckFullIdle();
Q_SIGNALS:
void CheckAssetProcessorManagerIdleState();
void ConnectionStatusMsg(QString message);
void SourceControlReady();
void OnBuildersRegistered();
void AssetProcesserManagerIdleStateChange(bool isIdle);
void FullIdle(bool isIdle);
public Q_SLOTS:
void OnAssetProcessorManagerIdleState(bool isIdle);
protected:
virtual void InitAssetProcessorManager();//Deletion of assetProcessor Manager will be handled by the ThreadController
virtual void InitAssetCatalog();//Deletion of AssetCatalog will be handled when the ThreadController is deleted by the base ApplicationManager
virtual void InitRCController();
virtual void DestroyRCController();
virtual void InitAssetScanner();
virtual void DestroyAssetScanner();
virtual bool InitPlatformConfiguration();
virtual void DestroyPlatformConfiguration();
virtual void InitFileMonitor();
virtual void DestroyFileMonitor();
virtual bool InitBuilderConfiguration();
virtual void InitControlRequestHandler();
virtual void DestroyControlRequestHandler();
virtual bool InitApplicationServer() = 0;
void DestroyApplicationServer();
virtual void InitConnectionManager();
void DestroyConnectionManager();
void InitAssetRequestHandler(AssetProcessor::AssetRequestHandler* assetRequestHandler);
void InitFileStateCache();
void CreateQtApplication() override;
bool InitializeInternalBuilders();
void InitBuilderManager();
void ShutdownBuilderManager();
bool InitAssetDatabase();
void ShutDownAssetDatabase();
void InitAssetServerHandler();
void DestroyAssetServerHandler();
void InitFileProcessor();
void ShutDownFileProcessor();
virtual void InitSourceControl() = 0;
void InitInputThread();
void InputThread();
// Give an opportunity to derived classes to make connections before the application server starts listening
virtual void MakeActivationConnections() {}
virtual bool GetShouldExitOnIdle() const = 0;
virtual void TryScanProductDependencies() {}
virtual void TryHandleFileRelocation() {}
// IMPLEMENTATION OF -------------- AzToolsFramework::AssetDatabase::AssetDatabaseRequests::Bus::Listener
bool GetAssetDatabaseLocation(AZStd::string& location) override;
// ------------------------------------------------------------
AssetProcessor::AssetCatalog* GetAssetCatalog() const { return m_assetCatalog; }
ApplicationServer* m_applicationServer = nullptr;
ConnectionManager* m_connectionManager = nullptr;
// keep track of the critical loading point where we are loading other dlls so the error messages can be better.
bool m_isCurrentlyLoadingGems = false;
public Q_SLOTS:
void OnActiveJobsCountChanged(unsigned int count);
protected Q_SLOTS:
void CheckForIdle();
protected:
int m_processedAssetCount = 0;
int m_failedAssetsCount = 0;
int m_warningCount = 0;
int m_errorCount = 0;
bool m_AssetProcessorManagerIdleState = false;
bool m_sourceControlReady = false;
bool m_fullIdle = false;
FileWatcher m_fileWatcher;
AssetProcessor::PlatformConfiguration* m_platformConfiguration = nullptr;
AssetProcessor::AssetProcessorManager* m_assetProcessorManager = nullptr;
AssetProcessor::AssetCatalog* m_assetCatalog = nullptr;
AssetProcessor::AssetScanner* m_assetScanner = nullptr;
AssetProcessor::RCController* m_rcController = nullptr;
AssetProcessor::AssetRequestHandler* m_assetRequestHandler = nullptr;
AssetProcessor::BuilderManager* m_builderManager = nullptr;
AssetProcessor::AssetServerHandler* m_assetServerHandler = nullptr;
ControlRequestHandler* m_controlRequestHandler = nullptr;
AZStd::unique_ptr<AssetProcessor::FileStateBase> m_fileStateCache;
AZStd::unique_ptr<AssetProcessor::FileProcessor> m_fileProcessor;
AZStd::unique_ptr<AssetProcessor::BuilderConfigurationManager> m_builderConfig;
// The internal builders
AZStd::shared_ptr<AssetProcessor::InternalRecognizerBasedBuilder> m_internalBuilder;
AZStd::shared_ptr<AssetProcessor::SettingsRegistryBuilder> m_settingsRegistryBuilder;
bool m_builderRegistrationComplete = false;
// Builder description map based on the builder id
AZStd::unordered_map<AZ::Uuid, AssetBuilderSDK::AssetBuilderDesc> m_builderDescMap;
// Lookup for builder ids based on the name. The builder name must be unique
AZStd::unordered_map<AZStd::string, AZ::Uuid> m_builderNameToId;
// Builder pattern matchers to used to locate the builder descriptors that match a pattern
AZStd::list<AssetUtilities::BuilderFilePatternMatcher> m_matcherBuilderPatterns;
// Collection of all the external module builders
AZStd::list<AssetProcessor::ExternalModuleAssetBuilderInfo*> m_externalAssetBuilders;
AssetProcessor::ExternalModuleAssetBuilderInfo* m_currentExternalAssetBuilder = nullptr;
QAtomicInt m_connectionsAwaitingAssetCatalogSave = 0;
int m_remainingAPMJobs = 0;
bool m_assetProcessorManagerIsReady = false;
// When job priority and escalation is equal, jobs sort in order by job key.
// This switches that behavior to instead sort by the DB source name, which
// allows automated tests to get deterministic behavior out of Asset Processor.
bool m_sortJobsByDBSourceName = false;
unsigned int m_highestConnId = 0;
AzToolsFramework::Ticker* m_ticker = nullptr; // for ticking the tickbus.
QList<QMetaObject::Connection> m_connectionsToRemoveOnShutdown;
QString m_dependencyScanPattern;
QString m_fileDependencyScanPattern;
AZStd::vector<AZStd::string> m_dependencyAddtionalScanFolders;
int m_dependencyScanMaxIteration = AssetProcessor::MissingDependencyScanner::DefaultMaxScanIteration; // The maximum number of times to recurse when scanning a file for missing dependencies.
};