Project

General

Profile

Statistics
| Branch: | Revision:

root / src / envir / sectionbasedconfig.h @ 636cbdd5

History | View | Annotate | Download (11.8 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//  SECTIONBASEDCONFIG.H - part of
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//  Author: Andras Varga
7
//
8
//==========================================================================
9
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992-2008 Andras Varga
12
  Copyright (C) 2006-2008 OpenSim Ltd.
13

14
  This file is distributed WITHOUT ANY WARRANTY. See the file
15
  `license' for details on this and other legal matters.
16
*--------------------------------------------------------------*/
17
18
#ifndef SECTIONBASEDCONFIG_H_
19
#define SECTIONBASEDCONFIG_H_
20
21
#include <map>
22
#include <vector>
23
#include <set>
24
#include <string>
25
#include "envirdefs.h"
26
#include "cconfiguration.h"
27
#include "cconfigreader.h"
28
#include "stringpool.h"
29
30
NAMESPACE_BEGIN
31
32
class PatternMatcher;
33
class Scenario;
34
35
36
/**
37
 * Wraps a cConfigurationReader (usually an InifileReader), and presents
38
 * its contents on a higher level towards the simulation.
39
 *
40
 * This object "flattens out" the configuration with respect to an
41
 * active section, i.e. the section fallback sequence ("extends") is
42
 * resolved, and sections are made invisible to the user.
43
 */
44
class ENVIR_API SectionBasedConfiguration : public cConfigurationEx
45
{
46
  private:
47
    // if we make our own copy, we only need cConfigurationReader for initialization, and after that it can be disposed of
48
    class KeyValue1 : public cConfiguration::KeyValue {
49
      public:
50
        static std::string nullbasedir;
51
        const std::string *basedirRef; // points into basedirs[]
52
        std::string key;
53
        std::string value;
54
        KeyValue1() {basedirRef = &nullbasedir;}
55
        KeyValue1(const std::string *bd, const char *k, const char *v) {basedirRef = bd?bd:&nullbasedir; key = k; value = v;}
56
57
        // virtual functions implementing the KeyValue interface
58
        virtual const char *getKey() const   {return key.c_str();}
59
        virtual const char *getValue() const {return value.c_str();}
60
        virtual const char *getBaseDirectory() const {return basedirRef->c_str();}
61
    };
62
63
    cConfigurationReader *ini;
64
    std::vector<KeyValue1> commandLineOptions;
65
    std::string activeConfig;
66
    int activeRunNumber;
67
    std::string runId;
68
69
    typedef std::set<std::string> StringSet;
70
    StringSet basedirs;  // stores ini file locations (absolute paths)
71
72
    // config entries (i.e. keys not containing a dot or wildcard)
73
    std::map<std::string,KeyValue1> config;  //XXX use const char * and CommonStringPool
74
75
    class KeyValue2 : public KeyValue1 {
76
      public:
77
        PatternMatcher *ownerPattern; // key without the suffix
78
        PatternMatcher *suffixPattern; // only filled in when this is a wildcard group
79
        PatternMatcher *fullPathPattern; // when present, match against this instead of ownerPattern & suffixPattern
80
81
        KeyValue2(const KeyValue1& e) : KeyValue1(e) {
82
            ownerPattern = suffixPattern = fullPathPattern = NULL;
83
        }
84
        KeyValue2(const KeyValue2& e) : KeyValue1(e) {
85
            ownerPattern = e.ownerPattern;
86
            suffixPattern = e.suffixPattern;
87
            fullPathPattern = e.fullPathPattern;
88
        }
89
        //FIXME patterns never get deleted?
90
    };
91
92
    // Some explanation. Basically we could just store all entries in order,
93
    // and when a param fullPath etc comes in, just match it against all entries
94
    // linearly. However, we optimize on this: the parameter names in the keys
95
    // rarely contain wildcards, so if we group all entries by parameter
96
    // name, we can find the right group by just one map lookup, thereby significantly
97
    // reducing the number of entries to match against. For example,
98
    // if the parameter "Net.host[1].radio.power" comes in, we only match it
99
    // against the group which contains the keys ending in ".power" (e.g.
100
    // "**.server.radio.power", "**.host[0].**.power", etc).
101
    // If there is an entry which contains a wildcard in the parameter name part,
102
    // that unfortunately has to be added to all suffix groups.
103
    //
104
    // Examples:
105
    // Parameter keys:
106
    //   **.host[*].address  ==> goes into the "address" suffix group; ownerPattern="**.host[*]"
107
    //   **.host[*].addr*    ==> goes into the wildcard suffix group; ownerPattern="**.host[*]", suffixPattern="addr*"
108
    //   **.address          ==> goes into the "address" suffix group; ownerPattern="**"
109
    //   **.addr*            ==> goes into the wildcard suffix group; ownerPattern="**"
110
    //   **                  ==> goes into the wildcard suffix group as "*"; ownerPattern="**"
111
    //   **.**               ==> goes into the wildcard suffix group as "*"; ownerPattern="**"
112
    //   **-*                ==> goes into the wildcard suffix group as "*-*"; ownerPattern="**"
113
    //   **-**               ==> goes into the wildcard suffix group as "*-*"(?); ownerPattern="**"
114
    //
115
    // Per-object config keys:
116
    //   **.tcp.eedVector.record-interval ==> goes into the "record-interval" suffix group; ownerPattern="**.tcp.eedVector"
117
    //   **.tcp.eedVector.record-*"       ==> goes into the wildcard suffix group; ownerPattern="**.tcp.eedVector", suffixPattern="record-*"
118
    //
119
    struct SuffixGroup {
120
        std::vector<KeyValue2> entries;
121
    };
122
123
    std::map<std::string,SuffixGroup> suffixGroups;
124
    SuffixGroup wildcardSuffixGroup;
125
126
    // getConfigEntry() etc return a reference to nullEntry when the
127
    // requested key is not found
128
    class NullKeyValue : public cConfiguration::KeyValue
129
    {
130
      private:
131
        std::string defaultBasedir;
132
      public:
133
        void setBaseDirectory(const char *s) {defaultBasedir = s;}
134
        virtual const char *getKey() const   {return NULL;}
135
        virtual const char *getValue() const {return NULL;}
136
        virtual const char *getBaseDirectory() const {return defaultBasedir.c_str();}
137
    };
138
    NullKeyValue nullEntry;
139
140
    // predefined variables (${configname} etc) and iteration variables. id-to-value map.
141
    // Also stores iterator positions (i.e. the iteration counter), with key "&varname"
142
    typedef std::map<std::string,std::string> StringMap;
143
    StringMap variables;
144
145
    // storage for values returned by substituteVariables()
146
    CommonStringPool stringPool;
147
148
  public:
149
    /**
150
     * Used during scenario resolution: an iteration variable in the
151
     * configuration. An iteration spec may be in one of the following forms:
152
     * ${1,2,5,10}; ${x=1,2,5,10}. (Note: ${x} is just an iteration variable
153
     * _reference_, not an an iteration variable itself.
154
     *
155
     * varid identifies the variable; for named variables it's the same as
156
     * varname. For unnamed ones, it is a string like "2-5-0", composed of
157
     * (sectionId, entryId, index), so that it identifies the place
158
     * where the value has to be substituted back.
159
     *
160
     * It is also possible to do "parallel iterations": the ${1..9 ! varname}
161
     * notation means that "if variable varname is at its kth iteration,
162
     * take the kth value from 0..9 as well". That is, this iteration and
163
     * varname's iterator are advanced in lockstep.
164
     */
165
    struct IterationVariable {
166
        std::string varid;   // identifies the variable, see above
167
        std::string varname; // printable variable name ("x"); may be a generated one like "0"; never empty
168
        std::string value;   // "1,2,5..10"; never empty
169
        std::string parvar;  // "in parallel to" variable", as in the ${1,2,5..10 ! var} notation
170
    };
171
172
  private:
173
    void clear();
174
    int internalFindSection(const char *section) const;
175
    int internalGetSectionId(const char *section) const;
176
    int internalFindEntry(int sectionId, const char *key) const;
177
    const char *internalGetValue(const std::vector<int>& sectionChain, const char *key, const char *fallbackValue=NULL) const;
178
    int resolveConfigName(const char *configName) const;
179
    std::vector<int> resolveSectionChain(int sectionId) const;
180
    std::vector<int> resolveSectionChain(const char *section) const;
181
    void addEntry(const KeyValue1& entry);
182
    static void splitKey(const char *key, std::string& outOwnerName, std::string& outGroupName);
183
    static bool entryMatches(const KeyValue2& entry, const char *moduleFullPath, const char *paramName);
184
    std::vector<IterationVariable> collectIterationVariables(const std::vector<int>& sectionChain) const;
185
    static void parseVariable(const char *pos, std::string& outVarname, std::string& outValue, std::string& outParVar, const char *&outEndPos);
186
    std::string substituteVariables(const char *text, int sectionId, int entryId) const;
187
    bool isPredefinedVariable(const char *varname) const;
188
    void setupVariables(const char *configName, int runNumber, Scenario *scenario, const std::vector<int>& sectionChain);
189
    KeyValue1 convert(int sectionId, int entryId);
190
    static bool isIgnorableConfigKey(const char *ignoredKeyPatterns, const char *key);
191
    static cConfigOption *lookupConfigOption(const char *key);
192
193
  public:
194
    SectionBasedConfiguration();
195
    virtual ~SectionBasedConfiguration();
196
197
    /**
198
     * This cConfiguration uses a cConfigurationReader as input; the reader
199
     * should be passed with this method.
200
     */
201
    virtual void setConfigurationReader(cConfigurationReader *ini);
202
203
    /**
204
     * Specifies config options passed on the command line. These options
205
     * are global (effective for all configs), cannot be per-object options,
206
     * and take precedence over the ones read from the ini file (i.e. from
207
     * cConfigurationReader). This method immediately validates the option
208
     * names, and thows an error for unrecogized/unacceptable ones.
209
     */
210
    virtual void setCommandLineConfigOptions(const std::map<std::string,std::string>& options);
211
212
    /** @name Methods that implement the cConfiguration(Ex) interface. */
213
    //@{
214
    virtual void initializeFrom(cConfiguration *bootConfig);
215
    virtual const char *getFileName() const;
216
    virtual void validate(const char *ignorableConfigKeys) const;
217
    virtual std::vector<std::string> getConfigNames();
218
    virtual void activateConfig(const char *configName, int runNumber=0);
219
    virtual std::string getConfigDescription(const char *configName) const;
220
    virtual std::string getBaseConfig(const char *configName) const;
221
    virtual int getNumRunsInConfig(const char *configName) const;
222
    virtual std::vector<std::string> unrollConfig(const char *configName, bool detailed) const;
223
    virtual const char *getActiveConfigName() const;
224
    virtual int getActiveRunNumber() const;
225
    virtual const char *getConfigValue(const char *key) const;
226
    virtual const KeyValue& getConfigEntry(const char *key) const;
227
    virtual std::vector<const char *> getMatchingConfigKeys(const char *pattern) const;
228
    virtual const char *getParameterValue(const char *moduleFullPath, const char *paramName, bool hasDefaultValue) const;
229
    virtual const KeyValue& getParameterEntry(const char *moduleFullPath, const char *paramName, bool hasDefaultValue) const;
230
    virtual std::vector<const char *> getParameterKeyValuePairs() const;
231
    virtual const char *getPerObjectConfigValue(const char *objectFullPath, const char *keySuffix) const;
232
    virtual const KeyValue& getPerObjectConfigEntry(const char *objectFullPath, const char *keySuffix) const;
233
    virtual std::vector<const char *> getMatchingPerObjectConfigKeys(const char *objectFullPath, const char *keySuffixPattern) const;
234
    virtual std::vector<const char *> getMatchingPerObjectConfigKeySuffixes(const char *objectFullPath, const char *keySuffixPattern) const;
235
    virtual const char *getVariable(const char *varname) const;
236
    virtual std::vector<const char *> getIterationVariableNames() const;
237
    virtual std::vector<const char *> getPredefinedVariableNames() const;
238
    virtual const char *getVariableDescription(const char *varname) const;
239
    virtual const char *substituteVariables(const char *value);
240
    virtual void dump() const;
241
    //@}
242
};
243
244
NAMESPACE_END
245
246
247
#endif
248