using System;
using System.Collections.Generic;
+using System.Collections.Concurrent;
using Interlocked = System.Threading.Interlocked;
#if ES_BUILD_STANDALONE
internal readonly byte[] nameMetadata;
#if FEATURE_PERFTRACING
- private IntPtr eventHandle = IntPtr.Zero;
private readonly object eventHandleCreationLock = new object();
#endif
}
#if FEATURE_PERFTRACING
- public IntPtr GetOrCreateEventHandle(EventProvider provider, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes)
+ public IntPtr GetOrCreateEventHandle(EventProvider provider, ConcurrentDictionary<int, IntPtr> eventHandleMap, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes)
{
- if (eventHandle == IntPtr.Zero)
+ IntPtr eventHandle = IntPtr.Zero;
+ if(!eventHandleMap.TryGetValue(descriptor.EventId, out eventHandle))
{
lock (eventHandleCreationLock)
{
- if (eventHandle == IntPtr.Zero)
+ if (!eventHandleMap.TryGetValue(descriptor.EventId, out eventHandle))
{
byte[] metadataBlob = EventPipeMetadataGenerator.Instance.GenerateEventMetadata(
descriptor.EventId,
(EventLevel)descriptor.Level,
descriptor.Version,
eventTypes);
+ uint metadataLength = (metadataBlob != null) ? (uint)metadataBlob.Length : 0;
unsafe
{
descriptor.Version,
descriptor.Level,
pMetadataBlob,
- (uint)metadataBlob.Length);
+ metadataLength);
}
}
}
using System.Runtime.InteropServices;
using System.Security;
using System.Collections.ObjectModel;
+using System.Collections.Concurrent;
#if !ES_BUILD_AGAINST_DOTNET_V35
using Contract = System.Diagnostics.Contracts.Contract;
private byte[] providerMetadata;
#endif
+#if FEATURE_PERFTRACING
+ private ConcurrentDictionary<int, IntPtr> m_eventHandleMap = new ConcurrentDictionary<int, IntPtr>();
+#endif
+
/// <summary>
/// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API).
/// </summary>
EventDescriptor descriptor = new EventDescriptor(identity, level, opcode, (long)keywords);
#if FEATURE_PERFTRACING
- IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, descriptor, eventTypes);
+ IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, m_eventHandleMap, descriptor, eventTypes);
Debug.Assert(eventHandle != IntPtr.Zero);
#else
IntPtr eventHandle = IntPtr.Zero;
}
#if FEATURE_PERFTRACING
- IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, descriptor, eventTypes);
+ IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, m_eventHandleMap, descriptor, eventTypes);
Debug.Assert(eventHandle != IntPtr.Zero);
#else
IntPtr eventHandle = IntPtr.Zero;
}
#if FEATURE_PERFTRACING
- IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, descriptor, eventTypes);
+ IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_provider, m_eventHandleMap, descriptor, eventTypes);
Debug.Assert(eventHandle != IntPtr.Zero);
#else
IntPtr eventHandle = IntPtr.Zero;
uint version,
EventParameterInfo[] parameters)
{
- // eventID : 4 bytes
- // eventName : (eventName.Length + 1) * 2 bytes
- // keywords : 8 bytes
- // eventVersion : 4 bytes
- // level : 4 bytes
- // parameterCount : 4 bytes
- uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;
-
- // Check for an empty payload.
- // Write<T> calls with no arguments by convention have a parameter of
- // type NullTypeInfo which is serialized as nothing.
- if((parameters.Length == 1) && (parameters[0].ParameterType == typeof(EmptyStruct)))
+ byte[] metadata = null;
+ try
{
- parameters = Array.Empty<EventParameterInfo>();
- }
-
- // Increase the metadataLength for parameters.
- foreach (var parameter in parameters)
- {
- metadataLength = metadataLength + parameter.GetMetadataLength();
- }
-
- byte[] metadata = new byte[metadataLength];
-
- // Write metadata: eventID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
- fixed (byte *pMetadata = metadata)
- {
- uint offset = 0;
- WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)eventId);
- fixed(char *pEventName = eventName)
+ // eventID : 4 bytes
+ // eventName : (eventName.Length + 1) * 2 bytes
+ // keywords : 8 bytes
+ // eventVersion : 4 bytes
+ // level : 4 bytes
+ // parameterCount : 4 bytes
+ uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;
+
+ // Check for an empty payload.
+ // Write<T> calls with no arguments by convention have a parameter of
+ // type NullTypeInfo which is serialized as nothing.
+ if ((parameters.Length == 1) && (parameters[0].ParameterType == typeof(EmptyStruct)))
{
- WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pEventName, ((uint)eventName.Length + 1) * 2);
+ parameters = Array.Empty<EventParameterInfo>();
}
- WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
- WriteToBuffer(pMetadata, metadataLength, ref offset, version);
- WriteToBuffer(pMetadata, metadataLength, ref offset, level);
- WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)parameters.Length);
+
+ // Increase the metadataLength for parameters.
foreach (var parameter in parameters)
{
- parameter.GenerateMetadata(pMetadata, ref offset, metadataLength);
+ metadataLength = metadataLength + parameter.GetMetadataLength();
+ }
+
+ metadata = new byte[metadataLength];
+
+ // Write metadata: eventID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
+ fixed (byte* pMetadata = metadata)
+ {
+ uint offset = 0;
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)eventId);
+ fixed (char* pEventName = eventName)
+ {
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (byte*)pEventName, ((uint)eventName.Length + 1) * 2);
+ }
+ WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, version);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, level);
+ WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)parameters.Length);
+ foreach (var parameter in parameters)
+ {
+ parameter.GenerateMetadata(pMetadata, ref offset, metadataLength);
+ }
+ Debug.Assert(metadataLength == offset);
}
- Debug.Assert(metadataLength == offset);
+ }
+ catch
+ {
+ // If a failure occurs during metadata generation, make sure that we don't return
+ // malformed metadata. Instead, return a null metadata blob.
+ // Consumers can either build in knowledge of the event or skip it entirely.
+ metadata = null;
}
return metadata;
// TypeCode : 4 bytes
// PropertyName : NULL-terminated string
TypeCode typeCode = GetTypeCodeExtended(property.typeInfo.DataType);
- Debug.Assert(typeCode != TypeCode.Object);
+
+ // EventPipe does not support this type. Throw, which will cause no metadata to be registered for this event.
+ if(typeCode == TypeCode.Object)
+ {
+ throw new NotSupportedException();
+ }
// Write the type code.
EventPipeMetadataGenerator.WriteToBuffer(pMetadataBlob, blobSize, ref offset, (uint)typeCode);