-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
Converters.java
188 lines (178 loc) · 10.7 KB
/
Converters.java
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.config;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import org.apache.cassandra.schema.SchemaConstants;
import static org.apache.cassandra.config.DataRateSpec.DataRateUnit.MEBIBYTES_PER_SECOND;
/**
* Converters for backward compatibility with the old cassandra.yaml where duration, data rate and
* data storage configuration parameters were provided only by value and the expected unit was part of the configuration
* parameter name(suffix). (CASSANDRA-15234)
* It is important to be noted that this converter is not intended to be used when we don't change name of a configuration
* parameter but we want to add unit. This would always default to the old value provided without a unit at the moment.
* In case this functionality is needed at some point, please, raise a Jira ticket. There is only one exception handling
* three parameters (key_cache_save_period, row_cache_save_period, counter_cache_save_period) - the SECONDS_CUSTOM_DURATION
* converter.
*/
public enum Converters
{
/**
* This converter is used when we change the name of a cassandra.yaml configuration parameter but we want to be
* able to still use the old name too. No units involved.
*/
IDENTITY(null, null, o -> o, o -> o),
MILLIS_DURATION_LONG(Long.class, DurationSpec.LongMillisecondsBound.class,
DurationSpec.LongMillisecondsBound::new,
o -> o == null ? null : o.toMilliseconds()),
MILLIS_DURATION_INT(Integer.class, DurationSpec.IntMillisecondsBound.class,
DurationSpec.IntMillisecondsBound::new,
o -> o == null ? null : o.toMilliseconds()),
MILLIS_DURATION_DOUBLE(Double.class, DurationSpec.IntMillisecondsBound.class,
o -> Double.isNaN(o) ? new DurationSpec.IntMillisecondsBound(0) :
new DurationSpec.IntMillisecondsBound(o, TimeUnit.MILLISECONDS),
o -> (double) o.toMilliseconds()),
/**
* This converter is used to support backward compatibility for parameters where in the past -1 was used as a value
* Example: credentials_update_interval_in_ms = -1 and credentials_update_interval = null are equal.
*/
MILLIS_CUSTOM_DURATION(Integer.class, DurationSpec.IntMillisecondsBound.class,
o -> o == -1 ? null : new DurationSpec.IntMillisecondsBound(o),
o -> o == null ? -1 : o.toMilliseconds()),
SECONDS_DURATION(Integer.class, DurationSpec.IntSecondsBound.class,
DurationSpec.IntSecondsBound::new,
o -> o == null ? null : o.toSeconds()),
NEGATIVE_SECONDS_DURATION(Integer.class, DurationSpec.IntSecondsBound.class,
o -> o < 0 ? new DurationSpec.IntSecondsBound(0) : new DurationSpec.IntSecondsBound(o),
o -> o == null ? null : o.toSeconds()),
/**
* This converter is used to support backward compatibility for Duration parameters where we added the opportunity
* for the users to add a unit in the parameters' values but we didn't change the names. (key_cache_save_period,
* row_cache_save_period, counter_cache_save_period)
* Example: row_cache_save_period = 0 and row_cache_save_period = 0s (quantity of 0s) are equal.
*/
SECONDS_CUSTOM_DURATION(String.class, DurationSpec.IntSecondsBound.class,
DurationSpec.IntSecondsBound::inSecondsString,
o -> o == null ? null : Long.toString(o.toSeconds())),
/**
* This converter is used to support backward compatibility for parameters where in the past -1 was used as a value
* Example: index_summary_resize_interval_in_minutes = -1 and index_summary_resize_interval = null are equal.
*/
MINUTES_CUSTOM_DURATION(Integer.class, DurationSpec.IntMinutesBound.class,
o -> o == -1 ? null : new DurationSpec.IntMinutesBound(o),
o -> o == null ? -1 : o.toMinutes()),
MEBIBYTES_DATA_STORAGE_LONG(Long.class, DataStorageSpec.LongMebibytesBound.class,
DataStorageSpec.LongMebibytesBound::new,
o -> o == null ? null : o.toMebibytes()),
MEBIBYTES_DATA_STORAGE_INT(Integer.class, DataStorageSpec.IntMebibytesBound.class,
DataStorageSpec.IntMebibytesBound::new,
o -> o == null ? null : o.toMebibytes()),
NEGATIVE_MEBIBYTES_DATA_STORAGE_INT(Integer.class, DataStorageSpec.IntMebibytesBound.class,
o -> o < 0 ? null : new DataStorageSpec.IntMebibytesBound(o),
o -> o == null ? -1 : o.toMebibytes()),
KIBIBYTES_DATASTORAGE(Integer.class, DataStorageSpec.IntKibibytesBound.class,
DataStorageSpec.IntKibibytesBound::new,
o -> o == null ? null : o.toKibibytes()),
BYTES_DATASTORAGE(Integer.class, DataStorageSpec.IntBytesBound.class,
DataStorageSpec.IntBytesBound::new,
o -> o == null ? null : o.toBytes()),
LONG_BYTES_DATASTORAGE_MEBIBYTES_INT(Integer.class, DataStorageSpec.LongBytesBound.class,
o -> o == null ? null : new DataStorageSpec.LongBytesBound(o, DataStorageSpec.DataStorageUnit.MEBIBYTES),
o -> o == null ? null : o.toMebibytesInt()),
LONG_BYTES_DATASTORAGE_MEBIBYTES_DATASTORAGE(DataStorageSpec.IntMebibytesBound.class, DataStorageSpec.LongBytesBound.class,
o -> o == null ? null : new DataStorageSpec.LongBytesBound(o.toBytesInLong()),
o -> o == null ? null : new DataStorageSpec.IntMebibytesBound(o.toMebibytesInt())),
/**
* This converter is used to support backward compatibility for parameters where in the past negative number was used as a value
* Example: native_transport_max_concurrent_requests_in_bytes_per_ip = -1 and native_transport_max_request_data_in_flight_per_ip = null
* are equal. All negative numbers are printed as 0 in virtual tables.
*/
BYTES_CUSTOM_DATASTORAGE(Long.class, DataStorageSpec.LongBytesBound.class,
o -> o == -1 ? null : new DataStorageSpec.LongBytesBound(o),
o -> o == null ? null : o.toBytes()),
MEBIBYTES_PER_SECOND_DATA_RATE(Integer.class, DataRateSpec.LongBytesPerSecondBound.class,
i -> new DataRateSpec.LongBytesPerSecondBound(i, MEBIBYTES_PER_SECOND),
o -> o == null ? null : o.toMebibytesPerSecondAsInt()),
/**
* This converter is a custom one to support backward compatibility for stream_throughput_outbound and
* inter_dc_stream_throughput_outbound which were provided in megabits per second prior CASSANDRA-15234.
*/
MEGABITS_TO_BYTES_PER_SECOND_DATA_RATE(Integer.class, DataRateSpec.LongBytesPerSecondBound.class,
i -> DataRateSpec.LongBytesPerSecondBound.megabitsPerSecondInBytesPerSecond(i),
o -> o == null ? null : o.toMegabitsPerSecondAsInt()),
KEYSPACE_COUNT_THRESHOLD_TO_GUARDRAIL(int.class, int.class,
i -> i - SchemaConstants.getLocalAndReplicatedSystemKeyspaceNames().size(),
o -> o == null ? null : o + SchemaConstants.getLocalAndReplicatedSystemKeyspaceNames().size()),
TABLE_COUNT_THRESHOLD_TO_GUARDRAIL(int.class, int.class,
i -> i - SchemaConstants.getLocalAndReplicatedSystemTableNames().size(),
o -> o == null ? null : o + SchemaConstants.getLocalAndReplicatedSystemTableNames().size());
private final Class<?> oldType;
private final Class<?> newType;
private final Function<Object, Object> convert;
private final Function<Object, Object> reverseConvert;
<Old, New> Converters(Class<Old> oldType, Class<New> newType, Function<Old, New> convert, Function<New, Old> reverseConvert)
{
this.oldType = oldType;
this.newType = newType;
this.convert = (Function<Object, Object>) convert;
this.reverseConvert = (Function<Object, Object>) reverseConvert;
}
/**
* A method to identify what type is needed to be returned by the converter used for a configuration parameter
* in {@link Replaces} annotation in {@link Config}
*
* @return class type
*/
public Class<?> getOldType()
{
return oldType;
}
/**
* Expected return type from {@link #convert(Object)}, and input type to {@link #unconvert(Object)}
*
* @return type that {@link #convert(Object)} is expected to return
*/
public Class<?> getNewType()
{
return newType;
}
/**
* Apply the converter specified as part of the {@link Replaces} annotation in {@link Config}
*
* @param value we will use from cassandra.yaml to create a new {@link Config} parameter of type {@link DurationSpec},
* {@link DataRateSpec} or {@link DataStorageSpec}
* @return new object of type {@link DurationSpec}, {@link DataRateSpec} or {@link DataStorageSpec}
*/
public Object convert(Object value)
{
if (value == null) return null;
return convert.apply(value);
}
/**
* Apply the converter specified as part of the {@link Replaces} annotation in {@link Config} to get config parameters'
* values in the old format pre-CASSANDRA-15234 and in the right units, used in the Virtual Tables to ensure backward
* compatibility
*
* @param value we will use to calculate the output value
* @return the numeric value
*/
public Object unconvert(Object value)
{
return reverseConvert.apply(value);
}
}