Expand IStackResolver into ICaptureAccess to allow section read/write

This commit is contained in:
baldurk
2017-11-16 14:35:48 +00:00
parent a238d3022a
commit bb6452c334
7 changed files with 398 additions and 26 deletions
+1 -1
View File
@@ -668,7 +668,7 @@ struct IReplayManager
:return: The file handle active, or ``None`` if no capture is open.
:rtype: StackResolver
)");
virtual IStackResolver *GetResolver() = 0;
virtual ICaptureAccess *GetCaptureAccess() = 0;
DOCUMENT(R"(Launch an application and inject into it to allow capturing.
+3 -3
View File
@@ -75,12 +75,12 @@ public:
void ShutdownServer();
void PingRemote();
IStackResolver *GetResolver()
ICaptureAccess *GetCaptureAccess()
{
if(m_CaptureFile)
return m_CaptureFile;
if(m_Remote)
return m_Remote;
if(m_CaptureFile)
return m_CaptureFile;
return NULL;
}
+2 -2
View File
@@ -101,10 +101,10 @@ void APIInspector::on_apiEvents_itemSelectionChanged()
if(!ev.callstack.isEmpty())
{
if(m_Ctx.Replay().GetResolver())
if(m_Ctx.Replay().GetCaptureAccess())
{
m_Ctx.Replay().AsyncInvoke([this, ev](IReplayController *) {
rdcarray<rdcstr> stack = m_Ctx.Replay().GetResolver()->GetResolve(ev.callstack);
rdcarray<rdcstr> stack = m_Ctx.Replay().GetCaptureAccess()->GetResolve(ev.callstack);
GUIInvoke::call([this, stack]() { addCallstack(stack); });
});
+3 -3
View File
@@ -1241,7 +1241,7 @@ void MainWindow::OnCaptureLoaded()
ui->action_Resolve_Symbols->setEnabled(false);
m_Ctx.Replay().AsyncInvoke([this](IReplayController *) {
bool hasResolver = m_Ctx.Replay().GetResolver()->HasCallstacks();
bool hasResolver = m_Ctx.Replay().GetCaptureAccess()->HasCallstacks();
GUIInvoke::call([this, hasResolver]() {
ui->action_Resolve_Symbols->setEnabled(hasResolver);
@@ -1505,7 +1505,7 @@ void MainWindow::on_action_Python_Shell_triggered()
void MainWindow::on_action_Resolve_Symbols_triggered()
{
if(!m_Ctx.Replay().GetResolver())
if(!m_Ctx.Replay().GetCaptureAccess())
{
RDDialog::critical(
this, tr("Not Available"),
@@ -1517,7 +1517,7 @@ void MainWindow::on_action_Resolve_Symbols_triggered()
bool finished = false;
m_Ctx.Replay().AsyncInvoke([this, &progress, &finished](IReplayController *) {
bool success = m_Ctx.Replay().GetResolver()->InitResolver(&progress, NULL);
bool success = m_Ctx.Replay().GetCaptureAccess()->InitResolver(&progress, NULL);
if(!success)
{
+53 -7
View File
@@ -1074,11 +1074,57 @@ protected:
~ITargetControl() = default;
};
DOCUMENT(R"(An interface for resolving callstacks. This is separate since it can be either
implemented locally by a file handle, or remotely to an open capture.
DOCUMENT(R"(An interface for accessing a capture, possibly over a network connection. This is a
subset of the functionality provided in :class:`CaptureFile` which only supports import/export
and construction of files.
)");
struct IStackResolver
struct ICaptureAccess
{
DOCUMENT(R"(Locate the index of a section by its name. Returns ``-1`` if the section is not found.
This index should not be cached, as writing sections could re-order the indices.
:param str name: The name of the section to search for.
:return: The index of the section, or ``-1`` if not found.
:rtype: ``int``.
)");
virtual int FindSectionByName(const char *name) = 0;
DOCUMENT(R"(Locate the index of a section by its type. Returns ``-1`` if the section is not found.
This index should not be cached, as writing sections could re-order the indices.
:param SectionType type: The type of the section to search for.
:return: The index of the section, or ``-1`` if not found.
:rtype: ``int``.
)");
virtual int FindSectionByType(SectionType type) = 0;
DOCUMENT(R"(Get the describing properties of the specified section.
:param int index: The index of the section.
:return: The properties of the section, if the index is valid.
:rtype: SectionProperties.
)");
virtual SectionProperties GetSectionProperties(int index) = 0;
DOCUMENT(R"(Get the raw byte contents of the specified section.
:param int index: The index of the section.
:return: The raw contents of the section, if the index is valid.
:rtype: ``bytes``.
)");
virtual bytebuf GetSectionContents(int index) = 0;
DOCUMENT(R"(Writes a new section with specified properties and contents. If an existing section
already has the same type or name, it will be overwritten (two sections cannot share the same type
or name).
:param SectionProperties props: The properties of the section to be written.
:param byte contents: The raw contents of the section.
)");
virtual void WriteSection(const SectionProperties &props, const bytebuf &contents) = 0;
DOCUMENT(R"(Query if callstacks are available.
:return: ``True`` if any callstacks are available, ``False`` otherwise.
@@ -1112,8 +1158,8 @@ Must only be called after :meth:`InitResolver` has returned ``True``.
virtual rdcarray<rdcstr> GetResolve(const rdcarray<uint64_t> &callstack) = 0;
protected:
IStackResolver() = default;
~IStackResolver() = default;
ICaptureAccess() = default;
~ICaptureAccess() = default;
};
DOCUMENT(R"(A connection to a running remote RenderDoc server on another machine. This allows the
@@ -1125,7 +1171,7 @@ much work as possible happening on the local machine.
No preference for a particular value, see :meth:`DebugPixel`.
)");
struct IRemoteServer : public IStackResolver
struct IRemoteServer : public ICaptureAccess
{
DOCUMENT("Closes the connection without affecting the running server.");
virtual void ShutdownConnection() = 0;
@@ -1276,7 +1322,7 @@ protected:
DOCUMENT(R"(A handle to a capture file. Used for simple cheap processing and meta-data fetching
without opening the capture for analysis.
)")
struct ICaptureFile : public IStackResolver
struct ICaptureFile : public ICaptureAccess
{
DOCUMENT("Closes the file handle.");
virtual void Shutdown() = 0;
+271 -10
View File
@@ -61,6 +61,11 @@ enum RemoteServerPacket
eRemoteServer_ListDir,
eRemoteServer_ExecuteAndInject,
eRemoteServer_ShutdownServer,
eRemoteServer_FindSectionByName,
eRemoteServer_FindSectionByType,
eRemoteServer_GetSectionProperties,
eRemoteServer_GetSectionContents,
eRemoteServer_WriteSection,
eRemoteServer_RemoteServerCount,
};
@@ -547,6 +552,121 @@ static void ActiveRemoteClientThread(ClientThread *threadData)
SERIALISE_ELEMENT(StackFrames);
}
}
else if(type == eRemoteServer_FindSectionByName)
{
std::string name;
{
READ_DATA_SCOPE();
SERIALISE_ELEMENT(name);
}
reader.EndChunk();
int index = rdc ? rdc->SectionIndex(name.c_str()) : -1;
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_FindSectionByName);
SERIALISE_ELEMENT(index);
}
}
else if(type == eRemoteServer_FindSectionByType)
{
SectionType sectionType;
{
READ_DATA_SCOPE();
SERIALISE_ELEMENT(sectionType);
}
reader.EndChunk();
int index = rdc ? rdc->SectionIndex(sectionType) : -1;
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_FindSectionByType);
SERIALISE_ELEMENT(index);
}
}
else if(type == eRemoteServer_GetSectionProperties)
{
int index = -1;
{
READ_DATA_SCOPE();
SERIALISE_ELEMENT(index);
}
reader.EndChunk();
SectionProperties props;
if(rdc && index >= 0 && index < rdc->NumSections())
props = rdc->GetSectionProperties(index);
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_GetSectionProperties);
SERIALISE_ELEMENT(props);
}
}
else if(type == eRemoteServer_GetSectionContents)
{
int index = -1;
{
READ_DATA_SCOPE();
SERIALISE_ELEMENT(index);
}
reader.EndChunk();
bytebuf contents;
if(rdc && index >= 0 && index < rdc->NumSections())
{
StreamReader *sectionReader = rdc->ReadSection(index);
contents.resize((size_t)sectionReader->GetSize());
bool success = sectionReader->Read(contents.data(), sectionReader->GetSize());
if(!success)
contents.clear();
delete sectionReader;
}
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_GetSectionContents);
SERIALISE_ELEMENT(contents);
}
}
else if(type == eRemoteServer_WriteSection)
{
SectionProperties props;
bytebuf contents;
{
READ_DATA_SCOPE();
SERIALISE_ELEMENT(props);
SERIALISE_ELEMENT(contents);
}
reader.EndChunk();
if(rdc)
{
StreamWriter *sectionWriter = rdc->WriteSection(props);
if(sectionWriter)
{
sectionWriter->Write(contents.data(), contents.size());
delete sectionWriter;
}
}
}
else if(type == eRemoteServer_CloseLog)
{
reader.EndChunk();
@@ -1268,6 +1388,157 @@ public:
return ret;
}
void CloseCapture(IReplayController *rend)
{
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_CloseLog);
}
rend->Shutdown();
}
int FindSectionByName(const char *name)
{
if(!Connected())
return -1;
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_FindSectionByName);
SERIALISE_ELEMENT(name);
}
int index = -1;
{
READ_DATA_SCOPE();
RemoteServerPacket type = ser.ReadChunk<RemoteServerPacket>();
if(type == eRemoteServer_FindSectionByName)
{
SERIALISE_ELEMENT(index);
}
else
{
RDCERR("Unexpected response to FindSectionByName");
}
ser.EndChunk();
}
return index;
}
int FindSectionByType(SectionType sectionType)
{
if(!Connected())
return -1;
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_FindSectionByType);
SERIALISE_ELEMENT(sectionType);
}
int index = -1;
{
READ_DATA_SCOPE();
RemoteServerPacket type = ser.ReadChunk<RemoteServerPacket>();
if(type == eRemoteServer_FindSectionByType)
{
SERIALISE_ELEMENT(index);
}
else
{
RDCERR("Unexpected response to FindSectionByType");
}
ser.EndChunk();
}
return index;
}
SectionProperties GetSectionProperties(int index)
{
if(!Connected())
return SectionProperties();
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_GetSectionProperties);
SERIALISE_ELEMENT(index);
}
SectionProperties props;
{
READ_DATA_SCOPE();
RemoteServerPacket type = ser.ReadChunk<RemoteServerPacket>();
if(type == eRemoteServer_GetSectionProperties)
{
SERIALISE_ELEMENT(props);
}
else
{
RDCERR("Unexpected response to GetSectionProperties");
}
ser.EndChunk();
}
return props;
}
bytebuf GetSectionContents(int index) override
{
if(!Connected())
return bytebuf();
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_GetSectionContents);
SERIALISE_ELEMENT(index);
}
bytebuf contents;
{
READ_DATA_SCOPE();
RemoteServerPacket type = ser.ReadChunk<RemoteServerPacket>();
if(type == eRemoteServer_GetSectionContents)
{
SERIALISE_ELEMENT(contents);
}
else
{
RDCERR("Unexpected response to GetSectionContents");
}
ser.EndChunk();
}
return contents;
}
void WriteSection(const SectionProperties &props, const bytebuf &contents)
{
if(!Connected())
return;
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_WriteSection);
SERIALISE_ELEMENT(props);
SERIALISE_ELEMENT(contents);
}
}
bool HasCallstacks()
{
if(!Connected())
@@ -1377,16 +1648,6 @@ public:
return StackFrames;
}
void CloseCapture(IReplayController *rend)
{
{
WRITE_DATA_SCOPE();
SCOPED_SERIALISE_CHUNK(eRemoteServer_CloseLog);
}
rend->Shutdown();
}
private:
Network::Socket *m_Socket;
WriteSerialiser writer;
+65
View File
@@ -162,6 +162,15 @@ public:
}
bytebuf GetThumbnail(FileType type, uint32_t maxsize);
// ICaptureAccess
int FindSectionByName(const char *name);
int FindSectionByType(SectionType type);
SectionProperties GetSectionProperties(int index);
bytebuf GetSectionContents(int index);
void WriteSection(const SectionProperties &props, const bytebuf &contents);
bool HasCallstacks();
bool InitResolver(float *progress, volatile bool *killSignal);
rdcarray<rdcstr> GetResolve(const rdcarray<uint64_t> &callstack);
@@ -213,6 +222,7 @@ ReplayStatus CaptureFile::OpenFile(const char *filename, const char *filetype)
if(filetype != NULL && strcmp(filetype, "") && strcmp(filetype, "rdc"))
RDCWARN("Opening file with unrecognised filetype '%s' - treating as 'rdc'", filetype);
delete m_RDC;
m_RDC = new RDCFile;
m_RDC->Open(filename);
}
@@ -582,6 +592,61 @@ bytebuf CaptureFile::GetThumbnail(FileType type, uint32_t maxsize)
return buf;
}
int CaptureFile::FindSectionByName(const char *name)
{
if(!m_RDC)
return -1;
return m_RDC->SectionIndex(name);
}
int CaptureFile::FindSectionByType(SectionType type)
{
if(!m_RDC)
return -1;
return m_RDC->SectionIndex(type);
}
SectionProperties CaptureFile::GetSectionProperties(int index)
{
if(!m_RDC || index < 0 || index >= m_RDC->NumSections())
return SectionProperties();
return m_RDC->GetSectionProperties(index);
}
bytebuf CaptureFile::GetSectionContents(int index)
{
bytebuf ret;
if(!m_RDC || index < 0 || index >= m_RDC->NumSections())
return ret;
StreamReader *reader = m_RDC->ReadSection(index);
ret.resize((size_t)reader->GetSize());
bool success = reader->Read(ret.data(), reader->GetSize());
delete reader;
if(!success)
ret.clear();
return ret;
}
void CaptureFile::WriteSection(const SectionProperties &props, const bytebuf &contents)
{
StreamWriter *writer = m_RDC->WriteSection(props);
if(!writer)
return;
writer->Write(contents.data(), contents.size());
delete writer;
}
bool CaptureFile::HasCallstacks()
{
return m_RDC && m_RDC->SectionIndex(SectionType::ResolveDatabase) >= 0;