diff options
author | dotnet-bot <dotnet-bot@microsoft.com> | 2015-10-01 00:47:24 +0300 |
---|---|---|
committer | Scott Mosier <smosier@microsoft.com> | 2015-10-01 00:47:24 +0300 |
commit | ad0323ab91a7b1469b42ca5457ddd631b94294fe (patch) | |
tree | 88fae57e1ec3aae90288463dc07e58f7aebc1de8 /src/Native/Runtime/RhConfig.h | |
parent | 6763d16387778f126ec510c0421783952602f8f7 (diff) |
Initial population of CoreRT Runtime files.
Diffstat (limited to 'src/Native/Runtime/RhConfig.h')
-rw-r--r-- | src/Native/Runtime/RhConfig.h | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/Native/Runtime/RhConfig.h b/src/Native/Runtime/RhConfig.h new file mode 100644 index 000000000..4045db0b4 --- /dev/null +++ b/src/Native/Runtime/RhConfig.h @@ -0,0 +1,130 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// +// Provides simple configuration support through environment variables. Each variable is lazily inspected on +// first query and the resulting value cached for future use. To keep things simple we support reading only +// 32-bit hex quantities and a zero value is considered equivalent to the environment variable not being +// defined. We can get more sophisticated if needs be, but the hope is that very few configuration values are +// exposed in this manner. +// +// Values can also be configured through an rhconfig.ini file. The file must be and ASCII text file, must be +// placed next to the executing assembly, and be named rhconfig.ini. The file consists of one config entry per line +// in the format: <Key>=<Value> +// example: +// RH_HeapVerify=1 +// RH_BreakOnAssert=1 +// + + +#ifndef DACCESS_COMPILE + +#if defined(_DEBUG) || !defined(APP_LOCAL_RUNTIME) +#define RH_ENVIRONMENT_VARIABLE_CONFIG_ENABLED +#endif + +class RhConfig +{ + +#define CONFIG_INI_FILENAME L"rhconfig.ini" +#define CONFIG_INI_NOT_AVAIL (void*)0x1 //signal for ini file failed to load +#define CONFIG_KEY_MAXLEN 50 //arbitrary max length of config keys increase if needed +#define CONFIG_VAL_MAXLEN 8 //32 bit uint in hex + +private: + struct ConfigPair + { + public: + WCHAR Key[CONFIG_KEY_MAXLEN + 1]; //maxlen + null terminator + WCHAR Value[CONFIG_VAL_MAXLEN + 1]; //maxlen + null terminator + }; + + //g_iniSettings is a buffer of ConfigPair structs which when initialized is of length RCV_Count + //the first N settings which are set in rhconfig.ini will be initialized and the remainder with have + //empty string "\0" as a Key and Value + // + //if the buffer has not been initialized (ie the ini file has not been read) the value will be NULL + //if we already attempted to initialize the file and could not find or read the contents the + //value will be CONFIG_INI_NOT_AVAIL to distinguish from the unitialized buffer. + // + //NOTE: g_iniSettings is only set in ReadConfigIni and must be set atomically only once + // using PalInterlockedCompareExchangePointer to avoid races when initializing +private: + void* volatile g_iniSettings = NULL; + +public: + +#define DEFINE_VALUE_ACCESSOR(_name) \ + UInt32 Get##_name() \ + { \ + if (m_uiConfigValuesRead & (1 << RCV_##_name)) \ + return m_uiConfigValues[RCV_##_name]; \ + UInt32 uiValue = ReadConfigValue(L"RH_" L ## #_name); \ + m_uiConfigValues[RCV_##_name] = uiValue; \ + m_uiConfigValuesRead |= 1 << RCV_##_name; \ + return uiValue; \ + } + + +#ifdef _DEBUG +#define DEBUG_CONFIG_VALUE(_name) DEFINE_VALUE_ACCESSOR(_name) +#else +#define DEBUG_CONFIG_VALUE(_name) +#endif +#define RETAIL_CONFIG_VALUE(_name) DEFINE_VALUE_ACCESSOR(_name) +#include "RhConfigValues.h" +#undef DEBUG_CONFIG_VALUE +#undef RETAIL_CONFIG_VALUE + +private: + + UInt32 ReadConfigValue(_In_z_ WCHAR *wszName); + + enum RhConfigValue + { +#define DEBUG_CONFIG_VALUE(_name) RCV_##_name, +#define RETAIL_CONFIG_VALUE(_name) RCV_##_name, +#include "RhConfigValues.h" +#undef DEBUG_CONFIG_VALUE +#undef RETAIL_CONFIG_VALUE + RCV_Count + }; + +//accomidate for the maximum number of config values plus sizable buffer for whitespace 2K +#define CONFIG_FILE_MAXLEN RCV_Count * sizeof(ConfigPair) + 2000 + +private: + _Ret_maybenull_z_ WCHAR* RhConfig::GetConfigPath(); + + //Parses one line of rhconfig.ini and populates values in the passed in configPair + //returns: true if the parsing was successful, false if the parsing failed. + //NOTE: if the method fails configPair is left in an unitialized state + bool ParseConfigLine(_Out_ ConfigPair* configPair, _In_z_ const char * line); + + //reads the configuration values from rhconfig.ini and updates g_iniSettings + //if the file is read succesfully and g_iniSettings will be set to a valid ConfigPair[] of length RCV_Count. + //if the file does not exist or reading the file fails, g_iniSettings is set to CONFIG_INI_NOT_AVAIL + //NOTE: all return paths must set g_iniSettings + void ReadConfigIni(); + + //reads a config value from rhconfig.ini into outputBuffer buffer returning the length of the value. + //lazily reads the file so if the file is not yet read, it will read it on first called + //if the file is not avaliable, or unreadable zero will always be returned + //cchOuputBuffer is the maximum number of characters to write to outputBuffer + UInt32 GetIniVariable(_In_z_ WCHAR* configName, _Out_writes_all_(cchBuff) WCHAR* outputBuffer, _In_ UInt32 cchOuputBuffer); + + static bool priv_isspace(char c) + { + return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'); + } + + + UInt32 m_uiConfigValuesRead; + UInt32 m_uiConfigValues[RCV_Count]; +}; + +extern RhConfig * g_pRhConfig; + +#endif //!DACCESS_COMPILE
\ No newline at end of file |