Builder.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <AzCore/std/string/string.h>
  10. #include <AzCore/std/parallel/binary_semaphore.h>
  11. #include <utilities/assetUtils.h>
  12. #include <AzFramework/Process/ProcessWatcher.h>
  13. #include <AzFramework/Process/ProcessCommunicatorTracePrinter.h>
  14. namespace AssetProcessor
  15. {
  16. //! Enum used to indicate the purpose of a builder which may result in special handling
  17. enum class BuilderPurpose
  18. {
  19. CreateJobs,
  20. ProcessJob,
  21. Registration
  22. };
  23. enum class BuilderRunJobOutcome
  24. {
  25. Ok,
  26. LostConnection,
  27. ProcessTerminated,
  28. JobCancelled,
  29. ResponseFailure,
  30. FailedToDecodeResponse,
  31. FailedToWriteDebugRequest
  32. };
  33. //! Wrapper for managing a single builder process and sending job requests to it
  34. class Builder
  35. {
  36. friend class BuilderManager;
  37. friend struct BuilderRef;
  38. friend class BuilderList;
  39. public:
  40. Builder(const AssetUtilities::QuitListener& quitListener, AZ::Uuid uuid)
  41. : m_uuid(uuid)
  42. , m_quitListener(quitListener)
  43. {
  44. }
  45. virtual ~Builder() = default;
  46. // Disable copy and move (can't move a semaphore)
  47. AZ_DISABLE_COPY_MOVE(Builder);
  48. //! Returns true if the builder has a valid connection id and, if there is a process associated, the process is running
  49. bool IsValid() const;
  50. //! Returns true if the builder has a process watcher and the process is running OR does not have a process watcher. Returns false
  51. //! otherwise
  52. bool IsRunning(AZ::u32* exitCode = nullptr) const;
  53. //! Returns true if the builder exe has established a connection
  54. bool IsConnected() const;
  55. //! Blocks waiting for the builder to establish a connection
  56. AZ::Outcome<void, AZStd::string> WaitForConnection();
  57. AZ::u32 GetConnectionId() const;
  58. AZ::Uuid GetUuid() const;
  59. AZStd::string UuidString() const;
  60. void PumpCommunicator() const;
  61. void FlushCommunicator() const;
  62. void TerminateProcess(AZ::u32 exitCode) const;
  63. //! Sends the job over to the builder and blocks until the response is received or the builder crashes/times out
  64. template<typename TNetRequest, typename TNetResponse, typename TRequest, typename TResponse>
  65. BuilderRunJobOutcome RunJob(
  66. const TRequest& request,
  67. TResponse& response,
  68. AZ::u32 processTimeoutLimitInSeconds,
  69. const AZStd::string& task,
  70. const AZStd::string& modulePath,
  71. AssetBuilderSDK::JobCancelListener* jobCancelListener = nullptr,
  72. AZStd::string tempFolderPath = AZStd::string()) const;
  73. protected:
  74. //! Starts the builder process and waits for it to connect
  75. virtual AZ::Outcome<void, AZStd::string> Start(BuilderPurpose purpose);
  76. //! Sets the connection id and signals that the builder has connected
  77. void SetConnection(AZ::u32 connId);
  78. AZStd::vector<AZStd::string> BuildParams(
  79. const char* task,
  80. const char* moduleFilePath,
  81. const AZStd::string& builderGuid,
  82. const AZStd::string& jobDescriptionFile,
  83. const AZStd::string& jobResponseFile,
  84. BuilderPurpose purpose) const;
  85. AZStd::unique_ptr<AzFramework::ProcessWatcher> LaunchProcess(
  86. const char* fullExePath, const AZStd::vector<AZStd::string>& params) const;
  87. //! Waits for the builder exe to send the job response and pumps stdout/err
  88. BuilderRunJobOutcome WaitForBuilderResponse(
  89. AssetBuilderSDK::JobCancelListener* jobCancelListener,
  90. AZ::u32 processTimeoutLimitInSeconds,
  91. AZStd::binary_semaphore* waitEvent) const;
  92. //! Writes the request out to disk for debug purposes and logs info on how to manually run the asset builder
  93. template<typename TRequest>
  94. bool DebugWriteRequestFile(
  95. QString tempFolderPath,
  96. const TRequest& request,
  97. const AZStd::string& task,
  98. const AZStd::string& modulePath,
  99. BuilderPurpose purpose) const;
  100. const AZ::Uuid m_uuid;
  101. //! Indicates if the builder is currently in use
  102. bool m_busy = false;
  103. AZStd::atomic<AZ::u32> m_connectionId = 0;
  104. //! Signals the exe has successfully established a connection
  105. AZStd::binary_semaphore m_connectionEvent;
  106. //! Optional process watcher
  107. AZStd::unique_ptr<AzFramework::ProcessWatcher> m_processWatcher = nullptr;
  108. //! Optional communicator, only available if we have a process watcher
  109. AZStd::unique_ptr<ProcessCommunicatorTracePrinter> m_tracePrinter = nullptr;
  110. const AssetUtilities::QuitListener& m_quitListener;
  111. //! Time to wait in seconds for a builder to startup before timing out.
  112. AZ::s64 m_startupWaitTimeS = 0;
  113. };
  114. //! Scoped reference to a builder. Destructor returns the builder to the free builders pool
  115. struct BuilderRef
  116. {
  117. BuilderRef() = default;
  118. explicit BuilderRef(const AZStd::shared_ptr<Builder>& builder);
  119. ~BuilderRef();
  120. // Disable copy
  121. BuilderRef(const BuilderRef&) = delete;
  122. BuilderRef& operator=(const BuilderRef&) = delete;
  123. // Allow move
  124. BuilderRef(BuilderRef&&);
  125. BuilderRef& operator=(BuilderRef&&);
  126. const Builder* operator->() const;
  127. explicit operator bool() const;
  128. void release();
  129. private:
  130. AZStd::shared_ptr<Builder> m_builder = nullptr;
  131. };
  132. } // namespace AssetProcessor