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
8#ifdef FEATURE_PERFTRACING
9
10// Event Pipe has previously implemented a feature called "forward references"
11// As a result of work on V3 of Event Pipe (https://github.com/Microsoft/perfview/pull/532) it got removed
12// if you need it, please use git to restore it
13
14FastSerializer::FastSerializer(SString &outputFilePath)
15{
16 CONTRACTL
17 {
18 THROWS;
19 GC_TRIGGERS;
20 MODE_ANY;
21 }
22 CONTRACTL_END;
23
24 m_writeErrorEncountered = false;
25 m_currentPos = 0;
26 m_pFileStream = new CFileStream();
27 if(FAILED(m_pFileStream->OpenForWrite(outputFilePath)))
28 {
29 _ASSERTE(!"Unable to open file for write.");
30 delete(m_pFileStream);
31 m_pFileStream = NULL;
32 return;
33 }
34
35 WriteFileHeader();
36}
37
38FastSerializer::~FastSerializer()
39{
40 CONTRACTL
41 {
42 NOTHROW;
43 GC_TRIGGERS;
44 MODE_ANY;
45 }
46 CONTRACTL_END;
47
48 if(m_pFileStream != NULL)
49 {
50 delete(m_pFileStream);
51 m_pFileStream = NULL;
52 }
53}
54
55StreamLabel FastSerializer::GetStreamLabel() const
56{
57 LIMITED_METHOD_CONTRACT;
58
59 return (StreamLabel)m_currentPos;
60}
61
62void FastSerializer::WriteObject(FastSerializableObject *pObject)
63{
64 CONTRACTL
65 {
66 NOTHROW;
67 GC_NOTRIGGER;
68 MODE_ANY;
69 PRECONDITION(pObject != NULL);
70 }
71 CONTRACTL_END;
72
73 WriteTag(FastSerializerTags::BeginObject);
74
75 WriteSerializationType(pObject);
76
77 // Ask the object to serialize itself using the current serializer.
78 pObject->FastSerialize(this);
79
80 WriteTag(FastSerializerTags::EndObject);
81}
82
83void FastSerializer::WriteBuffer(BYTE *pBuffer, unsigned int length)
84{
85 CONTRACTL
86 {
87 NOTHROW;
88 GC_NOTRIGGER;
89 MODE_PREEMPTIVE;
90 PRECONDITION(pBuffer != NULL);
91 PRECONDITION(length > 0);
92 }
93 CONTRACTL_END;
94
95 if(m_writeErrorEncountered || m_pFileStream == NULL)
96 {
97 return;
98 }
99
100 EX_TRY
101 {
102 ULONG outCount;
103 m_pFileStream->Write(pBuffer, length, &outCount);
104
105#ifdef _DEBUG
106 size_t prevPos = m_currentPos;
107#endif
108 m_currentPos += outCount;
109#ifdef _DEBUG
110 _ASSERTE(prevPos < m_currentPos);
111#endif
112
113 if (length != outCount)
114 {
115 // This will cause us to stop writing to the file.
116 // The file will still remain open until shutdown so that we don't have to take a lock at this level when we touch the file stream.
117 m_writeErrorEncountered = true;
118 }
119 }
120 EX_CATCH
121 {
122 m_writeErrorEncountered = true;
123 }
124 EX_END_CATCH(SwallowAllExceptions);
125}
126
127void FastSerializer::WriteSerializationType(FastSerializableObject *pObject)
128{
129 CONTRACTL
130 {
131 NOTHROW;
132 GC_NOTRIGGER;
133 MODE_PREEMPTIVE;
134 PRECONDITION(pObject != NULL);
135 }
136 CONTRACTL_END;
137
138 // Write the BeginObject tag.
139 WriteTag(FastSerializerTags::BeginObject);
140
141 // Write a NullReferenceTag, which implies that the following fields belong to SerializationType.
142 WriteTag(FastSerializerTags::NullReference);
143
144 // Write the SerializationType version fields.
145 int serializationType[2];
146 serializationType[0] = pObject->GetObjectVersion();
147 serializationType[1] = pObject->GetMinReaderVersion();
148 WriteBuffer((BYTE*) &serializationType, sizeof(serializationType));
149
150 // Write the SerializationType TypeName field.
151 const char *strTypeName = pObject->GetTypeName();
152 unsigned int length = (unsigned int)strlen(strTypeName);
153
154 WriteString(strTypeName, length);
155
156 // Write the EndObject tag.
157 WriteTag(FastSerializerTags::EndObject);
158}
159
160
161void FastSerializer::WriteTag(FastSerializerTags tag, BYTE *payload, unsigned int payloadLength)
162{
163 CONTRACTL
164 {
165 NOTHROW;
166 GC_NOTRIGGER;
167 MODE_PREEMPTIVE;
168 }
169 CONTRACTL_END;
170
171 WriteBuffer((BYTE *)&tag, sizeof(tag));
172 if(payload != NULL)
173 {
174 _ASSERTE(payloadLength > 0);
175 WriteBuffer(payload, payloadLength);
176 }
177}
178
179void FastSerializer::WriteFileHeader()
180{
181 CONTRACTL
182 {
183 NOTHROW;
184 GC_NOTRIGGER;
185 MODE_ANY;
186 }
187 CONTRACTL_END;
188
189 const char *strSignature = "!FastSerialization.1"; // the consumer lib expects exactly the same string, it must not be changed
190 unsigned int length = (unsigned int)strlen(strSignature);
191 WriteString(strSignature, length);
192}
193
194void FastSerializer::WriteString(const char *strContents, unsigned int length)
195{
196 CONTRACTL
197 {
198 NOTHROW;
199 GC_NOTRIGGER;
200 MODE_PREEMPTIVE;
201 }
202 CONTRACTL_END;
203
204 // Write the string length .
205 WriteBuffer((BYTE*) &length, sizeof(length));
206
207 // Write the string contents.
208 WriteBuffer((BYTE*) strContents, length);
209}
210
211#endif // FEATURE_PERFTRACING
212