mirror of https://github.com/apache/cassandra
Represent complex settings as JSON on system_views.settings table
The patch for 5.0 is preserving old behavior, it is possible to turn on JSON representation by a system property. The patch for trunk is by default transforming collections to JSON string but there is the property (same as in 5.0) which has default to be set to true. patch by Marko Tsymbaluk; reviewed by Paulo Motta, Stefan Miklosovic for CASSANDRA-20827 Co-authored-by: Stefan Miklosovic <smiklosovic@apache.org>
This commit is contained in:
parent
7f92e1ac2c
commit
b26e33d506
|
|
@ -1,4 +1,5 @@
|
|||
5.0.6
|
||||
* Represent complex settings as JSON on system_views.settings table (CASSANDRA-20827)
|
||||
* Expose StorageService.dropPreparedStatements via JMX (CASSANDRA-20870)
|
||||
* Sort SSTable TOC entries for determinism (CASSANDRA-20494)
|
||||
Merged from 4.1:
|
||||
|
|
|
|||
|
|
@ -607,6 +607,8 @@ public enum CassandraRelevantProperties
|
|||
USE_NIX_RECURSIVE_DELETE("cassandra.use_nix_recursive_delete"),
|
||||
/** Gossiper compute expiration timeout. Default value 3 days. */
|
||||
VERY_LONG_TIME_MS("cassandra.very_long_time_ms", "259200000"),
|
||||
/** Controls output format for Collection-type settings in system_views.settings table */
|
||||
VIRTUAL_TABLE_COMPLEX_SETTINGS_FORMAT_JSON("cassandra.virtual_table_complex_settings_format_json", "false"),
|
||||
WAIT_FOR_TRACING_EVENTS_TIMEOUT_SECS("cassandra.wait_for_tracing_events_timeout_secs", "0");
|
||||
|
||||
static
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.cassandra.db.virtual;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
|
@ -25,6 +26,7 @@ import java.util.Objects;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import org.apache.cassandra.config.CassandraRelevantProperties;
|
||||
import org.apache.cassandra.config.Config;
|
||||
import org.apache.cassandra.config.Redacted;
|
||||
import org.apache.cassandra.config.DatabaseDescriptor;
|
||||
|
|
@ -36,6 +38,7 @@ import org.apache.cassandra.db.DecoratedKey;
|
|||
import org.apache.cassandra.db.marshal.UTF8Type;
|
||||
import org.apache.cassandra.dht.LocalPartitioner;
|
||||
import org.apache.cassandra.schema.TableMetadata;
|
||||
import org.apache.cassandra.utils.JsonUtils;
|
||||
import org.apache.cassandra.service.ClientWarn;
|
||||
import org.yaml.snakeyaml.introspector.Property;
|
||||
|
||||
|
|
@ -48,6 +51,7 @@ final class SettingsTable extends AbstractVirtualTable
|
|||
protected static final Map<String, Property> PROPERTIES = ImmutableMap.copyOf(getProperties());
|
||||
|
||||
private final Config config;
|
||||
private final boolean useJsonFormat;
|
||||
|
||||
SettingsTable(String keyspace)
|
||||
{
|
||||
|
|
@ -64,6 +68,7 @@ final class SettingsTable extends AbstractVirtualTable
|
|||
.addRegularColumn(VALUE, UTF8Type.instance)
|
||||
.build());
|
||||
this.config = config;
|
||||
this.useJsonFormat = CassandraRelevantProperties.VIRTUAL_TABLE_COMPLEX_SETTINGS_FORMAT_JSON.getBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -99,9 +104,10 @@ final class SettingsTable extends AbstractVirtualTable
|
|||
return null;
|
||||
|
||||
if (value.getClass().isArray())
|
||||
return Arrays.asList((Object[]) value).toString();
|
||||
|
||||
if (value instanceof Map)
|
||||
return tryConstructJson(Arrays.asList((Object[]) value));
|
||||
else if (value instanceof Collection)
|
||||
return tryConstructJson(value);
|
||||
else if (value instanceof Map)
|
||||
{
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
for (Map.Entry<String, Object> entry : ((Map<String, Object>) value).entrySet())
|
||||
|
|
@ -115,12 +121,31 @@ final class SettingsTable extends AbstractVirtualTable
|
|||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return map.toString();
|
||||
return tryConstructJson(map);
|
||||
}
|
||||
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
private String tryConstructJson(Object o)
|
||||
{
|
||||
if (useJsonFormat)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JsonUtils.JSON_OBJECT_MAPPER.writeValueAsString(o);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return o.toString();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return o.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, Property> getProperties()
|
||||
{
|
||||
Loader loader = Properties.defaultLoader();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.apache.cassandra.db.virtual;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -33,6 +34,7 @@ import org.junit.Test;
|
|||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.Row;
|
||||
import org.apache.cassandra.config.CassandraRelevantProperties;
|
||||
import org.apache.cassandra.config.Config;
|
||||
import org.apache.cassandra.config.Redacted;
|
||||
import org.apache.cassandra.config.DefaultLoader;
|
||||
|
|
@ -41,13 +43,17 @@ import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.Int
|
|||
import org.apache.cassandra.config.ParameterizedClass;
|
||||
import org.apache.cassandra.config.TransparentDataEncryptionOptions;
|
||||
import org.apache.cassandra.cql3.CQLTester;
|
||||
import org.apache.cassandra.distributed.shared.WithProperties;
|
||||
import org.apache.cassandra.security.SSLFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.yaml.snakeyaml.introspector.Property;
|
||||
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
public class SettingsTableTest extends CQLTester
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(SettingsTableTest.class);
|
||||
private static final String KS_NAME = "vts";
|
||||
|
||||
private Config config;
|
||||
|
|
@ -172,12 +178,12 @@ public class SettingsTableTest extends CQLTester
|
|||
assertRowsNet(executeNet(q), new Object[] {"credentials_update_interval_in_ms", "-1"});
|
||||
}
|
||||
|
||||
private void check(String setting, String expected) throws Throwable
|
||||
private void check(String keyspaceTable, String setting, String expected)
|
||||
{
|
||||
String q = "SELECT * FROM vts.settings WHERE name = '"+setting+'\'';
|
||||
String q = "SELECT * FROM " + keyspaceTable + " WHERE name = '" + setting + '\'';
|
||||
try
|
||||
{
|
||||
assertRowsNet(executeNet(q), new Object[] {setting, expected});
|
||||
assertRowsNet(executeNet(q), new Object[]{ setting, expected });
|
||||
}
|
||||
catch (AssertionError e)
|
||||
{
|
||||
|
|
@ -185,6 +191,11 @@ public class SettingsTableTest extends CQLTester
|
|||
}
|
||||
}
|
||||
|
||||
private void check(String setting, String expected)
|
||||
{
|
||||
check("vts.settings", setting, expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncryptionOverride() throws Throwable
|
||||
{
|
||||
|
|
@ -353,4 +364,38 @@ public class SettingsTableTest extends CQLTester
|
|||
Assert.assertEquals(settingName, name);
|
||||
Assert.assertEquals(expectedValue, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexSettingsFormatProperty()
|
||||
{
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
parameters.put("seeds", "127.0.0.1:7000");
|
||||
config.seed_provider = new ParameterizedClass("org.apache.cassandra.locator.SimpleSeedProvider", parameters);
|
||||
|
||||
// Test set property to true (collection as json)
|
||||
try (WithProperties properties = new WithProperties().set(CassandraRelevantProperties.VIRTUAL_TABLE_COMPLEX_SETTINGS_FORMAT_JSON, "true"))
|
||||
{
|
||||
table = new SettingsTable("json_true", config);
|
||||
VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace("json_true", ImmutableList.of(table)));
|
||||
|
||||
check("json_true.settings", "data_file_directories", "[\"/my/data/directory\",\"/another/data/directory\"]");
|
||||
check("json_true.settings", "seed_provider.parameters", "{\"seeds\":\"127.0.0.1:7000\"}");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOldBehaviourForComplexSettingsFormatProperty()
|
||||
{
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
parameters.put("seeds", "127.0.0.1:7000");
|
||||
config.seed_provider = new ParameterizedClass("org.apache.cassandra.locator.SimpleSeedProvider", parameters);
|
||||
|
||||
// we are not setting property here to false, we expect it to be false by default
|
||||
|
||||
table = new SettingsTable("json_false", config);
|
||||
VirtualKeyspaceRegistry.instance.register(new VirtualKeyspace("json_false", ImmutableList.of(table)));
|
||||
|
||||
check("json_false.settings", "data_file_directories", "[/my/data/directory, /another/data/directory]");
|
||||
check("json_false.settings", "seed_provider.parameters", "{seeds=127.0.0.1:7000}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue