17
17
package com .alibaba .fluss .config ;
18
18
19
19
import com .alibaba .fluss .annotation .Internal ;
20
+ import com .alibaba .fluss .annotation .VisibleForTesting ;
20
21
import com .alibaba .fluss .exception .IllegalConfigurationException ;
21
22
22
23
import org .slf4j .Logger ;
29
30
import java .io .FileInputStream ;
30
31
import java .io .IOException ;
31
32
import java .io .InputStreamReader ;
33
+ import java .util .ArrayList ;
34
+ import java .util .Collections ;
35
+ import java .util .List ;
32
36
33
37
/* This file is based on source code of Apache Flink Project (https://flink.apache.org/), licensed by the Apache
34
38
* Software Foundation (ASF) under the Apache License, Version 2.0. See the NOTICE file distributed with this work for
@@ -46,19 +50,20 @@ public class GlobalConfiguration {
46
50
47
51
private static final Logger LOG = LoggerFactory .getLogger (GlobalConfiguration .class );
48
52
49
- public static final String FLUSS_CONF_FILENAME = "server.yaml" ;
53
+ @ VisibleForTesting
54
+ public static final String [] FLUSS_CONF_FILENAME = new String [] {"server.yaml" , "common.yaml" };
50
55
51
56
// --------------------------------------------------------------------------------------------
52
57
53
58
private GlobalConfiguration () {}
54
59
55
60
/**
56
- * Load the configuration files from the config file specified by key {@link
61
+ * Loads the configuration files from the config file specified by key {@link
57
62
* #SERVER_CONFIG_FILE} in {@code dynamicProperties}. If no config file is specified, it'll load
58
- * the configuration from the specified {@code defaultConfigDir}.
63
+ * the common configuration from the specified {@code defaultConfigDir}.
59
64
*
60
65
* <p>If the {@code dynamicProperties} is not null, then it is added to the loaded
61
- * configuration.
66
+ * configuration. Dynamic configuration options take precedence over file configuration options.
62
67
*
63
68
* @param defaultConfigDir directory to load the configuration from when no config file is
64
69
* specified in the dynamic properties
@@ -67,16 +72,42 @@ private GlobalConfiguration() {}
67
72
*/
68
73
public static Configuration loadConfiguration (
69
74
final String defaultConfigDir , @ Nullable final Configuration dynamicProperties ) {
75
+ return loadConfiguration (defaultConfigDir , Collections .emptyList (), dynamicProperties );
76
+ }
70
77
71
- File yamlConfigFile = null ;
78
+ /**
79
+ * Loads the configuration as described in {@link GlobalConfiguration#loadConfiguration(String,
80
+ * Configuration)}, but allows to specify a list of files that should be loaded from {@code
81
+ * defaultConfigDir} in addition to the common configuration, in case the user does not specify
82
+ * {@link #SERVER_CONFIG_FILE} in {@code dynamicProperties}.
83
+ *
84
+ * <p>The configuration files are read in the specified order. If multiple configuration files
85
+ * are given, and a configuration option is present in at least two of them, the configuration
86
+ * option in the <i>latest</i> configuration file that contains the option takes precedence.
87
+ * Additionally, dynamic configuration options take precedence over configuration options given
88
+ * in <i>any</i> file.
89
+ *
90
+ * @param defaultConfigDir see {@link GlobalConfiguration#loadConfiguration(String,
91
+ * Configuration)}
92
+ * @param additionalDefaultFiles a list of additional config files that should be loaded from
93
+ * defaultConfigDir that will be read in the given order
94
+ * @param dynamicProperties see {@link GlobalConfiguration#loadConfiguration(String,
95
+ * Configuration)}
96
+ */
97
+ public static Configuration loadConfiguration (
98
+ final String defaultConfigDir ,
99
+ final List <String > additionalDefaultFiles ,
100
+ @ Nullable final Configuration dynamicProperties ) {
101
+
102
+ List <File > yamlConfigFiles = new ArrayList <>();
72
103
73
104
// first, try to get the config file name from the dynamic properties
74
105
// user passed
75
106
if (dynamicProperties != null && dynamicProperties .contains (SERVER_CONFIG_FILE )) {
76
107
// get the config file name passed by user
77
108
String configFileName = dynamicProperties .getString (SERVER_CONFIG_FILE );
78
109
dynamicProperties .removeConfig (SERVER_CONFIG_FILE );
79
- yamlConfigFile = new File (configFileName );
110
+ File yamlConfigFile = new File (configFileName );
80
111
if (!yamlConfigFile .exists () && !yamlConfigFile .isFile ()) {
81
112
throw new IllegalConfigurationException (
82
113
"The given configuration file name '"
@@ -85,9 +116,10 @@ public static Configuration loadConfiguration(
85
116
+ yamlConfigFile .getAbsolutePath ()
86
117
+ ") does not describe an existing file." );
87
118
}
119
+ yamlConfigFiles .add (yamlConfigFile );
88
120
}
89
121
90
- if (yamlConfigFile == null ) {
122
+ if (yamlConfigFiles . isEmpty () ) {
91
123
// try to load from the default conf dir
92
124
if (defaultConfigDir == null ) {
93
125
throw new IllegalArgumentException (
@@ -102,11 +134,41 @@ public static Configuration loadConfiguration(
102
134
+ confDirFile .getAbsolutePath ()
103
135
+ ") does not describe an existing directory." );
104
136
}
105
- // get Fluss yaml configuration file from dir
106
- yamlConfigFile = new File (confDirFile , FLUSS_CONF_FILENAME );
137
+
138
+ // get Fluss yaml configuration files from dir
139
+ final File serverYamlFile = new File (confDirFile , FLUSS_CONF_FILENAME [0 ]);
140
+ final File commonYamlFile = new File (confDirFile , FLUSS_CONF_FILENAME [1 ]);
141
+
142
+ // 1. check if old and new configuration files are mixed which is not supported
143
+ if (serverYamlFile .exists () && commonYamlFile .exists ()) {
144
+ throw new IllegalConfigurationException (
145
+ "Only one of "
146
+ + FLUSS_CONF_FILENAME [0 ]
147
+ + " and "
148
+ + FLUSS_CONF_FILENAME [1 ]
149
+ + " may be specified." );
150
+ }
151
+
152
+ // 2. backward compatability, use server.yaml
153
+ if (serverYamlFile .exists ()) {
154
+ yamlConfigFiles .add (new File (confDirFile , FLUSS_CONF_FILENAME [0 ]));
155
+ }
156
+
157
+ // 3. latest configuration setup: load common.yaml and additionally specified, dedicated
158
+ // configuration files
159
+ if (commonYamlFile .exists ()) {
160
+ yamlConfigFiles .add (new File (confDirFile , FLUSS_CONF_FILENAME [1 ]));
161
+
162
+ for (String additionalDefaultFile : additionalDefaultFiles ) {
163
+ yamlConfigFiles .add (new File (confDirFile , additionalDefaultFile ));
164
+ }
165
+ }
107
166
}
108
167
109
- Configuration configuration = loadYAMLResource (yamlConfigFile );
168
+ Configuration configuration = loadYAMLResource (yamlConfigFiles .remove (0 ));
169
+ for (File yamlConfigFile : yamlConfigFiles ) {
170
+ configuration .addAll (loadYAMLResource (yamlConfigFile ));
171
+ }
110
172
111
173
logConfiguration ("Loading" , configuration );
112
174
0 commit comments