private static unsafe int CreateCategory(int categoryNameHashCode, string categoryName, int counterNameHashCode, string counterName, int instanceNameHashCode, string instanceName) { int categoryNameLength = (categoryName.Length + 1) * 2; int instanceNameLength = (instanceName.Length + 1) * 2; int counterNameLength = (counterName.Length + 1) * 2; IntPtr baseAddress = FileView.FileViewAddress; int totalSize = sizeof(CategoryEntry) + sizeof(InstanceEntry) + sizeof(CounterEntry) + categoryNameLength + instanceNameLength + counterNameLength; //Need to guarantee that the location where we store the counter //value, is DWORD aligend, so 64 bit interlocked operations don't fail. if (totalSize % 8 != 0) { totalSize = totalSize + (8 - (totalSize % 8)); } int freeMemoryOffset = SafeNativeMethods.InterlockedExchangeAdd(baseAddress, totalSize); if (freeMemoryOffset + totalSize > FileView.FileMappingSize) { throw new InvalidOperationException(SR.GetString(SR.CountersOOM)); } CategoryEntry *newCategoryEntryPointer = (CategoryEntry *)((long)baseAddress + freeMemoryOffset); InstanceEntry *newInstanceEntryPointer = (InstanceEntry *)(newCategoryEntryPointer + 1); CounterEntry * newCounterEntryPointer = (CounterEntry *)(newInstanceEntryPointer + 1); newCategoryEntryPointer->CategoryNameOffset = freeMemoryOffset + sizeof(CategoryEntry) + sizeof(InstanceEntry) + sizeof(CounterEntry); newInstanceEntryPointer->InstanceNameOffset = newCategoryEntryPointer->CategoryNameOffset + categoryNameLength; newCounterEntryPointer->CounterNameOffset = newInstanceEntryPointer->InstanceNameOffset + instanceNameLength; newCategoryEntryPointer->CategoryNameHashCode = categoryNameHashCode; newCategoryEntryPointer->NextCategoryOffset = 0; newCategoryEntryPointer->FirstInstanceOffset = (int)((long)newInstanceEntryPointer - (long)baseAddress); Marshal.Copy(categoryName.ToCharArray(), 0, (IntPtr)((long)baseAddress + newCategoryEntryPointer->CategoryNameOffset), categoryName.Length); newInstanceEntryPointer->InstanceNameHashCode = instanceNameHashCode; newInstanceEntryPointer->NextInstanceOffset = 0; newInstanceEntryPointer->FirstCounterOffset = (int)((long)newCounterEntryPointer - (long)baseAddress); newInstanceEntryPointer->RefCount = 1; Marshal.Copy(instanceName.ToCharArray(), 0, (IntPtr)((long)baseAddress + newInstanceEntryPointer->InstanceNameOffset), instanceName.Length); newCounterEntryPointer->CounterNameHashCode = counterNameHashCode; newCounterEntryPointer->NextCounterOffset = 0; newCounterEntryPointer->Value = 0; Marshal.Copy(counterName.ToCharArray(), 0, (IntPtr)((long)baseAddress + newCounterEntryPointer->CounterNameOffset), counterName.Length); return(freeMemoryOffset); }
internal static unsafe string[] GetInstanceNames(int categoryNameHashCode, string categoryName) { IntPtr baseAddress = FileView.FileViewAddress; CategoryEntry *categoryPointer = (CategoryEntry *)(ResolveOffset(4)); if (!FindCategory(categoryNameHashCode, categoryName, categoryPointer, &categoryPointer) || categoryPointer->FirstInstanceOffset == 0) { return(new string[0]); } ArrayList instancesList = new ArrayList(); InstanceEntry *currentInstancePointer = (InstanceEntry *)(ResolveOffset(categoryPointer->FirstInstanceOffset)); if (currentInstancePointer->InstanceNameHashCode == SingleInstanceHashCode) { return(new string[0]); } for (;;) { if (currentInstancePointer->RefCount > 0) { string instanceName = Marshal.PtrToStringUni((IntPtr)(ResolveOffset(currentInstancePointer->InstanceNameOffset))); instancesList.Add(instanceName); } if (currentInstancePointer->NextInstanceOffset == 0) { break; } else { currentInstancePointer = (InstanceEntry *)(ResolveOffset(currentInstancePointer->NextInstanceOffset)); } } string[] instancesNames = new string[instancesList.Count]; instancesList.CopyTo(instancesNames, 0); return(instancesNames); }
internal static unsafe int GetNumberOfInstances(int categoryNameHashCode, string categoryName) { CategoryEntry *categoryPointer = (CategoryEntry *)(ResolveOffset(4)); if (!FindCategory(categoryNameHashCode, categoryName, categoryPointer, &categoryPointer) || categoryPointer->FirstInstanceOffset == 0) { return(0); } int count = 0; InstanceEntry *currentInstancePointer = (InstanceEntry *)(ResolveOffset(categoryPointer->FirstInstanceOffset)); if (currentInstancePointer->InstanceNameHashCode == SingleInstanceHashCode) { return(0); } for (;;) { if (currentInstancePointer->RefCount > 0) { ++count; } if (currentInstancePointer->NextInstanceOffset == 0) { break; } else { currentInstancePointer = (InstanceEntry *)(ResolveOffset(currentInstancePointer->NextInstanceOffset)); } } return(count); }
private static unsafe bool FindCategory(int categoryNameHashCode, string categoryName, CategoryEntry *firstCategoryPointer, CategoryEntry **returnCategoryPointerReference) { CategoryEntry *currentCategoryPointer = firstCategoryPointer; CategoryEntry *previousCategoryPointer = firstCategoryPointer; for (;;) { WaitForCriticalSection(&(currentCategoryPointer->SpinLock)); if (currentCategoryPointer->CategoryNameHashCode == categoryNameHashCode) { string currentCategoryName = Marshal.PtrToStringUni((IntPtr)(ResolveOffset(currentCategoryPointer->CategoryNameOffset))); if (categoryName == currentCategoryName) { *returnCategoryPointerReference = currentCategoryPointer; return(true); } } previousCategoryPointer = currentCategoryPointer; if (currentCategoryPointer->NextCategoryOffset != 0) { currentCategoryPointer = (CategoryEntry *)(ResolveOffset(currentCategoryPointer->NextCategoryOffset)); } else { *returnCategoryPointerReference = previousCategoryPointer; return(false); } } }
private static unsafe IntPtr GetCounter(string categoryName, string counterName, string instanceName) { int categoryNameHashCode = categoryName.GetHashCode(); int counterNameHashCode = counterName.GetHashCode(); int instanceNameHashCode; if (instanceName != "" && instanceName != null) { instanceNameHashCode = instanceName.GetHashCode(); } else { instanceNameHashCode = SingleInstanceHashCode; instanceName = SingleInstanceName; } CategoryEntry *categoryPointer = (CategoryEntry *)(ResolveOffset(4)); while (!FindCategory(categoryNameHashCode, categoryName, categoryPointer, &categoryPointer)) { if (EnterCriticalSection(&(categoryPointer->SpinLock))) { try { int newCategoryOffset = CreateCategory(categoryNameHashCode, categoryName, counterNameHashCode, counterName, instanceNameHashCode, instanceName); //If not the first category node, link it. if (newCategoryOffset != 4) { categoryPointer->NextCategoryOffset = newCategoryOffset; } return((IntPtr)(ResolveOffset(((InstanceEntry *)(ResolveOffset(((CategoryEntry *)(ResolveOffset(newCategoryOffset)))->FirstInstanceOffset)))->FirstCounterOffset))); } finally { ExitCriticalSection(&(categoryPointer->SpinLock)); } } } InstanceEntry *instancePointer = (InstanceEntry *)(ResolveOffset(categoryPointer->FirstInstanceOffset)); while (!FindInstance(instanceNameHashCode, instanceName, instancePointer, &instancePointer)) { if (EnterCriticalSection(&(instancePointer->SpinLock))) { try { int newInstanceOffset = CreateInstance(counterNameHashCode, counterName, instanceNameHashCode, instanceName); //This will never be the first instance node, no need to check instancePointer->NextInstanceOffset = newInstanceOffset; return((IntPtr)(ResolveOffset(((InstanceEntry *)(ResolveOffset(newInstanceOffset)))->FirstCounterOffset))); } finally { ExitCriticalSection(&(instancePointer->SpinLock)); } } } CounterEntry *counterPointer = (CounterEntry *)(ResolveOffset(instancePointer->FirstCounterOffset)); while (!FindCounter(counterNameHashCode, counterName, counterPointer, &counterPointer)) { if (EnterCriticalSection(&(counterPointer->SpinLock))) { try { int newCounterOffset = CreateCounter(counterNameHashCode, counterName); //This will never be the first counter node, no need to check counterPointer->NextCounterOffset = newCounterOffset; return((IntPtr)(ResolveOffset(newCounterOffset))); } finally { ExitCriticalSection(&(counterPointer->SpinLock)); } } } return((IntPtr)counterPointer); }