Add preliminary budget tracking system and remove driller integration

Signed-off-by: Jeremy Ong <jcong@amazon.com>
This commit is contained in:
Jeremy Ong
2021-08-23 12:44:21 -06:00
parent 07a14bdce1
commit 5e04c3737f
50 changed files with 191 additions and 2288 deletions
@@ -10,7 +10,6 @@
// Component includes
#include <AzCore/Asset/AssetManagerComponent.h>
#include <AzCore/Debug/BudgetsComponent.h>
#include <AzCore/IO/Streamer/StreamerComponent.h>
#include <AzCore/Jobs/JobManagerComponent.h>
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
@@ -36,7 +35,6 @@ namespace AZ
JsonSystemComponent::CreateDescriptor(),
AssetManagerComponent::CreateDescriptor(),
UserSettingsComponent::CreateDescriptor(),
Debug::BudgetsComponent::CreateDescriptor(),
SliceComponent::CreateDescriptor(),
SliceSystemComponent::CreateDescriptor(),
SliceMetadataInfoComponent::CreateDescriptor(),
@@ -54,7 +52,6 @@ namespace AZ
{
return AZ::ComponentTypeList
{
azrtti_typeid<Debug::BudgetsComponent>(),
azrtti_typeid<TimeSystemComponent>(),
azrtti_typeid<LoggerSystemComponent>(),
azrtti_typeid<EventSchedulerSystemComponent>(),
@@ -593,6 +593,8 @@ namespace AZ
CreateOSAllocator();
CreateSystemAllocator();
m_budgetTracker.Init();
// This can be moved to the ComponentApplication constructor if need be
// This is reading the *.setreg files using SystemFile and merging the settings
// to the settings registry.
@@ -624,8 +626,6 @@ namespace AZ
m_eventLogger->Start(outputPath.Native(), baseFileName);
}
CreateDrillers();
Sfmt::Create();
CreateReflectionManager();
@@ -745,12 +745,6 @@ namespace AZ
ComponentApplicationBus::Handler::BusDisconnect();
TickRequestBus::Handler::BusDisconnect();
if (m_drillerManager)
{
Debug::DrillerManager::Destroy(m_drillerManager);
m_drillerManager = nullptr;
}
m_eventLogger->Stop();
// Clear the descriptor to deallocate all strings (owned by ModuleDescriptor)
@@ -898,31 +892,6 @@ namespace AZ
allocatorManager.FinalizeConfiguration();
}
//=========================================================================
// CreateDrillers
// [2/20/2013]
//=========================================================================
void ComponentApplication::CreateDrillers()
{
// Create driller manager and register drillers if requested
if (m_descriptor.m_enableDrilling)
{
m_drillerManager = Debug::DrillerManager::Create();
// Memory driller is responsible for tracking allocations.
// Tracking type and overhead is determined by app configuration.
// Only one MemoryDriller is supported at a time
// Only create the memory driller if there is no handlers connected to the MemoryDrillerBus
if (!Debug::MemoryDrillerBus::HasHandlers())
{
m_drillerManager->Register(aznew Debug::MemoryDriller);
}
// Trace messages driller will consume resources only when started.
m_drillerManager->Register(aznew Debug::TraceMessagesDriller);
m_drillerManager->Register(aznew Debug::EventTraceDriller);
}
}
void ComponentApplication::MergeSettingsToRegistry(SettingsRegistryInterface& registry)
{
SettingsRegistryInterface::Specializations specializations;
@@ -1413,10 +1382,6 @@ namespace AZ
EBUS_EVENT(TickBus, OnTick, m_deltaTime, ScriptTimePoint(now));
}
}
if (m_drillerManager)
{
m_drillerManager->FrameUpdate();
}
}
//=========================================================================
@@ -11,6 +11,7 @@
#include <AzCore/Component/Component.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/Debug/BudgetTracker.h>
#include <AzCore/Memory/AllocationRecords.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/Module/DynamicModuleHandle.h>
@@ -225,11 +226,6 @@ namespace AZ
/// Returns the path to the folder the executable is in.
const char* GetExecutableFolder() const override { return m_exeDirectory.c_str(); }
/// Returns pointer to the driller manager if it's enabled, otherwise NULL.
Debug::DrillerManager* GetDrillerManager() override { return m_drillerManager; }
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/// TickRequestBus
float GetTickDeltaTime() override;
@@ -324,9 +320,6 @@ namespace AZ
/// Create the system allocator using the data in the m_descriptor
void CreateSystemAllocator();
/// Create the drillers
void CreateDrillers();
virtual void MergeSettingsToRegistry(SettingsRegistryInterface& registry);
//! Sets the specializations that will be used when loading the Settings Registry. Extend this in derived
@@ -409,7 +402,7 @@ namespace AZ
char m_commandLineBuffer[AZ_MAX_PATH_LEN];
char* m_commandLineBufferAddress{ m_commandLineBuffer };
Debug::DrillerManager* m_drillerManager{ nullptr };
AZ::Debug::BudgetTracker m_budgetTracker;
StartupParameters m_startupParameters;
@@ -187,11 +187,6 @@ namespace AZ
//! @return a pointer to the name of the path that contains the application's executable.
virtual const char* GetExecutableFolder() const = 0;
//! Returns a pointer to the driller manager, if driller is enabled.
//! The driller manager manages all active driller sessions and driller factories.
//! @return A pointer to the driller manager. If driller is not enabled, this function returns null.
virtual Debug::DrillerManager* GetDrillerManager() = 0;
//! ResolveModulePath is called whenever LoadDynamicModule wants to resolve a module in order to actually load it.
//! You can override this if you need to load modules from a different path or hijack module loading in some other way.
//! If you do, ensure that you use platform-specific conventions to do so, as this is called by multiple platforms.
+35 -13
View File
@@ -10,6 +10,7 @@
#include <AzCore/Module/Environment.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/Memory/SystemAllocator.h>
AZ_DEFINE_BUDGET(AzCore);
AZ_DEFINE_BUDGET(Editor);
@@ -21,25 +22,46 @@ AZ_DEFINE_BUDGET(Animation);
namespace AZ::Debug
{
// Global container for all registered budgets
class BudgetRegistry
struct BudgetImpl
{
public:
static BudgetRegistry& Instance()
{
}
private:
AZ_CLASS_ALLOCATOR(BudgetImpl, AZ::SystemAllocator, 0);
// TODO: Budget implementation for tracking budget wall time per-core, memory, etc.
};
void Budget::ResetAll()
{
}
Budget::Budget(const char* name)
: m_name{ name }
, m_crc{ Crc32(name) }
{
// TODO: Register budget with singleton budget registry
m_impl = aznew BudgetImpl;
}
Budget::~Budget()
{
if (m_impl)
{
delete m_impl;
}
}
// TODO:Budgets Methods below are stubbed pending future work to both update budget data and visualize it
void Budget::PerFrameReset()
{
}
void Budget::BeginProfileRegion()
{
}
void Budget::EndProfileRegion()
{
}
void Budget::TrackAllocation(uint64_t)
{
}
void Budget::UntrackAllocation(uint64_t)
{
}
} // namespace AZ::Debug
+17 -30
View File
@@ -7,9 +7,8 @@
*/
#pragma once
#include <AzCore/Module/Environment.h>
#include <AzCore/std/parallel/scoped_lock.h>
#include <AzCore/std/parallel/atomic.h>
#include <AzCore/Debug/BudgetTracker.h>
#pragma warning(push)
// This warning must be disabled because Budget::Get<T> may not have an implementation if this file is transitively included
@@ -24,9 +23,6 @@ namespace AZ::Debug
class Budget final
{
public:
// Invoked once at the start of the frame to reset per-frame counters
static void ResetAll();
// If you encounter a linker error complaining that this function is not defined, you have likely forgotten to either
// define or declare the budget used in a profile or memory marker. See AZ_DEFINE_BUDGET and AZ_DECLARE_BUDGET below
// for usage.
@@ -34,6 +30,13 @@ namespace AZ::Debug
static Budget* Get();
explicit Budget(const char* name);
~Budget();
void PerFrameReset();
void BeginProfileRegion();
void EndProfileRegion();
void TrackAllocation(uint64_t bytes);
void UntrackAllocation(uint64_t bytes);
const char* Name() const
{
@@ -48,11 +51,14 @@ namespace AZ::Debug
private:
const char* m_name;
uint32_t m_crc;
struct BudgetImpl* m_impl = nullptr;
};
} // namespace AZ::Debug
#pragma warning(pop)
#define AZ_BUDGET_NAME(name) AzBudget##name
// Budgets are registered and retrieved using the proxy type specialization of Budget::Get<T>. The type itself has no declaration/definition
// other than this forward type pointer declaration
#define AZ_BUDGET_PROXY_TYPE(name) class AzBudget##name*
// Usage example:
// In a single C++ source file:
@@ -62,45 +68,26 @@ namespace AZ::Debug
// AZ_DECLARE_BUDGET(AzCore);
//
// The budget is usable in the same file it was defined without needing an additional declaration
// Implementation notes:
// Every budget definition is declared in static storage along with the environment variable and mutex. This imposes a slight
// memory overhead in the data segment only in instances where the same static module defining a budget is linked against multiple
// DLLs, however, this simplifies the implementation and works regardless of whether the budget is defined in a static or dynamic
// library. When loading the budget, a relaxed load is sufficient because Environment::CreateVariable internally locks and returns
// the element found if the environment variable was already created (skipping construction in the process). Thus, the budget pointer
// will reference the statically stored budget for the first thread that grabs the lock.
#define AZ_DEFINE_BUDGET(name) \
template<> \
::AZ::Debug::Budget* ::AZ::Debug::Budget::Get<class AZ_BUDGET_NAME(name)*>() \
::AZ::Debug::Budget* ::AZ::Debug::Budget::Get<AZ_BUDGET_PROXY_TYPE(name)>() \
{ \
static ::AZStd::mutex s_azBudgetMutex##name; \
static ::AZ::EnvironmentVariable<::AZ::Debug::Budget*> s_azBudgetEnv##name; \
static ::AZ::Debug::Budget s_azBudget##name{ #name }; \
static ::AZStd::atomic<::AZ::Debug::Budget*> budget; \
::AZ::Debug::Budget* out = budget.load(AZStd::memory_order_relaxed); \
::AZ::Debug::Budget* out = budget.load(AZStd::memory_order_acquire); \
if (out) \
{ \
return out; \
} \
else \
{ \
{ \
AZStd::scoped_lock lock{ s_azBudgetMutex##name }; \
if (!s_azBudgetEnv##name) \
{ \
s_azBudgetEnv##name = ::AZ::Environment::CreateVariable<::AZ::Debug::Budget*>("budgetEnv" #name, &s_azBudget##name); \
} \
} \
out = *s_azBudgetEnv##name; \
budget = out; \
return out; \
budget.store(&::AZ::Debug::BudgetTracker::GetBudgetFromEnvironment(#name), AZStd::memory_order_release); \
return budget; \
} \
}
// If using a budget defined in a different C++ source file, add AZ_DECLARE_BUDGET(yourBudget); somewhere in your source file at namespace
// scope Alternatively, AZ_DECLARE_BUDGET can be used in a header to declare the budget for use across any users of the header
#define AZ_DECLARE_BUDGET(name) extern template ::AZ::Debug::Budget* ::AZ::Debug::Budget::Get<class AZ_BUDGET_NAME(name)*>()
#define AZ_DECLARE_BUDGET(name) extern template ::AZ::Debug::Budget* ::AZ::Debug::Budget::Get<AZ_BUDGET_PROXY_TYPE(name)>()
// Declare budgets that are core engine budgets, or may be shared/needed across multiple external gems
// You should NOT need to declare user-space or budgets with isolated usage here. Prefer declaring them local to the module(s) that use
@@ -0,0 +1,61 @@
/*
* 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
*
*/
#include <AzCore/Debug/BudgetTracker.h>
#include <AzCore/base.h>
#include <AzCore/Debug/Budget.h>
#include <AzCore/Memory/Memory.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/parallel/scoped_lock.h>
namespace AZ::Debug
{
constexpr static const char* BudgetTrackerEnvName = "budgetTrackerEnv";
struct BudgetTrackerImpl
{
AZ_CLASS_ALLOCATOR(BudgetTrackerImpl, AZ::SystemAllocator, 0);
AZStd::unordered_map<const char*, Budget> m_budgets;
};
Budget& BudgetTracker::GetBudgetFromEnvironment(const char* budgetName)
{
return (*Environment::FindVariable<BudgetTracker*>(BudgetTrackerEnvName))->GetBudget(budgetName);
}
BudgetTracker::~BudgetTracker()
{
if (m_impl)
{
delete m_impl;
}
}
void BudgetTracker::Init()
{
AZ_Assert(!m_impl, "BudgetTracker::Init called more than once");
m_impl = aznew BudgetTrackerImpl;
m_envVar = Environment::CreateVariable<BudgetTracker*>(BudgetTrackerEnvName, this);
}
Budget& BudgetTracker::GetBudget(const char* budgetName)
{
AZStd::scoped_lock lock{ m_mutex };
auto it = m_impl->m_budgets.find(budgetName);
if (it == m_impl->m_budgets.end())
{
it = m_impl->m_budgets.emplace(budgetName, budgetName).first;
}
return it->second;
}
} // namespace AZ::Debug
@@ -0,0 +1,38 @@
/*
* 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
#include <AzCore/Module/Environment.h>
#include <AzCore/std/parallel/mutex.h>
namespace AZ::Debug
{
class Budget;
class BudgetTracker
{
public:
static Budget& GetBudgetFromEnvironment(const char* budgetName);
~BudgetTracker();
void Init();
Budget& GetBudget(const char* budgetName);
private:
AZStd::mutex m_mutex;
AZ::EnvironmentVariable<BudgetTracker*> m_envVar;
// The BudgetTracker is likely included in proportionally high number of files throughout the
// engine, so indirection is used here to avoid imposing excessive recompilation in periods
// while the budget system is iterated on.
struct BudgetTrackerImpl* m_impl = nullptr;
};
} // namespace AZ::Debug
@@ -1,29 +0,0 @@
#include <AzCore/Debug/BudgetsComponent.h>
namespace AZ::Debug
{
void BudgetsComponent::Reflect(AZ::ReflectContext*)
{
}
BudgetsComponent::BudgetsComponent()
{
}
BudgetsComponent::~BudgetsComponent()
{
}
void BudgetsComponent::Init()
{
}
void BudgetsComponent::Activate()
{
}
void BudgetsComponent::Deactivate()
{
}
} // namespace AZ::Debug
@@ -1,31 +0,0 @@
/*
* 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
#include <AzCore/Component/Component.h>
namespace AZ::Debug
{
class BudgetsComponent : public Component
{
public:
AZ_COMPONENT(AZ::Debug::BudgetsComponent, "{52063706-5B36-4B24-A781-B49AFDBB5BC5}");
static void Reflect(AZ::ReflectContext* context);
BudgetsComponent();
~BudgetsComponent() override;
void Init() override;
void Activate() override;
void Deactivate() override;
private:
};
} // namespace AZ::Debug
@@ -8,13 +8,3 @@
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Math/Crc.h>
namespace AZ::Debug
{
uint32_t ProfileScope::GetSystemID(const char* system)
{
// TODO: stable ids for registered budgets
return AZ::Crc32(system);
}
} // namespace AZ::Debug
+13 -10
View File
@@ -29,15 +29,15 @@
#define AZ_PROFILE_SCOPE(budget, ...) \
::AZ::Debug::ProfileScope AZ_JOIN(azProfileScope, __LINE__) \
{ \
*::AZ::Debug::Budget::Get<class AZ_BUDGET_NAME(budget)*>(), __VA_ARGS__ \
*::AZ::Debug::Budget::Get<AZ_BUDGET_PROXY_TYPE(budget)>(), __VA_ARGS__ \
}
#define AZ_PROFILE_FUNCTION(category) AZ_PROFILE_SCOPE(category, AZ_FUNCTION_SIGNATURE)
// Prefer using the scoped macros which automatically end the event (AZ_PROFILE_SCOPE/AZ_PROFILE_FUNCTION)
#define AZ_PROFILE_BEGIN(budget, ...) \
::AZ::Debug::ProfileScope::BeginRegion(*::AZ::Debug::Budget::Get<class AZ_BUDGET_NAME(budget)*>(), __VA_ARGS__)
#define AZ_PROFILE_END() ::AZ::Debug::ProfileScope::EndRegion()
::AZ::Debug::ProfileScope::BeginRegion(*::AZ::Debug::Budget::Get<AZ_BUDGET_PROXY_TYPE(budget)>(), __VA_ARGS__)
#define AZ_PROFILE_END(budget) ::AZ::Debug::ProfileScope::EndRegion(*::AZ::Debug::Budget::Get<AZ_BUDGET_PROXY_TYPE(budget)>())
#endif // AZ_PROFILER_MACRO_DISABLE
@@ -63,26 +63,25 @@ namespace AZ::Debug
class ProfileScope
{
public:
static uint32_t GetSystemID(const char* system);
template<typename... T>
static void BeginRegion(
[[maybe_unused]] const Budget& budget, [[maybe_unused]] const char* eventName, [[maybe_unused]] T const&... args)
static void BeginRegion([[maybe_unused]] Budget& budget, [[maybe_unused]] const char* eventName, [[maybe_unused]] T const&... args)
{
#if !defined(_RELEASE)
// TODO: Verification that the supplied system name corresponds to a known budget
#if defined(USE_PIX)
PIXBeginEvent(PIX_COLOR_INDEX(budget.Crc() & 0xff), eventName, args...);
#endif
budget.BeginProfileRegion();
// TODO: injecting instrumentation for other profilers
// NOTE: external profiler registration won't occur inline in a header necessarily in this manner, but the exact mechanism
// will be introduced in a future PR
#endif
}
static void EndRegion()
static void EndRegion([[maybe_unused]] Budget& budget)
{
#if !defined(_RELEASE)
budget.EndProfileRegion();
#if defined(USE_PIX)
PIXEndEvent();
#endif
@@ -90,15 +89,19 @@ namespace AZ::Debug
}
template<typename... T>
ProfileScope(const Budget& budget, char const* eventName, T const&... args)
ProfileScope(Budget& budget, char const* eventName, T const&... args)
: m_budget{ budget }
{
BeginRegion(budget, eventName, args...);
}
~ProfileScope()
{
EndRegion();
EndRegion(m_budget);
}
private:
Budget& m_budget;
};
} // namespace AZ::Debug
@@ -44,7 +44,6 @@ namespace UnitTest
MOCK_CONST_METHOD0(GetAppRoot, const char* ());
MOCK_CONST_METHOD0(GetEngineRoot, const char* ());
MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
MOCK_METHOD0(GetDrillerManager, AZ::Debug::DrillerManager* ());
MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&));
};
} // namespace UnitTest
@@ -95,8 +95,8 @@ set(FILES
Debug/AssetTrackingTypes.h
Debug/Budget.h
Debug/Budget.cpp
Debug/BudgetsComponent.h
Debug/BudgetsComponent.cpp
Debug/BudgetTracker.h
Debug/BudgetTracker.cpp
Debug/LocalFileEventLogger.h
Debug/LocalFileEventLogger.cpp
Debug/IEventLogger.h
@@ -62,7 +62,6 @@ namespace UnitTest
const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
AZ::Debug::DrillerManager* GetDrillerManager() override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {}
////
-698
View File
@@ -1,698 +0,0 @@
/*
* 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
*
*/
#include <time.h>
#include <AzCore/IO/FileIOEventBus.h>
#include <AzCore/Driller/Driller.h>
#include <AzCore/Driller/DrillerBus.h>
#include <AzCore/Driller/DrillerRootHandler.h>
#include <AzCore/Driller/DefaultStringPool.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Memory/MemoryComponent.h>
#include <AzCore/IO/Streamer/StreamerComponent.h>
#include <AzCore/UnitTest/TestTypes.h>
//#define AZ_CORE_DRILLER_COMPARE_TEST
#if defined(AZ_CORE_DRILLER_COMPARE_TEST)
# include <AzCore/IO/GenericStreams.h>
# include <AzCore/Serialization/ObjectStream.h>
# include <AzCore/Serialization/SerializeContext.h>
#endif
#include <AZTestShared/Utils/Utils.h>
using namespace AZ;
using namespace AZ::Debug;
namespace UnitTest
{
/**
* MyDriller event bus...
*/
class MyDrillerInterface
: public AZ::Debug::DrillerEBusTraits
{
public:
virtual ~MyDrillerInterface() {}
// define one event X
virtual void OnEventX(int data) = 0;
// define a string event
virtual void OnStringEvent() = 0;
};
class MyDrillerCommandInterface
: public AZ::Debug::DrillerEBusTraits
{
public:
virtual ~MyDrillerCommandInterface() {}
virtual class MyDrilledObject* RequestDrilledObject() = 0;
};
typedef AZ::EBus<MyDrillerInterface> MyDrillerBus;
typedef AZ::EBus<MyDrillerCommandInterface> MyDrillerCommandBus;
class MyDrilledObject
: public MyDrillerCommandBus::Handler
{
int i;
public:
MyDrilledObject()
: i(0)
{
BusConnect();
}
~MyDrilledObject() override
{
BusDisconnect();
}
//////////////////////////////////////////////////////////////////////////
// MyDrillerCommandBus
MyDrilledObject* RequestDrilledObject() override
{
return this;
}
//////////////////////////////////////////////////////////////////////////
void OnEventX()
{
EBUS_EVENT(MyDrillerBus, OnEventX, i);
++i;
}
void OnStringEvent()
{
EBUS_DBG_EVENT(MyDrillerBus, OnStringEvent);
}
};
/**
* My driller implements the driller interface and an handles the MyDrillerBus events...
*/
class MyDriller
: public Driller
, public MyDrillerBus::Handler
{
bool m_isDetailedCapture;
class MyDrilledObject* drilledObject;
typedef vector<Param>::type ParamArrayType;
ParamArrayType m_params;
public:
AZ_CLASS_ALLOCATOR(MyDriller, OSAllocator, 0);
const char* GroupName() const override { return "TestDrillers"; }
const char* GetName() const override { return "MyTestDriller"; }
const char* GetDescription() const override { return "MyTestDriller description...."; }
int GetNumParams() const override { return static_cast<int>(m_params.size()); }
const Param* GetParam(int index) const override { return &m_params[index]; }
MyDriller()
: m_isDetailedCapture(false)
, drilledObject(NULL)
{
Param isDetailed;
isDetailed.desc = "IsDetailedDrill";
isDetailed.name = AZ_CRC("IsDetailedDrill", 0x2155cef2);
isDetailed.type = Param::PT_BOOL;
isDetailed.value = 0;
m_params.push_back(isDetailed);
}
void Start(const Param* params = NULL, int numParams = 0) override
{
m_isDetailedCapture = m_params[0].value != 0;
if (params)
{
for (int i = 0; i < numParams; i++)
{
if (params[i].name == m_params[0].name)
{
m_isDetailedCapture = params[i].value != 0;
}
}
}
EBUS_EVENT_RESULT(drilledObject, MyDrillerCommandBus, RequestDrilledObject);
AZ_TEST_ASSERT(drilledObject != NULL); /// Make sure we have our object by the time we started the driller
m_output->BeginTag(AZ_CRC("MyDriller", 0xc3b7dceb));
m_output->Write(AZ_CRC("OnStart", 0x8b372fca), m_isDetailedCapture);
// write drilled object initial state
m_output->EndTag(AZ_CRC("MyDriller", 0xc3b7dceb));
BusConnect();
}
void Stop() override
{
drilledObject = NULL;
m_output->BeginTag(AZ_CRC("MyDriller", 0xc3b7dceb));
m_output->Write(AZ_CRC("OnStop", 0xf6701caa), m_isDetailedCapture);
m_output->EndTag(AZ_CRC("MyDriller", 0xc3b7dceb));
BusDisconnect();
}
void OnEventX(int data) override
{
void* ptr = AZ_INVALID_POINTER;
float f = 3.2f;
m_output->BeginTag(AZ_CRC("MyDriller", 0xc3b7dceb));
m_output->Write(AZ_CRC("EventX", 0xc4558ec2), data);
m_output->Write(AZ_CRC("Pointer", 0x320468a8), ptr);
m_output->Write(AZ_CRC("Float", 0xc9a55e95), f);
m_output->EndTag(AZ_CRC("MyDriller", 0xc3b7dceb));
}
void OnStringEvent() override
{
m_output->BeginTag(AZ_CRC("MyDriller", 0xc3b7dceb));
m_output->BeginTag(AZ_CRC("StringEvent", 0xd1e005df));
m_output->Write(AZ_CRC("StringOne", 0x56efb231), "This is copied string");
m_output->Write(AZ_CRC("StringTwo", 0x3d49bea6), "This is referenced string", false); // don't copy the string if we use string pool, this will be faster as we don't delete the string
m_output->EndTag(AZ_CRC("StringEvent", 0xd1e005df));
m_output->EndTag(AZ_CRC("MyDriller", 0xc3b7dceb));
}
};
/**
*
*/
class FileStreamDrillerTest
: public AllocatorsFixture
{
DrillerManager* m_drillerManager = nullptr;
MyDriller* m_driller = nullptr;
public:
void SetUp() override
{
AllocatorsFixture::SetUp();
m_drillerManager = DrillerManager::Create();
m_driller = aznew MyDriller;
// Register driller descriptor
m_drillerManager->Register(m_driller);
// check that our driller descriptor is registered
AZ_TEST_ASSERT(m_drillerManager->GetNumDrillers() == 1);
}
void TearDown() override
{
// remove our driller descriptor
m_drillerManager->Unregister(m_driller);
AZ_TEST_ASSERT(m_drillerManager->GetNumDrillers() == 0);
DrillerManager::Destroy(m_drillerManager);
AllocatorsFixture::TearDown();
}
/**
* My Driller data handler.
*/
class MyDrillerHandler
: public DrillerHandlerParser
{
public:
static const bool s_isWarnOnMissingDrillers = true;
int m_lastData;
MyDrillerHandler()
: m_lastData(-1) {}
// From the template query
DrillerHandlerParser* FindDrillerHandler(u32 drillerId)
{
if (drillerId == AZ_CRC("MyDriller", 0xc3b7dceb))
{
return this;
}
return NULL;
}
DrillerHandlerParser* OnEnterTag(u32 tagName) override
{
(void)tagName;
return NULL;
}
void OnData(const DrillerSAXParser::Data& dataNode) override
{
if (dataNode.m_name == AZ_CRC("OnStart", 0x8b372fca) || dataNode.m_name == AZ_CRC("OnStop", 0xf6701caa))
{
bool isDetailedCapture;
dataNode.Read(isDetailedCapture);
AZ_TEST_ASSERT(isDetailedCapture == true);
}
else if (dataNode.m_name == AZ_CRC("EventX", 0xc4558ec2))
{
int data;
dataNode.Read(data);
AZ_TEST_ASSERT(data > m_lastData);
m_lastData = data;
}
else if (dataNode.m_name == AZ_CRC("Pointer", 0x320468a8))
{
AZ::u64 pointer = 0; //< read pointers in u64 to cover all platforms
dataNode.Read(pointer);
AZ_TEST_ASSERT(pointer == 0x0badf00dul);
}
else if (dataNode.m_name == AZ_CRC("Float", 0xc9a55e95))
{
float f;
dataNode.Read(f);
AZ_TEST_ASSERT(f == 3.2f);
}
}
};
//////////////////////////////////////////////////////////////////////////
void run()
{
// get our driller descriptor
Driller* driller = m_drillerManager->GetDriller(0);
AZ_TEST_ASSERT(driller != NULL);
AZ_TEST_ASSERT(strcmp(driller->GetName(), "MyTestDriller") == 0);
AZ_TEST_ASSERT(driller->GetNumParams() == 1);
// read the default params and make a copy...
Driller::Param param = *driller->GetParam(0);
AZ_TEST_ASSERT(strcmp(param.desc, "IsDetailedDrill") == 0);
AZ_TEST_ASSERT(param.name == AZ_CRC("IsDetailedDrill", 0x2155cef2));
AZ_TEST_ASSERT(param.type == Driller::Param::PT_BOOL);
// tweak the default params by enabling detailed drilling
param.value = 1;
// create a list of driller we what to drill
DrillerManager::DrillerListType dillersToDrill;
DrillerManager::DrillerInfo di;
di.id = driller->GetId(); // set driller id
di.params.push_back(param); // set driller custom params
dillersToDrill.push_back(di);
// open a driller output file stream
// open a driller output file stream
AZStd::string testFileName = GetTestFolderPath() + "drilltest.dat";
DrillerOutputFileStream drillerOutputStream;
drillerOutputStream.Open(testFileName.c_str(), IO::SystemFile::SF_OPEN_CREATE | IO::SystemFile::SF_OPEN_WRITE_ONLY);
//////////////////////////////////////////////////////////////////////////
// Drill an object
MyDrilledObject myDrilledObject;
clock_t st = clock();
// start a driller session with the file stream and the list of drillers
DrillerSession* drillerSession = m_drillerManager->Start(drillerOutputStream, dillersToDrill);
// update for N frames
for (int i = 0; i < AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT; ++i)
{
// trigger event X that we want to drill...
myDrilledObject.OnEventX();
m_drillerManager->FrameUpdate();
}
// stop the drillers
m_drillerManager->Stop(drillerSession);
// Stop writing and flush all data
drillerOutputStream.Close();
AZ_Printf("Driller", "Compression time %.09f seconds\n", (double)(clock() - st) / CLOCKS_PER_SEC);
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// try to load the drill data
DrillerInputFileStream drillerInputStream;
drillerInputStream.Open(testFileName.c_str(), IO::SystemFile::SF_OPEN_READ_ONLY);
DrillerDOMParser dp;
AZ_TEST_ASSERT(dp.CanParse() == true);
dp.ProcessStream(drillerInputStream);
AZ_TEST_ASSERT(dp.CanParse() == true);
drillerInputStream.Close();
u32 startDataId = AZ_CRC("StartData", 0xecf3f53f);
u32 frameId = AZ_CRC("Frame", 0xb5f83ccd);
//////////////////////////////////////////////////////////////////////////
// read all data
const DrillerDOMParser::Node* root = dp.GetRootNode();
int lastFrame = -1;
int lastData = -1;
for (DrillerDOMParser::Node::NodeListType::const_iterator iter = root->m_tags.begin(); iter != root->m_tags.end(); ++iter)
{
const DrillerDOMParser::Node* node = &*iter;
u32 name = node->m_name;
AZ_TEST_ASSERT(name == startDataId || name == frameId);
if (name == startDataId)
{
unsigned int currentPlatform;
node->GetDataRequired(AZ_CRC("Platform", 0x3952d0cb))->Read(currentPlatform);
AZ_TEST_ASSERT(currentPlatform == static_cast<int>(AZ::g_currentPlatform));
const DrillerDOMParser::Node* drillerNode = node->GetTag(AZ_CRC("Driller", 0xa6e1fb73));
AZ_TEST_ASSERT(drillerNode != NULL);
AZ::u32 drillerName;
drillerNode->GetDataRequired(AZ_CRC("Name", 0x5e237e06))->Read(drillerName);
AZ_TEST_ASSERT(drillerName == m_driller->GetId());
const DrillerDOMParser::Node* paramNode = drillerNode->GetTag(AZ_CRC("Param", 0xa4fa7c89));
AZ_TEST_ASSERT(paramNode != NULL);
u32 paramName;
char paramDesc[128];
int paramType;
int paramValue;
paramNode->GetDataRequired(AZ_CRC("Name", 0x5e237e06))->Read(paramName);
AZ_TEST_ASSERT(paramName == param.name);
paramNode->GetDataRequired(AZ_CRC("Description", 0x6de44026))->Read(paramDesc, AZ_ARRAY_SIZE(paramDesc));
AZ_TEST_ASSERT(strcmp(paramDesc, param.desc) == 0);
paramNode->GetDataRequired(AZ_CRC("Type", 0x8cde5729))->Read(paramType);
AZ_TEST_ASSERT(paramType == param.type);
paramNode->GetDataRequired(AZ_CRC("Value", 0x1d775834))->Read(paramValue);
AZ_TEST_ASSERT(paramValue == param.value);
}
else
{
int curFrame;
node->GetDataRequired(AZ_CRC("FrameNum", 0x85a1a919))->Read(curFrame);
AZ_TEST_ASSERT(curFrame > lastFrame); // check order
lastFrame = curFrame;
const DrillerDOMParser::Node* myDrillerNode = node->GetTag(AZ_CRC("MyDriller", 0xc3b7dceb));
AZ_TEST_ASSERT(myDrillerNode != NULL);
const DrillerDOMParser::Data* dataEntry;
dataEntry = myDrillerNode->GetData(AZ_CRC("EventX", 0xc4558ec2));
if (dataEntry)
{
int data;
dataEntry->Read(data);
AZ_TEST_ASSERT(data > lastData);
lastData = data;
dataEntry = myDrillerNode->GetData(AZ_CRC("Pointer", 0x320468a8));
AZ_TEST_ASSERT(dataEntry);
unsigned int ptr;
dataEntry->Read(ptr);
AZ_TEST_ASSERT(static_cast<size_t>(ptr) == reinterpret_cast<size_t>(AZ_INVALID_POINTER));
float f;
dataEntry = myDrillerNode->GetData(AZ_CRC("Float", 0xc9a55e95));
AZ_TEST_ASSERT(dataEntry);
dataEntry->Read(f);
AZ_TEST_ASSERT(f == 3.2f);
}
else
{
bool isDetailedCapture;
dataEntry = myDrillerNode->GetData(AZ_CRC("OnStart", 0x8b372fca));
if (dataEntry)
{
dataEntry->Read(isDetailedCapture);
}
else
{
myDrillerNode->GetDataRequired(AZ_CRC("OnStop", 0xf6701caa))->Read(isDetailedCapture);
}
AZ_TEST_ASSERT(isDetailedCapture == true);
}
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Read that with Tag Handlers
drillerInputStream.Open(testFileName.c_str(), IO::SystemFile::SF_OPEN_READ_ONLY);
DrillerRootHandler<MyDrillerHandler> rootHandler;
DrillerSAXParserHandler dhp(&rootHandler);
dhp.ProcessStream(drillerInputStream);
// Verify that Default templates forked fine...
AZ_TEST_ASSERT(rootHandler.m_drillerSessionInfo.m_platform == static_cast<uint32_t>(AZ::g_currentPlatform));
AZ_TEST_ASSERT(rootHandler.m_drillerSessionInfo.m_drillers.size() == 1);
{
const DrillerManager::DrillerInfo& dinfo = rootHandler.m_drillerSessionInfo.m_drillers.front();
AZ_TEST_ASSERT(dinfo.id == AZ_CRC("MyTestDriller", 0x5cc4edf5));
AZ_TEST_ASSERT(dinfo.params.size() == 1);
AZ_TEST_ASSERT(strcmp(param.desc, "IsDetailedDrill") == 0);
AZ_TEST_ASSERT(param.name == AZ_CRC("IsDetailedDrill", 0x2155cef2));
AZ_TEST_ASSERT(param.type == Driller::Param::PT_BOOL);
// tweak the default params by enabling detailed drilling
param.value = 1;
AZ_TEST_ASSERT(dinfo.params[0].name == AZ_CRC("IsDetailedDrill", 0x2155cef2));
AZ_TEST_ASSERT(dinfo.params[0].desc == NULL); // ignored for now
AZ_TEST_ASSERT(dinfo.params[0].type == Driller::Param::PT_BOOL);
AZ_TEST_ASSERT(dinfo.params[0].value == 1);
}
drillerInputStream.Close();
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////
}
};
TEST_F(FileStreamDrillerTest, Test)
{
run();
}
/**
*
*/
class StringPoolDrillerTest
: public AllocatorsFixture
{
DrillerManager* m_drillerManager = nullptr;
MyDriller* m_driller = nullptr;
public:
void SetUp() override
{
AllocatorsFixture::SetUp();
m_drillerManager = DrillerManager::Create();
m_driller = aznew MyDriller;
// Register driller descriptor
m_drillerManager->Register(m_driller);
// check that our driller descriptor is registered
AZ_TEST_ASSERT(m_drillerManager->GetNumDrillers() == 1);
}
void TearDown() override
{
// remove our driller descriptor
m_drillerManager->Unregister(m_driller);
AZ_TEST_ASSERT(m_drillerManager->GetNumDrillers() == 0);
DrillerManager::Destroy(m_drillerManager);
AllocatorsFixture::TearDown();
}
/**
* My Driller data handler.
*/
class MyDrillerHandler
: public DrillerHandlerParser
{
public:
static const bool s_isWarnOnMissingDrillers = true;
MyDrillerHandler() {}
// From the template query
DrillerHandlerParser* FindDrillerHandler(u32 drillerId)
{
if (drillerId == AZ_CRC("MyDriller", 0xc3b7dceb))
{
return this;
}
return NULL;
}
DrillerHandlerParser* OnEnterTag(u32 tagName) override
{
if (tagName == AZ_CRC("StringEvent", 0xd1e005df))
{
return this;
}
return NULL;
}
void OnData(const DrillerSAXParser::Data& dataNode) override
{
if (dataNode.m_name == AZ_CRC("OnStart", 0x8b372fca) || dataNode.m_name == AZ_CRC("OnStop", 0xf6701caa))
{
bool isDetailedCapture;
dataNode.Read(isDetailedCapture);
AZ_TEST_ASSERT(isDetailedCapture == true);
}
else if (dataNode.m_name == AZ_CRC("StringOne", 0x56efb231))
{
// read string as a copy
char stringCopy[256];
dataNode.Read(stringCopy, AZ_ARRAY_SIZE(stringCopy));
AZ_TEST_ASSERT(strcmp(stringCopy, "This is copied string") == 0);
}
else if (dataNode.m_name == AZ_CRC("StringTwo", 0x3d49bea6))
{
// read string as reference if possible, otherwise read it as a copy
const char* stringRef = dataNode.ReadPooledString();
AZ_TEST_ASSERT(strcmp(stringRef, "This is referenced string") == 0);
}
}
};
void run()
{
// get our driller descriptor
Driller* driller = m_drillerManager->GetDriller(0);
Driller::Param param = *driller->GetParam(0);
param.value = 1;
// create a list of driller we what to drill
DrillerManager::DrillerListType dillersToDrill;
DrillerManager::DrillerInfo di;
di.id = driller->GetId(); // set driller id
di.params.push_back(param); // set driller custom params
dillersToDrill.push_back(di);
MyDrilledObject myDrilledObject;
// open a driller output file stream
AZStd::string testFileName = GetTestFolderPath() + "stringpooldrilltest.dat";
DrillerOutputFileStream drillerOutputStream;
DrillerInputFileStream drillerInputStream;
DrillerDefaultStringPool stringPool;
DrillerSession* drillerSession;
DrillerRootHandler<MyDrillerHandler> rootHandler;
DrillerSAXParserHandler dhp(&rootHandler);
//////////////////////////////////////////////////////////////////////////
// Drill an object without string pools
drillerOutputStream.Open(testFileName.c_str(), IO::SystemFile::SF_OPEN_CREATE | IO::SystemFile::SF_OPEN_WRITE_ONLY);
// start a driller session with the file stream and the list of drillers
drillerSession = m_drillerManager->Start(drillerOutputStream, dillersToDrill);
// update for N frames
for (int i = 0; i < AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT; ++i)
{
myDrilledObject.OnStringEvent();
m_drillerManager->FrameUpdate();
}
// stop the drillers
m_drillerManager->Stop(drillerSession);
// Stop writing and flush all data
drillerOutputStream.Close();
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Read all data that was written without string pool, in a stream that uses one.
drillerInputStream.Open(testFileName.c_str(), IO::SystemFile::SF_OPEN_READ_ONLY);
drillerInputStream.SetStringPool(&stringPool);
dhp.ProcessStream(drillerInputStream);
drillerInputStream.Close();
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Drill an object without string pools
drillerOutputStream.Open(testFileName.c_str(), IO::SystemFile::SF_OPEN_CREATE | IO::SystemFile::SF_OPEN_WRITE_ONLY);
stringPool.Reset();
drillerOutputStream.SetStringPool(&stringPool); // set the string pool on save
// start a driller session with the file stream and the list of drillers
drillerSession = m_drillerManager->Start(drillerOutputStream, dillersToDrill);
// update for N frames
for (int i = 0; i < AZ_TRAIT_UNIT_TEST_DILLER_TRIGGER_EVENT_COUNT; ++i)
{
myDrilledObject.OnStringEvent();
m_drillerManager->FrameUpdate();
}
// stop the drillers
m_drillerManager->Stop(drillerSession);
// Stop writing and flush all data
drillerOutputStream.Close();
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Read all data that was written without string pool, in a stream that uses one.
stringPool.Reset();
drillerInputStream.Open(testFileName.c_str(), IO::SystemFile::SF_OPEN_READ_ONLY);
drillerInputStream.SetStringPool(&stringPool);
dhp.ProcessStream(drillerInputStream);
drillerInputStream.Close();
//////////////////////////////////////////////////////////////////////////
}
};
TEST_F(StringPoolDrillerTest, Test)
{
run();
}
/**
*
*/
class DrillFileStreamCheck
{
public:
void run()
{
// open and read drilled file
}
};
/**
* Driller application test
*/
TEST(DrillerApplication, Test)
{
ComponentApplication app;
//////////////////////////////////////////////////////////////////////////
// Create application environment code driven
ComponentApplication::Descriptor appDesc;
appDesc.m_memoryBlocksByteSize = 10 * 1024 * 1024;
appDesc.m_enableDrilling = true;
Entity* systemEntity = app.Create(appDesc);
systemEntity->CreateComponent<MemoryComponent>();
systemEntity->CreateComponent<StreamerComponent>(); // note that this component is what registers the streamer driller
systemEntity->Init();
systemEntity->Activate();
{
// open a driller output file stream
char testFileName[AZ_MAX_PATH_LEN];
MakePathFromTestFolder(testFileName, AZ_MAX_PATH_LEN, "drillapptest.dat");
DrillerOutputFileStream fs;
fs.Open(testFileName, IO::SystemFile::SF_OPEN_CREATE | IO::SystemFile::SF_OPEN_WRITE_ONLY);
// create a list of driller we what to drill
DrillerManager::DrillerListType drillersToDrill;
DrillerManager::DrillerInfo di;
di.id = AZ_CRC("TraceMessagesDriller", 0xa61d1b00);
drillersToDrill.push_back(di);
di.id = AZ_CRC("MemoryDriller", 0x1b31269d);
drillersToDrill.push_back(di);
ASSERT_NE(nullptr, app.GetDrillerManager());
DrillerSession* drillerSession = app.GetDrillerManager()->Start(fs, drillersToDrill);
ASSERT_NE(nullptr, drillerSession);
const int numOfFrames = 10000;
void* memory = NULL;
for (int i = 0; i < numOfFrames; ++i)
{
memory = azmalloc(rand() % 2048 + 1);
azfree(memory);
app.Tick();
}
app.GetDrillerManager()->Stop(drillerSession); // stop session manually
fs.Close(); // close the file with driller info
}
app.Destroy();
//////////////////////////////////////////////////////////////////////////
}
}
@@ -1242,7 +1242,6 @@ namespace UnitTest
const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
Debug::DrillerManager* GetDrillerManager() override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {}
//////////////////////////////////////////////////////////////////////////
@@ -29,7 +29,6 @@ set(FILES
Console/ConsoleTests.cpp
Debug.cpp
DLL.cpp
Driller.cpp
EBus.cpp
EntityIdTests.cpp
EntityTests.cpp
@@ -59,7 +59,6 @@
#include <AzFramework/StreamingInstall/StreamingInstall.h>
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
#include <AzFramework/Viewport/CameraState.h>
#include <AzFramework/Driller/RemoteDrillerInterface.h>
#include <AzFramework/Metrics/MetricsPlainTextNameRegistration.h>
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
@@ -310,7 +309,6 @@ namespace AzFramework
#endif
azrtti_typeid<AzFramework::AssetSystem::AssetSystemComponent>(),
azrtti_typeid<AzFramework::InputSystemComponent>(),
azrtti_typeid<AzFramework::DrillerNetworkAgentComponent>(),
#if !defined(AZCORE_EXCLUDE_LUA)
azrtti_typeid<AZ::ScriptSystemComponent>(),
@@ -372,7 +370,6 @@ namespace AzFramework
azrtti_typeid<AzFramework::RenderGeometry::GameIntersectorComponent>(),
azrtti_typeid<AzFramework::AssetSystem::AssetSystemComponent>(),
azrtti_typeid<AzFramework::InputSystemComponent>(),
azrtti_typeid<AzFramework::DrillerNetworkAgentComponent>(),
azrtti_typeid<AzFramework::StreamingInstall::StreamingInstallSystemComponent>(),
azrtti_typeid<AzFramework::SpawnableSystemComponent>(),
AZ::Uuid("{624a7be2-3c7e-4119-aee2-1db2bdb6cc89}"), // ScriptDebugAgent
@@ -14,7 +14,6 @@
#include <AzFramework/Components/TransformComponent.h>
#include <AzFramework/Components/NonUniformScaleComponent.h>
#include <AzFramework/Components/AzFrameworkConfigurationSystemComponent.h>
#include <AzFramework/Driller/RemoteDrillerInterface.h>
#include <AzFramework/Entity/GameEntityContextComponent.h>
#include <AzFramework/FileTag/FileTagComponent.h>
#include <AzFramework/Input/System/InputSystemComponent.h>
@@ -48,7 +47,6 @@ namespace AzFramework
AzFramework::CreateScriptDebugAgentFactory(),
AzFramework::AssetSystem::AssetSystemComponent::CreateDescriptor(),
AzFramework::InputSystemComponent::CreateDescriptor(),
AzFramework::DrillerNetworkAgentComponent::CreateDescriptor(),
#if !defined(AZCORE_EXCLUDE_LUA)
AzFramework::ScriptComponent::CreateDescriptor(),
@@ -1,197 +0,0 @@
/*
* 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
*
*/
#include <AzFramework/Driller/DrillToFileComponent.h>
#include <AzCore/Driller/Driller.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/IO/FileIO.h>
namespace AzFramework
{
void DrillToFileComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
if (serialize)
{
serialize->Class<DrillToFileComponent, AZ::Component>()
;
if (serialize->FindClassData(DrillerInfo::RTTI_Type()) == nullptr)
{
serialize->Class<DrillerInfo>()
->Field("Id", &DrillerInfo::m_id)
->Field("GroupName", &DrillerInfo::m_groupName)
->Field("Name", &DrillerInfo::m_name)
->Field("Description", &DrillerInfo::m_description);
}
}
}
void DrillToFileComponent::Activate()
{
m_drillerSession = nullptr;
DrillerConsoleCommandBus::Handler::BusConnect();
}
void DrillToFileComponent::Deactivate()
{
DrillerConsoleCommandBus::Handler::BusDisconnect();
StopDrillerSession(reinterpret_cast<AZ::u64>(this));
}
void DrillToFileComponent::WriteBinary(const void* data, unsigned int dataSize)
{
if (dataSize > 0)
{
m_frameBuffer.insert(m_frameBuffer.end(), reinterpret_cast<const AZ::u8*>(data), reinterpret_cast<const AZ::u8*>(data) + dataSize);
}
}
void DrillToFileComponent::OnEndOfFrame()
{
AZStd::lock_guard<AZStd::mutex> lock(m_writerMutex);
m_writeQueue.push_back();
m_writeQueue.back().swap(m_frameBuffer);
m_signal.notify_all();
}
void DrillToFileComponent::EnumerateAvailableDrillers()
{
DrillerInfoListType availableDrillers;
AZ::Debug::DrillerManager* mgr = NULL;
EBUS_EVENT_RESULT(mgr, AZ::ComponentApplicationBus, GetDrillerManager);
if (mgr)
{
for (int i = 0; i < mgr->GetNumDrillers(); ++i)
{
AZ::Debug::Driller* driller = mgr->GetDriller(i);
AZ_Assert(driller, "DrillerManager returned a NULL driller. This is not legal!");
availableDrillers.push_back();
availableDrillers.back().m_id = driller->GetId();
availableDrillers.back().m_groupName = driller->GroupName();
availableDrillers.back().m_name = driller->GetName();
availableDrillers.back().m_description = driller->GetDescription();
}
}
EBUS_EVENT(DrillerConsoleEventBus, OnDrillersEnumerated, availableDrillers);
}
void DrillToFileComponent::StartDrillerSession(const AZ::Debug::DrillerManager::DrillerListType& requestedDrillers, AZ::u64 sessionId)
{
if (!m_drillerSession)
{
AZ_Assert(m_writeQueue.empty(), "write queue is not empty!");
m_sessionId = sessionId;
AZ::Debug::DrillerManager* mgr = nullptr;
EBUS_EVENT_RESULT(mgr, AZ::ComponentApplicationBus, GetDrillerManager);
if (mgr)
{
SetStringPool(&m_stringPool);;
m_drillerSession = mgr->Start(*this, requestedDrillers);
AZStd::unique_lock<AZStd::mutex> signalLock(m_writerMutex);
m_isWriterEnabled = true;
AZStd::thread_desc td;
td.m_name = "DrillToFileComponent Writer Thread";
m_writerThread = AZStd::thread(AZStd::bind(&DrillToFileComponent::AsyncWritePump, this), &td);
m_signal.wait(signalLock);
EBUS_EVENT(DrillerConsoleEventBus, OnDrillerSessionStarted, sessionId);
}
}
}
void DrillToFileComponent::StopDrillerSession(AZ::u64 sessionId)
{
if (sessionId == m_sessionId)
{
if (m_drillerSession)
{
AZ::Debug::DrillerManager* mgr = NULL;
EBUS_EVENT_RESULT(mgr, AZ::ComponentApplicationBus, GetDrillerManager);
if (mgr)
{
mgr->Stop(m_drillerSession);
}
m_drillerSession = nullptr;
EBUS_EVENT(DrillerConsoleEventBus, OnDrillerSessionStopped, reinterpret_cast<AZ::u64>(this));
}
m_isWriterEnabled = false;
if (m_writerThread.joinable())
{
m_writerMutex.lock();
m_signal.notify_all();
m_writerMutex.unlock();
m_writerThread.join();
}
SetStringPool(nullptr);
m_stringPool.Reset();
m_frameBuffer.clear(); // there may be pending data but we don't want to write it because it's an incomplete frame.
}
}
void DrillToFileComponent::AsyncWritePump()
{
AZStd::unique_lock<AZStd::mutex> signalLock(m_writerMutex);
AZStd::basic_string<char, AZStd::char_traits<char>, AZ::OSStdAllocator> drillerOutputPath;
// Try the log path first
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
if (fileIO)
{
const char* logLocation = fileIO->GetAlias("@log@");
if (logLocation)
{
drillerOutputPath = logLocation;
drillerOutputPath.append("/");
}
}
// Try the executable path
if (drillerOutputPath.empty())
{
EBUS_EVENT_RESULT(drillerOutputPath, AZ::ComponentApplicationBus, GetExecutableFolder);
drillerOutputPath.append("/");
}
drillerOutputPath.append("drillerdata.drl");
AZ::IO::SystemFile output;
output.Open(drillerOutputPath.c_str(), AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY);
AZ_Assert(output.IsOpen(), "Failed to open driller output file!");
m_signal.notify_all();
while (true)
{
while (!m_writeQueue.empty())
{
AZStd::vector<AZ::u8, AZ::OSStdAllocator> outBuffer;
outBuffer.swap(m_writeQueue.front());
m_writeQueue.pop_front();
signalLock.unlock();
output.Write(outBuffer.data(), outBuffer.size());
output.Flush();
signalLock.lock();
}
if (!m_isWriterEnabled)
{
break;
}
m_signal.wait(signalLock);
}
output.Close();
}
} // namespace AzFramework
@@ -1,74 +0,0 @@
/*
* 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
#include <AzFramework/Driller/DrillerConsoleAPI.h>
#include <AzCore/Driller/Driller.h>
#include <AzCore/Driller/DefaultStringPool.h>
#include <AzCore/Component/Component.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/containers/deque.h>
#include <AzCore/std/parallel/condition_variable.h>
//#define ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
namespace AZ
{
struct ClassDataReflection;
}
namespace AzFramework
{
/**
* Runs on the machine being drilled and is responsible for communications
* with the DrillerNetworkConsole running on the tool side as well as
* creating DrillerNetSessionStreams for each driller session being started.
*/
class DrillToFileComponent
: public AZ::Component
, public AZ::Debug::DrillerOutputStream
, public DrillerConsoleCommandBus::Handler
{
public:
AZ_COMPONENT(DrillToFileComponent, "{42BAA25D-7CEB-4A37-8BD4-4A1FE2253894}")
//////////////////////////////////////////////////////////////////////////
// AZ::Component
static void Reflect(AZ::ReflectContext* context);
void Activate() override;
void Deactivate() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// DrillerOutputStream
void WriteBinary(const void* data, unsigned int dataSize) override;
void OnEndOfFrame() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// DrillerConsoleCommandBus
void EnumerateAvailableDrillers() override;
void StartDrillerSession(const AZ::Debug::DrillerManager::DrillerListType& requestedDrillers, AZ::u64 sessionId) override;
void StopDrillerSession(AZ::u64 sessionId) override;
//////////////////////////////////////////////////////////////////////////
protected:
void AsyncWritePump();
AZ::u64 m_sessionId;
AZ::Debug::DrillerSession* m_drillerSession;
AZ::Debug::DrillerDefaultStringPool m_stringPool;
AZStd::vector<AZ::u8, AZ::OSStdAllocator> m_frameBuffer;
AZStd::deque<AZStd::vector<AZ::u8, AZ::OSStdAllocator>, AZ::OSStdAllocator> m_writeQueue;
AZStd::mutex m_writerMutex;
AZStd::condition_variable m_signal;
AZStd::thread m_writerThread;
bool m_isWriterEnabled;
};
} // namespace AzFramework
@@ -1,79 +0,0 @@
/*
* 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
#include <AzCore/Driller/Driller.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/EBus/EBus.h>
namespace AzFramework
{
/*
* Descriptors for drillers available on the target machine.
*/
struct DrillerInfo final
{
AZ_RTTI(DrillerInfo, "{197AC318-B65C-4B36-A109-BD25422BF7D0}");
AZ::u32 m_id;
AZStd::string m_groupName;
AZStd::string m_name;
AZStd::string m_description;
};
typedef AZStd::vector<DrillerInfo> DrillerInfoListType;
typedef AZStd::vector<AZ::u32> DrillerListType;
/**
* Driller clients interested in receiving notification events from the
* console should implement this interface.
*/
class DrillerConsoleEvents
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
typedef AZ::OSStdAllocator AllocatorType;
//////////////////////////////////////////////////////////////////////////
virtual ~DrillerConsoleEvents() {}
// A list of available drillers has been received from the target machine.
virtual void OnDrillersEnumerated(const DrillerInfoListType& availableDrillers) = 0;
virtual void OnDrillerSessionStarted(AZ::u64 sessionId) = 0;
virtual void OnDrillerSessionStopped(AZ::u64 sessionId) = 0;
};
typedef AZ::EBus<DrillerConsoleEvents> DrillerConsoleEventBus;
/**
* Commands can be sent to the driller through this interface.
*/
class DrillerConsoleCommands
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
typedef AZ::OSStdAllocator AllocatorType;
// there's only one driller console instance allowed
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
virtual ~DrillerConsoleCommands() {}
// Request an enumeration of available drillers from the target machine
virtual void EnumerateAvailableDrillers() = 0;
// Start a drilling session. This function is normally called internally by DrillerRemoteSession
virtual void StartDrillerSession(const AZ::Debug::DrillerManager::DrillerListType& requestedDrillers, AZ::u64 sessionId) = 0;
// Stop a drilling session. This function is normally called internally by DrillerRemoteSession
virtual void StopDrillerSession(AZ::u64 sessionId) = 0;
};
typedef AZ::EBus<DrillerConsoleCommands> DrillerConsoleCommandBus;
} // namespace AzFramework
@@ -1,740 +0,0 @@
/*
* 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
*
*/
#include <AzFramework/Driller/RemoteDrillerInterface.h>
#include <AzCore/Component/Component.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Driller/Driller.h>
#include <AzCore/Driller/Stream.h>
#include <AzCore/Driller/DefaultStringPool.h>
#include <AzCore/std/containers/fixed_vector.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/Component/TickBus.h>
namespace AzFramework
{
//---------------------------------------------------------------------
// TEMP FOR DEBUGGING ONLY!!!
//---------------------------------------------------------------------
class DebugDrillerRemoteSession
: public DrillerRemoteSession
{
public:
AZ_CLASS_ALLOCATOR(DebugDrillerRemoteSession, AZ::OSAllocator, 0);
DebugDrillerRemoteSession()
{
AZStd::string filename = AZStd::string::format("remotedrill_%llu", static_cast<AZ::u64>(reinterpret_cast<size_t>(static_cast<DrillerRemoteSession*>(this))));
m_file.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE);
}
~DebugDrillerRemoteSession()
{
m_file.Close();
}
virtual void ProcessIncomingDrillerData(const char* streamIdentifier, const void* data, size_t dataSize)
{
(void)streamIdentifier;
m_file.Write(data, dataSize);
}
virtual void OnDrillerConnectionLost()
{
delete this;
}
AZ::IO::SystemFile m_file;
};
//---------------------------------------------------------------------
/**
* These are the different synchronization messages that are used.
*/
namespace NetworkDrillerSyncMsgId
{
static const AZ::Crc32 NetDrillMsg_RequestDrillerEnum = AZ_CRC("NetDrillMsg_RequestEnum", 0x517cca25);
static const AZ::Crc32 NetDrillMsg_RequestStartSession = AZ_CRC("NetDrillMsg_RequestStartSession", 0x5238b5fe);
static const AZ::Crc32 NetDrillMsg_RequestStopSession = AZ_CRC("NetDrillMsg_RequestStopSession", 0x1abe6888);
static const AZ::Crc32 NetDrillMsg_DrillerEnum = AZ_CRC("NetDrillMsg_Enum", 0x3d0a0f76);
};
struct NetDrillerStartSessionRequest
: public TmMsg
{
AZ_CLASS_ALLOCATOR(NetDrillerStartSessionRequest, AZ::OSAllocator, 0);
AZ_RTTI(NetDrillerStartSessionRequest, "{FF899D61-A445-44B5-9B67-8319ACC8BB06}");
NetDrillerStartSessionRequest()
: TmMsg(NetworkDrillerSyncMsgId::NetDrillMsg_RequestStartSession) {}
// TODO: Replace this with the DrillerListType from driller.h
DrillerListType m_drillerIds;
AZ::u64 m_sessionId;
};
struct NetDrillerStopSessionRequest
: public TmMsg
{
AZ_CLASS_ALLOCATOR(NetDrillerStopSessionRequest, AZ::OSAllocator, 0);
AZ_RTTI(NetDrillerStopSessionRequest, "{BCC6524F-287F-48D2-A21A-029215DB24DD}");
NetDrillerStopSessionRequest(AZ::u64 sessionId = 0)
: TmMsg(NetworkDrillerSyncMsgId::NetDrillMsg_RequestStopSession)
, m_sessionId(sessionId) {}
AZ::u64 m_sessionId;
};
struct NetDrillerEnumeration
: public TmMsg
{
AZ_CLASS_ALLOCATOR(NetDrillerEnumeration, AZ::OSAllocator, 0);
AZ_RTTI(NetDrillerEnumeration, "{60E5BED2-F492-4A55-8EF6-2628CD390991}");
NetDrillerEnumeration()
: TmMsg(NetworkDrillerSyncMsgId::NetDrillMsg_DrillerEnum) {}
DrillerInfoListType m_enumeration;
};
//---------------------------------------------------------------------
// DrillerRemoteSession
//---------------------------------------------------------------------
DrillerRemoteSession::DrillerRemoteSession()
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
: m_decompressor(&AZ::AllocatorInstance<AZ::OSAllocator>::Get())
#endif
{
}
//---------------------------------------------------------------------
DrillerRemoteSession::~DrillerRemoteSession()
{
}
//---------------------------------------------------------------------
void DrillerRemoteSession::StartDrilling(const DrillerListType& drillers, const char* captureFile)
{
if (captureFile)
{
m_captureFile.Open(captureFile, AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY);
AZ_Warning("DrillerRemoteSession", m_captureFile.IsOpen(), "Failed to open %s. Driller data will not be saved.", captureFile);
}
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
m_decompressor.StartDecompressor();
#endif
BusConnect(static_cast<AZ::u64>(reinterpret_cast<size_t>(this)));
EBUS_EVENT(DrillerNetworkConsoleCommandBus, StartRemoteDrillerSession, drillers, this);
}
//---------------------------------------------------------------------
void DrillerRemoteSession::StopDrilling()
{
EBUS_EVENT(DrillerNetworkConsoleCommandBus, StopRemoteDrillerSession, static_cast<AZ::u64>(reinterpret_cast<size_t>(this)));
BusDisconnect();
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
if (m_decompressor.IsDecompressorStarted())
{
m_decompressor.StopDecompressor();
}
#endif
m_captureFile.Close();
}
//---------------------------------------------------------------------
void DrillerRemoteSession::LoadCaptureData(const char* fileName)
{
m_captureFile.Open(fileName, AZ::IO::SystemFile::SF_OPEN_READ_ONLY);
AZ_Warning("DrillerRemoteSession", m_captureFile.IsOpen(), "Failed to open %s. No driller data could be loaded.", fileName);
if (m_captureFile.IsOpen())
{
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
m_decompressor.StartDecompressor();
#endif
AZ::IO::SystemFile::SizeType bytesRemaining = m_captureFile.Length();
AZ::IO::SystemFile::SizeType maxReadChunkSize = 1024 * 1024;
AZStd::vector<char> readBuffer;
readBuffer.resize_no_construct(static_cast<size_t>(maxReadChunkSize));
while (bytesRemaining > 0)
{
AZ::IO::SystemFile::SizeType bytesToRead = bytesRemaining < maxReadChunkSize ? bytesRemaining : maxReadChunkSize;
if (m_captureFile.Read(bytesToRead, readBuffer.data()) != bytesToRead)
{
AZ_Warning("DrillerRemoteSession", false, "Failed reading driller data. No more driller data can be read.");
break;
}
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
Decompress(readBuffer.data(), static_cast<size_t>(bytesToRead));
ProcessIncomingDrillerData(fileName, m_uncompressedMsgBuffer.data(), m_uncompressedMsgBuffer.size());
#else
ProcessIncomingDrillerData(fileName, readBuffer.data(), readBuffer.size());
#endif
bytesRemaining -= bytesToRead;
}
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
m_decompressor.StopDecompressor();
#endif
m_captureFile.Close();
}
}
//---------------------------------------------------------------------
void DrillerRemoteSession::OnReceivedMsg(TmMsgPtr msg)
{
AZ_Assert(msg->GetCustomBlob(), "Missing driller frame data!");
if (msg->GetCustomBlobSize() == 0)
{
return;
}
if (m_captureFile.IsOpen())
{
if (m_captureFile.Write(msg->GetCustomBlob(), msg->GetCustomBlobSize()) != msg->GetCustomBlobSize())
{
AZ_Warning("DrillerRemoteSession", false, "Failed writing capture data to %s, no more data will be written out.", m_captureFile.Name());
m_captureFile.Close();
}
}
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
Decompress(msg->GetCustomBlob(), msg->GetCustomBlobSize());
ProcessIncomingDrillerData(m_captureFile.Name(),m_uncompressedMsgBuffer.data(), m_uncompressedMsgBuffer.size());
#else
ProcessIncomingDrillerData(m_captureFile.Name(),msg->GetCustomBlob(), msg->GetCustomBlobSize());
#endif
}
//---------------------------------------------------------------------
void DrillerRemoteSession::Decompress(const void* compressedBuffer, size_t compressedBufferSize)
{
m_uncompressedMsgBuffer.clear();
if (m_uncompressedMsgBuffer.capacity() < compressedBufferSize * 10)
{
m_uncompressedMsgBuffer.reserve(compressedBufferSize * 10);
}
#if defined(ENABLE_COMPRESSION_FOR_REMOTE_DRILLER)
unsigned int compressedBytesRemaining = static_cast<unsigned int>(compressedBufferSize);
unsigned int decompressedBytes = 0;
while (compressedBytesRemaining > 0)
{
unsigned int uncompressedBytes = c_decompressionBufferSize;
unsigned int bytesConsumed = m_decompressor.Decompress(reinterpret_cast<const char*>(compressedBuffer) + decompressedBytes, compressedBytesRemaining, m_decompressionBuffer, uncompressedBytes);
decompressedBytes += bytesConsumed;
compressedBytesRemaining -= bytesConsumed;
m_uncompressedMsgBuffer.insert(m_uncompressedMsgBuffer.end(), &m_decompressionBuffer[0], &m_decompressionBuffer[uncompressedBytes]);
}
#else
m_uncompressedMsgBuffer.insert(m_uncompressedMsgBuffer.end(), &((char*)compressedBuffer)[0], &((char*)compressedBuffer)[compressedBufferSize]);
#endif
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// DrillerNetSessionStream
//---------------------------------------------------------------------
/**
* Represents a driller session on the target machine.
* It is responsible for listening for driller events and forwarding
* them to the console machine.
*/
class DrillerNetSessionStream
: public AZ::Debug::DrillerOutputStream
, AZ::SystemTickBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(DrillerNetSessionStream, AZ::OSAllocator, 0);
DrillerNetSessionStream(AZ::u64 sessionId);
~DrillerNetSessionStream();
//---------------------------------------------------------------------
// DrillerOutputStream
//---------------------------------------------------------------------
virtual void WriteBinary(const void* data, unsigned int dataSize);
virtual void OnEndOfFrame();
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// AZ::SystemTickBus
//---------------------------------------------------------------------
void OnSystemTick() override;
//---------------------------------------------------------------------
static const size_t c_defaultUncompressedBufferSize = 256 * 1024;
static const size_t c_defaultCompressedBufferSize = 32 * 1024;
static const size_t c_bufferCount = 2;
AZ::Debug::DrillerSession* m_session;
AZ::u64 m_sessionId;
TargetInfo m_requestor;
size_t m_activeBuffer;
AZStd::vector<char, AZ::OSStdAllocator> m_uncompressedBuffer[c_bufferCount];
AZStd::vector<char, AZ::OSStdAllocator> m_compressedBuffer[c_bufferCount];
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
// Compression
AZ::ZLib m_compressor;
AZStd::fixed_vector<char, c_defaultCompressedBufferSize> m_compressionBuffer;
#endif
// String Pooling
AZ::Debug::DrillerDefaultStringPool m_stringPool;
// TEMP Debug
//AZ::IO::SystemFile m_file;
};
DrillerNetSessionStream::DrillerNetSessionStream(AZ::u64 sessionId)
: m_session(NULL)
, m_sessionId(sessionId)
, m_activeBuffer(0)
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
, m_compressor(&AZ::AllocatorInstance<AZ::OSAllocator>::Get())
#endif
{
for (size_t i = 0; i < c_bufferCount; ++i)
{
m_uncompressedBuffer[i].reserve(c_defaultUncompressedBufferSize);
m_compressedBuffer[i].reserve(c_defaultCompressedBufferSize);
}
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
// Level 3 compression seems to give pretty good compression at decent speed.
// Speed is paramount for us because initial driller packets can be huge and
// we need to be able to compress the data within the driller report call
// without blocking for too long.
m_compressor.StartCompressor(3);
#endif
SetStringPool(&m_stringPool);
AZ::SystemTickBus::Handler::BusConnect();
}
//---------------------------------------------------------------------
DrillerNetSessionStream::~DrillerNetSessionStream()
{
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
m_compressor.StopCompressor();
#endif
// Debug
//m_file.Close();
}
//---------------------------------------------------------------------
void DrillerNetSessionStream::WriteBinary(const void* data, unsigned int dataSize)
{
size_t activeBuffer = m_activeBuffer;
if (dataSize > 0)
{
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
// Only do the compression when the buffer is full so we don't run the compression all the time
if (m_uncompressedBuffer[activeBuffer].size() + dataSize > c_defaultUncompressedBufferSize)
{
// compress
unsigned int curDataSize = static_cast<unsigned int>(m_uncompressedBuffer[activeBuffer].size());
unsigned int remaining = curDataSize;
while (remaining > 0)
{
unsigned int processedBytes = curDataSize - remaining;
unsigned int compressedBytes = m_compressor.Compress(m_uncompressedBuffer[activeBuffer].data() + processedBytes, remaining, m_compressionBuffer.data(), static_cast<unsigned int>(c_defaultCompressedBufferSize));
if (compressedBytes > 0)
{
m_compressedBuffer[activeBuffer].insert(m_compressedBuffer[activeBuffer].end(), m_compressionBuffer.data(), m_compressionBuffer.data() + compressedBytes);
}
}
m_uncompressedBuffer[activeBuffer].clear();
}
m_uncompressedBuffer[activeBuffer].insert(m_uncompressedBuffer[activeBuffer].end(), reinterpret_cast<const char*>(data), reinterpret_cast<const char*>(data) + dataSize);
#else
// Since we are not compressing, transfer the input directly into our compressed buffer
m_compressedBuffer[activeBuffer].insert(m_compressedBuffer[activeBuffer].end(), reinterpret_cast<const char*>(data), reinterpret_cast<const char*>(data) + dataSize);
#endif
}
}
//---------------------------------------------------------------------
void DrillerNetSessionStream::OnEndOfFrame()
{
size_t activeBuffer = m_activeBuffer;
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
// Write whatever data has not yet been compressed and flush the compressor
unsigned int curDataSize = static_cast<unsigned int>(m_uncompressedBuffer[activeBuffer].size());
unsigned int remaining = curDataSize;
unsigned int compressedBytes = 0;
do
{
unsigned int processedBytes = curDataSize - remaining;
compressedBytes = m_compressor.Compress(m_uncompressedBuffer[activeBuffer].data() + processedBytes, remaining, m_compressionBuffer.data(), static_cast<unsigned int>(c_defaultCompressedBufferSize), AZ::ZLib::FT_SYNC_FLUSH);
if (compressedBytes > 0)
{
m_compressedBuffer[activeBuffer].insert(m_compressedBuffer[activeBuffer].end(), m_compressionBuffer.data(), m_compressionBuffer.data() + compressedBytes);
}
} while (compressedBytes > 0 || remaining > 0);
#endif
m_activeBuffer = (activeBuffer + 1) % 2; // switch buffers
}
//-------------------------------------------------------------------------
void DrillerNetSessionStream::OnSystemTick()
{
// The buffer index we want to send is the one we wrote to in the previous frame.
size_t bufferIndex = (m_activeBuffer + 1) % 2;
if (m_compressedBuffer[bufferIndex].empty())
{
return;
}
TmMsg msg(m_sessionId);
msg.AddCustomBlob(m_compressedBuffer[bufferIndex].data(), m_compressedBuffer[bufferIndex].size());
EBUS_EVENT(TargetManager::Bus, SendTmMessage, m_requestor, msg);
// Debug
//if (!m_file.IsOpen())
//{
// AZStd::string filename = AZStd::string::format("localdrill_%llu", m_sessionId);
// m_file.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE);
//}
//m_file.Write(msg.GetCustomBlob(), msg.GetCustomBlobSize());
// Reset buffers
m_uncompressedBuffer[bufferIndex].clear();
m_compressedBuffer[bufferIndex].clear();
// Buffers may grow during exceptional circumstances. Re-shrink them to their default sizes
// so we don't keep holding on to the memory.
m_uncompressedBuffer[bufferIndex].reserve(c_defaultUncompressedBufferSize);
m_compressedBuffer[bufferIndex].reserve(c_defaultCompressedBufferSize);
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// DrillerNetworkAgent
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::Init()
{
m_cbDrillerEnumRequest = TmMsgCallback(AZStd::bind(&DrillerNetworkAgentComponent::OnRequestDrillerEnum, this, AZStd::placeholders::_1));
m_cbDrillerStartRequest = TmMsgCallback(AZStd::bind(&DrillerNetworkAgentComponent::OnRequestDrillerStart, this, AZStd::placeholders::_1));
m_cbDrillerStopRequest = TmMsgCallback(AZStd::bind(&DrillerNetworkAgentComponent::OnRequestDrillerStop, this, AZStd::placeholders::_1));
}
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::Activate()
{
m_cbDrillerEnumRequest.BusConnect(NetworkDrillerSyncMsgId::NetDrillMsg_RequestDrillerEnum);
m_cbDrillerStartRequest.BusConnect(NetworkDrillerSyncMsgId::NetDrillMsg_RequestStartSession);
m_cbDrillerStopRequest.BusConnect(NetworkDrillerSyncMsgId::NetDrillMsg_RequestStopSession);
TargetManagerClient::Bus::Handler::BusConnect();
}
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::Deactivate()
{
TargetManagerClient::Bus::Handler::BusDisconnect();
m_cbDrillerEnumRequest.BusDisconnect(NetworkDrillerSyncMsgId::NetDrillMsg_RequestDrillerEnum);
m_cbDrillerStartRequest.BusDisconnect(NetworkDrillerSyncMsgId::NetDrillMsg_RequestStartSession);
m_cbDrillerStopRequest.BusDisconnect(NetworkDrillerSyncMsgId::NetDrillMsg_RequestStopSession);
AZ::Debug::DrillerManager* mgr = NULL;
EBUS_EVENT_RESULT(mgr, AZ::ComponentApplicationBus, GetDrillerManager);
for (size_t i = 0; i < m_activeSessions.size(); ++i)
{
if (mgr)
{
mgr->Stop(m_activeSessions[i]->m_session);
}
delete m_activeSessions[i];
}
m_activeSessions.clear();
}
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("DrillerNetworkAgentService", 0xcd2ab821));
}
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("DrillerNetworkAgentService", 0xcd2ab821));
}
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<DrillerNetworkAgentComponent, AZ::Component>()
->Version(1)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
editContext->Class<DrillerNetworkAgentComponent>(
"Driller Network Agent", "Runs on the machine being drilled and communicates with tools")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Category, "Profiling")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
;
}
ReflectNetDrillerClasses(context);
}
}
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::TargetLeftNetwork(TargetInfo info)
{
AZ::Debug::DrillerManager* mgr = NULL;
EBUS_EVENT_RESULT(mgr, AZ::ComponentApplicationBus, GetDrillerManager);
for (AZStd::vector<DrillerNetSessionStream*>::iterator it = m_activeSessions.begin(); it != m_activeSessions.end(); )
{
if ((*it)->m_requestor.GetNetworkId() == info.GetNetworkId())
{
if (mgr)
{
mgr->Stop((*it)->m_session);
}
delete *it;
it = m_activeSessions.erase(it);
}
else
{
++it;
}
}
}
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::OnRequestDrillerEnum(TmMsgPtr msg)
{
AZ::Debug::DrillerManager* mgr = NULL;
EBUS_EVENT_RESULT(mgr, AZ::ComponentApplicationBus, GetDrillerManager);
if (!mgr)
{
return;
}
TargetInfo sendTo;
EBUS_EVENT_RESULT(sendTo, TargetManager::Bus, GetTargetInfo, msg->GetSenderTargetId());
NetDrillerEnumeration drillerEnum;
for (int i = 0; i < mgr->GetNumDrillers(); ++i)
{
AZ::Debug::Driller* driller = mgr->GetDriller(i);
AZ_Assert(driller, "DrillerManager returned a NULL driller. This is not legal!");
drillerEnum.m_enumeration.push_back();
drillerEnum.m_enumeration.back().m_id = driller->GetId();
drillerEnum.m_enumeration.back().m_groupName = driller->GroupName();
drillerEnum.m_enumeration.back().m_name = driller->GetName();
drillerEnum.m_enumeration.back().m_description = driller->GetDescription();
}
EBUS_EVENT(TargetManager::Bus, SendTmMessage, sendTo, drillerEnum);
}
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::OnRequestDrillerStart(TmMsgPtr msg)
{
AZ::Debug::DrillerManager* mgr = NULL;
EBUS_EVENT_RESULT(mgr, AZ::ComponentApplicationBus, GetDrillerManager);
if (!mgr)
{
return;
}
NetDrillerStartSessionRequest* request = azdynamic_cast<NetDrillerStartSessionRequest*>(msg.get());
AZ_Assert(request, "Not a NetDrillerStartSessionRequest msg!");
AZ::Debug::DrillerManager::DrillerListType drillers;
for (size_t i = 0; i < request->m_drillerIds.size(); ++i)
{
AZ::Debug::DrillerManager::DrillerInfo di;
di.id = request->m_drillerIds[i];
drillers.push_back(di);
}
DrillerNetSessionStream* session = aznew DrillerNetSessionStream(request->m_sessionId);
EBUS_EVENT_RESULT(session->m_requestor, TargetManager::Bus, GetTargetInfo, msg->GetSenderTargetId());
m_activeSessions.push_back(session);
session->m_session = mgr->Start(*session, drillers);
}
//---------------------------------------------------------------------
void DrillerNetworkAgentComponent::OnRequestDrillerStop(TmMsgPtr msg)
{
NetDrillerStopSessionRequest* request = azdynamic_cast<NetDrillerStopSessionRequest*>(msg.get());
for (AZStd::vector<DrillerNetSessionStream*>::iterator it = m_activeSessions.begin(); it != m_activeSessions.end(); ++it)
{
if ((*it)->m_sessionId == request->m_sessionId)
{
AZ::Debug::DrillerManager* mgr = NULL;
EBUS_EVENT_RESULT(mgr, AZ::ComponentApplicationBus, GetDrillerManager);
if (mgr)
{
mgr->Stop((*it)->m_session);
}
delete *it;
m_activeSessions.erase(it);
return;
}
}
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// DrillerRemoteConsole
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::Init()
{
m_cbDrillerEnum = TmMsgCallback(AZStd::bind(&DrillerNetworkConsoleComponent::OnReceivedDrillerEnum, this, AZStd::placeholders::_1));
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::Activate()
{
m_cbDrillerEnum.BusConnect(NetworkDrillerSyncMsgId::NetDrillMsg_DrillerEnum);
DrillerNetworkConsoleCommandBus::Handler::BusConnect();
TargetManagerClient::Bus::Handler::BusConnect();
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::Deactivate()
{
TargetManagerClient::Bus::Handler::BusDisconnect();
DrillerNetworkConsoleCommandBus::Handler::BusDisconnect();
m_cbDrillerEnum.BusDisconnect(NetworkDrillerSyncMsgId::NetDrillMsg_DrillerEnum);
for (size_t i = 0; i < m_activeSessions.size(); ++i)
{
EBUS_EVENT(TargetManager::Bus, SendTmMessage, m_curTarget, NetDrillerStopSessionRequest(static_cast<AZ::u64>(reinterpret_cast<size_t>(m_activeSessions[i]))));
m_activeSessions[i]->OnDrillerConnectionLost();
}
m_activeSessions.clear();
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("DrillerNetworkConsoleService", 0x2286125d));
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("DrillerNetworkConsoleService", 0x2286125d));
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
if (serialize)
{
serialize->Class<DrillerNetworkConsoleComponent, AZ::Component>()
->Version(1)
;
if (AZ::EditContext* editContext = serialize->GetEditContext())
{
editContext->Class<DrillerNetworkConsoleComponent>(
"Driller Network Console", "Runs on the tool machine and is responsible for communications with the DrillerNetworkAgent")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Category, "Profiling")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
;
}
ReflectNetDrillerClasses(context);
}
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::EnumerateAvailableDrillers()
{
EBUS_EVENT(TargetManager::Bus, SendTmMessage, m_curTarget, TmMsg(NetworkDrillerSyncMsgId::NetDrillMsg_RequestDrillerEnum));
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::StartRemoteDrillerSession(const DrillerListType& drillers, DrillerRemoteSession* handler)
{
NetDrillerStartSessionRequest request;
request.m_drillerIds = drillers;
request.m_sessionId = static_cast<AZ::u64>(reinterpret_cast<size_t>(handler));
m_activeSessions.push_back(handler);
EBUS_EVENT(TargetManager::Bus, SendTmMessage, m_curTarget, request);
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::StopRemoteDrillerSession(AZ::u64 sessionId)
{
for (size_t i = 0; i < m_activeSessions.size(); ++i)
{
if (sessionId == static_cast<AZ::u64>(reinterpret_cast<size_t>(m_activeSessions[i])))
{
EBUS_EVENT(TargetManager::Bus, SendTmMessage, m_curTarget, NetDrillerStopSessionRequest(sessionId));
m_activeSessions[i] = m_activeSessions.back();
m_activeSessions.pop_back();
}
}
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::DesiredTargetConnected(bool connected)
{
if (connected)
{
EBUS_EVENT_RESULT(m_curTarget, TargetManager::Bus, GetDesiredTarget);
EBUS_EVENT(DrillerNetworkConsoleCommandBus, EnumerateAvailableDrillers);
}
else
{
for (size_t i = 0; i < m_activeSessions.size(); ++i)
{
m_activeSessions[i]->OnDrillerConnectionLost();
}
m_activeSessions.clear();
EBUS_EVENT(DrillerNetworkConsoleEventBus, OnReceivedDrillerEnumeration, DrillerInfoListType());
}
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::DesiredTargetChanged(AZ::u32 newTargetID, AZ::u32 oldTargetID)
{
(void)oldTargetID;
(void)newTargetID;
EBUS_EVENT(DrillerNetworkConsoleEventBus, OnReceivedDrillerEnumeration, DrillerInfoListType());
for (size_t i = 0; i < m_activeSessions.size(); ++i)
{
EBUS_EVENT(TargetManager::Bus, SendTmMessage, m_curTarget, NetDrillerStopSessionRequest(static_cast<AZ::u64>(reinterpret_cast<size_t>(m_activeSessions[i]))));
m_activeSessions[i]->OnDrillerConnectionLost();
}
m_activeSessions.clear();
}
//---------------------------------------------------------------------
void DrillerNetworkConsoleComponent::OnReceivedDrillerEnum(TmMsgPtr msg)
{
NetDrillerEnumeration* drillerEnum = azdynamic_cast<NetDrillerEnumeration*>(msg.get());
AZ_Assert(drillerEnum, "No NetDrillerEnumeration message!");
EBUS_EVENT(DrillerNetworkConsoleEventBus, OnReceivedDrillerEnumeration, drillerEnum->m_enumeration);
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// ReflectNetDrillerClasses
//---------------------------------------------------------------------
void ReflectNetDrillerClasses(AZ::ReflectContext* context)
{
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
if (serialize)
{
// Assume no one else will register our classes.
if (serialize->FindClassData(DrillerInfo::RTTI_Type()) == nullptr)
{
serialize->Class<DrillerInfo>()
->Field("Id", &DrillerInfo::m_id)
->Field("GroupName", &DrillerInfo::m_groupName)
->Field("Name", &DrillerInfo::m_name)
->Field("Description", &DrillerInfo::m_description);
serialize->Class<NetDrillerStartSessionRequest, TmMsg>()
->Field("DrillerIds", &NetDrillerStartSessionRequest::m_drillerIds)
->Field("SessionId", &NetDrillerStartSessionRequest::m_sessionId);
serialize->Class<NetDrillerStopSessionRequest, TmMsg>()
->Field("SessionId", &NetDrillerStopSessionRequest::m_sessionId);
serialize->Class<NetDrillerEnumeration, TmMsg>()
->Field("Enumeration", &NetDrillerEnumeration::m_enumeration);
}
}
}
//---------------------------------------------------------------------
} // namespace AzFramework
@@ -1,217 +0,0 @@
/*
* 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
*
*/
#ifndef AZFRAMEWORK_REMOTE_DRILLER_INTERFACE_H
#define AZFRAMEWORK_REMOTE_DRILLER_INTERFACE_H
#include <AzCore/Driller/Driller.h>
#include <AzCore/Compression/Compression.h>
#include <AzCore/Component/Component.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Driller/DrillerConsoleAPI.h>
#include <AzFramework/TargetManagement/TargetManagementAPI.h>
//#define ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
namespace AZ
{
struct ClassDataReflection;
}
namespace AzFramework
{
/**
* Represents a remote driller session on the tool machine.
* It is responsible for receiving and processing remote driller data.
* Driller clients should derive from this class and implement the virtual interfaces.
*/
class DrillerRemoteSession
: public TmMsgBus::Handler
{
public:
DrillerRemoteSession();
~DrillerRemoteSession();
// Called when new driller data arrives
virtual void ProcessIncomingDrillerData(const char* streamIdentifier, const void* data, size_t dataSize) = 0;
// Called when the connection to the driller is lost. The session should be deleted in response to this message
virtual void OnDrillerConnectionLost() = 0;
// Start drilling the selected drillers as part of this session
void StartDrilling(const DrillerListType& drillers, const char* captureFile);
// Stop this drill session
void StopDrilling();
// Replay a previously captured driller session from file
void LoadCaptureData(const char* fileName);
protected:
//---------------------------------------------------------------------
// TmMsgBus
//---------------------------------------------------------------------
virtual void OnReceivedMsg(TmMsgPtr msg);
//---------------------------------------------------------------------
void Decompress(const void* compressedBuffer, size_t compressedBufferSize);
static const AZ::u32 c_decompressionBufferSize = 128 * 1024;
AZStd::vector<char> m_uncompressedMsgBuffer;
#ifdef ENABLE_COMPRESSION_FOR_REMOTE_DRILLER
AZ::ZLib m_decompressor;
char m_decompressionBuffer[c_decompressionBufferSize];
#endif
AZ::IO::SystemFile m_captureFile;
};
/**
* Driller clients interested in receiving notification events from the
* network console should implement this interface.
*/
class DrillerNetworkConsoleEvents
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
typedef AZ::OSStdAllocator AllocatorType;
//////////////////////////////////////////////////////////////////////////
virtual ~DrillerNetworkConsoleEvents() {}
// A list of available drillers has been received from the target machine.
virtual void OnReceivedDrillerEnumeration(const DrillerInfoListType& availableDrillers) = 0;
};
typedef AZ::EBus<DrillerNetworkConsoleEvents> DrillerNetworkConsoleEventBus;
/**
* The network driller console implements this interface.
* Commands can be sent to the network console through this interface.
*/
class DrillerNetworkConsoleCommands
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
typedef AZ::OSStdAllocator AllocatorType;
// there's only one driller console instance allowed
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
virtual ~DrillerNetworkConsoleCommands() {}
// Request an enumeration of available drillers from the target machine
virtual void EnumerateAvailableDrillers() = 0;
// Start a drilling session. This function is normally called internally by DrillerRemoteSession
virtual void StartRemoteDrillerSession(const DrillerListType& drillers, DrillerRemoteSession* handler) = 0;
// Stop a drilling session. This function is normally called internally by DrillerRemoteSession
virtual void StopRemoteDrillerSession(AZ::u64 sessionId) = 0;
};
typedef AZ::EBus<DrillerNetworkConsoleCommands> DrillerNetworkConsoleCommandBus;
class DrillerNetSessionStream;
/**
* Runs on the machine being drilled and is responsible for communications
* with the DrillerNetworkConsole running on the tool side as well as
* creating DrillerNetSessionStreams for each driller session being started.
*/
class DrillerNetworkAgentComponent
: public AZ::Component
, public TargetManagerClient::Bus::Handler
{
public:
AZ_COMPONENT(DrillerNetworkAgentComponent, "{B587A74D-6190-4149-91CB-0EA69936BD59}")
//////////////////////////////////////////////////////////////////////////
// AZ::Component
virtual void Init();
virtual void Activate();
virtual void Deactivate();
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void Reflect(AZ::ReflectContext* context);
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// TargetManagerClient
virtual void TargetLeftNetwork(TargetInfo info);
//////////////////////////////////////////////////////////////////////////
protected:
//////////////////////////////////////////////////////////////////////////
// TmMsg handlers
virtual void OnRequestDrillerEnum(TmMsgPtr msg);
virtual void OnRequestDrillerStart(TmMsgPtr msg);
virtual void OnRequestDrillerStop(TmMsgPtr msg);
//////////////////////////////////////////////////////////////////////////
TmMsgCallback m_cbDrillerEnumRequest;
TmMsgCallback m_cbDrillerStartRequest;
TmMsgCallback m_cbDrillerStopRequest;
AZStd::vector<DrillerNetSessionStream*> m_activeSessions;
};
/**
* Runs on the tool machine and is responsible for communications with the
* DrillerNetworkAgent.
*/
class DrillerNetworkConsoleComponent
: public AZ::Component
, public DrillerNetworkConsoleCommandBus::Handler
, public TargetManagerClient::Bus::Handler
{
public:
AZ_COMPONENT(DrillerNetworkConsoleComponent, "{78ACADA4-F2C7-4320-8E97-59DD8B9BE33A}")
//////////////////////////////////////////////////////////////////////////
// AZ::Component
virtual void Init();
virtual void Activate();
virtual void Deactivate();
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void Reflect(AZ::ReflectContext* context);
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// DrillerNetworkConsoleCommandBus
virtual void EnumerateAvailableDrillers();
virtual void StartRemoteDrillerSession(const DrillerListType& drillers, DrillerRemoteSession* handler);
virtual void StopRemoteDrillerSession(AZ::u64 sessionId);
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// TargetManagerClient
virtual void DesiredTargetConnected(bool connected);
virtual void DesiredTargetChanged(AZ::u32 newTargetID, AZ::u32 oldTargetID);
//////////////////////////////////////////////////////////////////////////
protected:
//////////////////////////////////////////////////////////////////////////
// TmMsg handlers
virtual void OnReceivedDrillerEnum(TmMsgPtr msg);
//////////////////////////////////////////////////////////////////////////
typedef AZStd::vector<DrillerRemoteSession*> ActiveSessionListType;
ActiveSessionListType m_activeSessions;
TargetInfo m_curTarget;
TmMsgCallback m_cbDrillerEnum;
};
void ReflectNetDrillerClasses(AZ::ReflectContext* context);
} // namespace AzFramework
#endif // AZFRAMEWORK_REMOTE_DRILLER_INTERFACE_H
#pragma once
@@ -123,11 +123,6 @@ set(FILES
Entity/SliceGameEntityOwnershipServiceBus.h
Entity/PrefabEntityOwnershipService.h
Entity/PrefabEntityOwnershipService.cpp
Driller/RemoteDrillerInterface.cpp
Driller/RemoteDrillerInterface.h
Driller/DrillerConsoleAPI.h
Driller/DrillToFileComponent.h
Driller/DrillToFileComponent.cpp
Components/ComponentAdapter.h
Components/ComponentAdapter.inl
Components/ComponentAdapterHelpers.h
@@ -11,8 +11,6 @@
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <AzCore/std/string/conversions.h>
#include <AzFramework/Driller/RemoteDrillerInterface.h>
#include <AzFramework/Driller/DrillToFileComponent.h>
#include <GridMate/Drillers/CarrierDriller.h>
#include <GridMate/Drillers/ReplicaDriller.h>
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
@@ -37,12 +35,6 @@ namespace AzGameFramework
void GameApplication::StartCommon(AZ::Entity* systemEntity)
{
AzFramework::Application::StartCommon(systemEntity);
if (GetDrillerManager())
{
GetDrillerManager()->Register(aznew GridMate::Debug::CarrierDriller());
GetDrillerManager()->Register(aznew GridMate::Debug::ReplicaDriller());
}
}
void GameApplication::MergeSettingsToRegistry(AZ::SettingsRegistryInterface& registry)
@@ -92,10 +84,6 @@ namespace AzGameFramework
components.emplace_back(azrtti_typeid<AzFramework::TargetManagementComponent>());
#endif
// Note that this component is registered by AzFramework.
// It must be registered here instead of in the module so that existence of AzFrameworkModule is guaranteed.
components.emplace_back(azrtti_typeid<AzFramework::DrillerNetworkAgentComponent>());
return components;
}
@@ -104,9 +92,6 @@ namespace AzGameFramework
AzFramework::Application::CreateStaticModules(outModules);
outModules.emplace_back(aznew AzGameFrameworkModule());
// have to let the metrics system know that it's ok to send back the name of the DrillerNetworkAgentComponent to Amazon as plain text, without hashing
EBUS_EVENT(AzFramework::MetricsPlainTextNameRegistrationBus, RegisterForNameSending, AZStd::vector<AZ::Uuid>{ azrtti_typeid<AzFramework::DrillerNetworkAgentComponent>() });
}
void GameApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const
@@ -7,24 +7,15 @@
*/
#include <AzGameFramework/AzGameFrameworkModule.h>
// Component includes
#include <AzFramework/Driller/RemoteDrillerInterface.h>
#include <AzFramework/Driller/DrillToFileComponent.h>
namespace AzGameFramework
{
AzGameFrameworkModule::AzGameFrameworkModule()
: AZ::Module()
{
m_descriptors.insert(m_descriptors.end(), {
AzFramework::DrillToFileComponent::CreateDescriptor(),
});
}
AZ::ComponentTypeList AzGameFrameworkModule::GetRequiredSystemComponents() const
{
return AZ::ComponentTypeList{
azrtti_typeid<AzFramework::DrillToFileComponent>(),
};
return {};
}
}
@@ -35,7 +35,6 @@
#include <AzFramework/Asset/AssetCatalogComponent.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzFramework/TargetManagement/TargetManagementComponent.h>
#include <AzFramework/Driller/RemoteDrillerInterface.h>
#include <AzCore/Driller/Driller.h>
@@ -484,8 +483,6 @@ namespace LegacyFramework
void Application::CreateApplicationComponents()
{
EnsureComponentCreated(AzFramework::TargetManagementComponent::RTTI_Type());
EnsureComponentCreated(AzFramework::DrillerNetworkConsoleComponent::RTTI_Type());
EnsureComponentCreated(AzFramework::DrillerNetworkAgentComponent::RTTI_Type());
}
void Application::CreateSystemComponents()
@@ -506,8 +503,6 @@ namespace LegacyFramework
ComponentApplication::RegisterCoreComponents();
RegisterComponentDescriptor(AzFramework::TargetManagementComponent::CreateDescriptor());
RegisterComponentDescriptor(AzFramework::DrillerNetworkConsoleComponent::CreateDescriptor());
RegisterComponentDescriptor(AzFramework::DrillerNetworkAgentComponent::CreateDescriptor());
RegisterComponentDescriptor(AzToolsFramework::Framework::CreateDescriptor());
}
}
@@ -1117,7 +1117,6 @@ namespace UnitTest
const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
Debug::DrillerManager* GetDrillerManager() override { return nullptr; }
void EnumerateEntities(const EntityCallback& /*callback*/) override {}
void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {}
//////////////////////////////////////////////////////////////////////////