| /* |
| * 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.HashSet; |
| import java.util.Set; |
| import java.util.concurrent.TimeUnit; |
| |
| import javax.annotation.Nullable; |
| |
| import com.google.common.primitives.Ints; |
| |
| import org.apache.cassandra.db.virtual.LogMessagesTable; |
| import org.apache.cassandra.exceptions.ConfigurationException; |
| import org.apache.cassandra.service.FileSystemOwnershipCheck; |
| |
| // checkstyle: suppress below 'blockSystemPropertyUsage' |
| |
| /** A class that extracts system properties for the cassandra node it runs within. */ |
| public enum CassandraRelevantProperties |
| { |
| ACQUIRE_RETRY_SECONDS("cassandra.acquire_retry_seconds", "60"), |
| ACQUIRE_SLEEP_MS("cassandra.acquire_sleep_ms", "1000"), |
| ALLOCATE_TOKENS_FOR_KEYSPACE("cassandra.allocate_tokens_for_keyspace"), |
| ALLOW_ALTER_RF_DURING_RANGE_MOVEMENT("cassandra.allow_alter_rf_during_range_movement"), |
| /** If we should allow having duplicate keys in the config file, default to true for legacy reasons */ |
| ALLOW_DUPLICATE_CONFIG_KEYS("cassandra.allow_duplicate_config_keys", "true"), |
| /** If we should allow having both new (post CASSANDRA-15234) and old config keys for the same config item in the yaml */ |
| ALLOW_NEW_OLD_CONFIG_KEYS("cassandra.allow_new_old_config_keys"), |
| ALLOW_UNLIMITED_CONCURRENT_VALIDATIONS("cassandra.allow_unlimited_concurrent_validations"), |
| ALLOW_UNSAFE_AGGRESSIVE_SSTABLE_EXPIRATION("cassandra.allow_unsafe_aggressive_sstable_expiration"), |
| ALLOW_UNSAFE_JOIN("cassandra.allow_unsafe_join"), |
| ALLOW_UNSAFE_REPLACE("cassandra.allow_unsafe_replace"), |
| ALLOW_UNSAFE_TRANSIENT_CHANGES("cassandra.allow_unsafe_transient_changes"), |
| APPROXIMATE_TIME_PRECISION_MS("cassandra.approximate_time_precision_ms", "2"), |
| /** 2 ** GENSALT_LOG2_ROUNDS rounds of hashing will be performed. */ |
| AUTH_BCRYPT_GENSALT_LOG2_ROUNDS("cassandra.auth_bcrypt_gensalt_log2_rounds"), |
| /** We expect default values on cache retries and interval to be sufficient for everyone but have this escape hatch just in case. */ |
| AUTH_CACHE_WARMING_MAX_RETRIES("cassandra.auth_cache.warming.max_retries"), |
| AUTH_CACHE_WARMING_RETRY_INTERVAL_MS("cassandra.auth_cache.warming.retry_interval_ms"), |
| AUTOCOMPACTION_ON_STARTUP_ENABLED("cassandra.autocompaction_on_startup_enabled", "true"), |
| AUTO_BOOTSTRAP("cassandra.auto_bootstrap"), |
| AUTO_REPAIR_FREQUENCY_SECONDS("cassandra.auto_repair_frequency_seconds", convertToString(TimeUnit.MINUTES.toSeconds(5))), |
| BATCHLOG_REPLAY_TIMEOUT_IN_MS("cassandra.batchlog.replay_timeout_in_ms"), |
| BATCH_COMMIT_LOG_SYNC_INTERVAL("cassandra.batch_commitlog_sync_interval_millis", "1000"), |
| /** |
| * When bootstraping how long to wait for schema versions to be seen. |
| */ |
| BOOTSTRAP_SCHEMA_DELAY_MS("cassandra.schema_delay_ms"), |
| /** |
| * When bootstraping we wait for all schema versions found in gossip to be seen, and if not seen in time we fail |
| * the bootstrap; this property will avoid failing and allow bootstrap to continue if set to true. |
| */ |
| BOOTSTRAP_SKIP_SCHEMA_CHECK("cassandra.skip_schema_check"), |
| BROADCAST_INTERVAL_MS("cassandra.broadcast_interval_ms", "60000"), |
| BTREE_BRANCH_SHIFT("cassandra.btree.branchshift", "5"), |
| BTREE_FAN_FACTOR("cassandra.btree.fanfactor"), |
| /** Represents the maximum size (in bytes) of a serialized mutation that can be cached **/ |
| CACHEABLE_MUTATION_SIZE_LIMIT("cassandra.cacheable_mutation_size_limit_bytes", convertToString(1_000_000)), |
| CASSANDRA_ALLOW_SIMPLE_STRATEGY("cassandra.allow_simplestrategy"), |
| CASSANDRA_AVAILABLE_PROCESSORS("cassandra.available_processors"), |
| /** The classpath storage configuration file. */ |
| CASSANDRA_CONFIG("cassandra.config", "cassandra.yaml"), |
| /** |
| * The cassandra-foreground option will tell CassandraDaemon whether |
| * to close stdout/stderr, but it's up to us not to background. |
| * yes/null |
| */ |
| CASSANDRA_FOREGROUND("cassandra-foreground"), |
| CASSANDRA_JMX_AUTHORIZER("cassandra.jmx.authorizer"), |
| CASSANDRA_JMX_LOCAL_PORT("cassandra.jmx.local.port"), |
| CASSANDRA_JMX_REMOTE_LOGIN_CONFIG("cassandra.jmx.remote.login.config"), |
| /** Cassandra jmx remote and local port */ |
| CASSANDRA_JMX_REMOTE_PORT("cassandra.jmx.remote.port"), |
| CASSANDRA_MAX_HINT_TTL("cassandra.maxHintTTL", convertToString(Integer.MAX_VALUE)), |
| CASSANDRA_MINIMUM_REPLICATION_FACTOR("cassandra.minimum_replication_factor"), |
| CASSANDRA_NETTY_USE_HEAP_ALLOCATOR("cassandra.netty_use_heap_allocator"), |
| CASSANDRA_PID_FILE("cassandra-pidfile"), |
| CASSANDRA_RACKDC_PROPERTIES("cassandra-rackdc.properties"), |
| CASSANDRA_SKIP_AUTOMATIC_UDT_FIX("cassandra.skipautomaticudtfix"), |
| CASSANDRA_STREAMING_DEBUG_STACKTRACE_LIMIT("cassandra.streaming.debug_stacktrace_limit", "2"), |
| CASSANDRA_UNSAFE_TIME_UUID_NODE("cassandra.unsafe.timeuuidnode"), |
| CASSANDRA_VERSION("cassandra.version"), |
| /** default heartbeating period is 1 minute */ |
| CHECK_DATA_RESURRECTION_HEARTBEAT_PERIOD("check_data_resurrection_heartbeat_period_milli", "60000"), |
| CHRONICLE_ANNOUNCER_DISABLE("chronicle.announcer.disable"), |
| CLOCK_GLOBAL("cassandra.clock"), |
| CLOCK_MONOTONIC_APPROX("cassandra.monotonic_clock.approx"), |
| CLOCK_MONOTONIC_PRECISE("cassandra.monotonic_clock.precise"), |
| COMMITLOG_ALLOW_IGNORE_SYNC_CRC("cassandra.commitlog.allow_ignore_sync_crc"), |
| COMMITLOG_IGNORE_REPLAY_ERRORS("cassandra.commitlog.ignorereplayerrors"), |
| COMMITLOG_MAX_OUTSTANDING_REPLAY_BYTES("cassandra.commitlog_max_outstanding_replay_bytes", convertToString(1024 * 1024 * 64)), |
| COMMITLOG_MAX_OUTSTANDING_REPLAY_COUNT("cassandra.commitlog_max_outstanding_replay_count", "1024"), |
| COMMITLOG_STOP_ON_ERRORS("cassandra.commitlog.stop_on_errors"), |
| /** |
| * Entities to replay mutations for upon commit log replay, property is meant to contain |
| * comma-separated entities which are either names of keyspaces or keyspaces and tables or their mix. |
| * Examples: |
| * just keyspaces |
| * -Dcassandra.replayList=ks1,ks2,ks3 |
| * specific tables |
| * -Dcassandra.replayList=ks1.tb1,ks2.tb2 |
| * mix of tables and keyspaces |
| * -Dcassandra.replayList=ks1.tb1,ks2 |
| * |
| * If only keyspaces are specified, mutations for all tables in such keyspace will be replayed |
| * */ |
| COMMIT_LOG_REPLAY_LIST("cassandra.replayList"), |
| /** |
| * This property indicates the location for the access file. If com.sun.management.jmxremote.authenticate is false, |
| * then this property and the password and access files, are ignored. Otherwise, the access file must exist and |
| * be in the valid format. If the access file is empty or nonexistent, then no access is allowed. |
| */ |
| COM_SUN_MANAGEMENT_JMXREMOTE_ACCESS_FILE("com.sun.management.jmxremote.access.file"), |
| /** |
| * This property indicates whether password authentication for remote monitoring is |
| * enabled. By default it is disabled - com.sun.management.jmxremote.authenticate |
| */ |
| COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE("com.sun.management.jmxremote.authenticate"), |
| /** This property indicates the path to the password file - com.sun.management.jmxremote.password.file */ |
| COM_SUN_MANAGEMENT_JMXREMOTE_PASSWORD_FILE("com.sun.management.jmxremote.password.file"), |
| /** Port number to enable JMX RMI connections - com.sun.management.jmxremote.port */ |
| COM_SUN_MANAGEMENT_JMXREMOTE_PORT("com.sun.management.jmxremote.port"), |
| /** |
| * The port number to which the RMI connector will be bound - com.sun.management.jmxremote.rmi.port. |
| * An Integer object that represents the value of the second argument is returned |
| * if there is no port specified, if the port does not have the correct numeric format, |
| * or if the specified name is empty or null. |
| */ |
| COM_SUN_MANAGEMENT_JMXREMOTE_RMI_PORT("com.sun.management.jmxremote.rmi.port", "0"), |
| /** This property indicates whether SSL is enabled for monitoring remotely. Default is set to false. */ |
| COM_SUN_MANAGEMENT_JMXREMOTE_SSL("com.sun.management.jmxremote.ssl"), |
| /** |
| * A comma-delimited list of SSL/TLS cipher suites to enable. |
| * Used in conjunction with com.sun.management.jmxremote.ssl - com.sun.management.jmxremote.ssl.enabled.cipher.suites |
| */ |
| COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_CIPHER_SUITES("com.sun.management.jmxremote.ssl.enabled.cipher.suites"), |
| /** |
| * A comma-delimited list of SSL/TLS protocol versions to enable. |
| * Used in conjunction with com.sun.management.jmxremote.ssl - com.sun.management.jmxremote.ssl.enabled.protocols |
| */ |
| COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_PROTOCOLS("com.sun.management.jmxremote.ssl.enabled.protocols"), |
| /** |
| * This property indicates whether SSL client authentication is enabled - com.sun.management.jmxremote.ssl.need.client.auth. |
| * Default is set to false. |
| */ |
| COM_SUN_MANAGEMENT_JMXREMOTE_SSL_NEED_CLIENT_AUTH("com.sun.management.jmxremote.ssl.need.client.auth"), |
| /** Defaults to false for 4.1 but plan to switch to true in a later release the thinking is that environments |
| * may not work right off the bat so safer to add this feature disabled by default */ |
| CONFIG_ALLOW_SYSTEM_PROPERTIES("cassandra.config.allow_system_properties"), |
| CONFIG_LOADER("cassandra.config.loader"), |
| CONSISTENT_DIRECTORY_LISTINGS("cassandra.consistent_directory_listings"), |
| CONSISTENT_RANGE_MOVEMENT("cassandra.consistent.rangemovement", "true"), |
| CONSISTENT_SIMULTANEOUS_MOVES_ALLOW("cassandra.consistent.simultaneousmoves.allow"), |
| CUSTOM_GUARDRAILS_CONFIG_PROVIDER_CLASS("cassandra.custom_guardrails_config_provider_class"), |
| CUSTOM_QUERY_HANDLER_CLASS("cassandra.custom_query_handler_class"), |
| CUSTOM_TRACING_CLASS("cassandra.custom_tracing_class"), |
| /** Controls the type of bufffer (heap/direct) used for shared scratch buffers */ |
| DATA_OUTPUT_BUFFER_ALLOCATE_TYPE("cassandra.dob.allocate_type"), |
| DATA_OUTPUT_STREAM_PLUS_TEMP_BUFFER_SIZE("cassandra.data_output_stream_plus_temp_buffer_size", "8192"), |
| DECAYING_ESTIMATED_HISTOGRAM_RESERVOIR_STRIPE_COUNT("cassandra.dehr_stripe_count", "2"), |
| DEFAULT_PROVIDE_OVERLAPPING_TOMBSTONES("default.provide.overlapping.tombstones"), |
| /** determinism properties for testing */ |
| DETERMINISM_SSTABLE_COMPRESSION_DEFAULT("cassandra.sstable_compression_default", "true"), |
| DETERMINISM_UNSAFE_UUID_NODE("cassandra.unsafe.deterministicuuidnode"), |
| DIAGNOSTIC_SNAPSHOT_INTERVAL_NANOS("cassandra.diagnostic_snapshot_interval_nanos", "60000000000"), |
| DISABLE_AUTH_CACHES_REMOTE_CONFIGURATION("cassandra.disable_auth_caches_remote_configuration"), |
| /** properties to disable certain behaviours for testing */ |
| DISABLE_GOSSIP_ENDPOINT_REMOVAL("cassandra.gossip.disable_endpoint_removal"), |
| DISABLE_PAXOS_AUTO_REPAIRS("cassandra.disable_paxos_auto_repairs"), |
| DISABLE_PAXOS_STATE_FLUSH("cassandra.disable_paxos_state_flush"), |
| DISABLE_SSTABLE_ACTIVITY_TRACKING("cassandra.sstable_activity_tracking", "true"), |
| DISABLE_STCS_IN_L0("cassandra.disable_stcs_in_l0"), |
| DISABLE_TCACTIVE_OPENSSL("cassandra.disable_tcactive_openssl"), |
| /** property for the rate of the scheduled task that monitors disk usage */ |
| DISK_USAGE_MONITOR_INTERVAL_MS("cassandra.disk_usage.monitor_interval_ms", convertToString(TimeUnit.SECONDS.toMillis(30))), |
| /** property for the interval on which the repeated client warnings and diagnostic events about disk usage are ignored */ |
| DISK_USAGE_NOTIFY_INTERVAL_MS("cassandra.disk_usage.notify_interval_ms", convertToString(TimeUnit.MINUTES.toMillis(30))), |
| DOB_DOUBLING_THRESHOLD_MB("cassandra.DOB_DOUBLING_THRESHOLD_MB", "64"), |
| DOB_MAX_RECYCLE_BYTES("cassandra.dob_max_recycle_bytes", convertToString(1024 * 1024)), |
| /** |
| * When draining, how long to wait for mutating executors to shutdown. |
| */ |
| DRAIN_EXECUTOR_TIMEOUT_MS("cassandra.drain_executor_timeout_ms", convertToString(TimeUnit.MINUTES.toMillis(5))), |
| DROP_OVERSIZED_READ_REPAIR_MUTATIONS("cassandra.drop_oversized_readrepair_mutations"), |
| DTEST_API_LOG_TOPOLOGY("cassandra.dtest.api.log.topology"), |
| /** This property indicates if the code is running under the in-jvm dtest framework */ |
| DTEST_IS_IN_JVM_DTEST("org.apache.cassandra.dtest.is_in_jvm_dtest"), |
| ENABLE_DC_LOCAL_COMMIT("cassandra.enable_dc_local_commit", "true"), |
| /** |
| * Whether {@link org.apache.cassandra.db.ConsistencyLevel#NODE_LOCAL} should be allowed. |
| */ |
| ENABLE_NODELOCAL_QUERIES("cassandra.enable_nodelocal_queries"), |
| EXPIRATION_DATE_OVERFLOW_POLICY("cassandra.expiration_date_overflow_policy"), |
| EXPIRATION_OVERFLOW_WARNING_INTERVAL_MINUTES("cassandra.expiration_overflow_warning_interval_minutes", "5"), |
| FAILURE_LOGGING_INTERVAL_SECONDS("cassandra.request_failure_log_interval_seconds", "60"), |
| FD_INITIAL_VALUE_MS("cassandra.fd_initial_value_ms"), |
| FD_MAX_INTERVAL_MS("cassandra.fd_max_interval_ms"), |
| FILE_CACHE_ENABLED("cassandra.file_cache_enabled"), |
| /** @deprecated should be removed in favor of enable flag of relevant startup check (FileSystemOwnershipCheck) */ |
| @Deprecated |
| FILE_SYSTEM_CHECK_ENABLE("cassandra.enable_fs_ownership_check"), |
| /** @deprecated should be removed in favor of flags in relevant startup check (FileSystemOwnershipCheck) */ |
| @Deprecated |
| FILE_SYSTEM_CHECK_OWNERSHIP_FILENAME("cassandra.fs_ownership_filename", FileSystemOwnershipCheck.DEFAULT_FS_OWNERSHIP_FILENAME), |
| /** @deprecated should be removed in favor of flags in relevant startup check (FileSystemOwnershipCheck) */ |
| @Deprecated |
| FILE_SYSTEM_CHECK_OWNERSHIP_TOKEN(FileSystemOwnershipCheck.FILE_SYSTEM_CHECK_OWNERSHIP_TOKEN), |
| FORCE_DEFAULT_INDEXING_PAGE_SIZE("cassandra.force_default_indexing_page_size"), |
| /** Used when running in Client mode and the system and schema keyspaces need to be initialized outside of their normal initialization path **/ |
| FORCE_LOAD_LOCAL_KEYSPACES("cassandra.schema.force_load_local_keyspaces"), |
| FORCE_PAXOS_STATE_REBUILD("cassandra.force_paxos_state_rebuild"), |
| GIT_SHA("cassandra.gitSHA"), |
| /** |
| * Gossip quarantine delay is used while evaluating membership changes and should only be changed with extreme care. |
| */ |
| GOSSIPER_QUARANTINE_DELAY("cassandra.gossip_quarantine_delay_ms"), |
| GOSSIPER_SKIP_WAITING_TO_SETTLE("cassandra.skip_wait_for_gossip_to_settle", "-1"), |
| GOSSIP_DISABLE_THREAD_VALIDATION("cassandra.gossip.disable_thread_validation"), |
| IGNORED_SCHEMA_CHECK_ENDPOINTS("cassandra.skip_schema_check_for_endpoints"), |
| IGNORED_SCHEMA_CHECK_VERSIONS("cassandra.skip_schema_check_for_versions"), |
| IGNORE_CORRUPTED_SCHEMA_TABLES("cassandra.ignore_corrupted_schema_tables"), |
| /** @deprecated should be removed in favor of enable flag of relevant startup check (checkDatacenter) */ |
| @Deprecated |
| IGNORE_DC("cassandra.ignore_dc"), |
| IGNORE_DYNAMIC_SNITCH_SEVERITY("cassandra.ignore_dynamic_snitch_severity"), |
| IGNORE_MISSING_NATIVE_FILE_HINTS("cassandra.require_native_file_hints"), |
| /** @deprecated should be removed in favor of enable flag of relevant startup check (checkRack) */ |
| @Deprecated |
| IGNORE_RACK("cassandra.ignore_rack"), |
| INDEX_SUMMARY_EXPECTED_KEY_SIZE("cassandra.index_summary_expected_key_size", "64"), |
| INITIAL_TOKEN("cassandra.initial_token"), |
| INTERNODE_EVENT_THREADS("cassandra.internode-event-threads"), |
| IO_NETTY_EVENTLOOP_THREADS("io.netty.eventLoopThreads"), |
| IO_NETTY_TRANSPORT_ESTIMATE_SIZE_ON_SUBMIT("io.netty.transport.estimateSizeOnSubmit"), |
| JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES("javax.rmi.ssl.client.enabledCipherSuites"), |
| JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS("javax.rmi.ssl.client.enabledProtocols"), |
| /** Java class path. */ |
| JAVA_CLASS_PATH("java.class.path"), |
| JAVA_HOME("java.home"), |
| /** |
| * Indicates the temporary directory used by the Java Virtual Machine (JVM) |
| * to create and store temporary files. |
| */ |
| JAVA_IO_TMPDIR("java.io.tmpdir"), |
| /** |
| * Path from which to load native libraries. |
| * Default is absolute path to lib directory. |
| */ |
| JAVA_LIBRARY_PATH("java.library.path"), |
| /** |
| * Controls the distributed garbage collector lease time for JMX objects. |
| * Should only be set by in-jvm dtests. |
| */ |
| JAVA_RMI_DGC_LEASE_VALUE_IN_JVM_DTEST("java.rmi.dgc.leaseValue"), |
| /** |
| * The value of this property represents the host name string |
| * that should be associated with remote stubs for locally created remote objects, |
| * in order to allow clients to invoke methods on the remote object. |
| */ |
| JAVA_RMI_SERVER_HOSTNAME("java.rmi.server.hostname"), |
| /** |
| * If this value is true, object identifiers for remote objects exported by this VM will be generated by using |
| * a cryptographically secure random number generator. The default value is false. |
| */ |
| JAVA_RMI_SERVER_RANDOM_ID("java.rmi.server.randomIDs"), |
| JAVA_SECURITY_AUTH_LOGIN_CONFIG("java.security.auth.login.config"), |
| JAVA_SECURITY_EGD("java.security.egd"), |
| /** Java Runtime Environment version */ |
| JAVA_VERSION("java.version"), |
| /** Java Virtual Machine implementation name */ |
| JAVA_VM_NAME("java.vm.name"), |
| JOIN_RING("cassandra.join_ring", "true"), |
| /** startup checks properties */ |
| LIBJEMALLOC("cassandra.libjemalloc"), |
| /** Line separator ("\n" on UNIX). */ |
| LINE_SEPARATOR("line.separator"), |
| /** Load persistence ring state. Default value is {@code true}. */ |
| LOAD_RING_STATE("cassandra.load_ring_state", "true"), |
| LOG4J2_DISABLE_JMX("log4j2.disableJmx"), |
| LOG4J2_DISABLE_JMX_LEGACY("log4j2.disable.jmx"), |
| LOG4J_SHUTDOWN_HOOK_ENABLED("log4j.shutdownHookEnabled"), |
| LOGBACK_CONFIGURATION_FILE("logback.configurationFile"), |
| /** Maximum number of rows in system_views.logs table */ |
| LOGS_VIRTUAL_TABLE_MAX_ROWS("cassandra.virtual.logs.max.rows", convertToString(LogMessagesTable.LOGS_VIRTUAL_TABLE_DEFAULT_ROWS)), |
| /** |
| * Directory where Cassandra puts its logs, defaults to "." which is current directory. |
| */ |
| LOG_DIR("cassandra.logdir", "."), |
| /** |
| * Directory where Cassandra persists logs from audit logging. If this property is not set, the audit log framework |
| * will set it automatically to {@link CassandraRelevantProperties#LOG_DIR} + "/audit". |
| */ |
| LOG_DIR_AUDIT("cassandra.logdir.audit"), |
| /** Loosen the definition of "empty" for gossip state, for use during host replacements if things go awry */ |
| LOOSE_DEF_OF_EMPTY_ENABLED(Config.PROPERTY_PREFIX + "gossiper.loose_empty_enabled"), |
| MAX_CONCURRENT_RANGE_REQUESTS("cassandra.max_concurrent_range_requests"), |
| MAX_HINT_BUFFERS("cassandra.MAX_HINT_BUFFERS", "3"), |
| MAX_LOCAL_PAUSE_IN_MS("cassandra.max_local_pause_in_ms", "5000"), |
| /** what class to use for mbean registeration */ |
| MBEAN_REGISTRATION_CLASS("org.apache.cassandra.mbean_registration_class"), |
| MEMTABLE_OVERHEAD_COMPUTE_STEPS("cassandra.memtable_row_overhead_computation_step", "100000"), |
| MEMTABLE_OVERHEAD_SIZE("cassandra.memtable.row_overhead_size", "-1"), |
| MEMTABLE_SHARD_COUNT("cassandra.memtable.shard.count"), |
| MEMTABLE_TRIE_SIZE_LIMIT("cassandra.trie_size_limit_mb"), |
| METRICS_REPORTER_CONFIG_FILE("cassandra.metricsReporterConfigFile"), |
| MIGRATION_DELAY("cassandra.migration_delay_ms", "60000"), |
| /** Defines the maximum number of unique timed out queries that will be reported in the logs. Use a negative number to remove any limit. */ |
| MONITORING_MAX_OPERATIONS("cassandra.monitoring_max_operations", "50"), |
| /** Defines the interval for reporting any operations that have timed out. */ |
| MONITORING_REPORT_INTERVAL_MS("cassandra.monitoring_report_interval_ms", "5000"), |
| MV_ALLOW_FILTERING_NONKEY_COLUMNS_UNSAFE("cassandra.mv.allow_filtering_nonkey_columns_unsafe"), |
| MV_ENABLE_COORDINATOR_BATCHLOG("cassandra.mv_enable_coordinator_batchlog"), |
| /** mx4jaddress */ |
| MX4JADDRESS("mx4jaddress"), |
| /** mx4jport */ |
| MX4JPORT("mx4jport"), |
| NANOTIMETOMILLIS_TIMESTAMP_UPDATE_INTERVAL("cassandra.NANOTIMETOMILLIS_TIMESTAMP_UPDATE_INTERVAL", "10000"), |
| NATIVE_EPOLL_ENABLED("cassandra.native.epoll.enabled", "true"), |
| /** This is the port used with RPC address for the native protocol to communicate with clients. Now that thrift RPC is no longer in use there is no RPC port. */ |
| NATIVE_TRANSPORT_PORT("cassandra.native_transport_port"), |
| NEVER_PURGE_TOMBSTONES("cassandra.never_purge_tombstones"), |
| NIO_DATA_OUTPUT_STREAM_PLUS_BUFFER_SIZE("cassandra.nio_data_output_stream_plus_buffer_size", convertToString(32 * 1024)), |
| NODETOOL_JMX_NOTIFICATION_POLL_INTERVAL_SECONDS("cassandra.nodetool.jmx_notification_poll_interval_seconds", convertToString(TimeUnit.SECONDS.convert(5, TimeUnit.MINUTES))), |
| /** If set, {@link org.apache.cassandra.net.MessagingService} is shutdown abrtuptly without waiting for anything. |
| * This is an optimization used in unit tests becuase we never restart a node there. The only node is stopoped |
| * when the JVM terminates. Therefore, we can use such optimization and not wait unnecessarily. */ |
| NON_GRACEFUL_SHUTDOWN("cassandra.test.messagingService.nonGracefulShutdown"), |
| /** for specific tests */ |
| /** This property indicates whether disable_mbean_registration is true */ |
| ORG_APACHE_CASSANDRA_DISABLE_MBEAN_REGISTRATION("org.apache.cassandra.disable_mbean_registration"), |
| /** Operating system architecture. */ |
| OS_ARCH("os.arch"), |
| /** Operating system name. */ |
| OS_NAME("os.name"), |
| OTCP_LARGE_MESSAGE_THRESHOLD("cassandra.otcp_large_message_threshold", convertToString(1024 * 64)), |
| /** Enabled/disable TCP_NODELAY for intradc connections. Defaults is enabled. */ |
| OTC_INTRADC_TCP_NODELAY("cassandra.otc_intradc_tcp_nodelay", "true"), |
| OVERRIDE_DECOMMISSION("cassandra.override_decommission"), |
| PARENT_REPAIR_STATUS_CACHE_SIZE("cassandra.parent_repair_status_cache_size", "100000"), |
| PARENT_REPAIR_STATUS_EXPIRY_SECONDS("cassandra.parent_repair_status_expiry_seconds", convertToString(TimeUnit.SECONDS.convert(1, TimeUnit.DAYS))), |
| PARTITIONER("cassandra.partitioner"), |
| PAXOS_CLEANUP_SESSION_TIMEOUT_SECONDS("cassandra.paxos_cleanup_session_timeout_seconds", convertToString(TimeUnit.HOURS.toSeconds(2))), |
| PAXOS_DISABLE_COORDINATOR_LOCKING("cassandra.paxos.disable_coordinator_locking"), |
| PAXOS_LOG_TTL_LINEARIZABILITY_VIOLATIONS("cassandra.paxos.log_ttl_linearizability_violations", "true"), |
| PAXOS_MODERN_RELEASE("cassandra.paxos.modern_release", "4.1"), |
| PAXOS_REPAIR_ALLOW_MULTIPLE_PENDING_UNSAFE("cassandra.paxos_repair_allow_multiple_pending_unsafe"), |
| PAXOS_REPAIR_ON_TOPOLOGY_CHANGE_RETRIES("cassandra.paxos_repair_on_topology_change_retries", "10"), |
| PAXOS_REPAIR_ON_TOPOLOGY_CHANGE_RETRY_DELAY_SECONDS("cassandra.paxos_repair_on_topology_change_retry_delay_seconds", "10"), |
| PAXOS_REPAIR_RETRY_TIMEOUT_IN_MS("cassandra.paxos_repair_retry_timeout_millis", "60000"), |
| PAXOS_USE_SELF_EXECUTION("cassandra.paxos.use_self_execution", "true"), |
| PRINT_HEAP_HISTOGRAM_ON_OUT_OF_MEMORY_ERROR("cassandra.printHeapHistogramOnOutOfMemoryError"), |
| READS_THRESHOLDS_COORDINATOR_DEFENSIVE_CHECKS_ENABLED("cassandra.reads.thresholds.coordinator.defensive_checks_enabled"), |
| RELEASE_VERSION("cassandra.releaseVersion"), |
| RELOCATED_SHADED_IO_NETTY_TRANSPORT_NONATIVE("relocated.shaded.io.netty.transport.noNative"), |
| REPAIR_CLEANUP_INTERVAL_SECONDS("cassandra.repair_cleanup_interval_seconds", convertToString(Ints.checkedCast(TimeUnit.MINUTES.toSeconds(10)))), |
| REPAIR_DELETE_TIMEOUT_SECONDS("cassandra.repair_delete_timeout_seconds", convertToString(Ints.checkedCast(TimeUnit.DAYS.toSeconds(1)))), |
| REPAIR_FAIL_TIMEOUT_SECONDS("cassandra.repair_fail_timeout_seconds", convertToString(Ints.checkedCast(TimeUnit.DAYS.toSeconds(1)))), |
| REPAIR_MUTATION_REPAIR_ROWS_PER_BATCH("cassandra.repair.mutation_repair_rows_per_batch", "100"), |
| REPAIR_STATUS_CHECK_TIMEOUT_SECONDS("cassandra.repair_status_check_timeout_seconds", convertToString(Ints.checkedCast(TimeUnit.HOURS.toSeconds(1)))), |
| /** |
| * When doing a host replacement its possible that the gossip state is "empty" meaning that the endpoint is known |
| * but the current state isn't known. If the host replacement is needed to repair this state, this property must |
| * be true. |
| */ |
| REPLACEMENT_ALLOW_EMPTY("cassandra.allow_empty_replace_address", "true"), |
| REPLACE_ADDRESS("cassandra.replace_address"), |
| REPLACE_ADDRESS_FIRST_BOOT("cassandra.replace_address_first_boot"), |
| REPLACE_NODE("cassandra.replace_node"), |
| REPLACE_TOKEN("cassandra.replace_token"), |
| /** |
| * Whether we reset any found data from previously run bootstraps. |
| */ |
| RESET_BOOTSTRAP_PROGRESS("cassandra.reset_bootstrap_progress"), |
| RING_DELAY("cassandra.ring_delay_ms"), |
| /** Defines how often schema definitions are pulled from the other nodes */ |
| SCHEMA_PULL_INTERVAL_MS("cassandra.schema_pull_interval_ms", "60000"), |
| SCHEMA_UPDATE_HANDLER_FACTORY_CLASS("cassandra.schema.update_handler_factory.class"), |
| SEARCH_CONCURRENCY_FACTOR("cassandra.search_concurrency_factor", "1"), |
| /** |
| * The maximum number of seeds returned by a seed provider before emmitting a warning. |
| * A large seed list may impact effectiveness of the third gossip round. |
| * The default used in SimpleSeedProvider is 20. |
| */ |
| SEED_COUNT_WARN_THRESHOLD("cassandra.seed_count_warn_threshold"), |
| SERIALIZATION_EMPTY_TYPE_NONEMPTY_BEHAVIOR("cassandra.serialization.emptytype.nonempty_behavior"), |
| SET_SEP_THREAD_NAME("cassandra.set_sep_thread_name", "true"), |
| SHUTDOWN_ANNOUNCE_DELAY_IN_MS("cassandra.shutdown_announce_in_ms", "2000"), |
| SIZE_RECORDER_INTERVAL("cassandra.size_recorder_interval", "300"), |
| SKIP_PAXOS_REPAIR_ON_TOPOLOGY_CHANGE("cassandra.skip_paxos_repair_on_topology_change"), |
| /** If necessary for operational purposes, permit certain keyspaces to be ignored for paxos topology repairs. */ |
| SKIP_PAXOS_REPAIR_ON_TOPOLOGY_CHANGE_KEYSPACES("cassandra.skip_paxos_repair_on_topology_change_keyspaces"), |
| SKIP_PAXOS_REPAIR_VERSION_VALIDATION("cassandra.skip_paxos_repair_version_validation"), |
| SKIP_PAXOS_STATE_REBUILD("cassandra.skip_paxos_state_rebuild"), |
| /** snapshots ttl cleanup initial delay in seconds */ |
| SNAPSHOT_CLEANUP_INITIAL_DELAY_SECONDS("cassandra.snapshot.ttl_cleanup_initial_delay_seconds", "5"), |
| /** snapshots ttl cleanup period in seconds */ |
| SNAPSHOT_CLEANUP_PERIOD_SECONDS("cassandra.snapshot.ttl_cleanup_period_seconds", "60"), |
| /** minimum allowed TTL for snapshots */ |
| SNAPSHOT_MIN_ALLOWED_TTL_SECONDS("cassandra.snapshot.min_allowed_ttl_seconds", "60"), |
| SSL_ENABLE("ssl.enable"), |
| SSL_STORAGE_PORT("cassandra.ssl_storage_port"), |
| SSTABLE_FORMAT_DEFAULT("cassandra.sstable.format.default"), |
| START_GOSSIP("cassandra.start_gossip", "true"), |
| START_NATIVE_TRANSPORT("cassandra.start_native_transport"), |
| STORAGE_DIR("cassandra.storagedir"), |
| STORAGE_HOOK("cassandra.storage_hook"), |
| STORAGE_PORT("cassandra.storage_port"), |
| STREAMING_HISTOGRAM_ROUND_SECONDS("cassandra.streaminghistogram.roundseconds", "60"), |
| STREAMING_SESSION_PARALLELTRANSFERS("cassandra.streaming.session.parallelTransfers"), |
| STREAM_HOOK("cassandra.stream_hook"), |
| /** Platform word size sun.arch.data.model. Examples: "32", "64", "unknown"*/ |
| SUN_ARCH_DATA_MODEL("sun.arch.data.model"), |
| SUN_JAVA_COMMAND("sun.java.command", ""), |
| /** |
| * Controls the JMX server threadpool keap-alive time. |
| * Should only be set by in-jvm dtests. |
| */ |
| SUN_RMI_TRANSPORT_TCP_THREADKEEPALIVETIME("sun.rmi.transport.tcp.threadKeepAliveTime"), |
| SUN_STDERR_ENCODING("sun.stderr.encoding"), |
| SUN_STDOUT_ENCODING("sun.stdout.encoding"), |
| SUPERUSER_SETUP_DELAY_MS("cassandra.superuser_setup_delay_ms", "10000"), |
| SYSTEM_AUTH_DEFAULT_RF("cassandra.system_auth.default_rf", "1"), |
| SYSTEM_DISTRIBUTED_DEFAULT_RF("cassandra.system_distributed.default_rf", "3"), |
| SYSTEM_TRACES_DEFAULT_RF("cassandra.system_traces.default_rf", "2"), |
| TEST_BBFAILHELPER_ENABLED("test.bbfailhelper.enabled"), |
| TEST_BLOB_SHARED_SEED("cassandra.test.blob.shared.seed"), |
| TEST_BYTEMAN_TRANSFORMATIONS_DEBUG("cassandra.test.byteman.transformations.debug"), |
| TEST_CASSANDRA_KEEPBRIEFBRIEF("cassandra.keepBriefBrief"), |
| TEST_CASSANDRA_RELEVANT_PROPERTIES("org.apache.cassandra.conf.CassandraRelevantPropertiesTest"), |
| /** A property for various mechanisms for syncing files that makes it possible it intercept and skip syncing. */ |
| TEST_CASSANDRA_SKIP_SYNC("cassandra.skip_sync"), |
| TEST_CASSANDRA_SUITENAME("suitename", "suitename_IS_UNDEFINED"), |
| TEST_CASSANDRA_TESTTAG("cassandra.testtag", "cassandra.testtag_IS_UNDEFINED"), |
| TEST_COMPRESSION("cassandra.test.compression"), |
| TEST_COMPRESSION_ALGO("cassandra.test.compression.algo", "lz4"), |
| TEST_DEBUG_REF_COUNT("cassandra.debugrefcount"), |
| TEST_DRIVER_CONNECTION_TIMEOUT_MS("cassandra.test.driver.connection_timeout_ms", "5000"), |
| TEST_DRIVER_READ_TIMEOUT_MS("cassandra.test.driver.read_timeout_ms", "12000"), |
| TEST_FAIL_MV_LOCKS_COUNT("cassandra.test.fail_mv_locks_count", "0"), |
| TEST_FAIL_WRITES_KS("cassandra.test.fail_writes_ks", ""), |
| /** Flush changes of {@link org.apache.cassandra.schema.SchemaKeyspace} after each schema modification. In production, |
| * we always do that. However, tests which do not restart nodes may disable this functionality in order to run |
| * faster. Note that this is disabled for unit tests but if an individual test requires schema to be flushed, it |
| * can be also done manually for that particular case: {@code flush(SchemaConstants.SCHEMA_KEYSPACE_NAME);}. */ |
| TEST_FLUSH_LOCAL_SCHEMA_CHANGES("cassandra.test.flush_local_schema_changes", "true"), |
| TEST_IGNORE_SIGAR("cassandra.test.ignore_sigar"), |
| TEST_INVALID_LEGACY_SSTABLE_ROOT("invalid-legacy-sstable-root"), |
| TEST_JVM_DTEST_DISABLE_SSL("cassandra.test.disable_ssl"), |
| TEST_LEGACY_SSTABLE_ROOT("legacy-sstable-root"), |
| TEST_ORG_CAFFINITAS_OHC_SEGMENTCOUNT("org.caffinitas.ohc.segmentCount"), |
| TEST_READ_ITERATION_DELAY_MS("cassandra.test.read_iteration_delay_ms", "0"), |
| TEST_REUSE_PREPARED("cassandra.test.reuse_prepared", "true"), |
| TEST_ROW_CACHE_SIZE("cassandra.test.row_cache_size"), |
| TEST_SERIALIZATION_WRITES("cassandra.test-serialization-writes"), |
| TEST_SIMULATOR_DEBUG("cassandra.test.simulator.debug"), |
| TEST_SIMULATOR_DETERMINISM_CHECK("cassandra.test.simulator.determinismcheck", "none"), |
| TEST_SIMULATOR_LIVENESS_CHECK("cassandra.test.simulator.livenesscheck", "true"), |
| /** properties for debugging simulator ASM output */ |
| TEST_SIMULATOR_PRINT_ASM("cassandra.test.simulator.print_asm", "none"), |
| TEST_SIMULATOR_PRINT_ASM_CLASSES("cassandra.test.simulator.print_asm_classes", ""), |
| TEST_SIMULATOR_PRINT_ASM_OPTS("cassandra.test.simulator.print_asm_opts", ""), |
| TEST_SIMULATOR_PRINT_ASM_TYPES("cassandra.test.simulator.print_asm_types", ""), |
| TEST_SSTABLE_FORMAT_DEVELOPMENT("cassandra.test.sstableformatdevelopment"), |
| TEST_STRICT_LCS_CHECKS("cassandra.test.strict_lcs_checks"), |
| /** Turns some warnings into exceptions for testing. */ |
| TEST_STRICT_RUNTIME_CHECKS("cassandra.strict.runtime.checks"), |
| /** Not to be used in production, this causes a Netty logging handler to be added to the pipeline, which will throttle a system under any normal load. */ |
| TEST_UNSAFE_VERBOSE_DEBUG_CLIENT_PROTOCOL("cassandra.unsafe_verbose_debug_client_protocol"), |
| TEST_USE_PREPARED("cassandra.test.use_prepared", "true"), |
| TEST_UTIL_ALLOW_TOOL_REINIT_FOR_TEST("org.apache.cassandra.tools.UtilALLOW_TOOL_REINIT_FOR_TEST"), |
| /** Activate write survey mode. The node not becoming an active ring member, and you must use JMX StorageService->joinRing() to finalize the ring joining. */ |
| TEST_WRITE_SURVEY("cassandra.write_survey"), |
| TOLERATE_SSTABLE_SIZE("cassandra.tolerate_sstable_size"), |
| TRIGGERS_DIR("cassandra.triggers_dir"), |
| TRUNCATE_BALLOT_METADATA("cassandra.truncate_ballot_metadata"), |
| TYPE_UDT_CONFLICT_BEHAVIOR("cassandra.type.udt.conflict_behavior"), |
| UDF_EXECUTOR_THREAD_KEEPALIVE_MS("cassandra.udf_executor_thread_keepalive_ms", "30000"), |
| UNSAFE_SYSTEM("cassandra.unsafesystem"), |
| /** User's home directory. */ |
| USER_HOME("user.home"), |
| /** When enabled, recursive directory deletion will be executed using a unix command `rm -rf` instead of traversing |
| * and removing individual files. This is now used only tests, but eventually we will make it true by default.*/ |
| 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"), |
| WAIT_FOR_TRACING_EVENTS_TIMEOUT_SECS("cassandra.wait_for_tracing_events_timeout_secs", "0"); |
| |
| static |
| { |
| CassandraRelevantProperties[] values = CassandraRelevantProperties.values(); |
| Set<String> visited = new HashSet<>(values.length); |
| CassandraRelevantProperties prev = null; |
| for (CassandraRelevantProperties next : values) |
| { |
| if (!visited.add(next.getKey())) |
| throw new IllegalStateException("System properties have duplicate key: " + next.getKey()); |
| if (prev != null && next.name().compareTo(prev.name()) < 0) |
| throw new IllegalStateException("Enum constants are not in alphabetical order: " + prev.name() + " should come before " + next.name()); |
| else |
| prev = next; |
| } |
| } |
| |
| CassandraRelevantProperties(String key, String defaultVal) |
| { |
| this.key = key; |
| this.defaultVal = defaultVal; |
| } |
| |
| CassandraRelevantProperties(String key) |
| { |
| this.key = key; |
| this.defaultVal = null; |
| } |
| |
| private final String key; |
| private final String defaultVal; |
| |
| public String getKey() |
| { |
| return key; |
| } |
| |
| /** |
| * Gets the value of the indicated system property. |
| * @return system property value if it exists, defaultValue otherwise. |
| */ |
| public String getString() |
| { |
| String value = System.getProperty(key); |
| |
| return value == null ? defaultVal : STRING_CONVERTER.convert(value); |
| } |
| |
| /** |
| * Returns default value. |
| * |
| * @return default value, if any, otherwise null. |
| */ |
| public String getDefaultValue() |
| { |
| return defaultVal; |
| } |
| |
| /** |
| * Sets the property to its default value if a default value was specified. Remove the property otherwise. |
| */ |
| public void reset() |
| { |
| if (defaultVal != null) |
| System.setProperty(key, defaultVal); |
| else |
| System.getProperties().remove(key); |
| } |
| |
| /** |
| * Gets the value of a system property as a String. |
| * @return system property String value if it exists, overrideDefaultValue otherwise. |
| */ |
| public String getString(String overrideDefaultValue) |
| { |
| String value = System.getProperty(key); |
| if (value == null) |
| return overrideDefaultValue; |
| |
| return STRING_CONVERTER.convert(value); |
| } |
| |
| public <T> T convert(PropertyConverter<T> converter) |
| { |
| String value = System.getProperty(key); |
| if (value == null) |
| value = defaultVal; |
| |
| return converter.convert(value); |
| } |
| |
| public static String convertToString(@Nullable Object value) |
| { |
| if (value == null) |
| return null; |
| if (value instanceof String) |
| return (String) value; |
| if (value instanceof Boolean) |
| return Boolean.toString((Boolean) value); |
| if (value instanceof Long) |
| return Long.toString((Long) value); |
| if (value instanceof Integer) |
| return Integer.toString((Integer) value); |
| if (value instanceof Double) |
| return Double.toString((Double) value); |
| if (value instanceof Float) |
| return Float.toString((Float) value); |
| throw new IllegalArgumentException("Unknown type " + value.getClass()); |
| } |
| |
| /** |
| * Sets the value into system properties. |
| * @param value to set |
| */ |
| public String setString(String value) |
| { |
| return System.setProperty(key, value); |
| } |
| |
| /** |
| * Gets the value of a system property as a boolean. |
| * @return system property boolean value if it exists, false otherwise(). |
| */ |
| public boolean getBoolean() |
| { |
| String value = System.getProperty(key); |
| |
| return BOOLEAN_CONVERTER.convert(value == null ? defaultVal : value); |
| } |
| |
| /** |
| * Gets the value of a system property as a boolean. |
| * @return system property boolean value if it exists, overrideDefaultValue otherwise. |
| */ |
| public boolean getBoolean(boolean overrideDefaultValue) |
| { |
| String value = System.getProperty(key); |
| if (value == null) |
| return overrideDefaultValue; |
| |
| return BOOLEAN_CONVERTER.convert(value); |
| } |
| |
| /** |
| * Sets the value into system properties. |
| * @param value to set |
| * @return Previous value if it exists. |
| */ |
| public Boolean setBoolean(boolean value) |
| { |
| String prev = System.setProperty(key, convertToString(value)); |
| return prev == null ? null : BOOLEAN_CONVERTER.convert(prev); |
| } |
| |
| /** |
| * Clears the value set in the system property. |
| */ |
| public void clearValue() |
| { |
| System.clearProperty(key); |
| } |
| |
| /** |
| * Gets the value of a system property as a int. |
| * @return System property value if it exists, defaultValue otherwise. Throws an exception if no default value is set. |
| */ |
| public int getInt() |
| { |
| String value = System.getProperty(key); |
| if (value == null && defaultVal == null) |
| throw new ConfigurationException("Missing property value or default value is not set: " + key); |
| return INTEGER_CONVERTER.convert(value == null ? defaultVal : value); |
| } |
| |
| /** |
| * Gets the value of a system property as a long. |
| * @return System property value if it exists, defaultValue otherwise. Throws an exception if no default value is set. |
| */ |
| public long getLong() |
| { |
| String value = System.getProperty(key); |
| if (value == null && defaultVal == null) |
| throw new ConfigurationException("Missing property value or default value is not set: " + key); |
| return LONG_CONVERTER.convert(value == null ? defaultVal : value); |
| } |
| |
| /** |
| * Gets the value of a system property as a long. |
| * @return system property long value if it exists, defaultValue otherwise. |
| */ |
| public long getLong(long overrideDefaultValue) |
| { |
| String value = System.getProperty(key); |
| if (value == null) |
| return overrideDefaultValue; |
| |
| return LONG_CONVERTER.convert(value); |
| } |
| |
| /** |
| * Gets the value of a system property as an int. |
| * @return system property int value if it exists, overrideDefaultValue otherwise. |
| */ |
| public int getInt(int overrideDefaultValue) |
| { |
| String value = System.getProperty(key); |
| if (value == null) |
| return overrideDefaultValue; |
| |
| return INTEGER_CONVERTER.convert(value); |
| } |
| |
| /** |
| * Sets the value into system properties. |
| * @param value to set |
| * @return Previous value or null if it did not have one. |
| */ |
| public Integer setInt(int value) |
| { |
| String prev = System.setProperty(key, convertToString(value)); |
| return prev == null ? null : INTEGER_CONVERTER.convert(prev); |
| } |
| |
| /** |
| * Sets the value into system properties. |
| * @param value to set |
| * @return Previous value or null if it did not have one. |
| */ |
| public Long setLong(long value) |
| { |
| String prev = System.setProperty(key, convertToString(value)); |
| return prev == null ? null : LONG_CONVERTER.convert(prev); |
| } |
| |
| /** |
| * Gets the value of a system property as a enum, calling {@link String#toUpperCase()} first. |
| * |
| * @param defaultValue to return when not defined |
| * @param <T> type |
| * @return enum value |
| */ |
| public <T extends Enum<T>> T getEnum(T defaultValue) |
| { |
| return getEnum(true, defaultValue); |
| } |
| |
| /** |
| * Gets the value of a system property as a enum, optionally calling {@link String#toUpperCase()} first. |
| * |
| * @param toUppercase before converting to enum |
| * @param defaultValue to return when not defined |
| * @param <T> type |
| * @return enum value |
| */ |
| public <T extends Enum<T>> T getEnum(boolean toUppercase, T defaultValue) |
| { |
| String value = System.getProperty(key); |
| if (value == null) |
| return defaultValue; |
| return Enum.valueOf(defaultValue.getDeclaringClass(), toUppercase ? value.toUpperCase() : value); |
| } |
| |
| /** |
| * Gets the value of a system property as an enum, optionally calling {@link String#toUpperCase()} first. |
| * If the value is missing, the default value for this property is used |
| * |
| * @param toUppercase before converting to enum |
| * @param enumClass enumeration class |
| * @param <T> type |
| * @return enum value |
| */ |
| public <T extends Enum<T>> T getEnum(boolean toUppercase, Class<T> enumClass) |
| { |
| String value = System.getProperty(key, defaultVal); |
| return Enum.valueOf(enumClass, toUppercase ? value.toUpperCase() : value); |
| } |
| |
| /** |
| * Sets the value into system properties. |
| * @param value to set |
| */ |
| public void setEnum(Enum<?> value) |
| { |
| System.setProperty(key, value.name()); |
| } |
| |
| public interface PropertyConverter<T> |
| { |
| T convert(String value); |
| } |
| |
| private static final PropertyConverter<String> STRING_CONVERTER = value -> value; |
| |
| private static final PropertyConverter<Boolean> BOOLEAN_CONVERTER = Boolean::parseBoolean; |
| |
| private static final PropertyConverter<Integer> INTEGER_CONVERTER = value -> |
| { |
| try |
| { |
| return Integer.decode(value); |
| } |
| catch (NumberFormatException e) |
| { |
| throw new ConfigurationException(String.format("Invalid value for system property: " + |
| "expected integer value but got '%s'", value)); |
| } |
| }; |
| |
| private static final PropertyConverter<Long> LONG_CONVERTER = value -> |
| { |
| try |
| { |
| return Long.decode(value); |
| } |
| catch (NumberFormatException e) |
| { |
| throw new ConfigurationException(String.format("Invalid value for system property: " + |
| "expected long value but got '%s'", value)); |
| } |
| }; |
| |
| /** |
| * @return whether a system property is present or not. |
| */ |
| public boolean isPresent() |
| { |
| return System.getProperties().containsKey(key); |
| } |
| } |