620b51077dd97784026e0de0b9fc0fcf208b0d60
[platform/upstream/coreclr.git] / src / vm / fastserializer.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 #include "common.h"
6 #include "fastserializer.h"
7 #include "diagnosticsipc.h"
8
9 #ifdef FEATURE_PERFTRACING
10
11 // Event Pipe has previously implemented a feature called "forward references"
12 // As a result of work on V3 of Event Pipe (https://github.com/Microsoft/perfview/pull/532) it got removed
13 // if you need it, please use git to restore it
14
15 IpcStreamWriter::IpcStreamWriter(uint64_t id, IpcStream *pStream) : _pStream(pStream)
16 {
17     CONTRACTL
18     {
19         NOTHROW;
20         GC_TRIGGERS;
21         MODE_ANY;
22         PRECONDITION(_pStream != nullptr);
23     }
24     CONTRACTL_END;
25
26     if (_pStream == nullptr)
27         return;
28
29     uint32_t nBytesWritten = 0;
30     bool fSuccess = _pStream->Write(&id, sizeof(id), nBytesWritten);
31     if (!fSuccess)
32     {
33         delete _pStream;
34         _pStream = nullptr;
35     }
36 }
37
38 IpcStreamWriter::~IpcStreamWriter()
39 {
40     CONTRACTL
41     {
42         NOTHROW;
43         GC_TRIGGERS;
44         MODE_ANY;
45     }
46     CONTRACTL_END;
47
48     delete _pStream;
49 }
50
51 bool IpcStreamWriter::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const
52 {
53     CONTRACTL
54     {
55         NOTHROW;
56         GC_NOTRIGGER;
57         MODE_PREEMPTIVE;
58         PRECONDITION(lpBuffer != nullptr);
59         PRECONDITION(nBytesToWrite > 0);
60     }
61     CONTRACTL_END;
62
63     if (_pStream == nullptr)
64         return false;
65     if (lpBuffer == nullptr || nBytesToWrite == 0)
66         return false;
67     return _pStream->Write(lpBuffer, nBytesToWrite, nBytesWritten);
68 }
69
70 FileStreamWriter::FileStreamWriter(const SString &outputFilePath)
71 {
72     CONTRACTL
73     {
74         THROWS;
75         GC_TRIGGERS;
76         MODE_ANY;
77     }
78     CONTRACTL_END;
79     m_pFileStream = new CFileStream();
80     if (FAILED(m_pFileStream->OpenForWrite(outputFilePath)))
81     {
82         _ASSERTE(!"Unable to open file for write.");
83         delete m_pFileStream;
84         m_pFileStream = NULL;
85         return;
86     }
87 }
88
89 FileStreamWriter::~FileStreamWriter()
90 {
91     CONTRACTL
92     {
93         NOTHROW;
94         GC_TRIGGERS;
95         MODE_ANY;
96     }
97     CONTRACTL_END;
98
99     delete m_pFileStream;
100 }
101
102 bool FileStreamWriter::Write(const void *lpBuffer, const uint32_t nBytesToWrite, uint32_t &nBytesWritten) const
103 {
104     CONTRACTL
105     {
106         NOTHROW;
107         GC_NOTRIGGER;
108         MODE_PREEMPTIVE;
109         PRECONDITION(lpBuffer != nullptr);
110         PRECONDITION(nBytesToWrite > 0);
111     }
112     CONTRACTL_END;
113
114     if (m_pFileStream == nullptr)
115         return false;
116
117     ULONG outCount;
118     HRESULT hResult = m_pFileStream->Write(lpBuffer, nBytesToWrite, &outCount);
119     nBytesWritten = static_cast<uint32_t>(outCount);
120     return hResult == S_OK;
121 }
122
123 FastSerializer::FastSerializer(StreamWriter *pStreamWriter) : m_pStreamWriter(pStreamWriter)
124 {
125     CONTRACTL
126     {
127         THROWS;
128         GC_TRIGGERS;
129         MODE_ANY;
130         PRECONDITION(m_pStreamWriter != NULL);
131     }
132     CONTRACTL_END;
133
134     m_writeErrorEncountered = false;
135     m_currentPos = 0;
136     WriteFileHeader();
137 }
138
139 FastSerializer::~FastSerializer()
140 {
141     CONTRACTL
142     {
143         NOTHROW;
144         GC_TRIGGERS;
145         MODE_ANY;
146     }
147     CONTRACTL_END;
148
149     delete m_pStreamWriter;
150 }
151
152 void FastSerializer::WriteObject(FastSerializableObject *pObject)
153 {
154     CONTRACTL
155     {
156         NOTHROW;
157         GC_NOTRIGGER;
158         MODE_ANY;
159         PRECONDITION(pObject != NULL);
160     }
161     CONTRACTL_END;
162
163     WriteTag(FastSerializerTags::BeginObject);
164
165     WriteSerializationType(pObject);
166
167     // Ask the object to serialize itself using the current serializer.
168     pObject->FastSerialize(this);
169
170     WriteTag(FastSerializerTags::EndObject);
171 }
172
173 void FastSerializer::WriteBuffer(BYTE *pBuffer, unsigned int length)
174 {
175     CONTRACTL
176     {
177         NOTHROW;
178         GC_NOTRIGGER;
179         MODE_PREEMPTIVE;
180         PRECONDITION(pBuffer != NULL);
181         PRECONDITION(length > 0);
182     }
183     CONTRACTL_END;
184
185     if (m_writeErrorEncountered || m_pStreamWriter == NULL)
186         return;
187
188     EX_TRY
189     {
190         uint32_t outCount;
191         m_pStreamWriter->Write(pBuffer, length, outCount);
192
193 #ifdef _DEBUG
194         size_t prevPos = m_currentPos;
195 #endif
196         m_currentPos += outCount;
197
198         // This will cause us to stop writing to the file.
199         // The file will still remain open until shutdown so that we don't
200         // have to take a lock at this level when we touch the file stream.
201         m_writeErrorEncountered = (length != outCount);
202
203 #ifdef _DEBUG
204         _ASSERTE(m_writeErrorEncountered || (prevPos < m_currentPos));
205 #endif
206     }
207     EX_CATCH
208     {
209         m_writeErrorEncountered = true;
210     }
211     EX_END_CATCH(SwallowAllExceptions);
212 }
213
214 void FastSerializer::WriteSerializationType(FastSerializableObject *pObject)
215 {
216     CONTRACTL
217     {
218         NOTHROW;
219         GC_NOTRIGGER;
220         MODE_PREEMPTIVE;
221         PRECONDITION(pObject != NULL);
222     }
223     CONTRACTL_END;
224
225     // Write the BeginObject tag.
226     WriteTag(FastSerializerTags::BeginObject);
227
228     // Write a NullReferenceTag, which implies that the following fields belong to SerializationType.
229     WriteTag(FastSerializerTags::NullReference);
230
231     // Write the SerializationType version fields.
232     int serializationType[2] = {
233         pObject->GetObjectVersion(),
234         pObject->GetMinReaderVersion()};
235     WriteBuffer((BYTE *)&serializationType, sizeof(serializationType));
236
237     // Write the SerializationType TypeName field.
238     const char *strTypeName = pObject->GetTypeName();
239     unsigned int length = (unsigned int)strlen(strTypeName);
240
241     WriteString(strTypeName, length);
242
243     // Write the EndObject tag.
244     WriteTag(FastSerializerTags::EndObject);
245 }
246
247 void FastSerializer::WriteTag(FastSerializerTags tag, BYTE *payload, unsigned int payloadLength)
248 {
249     CONTRACTL
250     {
251         NOTHROW;
252         GC_NOTRIGGER;
253         MODE_PREEMPTIVE;
254     }
255     CONTRACTL_END;
256
257     WriteBuffer((BYTE *)&tag, sizeof(tag));
258     if (payload != NULL)
259     {
260         _ASSERTE(payloadLength > 0);
261         WriteBuffer(payload, payloadLength);
262     }
263 }
264
265 void FastSerializer::WriteFileHeader()
266 {
267     CONTRACTL
268     {
269         NOTHROW;
270         GC_NOTRIGGER;
271         MODE_ANY;
272     }
273     CONTRACTL_END;
274
275     const char *strSignature = "!FastSerialization.1"; // the consumer lib expects exactly the same string, it must not be changed
276     unsigned int length = (unsigned int)strlen(strSignature);
277     WriteString(strSignature, length);
278 }
279
280 void FastSerializer::WriteString(const char *strContents, unsigned int length)
281 {
282     CONTRACTL
283     {
284         NOTHROW;
285         GC_NOTRIGGER;
286         MODE_PREEMPTIVE;
287     }
288     CONTRACTL_END;
289
290     // Write the string length .
291     WriteBuffer((BYTE *)&length, sizeof(length));
292
293     // Write the string contents.
294     WriteBuffer((BYTE *)strContents, length);
295 }
296
297 #endif // FEATURE_PERFTRACING