Welcome to mirror list, hosted at ThFree Co, Russian Federation.

RhConfig.h « Runtime « Native « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b5879c38629b3312a73736d87f9066b1058a2ecd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more 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 FEATURE_ENVIRONMENT_VARIABLE_CONFIG
#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:
        TCHAR Key[CONFIG_KEY_MAXLEN + 1];  //maxlen + null terminator
        TCHAR 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;

#ifdef FEATURE_EMBEDDED_CONFIG
    // g_embeddedSettings works similarly to g_iniSettings, except the source of the data
    // is a data blob generated by the compiler and embedded into the executable.
    void* volatile g_embeddedSettings = NULL;
#endif // FEATURE_EMBEDDED_CONFIG

public:

#define DEFINE_VALUE_ACCESSOR(_name, defaultVal)        \
    UInt32 Get##_name()                                 \
    {                                                   \
        if (m_uiConfigValuesRead & (1 << RCV_##_name))  \
            return m_uiConfigValues[RCV_##_name];       \
        UInt32 uiValue = ReadConfigValue(_T("RH_") _T(#_name), defaultVal); \
        m_uiConfigValues[RCV_##_name] = uiValue;        \
        m_uiConfigValuesRead |= 1 << RCV_##_name;       \
        return uiValue;                                 \
    }


#ifdef _DEBUG
#define DEBUG_CONFIG_VALUE(_name) DEFINE_VALUE_ACCESSOR(_name, 0)
#define DEBUG_CONFIG_VALUE_WITH_DEFAULT(_name, defaultVal) DEFINE_VALUE_ACCESSOR(_name, defaultVal)
#else
#define DEBUG_CONFIG_VALUE(_name) 
#define DEBUG_CONFIG_VALUE_WITH_DEFAULT(_name, defaultVal) 
#endif
#define RETAIL_CONFIG_VALUE(_name) DEFINE_VALUE_ACCESSOR(_name, 0)
#define RETAIL_CONFIG_VALUE_WITH_DEFAULT(_name, defaultVal) DEFINE_VALUE_ACCESSOR(_name, defaultVal)
#include "RhConfigValues.h"
#undef DEBUG_CONFIG_VALUE
#undef RETAIL_CONFIG_VALUE
#undef DEBUG_CONFIG_VALUE_WITH_DEFAULT
#undef RETAIL_CONFIG_VALUE_WITH_DEFAULT

private:

    UInt32 ReadConfigValue(_In_z_ const TCHAR *wszName, UInt32 uiDefault);

    enum RhConfigValue
    {
#define DEBUG_CONFIG_VALUE(_name) RCV_##_name,
#define RETAIL_CONFIG_VALUE(_name) RCV_##_name,
#define DEBUG_CONFIG_VALUE_WITH_DEFAULT(_name, defaultVal) RCV_##_name,
#define RETAIL_CONFIG_VALUE_WITH_DEFAULT(_name, defaultVal) RCV_##_name,
#include "RhConfigValues.h"
#undef DEBUG_CONFIG_VALUE
#undef RETAIL_CONFIG_VALUE
#undef DEBUG_CONFIG_VALUE_WITH_DEFAULT
#undef RETAIL_CONFIG_VALUE_WITH_DEFAULT
        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_ TCHAR* 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
    //cchOutputBuffer is the maximum number of characters to write to outputBuffer
    UInt32 GetIniVariable(_In_z_ const TCHAR* configName, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer);

#ifdef FEATURE_EMBEDDED_CONFIG
    void ReadEmbeddedSettings();

    UInt32 GetEmbeddedVariable(_In_z_ const TCHAR* configName, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer);
#endif // FEATURE_EMBEDDED_CONFIG

    UInt32 GetConfigVariable(_In_z_ const TCHAR* configName, const ConfigPair* configPairs, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer);

    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